@boxes-dev/dvb 0.2.45 → 0.2.46

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
@@ -423,7 +423,7 @@ var init_repo = __esm({
423
423
  });
424
424
 
425
425
  // ../core/src/sprites.ts
426
- var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
426
+ var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT, DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS, SPRITES_HTTP_RETRYABLE_STATUSES, delay, isIdempotentMethod, computeRetryDelayMs, isAbortError, getErrorCode, isRetryableFetchError, shouldRetrySpritesRequest, withSpritesRetry, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
427
427
  var init_sprites = __esm({
428
428
  "../core/src/sprites.ts"() {
429
429
  "use strict";
@@ -491,39 +491,126 @@ var init_sprites = __esm({
491
491
  return new URL(path26, `${protocol}//${base.host}`);
492
492
  };
493
493
  shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
494
- requestJson = async (apiBaseUrl, token, method, path26, body) => {
495
- const requestId = (0, import_node_crypto.randomUUID)();
496
- const url = new URL(path26, apiBaseUrl);
497
- const headers = {
498
- authorization: `Bearer ${token}`,
499
- "x-request-id": requestId
500
- };
501
- if (body) {
502
- headers["content-type"] = "application/json";
503
- }
504
- const init = { method, headers };
505
- if (body) {
506
- init.body = JSON.stringify(body);
494
+ DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT = 5e3;
495
+ DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT = 2e4;
496
+ DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS = 5;
497
+ SPRITES_HTTP_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 409, 425, 429, 500, 502, 503, 504]);
498
+ delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
499
+ isIdempotentMethod = (method) => {
500
+ const normalized = method.toUpperCase();
501
+ return normalized === "GET" || normalized === "HEAD" || normalized === "PUT" || normalized === "DELETE" || normalized === "OPTIONS";
502
+ };
503
+ computeRetryDelayMs = (attempt) => {
504
+ const base = 250;
505
+ const cap = 2500;
506
+ const exp = Math.min(cap, base * 2 ** Math.max(0, attempt - 1));
507
+ const jitter = Math.floor(Math.random() * 120);
508
+ return exp + jitter;
509
+ };
510
+ isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
511
+ getErrorCode = (error) => {
512
+ if (!error || typeof error !== "object") return void 0;
513
+ const record = error;
514
+ const code2 = record.code;
515
+ return typeof code2 === "string" || typeof code2 === "number" ? String(code2) : void 0;
516
+ };
517
+ isRetryableFetchError = (error) => {
518
+ if (isAbortError(error)) return true;
519
+ if (error instanceof TypeError) return true;
520
+ const code2 = getErrorCode(error);
521
+ return code2 === "ECONNRESET" || code2 === "ETIMEDOUT" || code2 === "EAI_AGAIN" || code2 === "ENOTFOUND" || code2 === "ECONNREFUSED";
522
+ };
523
+ shouldRetrySpritesRequest = (method, error) => {
524
+ if (!isIdempotentMethod(method)) return false;
525
+ if (error instanceof SpritesApiError) {
526
+ return SPRITES_HTTP_RETRYABLE_STATUSES.has(error.status);
527
+ }
528
+ return isRetryableFetchError(error);
529
+ };
530
+ withSpritesRetry = async (options) => {
531
+ const opId = (0, import_node_crypto.randomUUID)();
532
+ const timeoutMs = options.timeoutMs ?? (isIdempotentMethod(options.method) ? DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT : DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT);
533
+ const maxAttemptsRaw = options.maxAttempts ?? DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS;
534
+ const maxAttempts = isIdempotentMethod(options.method) ? Math.max(1, maxAttemptsRaw) : 1;
535
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
536
+ const requestId = (0, import_node_crypto.randomUUID)();
537
+ const controller = new AbortController();
538
+ const timeoutHandle = typeof timeoutMs === "number" && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
539
+ try {
540
+ logger.info("sprites_request", {
541
+ opId,
542
+ attempt,
543
+ requestId,
544
+ method: options.method,
545
+ path: options.path,
546
+ timeoutMs
547
+ });
548
+ return await options.run(controller.signal, requestId);
549
+ } catch (error) {
550
+ const retryable = shouldRetrySpritesRequest(options.method, error);
551
+ const remaining = maxAttempts - attempt;
552
+ if (!retryable || remaining <= 0) {
553
+ throw error;
554
+ }
555
+ const delayMs = computeRetryDelayMs(attempt);
556
+ logger.warn("sprites_http_retry", {
557
+ opId,
558
+ attempt,
559
+ requestId,
560
+ method: options.method,
561
+ path: options.path,
562
+ timeoutMs,
563
+ delayMs,
564
+ remainingAttempts: remaining,
565
+ errorName: error instanceof Error ? error.name : void 0,
566
+ errorMessage: error instanceof Error ? error.message : String(error),
567
+ errorCode: getErrorCode(error),
568
+ ...error instanceof SpritesApiError ? { status: error.status } : {}
569
+ });
570
+ await delay(delayMs);
571
+ } finally {
572
+ if (timeoutHandle) clearTimeout(timeoutHandle);
573
+ }
507
574
  }
508
- logger.info("sprites_request", { requestId, method, path: path26 });
509
- const response = await fetch(url, init);
510
- const text = await response.text();
511
- logger.info("sprites_response", {
512
- requestId,
575
+ throw new Error(`Sprites request failed: ${options.method} ${options.path}`);
576
+ };
577
+ requestJson = async (apiBaseUrl, token, method, path26, body) => {
578
+ return await withSpritesRetry({
513
579
  method,
514
580
  path: path26,
515
- status: response.status
581
+ run: async (signal, requestId) => {
582
+ const url = new URL(path26, apiBaseUrl);
583
+ const headers = {
584
+ authorization: `Bearer ${token}`,
585
+ "x-request-id": requestId
586
+ };
587
+ if (body) {
588
+ headers["content-type"] = "application/json";
589
+ }
590
+ const init = { method, headers, signal };
591
+ if (body) {
592
+ init.body = JSON.stringify(body);
593
+ }
594
+ const response = await fetch(url, init);
595
+ const text = await response.text();
596
+ logger.info("sprites_response", {
597
+ requestId,
598
+ method,
599
+ path: path26,
600
+ status: response.status
601
+ });
602
+ if (!response.ok) {
603
+ const snippet = text.trim().slice(0, 200);
604
+ throw new SpritesApiError(response.status, method, path26, snippet);
605
+ }
606
+ if (!text) return null;
607
+ try {
608
+ return JSON.parse(text);
609
+ } catch {
610
+ return text;
611
+ }
612
+ }
516
613
  });
517
- if (!response.ok) {
518
- const snippet = text.trim().slice(0, 200);
519
- throw new SpritesApiError(response.status, method, path26, snippet);
520
- }
521
- if (!text) return null;
522
- try {
523
- return JSON.parse(text);
524
- } catch {
525
- return text;
526
- }
527
614
  };
528
615
  listSprites = async (apiBaseUrl, token, options) => {
529
616
  const params = new URLSearchParams();
@@ -564,88 +651,99 @@ var init_sprites = __esm({
564
651
  return response;
565
652
  };
566
653
  requestNdjson = async (apiBaseUrl, token, method, path26, body) => {
567
- const requestId = (0, import_node_crypto.randomUUID)();
568
- const url = new URL(path26, apiBaseUrl);
569
- const headers = {
570
- authorization: `Bearer ${token}`,
571
- "x-request-id": requestId
572
- };
573
- if (body) {
574
- headers["content-type"] = "application/json";
575
- }
576
- const init = { method, headers };
577
- if (body) {
578
- init.body = JSON.stringify(body);
579
- }
580
- logger.info("sprites_request", { requestId, method, path: path26 });
581
- const response = await fetch(url, init);
582
- logger.info("sprites_response", {
583
- requestId,
654
+ return await withSpritesRetry({
584
655
  method,
585
656
  path: path26,
586
- status: response.status
587
- });
588
- const text = await response.text();
589
- if (!response.ok) {
590
- const snippet = text.trim().slice(0, 200);
591
- throw new SpritesApiError(response.status, method, path26, snippet);
592
- }
593
- const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
594
- const events = [];
595
- for (const line of lines) {
596
- try {
597
- const parsed = JSON.parse(line);
598
- if (Array.isArray(parsed)) {
599
- for (const entry of parsed) {
600
- if (entry && typeof entry === "object") {
601
- events.push(entry);
602
- } else {
603
- events.push({ value: entry });
657
+ run: async (signal, requestId) => {
658
+ const url = new URL(path26, apiBaseUrl);
659
+ const headers = {
660
+ authorization: `Bearer ${token}`,
661
+ "x-request-id": requestId
662
+ };
663
+ if (body) {
664
+ headers["content-type"] = "application/json";
665
+ }
666
+ const init = { method, headers, signal };
667
+ if (body) {
668
+ init.body = JSON.stringify(body);
669
+ }
670
+ const response = await fetch(url, init);
671
+ logger.info("sprites_response", {
672
+ requestId,
673
+ method,
674
+ path: path26,
675
+ status: response.status
676
+ });
677
+ const text = await response.text();
678
+ if (!response.ok) {
679
+ const snippet = text.trim().slice(0, 200);
680
+ throw new SpritesApiError(response.status, method, path26, snippet);
681
+ }
682
+ const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
683
+ const events = [];
684
+ for (const line of lines) {
685
+ try {
686
+ const parsed = JSON.parse(line);
687
+ if (Array.isArray(parsed)) {
688
+ for (const entry of parsed) {
689
+ if (entry && typeof entry === "object") {
690
+ events.push(entry);
691
+ } else {
692
+ events.push({ value: entry });
693
+ }
694
+ }
695
+ continue;
696
+ }
697
+ if (parsed && typeof parsed === "object") {
698
+ events.push(parsed);
699
+ continue;
604
700
  }
701
+ events.push({ value: parsed });
702
+ } catch {
703
+ events.push({ raw: line });
605
704
  }
606
- continue;
607
705
  }
608
- if (parsed && typeof parsed === "object") {
609
- events.push(parsed);
610
- continue;
611
- }
612
- events.push({ value: parsed });
613
- } catch {
614
- events.push({ raw: line });
706
+ return events;
615
707
  }
616
- }
617
- return events;
708
+ });
618
709
  };
619
710
  writeFile = async (apiBaseUrl, token, name, remotePath, data) => {
620
- const requestId = (0, import_node_crypto.randomUUID)();
621
711
  const path26 = `/v1/sprites/${name}/fs/write`;
622
712
  const url = new URL(path26, apiBaseUrl);
623
713
  url.searchParams.set("path", remotePath);
624
714
  url.searchParams.set("mkdir", "true");
625
- logger.info("sprites_fs_write", {
626
- requestId,
627
- path: path26,
628
- name,
629
- remotePath,
630
- size: data.length
631
- });
632
- const response = await fetch(url, {
715
+ await withSpritesRetry({
633
716
  method: "PUT",
634
- headers: {
635
- authorization: `Bearer ${token}`,
636
- "content-type": "application/octet-stream",
637
- "x-request-id": requestId
638
- },
639
- body: data
640
- });
641
- logger.info("sprites_fs_write_response", {
642
- requestId,
643
717
  path: path26,
644
- status: response.status
718
+ run: async (signal, requestId) => {
719
+ logger.info("sprites_fs_write", {
720
+ requestId,
721
+ path: path26,
722
+ name,
723
+ remotePath,
724
+ size: data.length
725
+ });
726
+ const response = await fetch(url, {
727
+ method: "PUT",
728
+ headers: {
729
+ authorization: `Bearer ${token}`,
730
+ "content-type": "application/octet-stream",
731
+ "x-request-id": requestId
732
+ },
733
+ body: data,
734
+ signal
735
+ });
736
+ logger.info("sprites_fs_write_response", {
737
+ requestId,
738
+ path: path26,
739
+ status: response.status
740
+ });
741
+ if (!response.ok) {
742
+ const snippet = (await response.text()).trim().slice(0, 200);
743
+ throw new SpritesApiError(response.status, "PUT", path26, snippet);
744
+ }
745
+ }
645
746
  });
646
- if (!response.ok) {
647
- throw new Error(`Sprites FS write failed: ${response.status}`);
648
- }
649
747
  };
650
748
  normalizeServiceRecord = (entry) => {
651
749
  const rawName = entry.name;
@@ -676,38 +774,44 @@ var init_sprites = __esm({
676
774
  return service;
677
775
  };
678
776
  readFile = async (apiBaseUrl, token, name, options) => {
679
- const requestId = (0, import_node_crypto.randomUUID)();
680
777
  const path26 = `/v1/sprites/${name}/fs/read`;
681
778
  const url = new URL(path26, apiBaseUrl);
682
779
  url.searchParams.set("path", options.path);
683
780
  if (options.workingDir) {
684
781
  url.searchParams.set("workingDir", options.workingDir);
685
782
  }
686
- logger.info("sprites_fs_read", {
687
- requestId,
688
- path: path26,
689
- name,
690
- remotePath: options.path,
691
- workingDir: options.workingDir
692
- });
693
- const response = await fetch(url, {
783
+ return await withSpritesRetry({
694
784
  method: "GET",
695
- headers: {
696
- authorization: `Bearer ${token}`,
697
- "x-request-id": requestId
698
- }
699
- });
700
- logger.info("sprites_fs_read_response", {
701
- requestId,
702
785
  path: path26,
703
- status: response.status
786
+ run: async (signal, requestId) => {
787
+ logger.info("sprites_fs_read", {
788
+ requestId,
789
+ path: path26,
790
+ name,
791
+ remotePath: options.path,
792
+ workingDir: options.workingDir
793
+ });
794
+ const response = await fetch(url, {
795
+ method: "GET",
796
+ headers: {
797
+ authorization: `Bearer ${token}`,
798
+ "x-request-id": requestId
799
+ },
800
+ signal
801
+ });
802
+ logger.info("sprites_fs_read_response", {
803
+ requestId,
804
+ path: path26,
805
+ status: response.status
806
+ });
807
+ if (!response.ok) {
808
+ const snippet = (await response.text()).trim().slice(0, 200);
809
+ throw new SpritesApiError(response.status, "GET", path26, snippet);
810
+ }
811
+ const buffer = await response.arrayBuffer();
812
+ return new Uint8Array(buffer);
813
+ }
704
814
  });
705
- if (!response.ok) {
706
- const snippet = (await response.text()).trim().slice(0, 200);
707
- throw new SpritesApiError(response.status, "GET", path26, snippet);
708
- }
709
- const buffer = await response.arrayBuffer();
710
- return new Uint8Array(buffer);
711
815
  };
712
816
  openExecSocket = (apiBaseUrl, token, name, options) => {
713
817
  const url = toWsUrl(apiBaseUrl, `/v1/sprites/${name}/exec`);
@@ -4748,27 +4852,27 @@ var init_authentication_manager = __esm({
4748
4852
  );
4749
4853
  return;
4750
4854
  }
4751
- let delay2 = Math.min(
4855
+ let delay3 = Math.min(
4752
4856
  MAXIMUM_REFRESH_DELAY,
4753
4857
  (tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1e3
4754
4858
  );
4755
- if (delay2 <= 0) {
4859
+ if (delay3 <= 0) {
4756
4860
  this.logger.warn(
4757
4861
  `Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`
4758
4862
  );
4759
- delay2 = 0;
4863
+ delay3 = 0;
4760
4864
  }
4761
4865
  const refetchTokenTimeoutId = setTimeout(() => {
4762
4866
  this._logVerbose("running scheduled token refetch");
4763
4867
  void this.refetchToken();
4764
- }, delay2);
4868
+ }, delay3);
4765
4869
  this.setAuthState({
4766
4870
  state: "waitingForScheduledRefetch",
4767
4871
  refetchTokenTimeoutId,
4768
4872
  config: this.authState.config
4769
4873
  });
4770
4874
  this._logVerbose(
4771
- `scheduled preemptive auth token refetching in ${delay2}ms`
4875
+ `scheduled preemptive auth token refetching in ${delay3}ms`
4772
4876
  );
4773
4877
  }
4774
4878
  // Protects against simultaneous calls to `setConfig`
@@ -19763,8 +19867,8 @@ var init_connect = __esm({
19763
19867
  pendingPortLogs.set(event.port, token2);
19764
19868
  const delays = [30, 60, 120, 200];
19765
19869
  void (async () => {
19766
- for (const delay2 of delays) {
19767
- await new Promise((resolve) => setTimeout(resolve, delay2));
19870
+ for (const delay3 of delays) {
19871
+ await new Promise((resolve) => setTimeout(resolve, delay3));
19768
19872
  if (pendingPortLogs.get(event.port) !== token2) {
19769
19873
  return;
19770
19874
  }
@@ -22339,7 +22443,7 @@ var init_weztermMux = __esm({
22339
22443
  });
22340
22444
 
22341
22445
  // src/devbox/commands/init/remote.ts
22342
- var import_node_crypto10, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS, BOOTSTRAP_EXEC_RETRY_DELAY_MS, logger8, truncateTail, shellQuote3, expandHome2, execWithLog, isExecTimeoutError, delay, writeRemoteFile, bootstrapDevbox, buildWeztermMuxConfig, buildWeztermMuxRunner, patchBashrc, writeRemoteCodexConfig, stageRemoteSetupArtifacts, resolveDaemonUrl, fetchDaemonBinary, buildDaemonConfig, isSameArgs, ensureSpriteDaemonService, installWeztermMux, ensureWeztermMuxService, hasWeztermMuxBinary, isWeztermMuxHealthy, installSpriteDaemon;
22446
+ var import_node_crypto10, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS, BOOTSTRAP_EXEC_RETRY_DELAY_MS, logger8, truncateTail, shellQuote3, expandHome2, execWithLog, isExecTimeoutError, delay2, writeRemoteFile, bootstrapDevbox, buildWeztermMuxConfig, buildWeztermMuxRunner, patchBashrc, writeRemoteCodexConfig, stageRemoteSetupArtifacts, resolveDaemonUrl, fetchDaemonBinary, buildDaemonConfig, isSameArgs, ensureSpriteDaemonService, installWeztermMux, ensureWeztermMuxService, hasWeztermMuxBinary, isWeztermMuxHealthy, installSpriteDaemon;
22343
22447
  var init_remote = __esm({
22344
22448
  "src/devbox/commands/init/remote.ts"() {
22345
22449
  "use strict";
@@ -22407,7 +22511,7 @@ var init_remote = __esm({
22407
22511
  return result;
22408
22512
  };
22409
22513
  isExecTimeoutError = (error) => error instanceof Error && typeof error.message === "string" && error.message.startsWith("Exec websocket timed out after ");
22410
- delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
22514
+ delay2 = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
22411
22515
  writeRemoteFile = async (client, canonical, path26, content, stage) => {
22412
22516
  const requestId = (0, import_node_crypto10.randomUUID)();
22413
22517
  logger8.info("sprites_request", {
@@ -22452,7 +22556,7 @@ var init_remote = __esm({
22452
22556
  timeoutMs: BOOTSTRAP_EXEC_TIMEOUT_MS,
22453
22557
  delayMs: BOOTSTRAP_EXEC_RETRY_DELAY_MS
22454
22558
  });
22455
- await delay(BOOTSTRAP_EXEC_RETRY_DELAY_MS);
22559
+ await delay2(BOOTSTRAP_EXEC_RETRY_DELAY_MS);
22456
22560
  return await execWithLog(
22457
22561
  client,
22458
22562
  canonical,
@@ -23943,17 +24047,26 @@ var init_template = __esm({
23943
24047
  });
23944
24048
 
23945
24049
  // src/devbox/commands/init/codex/prompts.ts
23946
- var import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
24050
+ var import_node_fs5, import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
23947
24051
  var init_prompts = __esm({
23948
24052
  "src/devbox/commands/init/codex/prompts.ts"() {
23949
24053
  "use strict";
24054
+ import_node_fs5 = __toESM(require("node:fs"), 1);
23950
24055
  import_promises23 = __toESM(require("node:fs/promises"), 1);
23951
24056
  import_node_path17 = __toESM(require("node:path"), 1);
23952
24057
  init_template();
23953
24058
  resolvePromptsDir = () => {
23954
- const binPath = process.argv[1];
23955
- if (binPath) {
23956
- return import_node_path17.default.resolve(import_node_path17.default.dirname(binPath), "..", "prompts");
24059
+ const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
24060
+ if (argv1) {
24061
+ try {
24062
+ const real = import_node_fs5.default.realpathSync(argv1);
24063
+ return import_node_path17.default.resolve(import_node_path17.default.dirname(real), "..", "prompts");
24064
+ } catch {
24065
+ }
24066
+ try {
24067
+ return import_node_path17.default.resolve(import_node_path17.default.dirname(argv1), "..", "prompts");
24068
+ } catch {
24069
+ }
23957
24070
  }
23958
24071
  return import_node_path17.default.resolve(process.cwd(), "prompts");
23959
24072
  };
@@ -24475,18 +24588,18 @@ fi`
24475
24588
  });
24476
24589
 
24477
24590
  // src/devbox/commands/init/codex/plan.ts
24478
- var import_node_path18, import_node_fs5, import_promises24, resolveSchemaPath, writeSetupEnvSecretsSchema, writeSetupExternalSchema, writeSetupExtraArtifactsSchema, writeServicesSchema, isObject4, isServicesSelection, isSetupPlan, isSetupEnvSecretsPlan, isSetupExternalPlan, isSetupExtraArtifactsPlan, isServicesPlan, readSetupPlan, readSetupEnvSecretsPlan, readSetupExternalPlan, readSetupExtraArtifactsPlan, readServicesPlan, writeSetupPlan, mergeSetupScans;
24591
+ var import_node_path18, import_node_fs6, import_promises24, resolveSchemaPath, writeSetupEnvSecretsSchema, writeSetupExternalSchema, writeSetupExtraArtifactsSchema, writeServicesSchema, isObject4, isServicesSelection, isSetupPlan, isSetupEnvSecretsPlan, isSetupExternalPlan, isSetupExtraArtifactsPlan, isServicesPlan, readSetupPlan, readSetupEnvSecretsPlan, readSetupExternalPlan, readSetupExtraArtifactsPlan, readServicesPlan, writeSetupPlan, mergeSetupScans;
24479
24592
  var init_plan = __esm({
24480
24593
  "src/devbox/commands/init/codex/plan.ts"() {
24481
24594
  "use strict";
24482
24595
  import_node_path18 = __toESM(require("node:path"), 1);
24483
- import_node_fs5 = __toESM(require("node:fs"), 1);
24596
+ import_node_fs6 = __toESM(require("node:fs"), 1);
24484
24597
  import_promises24 = __toESM(require("node:fs/promises"), 1);
24485
24598
  resolveSchemaPath = (fileName) => {
24486
24599
  const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
24487
24600
  if (argv1) {
24488
24601
  try {
24489
- const real = import_node_fs5.default.realpathSync(argv1);
24602
+ const real = import_node_fs6.default.realpathSync(argv1);
24490
24603
  return import_node_path18.default.resolve(import_node_path18.default.dirname(real), "..", "codex", fileName);
24491
24604
  } catch {
24492
24605
  }
@@ -24783,12 +24896,12 @@ ${bottom}
24783
24896
  });
24784
24897
 
24785
24898
  // src/devbox/commands/init/codex/local.ts
24786
- var import_node_child_process9, import_node_fs6, import_promises25, import_node_path19, stripAnsi3, extractBoldText2, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
24899
+ var import_node_child_process9, import_node_fs7, import_promises25, import_node_path19, stripAnsi3, extractBoldText2, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
24787
24900
  var init_local = __esm({
24788
24901
  "src/devbox/commands/init/codex/local.ts"() {
24789
24902
  "use strict";
24790
24903
  import_node_child_process9 = require("node:child_process");
24791
- import_node_fs6 = require("node:fs");
24904
+ import_node_fs7 = require("node:fs");
24792
24905
  import_promises25 = __toESM(require("node:fs/promises"), 1);
24793
24906
  import_node_path19 = __toESM(require("node:path"), 1);
24794
24907
  init_dist2();
@@ -24807,11 +24920,11 @@ var init_local = __esm({
24807
24920
  try {
24808
24921
  if (stdoutLogPath) {
24809
24922
  await import_promises25.default.mkdir(import_node_path19.default.dirname(stdoutLogPath), { recursive: true });
24810
- stdoutStream = (0, import_node_fs6.createWriteStream)(stdoutLogPath, { flags: "a" });
24923
+ stdoutStream = (0, import_node_fs7.createWriteStream)(stdoutLogPath, { flags: "a" });
24811
24924
  }
24812
24925
  if (stderrLogPath) {
24813
24926
  await import_promises25.default.mkdir(import_node_path19.default.dirname(stderrLogPath), { recursive: true });
24814
- stderrStream = (0, import_node_fs6.createWriteStream)(stderrLogPath, { flags: "a" });
24927
+ stderrStream = (0, import_node_fs7.createWriteStream)(stderrLogPath, { flags: "a" });
24815
24928
  }
24816
24929
  } catch {
24817
24930
  stdoutStream = null;
@@ -32254,7 +32367,7 @@ var init_cli = __esm({
32254
32367
  });
32255
32368
 
32256
32369
  // src/bin/dvb.ts
32257
- var import_node_fs7 = __toESM(require("node:fs"), 1);
32370
+ var import_node_fs8 = __toESM(require("node:fs"), 1);
32258
32371
  var import_node_os11 = __toESM(require("node:os"), 1);
32259
32372
  var import_node_path26 = __toESM(require("node:path"), 1);
32260
32373
  init_src();
@@ -32312,8 +32425,8 @@ run().catch((error) => {
32312
32425
  if (homeDir) {
32313
32426
  try {
32314
32427
  const logDir = import_node_path26.default.join(resolveDevboxDir(homeDir), "wezterm");
32315
- import_node_fs7.default.mkdirSync(logDir, { recursive: true });
32316
- import_node_fs7.default.appendFileSync(
32428
+ import_node_fs8.default.mkdirSync(logDir, { recursive: true });
32429
+ import_node_fs8.default.appendFileSync(
32317
32430
  import_node_path26.default.join(logDir, "proxy.log"),
32318
32431
  `${(/* @__PURE__ */ new Date()).toISOString()} ${message}
32319
32432
  `
package/dist/bin/dvbd.cjs CHANGED
@@ -351,7 +351,7 @@ var init_repo = __esm({
351
351
  });
352
352
 
353
353
  // ../core/src/sprites.ts
354
- var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
354
+ var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT, DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS, SPRITES_HTTP_RETRYABLE_STATUSES, delay, isIdempotentMethod, computeRetryDelayMs, isAbortError, getErrorCode, isRetryableFetchError, shouldRetrySpritesRequest, withSpritesRetry, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
355
355
  var init_sprites = __esm({
356
356
  "../core/src/sprites.ts"() {
357
357
  "use strict";
@@ -419,39 +419,126 @@ var init_sprites = __esm({
419
419
  return new URL(path6, `${protocol}//${base.host}`);
420
420
  };
421
421
  shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
422
- requestJson = async (apiBaseUrl, token, method, path6, body) => {
423
- const requestId = (0, import_node_crypto.randomUUID)();
424
- const url = new URL(path6, apiBaseUrl);
425
- const headers = {
426
- authorization: `Bearer ${token}`,
427
- "x-request-id": requestId
428
- };
429
- if (body) {
430
- headers["content-type"] = "application/json";
422
+ DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT = 5e3;
423
+ DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT = 2e4;
424
+ DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS = 5;
425
+ SPRITES_HTTP_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 409, 425, 429, 500, 502, 503, 504]);
426
+ delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
427
+ isIdempotentMethod = (method) => {
428
+ const normalized = method.toUpperCase();
429
+ return normalized === "GET" || normalized === "HEAD" || normalized === "PUT" || normalized === "DELETE" || normalized === "OPTIONS";
430
+ };
431
+ computeRetryDelayMs = (attempt) => {
432
+ const base = 250;
433
+ const cap = 2500;
434
+ const exp = Math.min(cap, base * 2 ** Math.max(0, attempt - 1));
435
+ const jitter = Math.floor(Math.random() * 120);
436
+ return exp + jitter;
437
+ };
438
+ isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
439
+ getErrorCode = (error) => {
440
+ if (!error || typeof error !== "object") return void 0;
441
+ const record = error;
442
+ const code2 = record.code;
443
+ return typeof code2 === "string" || typeof code2 === "number" ? String(code2) : void 0;
444
+ };
445
+ isRetryableFetchError = (error) => {
446
+ if (isAbortError(error)) return true;
447
+ if (error instanceof TypeError) return true;
448
+ const code2 = getErrorCode(error);
449
+ return code2 === "ECONNRESET" || code2 === "ETIMEDOUT" || code2 === "EAI_AGAIN" || code2 === "ENOTFOUND" || code2 === "ECONNREFUSED";
450
+ };
451
+ shouldRetrySpritesRequest = (method, error) => {
452
+ if (!isIdempotentMethod(method)) return false;
453
+ if (error instanceof SpritesApiError) {
454
+ return SPRITES_HTTP_RETRYABLE_STATUSES.has(error.status);
431
455
  }
432
- const init = { method, headers };
433
- if (body) {
434
- init.body = JSON.stringify(body);
456
+ return isRetryableFetchError(error);
457
+ };
458
+ withSpritesRetry = async (options) => {
459
+ const opId = (0, import_node_crypto.randomUUID)();
460
+ const timeoutMs = options.timeoutMs ?? (isIdempotentMethod(options.method) ? DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT : DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT);
461
+ const maxAttemptsRaw = options.maxAttempts ?? DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS;
462
+ const maxAttempts = isIdempotentMethod(options.method) ? Math.max(1, maxAttemptsRaw) : 1;
463
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
464
+ const requestId = (0, import_node_crypto.randomUUID)();
465
+ const controller = new AbortController();
466
+ const timeoutHandle = typeof timeoutMs === "number" && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
467
+ try {
468
+ logger.info("sprites_request", {
469
+ opId,
470
+ attempt,
471
+ requestId,
472
+ method: options.method,
473
+ path: options.path,
474
+ timeoutMs
475
+ });
476
+ return await options.run(controller.signal, requestId);
477
+ } catch (error) {
478
+ const retryable = shouldRetrySpritesRequest(options.method, error);
479
+ const remaining = maxAttempts - attempt;
480
+ if (!retryable || remaining <= 0) {
481
+ throw error;
482
+ }
483
+ const delayMs = computeRetryDelayMs(attempt);
484
+ logger.warn("sprites_http_retry", {
485
+ opId,
486
+ attempt,
487
+ requestId,
488
+ method: options.method,
489
+ path: options.path,
490
+ timeoutMs,
491
+ delayMs,
492
+ remainingAttempts: remaining,
493
+ errorName: error instanceof Error ? error.name : void 0,
494
+ errorMessage: error instanceof Error ? error.message : String(error),
495
+ errorCode: getErrorCode(error),
496
+ ...error instanceof SpritesApiError ? { status: error.status } : {}
497
+ });
498
+ await delay(delayMs);
499
+ } finally {
500
+ if (timeoutHandle) clearTimeout(timeoutHandle);
501
+ }
435
502
  }
436
- logger.info("sprites_request", { requestId, method, path: path6 });
437
- const response = await fetch(url, init);
438
- const text = await response.text();
439
- logger.info("sprites_response", {
440
- requestId,
503
+ throw new Error(`Sprites request failed: ${options.method} ${options.path}`);
504
+ };
505
+ requestJson = async (apiBaseUrl, token, method, path6, body) => {
506
+ return await withSpritesRetry({
441
507
  method,
442
508
  path: path6,
443
- status: response.status
509
+ run: async (signal, requestId) => {
510
+ const url = new URL(path6, apiBaseUrl);
511
+ const headers = {
512
+ authorization: `Bearer ${token}`,
513
+ "x-request-id": requestId
514
+ };
515
+ if (body) {
516
+ headers["content-type"] = "application/json";
517
+ }
518
+ const init = { method, headers, signal };
519
+ if (body) {
520
+ init.body = JSON.stringify(body);
521
+ }
522
+ const response = await fetch(url, init);
523
+ const text = await response.text();
524
+ logger.info("sprites_response", {
525
+ requestId,
526
+ method,
527
+ path: path6,
528
+ status: response.status
529
+ });
530
+ if (!response.ok) {
531
+ const snippet = text.trim().slice(0, 200);
532
+ throw new SpritesApiError(response.status, method, path6, snippet);
533
+ }
534
+ if (!text) return null;
535
+ try {
536
+ return JSON.parse(text);
537
+ } catch {
538
+ return text;
539
+ }
540
+ }
444
541
  });
445
- if (!response.ok) {
446
- const snippet = text.trim().slice(0, 200);
447
- throw new SpritesApiError(response.status, method, path6, snippet);
448
- }
449
- if (!text) return null;
450
- try {
451
- return JSON.parse(text);
452
- } catch {
453
- return text;
454
- }
455
542
  };
456
543
  listSprites = async (apiBaseUrl, token, options) => {
457
544
  const params = new URLSearchParams();
@@ -492,88 +579,99 @@ var init_sprites = __esm({
492
579
  return response;
493
580
  };
494
581
  requestNdjson = async (apiBaseUrl, token, method, path6, body) => {
495
- const requestId = (0, import_node_crypto.randomUUID)();
496
- const url = new URL(path6, apiBaseUrl);
497
- const headers = {
498
- authorization: `Bearer ${token}`,
499
- "x-request-id": requestId
500
- };
501
- if (body) {
502
- headers["content-type"] = "application/json";
503
- }
504
- const init = { method, headers };
505
- if (body) {
506
- init.body = JSON.stringify(body);
507
- }
508
- logger.info("sprites_request", { requestId, method, path: path6 });
509
- const response = await fetch(url, init);
510
- logger.info("sprites_response", {
511
- requestId,
582
+ return await withSpritesRetry({
512
583
  method,
513
584
  path: path6,
514
- status: response.status
515
- });
516
- const text = await response.text();
517
- if (!response.ok) {
518
- const snippet = text.trim().slice(0, 200);
519
- throw new SpritesApiError(response.status, method, path6, snippet);
520
- }
521
- const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
522
- const events = [];
523
- for (const line of lines) {
524
- try {
525
- const parsed = JSON.parse(line);
526
- if (Array.isArray(parsed)) {
527
- for (const entry of parsed) {
528
- if (entry && typeof entry === "object") {
529
- events.push(entry);
530
- } else {
531
- events.push({ value: entry });
585
+ run: async (signal, requestId) => {
586
+ const url = new URL(path6, apiBaseUrl);
587
+ const headers = {
588
+ authorization: `Bearer ${token}`,
589
+ "x-request-id": requestId
590
+ };
591
+ if (body) {
592
+ headers["content-type"] = "application/json";
593
+ }
594
+ const init = { method, headers, signal };
595
+ if (body) {
596
+ init.body = JSON.stringify(body);
597
+ }
598
+ const response = await fetch(url, init);
599
+ logger.info("sprites_response", {
600
+ requestId,
601
+ method,
602
+ path: path6,
603
+ status: response.status
604
+ });
605
+ const text = await response.text();
606
+ if (!response.ok) {
607
+ const snippet = text.trim().slice(0, 200);
608
+ throw new SpritesApiError(response.status, method, path6, snippet);
609
+ }
610
+ const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
611
+ const events = [];
612
+ for (const line of lines) {
613
+ try {
614
+ const parsed = JSON.parse(line);
615
+ if (Array.isArray(parsed)) {
616
+ for (const entry of parsed) {
617
+ if (entry && typeof entry === "object") {
618
+ events.push(entry);
619
+ } else {
620
+ events.push({ value: entry });
621
+ }
622
+ }
623
+ continue;
532
624
  }
625
+ if (parsed && typeof parsed === "object") {
626
+ events.push(parsed);
627
+ continue;
628
+ }
629
+ events.push({ value: parsed });
630
+ } catch {
631
+ events.push({ raw: line });
533
632
  }
534
- continue;
535
- }
536
- if (parsed && typeof parsed === "object") {
537
- events.push(parsed);
538
- continue;
539
633
  }
540
- events.push({ value: parsed });
541
- } catch {
542
- events.push({ raw: line });
634
+ return events;
543
635
  }
544
- }
545
- return events;
636
+ });
546
637
  };
547
638
  writeFile = async (apiBaseUrl, token, name, remotePath, data) => {
548
- const requestId = (0, import_node_crypto.randomUUID)();
549
639
  const path6 = `/v1/sprites/${name}/fs/write`;
550
640
  const url = new URL(path6, apiBaseUrl);
551
641
  url.searchParams.set("path", remotePath);
552
642
  url.searchParams.set("mkdir", "true");
553
- logger.info("sprites_fs_write", {
554
- requestId,
555
- path: path6,
556
- name,
557
- remotePath,
558
- size: data.length
559
- });
560
- const response = await fetch(url, {
643
+ await withSpritesRetry({
561
644
  method: "PUT",
562
- headers: {
563
- authorization: `Bearer ${token}`,
564
- "content-type": "application/octet-stream",
565
- "x-request-id": requestId
566
- },
567
- body: data
568
- });
569
- logger.info("sprites_fs_write_response", {
570
- requestId,
571
645
  path: path6,
572
- status: response.status
646
+ run: async (signal, requestId) => {
647
+ logger.info("sprites_fs_write", {
648
+ requestId,
649
+ path: path6,
650
+ name,
651
+ remotePath,
652
+ size: data.length
653
+ });
654
+ const response = await fetch(url, {
655
+ method: "PUT",
656
+ headers: {
657
+ authorization: `Bearer ${token}`,
658
+ "content-type": "application/octet-stream",
659
+ "x-request-id": requestId
660
+ },
661
+ body: data,
662
+ signal
663
+ });
664
+ logger.info("sprites_fs_write_response", {
665
+ requestId,
666
+ path: path6,
667
+ status: response.status
668
+ });
669
+ if (!response.ok) {
670
+ const snippet = (await response.text()).trim().slice(0, 200);
671
+ throw new SpritesApiError(response.status, "PUT", path6, snippet);
672
+ }
673
+ }
573
674
  });
574
- if (!response.ok) {
575
- throw new Error(`Sprites FS write failed: ${response.status}`);
576
- }
577
675
  };
578
676
  normalizeServiceRecord = (entry) => {
579
677
  const rawName = entry.name;
@@ -604,38 +702,44 @@ var init_sprites = __esm({
604
702
  return service;
605
703
  };
606
704
  readFile = async (apiBaseUrl, token, name, options) => {
607
- const requestId = (0, import_node_crypto.randomUUID)();
608
705
  const path6 = `/v1/sprites/${name}/fs/read`;
609
706
  const url = new URL(path6, apiBaseUrl);
610
707
  url.searchParams.set("path", options.path);
611
708
  if (options.workingDir) {
612
709
  url.searchParams.set("workingDir", options.workingDir);
613
710
  }
614
- logger.info("sprites_fs_read", {
615
- requestId,
616
- path: path6,
617
- name,
618
- remotePath: options.path,
619
- workingDir: options.workingDir
620
- });
621
- const response = await fetch(url, {
711
+ return await withSpritesRetry({
622
712
  method: "GET",
623
- headers: {
624
- authorization: `Bearer ${token}`,
625
- "x-request-id": requestId
626
- }
627
- });
628
- logger.info("sprites_fs_read_response", {
629
- requestId,
630
713
  path: path6,
631
- status: response.status
714
+ run: async (signal, requestId) => {
715
+ logger.info("sprites_fs_read", {
716
+ requestId,
717
+ path: path6,
718
+ name,
719
+ remotePath: options.path,
720
+ workingDir: options.workingDir
721
+ });
722
+ const response = await fetch(url, {
723
+ method: "GET",
724
+ headers: {
725
+ authorization: `Bearer ${token}`,
726
+ "x-request-id": requestId
727
+ },
728
+ signal
729
+ });
730
+ logger.info("sprites_fs_read_response", {
731
+ requestId,
732
+ path: path6,
733
+ status: response.status
734
+ });
735
+ if (!response.ok) {
736
+ const snippet = (await response.text()).trim().slice(0, 200);
737
+ throw new SpritesApiError(response.status, "GET", path6, snippet);
738
+ }
739
+ const buffer = await response.arrayBuffer();
740
+ return new Uint8Array(buffer);
741
+ }
632
742
  });
633
- if (!response.ok) {
634
- const snippet = (await response.text()).trim().slice(0, 200);
635
- throw new SpritesApiError(response.status, "GET", path6, snippet);
636
- }
637
- const buffer = await response.arrayBuffer();
638
- return new Uint8Array(buffer);
639
743
  };
640
744
  openExecSocket = (apiBaseUrl, token, name, options) => {
641
745
  const url = toWsUrl(apiBaseUrl, `/v1/sprites/${name}/exec`);
@@ -4556,27 +4660,27 @@ var init_authentication_manager = __esm({
4556
4660
  );
4557
4661
  return;
4558
4662
  }
4559
- let delay = Math.min(
4663
+ let delay2 = Math.min(
4560
4664
  MAXIMUM_REFRESH_DELAY,
4561
4665
  (tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1e3
4562
4666
  );
4563
- if (delay <= 0) {
4667
+ if (delay2 <= 0) {
4564
4668
  this.logger.warn(
4565
4669
  `Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`
4566
4670
  );
4567
- delay = 0;
4671
+ delay2 = 0;
4568
4672
  }
4569
4673
  const refetchTokenTimeoutId = setTimeout(() => {
4570
4674
  this._logVerbose("running scheduled token refetch");
4571
4675
  void this.refetchToken();
4572
- }, delay);
4676
+ }, delay2);
4573
4677
  this.setAuthState({
4574
4678
  state: "waitingForScheduledRefetch",
4575
4679
  refetchTokenTimeoutId,
4576
4680
  config: this.authState.config
4577
4681
  });
4578
4682
  this._logVerbose(
4579
- `scheduled preemptive auth token refetching in ${delay}ms`
4683
+ `scheduled preemptive auth token refetching in ${delay2}ms`
4580
4684
  );
4581
4685
  }
4582
4686
  // Protects against simultaneous calls to `setConfig`
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,kBAAkB,GAAU,MAAM,MAAM,oBAI7C,CAAC;AAOF,QAAA,MAAM,6BAA6B,uBACM,CAAC;AAC1C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AACvC,QAAA,MAAM,iCAAiC,uBACM,CAAC;AAC9C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AAEvC,QAAA,MAAM,qBAAqB,GACzB,WAAW,MAAM,EACjB,iBAAiB,MAAM,EACvB,mBAAmB,MAAM,EACzB,kBAAkB,MAAM,oBAOtB,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAyBA,QAAA,MAAM,kBAAkB,GAAU,MAAM,MAAM,oBAI7C,CAAC;AAOF,QAAA,MAAM,6BAA6B,uBACM,CAAC;AAC1C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AACvC,QAAA,MAAM,iCAAiC,uBACM,CAAC;AAC9C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AAEvC,QAAA,MAAM,qBAAqB,GACzB,WAAW,MAAM,EACjB,iBAAiB,MAAM,EACvB,mBAAmB,MAAM,EACzB,kBAAkB,MAAM,oBAOtB,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
@@ -1,16 +1,31 @@
1
- import fs from "node:fs/promises";
1
+ import fs from "node:fs";
2
+ import fsPromises from "node:fs/promises";
2
3
  import path from "node:path";
3
4
  import { renderTemplate } from "./template.js";
4
5
  const resolvePromptsDir = () => {
5
- const binPath = process.argv[1];
6
- if (binPath) {
7
- return path.resolve(path.dirname(binPath), "..", "prompts");
6
+ // Prefer resolving relative to the real dvb entrypoint, since `process.argv[1]`
7
+ // may be a bin shim (e.g. ~/.nvm/.../bin/dvb) rather than `.../dist/bin/dvb.cjs`.
8
+ const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
9
+ if (argv1) {
10
+ try {
11
+ const real = fs.realpathSync(argv1);
12
+ return path.resolve(path.dirname(real), "..", "prompts");
13
+ }
14
+ catch {
15
+ // ignore and fall back
16
+ }
17
+ try {
18
+ return path.resolve(path.dirname(argv1), "..", "prompts");
19
+ }
20
+ catch {
21
+ // ignore and fall back
22
+ }
8
23
  }
9
24
  return path.resolve(process.cwd(), "prompts");
10
25
  };
11
26
  const readPromptTemplate = async (name) => {
12
27
  const promptPath = path.join(resolvePromptsDir(), name);
13
- const raw = await fs.readFile(promptPath, "utf8");
28
+ const raw = await fsPromises.readFile(promptPath, "utf8");
14
29
  return raw;
15
30
  };
16
31
  const loadPrompt = async (name, vars = {}) => renderTemplate(await readPromptTemplate(name), vars).trim();
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,iBAAiB,GAAG,GAAG,EAAE;IAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,EACtB,IAAY,EACZ,OAA+B,EAAE,EACjC,EAAE,CAAC,cAAc,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAEjE,MAAM,6BAA6B,GAAG,KAAK,IAAI,EAAE,CAC/C,UAAU,CAAC,2BAA2B,CAAC,CAAC;AAC1C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AACvC,MAAM,iCAAiC,GAAG,KAAK,IAAI,EAAE,CACnD,UAAU,CAAC,+BAA+B,CAAC,CAAC;AAC9C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AAEvC,MAAM,qBAAqB,GAAG,KAAK,EACjC,SAAiB,EACjB,eAAuB,EACvB,iBAAyB,EACzB,gBAAwB,EACxB,EAAE,CACF,UAAU,CAAC,iBAAiB,EAAE;IAC5B,UAAU,EAAE,SAAS;IACrB,gBAAgB,EAAE,eAAe;IACjC,kBAAkB,EAAE,iBAAiB;IACrC,iBAAiB,EAAE,gBAAgB;CACpC,CAAC,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,iBAAiB,GAAG,GAAG,EAAE;IAC7B,gFAAgF;IAChF,kFAAkF;IAClF,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,EACtB,IAAY,EACZ,OAA+B,EAAE,EACjC,EAAE,CAAC,cAAc,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAEjE,MAAM,6BAA6B,GAAG,KAAK,IAAI,EAAE,CAC/C,UAAU,CAAC,2BAA2B,CAAC,CAAC;AAC1C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AACvC,MAAM,iCAAiC,GAAG,KAAK,IAAI,EAAE,CACnD,UAAU,CAAC,+BAA+B,CAAC,CAAC;AAC9C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AAEvC,MAAM,qBAAqB,GAAG,KAAK,EACjC,SAAiB,EACjB,eAAuB,EACvB,iBAAyB,EACzB,gBAAwB,EACxB,EAAE,CACF,UAAU,CAAC,iBAAiB,EAAE;IAC5B,UAAU,EAAE,SAAS;IACrB,gBAAgB,EAAE,eAAe;IACjC,kBAAkB,EAAE,iBAAiB;IACrC,iBAAiB,EAAE,gBAAgB;CACpC,CAAC,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxes-dev/dvb",
3
- "version": "0.2.45",
3
+ "version": "0.2.46",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {