@boxes-dev/dvb 0.2.43 → 0.2.44

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.
package/dist/bin/dvb.cjs CHANGED
@@ -404,11 +404,11 @@ var init_repo = __esm({
404
404
  try {
405
405
  const url = new URL(trimmed);
406
406
  const host = url.hostname.toLowerCase();
407
- const path25 = stripGitSuffix(url.pathname);
408
- if (!host || !path25) {
407
+ const path26 = stripGitSuffix(url.pathname);
408
+ if (!host || !path26) {
409
409
  throw new Error(`Unrecognized git URL: ${input}`);
410
410
  }
411
- return `${host}/${path25}`;
411
+ return `${host}/${path26}`;
412
412
  } catch {
413
413
  }
414
414
  if (trimmed.includes(":")) {
@@ -436,11 +436,11 @@ var init_sprites = __esm({
436
436
  method;
437
437
  path;
438
438
  body;
439
- constructor(status, method, path25, body) {
440
- super(`Sprites API error ${status} ${method} ${path25}: ${body}`);
439
+ constructor(status, method, path26, body) {
440
+ super(`Sprites API error ${status} ${method} ${path26}: ${body}`);
441
441
  this.status = status;
442
442
  this.method = method;
443
- this.path = path25;
443
+ this.path = path26;
444
444
  this.body = body;
445
445
  }
446
446
  };
@@ -485,15 +485,15 @@ var init_sprites = __esm({
485
485
  }
486
486
  return { message: String(event) };
487
487
  };
488
- toWsUrl = (apiBaseUrl, path25) => {
488
+ toWsUrl = (apiBaseUrl, path26) => {
489
489
  const base = new URL(apiBaseUrl);
490
490
  const protocol = base.protocol === "https:" ? "wss:" : "ws:";
491
- return new URL(path25, `${protocol}//${base.host}`);
491
+ return new URL(path26, `${protocol}//${base.host}`);
492
492
  };
493
493
  shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
494
- requestJson = async (apiBaseUrl, token, method, path25, body) => {
494
+ requestJson = async (apiBaseUrl, token, method, path26, body) => {
495
495
  const requestId = (0, import_node_crypto.randomUUID)();
496
- const url = new URL(path25, apiBaseUrl);
496
+ const url = new URL(path26, apiBaseUrl);
497
497
  const headers = {
498
498
  authorization: `Bearer ${token}`,
499
499
  "x-request-id": requestId
@@ -505,18 +505,18 @@ var init_sprites = __esm({
505
505
  if (body) {
506
506
  init.body = JSON.stringify(body);
507
507
  }
508
- logger.info("sprites_request", { requestId, method, path: path25 });
508
+ logger.info("sprites_request", { requestId, method, path: path26 });
509
509
  const response = await fetch(url, init);
510
510
  const text = await response.text();
511
511
  logger.info("sprites_response", {
512
512
  requestId,
513
513
  method,
514
- path: path25,
514
+ path: path26,
515
515
  status: response.status
516
516
  });
517
517
  if (!response.ok) {
518
518
  const snippet = text.trim().slice(0, 200);
519
- throw new SpritesApiError(response.status, method, path25, snippet);
519
+ throw new SpritesApiError(response.status, method, path26, snippet);
520
520
  }
521
521
  if (!text) return null;
522
522
  try {
@@ -536,8 +536,8 @@ var init_sprites = __esm({
536
536
  if (options?.prefix) {
537
537
  params.set("prefix", options.prefix);
538
538
  }
539
- const path25 = `/v1/sprites${params.size ? `?${params.toString()}` : ""}`;
540
- const payload = await requestJson(apiBaseUrl, token, "GET", path25);
539
+ const path26 = `/v1/sprites${params.size ? `?${params.toString()}` : ""}`;
540
+ const payload = await requestJson(apiBaseUrl, token, "GET", path26);
541
541
  const record = payload && typeof payload === "object" ? payload : null;
542
542
  const rawSprites = Array.isArray(record?.sprites) ? record?.sprites : Array.isArray(payload) ? payload : [];
543
543
  const sprites = rawSprites.filter(
@@ -563,9 +563,9 @@ var init_sprites = __esm({
563
563
  }
564
564
  return response;
565
565
  };
566
- requestNdjson = async (apiBaseUrl, token, method, path25, body) => {
566
+ requestNdjson = async (apiBaseUrl, token, method, path26, body) => {
567
567
  const requestId = (0, import_node_crypto.randomUUID)();
568
- const url = new URL(path25, apiBaseUrl);
568
+ const url = new URL(path26, apiBaseUrl);
569
569
  const headers = {
570
570
  authorization: `Bearer ${token}`,
571
571
  "x-request-id": requestId
@@ -577,18 +577,18 @@ var init_sprites = __esm({
577
577
  if (body) {
578
578
  init.body = JSON.stringify(body);
579
579
  }
580
- logger.info("sprites_request", { requestId, method, path: path25 });
580
+ logger.info("sprites_request", { requestId, method, path: path26 });
581
581
  const response = await fetch(url, init);
582
582
  logger.info("sprites_response", {
583
583
  requestId,
584
584
  method,
585
- path: path25,
585
+ path: path26,
586
586
  status: response.status
587
587
  });
588
588
  const text = await response.text();
589
589
  if (!response.ok) {
590
590
  const snippet = text.trim().slice(0, 200);
591
- throw new SpritesApiError(response.status, method, path25, snippet);
591
+ throw new SpritesApiError(response.status, method, path26, snippet);
592
592
  }
593
593
  const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
594
594
  const events = [];
@@ -618,13 +618,13 @@ var init_sprites = __esm({
618
618
  };
619
619
  writeFile = async (apiBaseUrl, token, name, remotePath, data) => {
620
620
  const requestId = (0, import_node_crypto.randomUUID)();
621
- const path25 = `/v1/sprites/${name}/fs/write`;
622
- const url = new URL(path25, apiBaseUrl);
621
+ const path26 = `/v1/sprites/${name}/fs/write`;
622
+ const url = new URL(path26, apiBaseUrl);
623
623
  url.searchParams.set("path", remotePath);
624
624
  url.searchParams.set("mkdir", "true");
625
625
  logger.info("sprites_fs_write", {
626
626
  requestId,
627
- path: path25,
627
+ path: path26,
628
628
  name,
629
629
  remotePath,
630
630
  size: data.length
@@ -640,7 +640,7 @@ var init_sprites = __esm({
640
640
  });
641
641
  logger.info("sprites_fs_write_response", {
642
642
  requestId,
643
- path: path25,
643
+ path: path26,
644
644
  status: response.status
645
645
  });
646
646
  if (!response.ok) {
@@ -677,15 +677,15 @@ var init_sprites = __esm({
677
677
  };
678
678
  readFile = async (apiBaseUrl, token, name, options) => {
679
679
  const requestId = (0, import_node_crypto.randomUUID)();
680
- const path25 = `/v1/sprites/${name}/fs/read`;
681
- const url = new URL(path25, apiBaseUrl);
680
+ const path26 = `/v1/sprites/${name}/fs/read`;
681
+ const url = new URL(path26, apiBaseUrl);
682
682
  url.searchParams.set("path", options.path);
683
683
  if (options.workingDir) {
684
684
  url.searchParams.set("workingDir", options.workingDir);
685
685
  }
686
686
  logger.info("sprites_fs_read", {
687
687
  requestId,
688
- path: path25,
688
+ path: path26,
689
689
  name,
690
690
  remotePath: options.path,
691
691
  workingDir: options.workingDir
@@ -699,12 +699,12 @@ var init_sprites = __esm({
699
699
  });
700
700
  logger.info("sprites_fs_read_response", {
701
701
  requestId,
702
- path: path25,
702
+ path: path26,
703
703
  status: response.status
704
704
  });
705
705
  if (!response.ok) {
706
706
  const snippet = (await response.text()).trim().slice(0, 200);
707
- throw new SpritesApiError(response.status, "GET", path25, snippet);
707
+ throw new SpritesApiError(response.status, "GET", path26, snippet);
708
708
  }
709
709
  const buffer = await response.arrayBuffer();
710
710
  return new Uint8Array(buffer);
@@ -932,8 +932,8 @@ var init_sprites = __esm({
932
932
  return [];
933
933
  };
934
934
  execCommand = async (apiBaseUrl, token, name, cmd, requestId) => {
935
- const path25 = `/v1/sprites/${name}/exec`;
936
- const url = toWsUrl(apiBaseUrl, path25);
935
+ const path26 = `/v1/sprites/${name}/exec`;
936
+ const url = toWsUrl(apiBaseUrl, path26);
937
937
  cmd.forEach((part) => url.searchParams.append("cmd", part));
938
938
  url.searchParams.set("tty", "false");
939
939
  url.searchParams.set("stdin", "false");
@@ -966,7 +966,7 @@ var init_sprites = __esm({
966
966
  const status = response.statusCode ?? 0;
967
967
  logger.warn("sprites_exec_unexpected_response", {
968
968
  requestId,
969
- path: path25,
969
+ path: path26,
970
970
  status,
971
971
  headers: response.headers,
972
972
  bodySnippet: snippet ? snippet.slice(0, 800) : void 0
@@ -980,7 +980,7 @@ var init_sprites = __esm({
980
980
  const finish = (code2) => {
981
981
  if (resolved) return;
982
982
  resolved = true;
983
- logger.info("sprites_exec_response", { requestId, path: path25, status: code2 });
983
+ logger.info("sprites_exec_response", { requestId, path: path26, status: code2 });
984
984
  resolve({
985
985
  exitCode: code2,
986
986
  stdout: Buffer.concat(stdout).toString("utf8"),
@@ -1030,7 +1030,7 @@ var init_sprites = __esm({
1030
1030
  const errorMessage = errorInfo.details && errorInfo.details !== errorInfo.message ? `${errorInfo.message} (${errorInfo.details})` : errorInfo.message;
1031
1031
  logger.warn("sprites_exec_error", {
1032
1032
  requestId,
1033
- path: path25,
1033
+ path: path26,
1034
1034
  errorMessage,
1035
1035
  errorName: errorInfo.name,
1036
1036
  errorCode: errorInfo.code,
@@ -3335,12 +3335,12 @@ function createApi(pathParts = []) {
3335
3335
  `API path is expected to be of the form \`api.moduleName.functionName\`. Found: \`${found}\``
3336
3336
  );
3337
3337
  }
3338
- const path25 = pathParts.slice(0, -1).join("/");
3338
+ const path26 = pathParts.slice(0, -1).join("/");
3339
3339
  const exportName = pathParts[pathParts.length - 1];
3340
3340
  if (exportName === "default") {
3341
- return path25;
3341
+ return path26;
3342
3342
  } else {
3343
- return path25 + ":" + exportName;
3343
+ return path26 + ":" + exportName;
3344
3344
  }
3345
3345
  } else if (prop === Symbol.toStringTag) {
3346
3346
  return "FunctionReference";
@@ -6549,8 +6549,8 @@ var init_simple_client_node = __esm({
6549
6549
  });
6550
6550
  require_node_gyp_build = __commonJS2({
6551
6551
  "../common/temp/node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js"(exports2, module2) {
6552
- var fs25 = __require("fs");
6553
- var path25 = __require("path");
6552
+ var fs26 = __require("fs");
6553
+ var path26 = __require("path");
6554
6554
  var os11 = __require("os");
6555
6555
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
6556
6556
  var vars = process.config && process.config.variables || {};
@@ -6567,21 +6567,21 @@ var init_simple_client_node = __esm({
6567
6567
  return runtimeRequire(load2.resolve(dir));
6568
6568
  }
6569
6569
  load2.resolve = load2.path = function(dir) {
6570
- dir = path25.resolve(dir || ".");
6570
+ dir = path26.resolve(dir || ".");
6571
6571
  try {
6572
- var name = runtimeRequire(path25.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
6572
+ var name = runtimeRequire(path26.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
6573
6573
  if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
6574
6574
  } catch (err) {
6575
6575
  }
6576
6576
  if (!prebuildsOnly) {
6577
- var release = getFirst(path25.join(dir, "build/Release"), matchBuild);
6577
+ var release = getFirst(path26.join(dir, "build/Release"), matchBuild);
6578
6578
  if (release) return release;
6579
- var debug = getFirst(path25.join(dir, "build/Debug"), matchBuild);
6579
+ var debug = getFirst(path26.join(dir, "build/Debug"), matchBuild);
6580
6580
  if (debug) return debug;
6581
6581
  }
6582
6582
  var prebuild = resolve(dir);
6583
6583
  if (prebuild) return prebuild;
6584
- var nearby = resolve(path25.dirname(process.execPath));
6584
+ var nearby = resolve(path26.dirname(process.execPath));
6585
6585
  if (nearby) return nearby;
6586
6586
  var target = [
6587
6587
  "platform=" + platform,
@@ -6598,26 +6598,26 @@ var init_simple_client_node = __esm({
6598
6598
  ].filter(Boolean).join(" ");
6599
6599
  throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
6600
6600
  function resolve(dir2) {
6601
- var tuples = readdirSync(path25.join(dir2, "prebuilds")).map(parseTuple);
6601
+ var tuples = readdirSync(path26.join(dir2, "prebuilds")).map(parseTuple);
6602
6602
  var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
6603
6603
  if (!tuple) return;
6604
- var prebuilds = path25.join(dir2, "prebuilds", tuple.name);
6604
+ var prebuilds = path26.join(dir2, "prebuilds", tuple.name);
6605
6605
  var parsed = readdirSync(prebuilds).map(parseTags);
6606
6606
  var candidates = parsed.filter(matchTags(runtime, abi));
6607
6607
  var winner = candidates.sort(compareTags(runtime))[0];
6608
- if (winner) return path25.join(prebuilds, winner.file);
6608
+ if (winner) return path26.join(prebuilds, winner.file);
6609
6609
  }
6610
6610
  };
6611
6611
  function readdirSync(dir) {
6612
6612
  try {
6613
- return fs25.readdirSync(dir);
6613
+ return fs26.readdirSync(dir);
6614
6614
  } catch (err) {
6615
6615
  return [];
6616
6616
  }
6617
6617
  }
6618
6618
  function getFirst(dir, filter) {
6619
6619
  var files = readdirSync(dir).filter(filter);
6620
- return files[0] && path25.join(dir, files[0]);
6620
+ return files[0] && path26.join(dir, files[0]);
6621
6621
  }
6622
6622
  function matchBuild(name) {
6623
6623
  return /\.node$/.test(name);
@@ -6704,7 +6704,7 @@ var init_simple_client_node = __esm({
6704
6704
  return typeof window !== "undefined" && window.process && window.process.type === "renderer";
6705
6705
  }
6706
6706
  function isAlpine(platform2) {
6707
- return platform2 === "linux" && fs25.existsSync("/etc/alpine-release");
6707
+ return platform2 === "linux" && fs26.existsSync("/etc/alpine-release");
6708
6708
  }
6709
6709
  load2.parseTags = parseTags;
6710
6710
  load2.matchTags = matchTags;
@@ -10686,7 +10686,7 @@ var init_server = __esm({
10686
10686
  });
10687
10687
 
10688
10688
  // ../daemon/src/spritesRegistry.ts
10689
- var import_node_crypto2, import_node_fs, import_promises4, registryGet, registryReplace, registryUpsert, registryUsage, registryRemove, logger4, TOKEN_REFRESH_BUFFER_MS, clientCache, migrationPromise, migrationCompleted, trimEnv, resolveConvexUrl, resolveControlPlaneUrl, requireConvexConfig, decodeJwtPayload, parseTokenExpiresAt, shouldRefreshToken, isUnauthorizedError, clearControlPlaneSession, handleUnauthorized, refreshSession, loadControlPlaneToken, getClient, spritePortsList, logRequest, logResponse, parseTimestamp, pickEarlier, pickLater, mergeBoxes, mergeProjects, mergeRegistry, getRegistryFromConvex, replaceRegistry, migrateLocalRegistry, backfillInitStatus, fetchRegistry, upsertRegistry, recordRegistryUsage, removeRegistryEntry, subscribeSpritePorts;
10689
+ var import_node_crypto2, import_node_fs, import_promises4, registryGet, registryReplace, registryUpsert, registryUsage, registryRemove, logger4, TOKEN_REFRESH_BUFFER_MS, clientCache, migrationPromise, migrationCompleted, trimEnv, normalizeConvexDeployment, stripDevPrefix, resolveFromDeployment, resolveFromUrl, resolveConvexUrl, resolveControlPlaneUrl, requireConvexConfig, decodeJwtPayload, parseTokenExpiresAt, shouldRefreshToken, isUnauthorizedError, clearControlPlaneSession, handleUnauthorized, refreshSession, loadControlPlaneToken, requireControlPlaneToken, getClient, spritePortsList, logRequest, logResponse, parseTimestamp, pickEarlier, pickLater, mergeBoxes, mergeProjects, mergeRegistry, getRegistryFromConvex, replaceRegistry, migrateLocalRegistry, backfillInitStatus, fetchRegistry, upsertRegistry, recordRegistryUsage, removeRegistryEntry, subscribeSpritePorts;
10690
10690
  var init_spritesRegistry = __esm({
10691
10691
  "../daemon/src/spritesRegistry.ts"() {
10692
10692
  "use strict";
@@ -10708,13 +10708,55 @@ var init_spritesRegistry = __esm({
10708
10708
  migrationPromise = null;
10709
10709
  migrationCompleted = false;
10710
10710
  trimEnv = (value) => value?.trim() ?? "";
10711
+ normalizeConvexDeployment = (value) => {
10712
+ const normalized = trimEnv(value).replace(/\r/g, "");
10713
+ if (!normalized) return "";
10714
+ if (normalized.includes(":")) {
10715
+ const [prefix, rest] = normalized.split(":", 2);
10716
+ return `${prefix}:${trimEnv(rest ?? "")}`;
10717
+ }
10718
+ return normalized;
10719
+ };
10720
+ stripDevPrefix = (value) => {
10721
+ if (value.startsWith("dev:")) {
10722
+ return trimEnv(value.slice(4));
10723
+ }
10724
+ return value;
10725
+ };
10726
+ resolveFromDeployment = (deploymentRaw, suffix) => {
10727
+ const deployment = stripDevPrefix(normalizeConvexDeployment(deploymentRaw));
10728
+ if (!deployment) return "";
10729
+ if (deployment.includes("://")) {
10730
+ return deployment;
10731
+ }
10732
+ if (deployment.includes(".")) {
10733
+ const host = suffix === "cloud" ? deployment.replace(".convex.site", ".convex.cloud") : deployment.replace(".convex.cloud", ".convex.site");
10734
+ return `https://${host}`;
10735
+ }
10736
+ return `https://${deployment}.convex.${suffix}`;
10737
+ };
10738
+ resolveFromUrl = (raw, suffix) => {
10739
+ const value = trimEnv(raw).replace(/\r/g, "");
10740
+ if (!value) return "";
10741
+ try {
10742
+ const url = new URL(value);
10743
+ const host = suffix === "cloud" ? url.host.replace(".convex.site", ".convex.cloud") : url.host.replace(".convex.cloud", ".convex.site");
10744
+ return `${url.protocol}//${host}`;
10745
+ } catch {
10746
+ return "";
10747
+ }
10748
+ };
10711
10749
  resolveConvexUrl = () => {
10712
10750
  const url = trimEnv(process.env.DEVBOX_CONVEX_URL) || trimEnv(process.env.VITE_CONVEX_URL);
10713
- return url.length > 0 ? url : null;
10751
+ if (url.length > 0) return url;
10752
+ const derived = resolveFromDeployment(process.env.CONVEX_DEPLOYMENT ?? "", "cloud") || resolveFromUrl(process.env.CONVEX_SITE_URL ?? "", "cloud");
10753
+ return derived ? derived : null;
10714
10754
  };
10715
10755
  resolveControlPlaneUrl = () => {
10716
10756
  const url = trimEnv(process.env.DEVBOX_CONTROL_PLANE_URL) || trimEnv(process.env.CONVEX_SITE_URL);
10717
- return url.length > 0 ? url : null;
10757
+ if (url.length > 0) return url;
10758
+ const derived = resolveFromDeployment(process.env.CONVEX_DEPLOYMENT ?? "", "site") || resolveFromUrl(process.env.VITE_CONVEX_URL ?? "", "site");
10759
+ return derived ? derived : null;
10718
10760
  };
10719
10761
  requireConvexConfig = () => {
10720
10762
  if (!resolveControlPlaneUrl()) {
@@ -10850,26 +10892,35 @@ var init_spritesRegistry = __esm({
10850
10892
  if (!token) {
10851
10893
  const refreshToken = await store.getControlPlaneRefreshToken();
10852
10894
  if (refreshToken) {
10853
- const refreshed = await refreshSession(refreshToken);
10854
- token = refreshed.token;
10855
- await store.setControlPlaneToken(token);
10856
- if (refreshed.refreshToken) {
10857
- await store.setControlPlaneRefreshToken(refreshed.refreshToken);
10858
- }
10859
- const nextExpiresAt = parseTokenExpiresAt(token);
10860
- if (nextExpiresAt) {
10861
- await store.setControlPlaneTokenExpiresAt(nextExpiresAt);
10862
- } else {
10863
- await store.clearControlPlaneTokenExpiresAt();
10895
+ try {
10896
+ const refreshed = await refreshSession(refreshToken);
10897
+ token = refreshed.token;
10898
+ await store.setControlPlaneToken(token);
10899
+ if (refreshed.refreshToken) {
10900
+ await store.setControlPlaneRefreshToken(refreshed.refreshToken);
10901
+ }
10902
+ const nextExpiresAt = parseTokenExpiresAt(token);
10903
+ if (nextExpiresAt) {
10904
+ await store.setControlPlaneTokenExpiresAt(nextExpiresAt);
10905
+ } else {
10906
+ await store.clearControlPlaneTokenExpiresAt();
10907
+ }
10908
+ } catch (error) {
10909
+ logger4.warn("control_plane_refresh_failed", { error: String(error) });
10864
10910
  }
10865
10911
  }
10866
10912
  }
10913
+ return token ?? null;
10914
+ };
10915
+ requireControlPlaneToken = async () => {
10916
+ const token = await loadControlPlaneToken();
10867
10917
  if (!token) {
10868
10918
  throw new Error("Control plane auth missing. Run `dvb setup` to sign in.");
10869
10919
  }
10870
10920
  return token;
10871
10921
  };
10872
10922
  getClient = async () => {
10923
+ await requireControlPlaneToken();
10873
10924
  const convexUrl = requireConvexConfig();
10874
10925
  if (clientCache && clientCache.url === convexUrl) {
10875
10926
  return clientCache.client;
@@ -11677,7 +11728,7 @@ __export(src_exports, {
11677
11728
  runDaemon: () => runDaemon,
11678
11729
  startDaemon: () => startDaemon
11679
11730
  });
11680
- var import_node_http, import_promises5, import_node_fs2, import_node_crypto4, import_node_net2, import_node_path5, logger6, startedAt, DAEMON_API_VERSION, DAEMON_FEATURES, allowShutdown, buildBoxSummaries, readBody, readRequestPath, writeJson, handleRequestError, isSocketAlive, ensureRuntimeDir, startDaemon, runDaemon;
11731
+ var import_node_http, import_promises5, import_node_fs2, import_node_crypto4, import_node_net2, import_node_path5, logger6, startedAt, DAEMON_API_VERSION, DAEMON_FEATURES, allowShutdown, buildBoxSummaries, readBody, readRequestPath, writeJson, handleRequestError, isSocketAlive, waitForSocketAlive, ensureRuntimeDir, startDaemon, runDaemon;
11681
11732
  var init_src2 = __esm({
11682
11733
  "../daemon/src/index.ts"() {
11683
11734
  import_node_http = require("node:http");
@@ -11790,6 +11841,15 @@ var init_src2 = __esm({
11790
11841
  socket.once("error", () => done(false));
11791
11842
  socket.setTimeout(250, () => done(false));
11792
11843
  });
11844
+ waitForSocketAlive = async (socketPath, timeoutMs) => {
11845
+ const deadline = Date.now() + timeoutMs;
11846
+ while (Date.now() < deadline) {
11847
+ if (!(0, import_node_fs2.existsSync)(socketPath)) return false;
11848
+ if (await isSocketAlive(socketPath)) return true;
11849
+ await new Promise((resolve) => setTimeout(resolve, 50));
11850
+ }
11851
+ return false;
11852
+ };
11793
11853
  ensureRuntimeDir = async (runtimeDir) => {
11794
11854
  await import_promises5.default.mkdir(runtimeDir, { recursive: true, mode: 448 });
11795
11855
  try {
@@ -11805,7 +11865,7 @@ var init_src2 = __esm({
11805
11865
  const { socketPath, runtimeDir } = socketInfo;
11806
11866
  await ensureRuntimeDir(runtimeDir);
11807
11867
  if ((0, import_node_fs2.existsSync)(socketPath)) {
11808
- const alive = await isSocketAlive(socketPath);
11868
+ const alive = await waitForSocketAlive(socketPath, 1e3);
11809
11869
  if (alive) {
11810
11870
  throw new Error(`dvbd already running at ${socketPath}`);
11811
11871
  }
@@ -11813,31 +11873,18 @@ var init_src2 = __esm({
11813
11873
  }
11814
11874
  const portManager = new PortManager();
11815
11875
  portManager.start();
11816
- void fetchRegistry().then((registry) => {
11817
- for (const canonical of Object.keys(registry.boxes)) {
11818
- portManager.noteBox(canonical);
11819
- }
11820
- for (const canonical of Object.values(registry.aliases)) {
11821
- portManager.noteBox(canonical);
11822
- }
11823
- for (const project of Object.values(registry.projects)) {
11824
- portManager.noteBox(project.canonical);
11825
- }
11826
- }).catch((error) => {
11827
- logger6.warn("ports_registry_load_failed", { error: String(error) });
11828
- });
11829
11876
  const server = (0, import_node_http.createServer)((req, res) => {
11830
11877
  const requestId = req.headers["x-request-id"] ?? (0, import_node_crypto4.randomUUID)();
11831
- const path25 = readRequestPath(req);
11878
+ const path26 = readRequestPath(req);
11832
11879
  res.on("finish", () => {
11833
11880
  logger6.info("daemon_request", {
11834
11881
  requestId,
11835
11882
  method: req.method,
11836
- path: path25,
11883
+ path: path26,
11837
11884
  status: res.statusCode
11838
11885
  });
11839
11886
  });
11840
- if (path25 === "/health") {
11887
+ if (path26 === "/health") {
11841
11888
  writeJson(res, 200, {
11842
11889
  ok: true,
11843
11890
  pid: process.pid,
@@ -11846,7 +11893,7 @@ var init_src2 = __esm({
11846
11893
  });
11847
11894
  return;
11848
11895
  }
11849
- if (path25 === "/version") {
11896
+ if (path26 === "/version") {
11850
11897
  writeJson(res, 200, {
11851
11898
  name: "dvbd",
11852
11899
  version: "0.0.0",
@@ -11855,7 +11902,7 @@ var init_src2 = __esm({
11855
11902
  });
11856
11903
  return;
11857
11904
  }
11858
- if (path25 === "/boxes") {
11905
+ if (path26 === "/boxes") {
11859
11906
  void buildBoxSummaries().then((boxes) => {
11860
11907
  writeJson(res, 200, { boxes });
11861
11908
  }).catch((error) => {
@@ -11863,7 +11910,7 @@ var init_src2 = __esm({
11863
11910
  });
11864
11911
  return;
11865
11912
  }
11866
- if (path25 === "/registry/project" && req.method === "GET") {
11913
+ if (path26 === "/registry/project" && req.method === "GET") {
11867
11914
  const url = new URL(req.url ?? "", "http://localhost");
11868
11915
  const fingerprint = url.searchParams.get("fingerprint") ?? "";
11869
11916
  void fetchRegistry().then((registry) => {
@@ -11874,7 +11921,7 @@ var init_src2 = __esm({
11874
11921
  });
11875
11922
  return;
11876
11923
  }
11877
- if (path25 === "/registry/alias" && req.method === "GET") {
11924
+ if (path26 === "/registry/alias" && req.method === "GET") {
11878
11925
  const url = new URL(req.url ?? "", "http://localhost");
11879
11926
  const alias = url.searchParams.get("alias") ?? "";
11880
11927
  void fetchRegistry().then((registry) => {
@@ -11885,7 +11932,7 @@ var init_src2 = __esm({
11885
11932
  });
11886
11933
  return;
11887
11934
  }
11888
- if (path25 === "/registry/upsert" && req.method === "POST") {
11935
+ if (path26 === "/registry/upsert" && req.method === "POST") {
11889
11936
  void readBody(req).then(async (payload) => {
11890
11937
  const project = payload?.project;
11891
11938
  const box = payload?.box;
@@ -11910,7 +11957,7 @@ var init_src2 = __esm({
11910
11957
  });
11911
11958
  return;
11912
11959
  }
11913
- if (path25 === "/registry/usage" && req.method === "POST") {
11960
+ if (path26 === "/registry/usage" && req.method === "POST") {
11914
11961
  void readBody(req).then(async (payload) => {
11915
11962
  const canonical = typeof payload?.canonical === "string" ? payload.canonical : "";
11916
11963
  if (!canonical) {
@@ -11925,7 +11972,7 @@ var init_src2 = __esm({
11925
11972
  });
11926
11973
  return;
11927
11974
  }
11928
- if (path25 === "/registry/remove" && req.method === "POST") {
11975
+ if (path26 === "/registry/remove" && req.method === "POST") {
11929
11976
  void readBody(req).then(async (payload) => {
11930
11977
  const canonical = typeof payload?.canonical === "string" ? payload.canonical : "";
11931
11978
  if (!canonical) {
@@ -11940,12 +11987,12 @@ var init_src2 = __esm({
11940
11987
  });
11941
11988
  return;
11942
11989
  }
11943
- if (path25 === "/ports" && req.method === "GET") {
11990
+ if (path26 === "/ports" && req.method === "GET") {
11944
11991
  const snapshot = portManager.listPorts();
11945
11992
  writeJson(res, 200, snapshot);
11946
11993
  return;
11947
11994
  }
11948
- if (path25 === "/ports/clear" && req.method === "POST") {
11995
+ if (path26 === "/ports/clear" && req.method === "POST") {
11949
11996
  void readBody(req).then((payload) => {
11950
11997
  const box = typeof payload?.box === "string" ? payload.box : void 0;
11951
11998
  if (!box) {
@@ -11959,7 +12006,7 @@ var init_src2 = __esm({
11959
12006
  });
11960
12007
  return;
11961
12008
  }
11962
- if (path25 === "/ports/reload" && req.method === "POST") {
12009
+ if (path26 === "/ports/reload" && req.method === "POST") {
11963
12010
  void readBody(req).then(async (payload) => {
11964
12011
  const box = typeof payload?.box === "string" ? payload.box : void 0;
11965
12012
  if (!box) {
@@ -11973,7 +12020,7 @@ var init_src2 = __esm({
11973
12020
  });
11974
12021
  return;
11975
12022
  }
11976
- if (path25 === "/ports/policy" && req.method === "POST") {
12023
+ if (path26 === "/ports/policy" && req.method === "POST") {
11977
12024
  void readBody(req).then((payload) => {
11978
12025
  const box = typeof payload?.box === "string" ? payload.box : void 0;
11979
12026
  const policy = payload?.policy === "auto" || payload?.policy === "disabled" ? payload.policy : null;
@@ -11990,7 +12037,7 @@ var init_src2 = __esm({
11990
12037
  });
11991
12038
  return;
11992
12039
  }
11993
- if (path25 === "/ports/forward" && req.method === "POST") {
12040
+ if (path26 === "/ports/forward" && req.method === "POST") {
11994
12041
  void readBody(req).then(async (payload) => {
11995
12042
  const box = typeof payload?.box === "string" ? payload.box : void 0;
11996
12043
  const port = typeof payload?.port === "number" ? payload.port : void 0;
@@ -12010,7 +12057,7 @@ var init_src2 = __esm({
12010
12057
  });
12011
12058
  return;
12012
12059
  }
12013
- if (path25 === "/ports/stop" && req.method === "POST") {
12060
+ if (path26 === "/ports/stop" && req.method === "POST") {
12014
12061
  void readBody(req).then((payload) => {
12015
12062
  const box = typeof payload?.box === "string" ? payload.box : void 0;
12016
12063
  const port = typeof payload?.port === "number" ? payload.port : void 0;
@@ -12025,7 +12072,7 @@ var init_src2 = __esm({
12025
12072
  });
12026
12073
  return;
12027
12074
  }
12028
- if (path25 === "/shutdown" && req.method === "POST" && allowShutdown()) {
12075
+ if (path26 === "/shutdown" && req.method === "POST" && allowShutdown()) {
12029
12076
  writeJson(res, 202, { ok: true });
12030
12077
  void close();
12031
12078
  return;
@@ -12098,7 +12145,7 @@ var init_logger2 = __esm({
12098
12145
  });
12099
12146
 
12100
12147
  // src/devbox/controlPlane.ts
12101
- var import_node_http2, import_node_crypto5, import_node_child_process, resolveControlPlaneUrl2, resolveConvexUrl2, openBrowser, requestJson2, startCallbackServer, getControlPlaneUrl, getConvexUrl, signInWithBrowser, spriteTokenGet, spriteTokenSet, spriteDaemonReleaseGet, spriteDaemonTokenIssue, spriteDaemonSessionSummariesList, spriteDaemonSessionsList, withConvexClient, fetchSpriteToken, storeSpriteToken, fetchSpriteDaemonRelease, issueSpriteDaemonToken, listSpriteDaemonSessionSummaries, listSpriteDaemonSessions, signOutControlPlane, refreshControlPlaneSession;
12148
+ var import_node_http2, import_node_crypto5, import_node_child_process, trim, normalizeConvexDeployment2, stripDevPrefix2, resolveFromDeployment2, resolveFromUrl2, resolveControlPlaneUrl2, resolveConvexUrl2, openBrowser, requestJson2, startCallbackServer, getControlPlaneUrl, getConvexUrl, signInWithBrowser, spriteTokenGet, spriteTokenSet, spriteDaemonReleaseGet, spriteDaemonTokenIssue, spriteDaemonSessionSummariesList, spriteDaemonSessionsList, withConvexClient, fetchSpriteToken, storeSpriteToken, fetchSpriteDaemonRelease, issueSpriteDaemonToken, listSpriteDaemonSessionSummaries, listSpriteDaemonSessions, signOutControlPlane, refreshControlPlaneSession;
12102
12149
  var init_controlPlane = __esm({
12103
12150
  "src/devbox/controlPlane.ts"() {
12104
12151
  "use strict";
@@ -12108,11 +12155,52 @@ var init_controlPlane = __esm({
12108
12155
  init_index_node();
12109
12156
  init_server();
12110
12157
  init_logger2();
12158
+ trim = (value) => value.trim().replace(/\r/g, "");
12159
+ normalizeConvexDeployment2 = (value) => {
12160
+ const normalized = trim(value);
12161
+ if (!normalized) return "";
12162
+ if (normalized.includes(":")) {
12163
+ const [prefix, rest] = normalized.split(":", 2);
12164
+ return `${prefix}:${trim(rest ?? "")}`;
12165
+ }
12166
+ return normalized;
12167
+ };
12168
+ stripDevPrefix2 = (value) => {
12169
+ if (value.startsWith("dev:")) {
12170
+ return trim(value.slice(4));
12171
+ }
12172
+ return value;
12173
+ };
12174
+ resolveFromDeployment2 = (deploymentRaw, suffix) => {
12175
+ const deployment = stripDevPrefix2(normalizeConvexDeployment2(deploymentRaw));
12176
+ if (!deployment) return "";
12177
+ if (deployment.includes("://")) {
12178
+ return deployment;
12179
+ }
12180
+ if (deployment.includes(".")) {
12181
+ const host = suffix === "cloud" ? deployment.replace(".convex.site", ".convex.cloud") : deployment.replace(".convex.cloud", ".convex.site");
12182
+ return `https://${host}`;
12183
+ }
12184
+ return `https://${deployment}.convex.${suffix}`;
12185
+ };
12186
+ resolveFromUrl2 = (raw, suffix) => {
12187
+ const value = trim(raw);
12188
+ if (!value) return "";
12189
+ try {
12190
+ const url = new URL(value);
12191
+ const host = suffix === "cloud" ? url.host.replace(".convex.site", ".convex.cloud") : url.host.replace(".convex.cloud", ".convex.site");
12192
+ return `${url.protocol}//${host}`;
12193
+ } catch {
12194
+ return "";
12195
+ }
12196
+ };
12111
12197
  resolveControlPlaneUrl2 = () => {
12112
12198
  const envOverride = process.env.DEVBOX_CONTROL_PLANE_URL ?? process.env.CONVEX_SITE_URL;
12113
12199
  if (envOverride && envOverride.trim().length > 0) {
12114
12200
  return envOverride.trim();
12115
12201
  }
12202
+ const derived = resolveFromDeployment2(process.env.CONVEX_DEPLOYMENT ?? "", "site") || resolveFromUrl2(process.env.VITE_CONVEX_URL ?? "", "site");
12203
+ if (derived) return derived;
12116
12204
  if (false) return null;
12117
12205
  const trimmed = "https://api.boxes.dev".trim();
12118
12206
  return trimmed.length > 0 ? trimmed : null;
@@ -12122,6 +12210,8 @@ var init_controlPlane = __esm({
12122
12210
  if (envOverride && envOverride.trim().length > 0) {
12123
12211
  return envOverride.trim();
12124
12212
  }
12213
+ const derived = resolveFromDeployment2(process.env.CONVEX_DEPLOYMENT ?? "", "cloud") || resolveFromUrl2(process.env.CONVEX_SITE_URL ?? "", "cloud");
12214
+ if (derived) return derived;
12125
12215
  if (false) return null;
12126
12216
  const trimmed = "https://convex.boxes.dev".trim();
12127
12217
  return trimmed.length > 0 ? trimmed : null;
@@ -12151,9 +12241,9 @@ var init_controlPlane = __esm({
12151
12241
  console.log(url);
12152
12242
  }
12153
12243
  };
12154
- requestJson2 = async (baseUrl, method, path25, body, token) => {
12244
+ requestJson2 = async (baseUrl, method, path26, body, token) => {
12155
12245
  const requestId = (0, import_node_crypto5.randomUUID)();
12156
- const url = new URL(path25, baseUrl);
12246
+ const url = new URL(path26, baseUrl);
12157
12247
  const headers = {
12158
12248
  "x-request-id": requestId
12159
12249
  };
@@ -12426,7 +12516,7 @@ var init_controlPlane = __esm({
12426
12516
  });
12427
12517
 
12428
12518
  // src/devbox/daemonClient.ts
12429
- var import_node_http3, import_node_path6, import_node_child_process2, import_node_crypto6, import_promises6, DAEMON_TIMEOUT_MS, DaemonConnectionError, isConnectionError, requestJson3, requireDaemonFeatures, resolveDaemonCommand, spawnDaemon, waitForHealth, listAlternateSocketPaths, pruneDuplicateDaemons, ensureDaemonRunning, waitForSocketGone, stopDaemon;
12519
+ var import_node_http3, import_node_path6, import_node_child_process2, import_node_crypto6, import_node_fs3, import_promises6, DAEMON_TIMEOUT_MS, DaemonConnectionError, isConnectionError, requestJson3, requireDaemonFeatures, resolveDaemonCommand, spawnDaemon, waitForHealth, listAlternateSocketPaths, pruneDuplicateDaemons, ensureDaemonRunning, waitForSocketGone, stopDaemon;
12430
12520
  var init_daemonClient = __esm({
12431
12521
  "src/devbox/daemonClient.ts"() {
12432
12522
  "use strict";
@@ -12434,6 +12524,7 @@ var init_daemonClient = __esm({
12434
12524
  import_node_path6 = __toESM(require("node:path"), 1);
12435
12525
  import_node_child_process2 = require("node:child_process");
12436
12526
  import_node_crypto6 = require("node:crypto");
12527
+ import_node_fs3 = __toESM(require("node:fs"), 1);
12437
12528
  import_promises6 = require("node:fs/promises");
12438
12529
  init_src();
12439
12530
  init_controlPlane();
@@ -12584,11 +12675,20 @@ var init_daemonClient = __esm({
12584
12675
  const command = resolveDaemonCommand();
12585
12676
  const controlPlaneUrl = getControlPlaneUrl();
12586
12677
  const convexUrl = getConvexUrl();
12678
+ const runtimeDir = import_node_path6.default.dirname(socketPath);
12679
+ const logPath = import_node_path6.default.join(runtimeDir, "dvbd.log");
12680
+ let logFd = null;
12681
+ try {
12682
+ logFd = import_node_fs3.default.openSync(logPath, "a");
12683
+ } catch {
12684
+ logFd = null;
12685
+ }
12587
12686
  logger7.info("daemon_spawn", {
12588
12687
  socketPath,
12589
12688
  command: command.command,
12590
12689
  args: command.args,
12591
- source: command.source
12690
+ source: command.source,
12691
+ ...logFd !== null ? { logPath } : {}
12592
12692
  });
12593
12693
  const child = (0, import_node_child_process2.spawn)(command.command, command.args, {
12594
12694
  env: {
@@ -12597,9 +12697,15 @@ var init_daemonClient = __esm({
12597
12697
  ...controlPlaneUrl ? { DEVBOX_CONTROL_PLANE_URL: controlPlaneUrl } : {},
12598
12698
  ...convexUrl ? { DEVBOX_CONVEX_URL: convexUrl } : {}
12599
12699
  },
12600
- stdio: "ignore",
12700
+ stdio: logFd !== null ? ["ignore", logFd, logFd] : "ignore",
12601
12701
  detached: true
12602
12702
  });
12703
+ if (logFd !== null) {
12704
+ try {
12705
+ import_node_fs3.default.closeSync(logFd);
12706
+ } catch {
12707
+ }
12708
+ }
12603
12709
  child.unref();
12604
12710
  };
12605
12711
  waitForHealth = async (socketPath, timeoutMs) => {
@@ -12879,11 +12985,11 @@ ${tokenInstructions()}`
12879
12985
  );
12880
12986
  }
12881
12987
  let controlPlaneToken = await store.getControlPlaneToken();
12882
- const requireControlPlaneToken = options?.requireControlPlaneToken !== false;
12883
- if (!controlPlaneToken && requireControlPlaneToken) {
12988
+ const requireControlPlaneToken2 = options?.requireControlPlaneToken !== false;
12989
+ if (!controlPlaneToken && requireControlPlaneToken2) {
12884
12990
  controlPlaneToken = await ensureControlPlaneToken(store, stage);
12885
12991
  }
12886
- if (controlPlaneToken && requireControlPlaneToken) {
12992
+ if (controlPlaneToken && requireControlPlaneToken2) {
12887
12993
  const expiresAt = await store.getControlPlaneTokenExpiresAt();
12888
12994
  if (shouldRefreshToken2(expiresAt)) {
12889
12995
  try {
@@ -22164,16 +22270,25 @@ var init_registry2 = __esm({
22164
22270
  });
22165
22271
 
22166
22272
  // src/devbox/commands/init/scripts.ts
22167
- var import_promises19, import_node_path14, resolveScriptsDir, loadInitScript;
22273
+ var import_node_fs4, import_promises19, import_node_path14, resolveScriptsDir, loadInitScript;
22168
22274
  var init_scripts = __esm({
22169
22275
  "src/devbox/commands/init/scripts.ts"() {
22170
22276
  "use strict";
22277
+ import_node_fs4 = __toESM(require("node:fs"), 1);
22171
22278
  import_promises19 = __toESM(require("node:fs/promises"), 1);
22172
22279
  import_node_path14 = __toESM(require("node:path"), 1);
22173
22280
  resolveScriptsDir = () => {
22174
- const binPath = process.argv[1];
22175
- if (binPath) {
22176
- return import_node_path14.default.resolve(import_node_path14.default.dirname(binPath), "..", "scripts");
22281
+ const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
22282
+ if (argv1) {
22283
+ try {
22284
+ const real = import_node_fs4.default.realpathSync(argv1);
22285
+ return import_node_path14.default.resolve(import_node_path14.default.dirname(real), "..", "scripts");
22286
+ } catch {
22287
+ }
22288
+ try {
22289
+ return import_node_path14.default.resolve(import_node_path14.default.dirname(argv1), "..", "scripts");
22290
+ } catch {
22291
+ }
22177
22292
  }
22178
22293
  return import_node_path14.default.resolve(process.cwd(), "scripts");
22179
22294
  };
@@ -22263,21 +22378,21 @@ var init_remote = __esm({
22263
22378
  });
22264
22379
  return result;
22265
22380
  };
22266
- writeRemoteFile = async (client, canonical, path25, content, stage) => {
22381
+ writeRemoteFile = async (client, canonical, path26, content, stage) => {
22267
22382
  const requestId = (0, import_node_crypto10.randomUUID)();
22268
22383
  logger8.info("sprites_request", {
22269
22384
  requestId,
22270
22385
  method: "writeFile",
22271
- path: path25,
22386
+ path: path26,
22272
22387
  box: canonical,
22273
22388
  stage
22274
22389
  });
22275
22390
  const buffer = typeof content === "string" ? Buffer.from(content, "utf8") : content;
22276
- await client.writeFile(canonical, path25, buffer);
22391
+ await client.writeFile(canonical, path26, buffer);
22277
22392
  logger8.info("sprites_response", {
22278
22393
  requestId,
22279
22394
  method: "writeFile",
22280
- path: path25,
22395
+ path: path26,
22281
22396
  status: "ok",
22282
22397
  box: canonical,
22283
22398
  stage
@@ -23293,7 +23408,7 @@ var init_ssh = __esm({
23293
23408
  }
23294
23409
  return trimmed.replace(/^\/+/, "");
23295
23410
  };
23296
- buildSshUrl = (host, path25) => `git@${host}:${stripGitSuffix2(path25)}.git`;
23411
+ buildSshUrl = (host, path26) => `git@${host}:${stripGitSuffix2(path26)}.git`;
23297
23412
  buildSettingsUrl = (host) => {
23298
23413
  const lower = host.toLowerCase();
23299
23414
  if (lower.includes("gitlab")) {
@@ -23306,12 +23421,12 @@ var init_ssh = __esm({
23306
23421
  const withoutUser = trimmed.startsWith("git@") ? trimmed.slice("git@".length) : trimmed;
23307
23422
  const [host, pathPart] = withoutUser.split(":");
23308
23423
  if (!host || !pathPart) return null;
23309
- const path25 = stripGitSuffix2(pathPart);
23424
+ const path26 = stripGitSuffix2(pathPart);
23310
23425
  return {
23311
23426
  host: host.toLowerCase(),
23312
- path: path25,
23427
+ path: path26,
23313
23428
  protocol: "ssh",
23314
- sshUrl: buildSshUrl(host, path25),
23429
+ sshUrl: buildSshUrl(host, path26),
23315
23430
  settingsUrl: buildSettingsUrl(host)
23316
23431
  };
23317
23432
  };
@@ -23328,13 +23443,13 @@ var init_ssh = __esm({
23328
23443
  try {
23329
23444
  const url = new URL(trimmed);
23330
23445
  const host = url.hostname;
23331
- const path25 = stripGitSuffix2(url.pathname);
23332
- if (!host || !path25) return null;
23446
+ const path26 = stripGitSuffix2(url.pathname);
23447
+ if (!host || !path26) return null;
23333
23448
  return {
23334
23449
  host: host.toLowerCase(),
23335
- path: path25,
23450
+ path: path26,
23336
23451
  protocol: "ssh",
23337
- sshUrl: buildSshUrl(host, path25),
23452
+ sshUrl: buildSshUrl(host, path26),
23338
23453
  settingsUrl: buildSettingsUrl(host)
23339
23454
  };
23340
23455
  } catch {
@@ -23345,13 +23460,13 @@ var init_ssh = __esm({
23345
23460
  try {
23346
23461
  const url = new URL(trimmed);
23347
23462
  const host = url.hostname;
23348
- const path25 = stripGitSuffix2(url.pathname);
23349
- if (!host || !path25) return null;
23463
+ const path26 = stripGitSuffix2(url.pathname);
23464
+ if (!host || !path26) return null;
23350
23465
  return {
23351
23466
  host: host.toLowerCase(),
23352
- path: path25,
23467
+ path: path26,
23353
23468
  protocol: "https",
23354
- sshUrl: buildSshUrl(host, path25),
23469
+ sshUrl: buildSshUrl(host, path26),
23355
23470
  settingsUrl: buildSettingsUrl(host)
23356
23471
  };
23357
23472
  } catch {
@@ -24613,12 +24728,12 @@ ${bottom}
24613
24728
  });
24614
24729
 
24615
24730
  // src/devbox/commands/init/codex/local.ts
24616
- var import_node_child_process9, import_node_fs3, import_promises25, import_node_path19, stripAnsi3, extractBoldText2, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
24731
+ var import_node_child_process9, import_node_fs5, import_promises25, import_node_path19, stripAnsi3, extractBoldText2, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
24617
24732
  var init_local = __esm({
24618
24733
  "src/devbox/commands/init/codex/local.ts"() {
24619
24734
  "use strict";
24620
24735
  import_node_child_process9 = require("node:child_process");
24621
- import_node_fs3 = require("node:fs");
24736
+ import_node_fs5 = require("node:fs");
24622
24737
  import_promises25 = __toESM(require("node:fs/promises"), 1);
24623
24738
  import_node_path19 = __toESM(require("node:path"), 1);
24624
24739
  init_dist2();
@@ -24637,11 +24752,11 @@ var init_local = __esm({
24637
24752
  try {
24638
24753
  if (stdoutLogPath) {
24639
24754
  await import_promises25.default.mkdir(import_node_path19.default.dirname(stdoutLogPath), { recursive: true });
24640
- stdoutStream = (0, import_node_fs3.createWriteStream)(stdoutLogPath, { flags: "a" });
24755
+ stdoutStream = (0, import_node_fs5.createWriteStream)(stdoutLogPath, { flags: "a" });
24641
24756
  }
24642
24757
  if (stderrLogPath) {
24643
24758
  await import_promises25.default.mkdir(import_node_path19.default.dirname(stderrLogPath), { recursive: true });
24644
- stderrStream = (0, import_node_fs3.createWriteStream)(stderrLogPath, { flags: "a" });
24759
+ stderrStream = (0, import_node_fs5.createWriteStream)(stderrLogPath, { flags: "a" });
24645
24760
  }
24646
24761
  } catch {
24647
24762
  stdoutStream = null;
@@ -30485,11 +30600,11 @@ var init_services = __esm({
30485
30600
  };
30486
30601
  loadConfigFromSprite = async (client, canonical) => {
30487
30602
  const workdir = await resolveProjectWorkdir(client, canonical);
30488
- const path25 = workdir ? `${workdir.replace(/\/$/, "")}/devbox.toml` : null;
30603
+ const path26 = workdir ? `${workdir.replace(/\/$/, "")}/devbox.toml` : null;
30489
30604
  if (!workdir) {
30490
30605
  return {
30491
30606
  workdir: null,
30492
- path: path25,
30607
+ path: path26,
30493
30608
  content: null,
30494
30609
  services: {},
30495
30610
  missing: true,
@@ -30504,7 +30619,7 @@ var init_services = __esm({
30504
30619
  const content = Buffer.from(bytes).toString("utf8");
30505
30620
  return {
30506
30621
  workdir,
30507
- path: path25,
30622
+ path: path26,
30508
30623
  content,
30509
30624
  services: parseServicesToml(content),
30510
30625
  missing: false
@@ -30513,7 +30628,7 @@ var init_services = __esm({
30513
30628
  if (error instanceof SpritesApiError && error.status === 404) {
30514
30629
  return {
30515
30630
  workdir,
30516
- path: path25,
30631
+ path: path26,
30517
30632
  content: null,
30518
30633
  services: {},
30519
30634
  missing: true
@@ -30521,7 +30636,7 @@ var init_services = __esm({
30521
30636
  }
30522
30637
  return {
30523
30638
  workdir,
30524
- path: path25,
30639
+ path: path26,
30525
30640
  content: null,
30526
30641
  services: {},
30527
30642
  missing: false,
@@ -30993,8 +31108,144 @@ var init_setup = __esm({
30993
31108
  }
30994
31109
  });
30995
31110
 
31111
+ // src/devbox/commands/version.ts
31112
+ var import_node_module, import_node_path24, parseVersionArgs, readPackageVersion, tryReadDaemonInfo, runVersion;
31113
+ var init_version = __esm({
31114
+ "src/devbox/commands/version.ts"() {
31115
+ "use strict";
31116
+ import_node_module = require("node:module");
31117
+ import_node_path24 = __toESM(require("node:path"), 1);
31118
+ init_src();
31119
+ init_src();
31120
+ init_controlPlane();
31121
+ init_daemonClient();
31122
+ parseVersionArgs = (args) => {
31123
+ const parsed = { json: false };
31124
+ for (const arg of args) {
31125
+ if (!arg) continue;
31126
+ if (arg === "--json") {
31127
+ parsed.json = true;
31128
+ continue;
31129
+ }
31130
+ if (arg === "--help" || arg === "-h") {
31131
+ throw new Error("help_requested");
31132
+ }
31133
+ if (arg.startsWith("-")) {
31134
+ throw new Error(`Unknown version flag: ${arg}`);
31135
+ }
31136
+ throw new Error(`Unexpected argument: ${arg}`);
31137
+ }
31138
+ return parsed;
31139
+ };
31140
+ readPackageVersion = () => {
31141
+ const fromArgv = typeof process.argv[1] === "string" ? process.argv[1] : "";
31142
+ const from = fromArgv ? import_node_path24.default.resolve(fromArgv) : import_node_path24.default.join(process.cwd(), "dvb");
31143
+ const require3 = (0, import_node_module.createRequire)(from);
31144
+ try {
31145
+ const pkg = require3("@boxes-dev/dvb/package.json");
31146
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
31147
+ } catch {
31148
+ return "unknown";
31149
+ }
31150
+ };
31151
+ tryReadDaemonInfo = async (socketPath) => {
31152
+ try {
31153
+ const health = await requestJson3(
31154
+ socketPath,
31155
+ "GET",
31156
+ "/health",
31157
+ DAEMON_TIMEOUT_MS.health
31158
+ );
31159
+ if (health.status !== 200 || !health.body.ok) return null;
31160
+ const version2 = await requestJson3(
31161
+ socketPath,
31162
+ "GET",
31163
+ "/version",
31164
+ DAEMON_TIMEOUT_MS.quick
31165
+ );
31166
+ return {
31167
+ health: health.body,
31168
+ version: version2.status === 200 ? version2.body : null
31169
+ };
31170
+ } catch {
31171
+ return null;
31172
+ }
31173
+ };
31174
+ runVersion = async (args) => {
31175
+ const parsed = parseVersionArgs(args);
31176
+ const dvbVersion = readPackageVersion();
31177
+ const nodeVersion = process.versions.node;
31178
+ const controlPlaneUrl = getControlPlaneUrl();
31179
+ const convexUrl = getConvexUrl();
31180
+ const homeDir = process.env.HOME?.trim();
31181
+ const config = await loadConfig(homeDir ? { homeDir } : void 0);
31182
+ const store = await createSecretStore(
31183
+ config?.tokenStore,
31184
+ homeDir ? { homeDir } : void 0
31185
+ );
31186
+ const spritesTokenPresent = Boolean(await store.getToken());
31187
+ const controlPlaneTokenPresent = Boolean(await store.getControlPlaneToken());
31188
+ const controlPlaneRefreshTokenPresent = Boolean(
31189
+ await store.getControlPlaneRefreshToken()
31190
+ );
31191
+ const socketInfo = resolveSocketInfo();
31192
+ const daemon = await tryReadDaemonInfo(socketInfo.socketPath);
31193
+ if (parsed.json) {
31194
+ console.log(
31195
+ JSON.stringify(
31196
+ {
31197
+ dvb: { version: dvbVersion },
31198
+ node: { version: nodeVersion },
31199
+ auth: {
31200
+ spritesToken: spritesTokenPresent,
31201
+ controlPlaneToken: controlPlaneTokenPresent,
31202
+ controlPlaneRefreshToken: controlPlaneRefreshTokenPresent
31203
+ },
31204
+ config: {
31205
+ controlPlaneUrl,
31206
+ convexUrl,
31207
+ socketPath: socketInfo.socketPath
31208
+ },
31209
+ dvbd: daemon ? {
31210
+ pid: daemon.health.pid,
31211
+ startedAt: daemon.health.startedAt,
31212
+ apiVersion: daemon.version?.apiVersion ?? null,
31213
+ features: daemon.version?.features ?? null
31214
+ } : null
31215
+ },
31216
+ null,
31217
+ 2
31218
+ )
31219
+ );
31220
+ return;
31221
+ }
31222
+ console.log(`dvb ${dvbVersion}`);
31223
+ console.log(`node ${nodeVersion}`);
31224
+ console.log(`control plane: ${controlPlaneUrl ?? "(not set/embedded)"}`);
31225
+ console.log(`convex: ${convexUrl ?? "(not set/embedded)"}`);
31226
+ console.log(
31227
+ `auth: sprites=${spritesTokenPresent ? "ok" : "missing"} control_plane=${controlPlaneTokenPresent ? "ok" : "missing"}`
31228
+ );
31229
+ console.log(`socket: ${socketInfo.socketPath}`);
31230
+ if (daemon) {
31231
+ const apiVersion = daemon.version?.apiVersion;
31232
+ const features = Array.isArray(daemon.version?.features) ? daemon.version?.features.join(", ") : "";
31233
+ console.log(`dvbd: running (pid ${daemon.health.pid})`);
31234
+ if (typeof apiVersion === "number") {
31235
+ console.log(`dvbd api: ${apiVersion}`);
31236
+ }
31237
+ if (features) {
31238
+ console.log(`dvbd features: ${features}`);
31239
+ }
31240
+ } else {
31241
+ console.log("dvbd: not running");
31242
+ }
31243
+ };
31244
+ }
31245
+ });
31246
+
30996
31247
  // src/devbox/commands/wezterm.ts
30997
- var import_node_crypto13, import_node_child_process11, import_promises31, import_node_os10, import_node_path24, import_promises32, logger10, WEZTERM_APP_PATH, WEZTERM_BIN_PATH, WEZTERM_BIN_DIR, WEZTERM_INSTALL_URL, WEZTERM_PATH_EXPORT, WEZTERM_HEALTH_POLL_INTERVAL_MS, WEZTERM_HEALTH_POLL_TIMEOUT_MS, WEZTERM_PROXY_BASE_ENV, WEZTERM_PROXY_LOG_NAME, WEZTERM_USAGE, parseWeztermArgs, resolveCanonical3, initWeztermClient, waitForWeztermMuxHealthy, ensureWeztermMuxReady, runWeztermProxy, runCommand6, promptYesNo2, fileExists, hasWeztermOnPath, resolveShellProfilePath, ensureWeztermOnPath, ensureWeztermInstalled, expandPath, resolveDefaultConfigPath, escapeRegExp, resolveCliName2, resolveDvbCommand, formatLuaArgs, resolveWeztermProxyEnv, buildProxyCommand, buildDomainBlock, canAppendToConfig, countReturns, applyReturnTableTransform, insertBlock, runWeztermSetup, startWeztermDomain, runWezterm;
31248
+ var import_node_crypto13, import_node_child_process11, import_promises31, import_node_os10, import_node_path25, import_promises32, logger10, WEZTERM_APP_PATH, WEZTERM_BIN_PATH, WEZTERM_BIN_DIR, WEZTERM_INSTALL_URL, WEZTERM_PATH_EXPORT, WEZTERM_HEALTH_POLL_INTERVAL_MS, WEZTERM_HEALTH_POLL_TIMEOUT_MS, WEZTERM_PROXY_BASE_ENV, WEZTERM_PROXY_LOG_NAME, WEZTERM_USAGE, parseWeztermArgs, resolveCanonical3, initWeztermClient, waitForWeztermMuxHealthy, ensureWeztermMuxReady, runWeztermProxy, runCommand6, promptYesNo2, fileExists, hasWeztermOnPath, resolveShellProfilePath, ensureWeztermOnPath, ensureWeztermInstalled, expandPath, resolveDefaultConfigPath, escapeRegExp, resolveCliName2, resolveDvbCommand, formatLuaArgs, resolveWeztermProxyEnv, buildProxyCommand, buildDomainBlock, canAppendToConfig, countReturns, applyReturnTableTransform, insertBlock, runWeztermSetup, startWeztermDomain, runWezterm;
30998
31249
  var init_wezterm = __esm({
30999
31250
  "src/devbox/commands/wezterm.ts"() {
31000
31251
  "use strict";
@@ -31002,7 +31253,7 @@ var init_wezterm = __esm({
31002
31253
  import_node_child_process11 = require("node:child_process");
31003
31254
  import_promises31 = __toESM(require("node:fs/promises"), 1);
31004
31255
  import_node_os10 = __toESM(require("node:os"), 1);
31005
- import_node_path24 = __toESM(require("node:path"), 1);
31256
+ import_node_path25 = __toESM(require("node:path"), 1);
31006
31257
  import_promises32 = __toESM(require("node:readline/promises"), 1);
31007
31258
  init_src();
31008
31259
  init_daemonClient();
@@ -31194,11 +31445,11 @@ var init_wezterm = __esm({
31194
31445
  const homeDir = import_node_os10.default.homedir();
31195
31446
  if (!homeDir) return;
31196
31447
  try {
31197
- const logDir = import_node_path24.default.join(resolveDevboxDir(homeDir), "wezterm");
31448
+ const logDir = import_node_path25.default.join(resolveDevboxDir(homeDir), "wezterm");
31198
31449
  await import_promises31.default.mkdir(logDir, { recursive: true });
31199
31450
  const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${message}
31200
31451
  `;
31201
- await import_promises31.default.appendFile(import_node_path24.default.join(logDir, WEZTERM_PROXY_LOG_NAME), line, "utf8");
31452
+ await import_promises31.default.appendFile(import_node_path25.default.join(logDir, WEZTERM_PROXY_LOG_NAME), line, "utf8");
31202
31453
  } catch {
31203
31454
  }
31204
31455
  };
@@ -31441,16 +31692,16 @@ var init_wezterm = __esm({
31441
31692
  }
31442
31693
  const shell = process.env.SHELL ?? "";
31443
31694
  if (shell.includes("zsh")) {
31444
- return import_node_path24.default.join(homeDir, ".zshrc");
31695
+ return import_node_path25.default.join(homeDir, ".zshrc");
31445
31696
  }
31446
31697
  if (shell.includes("bash")) {
31447
- const profile = import_node_path24.default.join(homeDir, ".bash_profile");
31698
+ const profile = import_node_path25.default.join(homeDir, ".bash_profile");
31448
31699
  if (await fileExists(profile)) {
31449
31700
  return profile;
31450
31701
  }
31451
- return import_node_path24.default.join(homeDir, ".bashrc");
31702
+ return import_node_path25.default.join(homeDir, ".bashrc");
31452
31703
  }
31453
- return import_node_path24.default.join(homeDir, ".profile");
31704
+ return import_node_path25.default.join(homeDir, ".profile");
31454
31705
  };
31455
31706
  ensureWeztermOnPath = async () => {
31456
31707
  if (await hasWeztermOnPath()) {
@@ -31507,7 +31758,7 @@ ${content ? "\n" : ""}${WEZTERM_PATH_EXPORT}
31507
31758
  expandPath = (value) => {
31508
31759
  if (value.startsWith("~/")) {
31509
31760
  const homeDir = process.env.HOME ?? "";
31510
- return homeDir ? import_node_path24.default.join(homeDir, value.slice(2)) : value;
31761
+ return homeDir ? import_node_path25.default.join(homeDir, value.slice(2)) : value;
31511
31762
  }
31512
31763
  return value;
31513
31764
  };
@@ -31517,8 +31768,8 @@ ${content ? "\n" : ""}${WEZTERM_PATH_EXPORT}
31517
31768
  throw new Error("HOME is not set; pass --path to wezterm setup.");
31518
31769
  }
31519
31770
  const candidates = [
31520
- import_node_path24.default.join(homeDir, ".wezterm.lua"),
31521
- import_node_path24.default.join(homeDir, ".config", "wezterm", "wezterm.lua")
31771
+ import_node_path25.default.join(homeDir, ".wezterm.lua"),
31772
+ import_node_path25.default.join(homeDir, ".config", "wezterm", "wezterm.lua")
31522
31773
  ];
31523
31774
  for (const candidate of candidates) {
31524
31775
  try {
@@ -31539,7 +31790,7 @@ ${content ? "\n" : ""}${WEZTERM_PATH_EXPORT}
31539
31790
  resolveDvbCommand = async () => {
31540
31791
  const scriptPath = process.argv[1];
31541
31792
  if (scriptPath) {
31542
- const candidate = import_node_path24.default.isAbsolute(scriptPath) ? scriptPath : import_node_path24.default.resolve(process.cwd(), scriptPath);
31793
+ const candidate = import_node_path25.default.isAbsolute(scriptPath) ? scriptPath : import_node_path25.default.resolve(process.cwd(), scriptPath);
31543
31794
  try {
31544
31795
  await import_promises31.default.access(candidate);
31545
31796
  return [process.execPath, candidate];
@@ -31679,7 +31930,7 @@ ${block}`;
31679
31930
  }
31680
31931
  }
31681
31932
  if (updated) {
31682
- await import_promises31.default.mkdir(import_node_path24.default.dirname(configPath), { recursive: true });
31933
+ await import_promises31.default.mkdir(import_node_path25.default.dirname(configPath), { recursive: true });
31683
31934
  await import_promises31.default.writeFile(configPath, nextContent, "utf8");
31684
31935
  console.log(`Updated WezTerm config: ${configPath}`);
31685
31936
  } else {
@@ -31780,10 +32031,12 @@ var init_cli = __esm({
31780
32031
  init_sessions2();
31781
32032
  init_services();
31782
32033
  init_setup();
32034
+ init_version();
31783
32035
  init_wezterm();
31784
32036
  init_completions();
31785
32037
  printUsage = () => {
31786
32038
  console.log("Usage:");
32039
+ console.log(" dvb --version");
31787
32040
  console.log(" dvb setup [--token <token>] [--org <slug>]");
31788
32041
  console.log(" [--api-base-url <url>] [--no-verify] [--json]");
31789
32042
  console.log(" dvb logout [--json]");
@@ -31836,6 +32089,7 @@ var init_cli = __esm({
31836
32089
  console.log(
31837
32090
  " dvb wezterm [<box>] [--port <port>] [--domain <name>] [--path <path>]"
31838
32091
  );
32092
+ console.log(" dvb version [--json]");
31839
32093
  };
31840
32094
  main2 = async () => {
31841
32095
  const args = process.argv.slice(2);
@@ -31843,9 +32097,25 @@ var init_cli = __esm({
31843
32097
  printUsage();
31844
32098
  return;
31845
32099
  }
32100
+ if (args[0] === "--version") {
32101
+ await runVersion([]);
32102
+ return;
32103
+ }
31846
32104
  if (args[0] !== "complete" && args[0] !== "completions") {
31847
32105
  await maybeAutoUpdateCompletions();
31848
32106
  }
32107
+ if (args[0] === "version") {
32108
+ try {
32109
+ await runVersion(args.slice(1));
32110
+ } catch (error) {
32111
+ if (error instanceof Error && error.message === "help_requested") {
32112
+ printUsage();
32113
+ return;
32114
+ }
32115
+ throw error;
32116
+ }
32117
+ return;
32118
+ }
31849
32119
  if (args[0] === "setup") {
31850
32120
  await runSetup(args.slice(1));
31851
32121
  return;
@@ -31929,9 +32199,9 @@ var init_cli = __esm({
31929
32199
  });
31930
32200
 
31931
32201
  // src/bin/dvb.ts
31932
- var import_node_fs4 = __toESM(require("node:fs"), 1);
32202
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
31933
32203
  var import_node_os11 = __toESM(require("node:os"), 1);
31934
- var import_node_path25 = __toESM(require("node:path"), 1);
32204
+ var import_node_path26 = __toESM(require("node:path"), 1);
31935
32205
  init_src();
31936
32206
  var MIN_NODE_MAJOR = 24;
31937
32207
  var assertNodeVersion = () => {
@@ -31986,10 +32256,10 @@ run().catch((error) => {
31986
32256
  const homeDir = import_node_os11.default.homedir();
31987
32257
  if (homeDir) {
31988
32258
  try {
31989
- const logDir = import_node_path25.default.join(resolveDevboxDir(homeDir), "wezterm");
31990
- import_node_fs4.default.mkdirSync(logDir, { recursive: true });
31991
- import_node_fs4.default.appendFileSync(
31992
- import_node_path25.default.join(logDir, "proxy.log"),
32259
+ const logDir = import_node_path26.default.join(resolveDevboxDir(homeDir), "wezterm");
32260
+ import_node_fs6.default.mkdirSync(logDir, { recursive: true });
32261
+ import_node_fs6.default.appendFileSync(
32262
+ import_node_path26.default.join(logDir, "proxy.log"),
31993
32263
  `${(/* @__PURE__ */ new Date()).toISOString()} ${message}
31994
32264
  `
31995
32265
  );