@vm0/cli 4.31.1 → 4.33.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 +965 -451
  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")
@@ -2760,7 +2760,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
2760
2760
  function isValidBase64URL(data) {
2761
2761
  if (!base64url.test(data))
2762
2762
  return false;
2763
- const base643 = data.replace(/[-_]/g, (c10) => c10 === "-" ? "+" : "/");
2763
+ const base643 = data.replace(/[-_]/g, (c11) => c11 === "-" ? "+" : "/");
2764
2764
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
2765
2765
  return isValidBase64(padded);
2766
2766
  }
@@ -11672,9 +11672,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
11672
11672
  ZodType.init(inst, def);
11673
11673
  inst.min = (value, params) => inst.check(_gte(value, params));
11674
11674
  inst.max = (value, params) => inst.check(_lte(value, params));
11675
- const c10 = inst._zod.bag;
11676
- inst.minDate = c10.minimum ? new Date(c10.minimum) : null;
11677
- inst.maxDate = c10.maximum ? new Date(c10.maximum) : null;
11675
+ const c11 = inst._zod.bag;
11676
+ inst.minDate = c11.minimum ? new Date(c11.minimum) : null;
11677
+ inst.maxDate = c11.maximum ? new Date(c11.maximum) : null;
11678
11678
  });
11679
11679
  function date3(params) {
11680
11680
  return _date(ZodDate, params);
@@ -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();
@@ -13504,6 +13526,82 @@ var scopeContract = c9.router({
13504
13526
  }
13505
13527
  });
13506
13528
 
13529
+ // ../../packages/core/src/contracts/sessions.ts
13530
+ var c10 = initContract();
13531
+ var sessionResponseSchema = external_exports.object({
13532
+ id: external_exports.string(),
13533
+ agentComposeId: external_exports.string(),
13534
+ agentComposeVersionId: external_exports.string().nullable(),
13535
+ conversationId: external_exports.string().nullable(),
13536
+ artifactName: external_exports.string().nullable(),
13537
+ vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13538
+ secretNames: external_exports.array(external_exports.string()).nullable(),
13539
+ volumeVersions: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13540
+ createdAt: external_exports.string(),
13541
+ updatedAt: external_exports.string()
13542
+ });
13543
+ var agentComposeSnapshotSchema = external_exports.object({
13544
+ agentComposeVersionId: external_exports.string(),
13545
+ vars: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13546
+ secretNames: external_exports.array(external_exports.string()).optional()
13547
+ });
13548
+ var artifactSnapshotSchema2 = external_exports.object({
13549
+ artifactName: external_exports.string(),
13550
+ artifactVersion: external_exports.string()
13551
+ });
13552
+ var volumeVersionsSnapshotSchema2 = external_exports.object({
13553
+ versions: external_exports.record(external_exports.string(), external_exports.string())
13554
+ });
13555
+ var checkpointResponseSchema = external_exports.object({
13556
+ id: external_exports.string(),
13557
+ runId: external_exports.string(),
13558
+ conversationId: external_exports.string(),
13559
+ agentComposeSnapshot: agentComposeSnapshotSchema,
13560
+ artifactSnapshot: artifactSnapshotSchema2.nullable(),
13561
+ volumeVersionsSnapshot: volumeVersionsSnapshotSchema2.nullable(),
13562
+ createdAt: external_exports.string()
13563
+ });
13564
+ var sessionsByIdContract = c10.router({
13565
+ /**
13566
+ * GET /api/agent/sessions/:id
13567
+ * Get session by ID
13568
+ */
13569
+ getById: {
13570
+ method: "GET",
13571
+ path: "/api/agent/sessions/:id",
13572
+ pathParams: external_exports.object({
13573
+ id: external_exports.string().min(1, "Session ID is required")
13574
+ }),
13575
+ responses: {
13576
+ 200: sessionResponseSchema,
13577
+ 401: apiErrorSchema,
13578
+ 403: apiErrorSchema,
13579
+ 404: apiErrorSchema
13580
+ },
13581
+ summary: "Get session by ID"
13582
+ }
13583
+ });
13584
+ var checkpointsByIdContract = c10.router({
13585
+ /**
13586
+ * GET /api/agent/checkpoints/:id
13587
+ * Get checkpoint by ID
13588
+ */
13589
+ getById: {
13590
+ method: "GET",
13591
+ path: "/api/agent/checkpoints/:id",
13592
+ pathParams: external_exports.object({
13593
+ id: external_exports.string().min(1, "Checkpoint ID is required")
13594
+ }),
13595
+ responses: {
13596
+ 200: checkpointResponseSchema,
13597
+ 401: apiErrorSchema,
13598
+ 403: apiErrorSchema,
13599
+ 404: apiErrorSchema
13600
+ },
13601
+ summary: "Get checkpoint by ID"
13602
+ }
13603
+ });
13604
+
13507
13605
  // ../../packages/core/src/scope-reference.ts
13508
13606
  function getLegacySystemTemplateWarning(legacyFormat) {
13509
13607
  if (!isLegacySystemTemplate(legacyFormat)) {
@@ -13908,10 +14006,51 @@ var ApiClient = class {
13908
14006
  }
13909
14007
  return await response.json();
13910
14008
  }
14009
+ /**
14010
+ * Get session by ID
14011
+ * Used by run continue to fetch session info including secretNames
14012
+ */
14013
+ async getSession(sessionId) {
14014
+ const baseUrl = await this.getBaseUrl();
14015
+ const headers = await this.getHeaders();
14016
+ const response = await fetch(`${baseUrl}/api/agent/sessions/${sessionId}`, {
14017
+ method: "GET",
14018
+ headers
14019
+ });
14020
+ if (!response.ok) {
14021
+ const error43 = await response.json();
14022
+ throw new Error(
14023
+ error43.error?.message || `Session not found: ${sessionId}`
14024
+ );
14025
+ }
14026
+ return await response.json();
14027
+ }
14028
+ /**
14029
+ * Get checkpoint by ID
14030
+ * Used by run resume to fetch checkpoint info including secretNames
14031
+ */
14032
+ async getCheckpoint(checkpointId) {
14033
+ const baseUrl = await this.getBaseUrl();
14034
+ const headers = await this.getHeaders();
14035
+ const response = await fetch(
14036
+ `${baseUrl}/api/agent/checkpoints/${checkpointId}`,
14037
+ {
14038
+ method: "GET",
14039
+ headers
14040
+ }
14041
+ );
14042
+ if (!response.ok) {
14043
+ const error43 = await response.json();
14044
+ throw new Error(
14045
+ error43.error?.message || `Checkpoint not found: ${checkpointId}`
14046
+ );
14047
+ }
14048
+ return await response.json();
14049
+ }
13911
14050
  /**
13912
14051
  * Generic GET request
13913
14052
  */
13914
- async get(path12) {
14053
+ async get(path14) {
13915
14054
  const baseUrl = await this.getBaseUrl();
13916
14055
  const token = await getToken();
13917
14056
  if (!token) {
@@ -13924,7 +14063,7 @@ var ApiClient = class {
13924
14063
  if (bypassSecret) {
13925
14064
  headers["x-vercel-protection-bypass"] = bypassSecret;
13926
14065
  }
13927
- return fetch(`${baseUrl}${path12}`, {
14066
+ return fetch(`${baseUrl}${path14}`, {
13928
14067
  method: "GET",
13929
14068
  headers
13930
14069
  });
@@ -13932,7 +14071,7 @@ var ApiClient = class {
13932
14071
  /**
13933
14072
  * Generic POST request
13934
14073
  */
13935
- async post(path12, options) {
14074
+ async post(path14, options) {
13936
14075
  const baseUrl = await this.getBaseUrl();
13937
14076
  const token = await getToken();
13938
14077
  if (!token) {
@@ -13948,7 +14087,7 @@ var ApiClient = class {
13948
14087
  if (bypassSecret) {
13949
14088
  headers["x-vercel-protection-bypass"] = bypassSecret;
13950
14089
  }
13951
- return fetch(`${baseUrl}${path12}`, {
14090
+ return fetch(`${baseUrl}${path14}`, {
13952
14091
  method: "POST",
13953
14092
  headers,
13954
14093
  body: options?.body
@@ -13957,7 +14096,7 @@ var ApiClient = class {
13957
14096
  /**
13958
14097
  * Generic DELETE request
13959
14098
  */
13960
- async delete(path12) {
14099
+ async delete(path14) {
13961
14100
  const baseUrl = await this.getBaseUrl();
13962
14101
  const token = await getToken();
13963
14102
  if (!token) {
@@ -13970,7 +14109,7 @@ var ApiClient = class {
13970
14109
  if (bypassSecret) {
13971
14110
  headers["x-vercel-protection-bypass"] = bypassSecret;
13972
14111
  }
13973
- return fetch(`${baseUrl}${path12}`, {
14112
+ return fetch(`${baseUrl}${path14}`, {
13974
14113
  method: "DELETE",
13975
14114
  headers
13976
14115
  });
@@ -14340,6 +14479,28 @@ import * as tar2 from "tar";
14340
14479
  import * as fs2 from "fs";
14341
14480
  import * as path2 from "path";
14342
14481
  import * as tar from "tar";
14482
+ function formatBytes(bytes) {
14483
+ if (bytes === 0) return "0 B";
14484
+ const k = 1024;
14485
+ const sizes = ["B", "KB", "MB", "GB"];
14486
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
14487
+ return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
14488
+ }
14489
+ function formatRelativeTime(isoDate) {
14490
+ const date5 = new Date(isoDate);
14491
+ const now = /* @__PURE__ */ new Date();
14492
+ const diffMs = now.getTime() - date5.getTime();
14493
+ const diffSec = Math.floor(diffMs / 1e3);
14494
+ const diffMin = Math.floor(diffSec / 60);
14495
+ const diffHour = Math.floor(diffMin / 60);
14496
+ const diffDay = Math.floor(diffHour / 24);
14497
+ const diffWeek = Math.floor(diffDay / 7);
14498
+ if (diffSec < 60) return "just now";
14499
+ if (diffMin < 60) return `${diffMin} minute${diffMin === 1 ? "" : "s"} ago`;
14500
+ if (diffHour < 24) return `${diffHour} hour${diffHour === 1 ? "" : "s"} ago`;
14501
+ if (diffDay < 7) return `${diffDay} day${diffDay === 1 ? "" : "s"} ago`;
14502
+ return `${diffWeek} week${diffWeek === 1 ? "" : "s"} ago`;
14503
+ }
14343
14504
  function excludeVm0Filter(filePath) {
14344
14505
  const shouldExclude = filePath === ".vm0" || filePath.startsWith(".vm0/") || filePath.startsWith("./.vm0");
14345
14506
  return !shouldExclude;
@@ -14679,6 +14840,11 @@ async function uploadSkill(skillUrl) {
14679
14840
  }
14680
14841
 
14681
14842
  // src/commands/compose.ts
14843
+ function getSecretsFromComposeContent(content) {
14844
+ const refs = extractVariableReferences(content);
14845
+ const grouped = groupVariablesBySource(refs);
14846
+ return new Set(grouped.secrets.map((r) => r.name));
14847
+ }
14682
14848
  function transformExperimentalShorthand(agent) {
14683
14849
  const experimentalSecrets = agent.experimental_secrets;
14684
14850
  const experimentalVars = agent.experimental_vars;
@@ -14843,6 +15009,15 @@ var composeCommand = new Command().name("compose").description("Create or update
14843
15009
  const newVars = [...skillVars.entries()].filter(
14844
15010
  ([name]) => !(name in environment)
14845
15011
  );
15012
+ let headSecrets = /* @__PURE__ */ new Set();
15013
+ try {
15014
+ const existingCompose = await apiClient.getComposeByName(agentName);
15015
+ if (existingCompose.content) {
15016
+ headSecrets = getSecretsFromComposeContent(existingCompose.content);
15017
+ }
15018
+ } catch {
15019
+ }
15020
+ const trulyNewSecrets = newSecrets.map(([name]) => name).filter((name) => !headSecrets.has(name));
14846
15021
  if (newSecrets.length > 0 || newVars.length > 0) {
14847
15022
  console.log();
14848
15023
  console.log(
@@ -14852,7 +15027,11 @@ var composeCommand = new Command().name("compose").description("Create or update
14852
15027
  if (newSecrets.length > 0) {
14853
15028
  console.log(chalk2.cyan(" Secrets:"));
14854
15029
  for (const [name, skills] of newSecrets) {
14855
- console.log(` ${name.padEnd(24)} <- ${skills.join(", ")}`);
15030
+ const isNew = trulyNewSecrets.includes(name);
15031
+ const newMarker = isNew ? chalk2.yellow(" (new)") : "";
15032
+ console.log(
15033
+ ` ${name.padEnd(24)}${newMarker} <- ${skills.join(", ")}`
15034
+ );
14856
15035
  }
14857
15036
  }
14858
15037
  if (newVars.length > 0) {
@@ -14862,24 +15041,31 @@ var composeCommand = new Command().name("compose").description("Create or update
14862
15041
  }
14863
15042
  }
14864
15043
  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);
15044
+ if (trulyNewSecrets.length > 0) {
15045
+ if (!options.yes) {
15046
+ if (!process.stdin.isTTY) {
15047
+ console.error(
15048
+ chalk2.red(
15049
+ `\u2717 New secrets detected: ${trulyNewSecrets.join(", ")}`
15050
+ )
15051
+ );
15052
+ console.error(
15053
+ chalk2.dim(
15054
+ " Use --yes flag to approve new secrets in non-interactive mode."
15055
+ )
15056
+ );
15057
+ process.exit(1);
15058
+ }
15059
+ const response2 = await prompts({
15060
+ type: "confirm",
15061
+ name: "value",
15062
+ message: `Approve ${trulyNewSecrets.length} new secret(s)?`,
15063
+ initial: true
15064
+ });
15065
+ if (!response2.value) {
15066
+ console.log(chalk2.yellow("Compose cancelled."));
15067
+ process.exit(0);
15068
+ }
14883
15069
  }
14884
15070
  }
14885
15071
  for (const [name] of newSecrets) {
@@ -15195,9 +15381,9 @@ var CodexEventParser = class {
15195
15381
  }
15196
15382
  }
15197
15383
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
15198
- const changes = item.changes.map((c10) => {
15199
- const action = c10.kind === "add" ? "Created" : c10.kind === "modify" ? "Modified" : "Deleted";
15200
- return `${action}: ${c10.path}`;
15384
+ const changes = item.changes.map((c11) => {
15385
+ const action = c11.kind === "add" ? "Created" : c11.kind === "modify" ? "Modified" : "Deleted";
15386
+ return `${action}: ${c11.path}`;
15201
15387
  }).join("\n");
15202
15388
  return {
15203
15389
  type: "text",
@@ -15538,9 +15724,9 @@ var CodexEventRenderer = class {
15538
15724
  return;
15539
15725
  }
15540
15726
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
15541
- const summary = item.changes.map((c10) => {
15542
- const icon = c10.kind === "add" ? "+" : c10.kind === "delete" ? "-" : "~";
15543
- return `${icon}${c10.path}`;
15727
+ const summary = item.changes.map((c11) => {
15728
+ const icon = c11.kind === "add" ? "+" : c11.kind === "delete" ? "-" : "~";
15729
+ return `${icon}${c11.path}`;
15544
15730
  }).join(", ");
15545
15731
  console.log(chalk4.green("[files]") + ` ${summary}`);
15546
15732
  return;
@@ -15959,8 +16145,9 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
15959
16145
  console.error(chalk5.dim(" Checkpoint ID must be a valid UUID"));
15960
16146
  process.exit(1);
15961
16147
  }
15962
- const secretNames = Object.keys(secrets);
15963
- const loadedSecrets = secretNames.length > 0 ? secrets : loadValues({}, []);
16148
+ const checkpointInfo = await apiClient.getCheckpoint(checkpointId);
16149
+ const requiredSecretNames = checkpointInfo.agentComposeSnapshot.secretNames || [];
16150
+ const loadedSecrets = loadValues(secrets, requiredSecretNames);
15964
16151
  if (verbose) {
15965
16152
  logVerbosePreFlight("Resuming agent run from checkpoint", [
15966
16153
  { label: "Checkpoint ID", value: checkpointId },
@@ -16056,8 +16243,9 @@ runCmd.command("continue").description(
16056
16243
  console.error(chalk5.dim(" Agent session ID must be a valid UUID"));
16057
16244
  process.exit(1);
16058
16245
  }
16059
- const secretNames = Object.keys(secrets);
16060
- const loadedSecrets = secretNames.length > 0 ? secrets : loadValues({}, []);
16246
+ const sessionInfo = await apiClient.getSession(agentSessionId);
16247
+ const requiredSecretNames = sessionInfo.secretNames || [];
16248
+ const loadedSecrets = loadValues(secrets, requiredSecretNames);
16061
16249
  if (verbose) {
16062
16250
  logVerbosePreFlight("Continuing agent run from session", [
16063
16251
  { label: "Session ID", value: agentSessionId },
@@ -16127,7 +16315,7 @@ runCmd.command("continue").description(
16127
16315
  var runCommand = runCmd;
16128
16316
 
16129
16317
  // src/commands/volume/index.ts
16130
- import { Command as Command7 } from "commander";
16318
+ import { Command as Command9 } from "commander";
16131
16319
 
16132
16320
  // src/commands/volume/init.ts
16133
16321
  import { Command as Command3 } from "commander";
@@ -16181,8 +16369,53 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
16181
16369
  await writeFile4(configPath, yamlContent, "utf8");
16182
16370
  }
16183
16371
 
16372
+ // src/lib/prompt-utils.ts
16373
+ import prompts2 from "prompts";
16374
+ function isInteractive() {
16375
+ return process.stdout.isTTY === true;
16376
+ }
16377
+ async function promptText(message, initial, validate) {
16378
+ if (!isInteractive()) {
16379
+ return void 0;
16380
+ }
16381
+ const response = await prompts2(
16382
+ {
16383
+ type: "text",
16384
+ name: "value",
16385
+ message,
16386
+ initial,
16387
+ validate
16388
+ },
16389
+ {
16390
+ onCancel: () => {
16391
+ return false;
16392
+ }
16393
+ }
16394
+ );
16395
+ return response.value;
16396
+ }
16397
+ async function promptConfirm(message, initial = true) {
16398
+ if (!isInteractive()) {
16399
+ return void 0;
16400
+ }
16401
+ const response = await prompts2(
16402
+ {
16403
+ type: "confirm",
16404
+ name: "value",
16405
+ message,
16406
+ initial
16407
+ },
16408
+ {
16409
+ onCancel: () => {
16410
+ return false;
16411
+ }
16412
+ }
16413
+ );
16414
+ return response.value;
16415
+ }
16416
+
16184
16417
  // src/commands/volume/init.ts
16185
- var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").action(async () => {
16418
+ 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
16419
  try {
16187
16420
  const cwd = process.cwd();
16188
16421
  const dirName = path7.basename(cwd);
@@ -16196,9 +16429,37 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
16196
16429
  );
16197
16430
  return;
16198
16431
  }
16199
- const volumeName = dirName;
16432
+ let volumeName;
16433
+ if (options.name) {
16434
+ volumeName = options.name;
16435
+ } else if (!isInteractive()) {
16436
+ console.error(
16437
+ chalk6.red("\u2717 --name flag is required in non-interactive mode")
16438
+ );
16439
+ console.error(
16440
+ chalk6.dim(" Usage: vm0 volume init --name <volume-name>")
16441
+ );
16442
+ process.exit(1);
16443
+ } else {
16444
+ const defaultName = isValidStorageName(dirName) ? dirName : void 0;
16445
+ const name = await promptText(
16446
+ "Enter volume name",
16447
+ defaultName,
16448
+ (value) => {
16449
+ if (!isValidStorageName(value)) {
16450
+ return "Must be 3-64 characters, lowercase alphanumeric with hyphens";
16451
+ }
16452
+ return true;
16453
+ }
16454
+ );
16455
+ if (name === void 0) {
16456
+ console.log(chalk6.dim("Cancelled"));
16457
+ return;
16458
+ }
16459
+ volumeName = name;
16460
+ }
16200
16461
  if (!isValidStorageName(volumeName)) {
16201
- console.error(chalk6.red(`\u2717 Invalid volume name: "${dirName}"`));
16462
+ console.error(chalk6.red(`\u2717 Invalid volume name: "${volumeName}"`));
16202
16463
  console.error(
16203
16464
  chalk6.dim(
16204
16465
  " Volume names must be 3-64 characters, lowercase alphanumeric with hyphens"
@@ -16228,7 +16489,7 @@ var initCommand = new Command3().name("init").description("Initialize a volume i
16228
16489
  // src/commands/volume/push.ts
16229
16490
  import { Command as Command4 } from "commander";
16230
16491
  import chalk7 from "chalk";
16231
- function formatBytes(bytes) {
16492
+ function formatBytes2(bytes) {
16232
16493
  if (bytes === 0) return "0 B";
16233
16494
  const k = 1024;
16234
16495
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16264,7 +16525,7 @@ var pushCommand = new Command4().name("push").description("Push local files to c
16264
16525
  }
16265
16526
  console.log(chalk7.dim(` Version: ${shortVersion}`));
16266
16527
  console.log(chalk7.dim(` Files: ${result.fileCount.toLocaleString()}`));
16267
- console.log(chalk7.dim(` Size: ${formatBytes(result.size)}`));
16528
+ console.log(chalk7.dim(` Size: ${formatBytes2(result.size)}`));
16268
16529
  } catch (error43) {
16269
16530
  console.error(chalk7.red("\u2717 Push failed"));
16270
16531
  if (error43 instanceof Error) {
@@ -16295,7 +16556,7 @@ async function handleEmptyStorageResponse(cwd) {
16295
16556
  }
16296
16557
 
16297
16558
  // src/commands/volume/pull.ts
16298
- function formatBytes2(bytes) {
16559
+ function formatBytes3(bytes) {
16299
16560
  if (bytes === 0) return "0 B";
16300
16561
  const k = 1024;
16301
16562
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16354,7 +16615,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
16354
16615
  }
16355
16616
  const arrayBuffer = await s3Response.arrayBuffer();
16356
16617
  const tarBuffer = Buffer.from(arrayBuffer);
16357
- console.log(chalk9.green(`\u2713 Downloaded ${formatBytes2(tarBuffer.length)}`));
16618
+ console.log(chalk9.green(`\u2713 Downloaded ${formatBytes3(tarBuffer.length)}`));
16358
16619
  const tmpDir = fs6.mkdtempSync(path8.join(os4.tmpdir(), "vm0-"));
16359
16620
  const tarPath = path8.join(tmpDir, "volume.tar.gz");
16360
16621
  await fs6.promises.writeFile(tarPath, tarBuffer);
@@ -16390,7 +16651,7 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
16390
16651
  // src/commands/volume/status.ts
16391
16652
  import { Command as Command6 } from "commander";
16392
16653
  import chalk10 from "chalk";
16393
- function formatBytes3(bytes) {
16654
+ function formatBytes4(bytes) {
16394
16655
  if (bytes === 0) return "0 B";
16395
16656
  const k = 1024;
16396
16657
  const sizes = ["B", "KB", "MB", "GB"];
@@ -16437,7 +16698,7 @@ var statusCommand = new Command6().name("status").description("Show status of cl
16437
16698
  console.log(chalk10.green("\u2713 Found"));
16438
16699
  console.log(chalk10.dim(` Version: ${shortVersion}`));
16439
16700
  console.log(chalk10.dim(` Files: ${info.fileCount.toLocaleString()}`));
16440
- console.log(chalk10.dim(` Size: ${formatBytes3(info.size)}`));
16701
+ console.log(chalk10.dim(` Size: ${formatBytes4(info.size)}`));
16441
16702
  }
16442
16703
  } catch (error43) {
16443
16704
  console.error(chalk10.red("\u2717 Status check failed"));
@@ -16448,85 +16709,275 @@ var statusCommand = new Command6().name("status").description("Show status of cl
16448
16709
  }
16449
16710
  });
16450
16711
 
16712
+ // src/commands/volume/list.ts
16713
+ import { Command as Command7 } from "commander";
16714
+ import chalk11 from "chalk";
16715
+ var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
16716
+ try {
16717
+ const url2 = "/api/storages/list?type=volume";
16718
+ const response = await apiClient.get(url2);
16719
+ if (!response.ok) {
16720
+ const error43 = await response.json();
16721
+ throw new Error(error43.error?.message || "List failed");
16722
+ }
16723
+ const items = await response.json();
16724
+ if (items.length === 0) {
16725
+ console.log(chalk11.dim("No volumes found"));
16726
+ console.log(
16727
+ chalk11.dim(" Create one with: vm0 volume init && vm0 volume push")
16728
+ );
16729
+ return;
16730
+ }
16731
+ const nameWidth = Math.max(4, ...items.map((i) => i.name.length));
16732
+ const sizeWidth = Math.max(
16733
+ 4,
16734
+ ...items.map((i) => formatBytes(i.size).length)
16735
+ );
16736
+ const filesWidth = Math.max(
16737
+ 5,
16738
+ ...items.map((i) => i.fileCount.toString().length)
16739
+ );
16740
+ const header = [
16741
+ "NAME".padEnd(nameWidth),
16742
+ "SIZE".padStart(sizeWidth),
16743
+ "FILES".padStart(filesWidth),
16744
+ "UPDATED"
16745
+ ].join(" ");
16746
+ console.log(chalk11.dim(header));
16747
+ for (const item of items) {
16748
+ const row = [
16749
+ item.name.padEnd(nameWidth),
16750
+ formatBytes(item.size).padStart(sizeWidth),
16751
+ item.fileCount.toString().padStart(filesWidth),
16752
+ formatRelativeTime(item.updatedAt)
16753
+ ].join(" ");
16754
+ console.log(row);
16755
+ }
16756
+ } catch (error43) {
16757
+ console.error(chalk11.red("\u2717 Failed to list volumes"));
16758
+ if (error43 instanceof Error) {
16759
+ if (error43.message.includes("Not authenticated")) {
16760
+ console.error(chalk11.dim(" Run: vm0 auth login"));
16761
+ } else {
16762
+ console.error(chalk11.dim(` ${error43.message}`));
16763
+ }
16764
+ }
16765
+ process.exit(1);
16766
+ }
16767
+ });
16768
+
16769
+ // src/commands/volume/clone.ts
16770
+ import { Command as Command8 } from "commander";
16771
+ import chalk13 from "chalk";
16772
+
16773
+ // src/lib/clone-utils.ts
16774
+ import chalk12 from "chalk";
16775
+ import path9 from "path";
16776
+ import * as fs7 from "fs";
16777
+ import * as os5 from "os";
16778
+ import * as tar4 from "tar";
16779
+ async function cloneStorage(name, type, destination, options = {}) {
16780
+ const typeLabel = type === "artifact" ? "artifact" : "volume";
16781
+ if (fs7.existsSync(destination)) {
16782
+ throw new Error(`Directory "${destination}" already exists`);
16783
+ }
16784
+ console.log(chalk12.dim(`Checking remote ${typeLabel}...`));
16785
+ let url2 = `/api/storages/download?name=${encodeURIComponent(name)}&type=${type}`;
16786
+ if (options.version) {
16787
+ url2 += `&version=${encodeURIComponent(options.version)}`;
16788
+ }
16789
+ const response = await apiClient.get(url2);
16790
+ if (!response.ok) {
16791
+ if (response.status === 404) {
16792
+ throw new Error(
16793
+ `${typeLabel.charAt(0).toUpperCase() + typeLabel.slice(1)} "${name}" not found`
16794
+ );
16795
+ }
16796
+ const error43 = await response.json();
16797
+ throw new Error(error43.error?.message || "Clone failed");
16798
+ }
16799
+ const downloadInfo = await response.json();
16800
+ console.log(chalk12.dim(`Creating directory: ${destination}/`));
16801
+ await fs7.promises.mkdir(destination, { recursive: true });
16802
+ if (downloadInfo.empty) {
16803
+ await writeStorageConfig(name, destination, type);
16804
+ console.log(chalk12.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
16805
+ console.log(chalk12.dim(`\u2713 Initialized .vm0/storage.yaml`));
16806
+ return {
16807
+ success: true,
16808
+ fileCount: 0,
16809
+ size: 0,
16810
+ versionId: downloadInfo.versionId
16811
+ };
16812
+ }
16813
+ if (!downloadInfo.url) {
16814
+ throw new Error("No download URL returned");
16815
+ }
16816
+ console.log(chalk12.dim("Downloading from S3..."));
16817
+ const s3Response = await fetch(downloadInfo.url);
16818
+ if (!s3Response.ok) {
16819
+ await fs7.promises.rm(destination, { recursive: true, force: true });
16820
+ throw new Error(`S3 download failed: ${s3Response.status}`);
16821
+ }
16822
+ const arrayBuffer = await s3Response.arrayBuffer();
16823
+ const tarBuffer = Buffer.from(arrayBuffer);
16824
+ console.log(chalk12.green(`\u2713 Downloaded ${formatBytes(tarBuffer.length)}`));
16825
+ const tmpDir = fs7.mkdtempSync(path9.join(os5.tmpdir(), "vm0-clone-"));
16826
+ const tarPath = path9.join(tmpDir, "archive.tar.gz");
16827
+ await fs7.promises.writeFile(tarPath, tarBuffer);
16828
+ const files = await listTarFiles(tarPath);
16829
+ console.log(chalk12.dim("Extracting files..."));
16830
+ await tar4.extract({
16831
+ file: tarPath,
16832
+ cwd: destination,
16833
+ gzip: true
16834
+ });
16835
+ await fs7.promises.unlink(tarPath);
16836
+ await fs7.promises.rmdir(tmpDir);
16837
+ console.log(chalk12.green(`\u2713 Extracted ${files.length} files`));
16838
+ await writeStorageConfig(name, destination, type);
16839
+ console.log(chalk12.green(`\u2713 Initialized .vm0/storage.yaml`));
16840
+ return {
16841
+ success: true,
16842
+ fileCount: downloadInfo.fileCount,
16843
+ size: downloadInfo.size,
16844
+ versionId: downloadInfo.versionId
16845
+ };
16846
+ }
16847
+
16848
+ // src/commands/volume/clone.ts
16849
+ 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) => {
16850
+ try {
16851
+ const targetDir = destination || name;
16852
+ console.log(`Cloning volume: ${name}`);
16853
+ const result = await cloneStorage(name, "volume", targetDir);
16854
+ console.log(chalk13.green(`
16855
+ \u2713 Successfully cloned volume: ${name}`));
16856
+ console.log(chalk13.dim(` Location: ${targetDir}/`));
16857
+ console.log(chalk13.dim(` Version: ${result.versionId.slice(0, 8)}`));
16858
+ } catch (error43) {
16859
+ console.error(chalk13.red("\u2717 Clone failed"));
16860
+ if (error43 instanceof Error) {
16861
+ if (error43.message.includes("Not authenticated")) {
16862
+ console.error(chalk13.dim(" Run: vm0 auth login"));
16863
+ } else {
16864
+ console.error(chalk13.dim(` ${error43.message}`));
16865
+ }
16866
+ }
16867
+ process.exit(1);
16868
+ }
16869
+ });
16870
+
16451
16871
  // src/commands/volume/index.ts
16452
- var volumeCommand = new Command7().name("volume").description("Manage cloud volumes").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand);
16872
+ var volumeCommand = new Command9().name("volume").description("Manage cloud volumes").addCommand(initCommand).addCommand(pushCommand).addCommand(pullCommand).addCommand(statusCommand).addCommand(listCommand).addCommand(cloneCommand);
16453
16873
 
16454
16874
  // src/commands/artifact/index.ts
16455
- import { Command as Command12 } from "commander";
16875
+ import { Command as Command16 } from "commander";
16456
16876
 
16457
16877
  // 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 () => {
16878
+ import { Command as Command10 } from "commander";
16879
+ import chalk14 from "chalk";
16880
+ import path10 from "path";
16881
+ var initCommand2 = new Command10().name("init").description("Initialize an artifact in the current directory").option(
16882
+ "-n, --name <name>",
16883
+ "Artifact name (required in non-interactive mode)"
16884
+ ).action(async (options) => {
16462
16885
  try {
16463
16886
  const cwd = process.cwd();
16464
- const dirName = path9.basename(cwd);
16887
+ const dirName = path10.basename(cwd);
16465
16888
  const existingConfig = await readStorageConfig(cwd);
16466
16889
  if (existingConfig) {
16467
16890
  if (existingConfig.type === "artifact") {
16468
16891
  console.log(
16469
- chalk11.yellow(
16892
+ chalk14.yellow(
16470
16893
  `Artifact already initialized: ${existingConfig.name}`
16471
16894
  )
16472
16895
  );
16473
16896
  } else {
16474
16897
  console.log(
16475
- chalk11.yellow(
16898
+ chalk14.yellow(
16476
16899
  `Directory already initialized as volume: ${existingConfig.name}`
16477
16900
  )
16478
16901
  );
16479
16902
  console.log(
16480
- chalk11.dim(
16903
+ chalk14.dim(
16481
16904
  " To change type, delete .vm0/storage.yaml and reinitialize"
16482
16905
  )
16483
16906
  );
16484
16907
  }
16485
16908
  console.log(
16486
- chalk11.dim(`Config file: ${path9.join(cwd, ".vm0", "storage.yaml")}`)
16909
+ chalk14.dim(`Config file: ${path10.join(cwd, ".vm0", "storage.yaml")}`)
16487
16910
  );
16488
16911
  return;
16489
16912
  }
16490
- const artifactName = dirName;
16913
+ let artifactName;
16914
+ if (options.name) {
16915
+ artifactName = options.name;
16916
+ } else if (!isInteractive()) {
16917
+ console.error(
16918
+ chalk14.red("\u2717 --name flag is required in non-interactive mode")
16919
+ );
16920
+ console.error(
16921
+ chalk14.dim(" Usage: vm0 artifact init --name <artifact-name>")
16922
+ );
16923
+ process.exit(1);
16924
+ } else {
16925
+ const defaultName = isValidStorageName(dirName) ? dirName : void 0;
16926
+ const name = await promptText(
16927
+ "Enter artifact name",
16928
+ defaultName,
16929
+ (value) => {
16930
+ if (!isValidStorageName(value)) {
16931
+ return "Must be 3-64 characters, lowercase alphanumeric with hyphens";
16932
+ }
16933
+ return true;
16934
+ }
16935
+ );
16936
+ if (name === void 0) {
16937
+ console.log(chalk14.dim("Cancelled"));
16938
+ return;
16939
+ }
16940
+ artifactName = name;
16941
+ }
16491
16942
  if (!isValidStorageName(artifactName)) {
16492
- console.error(chalk11.red(`\u2717 Invalid artifact name: "${dirName}"`));
16943
+ console.error(chalk14.red(`\u2717 Invalid artifact name: "${artifactName}"`));
16493
16944
  console.error(
16494
- chalk11.dim(
16945
+ chalk14.dim(
16495
16946
  " Artifact names must be 3-64 characters, lowercase alphanumeric with hyphens"
16496
16947
  )
16497
16948
  );
16498
16949
  console.error(
16499
- chalk11.dim(" Example: my-project, user-workspace, code-artifact")
16950
+ chalk14.dim(" Example: my-project, user-workspace, code-artifact")
16500
16951
  );
16501
16952
  process.exit(1);
16502
16953
  }
16503
16954
  await writeStorageConfig(artifactName, cwd, "artifact");
16504
- console.log(chalk11.green(`\u2713 Initialized artifact: ${artifactName}`));
16955
+ console.log(chalk14.green(`\u2713 Initialized artifact: ${artifactName}`));
16505
16956
  console.log(
16506
- chalk11.dim(
16507
- `\u2713 Config saved to ${path9.join(cwd, ".vm0", "storage.yaml")}`
16957
+ chalk14.dim(
16958
+ `\u2713 Config saved to ${path10.join(cwd, ".vm0", "storage.yaml")}`
16508
16959
  )
16509
16960
  );
16510
16961
  } catch (error43) {
16511
- console.error(chalk11.red("\u2717 Failed to initialize artifact"));
16962
+ console.error(chalk14.red("\u2717 Failed to initialize artifact"));
16512
16963
  if (error43 instanceof Error) {
16513
- console.error(chalk11.dim(` ${error43.message}`));
16964
+ console.error(chalk14.dim(` ${error43.message}`));
16514
16965
  }
16515
16966
  process.exit(1);
16516
16967
  }
16517
16968
  });
16518
16969
 
16519
16970
  // src/commands/artifact/push.ts
16520
- import { Command as Command9 } from "commander";
16521
- import chalk12 from "chalk";
16522
- function formatBytes4(bytes) {
16971
+ import { Command as Command11 } from "commander";
16972
+ import chalk15 from "chalk";
16973
+ function formatBytes5(bytes) {
16523
16974
  if (bytes === 0) return "0 B";
16524
16975
  const k = 1024;
16525
16976
  const sizes = ["B", "KB", "MB", "GB"];
16526
16977
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16527
16978
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16528
16979
  }
16529
- var pushCommand2 = new Command9().name("push").description("Push local files to cloud artifact").option(
16980
+ var pushCommand2 = new Command11().name("push").description("Push local files to cloud artifact").option(
16530
16981
  "-f, --force",
16531
16982
  "Force upload even if content unchanged (recreate archive)"
16532
16983
  ).action(async (options) => {
@@ -16534,76 +16985,76 @@ var pushCommand2 = new Command9().name("push").description("Push local files to
16534
16985
  const cwd = process.cwd();
16535
16986
  const config2 = await readStorageConfig(cwd);
16536
16987
  if (!config2) {
16537
- console.error(chalk12.red("\u2717 No artifact initialized in this directory"));
16538
- console.error(chalk12.dim(" Run: vm0 artifact init"));
16988
+ console.error(chalk15.red("\u2717 No artifact initialized in this directory"));
16989
+ console.error(chalk15.dim(" Run: vm0 artifact init"));
16539
16990
  process.exit(1);
16540
16991
  }
16541
16992
  if (config2.type !== "artifact") {
16542
16993
  console.error(
16543
- chalk12.red(
16994
+ chalk15.red(
16544
16995
  `\u2717 This directory is initialized as a volume, not an artifact`
16545
16996
  )
16546
16997
  );
16547
- console.error(chalk12.dim(" Use: vm0 volume push"));
16998
+ console.error(chalk15.dim(" Use: vm0 volume push"));
16548
16999
  process.exit(1);
16549
17000
  }
16550
17001
  console.log(`Pushing artifact: ${config2.name}`);
16551
17002
  const result = await directUpload(config2.name, "artifact", cwd, {
16552
17003
  onProgress: (message) => {
16553
- console.log(chalk12.dim(message));
17004
+ console.log(chalk15.dim(message));
16554
17005
  },
16555
17006
  force: options.force
16556
17007
  });
16557
17008
  const shortVersion = result.versionId.slice(0, 8);
16558
17009
  if (result.empty) {
16559
- console.log(chalk12.yellow("No files found (empty artifact)"));
17010
+ console.log(chalk15.yellow("No files found (empty artifact)"));
16560
17011
  } else if (result.deduplicated) {
16561
- console.log(chalk12.green("\u2713 Content unchanged (deduplicated)"));
17012
+ console.log(chalk15.green("\u2713 Content unchanged (deduplicated)"));
16562
17013
  } else {
16563
- console.log(chalk12.green("\u2713 Upload complete"));
17014
+ console.log(chalk15.green("\u2713 Upload complete"));
16564
17015
  }
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)}`));
17016
+ console.log(chalk15.dim(` Version: ${shortVersion}`));
17017
+ console.log(chalk15.dim(` Files: ${result.fileCount.toLocaleString()}`));
17018
+ console.log(chalk15.dim(` Size: ${formatBytes5(result.size)}`));
16568
17019
  } catch (error43) {
16569
- console.error(chalk12.red("\u2717 Push failed"));
17020
+ console.error(chalk15.red("\u2717 Push failed"));
16570
17021
  if (error43 instanceof Error) {
16571
- console.error(chalk12.dim(` ${error43.message}`));
17022
+ console.error(chalk15.dim(` ${error43.message}`));
16572
17023
  }
16573
17024
  process.exit(1);
16574
17025
  }
16575
17026
  });
16576
17027
 
16577
17028
  // 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) {
17029
+ import { Command as Command12 } from "commander";
17030
+ import chalk16 from "chalk";
17031
+ import path11 from "path";
17032
+ import * as fs8 from "fs";
17033
+ import * as os6 from "os";
17034
+ import * as tar5 from "tar";
17035
+ function formatBytes6(bytes) {
16585
17036
  if (bytes === 0) return "0 B";
16586
17037
  const k = 1024;
16587
17038
  const sizes = ["B", "KB", "MB", "GB"];
16588
17039
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16589
17040
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16590
17041
  }
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) => {
17042
+ 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
17043
  try {
16593
17044
  const cwd = process.cwd();
16594
17045
  const config2 = await readStorageConfig(cwd);
16595
17046
  if (!config2) {
16596
- console.error(chalk13.red("\u2717 No artifact initialized in this directory"));
16597
- console.error(chalk13.dim(" Run: vm0 artifact init"));
17047
+ console.error(chalk16.red("\u2717 No artifact initialized in this directory"));
17048
+ console.error(chalk16.dim(" Run: vm0 artifact init"));
16598
17049
  process.exit(1);
16599
17050
  }
16600
17051
  if (config2.type !== "artifact") {
16601
17052
  console.error(
16602
- chalk13.red(
17053
+ chalk16.red(
16603
17054
  `\u2717 This directory is initialized as a volume, not an artifact`
16604
17055
  )
16605
17056
  );
16606
- console.error(chalk13.dim(" Use: vm0 volume pull"));
17057
+ console.error(chalk16.dim(" Use: vm0 volume pull"));
16607
17058
  process.exit(1);
16608
17059
  }
16609
17060
  if (versionId) {
@@ -16611,7 +17062,7 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16611
17062
  } else {
16612
17063
  console.log(`Pulling artifact: ${config2.name}`);
16613
17064
  }
16614
- console.log(chalk13.dim("Getting download URL..."));
17065
+ console.log(chalk16.dim("Getting download URL..."));
16615
17066
  let url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=artifact`;
16616
17067
  if (versionId) {
16617
17068
  url2 += `&version=${encodeURIComponent(versionId)}`;
@@ -16619,14 +17070,14 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16619
17070
  const response = await apiClient.get(url2);
16620
17071
  if (!response.ok) {
16621
17072
  if (response.status === 404) {
16622
- console.error(chalk13.red(`\u2717 Artifact "${config2.name}" not found`));
17073
+ console.error(chalk16.red(`\u2717 Artifact "${config2.name}" not found`));
16623
17074
  console.error(
16624
- chalk13.dim(
17075
+ chalk16.dim(
16625
17076
  " Make sure the artifact name is correct in .vm0/storage.yaml"
16626
17077
  )
16627
17078
  );
16628
17079
  console.error(
16629
- chalk13.dim(" Or push the artifact first with: vm0 artifact push")
17080
+ chalk16.dim(" Or push the artifact first with: vm0 artifact push")
16630
17081
  );
16631
17082
  } else {
16632
17083
  const error43 = await response.json();
@@ -16642,18 +17093,18 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16642
17093
  if (!downloadInfo.url) {
16643
17094
  throw new Error("No download URL returned");
16644
17095
  }
16645
- console.log(chalk13.dim("Downloading from S3..."));
17096
+ console.log(chalk16.dim("Downloading from S3..."));
16646
17097
  const s3Response = await fetch(downloadInfo.url);
16647
17098
  if (!s3Response.ok) {
16648
17099
  throw new Error(`S3 download failed: ${s3Response.status}`);
16649
17100
  }
16650
17101
  const arrayBuffer = await s3Response.arrayBuffer();
16651
17102
  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..."));
17103
+ console.log(chalk16.green(`\u2713 Downloaded ${formatBytes6(tarBuffer.length)}`));
17104
+ const tmpDir = fs8.mkdtempSync(path11.join(os6.tmpdir(), "vm0-"));
17105
+ const tarPath = path11.join(tmpDir, "artifact.tar.gz");
17106
+ await fs8.promises.writeFile(tarPath, tarBuffer);
17107
+ console.log(chalk16.dim("Syncing local files..."));
16657
17108
  const remoteFiles = await listTarFiles(tarPath);
16658
17109
  const remoteFilesSet = new Set(
16659
17110
  remoteFiles.map((f) => f.replace(/\\/g, "/"))
@@ -16661,53 +17112,53 @@ var pullCommand2 = new Command10().name("pull").description("Pull cloud artifact
16661
17112
  const removedCount = await removeExtraFiles(cwd, remoteFilesSet);
16662
17113
  if (removedCount > 0) {
16663
17114
  console.log(
16664
- chalk13.green(`\u2713 Removed ${removedCount} files not in remote`)
17115
+ chalk16.green(`\u2713 Removed ${removedCount} files not in remote`)
16665
17116
  );
16666
17117
  }
16667
- console.log(chalk13.dim("Extracting files..."));
16668
- await tar4.extract({
17118
+ console.log(chalk16.dim("Extracting files..."));
17119
+ await tar5.extract({
16669
17120
  file: tarPath,
16670
17121
  cwd,
16671
17122
  gzip: true
16672
17123
  });
16673
- await fs7.promises.unlink(tarPath);
16674
- await fs7.promises.rmdir(tmpDir);
16675
- console.log(chalk13.green(`\u2713 Extracted ${remoteFiles.length} files`));
17124
+ await fs8.promises.unlink(tarPath);
17125
+ await fs8.promises.rmdir(tmpDir);
17126
+ console.log(chalk16.green(`\u2713 Extracted ${remoteFiles.length} files`));
16676
17127
  } catch (error43) {
16677
- console.error(chalk13.red("\u2717 Pull failed"));
17128
+ console.error(chalk16.red("\u2717 Pull failed"));
16678
17129
  if (error43 instanceof Error) {
16679
- console.error(chalk13.dim(` ${error43.message}`));
17130
+ console.error(chalk16.dim(` ${error43.message}`));
16680
17131
  }
16681
17132
  process.exit(1);
16682
17133
  }
16683
17134
  });
16684
17135
 
16685
17136
  // src/commands/artifact/status.ts
16686
- import { Command as Command11 } from "commander";
16687
- import chalk14 from "chalk";
16688
- function formatBytes6(bytes) {
17137
+ import { Command as Command13 } from "commander";
17138
+ import chalk17 from "chalk";
17139
+ function formatBytes7(bytes) {
16689
17140
  if (bytes === 0) return "0 B";
16690
17141
  const k = 1024;
16691
17142
  const sizes = ["B", "KB", "MB", "GB"];
16692
17143
  const i = Math.floor(Math.log(bytes) / Math.log(k));
16693
17144
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
16694
17145
  }
16695
- var statusCommand2 = new Command11().name("status").description("Show status of cloud artifact").action(async () => {
17146
+ var statusCommand2 = new Command13().name("status").description("Show status of cloud artifact").action(async () => {
16696
17147
  try {
16697
17148
  const cwd = process.cwd();
16698
17149
  const config2 = await readStorageConfig(cwd);
16699
17150
  if (!config2) {
16700
- console.error(chalk14.red("\u2717 No artifact initialized in this directory"));
16701
- console.error(chalk14.dim(" Run: vm0 artifact init"));
17151
+ console.error(chalk17.red("\u2717 No artifact initialized in this directory"));
17152
+ console.error(chalk17.dim(" Run: vm0 artifact init"));
16702
17153
  process.exit(1);
16703
17154
  }
16704
17155
  if (config2.type !== "artifact") {
16705
17156
  console.error(
16706
- chalk14.red(
17157
+ chalk17.red(
16707
17158
  "\u2717 This directory is initialized as a volume, not an artifact"
16708
17159
  )
16709
17160
  );
16710
- console.error(chalk14.dim(" Use: vm0 volume status"));
17161
+ console.error(chalk17.dim(" Use: vm0 volume status"));
16711
17162
  process.exit(1);
16712
17163
  }
16713
17164
  console.log(`Checking artifact: ${config2.name}`);
@@ -16715,8 +17166,8 @@ var statusCommand2 = new Command11().name("status").description("Show status of
16715
17166
  const response = await apiClient.get(url2);
16716
17167
  if (!response.ok) {
16717
17168
  if (response.status === 404) {
16718
- console.error(chalk14.red("\u2717 Not found on remote"));
16719
- console.error(chalk14.dim(" Run: vm0 artifact push"));
17169
+ console.error(chalk17.red("\u2717 Not found on remote"));
17170
+ console.error(chalk17.dim(" Run: vm0 artifact push"));
16720
17171
  } else {
16721
17172
  const error43 = await response.json();
16722
17173
  throw new Error(error43.error?.message || "Status check failed");
@@ -16726,32 +17177,116 @@ var statusCommand2 = new Command11().name("status").description("Show status of
16726
17177
  const info = await response.json();
16727
17178
  const shortVersion = info.versionId.slice(0, 8);
16728
17179
  if (info.empty) {
16729
- console.log(chalk14.green("\u2713 Found (empty)"));
16730
- console.log(chalk14.dim(` Version: ${shortVersion}`));
17180
+ console.log(chalk17.green("\u2713 Found (empty)"));
17181
+ console.log(chalk17.dim(` Version: ${shortVersion}`));
16731
17182
  } 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)}`));
17183
+ console.log(chalk17.green("\u2713 Found"));
17184
+ console.log(chalk17.dim(` Version: ${shortVersion}`));
17185
+ console.log(chalk17.dim(` Files: ${info.fileCount.toLocaleString()}`));
17186
+ console.log(chalk17.dim(` Size: ${formatBytes7(info.size)}`));
16736
17187
  }
16737
17188
  } catch (error43) {
16738
- console.error(chalk14.red("\u2717 Status check failed"));
17189
+ console.error(chalk17.red("\u2717 Status check failed"));
16739
17190
  if (error43 instanceof Error) {
16740
- console.error(chalk14.dim(` ${error43.message}`));
17191
+ console.error(chalk17.dim(` ${error43.message}`));
17192
+ }
17193
+ process.exit(1);
17194
+ }
17195
+ });
17196
+
17197
+ // src/commands/artifact/list.ts
17198
+ import { Command as Command14 } from "commander";
17199
+ import chalk18 from "chalk";
17200
+ var listCommand2 = new Command14().name("list").alias("ls").description("List all remote artifacts").action(async () => {
17201
+ try {
17202
+ const url2 = "/api/storages/list?type=artifact";
17203
+ const response = await apiClient.get(url2);
17204
+ if (!response.ok) {
17205
+ const error43 = await response.json();
17206
+ throw new Error(error43.error?.message || "List failed");
17207
+ }
17208
+ const items = await response.json();
17209
+ if (items.length === 0) {
17210
+ console.log(chalk18.dim("No artifacts found"));
17211
+ console.log(
17212
+ chalk18.dim(
17213
+ " Create one with: vm0 artifact init && vm0 artifact push"
17214
+ )
17215
+ );
17216
+ return;
17217
+ }
17218
+ const nameWidth = Math.max(4, ...items.map((i) => i.name.length));
17219
+ const sizeWidth = Math.max(
17220
+ 4,
17221
+ ...items.map((i) => formatBytes(i.size).length)
17222
+ );
17223
+ const filesWidth = Math.max(
17224
+ 5,
17225
+ ...items.map((i) => i.fileCount.toString().length)
17226
+ );
17227
+ const header = [
17228
+ "NAME".padEnd(nameWidth),
17229
+ "SIZE".padStart(sizeWidth),
17230
+ "FILES".padStart(filesWidth),
17231
+ "UPDATED"
17232
+ ].join(" ");
17233
+ console.log(chalk18.dim(header));
17234
+ for (const item of items) {
17235
+ const row = [
17236
+ item.name.padEnd(nameWidth),
17237
+ formatBytes(item.size).padStart(sizeWidth),
17238
+ item.fileCount.toString().padStart(filesWidth),
17239
+ formatRelativeTime(item.updatedAt)
17240
+ ].join(" ");
17241
+ console.log(row);
17242
+ }
17243
+ } catch (error43) {
17244
+ console.error(chalk18.red("\u2717 Failed to list artifacts"));
17245
+ if (error43 instanceof Error) {
17246
+ if (error43.message.includes("Not authenticated")) {
17247
+ console.error(chalk18.dim(" Run: vm0 auth login"));
17248
+ } else {
17249
+ console.error(chalk18.dim(` ${error43.message}`));
17250
+ }
17251
+ }
17252
+ process.exit(1);
17253
+ }
17254
+ });
17255
+
17256
+ // src/commands/artifact/clone.ts
17257
+ import { Command as Command15 } from "commander";
17258
+ import chalk19 from "chalk";
17259
+ 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) => {
17260
+ try {
17261
+ const targetDir = destination || name;
17262
+ console.log(`Cloning artifact: ${name}`);
17263
+ const result = await cloneStorage(name, "artifact", targetDir);
17264
+ console.log(chalk19.green(`
17265
+ \u2713 Successfully cloned artifact: ${name}`));
17266
+ console.log(chalk19.dim(` Location: ${targetDir}/`));
17267
+ console.log(chalk19.dim(` Version: ${result.versionId.slice(0, 8)}`));
17268
+ } catch (error43) {
17269
+ console.error(chalk19.red("\u2717 Clone failed"));
17270
+ if (error43 instanceof Error) {
17271
+ if (error43.message.includes("Not authenticated")) {
17272
+ console.error(chalk19.dim(" Run: vm0 auth login"));
17273
+ } else {
17274
+ console.error(chalk19.dim(` ${error43.message}`));
17275
+ }
16741
17276
  }
16742
17277
  process.exit(1);
16743
17278
  }
16744
17279
  });
16745
17280
 
16746
17281
  // 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);
17282
+ 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
17283
 
16749
17284
  // src/commands/cook.ts
16750
- import { Command as Command13 } from "commander";
16751
- import chalk16 from "chalk";
17285
+ import { Command as Command17 } from "commander";
17286
+ import chalk21 from "chalk";
16752
17287
  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";
17288
+ import { existsSync as existsSync8, readFileSync } from "fs";
17289
+ import path12 from "path";
16755
17290
  import { spawn as spawn2 } from "child_process";
16756
17291
  import { parse as parseYaml4 } from "yaml";
16757
17292
  import { config as dotenvConfig2 } from "dotenv";
@@ -16759,7 +17294,7 @@ import { config as dotenvConfig2 } from "dotenv";
16759
17294
  // src/lib/update-checker.ts
16760
17295
  import https from "https";
16761
17296
  import { spawn } from "child_process";
16762
- import chalk15 from "chalk";
17297
+ import chalk20 from "chalk";
16763
17298
  var PACKAGE_NAME = "@vm0/cli";
16764
17299
  var NPM_REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
16765
17300
  var TIMEOUT_MS = 5e3;
@@ -16824,21 +17359,21 @@ function performUpgrade(packageManager) {
16824
17359
  async function checkAndUpgrade(currentVersion, prompt) {
16825
17360
  const latestVersion = await getLatestVersion();
16826
17361
  if (latestVersion === null) {
16827
- console.log(chalk15.yellow("Warning: Could not check for updates"));
17362
+ console.log(chalk20.yellow("Warning: Could not check for updates"));
16828
17363
  console.log();
16829
17364
  return false;
16830
17365
  }
16831
17366
  if (latestVersion === currentVersion) {
16832
17367
  return false;
16833
17368
  }
16834
- console.log(chalk15.yellow("vm0 is currently in Early Access (EA)."));
17369
+ console.log(chalk20.yellow("vm0 is currently in Early Access (EA)."));
16835
17370
  console.log(
16836
- chalk15.yellow(
17371
+ chalk20.yellow(
16837
17372
  `Current version: ${currentVersion} -> Latest version: ${latestVersion}`
16838
17373
  )
16839
17374
  );
16840
17375
  console.log(
16841
- chalk15.yellow(
17376
+ chalk20.yellow(
16842
17377
  "Please always use the latest version for best compatibility."
16843
17378
  )
16844
17379
  );
@@ -16847,20 +17382,20 @@ async function checkAndUpgrade(currentVersion, prompt) {
16847
17382
  console.log(`Upgrading via ${packageManager}...`);
16848
17383
  const success2 = await performUpgrade(packageManager);
16849
17384
  if (success2) {
16850
- console.log(chalk15.green(`Upgraded to ${latestVersion}`));
17385
+ console.log(chalk20.green(`Upgraded to ${latestVersion}`));
16851
17386
  console.log();
16852
17387
  console.log("To continue, run:");
16853
- console.log(chalk15.cyan(` ${buildRerunCommand(prompt)}`));
17388
+ console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
16854
17389
  return true;
16855
17390
  }
16856
17391
  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`));
17392
+ console.log(chalk20.red("Upgrade failed. Please run manually:"));
17393
+ console.log(chalk20.cyan(` npm install -g ${PACKAGE_NAME}@latest`));
17394
+ console.log(chalk20.dim(" # or"));
17395
+ console.log(chalk20.cyan(` pnpm add -g ${PACKAGE_NAME}@latest`));
16861
17396
  console.log();
16862
17397
  console.log("Then re-run:");
16863
- console.log(chalk15.cyan(` ${buildRerunCommand(prompt)}`));
17398
+ console.log(chalk20.cyan(` ${buildRerunCommand(prompt)}`));
16864
17399
  return true;
16865
17400
  }
16866
17401
 
@@ -16868,12 +17403,12 @@ async function checkAndUpgrade(currentVersion, prompt) {
16868
17403
  import { homedir as homedir2 } from "os";
16869
17404
  import { join as join6 } from "path";
16870
17405
  import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
16871
- import { existsSync as existsSync6 } from "fs";
17406
+ import { existsSync as existsSync7 } from "fs";
16872
17407
  var CONFIG_DIR3 = join6(homedir2(), ".vm0");
16873
17408
  var COOK_STATE_FILE = join6(CONFIG_DIR3, "cook.json");
16874
17409
  var STALE_THRESHOLD_MS = 48 * 60 * 60 * 1e3;
16875
17410
  async function loadCookStateFile() {
16876
- if (!existsSync6(COOK_STATE_FILE)) {
17411
+ if (!existsSync7(COOK_STATE_FILE)) {
16877
17412
  return { ppid: {} };
16878
17413
  }
16879
17414
  try {
@@ -16933,7 +17468,7 @@ async function saveCookState(state) {
16933
17468
  var CONFIG_FILE3 = "vm0.yaml";
16934
17469
  var ARTIFACT_DIR = "artifact";
16935
17470
  function printCommand(cmd) {
16936
- console.log(chalk16.dim(`> ${cmd}`));
17471
+ console.log(chalk21.dim(`> ${cmd}`));
16937
17472
  }
16938
17473
  function execVm0Command(args, options = {}) {
16939
17474
  return new Promise((resolve2, reject) => {
@@ -17034,7 +17569,7 @@ function extractRequiredVarNames(config2) {
17034
17569
  }
17035
17570
  function checkMissingVariables(varNames, envFilePath) {
17036
17571
  let dotenvValues = {};
17037
- if (existsSync7(envFilePath)) {
17572
+ if (existsSync8(envFilePath)) {
17038
17573
  const result = dotenvConfig2({ path: envFilePath, quiet: true });
17039
17574
  if (result.parsed) {
17040
17575
  dotenvValues = result.parsed;
@@ -17052,7 +17587,7 @@ function checkMissingVariables(varNames, envFilePath) {
17052
17587
  }
17053
17588
  async function generateEnvPlaceholders(missingVars, envFilePath) {
17054
17589
  const placeholders = missingVars.map((name) => `${name}=`).join("\n");
17055
- if (existsSync7(envFilePath)) {
17590
+ if (existsSync8(envFilePath)) {
17056
17591
  const existingContent = readFileSync(envFilePath, "utf8");
17057
17592
  const needsNewline = existingContent.length > 0 && !existingContent.endsWith("\n");
17058
17593
  const prefix = needsNewline ? "\n" : "";
@@ -17068,9 +17603,9 @@ async function autoPullArtifact(runOutput, artifactDir) {
17068
17603
  runOutput,
17069
17604
  ARTIFACT_DIR
17070
17605
  );
17071
- if (serverVersion && existsSync7(artifactDir)) {
17606
+ if (serverVersion && existsSync8(artifactDir)) {
17072
17607
  console.log();
17073
- console.log(chalk16.bold("Pulling updated artifact:"));
17608
+ console.log(chalk21.bold("Pulling updated artifact:"));
17074
17609
  printCommand(`cd ${ARTIFACT_DIR}`);
17075
17610
  printCommand(`vm0 artifact pull ${serverVersion}`);
17076
17611
  try {
@@ -17080,23 +17615,23 @@ async function autoPullArtifact(runOutput, artifactDir) {
17080
17615
  });
17081
17616
  printCommand("cd ..");
17082
17617
  } catch (error43) {
17083
- console.error(chalk16.red(`\u2717 Artifact pull failed`));
17618
+ console.error(chalk21.red(`\u2717 Artifact pull failed`));
17084
17619
  if (error43 instanceof Error) {
17085
- console.error(chalk16.dim(` ${error43.message}`));
17620
+ console.error(chalk21.dim(` ${error43.message}`));
17086
17621
  }
17087
17622
  }
17088
17623
  }
17089
17624
  }
17090
- var cookCmd = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml");
17625
+ var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
17091
17626
  cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17092
- const shouldExit = await checkAndUpgrade("4.31.1", prompt);
17627
+ const shouldExit = await checkAndUpgrade("4.33.0", prompt);
17093
17628
  if (shouldExit) {
17094
17629
  process.exit(0);
17095
17630
  }
17096
17631
  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}`));
17632
+ console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
17633
+ if (!existsSync8(CONFIG_FILE3)) {
17634
+ console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
17100
17635
  process.exit(1);
17101
17636
  }
17102
17637
  let config2;
@@ -17104,49 +17639,49 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17104
17639
  const content = await readFile7(CONFIG_FILE3, "utf8");
17105
17640
  config2 = parseYaml4(content);
17106
17641
  } catch (error43) {
17107
- console.error(chalk16.red("\u2717 Invalid YAML format"));
17642
+ console.error(chalk21.red("\u2717 Invalid YAML format"));
17108
17643
  if (error43 instanceof Error) {
17109
- console.error(chalk16.dim(` ${error43.message}`));
17644
+ console.error(chalk21.dim(` ${error43.message}`));
17110
17645
  }
17111
17646
  process.exit(1);
17112
17647
  }
17113
17648
  const validation = validateAgentCompose(config2);
17114
17649
  if (!validation.valid) {
17115
- console.error(chalk16.red(`\u2717 ${validation.error}`));
17650
+ console.error(chalk21.red(`\u2717 ${validation.error}`));
17116
17651
  process.exit(1);
17117
17652
  }
17118
17653
  const agentNames = Object.keys(config2.agents);
17119
17654
  const agentName = agentNames[0];
17120
17655
  const volumeCount = config2.volumes ? Object.keys(config2.volumes).length : 0;
17121
17656
  console.log(
17122
- chalk16.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
17657
+ chalk21.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
17123
17658
  );
17124
17659
  const requiredVarNames = extractRequiredVarNames(config2);
17125
17660
  if (requiredVarNames.length > 0) {
17126
- const envFilePath = path11.join(cwd, ".env");
17661
+ const envFilePath = path12.join(cwd, ".env");
17127
17662
  const missingVars = checkMissingVariables(requiredVarNames, envFilePath);
17128
17663
  if (missingVars.length > 0) {
17129
17664
  await generateEnvPlaceholders(missingVars, envFilePath);
17130
17665
  console.log();
17131
17666
  console.log(
17132
- chalk16.yellow(
17667
+ chalk21.yellow(
17133
17668
  `\u26A0 Missing environment variables. Please fill in values in .env file:`
17134
17669
  )
17135
17670
  );
17136
17671
  for (const varName of missingVars) {
17137
- console.log(chalk16.yellow(` ${varName}`));
17672
+ console.log(chalk21.yellow(` ${varName}`));
17138
17673
  }
17139
17674
  process.exit(1);
17140
17675
  }
17141
17676
  }
17142
17677
  if (config2.volumes && Object.keys(config2.volumes).length > 0) {
17143
17678
  console.log();
17144
- console.log(chalk16.bold("Processing volumes:"));
17679
+ console.log(chalk21.bold("Processing volumes:"));
17145
17680
  for (const volumeConfig of Object.values(config2.volumes)) {
17146
- const volumeDir = path11.join(cwd, volumeConfig.name);
17147
- if (!existsSync7(volumeDir)) {
17681
+ const volumeDir = path12.join(cwd, volumeConfig.name);
17682
+ if (!existsSync8(volumeDir)) {
17148
17683
  console.error(
17149
- chalk16.red(
17684
+ chalk21.red(
17150
17685
  `\u2717 Directory not found: ${volumeConfig.name}. Create the directory and add files first.`
17151
17686
  )
17152
17687
  );
@@ -17156,11 +17691,14 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17156
17691
  printCommand(`cd ${volumeConfig.name}`);
17157
17692
  const existingConfig = await readStorageConfig(volumeDir);
17158
17693
  if (!existingConfig) {
17159
- printCommand("vm0 volume init");
17160
- await execVm0Command(["volume", "init"], {
17161
- cwd: volumeDir,
17162
- silent: true
17163
- });
17694
+ printCommand(`vm0 volume init --name ${volumeConfig.name}`);
17695
+ await execVm0Command(
17696
+ ["volume", "init", "--name", volumeConfig.name],
17697
+ {
17698
+ cwd: volumeDir,
17699
+ silent: true
17700
+ }
17701
+ );
17164
17702
  }
17165
17703
  printCommand("vm0 volume push");
17166
17704
  await execVm0Command(["volume", "push"], {
@@ -17169,27 +17707,27 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17169
17707
  });
17170
17708
  printCommand("cd ..");
17171
17709
  } catch (error43) {
17172
- console.error(chalk16.red(`\u2717 Failed`));
17710
+ console.error(chalk21.red(`\u2717 Failed`));
17173
17711
  if (error43 instanceof Error) {
17174
- console.error(chalk16.dim(` ${error43.message}`));
17712
+ console.error(chalk21.dim(` ${error43.message}`));
17175
17713
  }
17176
17714
  process.exit(1);
17177
17715
  }
17178
17716
  }
17179
17717
  }
17180
17718
  console.log();
17181
- console.log(chalk16.bold("Processing artifact:"));
17182
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17719
+ console.log(chalk21.bold("Processing artifact:"));
17720
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17183
17721
  try {
17184
- if (!existsSync7(artifactDir)) {
17722
+ if (!existsSync8(artifactDir)) {
17185
17723
  printCommand(`mkdir ${ARTIFACT_DIR}`);
17186
17724
  await mkdir6(artifactDir, { recursive: true });
17187
17725
  }
17188
17726
  printCommand(`cd ${ARTIFACT_DIR}`);
17189
17727
  const existingConfig = await readStorageConfig(artifactDir);
17190
17728
  if (!existingConfig) {
17191
- printCommand("vm0 artifact init");
17192
- await execVm0Command(["artifact", "init"], {
17729
+ printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
17730
+ await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
17193
17731
  cwd: artifactDir,
17194
17732
  silent: true
17195
17733
  });
@@ -17201,29 +17739,29 @@ cookCmd.argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
17201
17739
  });
17202
17740
  printCommand("cd ..");
17203
17741
  } catch (error43) {
17204
- console.error(chalk16.red(`\u2717 Failed`));
17742
+ console.error(chalk21.red(`\u2717 Failed`));
17205
17743
  if (error43 instanceof Error) {
17206
- console.error(chalk16.dim(` ${error43.message}`));
17744
+ console.error(chalk21.dim(` ${error43.message}`));
17207
17745
  }
17208
17746
  process.exit(1);
17209
17747
  }
17210
17748
  console.log();
17211
- console.log(chalk16.bold("Composing agent:"));
17749
+ console.log(chalk21.bold("Composing agent:"));
17212
17750
  printCommand(`vm0 compose ${CONFIG_FILE3}`);
17213
17751
  try {
17214
17752
  await execVm0Command(["compose", CONFIG_FILE3], {
17215
17753
  cwd
17216
17754
  });
17217
17755
  } catch (error43) {
17218
- console.error(chalk16.red(`\u2717 Compose failed`));
17756
+ console.error(chalk21.red(`\u2717 Compose failed`));
17219
17757
  if (error43 instanceof Error) {
17220
- console.error(chalk16.dim(` ${error43.message}`));
17758
+ console.error(chalk21.dim(` ${error43.message}`));
17221
17759
  }
17222
17760
  process.exit(1);
17223
17761
  }
17224
17762
  if (prompt) {
17225
17763
  console.log();
17226
- console.log(chalk16.bold("Running agent:"));
17764
+ console.log(chalk21.bold("Running agent:"));
17227
17765
  printCommand(
17228
17766
  `vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
17229
17767
  );
@@ -17265,8 +17803,8 @@ cookCmd.command("logs").description("View logs from the last cook run").option("
17265
17803
  async (options) => {
17266
17804
  const state = await loadCookState();
17267
17805
  if (!state.lastRunId) {
17268
- console.error(chalk16.red("\u2717 No previous run found"));
17269
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17806
+ console.error(chalk21.red("\u2717 No previous run found"));
17807
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17270
17808
  process.exit(1);
17271
17809
  }
17272
17810
  const args = ["logs", state.lastRunId];
@@ -17308,12 +17846,12 @@ cookCmd.command("continue").description(
17308
17846
  ).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
17309
17847
  const state = await loadCookState();
17310
17848
  if (!state.lastSessionId) {
17311
- console.error(chalk16.red("\u2717 No previous session found"));
17312
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17849
+ console.error(chalk21.red("\u2717 No previous session found"));
17850
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17313
17851
  process.exit(1);
17314
17852
  }
17315
17853
  const cwd = process.cwd();
17316
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17854
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17317
17855
  printCommand(`vm0 run continue ${state.lastSessionId} "${prompt}"`);
17318
17856
  console.log();
17319
17857
  let runOutput;
@@ -17340,12 +17878,12 @@ cookCmd.command("resume").description(
17340
17878
  ).argument("<prompt>", "Prompt for the resumed agent").action(async (prompt) => {
17341
17879
  const state = await loadCookState();
17342
17880
  if (!state.lastCheckpointId) {
17343
- console.error(chalk16.red("\u2717 No previous checkpoint found"));
17344
- console.error(chalk16.dim(" Run 'vm0 cook <prompt>' first"));
17881
+ console.error(chalk21.red("\u2717 No previous checkpoint found"));
17882
+ console.error(chalk21.dim(" Run 'vm0 cook <prompt>' first"));
17345
17883
  process.exit(1);
17346
17884
  }
17347
17885
  const cwd = process.cwd();
17348
- const artifactDir = path11.join(cwd, ARTIFACT_DIR);
17886
+ const artifactDir = path12.join(cwd, ARTIFACT_DIR);
17349
17887
  printCommand(`vm0 run resume ${state.lastCheckpointId} "${prompt}"`);
17350
17888
  console.log();
17351
17889
  let runOutput;
@@ -17370,13 +17908,13 @@ cookCmd.command("resume").description(
17370
17908
  var cookCommand = cookCmd;
17371
17909
 
17372
17910
  // src/commands/image/index.ts
17373
- import { Command as Command18 } from "commander";
17911
+ import { Command as Command22 } from "commander";
17374
17912
 
17375
17913
  // src/commands/image/build.ts
17376
- import { Command as Command14 } from "commander";
17377
- import chalk17 from "chalk";
17914
+ import { Command as Command18 } from "commander";
17915
+ import chalk22 from "chalk";
17378
17916
  import { readFile as readFile8 } from "fs/promises";
17379
- import { existsSync as existsSync8 } from "fs";
17917
+ import { existsSync as existsSync9 } from "fs";
17380
17918
 
17381
17919
  // src/lib/dockerfile-validator.ts
17382
17920
  var ALLOWED_INSTRUCTIONS = /* @__PURE__ */ new Set(["FROM", "RUN"]);
@@ -17410,17 +17948,17 @@ function validateDockerfile(content) {
17410
17948
 
17411
17949
  // src/commands/image/build.ts
17412
17950
  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(
17951
+ 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
17952
  async (options) => {
17415
17953
  const { file: file2, name, deleteExisting } = options;
17416
- if (!existsSync8(file2)) {
17417
- console.error(chalk17.red(`\u2717 Dockerfile not found: ${file2}`));
17954
+ if (!existsSync9(file2)) {
17955
+ console.error(chalk22.red(`\u2717 Dockerfile not found: ${file2}`));
17418
17956
  process.exit(1);
17419
17957
  }
17420
17958
  const nameRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/;
17421
17959
  if (!nameRegex.test(name)) {
17422
17960
  console.error(
17423
- chalk17.red(
17961
+ chalk22.red(
17424
17962
  "\u2717 Invalid name format. Must be 3-64 characters, letters, numbers, and hyphens only."
17425
17963
  )
17426
17964
  );
@@ -17428,7 +17966,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17428
17966
  }
17429
17967
  if (name.startsWith("vm0-")) {
17430
17968
  console.error(
17431
- chalk17.red(
17969
+ chalk22.red(
17432
17970
  '\u2717 Invalid name. Cannot start with "vm0-" (reserved prefix).'
17433
17971
  )
17434
17972
  );
@@ -17439,24 +17977,24 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17439
17977
  const dockerfile = await readFile8(file2, "utf8");
17440
17978
  const validation = validateDockerfile(dockerfile);
17441
17979
  if (!validation.valid) {
17442
- console.error(chalk17.red("\u2717 Dockerfile validation failed\n"));
17980
+ console.error(chalk22.red("\u2717 Dockerfile validation failed\n"));
17443
17981
  for (const error43 of validation.errors) {
17444
- console.error(chalk17.red(` ${error43}`));
17982
+ console.error(chalk22.red(` ${error43}`));
17445
17983
  }
17446
17984
  console.error();
17447
17985
  console.error(
17448
- chalk17.yellow(
17986
+ chalk22.yellow(
17449
17987
  " vm0 image build only supports FROM and RUN instructions."
17450
17988
  )
17451
17989
  );
17452
17990
  console.error(
17453
- chalk17.yellow(
17991
+ chalk22.yellow(
17454
17992
  " The purpose is to pre-install environment dependencies."
17455
17993
  )
17456
17994
  );
17457
17995
  process.exit(1);
17458
17996
  }
17459
- console.log(chalk17.bold(`Building image: ${scope.slug}/${name}`));
17997
+ console.log(chalk22.bold(`Building image: ${scope.slug}/${name}`));
17460
17998
  console.log();
17461
17999
  const buildInfo = await apiClient.createImage({
17462
18000
  dockerfile,
@@ -17464,7 +18002,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17464
18002
  deleteExisting
17465
18003
  });
17466
18004
  const { imageId, buildId, versionId } = buildInfo;
17467
- console.log(chalk17.dim(` Build ID: ${buildId}`));
18005
+ console.log(chalk22.dim(` Build ID: ${buildId}`));
17468
18006
  console.log();
17469
18007
  let logsOffset = 0;
17470
18008
  let status = "building";
@@ -17480,7 +18018,7 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17480
18018
  }
17481
18019
  const statusData = await statusResponse.json();
17482
18020
  for (const log of statusData.logs) {
17483
- console.log(chalk17.dim(` ${log}`));
18021
+ console.log(chalk22.dim(` ${log}`));
17484
18022
  }
17485
18023
  logsOffset = statusData.logsOffset;
17486
18024
  status = statusData.status;
@@ -17492,23 +18030,23 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17492
18030
  if (status === "ready") {
17493
18031
  const shortVersion = formatVersionIdForDisplay(versionId);
17494
18032
  console.log(
17495
- chalk17.green(`\u2713 Image built: ${scope.slug}/${name}:${shortVersion}`)
18033
+ chalk22.green(`\u2713 Image built: ${scope.slug}/${name}:${shortVersion}`)
17496
18034
  );
17497
18035
  } else {
17498
- console.error(chalk17.red(`\u2717 Build failed`));
18036
+ console.error(chalk22.red(`\u2717 Build failed`));
17499
18037
  process.exit(1);
17500
18038
  }
17501
18039
  } catch (error43) {
17502
18040
  if (error43 instanceof Error) {
17503
18041
  if (error43.message.includes("Not authenticated")) {
17504
18042
  console.error(
17505
- chalk17.red("\u2717 Not authenticated. Run: vm0 auth login")
18043
+ chalk22.red("\u2717 Not authenticated. Run: vm0 auth login")
17506
18044
  );
17507
18045
  } else {
17508
- console.error(chalk17.red(`\u2717 ${error43.message}`));
18046
+ console.error(chalk22.red(`\u2717 ${error43.message}`));
17509
18047
  }
17510
18048
  } else {
17511
- console.error(chalk17.red("\u2717 An unexpected error occurred"));
18049
+ console.error(chalk22.red("\u2717 An unexpected error occurred"));
17512
18050
  }
17513
18051
  process.exit(1);
17514
18052
  }
@@ -17516,9 +18054,9 @@ var buildCommand = new Command14().name("build").description("Build a custom ima
17516
18054
  );
17517
18055
 
17518
18056
  // 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 () => {
18057
+ import { Command as Command19 } from "commander";
18058
+ import chalk23 from "chalk";
18059
+ var listCommand3 = new Command19().name("list").alias("ls").description("List your custom images").action(async () => {
17522
18060
  try {
17523
18061
  const response = await apiClient.get("/api/images");
17524
18062
  if (!response.ok) {
@@ -17530,15 +18068,15 @@ var listCommand = new Command15().name("list").alias("ls").description("List you
17530
18068
  const data = await response.json();
17531
18069
  const { images } = data;
17532
18070
  if (images.length === 0) {
17533
- console.log(chalk18.dim("No images found."));
18071
+ console.log(chalk23.dim("No images found."));
17534
18072
  console.log();
17535
18073
  console.log("Build your first image:");
17536
18074
  console.log(
17537
- chalk18.cyan(" vm0 image build --file Dockerfile --name my-image")
18075
+ chalk23.cyan(" vm0 image build --file Dockerfile --name my-image")
17538
18076
  );
17539
18077
  return;
17540
18078
  }
17541
- console.log(chalk18.bold("Your images:"));
18079
+ console.log(chalk23.bold("Your images:"));
17542
18080
  console.log();
17543
18081
  const imagesByAlias = /* @__PURE__ */ new Map();
17544
18082
  for (const image of images) {
@@ -17552,50 +18090,49 @@ var listCommand = new Command15().name("list").alias("ls").description("List you
17552
18090
  latestVersions.set(alias, latestReady?.versionId || null);
17553
18091
  }
17554
18092
  console.log(
17555
- chalk18.dim(
18093
+ chalk23.dim(
17556
18094
  `${"NAME".padEnd(40)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(20)}`
17557
18095
  )
17558
18096
  );
17559
- console.log(chalk18.dim("-".repeat(72)));
18097
+ console.log(chalk23.dim("-".repeat(72)));
17560
18098
  for (const image of images) {
17561
- const statusColor = image.status === "ready" ? chalk18.green : image.status === "building" ? chalk18.yellow : chalk18.red;
18099
+ const statusColor = image.status === "ready" ? chalk23.green : image.status === "building" ? chalk23.yellow : chalk23.red;
17562
18100
  const createdAt = new Date(image.createdAt).toLocaleString();
17563
18101
  let displayName = image.alias;
17564
18102
  if (image.versionId) {
17565
18103
  const shortVersion = formatVersionIdForDisplay(image.versionId);
17566
18104
  displayName = `${image.alias}:${shortVersion}`;
17567
18105
  if (image.status === "ready" && latestVersions.get(image.alias) === image.versionId) {
17568
- displayName = `${displayName} ${chalk18.cyan("latest")}`;
18106
+ displayName = `${displayName} ${chalk23.cyan("latest")}`;
17569
18107
  }
17570
18108
  }
17571
18109
  console.log(
17572
18110
  `${displayName.padEnd(40)} ${statusColor(image.status.padEnd(12))} ${createdAt.padEnd(20)}`
17573
18111
  );
17574
18112
  if (image.status === "error" && image.errorMessage) {
17575
- console.log(chalk18.red(` Error: ${image.errorMessage}`));
18113
+ console.log(chalk23.red(` Error: ${image.errorMessage}`));
17576
18114
  }
17577
18115
  }
17578
18116
  console.log();
17579
- console.log(chalk18.dim(`Total: ${images.length} version(s)`));
18117
+ console.log(chalk23.dim(`Total: ${images.length} version(s)`));
17580
18118
  } catch (error43) {
17581
18119
  if (error43 instanceof Error) {
17582
18120
  if (error43.message.includes("Not authenticated")) {
17583
- console.error(chalk18.red("Not authenticated. Run: vm0 auth login"));
18121
+ console.error(chalk23.red("Not authenticated. Run: vm0 auth login"));
17584
18122
  } else {
17585
- console.error(chalk18.red(`Error: ${error43.message}`));
18123
+ console.error(chalk23.red(`Error: ${error43.message}`));
17586
18124
  }
17587
18125
  } else {
17588
- console.error(chalk18.red("An unexpected error occurred"));
18126
+ console.error(chalk23.red("An unexpected error occurred"));
17589
18127
  }
17590
18128
  process.exit(1);
17591
18129
  }
17592
18130
  });
17593
18131
 
17594
18132
  // 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(
18133
+ import { Command as Command20 } from "commander";
18134
+ import chalk24 from "chalk";
18135
+ 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
18136
  async (nameArg, options) => {
17600
18137
  try {
17601
18138
  const colonIndex = nameArg.lastIndexOf(":");
@@ -17616,12 +18153,12 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17616
18153
  (img) => img.alias === name && img.versionId && img.versionId.startsWith(versionId.toLowerCase())
17617
18154
  );
17618
18155
  if (matchingVersions.length === 0) {
17619
- console.error(chalk19.red(`Image version not found: ${nameArg}`));
18156
+ console.error(chalk24.red(`Image version not found: ${nameArg}`));
17620
18157
  process.exit(1);
17621
18158
  }
17622
18159
  if (matchingVersions.length > 1) {
17623
18160
  console.error(
17624
- chalk19.red(
18161
+ chalk24.red(
17625
18162
  `Ambiguous version prefix "${versionId}". Please use more characters.`
17626
18163
  )
17627
18164
  );
@@ -17631,7 +18168,7 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17631
18168
  } else if (options.all) {
17632
18169
  imagesToDelete = data.images.filter((img) => img.alias === name);
17633
18170
  if (imagesToDelete.length === 0) {
17634
- console.error(chalk19.red(`Image not found: ${name}`));
18171
+ console.error(chalk24.red(`Image not found: ${name}`));
17635
18172
  process.exit(1);
17636
18173
  }
17637
18174
  } else {
@@ -17639,7 +18176,7 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17639
18176
  (img) => img.alias === name
17640
18177
  );
17641
18178
  if (matchingImages.length === 0) {
17642
- console.error(chalk19.red(`Image not found: ${name}`));
18179
+ console.error(chalk24.red(`Image not found: ${name}`));
17643
18180
  process.exit(1);
17644
18181
  }
17645
18182
  const latestReady = matchingImages.find(
@@ -17655,18 +18192,9 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17655
18192
  const firstVersionDisplay = firstImage.versionId ? `:${formatVersionIdForDisplay(firstImage.versionId)}` : "";
17656
18193
  const confirmMsg = imagesToDelete.length === 1 ? `Delete image "${firstImage.alias}${firstVersionDisplay}"?` : `Delete ${imagesToDelete.length} versions of "${name}"?`;
17657
18194
  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."));
18195
+ const confirmed = await promptConfirm(confirmMsg, false);
18196
+ if (!confirmed) {
18197
+ console.log(chalk24.dim("Cancelled."));
17670
18198
  return;
17671
18199
  }
17672
18200
  }
@@ -17681,17 +18209,17 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17681
18209
  );
17682
18210
  }
17683
18211
  const displayName = image.versionId ? `${image.alias}:${formatVersionIdForDisplay(image.versionId)}` : image.alias;
17684
- console.log(chalk19.green(`Deleted image: ${displayName}`));
18212
+ console.log(chalk24.green(`Deleted image: ${displayName}`));
17685
18213
  }
17686
18214
  } catch (error43) {
17687
18215
  if (error43 instanceof Error) {
17688
18216
  if (error43.message.includes("Not authenticated")) {
17689
- console.error(chalk19.red("Not authenticated. Run: vm0 auth login"));
18217
+ console.error(chalk24.red("Not authenticated. Run: vm0 auth login"));
17690
18218
  } else {
17691
- console.error(chalk19.red(`Error: ${error43.message}`));
18219
+ console.error(chalk24.red(`Error: ${error43.message}`));
17692
18220
  }
17693
18221
  } else {
17694
- console.error(chalk19.red("An unexpected error occurred"));
18222
+ console.error(chalk24.red("An unexpected error occurred"));
17695
18223
  }
17696
18224
  process.exit(1);
17697
18225
  }
@@ -17699,9 +18227,9 @@ var deleteCommand = new Command16().name("delete").alias("rm").description("Dele
17699
18227
  );
17700
18228
 
17701
18229
  // 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) => {
18230
+ import { Command as Command21 } from "commander";
18231
+ import chalk25 from "chalk";
18232
+ var versionsCommand = new Command21().name("versions").description("List all versions of an image").argument("<name>", "Name of the image").action(async (name) => {
17705
18233
  try {
17706
18234
  const response = await apiClient.get("/api/images");
17707
18235
  if (!response.ok) {
@@ -17713,42 +18241,42 @@ var versionsCommand = new Command17().name("versions").description("List all ver
17713
18241
  const data = await response.json();
17714
18242
  const versions = data.images.filter((img) => img.alias === name);
17715
18243
  if (versions.length === 0) {
17716
- console.error(chalk20.red(`Image not found: ${name}`));
18244
+ console.error(chalk25.red(`Image not found: ${name}`));
17717
18245
  process.exit(1);
17718
18246
  }
17719
18247
  const latestReady = versions.find((v) => v.status === "ready");
17720
18248
  const latestVersionId = latestReady?.versionId || null;
17721
- console.log(chalk20.bold(`Versions of ${name}:`));
18249
+ console.log(chalk25.bold(`Versions of ${name}:`));
17722
18250
  console.log();
17723
18251
  console.log(
17724
- chalk20.dim(
18252
+ chalk25.dim(
17725
18253
  `${"VERSION".padEnd(20)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(24)}`
17726
18254
  )
17727
18255
  );
17728
- console.log(chalk20.dim("-".repeat(56)));
18256
+ console.log(chalk25.dim("-".repeat(56)));
17729
18257
  for (const version2 of versions) {
17730
- const statusColor = version2.status === "ready" ? chalk20.green : version2.status === "building" ? chalk20.yellow : chalk20.red;
18258
+ const statusColor = version2.status === "ready" ? chalk25.green : version2.status === "building" ? chalk25.yellow : chalk25.red;
17731
18259
  const createdAt = new Date(version2.createdAt).toLocaleString();
17732
18260
  let versionDisplay = version2.versionId ? formatVersionIdForDisplay(version2.versionId) : "(legacy)";
17733
18261
  if (version2.status === "ready" && version2.versionId === latestVersionId) {
17734
- versionDisplay = `${versionDisplay} ${chalk20.cyan("latest")}`;
18262
+ versionDisplay = `${versionDisplay} ${chalk25.cyan("latest")}`;
17735
18263
  }
17736
18264
  console.log(
17737
18265
  `${versionDisplay.padEnd(20)} ${statusColor(version2.status.padEnd(12))} ${createdAt.padEnd(24)}`
17738
18266
  );
17739
18267
  if (version2.status === "error" && version2.errorMessage) {
17740
- console.log(chalk20.red(` Error: ${version2.errorMessage}`));
18268
+ console.log(chalk25.red(` Error: ${version2.errorMessage}`));
17741
18269
  }
17742
18270
  }
17743
18271
  console.log();
17744
- console.log(chalk20.dim(`Total: ${versions.length} version(s)`));
18272
+ console.log(chalk25.dim(`Total: ${versions.length} version(s)`));
17745
18273
  console.log();
17746
- console.log(chalk20.dim("Usage:"));
17747
- console.log(chalk20.dim(` image: "${name}" # uses latest`));
18274
+ console.log(chalk25.dim("Usage:"));
18275
+ console.log(chalk25.dim(` image: "${name}" # uses latest`));
17748
18276
  if (latestVersionId) {
17749
18277
  const shortVersion = formatVersionIdForDisplay(latestVersionId);
17750
18278
  console.log(
17751
- chalk20.dim(
18279
+ chalk25.dim(
17752
18280
  ` image: "${name}:${shortVersion}" # pin to specific version`
17753
18281
  )
17754
18282
  );
@@ -17756,23 +18284,23 @@ var versionsCommand = new Command17().name("versions").description("List all ver
17756
18284
  } catch (error43) {
17757
18285
  if (error43 instanceof Error) {
17758
18286
  if (error43.message.includes("Not authenticated")) {
17759
- console.error(chalk20.red("Not authenticated. Run: vm0 auth login"));
18287
+ console.error(chalk25.red("Not authenticated. Run: vm0 auth login"));
17760
18288
  } else {
17761
- console.error(chalk20.red(`Error: ${error43.message}`));
18289
+ console.error(chalk25.red(`Error: ${error43.message}`));
17762
18290
  }
17763
18291
  } else {
17764
- console.error(chalk20.red("An unexpected error occurred"));
18292
+ console.error(chalk25.red("An unexpected error occurred"));
17765
18293
  }
17766
18294
  process.exit(1);
17767
18295
  }
17768
18296
  });
17769
18297
 
17770
18298
  // src/commands/image/index.ts
17771
- var imageCommand = new Command18().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand).addCommand(deleteCommand).addCommand(versionsCommand);
18299
+ var imageCommand = new Command22().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand3).addCommand(deleteCommand).addCommand(versionsCommand);
17772
18300
 
17773
18301
  // src/commands/logs/index.ts
17774
- import { Command as Command19 } from "commander";
17775
- import chalk21 from "chalk";
18302
+ import { Command as Command23 } from "commander";
18303
+ import chalk26 from "chalk";
17776
18304
 
17777
18305
  // src/lib/time-parser.ts
17778
18306
  function parseTime(timeStr) {
@@ -17819,7 +18347,7 @@ function parseRelativeTime(value, unit) {
17819
18347
  }
17820
18348
 
17821
18349
  // src/commands/logs/index.ts
17822
- function formatBytes7(bytes) {
18350
+ function formatBytes8(bytes) {
17823
18351
  if (bytes === 0) return "0 B";
17824
18352
  const k = 1024;
17825
18353
  const sizes = ["B", "KB", "MB", "GB"];
@@ -17829,28 +18357,28 @@ function formatBytes7(bytes) {
17829
18357
  function formatMetric(metric) {
17830
18358
  const memPercent = (metric.mem_used / metric.mem_total * 100).toFixed(1);
17831
18359
  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}%)`;
18360
+ 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
18361
  }
17834
18362
  function formatNetworkLog(entry) {
17835
18363
  let statusColor;
17836
18364
  if (entry.status >= 200 && entry.status < 300) {
17837
- statusColor = chalk21.green;
18365
+ statusColor = chalk26.green;
17838
18366
  } else if (entry.status >= 300 && entry.status < 400) {
17839
- statusColor = chalk21.yellow;
18367
+ statusColor = chalk26.yellow;
17840
18368
  } else if (entry.status >= 400) {
17841
- statusColor = chalk21.red;
18369
+ statusColor = chalk26.red;
17842
18370
  } else {
17843
- statusColor = chalk21.gray;
18371
+ statusColor = chalk26.gray;
17844
18372
  }
17845
18373
  let latencyColor;
17846
18374
  if (entry.latency_ms < 500) {
17847
- latencyColor = chalk21.green;
18375
+ latencyColor = chalk26.green;
17848
18376
  } else if (entry.latency_ms < 2e3) {
17849
- latencyColor = chalk21.yellow;
18377
+ latencyColor = chalk26.yellow;
17850
18378
  } else {
17851
- latencyColor = chalk21.red;
18379
+ latencyColor = chalk26.red;
17852
18380
  }
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)}`;
18381
+ 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
18382
  }
17855
18383
  function renderAgentEvent(event, provider) {
17856
18384
  const eventData = event.eventData;
@@ -17873,7 +18401,7 @@ function getLogType(options) {
17873
18401
  ].filter(Boolean).length;
17874
18402
  if (selected > 1) {
17875
18403
  console.error(
17876
- chalk21.red(
18404
+ chalk26.red(
17877
18405
  "Options --agent, --system, --metrics, and --network are mutually exclusive"
17878
18406
  )
17879
18407
  );
@@ -17884,7 +18412,7 @@ function getLogType(options) {
17884
18412
  if (options.network) return "network";
17885
18413
  return "agent";
17886
18414
  }
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(
18415
+ 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
18416
  "--since <time>",
17889
18417
  "Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z, 1705312200)"
17890
18418
  ).option("--tail <n>", "Show last N entries (default: 5, max: 100)").option("--head <n>", "Show first N entries (max: 100)").action(
@@ -17893,7 +18421,7 @@ var logsCommand = new Command19().name("logs").description("View logs for an age
17893
18421
  const logType = getLogType(options);
17894
18422
  if (options.tail !== void 0 && options.head !== void 0) {
17895
18423
  console.error(
17896
- chalk21.red("Options --tail and --head are mutually exclusive")
18424
+ chalk26.red("Options --tail and --head are mutually exclusive")
17897
18425
  );
17898
18426
  process.exit(1);
17899
18427
  }
@@ -17930,7 +18458,7 @@ var logsCommand = new Command19().name("logs").description("View logs for an age
17930
18458
  async function showAgentEvents(runId, options) {
17931
18459
  const response = await apiClient.getAgentEvents(runId, options);
17932
18460
  if (response.events.length === 0) {
17933
- console.log(chalk21.yellow("No agent events found for this run."));
18461
+ console.log(chalk26.yellow("No agent events found for this run."));
17934
18462
  return;
17935
18463
  }
17936
18464
  const events = options.order === "desc" ? [...response.events].reverse() : response.events;
@@ -17940,7 +18468,7 @@ async function showAgentEvents(runId, options) {
17940
18468
  if (response.hasMore) {
17941
18469
  console.log();
17942
18470
  console.log(
17943
- chalk21.dim(
18471
+ chalk26.dim(
17944
18472
  `Showing ${response.events.length} events. Use --tail to see more.`
17945
18473
  )
17946
18474
  );
@@ -17949,21 +18477,21 @@ async function showAgentEvents(runId, options) {
17949
18477
  async function showSystemLog(runId, options) {
17950
18478
  const response = await apiClient.getSystemLog(runId, options);
17951
18479
  if (!response.systemLog) {
17952
- console.log(chalk21.yellow("No system log found for this run."));
18480
+ console.log(chalk26.yellow("No system log found for this run."));
17953
18481
  return;
17954
18482
  }
17955
18483
  console.log(response.systemLog);
17956
18484
  if (response.hasMore) {
17957
18485
  console.log();
17958
18486
  console.log(
17959
- chalk21.dim("More log entries available. Use --tail to see more.")
18487
+ chalk26.dim("More log entries available. Use --tail to see more.")
17960
18488
  );
17961
18489
  }
17962
18490
  }
17963
18491
  async function showMetrics(runId, options) {
17964
18492
  const response = await apiClient.getMetrics(runId, options);
17965
18493
  if (response.metrics.length === 0) {
17966
- console.log(chalk21.yellow("No metrics found for this run."));
18494
+ console.log(chalk26.yellow("No metrics found for this run."));
17967
18495
  return;
17968
18496
  }
17969
18497
  const metrics = options.order === "desc" ? [...response.metrics].reverse() : response.metrics;
@@ -17973,7 +18501,7 @@ async function showMetrics(runId, options) {
17973
18501
  if (response.hasMore) {
17974
18502
  console.log();
17975
18503
  console.log(
17976
- chalk21.dim(
18504
+ chalk26.dim(
17977
18505
  `Showing ${response.metrics.length} metrics. Use --tail to see more.`
17978
18506
  )
17979
18507
  );
@@ -17983,7 +18511,7 @@ async function showNetworkLogs(runId, options) {
17983
18511
  const response = await apiClient.getNetworkLogs(runId, options);
17984
18512
  if (response.networkLogs.length === 0) {
17985
18513
  console.log(
17986
- chalk21.yellow(
18514
+ chalk26.yellow(
17987
18515
  "No network logs found for this run. Network logs are only captured when beta_network_security is enabled."
17988
18516
  )
17989
18517
  );
@@ -17996,7 +18524,7 @@ async function showNetworkLogs(runId, options) {
17996
18524
  if (response.hasMore) {
17997
18525
  console.log();
17998
18526
  console.log(
17999
- chalk21.dim(
18527
+ chalk26.dim(
18000
18528
  `Showing ${response.networkLogs.length} network logs. Use --tail to see more.`
18001
18529
  )
18002
18530
  );
@@ -18005,31 +18533,31 @@ async function showNetworkLogs(runId, options) {
18005
18533
  function handleError(error43, runId) {
18006
18534
  if (error43 instanceof Error) {
18007
18535
  if (error43.message.includes("Not authenticated")) {
18008
- console.error(chalk21.red("Not authenticated. Run: vm0 auth login"));
18536
+ console.error(chalk26.red("Not authenticated. Run: vm0 auth login"));
18009
18537
  } else if (error43.message.includes("not found")) {
18010
- console.error(chalk21.red(`Run not found: ${runId}`));
18538
+ console.error(chalk26.red(`Run not found: ${runId}`));
18011
18539
  } else if (error43.message.includes("Invalid time format")) {
18012
- console.error(chalk21.red(error43.message));
18540
+ console.error(chalk26.red(error43.message));
18013
18541
  } else {
18014
- console.error(chalk21.red("Failed to fetch logs"));
18015
- console.error(chalk21.dim(` ${error43.message}`));
18542
+ console.error(chalk26.red("Failed to fetch logs"));
18543
+ console.error(chalk26.dim(` ${error43.message}`));
18016
18544
  }
18017
18545
  } else {
18018
- console.error(chalk21.red("An unexpected error occurred"));
18546
+ console.error(chalk26.red("An unexpected error occurred"));
18019
18547
  }
18020
18548
  }
18021
18549
 
18022
18550
  // src/commands/scope/index.ts
18023
- import { Command as Command22 } from "commander";
18551
+ import { Command as Command26 } from "commander";
18024
18552
 
18025
18553
  // 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 () => {
18554
+ import { Command as Command24 } from "commander";
18555
+ import chalk27 from "chalk";
18556
+ var statusCommand3 = new Command24().name("status").description("View current scope status").action(async () => {
18029
18557
  try {
18030
18558
  const scope = await apiClient.getScope();
18031
- console.log(chalk22.bold("Scope Information:"));
18032
- console.log(` Slug: ${chalk22.green(scope.slug)}`);
18559
+ console.log(chalk27.bold("Scope Information:"));
18560
+ console.log(` Slug: ${chalk27.green(scope.slug)}`);
18033
18561
  console.log(` Type: ${scope.type}`);
18034
18562
  if (scope.displayName) {
18035
18563
  console.log(` Display Name: ${scope.displayName}`);
@@ -18040,29 +18568,29 @@ var statusCommand3 = new Command20().name("status").description("View current sc
18040
18568
  } catch (error43) {
18041
18569
  if (error43 instanceof Error) {
18042
18570
  if (error43.message.includes("Not authenticated")) {
18043
- console.error(chalk22.red("\u2717 Not authenticated. Run: vm0 auth login"));
18571
+ console.error(chalk27.red("\u2717 Not authenticated. Run: vm0 auth login"));
18044
18572
  } else if (error43.message.includes("No scope configured")) {
18045
- console.log(chalk22.yellow("No scope configured."));
18573
+ console.log(chalk27.yellow("No scope configured."));
18046
18574
  console.log();
18047
18575
  console.log("Set your scope with:");
18048
- console.log(chalk22.cyan(" vm0 scope set <slug>"));
18576
+ console.log(chalk27.cyan(" vm0 scope set <slug>"));
18049
18577
  console.log();
18050
18578
  console.log("Example:");
18051
- console.log(chalk22.dim(" vm0 scope set myusername"));
18579
+ console.log(chalk27.dim(" vm0 scope set myusername"));
18052
18580
  } else {
18053
- console.error(chalk22.red(`\u2717 ${error43.message}`));
18581
+ console.error(chalk27.red(`\u2717 ${error43.message}`));
18054
18582
  }
18055
18583
  } else {
18056
- console.error(chalk22.red("\u2717 An unexpected error occurred"));
18584
+ console.error(chalk27.red("\u2717 An unexpected error occurred"));
18057
18585
  }
18058
18586
  process.exit(1);
18059
18587
  }
18060
18588
  });
18061
18589
 
18062
18590
  // 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(
18591
+ import { Command as Command25 } from "commander";
18592
+ import chalk28 from "chalk";
18593
+ 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
18594
  async (slug, options) => {
18067
18595
  try {
18068
18596
  let existingScope;
@@ -18074,56 +18602,56 @@ var setCommand = new Command21().name("set").description("Set your scope slug").
18074
18602
  if (existingScope) {
18075
18603
  if (!options.force) {
18076
18604
  console.error(
18077
- chalk23.yellow(`You already have a scope: ${existingScope.slug}`)
18605
+ chalk28.yellow(`You already have a scope: ${existingScope.slug}`)
18078
18606
  );
18079
18607
  console.error();
18080
18608
  console.error("To change your scope, use --force:");
18081
- console.error(chalk23.cyan(` vm0 scope set ${slug} --force`));
18609
+ console.error(chalk28.cyan(` vm0 scope set ${slug} --force`));
18082
18610
  console.error();
18083
18611
  console.error(
18084
- chalk23.yellow(
18612
+ chalk28.yellow(
18085
18613
  "Warning: Changing your scope may break existing image references."
18086
18614
  )
18087
18615
  );
18088
18616
  process.exit(1);
18089
18617
  }
18090
18618
  scope = await apiClient.updateScope({ slug, force: true });
18091
- console.log(chalk23.green(`\u2713 Scope updated to ${scope.slug}`));
18619
+ console.log(chalk28.green(`\u2713 Scope updated to ${scope.slug}`));
18092
18620
  } else {
18093
18621
  scope = await apiClient.createScope({
18094
18622
  slug,
18095
18623
  displayName: options.displayName
18096
18624
  });
18097
- console.log(chalk23.green(`\u2713 Scope created: ${scope.slug}`));
18625
+ console.log(chalk28.green(`\u2713 Scope created: ${scope.slug}`));
18098
18626
  }
18099
18627
  console.log();
18100
18628
  console.log("Your images will now be namespaced as:");
18101
- console.log(chalk23.cyan(` ${scope.slug}/<image-name>`));
18629
+ console.log(chalk28.cyan(` ${scope.slug}/<image-name>`));
18102
18630
  } catch (error43) {
18103
18631
  if (error43 instanceof Error) {
18104
18632
  if (error43.message.includes("Not authenticated")) {
18105
18633
  console.error(
18106
- chalk23.red("\u2717 Not authenticated. Run: vm0 auth login")
18634
+ chalk28.red("\u2717 Not authenticated. Run: vm0 auth login")
18107
18635
  );
18108
18636
  } else if (error43.message.includes("already exists")) {
18109
18637
  console.error(
18110
- chalk23.red(
18638
+ chalk28.red(
18111
18639
  `\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
18112
18640
  )
18113
18641
  );
18114
18642
  } else if (error43.message.includes("reserved")) {
18115
- console.error(chalk23.red(`\u2717 ${error43.message}`));
18643
+ console.error(chalk28.red(`\u2717 ${error43.message}`));
18116
18644
  } else if (error43.message.includes("vm0")) {
18117
18645
  console.error(
18118
- chalk23.red(
18646
+ chalk28.red(
18119
18647
  "\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
18120
18648
  )
18121
18649
  );
18122
18650
  } else {
18123
- console.error(chalk23.red(`\u2717 ${error43.message}`));
18651
+ console.error(chalk28.red(`\u2717 ${error43.message}`));
18124
18652
  }
18125
18653
  } else {
18126
- console.error(chalk23.red("\u2717 An unexpected error occurred"));
18654
+ console.error(chalk28.red("\u2717 An unexpected error occurred"));
18127
18655
  }
18128
18656
  process.exit(1);
18129
18657
  }
@@ -18131,13 +18659,13 @@ var setCommand = new Command21().name("set").description("Set your scope slug").
18131
18659
  );
18132
18660
 
18133
18661
  // src/commands/scope/index.ts
18134
- var scopeCommand = new Command22().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
18662
+ var scopeCommand = new Command26().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
18135
18663
 
18136
18664
  // 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";
18665
+ import { Command as Command27 } from "commander";
18666
+ import chalk29 from "chalk";
18667
+ import path13 from "path";
18668
+ import { existsSync as existsSync10 } from "fs";
18141
18669
  import { writeFile as writeFile7 } from "fs/promises";
18142
18670
  var VM0_YAML_FILE = "vm0.yaml";
18143
18671
  var AGENTS_MD_FILE = "AGENTS.md";
@@ -18172,76 +18700,76 @@ You are a HackerNews AI content curator.
18172
18700
  }
18173
18701
  function checkExistingFiles() {
18174
18702
  const existingFiles = [];
18175
- if (existsSync9(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
18176
- if (existsSync9(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
18703
+ if (existsSync10(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
18704
+ if (existsSync10(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
18177
18705
  return existingFiles;
18178
18706
  }
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) => {
18707
+ 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
18708
  const existingFiles = checkExistingFiles();
18198
18709
  if (existingFiles.length > 0 && !options.force) {
18199
18710
  for (const file2 of existingFiles) {
18200
- console.log(chalk24.red(`\u2717 ${file2} already exists`));
18711
+ console.log(chalk29.red(`\u2717 ${file2} already exists`));
18201
18712
  }
18202
18713
  console.log();
18203
- console.log(`To overwrite: ${chalk24.cyan("vm0 init --force")}`);
18714
+ console.log(`To overwrite: ${chalk29.cyan("vm0 init --force")}`);
18204
18715
  process.exit(1);
18205
18716
  }
18206
18717
  let agentName;
18207
18718
  if (options.name) {
18208
18719
  agentName = options.name.trim();
18720
+ } else if (!isInteractive()) {
18721
+ console.error(
18722
+ chalk29.red("\u2717 --name flag is required in non-interactive mode")
18723
+ );
18724
+ console.error(chalk29.dim(" Usage: vm0 init --name <agent-name>"));
18725
+ process.exit(1);
18209
18726
  } else {
18210
- try {
18211
- agentName = await promptAgentName();
18212
- } catch {
18213
- process.exit(0);
18727
+ const dirName = path13.basename(process.cwd());
18728
+ const defaultName = validateAgentName(dirName) ? dirName : void 0;
18729
+ const name = await promptText(
18730
+ "Enter agent name",
18731
+ defaultName,
18732
+ (value) => {
18733
+ if (!validateAgentName(value)) {
18734
+ return "Must be 3-64 characters, alphanumeric and hyphens, start/end with letter or number";
18735
+ }
18736
+ return true;
18737
+ }
18738
+ );
18739
+ if (name === void 0) {
18740
+ console.log(chalk29.dim("Cancelled"));
18741
+ return;
18214
18742
  }
18743
+ agentName = name;
18215
18744
  }
18216
18745
  if (!agentName || !validateAgentName(agentName)) {
18217
- console.log(chalk24.red("\u2717 Invalid agent name"));
18746
+ console.log(chalk29.red("\u2717 Invalid agent name"));
18218
18747
  console.log(
18219
- chalk24.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
18748
+ chalk29.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
18220
18749
  );
18221
- console.log(chalk24.dim(" Must start and end with letter or number"));
18750
+ console.log(chalk29.dim(" Must start and end with letter or number"));
18222
18751
  process.exit(1);
18223
18752
  }
18224
18753
  await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
18225
18754
  const vm0Status = existingFiles.includes(VM0_YAML_FILE) ? " (overwritten)" : "";
18226
- console.log(chalk24.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
18755
+ console.log(chalk29.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
18227
18756
  await writeFile7(AGENTS_MD_FILE, generateAgentsMd());
18228
18757
  const agentsStatus = existingFiles.includes(AGENTS_MD_FILE) ? " (overwritten)" : "";
18229
- console.log(chalk24.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
18758
+ console.log(chalk29.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
18230
18759
  console.log();
18231
18760
  console.log("Next steps:");
18232
18761
  console.log(
18233
- ` 1. Get your Claude Code token: ${chalk24.cyan("claude setup-token")}`
18762
+ ` 1. Get your Claude Code token: ${chalk29.cyan("claude setup-token")}`
18234
18763
  );
18235
18764
  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"')}`);
18765
+ console.log(chalk29.dim(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
18766
+ console.log(` 3. Run your agent: ${chalk29.cyan('vm0 cook "your prompt"')}`);
18238
18767
  });
18239
18768
 
18240
18769
  // 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";
18770
+ import { Command as Command28 } from "commander";
18771
+ import chalk30 from "chalk";
18772
+ import { existsSync as existsSync11 } from "fs";
18245
18773
  import { mkdir as mkdir7, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
18246
18774
  import { execSync, spawnSync } from "child_process";
18247
18775
  import { parse as parseYaml5 } from "yaml";
@@ -18264,57 +18792,57 @@ function isGhAuthenticated() {
18264
18792
  async function checkPrerequisites() {
18265
18793
  console.log("Checking prerequisites...");
18266
18794
  if (!isGhInstalled()) {
18267
- console.log(chalk25.red("\u2717 GitHub CLI (gh) is not installed"));
18795
+ console.log(chalk30.red("\u2717 GitHub CLI (gh) is not installed"));
18268
18796
  console.log();
18269
18797
  console.log("GitHub CLI is required for this command.");
18270
18798
  console.log();
18271
- console.log(` macOS: ${chalk25.cyan("brew install gh")}`);
18272
- console.log(` Other: ${chalk25.cyan("https://cli.github.com/")}`);
18799
+ console.log(` macOS: ${chalk30.cyan("brew install gh")}`);
18800
+ console.log(` Other: ${chalk30.cyan("https://cli.github.com/")}`);
18273
18801
  console.log();
18274
18802
  console.log("After installation, run:");
18275
- console.log(` ${chalk25.cyan("gh auth login")}`);
18803
+ console.log(` ${chalk30.cyan("gh auth login")}`);
18276
18804
  console.log();
18277
18805
  console.log("Then try again:");
18278
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18806
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18279
18807
  process.exit(1);
18280
18808
  }
18281
- console.log(chalk25.green("\u2713 GitHub CLI (gh) is installed"));
18809
+ console.log(chalk30.green("\u2713 GitHub CLI (gh) is installed"));
18282
18810
  if (!isGhAuthenticated()) {
18283
- console.log(chalk25.red("\u2717 GitHub CLI is not authenticated"));
18811
+ console.log(chalk30.red("\u2717 GitHub CLI is not authenticated"));
18284
18812
  console.log();
18285
18813
  console.log("Please authenticate GitHub CLI first:");
18286
- console.log(` ${chalk25.cyan("gh auth login")}`);
18814
+ console.log(` ${chalk30.cyan("gh auth login")}`);
18287
18815
  console.log();
18288
18816
  console.log("Then try again:");
18289
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18817
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18290
18818
  process.exit(1);
18291
18819
  }
18292
- console.log(chalk25.green("\u2713 GitHub CLI is authenticated"));
18820
+ console.log(chalk30.green("\u2713 GitHub CLI is authenticated"));
18293
18821
  const token = await getToken();
18294
18822
  if (!token) {
18295
- console.log(chalk25.red("\u2717 VM0 not authenticated"));
18823
+ console.log(chalk30.red("\u2717 VM0 not authenticated"));
18296
18824
  console.log();
18297
18825
  console.log("Please authenticate with VM0 first:");
18298
- console.log(` ${chalk25.cyan("vm0 auth login")}`);
18826
+ console.log(` ${chalk30.cyan("vm0 auth login")}`);
18299
18827
  console.log();
18300
18828
  console.log("Then try again:");
18301
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18829
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18302
18830
  process.exit(1);
18303
18831
  }
18304
- console.log(chalk25.green("\u2713 VM0 authenticated"));
18305
- if (!existsSync10("vm0.yaml")) {
18306
- console.log(chalk25.red("\u2717 vm0.yaml not found"));
18832
+ console.log(chalk30.green("\u2713 VM0 authenticated"));
18833
+ if (!existsSync11("vm0.yaml")) {
18834
+ console.log(chalk30.red("\u2717 vm0.yaml not found"));
18307
18835
  console.log();
18308
18836
  console.log("This command requires a vm0.yaml configuration file.");
18309
18837
  console.log();
18310
18838
  console.log("To create one, run:");
18311
- console.log(` ${chalk25.cyan("vm0 init")}`);
18839
+ console.log(` ${chalk30.cyan("vm0 init")}`);
18312
18840
  console.log();
18313
18841
  console.log("Then try again:");
18314
- console.log(` ${chalk25.cyan("vm0 setup-github")}`);
18842
+ console.log(` ${chalk30.cyan("vm0 setup-github")}`);
18315
18843
  process.exit(1);
18316
18844
  }
18317
- console.log(chalk25.green("\u2713 vm0.yaml found"));
18845
+ console.log(chalk30.green("\u2713 vm0.yaml found"));
18318
18846
  return token;
18319
18847
  }
18320
18848
  function generatePublishYaml() {
@@ -18425,22 +18953,8 @@ function extractSecretsAndVars(config2) {
18425
18953
  };
18426
18954
  }
18427
18955
  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
- });
18956
+ const result = await promptConfirm(question, defaultYes);
18957
+ return result ?? false;
18444
18958
  }
18445
18959
  function setGitHubSecret(name, value) {
18446
18960
  const result = spawnSync("gh", ["secret", "set", name], {
@@ -18482,7 +18996,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
18482
18996
  if (secretStatuses.length > 0) {
18483
18997
  console.log("\u2502 Secrets: \u2502");
18484
18998
  for (const s of secretStatuses) {
18485
- const status = s.found ? chalk25.green("\u2713") : chalk25.red("\u2717");
18999
+ const status = s.found ? chalk30.green("\u2713") : chalk30.red("\u2717");
18486
19000
  const source = s.found ? `(from ${s.source})` : "not found";
18487
19001
  const paddedName = (s.name + " ").padEnd(23, ".");
18488
19002
  console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
@@ -18491,7 +19005,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
18491
19005
  if (varStatuses.length > 0) {
18492
19006
  console.log("\u2502 Variables: \u2502");
18493
19007
  for (const v of varStatuses) {
18494
- const status = v.found ? chalk25.green("\u2713") : chalk25.red("\u2717");
19008
+ const status = v.found ? chalk30.green("\u2713") : chalk30.red("\u2717");
18495
19009
  const source = v.found ? `(from ${v.source})` : "not found";
18496
19010
  const paddedName = (v.name + " ").padEnd(23, ".");
18497
19011
  console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
@@ -18503,17 +19017,17 @@ function showManualSetupInstructions(secrets, vars) {
18503
19017
  console.log("Skipped automatic setup. Configure secrets manually:");
18504
19018
  console.log();
18505
19019
  console.log(" Step 1: Get your VM0 token");
18506
- console.log(` ${chalk25.cyan("vm0 auth setup-token")}`);
19020
+ console.log(` ${chalk30.cyan("vm0 auth setup-token")}`);
18507
19021
  console.log();
18508
19022
  console.log(" Step 2: Set GitHub secrets");
18509
19023
  for (const s of secrets) {
18510
- console.log(` ${chalk25.cyan(`gh secret set ${s}`)}`);
19024
+ console.log(` ${chalk30.cyan(`gh secret set ${s}`)}`);
18511
19025
  }
18512
19026
  if (vars.length > 0) {
18513
19027
  console.log();
18514
19028
  console.log(" Step 3: Set GitHub variables");
18515
19029
  for (const v of vars) {
18516
- console.log(` ${chalk25.cyan(`gh variable set ${v}`)}`);
19030
+ console.log(` ${chalk30.cyan(`gh variable set ${v}`)}`);
18517
19031
  }
18518
19032
  }
18519
19033
  }
@@ -18556,7 +19070,7 @@ function showWorkflowsCreatedMessage() {
18556
19070
  console.log("\u2502 3. Push to main branch to trigger publish \u2502");
18557
19071
  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
19072
  }
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(
19073
+ 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
19074
  async (options) => {
18561
19075
  const vm0Token = await checkPrerequisites();
18562
19076
  if (!vm0Token) {
@@ -18568,10 +19082,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18568
19082
  const config2 = parseYaml5(content);
18569
19083
  const agents = config2.agents;
18570
19084
  const agentName = Object.keys(agents)[0];
18571
- console.log(chalk25.green(`\u2713 Agent: ${agentName}`));
19085
+ console.log(chalk30.green(`\u2713 Agent: ${agentName}`));
18572
19086
  const { secrets, vars } = extractSecretsAndVars(config2);
18573
19087
  console.log(
18574
- chalk25.green(
19088
+ chalk30.green(
18575
19089
  `\u2713 Found ${secrets.length} secrets, ${vars.length} variables`
18576
19090
  )
18577
19091
  );
@@ -18579,10 +19093,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18579
19093
  const publishPath = ".github/workflows/publish.yml";
18580
19094
  const runPath = ".github/workflows/run.yml";
18581
19095
  const existingFiles = [];
18582
- if (existsSync10(publishPath)) existingFiles.push(publishPath);
18583
- if (existsSync10(runPath)) existingFiles.push(runPath);
19096
+ if (existsSync11(publishPath)) existingFiles.push(publishPath);
19097
+ if (existsSync11(runPath)) existingFiles.push(runPath);
18584
19098
  if (existingFiles.length > 0 && !options.force) {
18585
- console.log(chalk25.yellow("\u26A0 Existing workflow files detected:"));
19099
+ console.log(chalk30.yellow("\u26A0 Existing workflow files detected:"));
18586
19100
  for (const file2 of existingFiles) {
18587
19101
  console.log(` \u2022 ${file2}`);
18588
19102
  }
@@ -18595,7 +19109,7 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18595
19109
  if (!overwrite) {
18596
19110
  console.log();
18597
19111
  console.log("Aborted. To force overwrite, run:");
18598
- console.log(` ${chalk25.cyan("vm0 setup-github --force")}`);
19112
+ console.log(` ${chalk30.cyan("vm0 setup-github --force")}`);
18599
19113
  process.exit(0);
18600
19114
  }
18601
19115
  }
@@ -18605,13 +19119,13 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18605
19119
  await mkdir7(".github/workflows", { recursive: true });
18606
19120
  await writeFile8(publishPath, generatePublishYaml());
18607
19121
  const publishStatus = existingFiles.includes(publishPath) ? "Overwrote" : "Created";
18608
- console.log(chalk25.green(`\u2713 ${publishStatus} ${publishPath}`));
19122
+ console.log(chalk30.green(`\u2713 ${publishStatus} ${publishPath}`));
18609
19123
  await writeFile8(runPath, generateRunYaml(agentName, secrets, vars));
18610
19124
  const runStatus = existingFiles.includes(runPath) ? "Overwrote" : "Created";
18611
- console.log(chalk25.green(`\u2713 ${runStatus} ${runPath}`));
19125
+ console.log(chalk30.green(`\u2713 ${runStatus} ${runPath}`));
18612
19126
  console.log();
18613
19127
  if (options.skipSecrets) {
18614
- console.log(chalk25.green("\u2713 Done (secrets setup skipped)"));
19128
+ console.log(chalk30.green("\u2713 Done (secrets setup skipped)"));
18615
19129
  return;
18616
19130
  }
18617
19131
  const { secretStatuses, varStatuses } = await detectSecretValues(
@@ -18651,14 +19165,14 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18651
19165
  if (s.found && s.value) {
18652
19166
  const success2 = setGitHubSecret(s.name, s.value);
18653
19167
  if (success2) {
18654
- console.log(` ${chalk25.green("\u2713")} ${s.name}`);
19168
+ console.log(` ${chalk30.green("\u2713")} ${s.name}`);
18655
19169
  } else {
18656
- console.log(` ${chalk25.red("\u2717")} ${s.name} (failed)`);
19170
+ console.log(` ${chalk30.red("\u2717")} ${s.name} (failed)`);
18657
19171
  failedSecrets.push(s.name);
18658
19172
  }
18659
19173
  } else {
18660
19174
  console.log(
18661
- ` ${chalk25.yellow("\u26A0")} ${s.name} (skipped - not found)`
19175
+ ` ${chalk30.yellow("\u26A0")} ${s.name} (skipped - not found)`
18662
19176
  );
18663
19177
  }
18664
19178
  }
@@ -18670,14 +19184,14 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18670
19184
  if (v.found && v.value) {
18671
19185
  const success2 = setGitHubVariable(v.name, v.value);
18672
19186
  if (success2) {
18673
- console.log(` ${chalk25.green("\u2713")} ${v.name}`);
19187
+ console.log(` ${chalk30.green("\u2713")} ${v.name}`);
18674
19188
  } else {
18675
- console.log(` ${chalk25.red("\u2717")} ${v.name} (failed)`);
19189
+ console.log(` ${chalk30.red("\u2717")} ${v.name} (failed)`);
18676
19190
  failedVars.push(v.name);
18677
19191
  }
18678
19192
  } else {
18679
19193
  console.log(
18680
- ` ${chalk25.yellow("\u26A0")} ${v.name} (skipped - not found)`
19194
+ ` ${chalk30.yellow("\u26A0")} ${v.name} (skipped - not found)`
18681
19195
  );
18682
19196
  }
18683
19197
  }
@@ -18700,10 +19214,10 @@ var setupGithubCommand = new Command24().name("setup-github").description("Initi
18700
19214
  );
18701
19215
 
18702
19216
  // src/index.ts
18703
- var program = new Command25();
18704
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.31.1");
19217
+ var program = new Command29();
19218
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.33.0");
18705
19219
  program.command("info").description("Display environment information").action(async () => {
18706
- console.log(chalk26.bold("System Information:"));
19220
+ console.log(chalk31.bold("System Information:"));
18707
19221
  console.log(`Node Version: ${process.version}`);
18708
19222
  console.log(`Platform: ${process.platform}`);
18709
19223
  console.log(`Architecture: ${process.arch}`);