@boxes-dev/dvb-runtime 1.0.178 → 1.0.179

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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a741b1b2-865d-5d60-b44d-6259dcc3a122")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1518c9c7-f041-5409-b81f-b01b956a3638")}catch(e){}}();
4
4
 
5
5
  var __create = Object.create;
6
6
  var __defProp = Object.defineProperty;
@@ -24219,9 +24219,9 @@ var require_is_export_retryable = __commonJS({
24219
24219
  if (Number.isInteger(seconds)) {
24220
24220
  return seconds > 0 ? seconds * 1e3 : -1;
24221
24221
  }
24222
- const delay3 = new Date(retryAfter).getTime() - Date.now();
24223
- if (delay3 >= 0) {
24224
- return delay3;
24222
+ const delay4 = new Date(retryAfter).getTime() - Date.now();
24223
+ if (delay4 >= 0) {
24224
+ return delay4;
24225
24225
  }
24226
24226
  return 0;
24227
24227
  }
@@ -37776,17 +37776,17 @@ var require_backoff_timeout = __commonJS({
37776
37776
  trace(text) {
37777
37777
  logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, "{" + this.id + "} " + text);
37778
37778
  }
37779
- runTimer(delay3) {
37779
+ runTimer(delay4) {
37780
37780
  var _a3, _b2;
37781
- this.trace("runTimer(delay=" + delay3 + ")");
37781
+ this.trace("runTimer(delay=" + delay4 + ")");
37782
37782
  this.endTime = this.startTime;
37783
- this.endTime.setMilliseconds(this.endTime.getMilliseconds() + delay3);
37783
+ this.endTime.setMilliseconds(this.endTime.getMilliseconds() + delay4);
37784
37784
  clearTimeout(this.timerId);
37785
37785
  this.timerId = setTimeout(() => {
37786
37786
  this.trace("timer fired");
37787
37787
  this.running = false;
37788
37788
  this.callback();
37789
- }, delay3);
37789
+ }, delay4);
37790
37790
  if (!this.hasRef) {
37791
37791
  (_b2 = (_a3 = this.timerId).unref) === null || _b2 === void 0 ? void 0 : _b2.call(_a3);
37792
37792
  }
@@ -88688,8 +88688,8 @@ var init_otel = __esm({
88688
88688
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
88689
88689
  };
88690
88690
  readBuildMetadata = () => {
88691
- const rawPackageVersion = "1.0.178";
88692
- const rawGitSha = "fccb442a9695c60f8de7dbe528d9ef8e52b29a99";
88691
+ const rawPackageVersion = "1.0.179";
88692
+ const rawGitSha = "2918029200d16706902b9262d982fa8437cbb319";
88693
88693
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
88694
88694
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
88695
88695
  return { packageVersion, gitSha };
@@ -95020,17 +95020,17 @@ function updateRateLimits(limits, { statusCode, headers }, now = safeDateNow())
95020
95020
  for (const limit of rateLimitHeader.trim().split(",")) {
95021
95021
  const [retryAfter, categories, , , namespaces] = limit.split(":", 5);
95022
95022
  const headerDelay = parseInt(retryAfter, 10);
95023
- const delay3 = (!isNaN(headerDelay) ? headerDelay : 60) * 1e3;
95023
+ const delay4 = (!isNaN(headerDelay) ? headerDelay : 60) * 1e3;
95024
95024
  if (!categories) {
95025
- updatedRateLimits.all = now + delay3;
95025
+ updatedRateLimits.all = now + delay4;
95026
95026
  } else {
95027
95027
  for (const category of categories.split(";")) {
95028
95028
  if (category === "metric_bucket") {
95029
95029
  if (!namespaces || namespaces.split(";").includes("custom")) {
95030
- updatedRateLimits[category] = now + delay3;
95030
+ updatedRateLimits[category] = now + delay4;
95031
95031
  }
95032
95032
  } else {
95033
- updatedRateLimits[category] = now + delay3;
95033
+ updatedRateLimits[category] = now + delay4;
95034
95034
  }
95035
95035
  }
95036
95036
  }
@@ -120881,9 +120881,9 @@ var init_sentry = __esm({
120881
120881
  sentryEnabled = false;
120882
120882
  uncaughtExceptionMonitorInstalled = false;
120883
120883
  readBuildMetadata2 = () => {
120884
- const rawPackageVersion = "1.0.178";
120885
- const rawGitSha = "fccb442a9695c60f8de7dbe528d9ef8e52b29a99";
120886
- const rawSentryRelease = "boxes-dev-dvb@1.0.178+fccb442a9695c60f8de7dbe528d9ef8e52b29a99";
120884
+ const rawPackageVersion = "1.0.179";
120885
+ const rawGitSha = "2918029200d16706902b9262d982fa8437cbb319";
120886
+ const rawSentryRelease = "boxes-dev-dvb@1.0.179+2918029200d16706902b9262d982fa8437cbb319";
120887
120887
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
120888
120888
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
120889
120889
  const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
@@ -124880,7 +124880,7 @@ var init_packageVersion = __esm({
124880
124880
  return import_node_path8.default.join(process.cwd(), "dvb");
124881
124881
  };
124882
124882
  readEmbeddedPackageVersion = () => {
124883
- const raw = "1.0.178";
124883
+ const raw = "1.0.179";
124884
124884
  return trimVersion(raw);
124885
124885
  };
124886
124886
  readNearestPackageMetadata = (basePath) => {
@@ -130560,27 +130560,27 @@ var init_authentication_manager = __esm({
130560
130560
  );
130561
130561
  return;
130562
130562
  }
130563
- let delay3 = Math.min(
130563
+ let delay4 = Math.min(
130564
130564
  MAXIMUM_REFRESH_DELAY,
130565
130565
  (tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1e3
130566
130566
  );
130567
- if (delay3 <= 0) {
130567
+ if (delay4 <= 0) {
130568
130568
  this.logger.warn(
130569
130569
  `Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`
130570
130570
  );
130571
- delay3 = 0;
130571
+ delay4 = 0;
130572
130572
  }
130573
130573
  const refetchTokenTimeoutId = setTimeout(() => {
130574
130574
  this._logVerbose("running scheduled token refetch");
130575
130575
  void this.refetchToken();
130576
- }, delay3);
130576
+ }, delay4);
130577
130577
  this.setAuthState({
130578
130578
  state: "waitingForScheduledRefetch",
130579
130579
  refetchTokenTimeoutId,
130580
130580
  config: this.authState.config
130581
130581
  });
130582
130582
  this._logVerbose(
130583
- `scheduled preemptive auth token refetching in ${delay3}ms`
130583
+ `scheduled preemptive auth token refetching in ${delay4}ms`
130584
130584
  );
130585
130585
  }
130586
130586
  // Protects against simultaneous calls to `setConfig`
@@ -151730,7 +151730,7 @@ var require_delay = __commonJS({
151730
151730
  Object.defineProperty(exports2, "__esModule", { value: true });
151731
151731
  exports2.delay = void 0;
151732
151732
  var execute_1 = require_execute();
151733
- function delay3(signal, dueTime) {
151733
+ function delay4(signal, dueTime) {
151734
151734
  return (0, execute_1.execute)(signal, (resolve2) => {
151735
151735
  const ms = typeof dueTime === "number" ? dueTime : dueTime.getTime() - Date.now();
151736
151736
  const timer = setTimeout(resolve2, ms);
@@ -151739,7 +151739,7 @@ var require_delay = __commonJS({
151739
151739
  };
151740
151740
  });
151741
151741
  }
151742
- exports2.delay = delay3;
151742
+ exports2.delay = delay4;
151743
151743
  }
151744
151744
  });
151745
151745
 
@@ -204017,7 +204017,7 @@ ${result.exception}`
204017
204017
  async #put(values, timeoutMs, partition, partitionTtlMs) {
204018
204018
  const valuesEncoded = values.map((v2) => dumps(v2));
204019
204019
  const partitionKey = _Queue.#validatePartitionKey(partition);
204020
- let delay3 = queueInitialPutBackoffMs;
204020
+ let delay4 = queueInitialPutBackoffMs;
204021
204021
  const deadline = timeoutMs ? Date.now() + timeoutMs : void 0;
204022
204022
  while (true) {
204023
204023
  try {
@@ -204030,14 +204030,14 @@ ${result.exception}`
204030
204030
  break;
204031
204031
  } catch (e2) {
204032
204032
  if (e2 instanceof import_nice_grpc9.ClientError && e2.code === import_nice_grpc9.Status.RESOURCE_EXHAUSTED) {
204033
- delay3 = Math.min(delay3 * 2, 3e4);
204033
+ delay4 = Math.min(delay4 * 2, 3e4);
204034
204034
  if (deadline !== void 0) {
204035
204035
  const remaining = deadline - Date.now();
204036
204036
  if (remaining <= 0)
204037
204037
  throw new QueueFullError(`Put failed on ${this.queueId}.`);
204038
- delay3 = Math.min(delay3, remaining);
204038
+ delay4 = Math.min(delay4, remaining);
204039
204039
  }
204040
- await new Promise((resolve2) => setTimeout(resolve2, delay3));
204040
+ await new Promise((resolve2) => setTimeout(resolve2, delay4));
204041
204041
  } else {
204042
204042
  throw e2;
204043
204043
  }
@@ -204967,9 +204967,9 @@ ${result.exception}`
204967
204967
  while (this.running) {
204968
204968
  const now = Math.floor(Date.now() / 1e3);
204969
204969
  const refreshTime = this.tokenExpiry - REFRESH_WINDOW;
204970
- const delay3 = Math.max(0, refreshTime - now) * 1e3;
204970
+ const delay4 = Math.max(0, refreshTime - now) * 1e3;
204971
204971
  await new Promise((resolve2) => {
204972
- this.timeoutId = setTimeout(resolve2, delay3);
204972
+ this.timeoutId = setTimeout(resolve2, delay4);
204973
204973
  this.timeoutId.unref();
204974
204974
  });
204975
204975
  if (!this.running) {
@@ -208682,8 +208682,8 @@ var init_connect2 = __esm({
208682
208682
  pendingPortLogs.set(event.port, token);
208683
208683
  const delays = [30, 60, 120, 200];
208684
208684
  void (async () => {
208685
- for (const delay3 of delays) {
208686
- await new Promise((resolve2) => setTimeout(resolve2, delay3));
208685
+ for (const delay4 of delays) {
208686
+ await new Promise((resolve2) => setTimeout(resolve2, delay4));
208687
208687
  if (pendingPortLogs.get(event.port) !== token) {
208688
208688
  return;
208689
208689
  }
@@ -214974,15 +214974,76 @@ var init_prompts = __esm({
214974
214974
  }
214975
214975
  });
214976
214976
 
214977
+ // src/devbox/commands/init/codex/events.ts
214978
+ var stripAnsi2, extractBoldText, normalizeProgressMessage, toRecord, extractProgressFromJsonLine, extractThreadIdFromJsonLine;
214979
+ var init_events = __esm({
214980
+ "src/devbox/commands/init/codex/events.ts"() {
214981
+ "use strict";
214982
+ stripAnsi2 = (value) => value.replace(/\u001b\[[0-9;]*[A-Za-z]/g, "");
214983
+ extractBoldText = (line) => {
214984
+ const match2 = line.match(/\*\*([^*]+)\*\*/);
214985
+ const text = match2?.[1];
214986
+ return text ? text.trim() : null;
214987
+ };
214988
+ normalizeProgressMessage = (value) => {
214989
+ if (!value) return null;
214990
+ const normalized = value.replace(/\s+/g, " ").trim();
214991
+ if (!normalized) return null;
214992
+ if (normalized.length > 140) return null;
214993
+ if (!/[A-Za-z]/.test(normalized)) return null;
214994
+ if (/\\[nrt"\\]/.test(normalized)) return null;
214995
+ if (/[\[\]{}]/.test(normalized)) return null;
214996
+ return normalized;
214997
+ };
214998
+ toRecord = (value) => typeof value === "object" && value !== null ? value : null;
214999
+ extractProgressFromJsonLine = (line) => {
215000
+ const trimmed = line.trim();
215001
+ if (!trimmed.startsWith("{")) return null;
215002
+ let parsed;
215003
+ try {
215004
+ parsed = JSON.parse(trimmed);
215005
+ } catch {
215006
+ return null;
215007
+ }
215008
+ const record = toRecord(parsed);
215009
+ if (!record) return null;
215010
+ if (record.type === "reasoning") {
215011
+ return normalizeProgressMessage(
215012
+ extractBoldText(String(record.text ?? "")) ?? String(record.text ?? "")
215013
+ );
215014
+ }
215015
+ const item = toRecord(record.item);
215016
+ if (!item || item.type !== "reasoning") return null;
215017
+ return normalizeProgressMessage(
215018
+ extractBoldText(String(item.text ?? "")) ?? String(item.text ?? "")
215019
+ );
215020
+ };
215021
+ extractThreadIdFromJsonLine = (line) => {
215022
+ const trimmed = line.trim();
215023
+ if (!trimmed.startsWith("{")) return null;
215024
+ let parsed;
215025
+ try {
215026
+ parsed = JSON.parse(trimmed);
215027
+ } catch {
215028
+ return null;
215029
+ }
215030
+ const record = toRecord(parsed);
215031
+ if (!record || record.type !== "thread.started") return null;
215032
+ const threadId2 = record.thread_id;
215033
+ return typeof threadId2 === "string" && threadId2.length > 0 ? threadId2 : null;
215034
+ };
215035
+ }
215036
+ });
215037
+
214977
215038
  // src/devbox/commands/init/codex/remote.ts
214978
- var import_node_child_process11, stripAnsi2, decodeBase643, parseExitCode2, parseRemoteExecMessage, extractBoldText, extractAuthUrl, extractLocalPort, isRelayForbidden, isRelayMissingOpenAiProxyConfiguration, summarizeExecOutput, buildEntrypointsBlock, resolveRemoteApplyTemplateName, renderRemoteApplyPromptFromTemplate, renderRemoteApplyPrompt, openBrowser3, ensureRemoteCodexInstalled, isRemoteCodexLoggedIn, runRemoteCodexLogin, runRemoteCodexExec;
215039
+ var import_node_child_process11, decodeBase643, parseExitCode2, parseRemoteExecMessage, extractAuthUrl, extractLocalPort, summarizeExecOutput, buildEntrypointsBlock, resolveRemoteApplyTemplateName, renderRemoteApplyPromptFromTemplate, renderRemoteApplyPrompt, openBrowser3, ensureRemoteCodexInstalled, isRemoteCodexLoggedIn, runRemoteCodexLogin, runRemoteCodexExec;
214979
215040
  var init_remote2 = __esm({
214980
215041
  "src/devbox/commands/init/codex/remote.ts"() {
214981
215042
  "use strict";
214982
215043
  import_node_child_process11 = require("node:child_process");
214983
215044
  init_prompts();
214984
215045
  init_template();
214985
- stripAnsi2 = (value) => value.replace(/\u001b\[[0-9;]*[A-Za-z]/g, "");
215046
+ init_events();
214986
215047
  decodeBase643 = (value) => {
214987
215048
  if (typeof value !== "string") return Buffer.alloc(0);
214988
215049
  try {
@@ -215039,11 +215100,6 @@ var init_remote2 = __esm({
215039
215100
  }
215040
215101
  return { kind: "raw" };
215041
215102
  };
215042
- extractBoldText = (line) => {
215043
- const match2 = line.match(/\*\*([^*]+)\*\*/);
215044
- const text = match2?.[1];
215045
- return text ? text.trim() : null;
215046
- };
215047
215103
  extractAuthUrl = (value) => {
215048
215104
  const match2 = value.match(
215049
215105
  /https:\/\/auth\.openai\.com\/oauth\/authorize[^\s]+/
@@ -215063,8 +215119,6 @@ var init_remote2 = __esm({
215063
215119
  }
215064
215120
  return null;
215065
215121
  };
215066
- isRelayForbidden = (value) => /(unexpected status 403 Forbidden|403 Forbidden: forbidden)/i.test(value) && /\/v1\/responses/i.test(value);
215067
- isRelayMissingOpenAiProxyConfiguration = (value) => /unexpected status 503 Service Unavailable/i.test(value) && /missing OpenAI proxy configuration/i.test(value) && /\/v1\/responses/i.test(value);
215068
215122
  summarizeExecOutput = (stderr, stdout) => {
215069
215123
  const summarize = (value) => {
215070
215124
  const cleaned = stripAnsi2(value);
@@ -215499,7 +215553,7 @@ fi`
215499
215553
  cmd,
215500
215554
  tty: tty2,
215501
215555
  onProgress
215502
- }) => new Promise((resolve2, reject) => {
215556
+ }) => new Promise((resolve2) => {
215503
215557
  const ws = client2.openExecSession(spriteAlias, {
215504
215558
  cmd,
215505
215559
  tty: tty2 ?? false,
@@ -215512,10 +215566,25 @@ fi`
215512
215566
  let exitCode = null;
215513
215567
  let resolved = false;
215514
215568
  let lastProgress = null;
215569
+ let threadId2 = null;
215515
215570
  const handleLine = (line) => {
215516
- if (!onProgress) return;
215517
215571
  const clean = stripAnsi2(line);
215518
- const bold = extractBoldText(clean);
215572
+ if (!threadId2) {
215573
+ const parsedThreadId = extractThreadIdFromJsonLine(clean);
215574
+ if (parsedThreadId) {
215575
+ threadId2 = parsedThreadId;
215576
+ }
215577
+ }
215578
+ if (!onProgress) return;
215579
+ const parsed = extractProgressFromJsonLine(clean);
215580
+ if (parsed) {
215581
+ if (parsed === lastProgress) return;
215582
+ lastProgress = parsed;
215583
+ onProgress(parsed);
215584
+ return;
215585
+ }
215586
+ if (clean.trimStart().startsWith("{")) return;
215587
+ const bold = normalizeProgressMessage(extractBoldText(clean));
215519
215588
  if (!bold || bold === lastProgress) return;
215520
215589
  lastProgress = bold;
215521
215590
  onProgress(bold);
@@ -215654,46 +215723,11 @@ fi`
215654
215723
  if (stderrBuffer) {
215655
215724
  handleLine(stderrBuffer);
215656
215725
  }
215657
- if (code2 === null) {
215658
- const detail2 = summarizeExecOutput(stderr, stdout);
215659
- const suffix2 = detail2 ? `: ${detail2}` : "";
215660
- reject(
215661
- new Error(
215662
- `codex exec failed: remote exec stream closed before exit status${suffix2}`
215663
- )
215664
- );
215665
- return;
215666
- }
215667
- const finalCode = code2;
215668
- if (finalCode === 0) {
215669
- resolve2({ stdout, stderr });
215670
- return;
215671
- }
215672
- if (isRelayForbidden(`${stderr}
215673
- ${stdout}`)) {
215674
- reject(
215675
- new Error(
215676
- "codex exec failed: relay proxy returned 403 forbidden. Run `dvb setup --codex-auth byo` and retry with `dvb init --resume`."
215677
- )
215678
- );
215679
- return;
215680
- }
215681
- if (isRelayMissingOpenAiProxyConfiguration(`${stderr}
215682
- ${stdout}`)) {
215683
- reject(
215684
- new Error(
215685
- "codex exec failed: relay proxy is missing OPENAI_API_KEY configuration. Re-run `just dev` so the relay tunnel deploy includes OPENAI_API_KEY, then retry with `dvb init --resume`."
215686
- )
215687
- );
215688
- return;
215689
- }
215690
- const detail = summarizeExecOutput(stderr, stdout);
215691
- const suffix = detail ? `: ${detail}` : "";
215692
- reject(new Error(`codex exec failed (exit ${finalCode})${suffix}`));
215726
+ resolve2({ stdout, stderr, exitCode: code2, threadId: threadId2 });
215693
215727
  };
215694
215728
  ws.addEventListener("message", onMessage);
215695
215729
  ws.addEventListener("close", () => finish(exitCode));
215696
- ws.addEventListener("error", () => finish(exitCode ?? 1));
215730
+ ws.addEventListener("error", () => finish(exitCode));
215697
215731
  });
215698
215732
  }
215699
215733
  });
@@ -215937,6 +215971,29 @@ var init_proxy2 = __esm({
215937
215971
  }
215938
215972
  });
215939
215973
 
215974
+ // src/devbox/commands/init/codex/retry.ts
215975
+ var DEFAULT_CODEX_EXEC_MAX_ATTEMPTS, delay2, computeCodexExecRetryDelayMs, RetryableCodexExecError;
215976
+ var init_retry = __esm({
215977
+ "src/devbox/commands/init/codex/retry.ts"() {
215978
+ "use strict";
215979
+ DEFAULT_CODEX_EXEC_MAX_ATTEMPTS = 3;
215980
+ delay2 = async (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
215981
+ computeCodexExecRetryDelayMs = (attempt) => {
215982
+ const baseMs = 1e3;
215983
+ const capMs = 8e3;
215984
+ return Math.min(capMs, baseMs * 2 ** Math.max(0, attempt - 1));
215985
+ };
215986
+ RetryableCodexExecError = class extends Error {
215987
+ sessionId;
215988
+ constructor(message, sessionId) {
215989
+ super(message);
215990
+ this.name = "RetryableCodexExecError";
215991
+ this.sessionId = sessionId;
215992
+ }
215993
+ };
215994
+ }
215995
+ });
215996
+
215940
215997
  // src/devbox/commands/init/clack.ts
215941
215998
  var import_node_util4, apply, wrapLine, DEFAULT_MULTISELECT_HELP, multiselectWithHelp;
215942
215999
  var init_clack = __esm({
@@ -216080,7 +216137,7 @@ ${bottom}
216080
216137
  });
216081
216138
 
216082
216139
  // src/devbox/commands/init/codex/local.ts
216083
- var import_node_child_process12, import_node_fs10, import_promises25, import_node_os15, import_node_path29, stripAnsi3, extractBoldText2, normalizeProgressMessage, toRecord, extractProgressFromJsonLine, extractThreadIdFromJsonLine, isRelayUsageLimitExceeded, isRelayForbidden2, isRelayMissingOpenAiProxyConfiguration2, CODEX_REQUEST_URL_REGEX, extractRequestUrl, isStreamDisconnected, isLoopbackRelayUrl, buildRetryPrompt, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
216140
+ var import_node_child_process12, import_node_fs10, import_promises25, import_node_os15, import_node_path29, isRelayUsageLimitExceeded, isRelayForbidden, isRelayMissingOpenAiProxyConfiguration, CODEX_REQUEST_URL_REGEX, extractRequestUrl, isStreamDisconnected, isLoopbackRelayUrl, buildRetryPrompt, parseCodexExecArgs, buildCodexExecArgs, formatCodexRetryProgress, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
216084
216141
  var init_local = __esm({
216085
216142
  "src/devbox/commands/init/codex/local.ts"() {
216086
216143
  "use strict";
@@ -216093,63 +216150,12 @@ var init_local = __esm({
216093
216150
  init_prompts();
216094
216151
  init_proxy2();
216095
216152
  init_execConfig();
216153
+ init_events();
216154
+ init_retry();
216096
216155
  init_clack();
216097
- stripAnsi3 = (value) => value.replace(/\u001b\[[0-9;]*[A-Za-z]/g, "");
216098
- extractBoldText2 = (line) => {
216099
- const match2 = line.match(/\*\*([^*]+)\*\*/);
216100
- const text = match2?.[1];
216101
- return text ? text.trim() : null;
216102
- };
216103
- normalizeProgressMessage = (value) => {
216104
- if (!value) return null;
216105
- const normalized = value.replace(/\s+/g, " ").trim();
216106
- if (!normalized) return null;
216107
- if (normalized.length > 140) return null;
216108
- if (!/[A-Za-z]/.test(normalized)) return null;
216109
- if (/\\[nrt"\\]/.test(normalized)) return null;
216110
- if (/[\[\]{}]/.test(normalized)) return null;
216111
- return normalized;
216112
- };
216113
- toRecord = (value) => typeof value === "object" && value !== null ? value : null;
216114
- extractProgressFromJsonLine = (line) => {
216115
- const trimmed = line.trim();
216116
- if (!trimmed.startsWith("{")) return null;
216117
- let parsed;
216118
- try {
216119
- parsed = JSON.parse(trimmed);
216120
- } catch {
216121
- return null;
216122
- }
216123
- const record = toRecord(parsed);
216124
- if (!record) return null;
216125
- if (record.type === "reasoning") {
216126
- return normalizeProgressMessage(
216127
- extractBoldText2(String(record.text ?? "")) ?? String(record.text ?? "")
216128
- );
216129
- }
216130
- const item = toRecord(record.item);
216131
- if (!item || item.type !== "reasoning") return null;
216132
- return normalizeProgressMessage(
216133
- extractBoldText2(String(item.text ?? "")) ?? String(item.text ?? "")
216134
- );
216135
- };
216136
- extractThreadIdFromJsonLine = (line) => {
216137
- const trimmed = line.trim();
216138
- if (!trimmed.startsWith("{")) return null;
216139
- let parsed;
216140
- try {
216141
- parsed = JSON.parse(trimmed);
216142
- } catch {
216143
- return null;
216144
- }
216145
- const record = toRecord(parsed);
216146
- if (!record || record.type !== "thread.started") return null;
216147
- const threadId2 = record.thread_id;
216148
- return typeof threadId2 === "string" && threadId2.length > 0 ? threadId2 : null;
216149
- };
216150
216156
  isRelayUsageLimitExceeded = (value) => /usage limit exceeded/i.test(value) && /(?:relay\.boxes\.dev\/v1\/responses|\/v1\/responses)/i.test(value);
216151
- isRelayForbidden2 = (value) => /(unexpected status 403 Forbidden|403 Forbidden: forbidden)/i.test(value) && /\/v1\/responses/i.test(value);
216152
- isRelayMissingOpenAiProxyConfiguration2 = (value) => /unexpected status 503 Service Unavailable/i.test(value) && /missing OpenAI proxy configuration/i.test(value) && /\/v1\/responses/i.test(value);
216157
+ isRelayForbidden = (value) => /(unexpected status 403 Forbidden|403 Forbidden: forbidden)/i.test(value) && /\/v1\/responses/i.test(value);
216158
+ isRelayMissingOpenAiProxyConfiguration = (value) => /unexpected status 503 Service Unavailable/i.test(value) && /missing OpenAI proxy configuration/i.test(value) && /\/v1\/responses/i.test(value);
216153
216159
  CODEX_REQUEST_URL_REGEX = /error sending request for url \(([^)]+)\)/i;
216154
216160
  extractRequestUrl = (value) => {
216155
216161
  const match2 = value.match(CODEX_REQUEST_URL_REGEX);
@@ -216173,12 +216179,58 @@ var init_local = __esm({
216173
216179
  "",
216174
216180
  "Re-run the scan and return corrected JSON."
216175
216181
  ].filter((line) => line.length > 0).join("\n") : basePrompt;
216182
+ parseCodexExecArgs = (args) => {
216183
+ if (args.length === 0) {
216184
+ throw new Error("Missing Codex exec prompt.");
216185
+ }
216186
+ if (args[0] === "resume") {
216187
+ if (args.length < 4) {
216188
+ throw new Error("Invalid Codex resume exec arguments.");
216189
+ }
216190
+ const prompt2 = args.at(-1);
216191
+ const resumeThreadId = args.at(-2);
216192
+ if (!prompt2 || !resumeThreadId) {
216193
+ throw new Error("Invalid Codex resume exec arguments.");
216194
+ }
216195
+ return {
216196
+ sharedArgs: args.slice(1, -2),
216197
+ prompt: prompt2,
216198
+ resumeThreadId
216199
+ };
216200
+ }
216201
+ const prompt = args.at(-1);
216202
+ if (!prompt) {
216203
+ throw new Error("Missing Codex exec prompt.");
216204
+ }
216205
+ return {
216206
+ sharedArgs: args.slice(0, -1),
216207
+ prompt,
216208
+ resumeThreadId: null
216209
+ };
216210
+ };
216211
+ buildCodexExecArgs = ({
216212
+ sharedArgs,
216213
+ prompt,
216214
+ resumeThreadId
216215
+ }) => resumeThreadId ? ["resume", ...sharedArgs, resumeThreadId, prompt] : [...sharedArgs, prompt];
216216
+ formatCodexRetryProgress = ({
216217
+ attempt,
216218
+ maxAttempts,
216219
+ delayMs,
216220
+ sessionId
216221
+ }) => {
216222
+ const nextAttempt = attempt + 1;
216223
+ const delaySeconds = Math.max(1, Math.ceil(delayMs / 1e3));
216224
+ const mode = sessionId ? "continuing existing session" : "starting a fresh session";
216225
+ return `retry ${nextAttempt}/${maxAttempts} in ${delaySeconds}s (${mode})`;
216226
+ };
216176
216227
  runCodexExec = async (cwd, args, onProgress, logOptions = {}) => {
216177
216228
  const {
216178
216229
  stdoutLogPath,
216179
216230
  stderrLogPath,
216180
216231
  proxyOptions,
216181
- trustedPaths = []
216232
+ trustedPaths = [],
216233
+ onRetry
216182
216234
  } = logOptions;
216183
216235
  let stdoutStream = null;
216184
216236
  let stderrStream = null;
@@ -216234,10 +216286,13 @@ var init_local = __esm({
216234
216286
  await new Promise((resolve2) => stream.end(() => resolve2()));
216235
216287
  };
216236
216288
  try {
216237
- return await new Promise((resolve2, reject) => {
216289
+ const baseArgs = parseCodexExecArgs(args);
216290
+ let resumeThreadId = baseArgs.resumeThreadId;
216291
+ let prompt = baseArgs.prompt;
216292
+ const runAttempt = async (attemptArgs, attemptResumeThreadId) => await new Promise((resolve2, reject) => {
216238
216293
  const child = (0, import_node_child_process12.spawn)(
216239
216294
  "codex",
216240
- ["-a", "never", "exec", ...buildCodexInitExecArgs(), ...args],
216295
+ ["-a", "never", "exec", ...buildCodexInitExecArgs(), ...attemptArgs],
216241
216296
  {
216242
216297
  cwd,
216243
216298
  env: childEnv,
@@ -216251,7 +216306,7 @@ var init_local = __esm({
216251
216306
  let lastProgress = null;
216252
216307
  let threadId2 = null;
216253
216308
  const handleLine = (line) => {
216254
- const clean = stripAnsi3(line);
216309
+ const clean = stripAnsi2(line);
216255
216310
  if (!threadId2) {
216256
216311
  const parsedThreadId = extractThreadIdFromJsonLine(clean);
216257
216312
  if (parsedThreadId) {
@@ -216267,7 +216322,7 @@ var init_local = __esm({
216267
216322
  return;
216268
216323
  }
216269
216324
  if (clean.trimStart().startsWith("{")) return;
216270
- const bold = normalizeProgressMessage(extractBoldText2(clean));
216325
+ const bold = normalizeProgressMessage(extractBoldText(clean));
216271
216326
  if (!bold || bold === lastProgress) return;
216272
216327
  lastProgress = bold;
216273
216328
  onProgress(bold);
@@ -216302,12 +216357,13 @@ var init_local = __esm({
216302
216357
  if (stdoutBuffer) handleLine(stdoutBuffer);
216303
216358
  if (stderrBuffer) handleLine(stderrBuffer);
216304
216359
  if (code2 === 0) {
216305
- resolve2({ threadId: threadId2 });
216360
+ resolve2({ threadId: threadId2 ?? attemptResumeThreadId });
216306
216361
  return;
216307
216362
  }
216308
216363
  const combinedOutput = `${stderr}
216309
216364
  ${stdout}`;
216310
216365
  const detail = stderr.trim() || stdout.trim();
216366
+ const sessionId = threadId2 ?? attemptResumeThreadId;
216311
216367
  if (isRelayUsageLimitExceeded(combinedOutput)) {
216312
216368
  reject(
216313
216369
  new Error(
@@ -216316,7 +216372,7 @@ ${stdout}`;
216316
216372
  );
216317
216373
  return;
216318
216374
  }
216319
- if (isRelayForbidden2(combinedOutput)) {
216375
+ if (isRelayForbidden(combinedOutput)) {
216320
216376
  reject(
216321
216377
  new Error(
216322
216378
  "Codex scan failed: relay proxy returned 403 forbidden. If you're using a dev/local relay config, keep local scans on that relay or run `dvb setup --codex-auth byo`, then retry with `dvb init --resume`."
@@ -216324,7 +216380,7 @@ ${stdout}`;
216324
216380
  );
216325
216381
  return;
216326
216382
  }
216327
- if (isRelayMissingOpenAiProxyConfiguration2(combinedOutput)) {
216383
+ if (isRelayMissingOpenAiProxyConfiguration(combinedOutput)) {
216328
216384
  reject(
216329
216385
  new Error(
216330
216386
  "Codex scan failed: relay proxy is missing OPENAI_API_KEY configuration. Re-run `just dev` so the relay tunnel deploy includes OPENAI_API_KEY, then retry with `dvb init --resume`."
@@ -216344,8 +216400,27 @@ ${stdout}`;
216344
216400
  }
216345
216401
  const requestTarget = requestUrl ?? "relay /v1/responses endpoint";
216346
216402
  reject(
216347
- new Error(
216348
- `Codex scan failed: transport disconnected while calling ${requestTarget}. Check relay health/auth and retry with \`dvb init --resume\`.`
216403
+ new RetryableCodexExecError(
216404
+ `Codex scan failed: transport disconnected while calling ${requestTarget}. Check relay health/auth and retry with \`dvb init --resume\`.`,
216405
+ sessionId
216406
+ )
216407
+ );
216408
+ return;
216409
+ }
216410
+ if (/no last agent message/i.test(combinedOutput)) {
216411
+ reject(
216412
+ new RetryableCodexExecError(
216413
+ "Codex scan failed: Codex session ended without a final response. Retry with `dvb init --resume`.",
216414
+ sessionId
216415
+ )
216416
+ );
216417
+ return;
216418
+ }
216419
+ if (code2 === null) {
216420
+ reject(
216421
+ new RetryableCodexExecError(
216422
+ "Codex scan failed: Codex session ended before reporting an exit status. Retry with `dvb init --resume`.",
216423
+ sessionId
216349
216424
  )
216350
216425
  );
216351
216426
  return;
@@ -216356,6 +216431,31 @@ ${stdout}`;
216356
216431
  );
216357
216432
  });
216358
216433
  });
216434
+ for (let attempt = 1; attempt <= DEFAULT_CODEX_EXEC_MAX_ATTEMPTS; attempt += 1) {
216435
+ const attemptArgs = buildCodexExecArgs({
216436
+ sharedArgs: baseArgs.sharedArgs,
216437
+ prompt,
216438
+ resumeThreadId
216439
+ });
216440
+ try {
216441
+ return await runAttempt(attemptArgs, resumeThreadId);
216442
+ } catch (error2) {
216443
+ if (!(error2 instanceof RetryableCodexExecError) || attempt >= DEFAULT_CODEX_EXEC_MAX_ATTEMPTS) {
216444
+ throw error2;
216445
+ }
216446
+ resumeThreadId = error2.sessionId ?? resumeThreadId;
216447
+ const delayMs = computeCodexExecRetryDelayMs(attempt);
216448
+ await onRetry?.({
216449
+ attempt,
216450
+ maxAttempts: DEFAULT_CODEX_EXEC_MAX_ATTEMPTS,
216451
+ delayMs,
216452
+ sessionId: resumeThreadId
216453
+ });
216454
+ await delay2(delayMs);
216455
+ prompt = resumeThreadId ? "continue" : baseArgs.prompt;
216456
+ }
216457
+ }
216458
+ throw new Error("Codex exec failed after retries.");
216359
216459
  } finally {
216360
216460
  await Promise.all([closeStream(stdoutStream), closeStream(stderrStream)]);
216361
216461
  if (tempCodexHome) {
@@ -216427,7 +216527,12 @@ ${stdout}`;
216427
216527
  stdoutLogPath,
216428
216528
  stderrLogPath,
216429
216529
  ...proxyOptions ? { proxyOptions } : {},
216430
- trustedPaths: [cwd]
216530
+ trustedPaths: [cwd],
216531
+ ...onProgress ? {
216532
+ onRetry: (info) => {
216533
+ onProgress(formatCodexRetryProgress(info));
216534
+ }
216535
+ } : {}
216431
216536
  });
216432
216537
  return result.threadId;
216433
216538
  };
@@ -216497,7 +216602,12 @@ ${stdout}`;
216497
216602
  stdoutLogPath,
216498
216603
  stderrLogPath,
216499
216604
  ...proxyOptions ? { proxyOptions } : {},
216500
- trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd]
216605
+ trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd],
216606
+ ...onProgress ? {
216607
+ onRetry: (info) => {
216608
+ onProgress(formatCodexRetryProgress(info));
216609
+ }
216610
+ } : {}
216501
216611
  });
216502
216612
  return result.threadId;
216503
216613
  };
@@ -216565,7 +216675,12 @@ ${stdout}`;
216565
216675
  stdoutLogPath,
216566
216676
  stderrLogPath,
216567
216677
  ...proxyOptions ? { proxyOptions } : {},
216568
- trustedPaths: [cwd]
216678
+ trustedPaths: [cwd],
216679
+ ...onProgress ? {
216680
+ onRetry: (info) => {
216681
+ onProgress(formatCodexRetryProgress(info));
216682
+ }
216683
+ } : {}
216569
216684
  });
216570
216685
  return result.threadId;
216571
216686
  };
@@ -216635,7 +216750,12 @@ ${stdout}`;
216635
216750
  stdoutLogPath,
216636
216751
  stderrLogPath,
216637
216752
  ...proxyOptions ? { proxyOptions } : {},
216638
- trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd]
216753
+ trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd],
216754
+ ...onProgress ? {
216755
+ onRetry: (info) => {
216756
+ onProgress(formatCodexRetryProgress(info));
216757
+ }
216758
+ } : {}
216639
216759
  });
216640
216760
  return result.threadId;
216641
216761
  };
@@ -217103,7 +217223,7 @@ var init_artifacts = __esm({
217103
217223
  });
217104
217224
 
217105
217225
  // src/devbox/commands/init/codex/index.ts
217106
- var import_node_path31, import_node_crypto16, import_promises27, import_node_os17, CODEX_REQUEST_URL_REGEX2, CODEX_STREAM_DISCONNECT_DETAIL_REGEX, CODEX_SESSION_ID_REGEX, extractRequestUrl2, extractStreamDisconnectDetail, extractCodexSessionId, summarizeCodexOutputDetail, summarizeCodexFailureDetail, isLoopbackRelayUrl2, resolveLocalCodexAuthPathCandidates, readLocalCodexAuthCache, syncLocalCodexAuthCacheToSprite, uploadSetupPlan, runRemoteCodexSetup;
217226
+ var import_node_path31, import_node_crypto16, import_promises27, import_node_os17, CODEX_REQUEST_URL_REGEX2, CODEX_STREAM_DISCONNECT_DETAIL_REGEX, CODEX_SESSION_ID_REGEX, REMOTE_RELAY_FORBIDDEN_REGEX, REMOTE_RELAY_MISSING_OPENAI_CONFIG_REGEX, extractRequestUrl2, extractStreamDisconnectDetail, extractCodexSessionId, summarizeCodexOutputDetail, summarizeCodexFailureDetail, isRelayForbidden2, isRelayMissingOpenAiProxyConfiguration2, formatCodexRetryProgress2, classifyRemoteCodexSetupFailure, isLoopbackRelayUrl2, resolveLocalCodexAuthPathCandidates, readLocalCodexAuthCache, syncLocalCodexAuthCacheToSprite, uploadSetupPlan, runRemoteCodexSetup;
217107
217227
  var init_codex = __esm({
217108
217228
  "src/devbox/commands/init/codex/index.ts"() {
217109
217229
  "use strict";
@@ -217123,9 +217243,12 @@ var init_codex = __esm({
217123
217243
  init_proxy2();
217124
217244
  init_artifacts();
217125
217245
  init_progress();
217246
+ init_retry();
217126
217247
  CODEX_REQUEST_URL_REGEX2 = /error sending request for url \(([^)]+)\)/i;
217127
217248
  CODEX_STREAM_DISCONNECT_DETAIL_REGEX = /stream disconnected before completion:\s*([^\n\r]+)/i;
217128
217249
  CODEX_SESSION_ID_REGEX = /session id:\s*([0-9a-f-]{20,})/i;
217250
+ REMOTE_RELAY_FORBIDDEN_REGEX = /(unexpected status 403 Forbidden|403 Forbidden: forbidden)/i;
217251
+ REMOTE_RELAY_MISSING_OPENAI_CONFIG_REGEX = /unexpected status 503 Service Unavailable/i;
217129
217252
  extractRequestUrl2 = (value) => {
217130
217253
  const match2 = value.match(CODEX_REQUEST_URL_REGEX2);
217131
217254
  const url = match2?.[1]?.trim();
@@ -217151,12 +217274,13 @@ var init_codex = __esm({
217151
217274
  };
217152
217275
  summarizeCodexFailureDetail = ({
217153
217276
  combinedOutputRaw,
217154
- lastMessageReadError
217277
+ lastMessageReadError,
217278
+ sessionId
217155
217279
  }) => {
217156
217280
  const parts = [];
217157
- const sessionId = extractCodexSessionId(combinedOutputRaw);
217158
- if (sessionId) {
217159
- parts.push(`session id: ${sessionId}`);
217281
+ const resolvedSessionId = sessionId ?? extractCodexSessionId(combinedOutputRaw);
217282
+ if (resolvedSessionId) {
217283
+ parts.push(`session id: ${resolvedSessionId}`);
217160
217284
  }
217161
217285
  const outputDetail = summarizeCodexOutputDetail(combinedOutputRaw);
217162
217286
  if (outputDetail) {
@@ -217169,6 +217293,143 @@ var init_codex = __esm({
217169
217293
  if (parts.length === 0) return null;
217170
217294
  return parts.join(" | ");
217171
217295
  };
217296
+ isRelayForbidden2 = (value) => REMOTE_RELAY_FORBIDDEN_REGEX.test(value) && /\/v1\/responses/i.test(value);
217297
+ isRelayMissingOpenAiProxyConfiguration2 = (value) => REMOTE_RELAY_MISSING_OPENAI_CONFIG_REGEX.test(value) && /missing OpenAI proxy configuration/i.test(value) && /\/v1\/responses/i.test(value);
217298
+ formatCodexRetryProgress2 = ({
217299
+ attempt,
217300
+ maxAttempts,
217301
+ delayMs,
217302
+ sessionId
217303
+ }) => {
217304
+ const nextAttempt = attempt + 1;
217305
+ const delaySeconds = Math.max(1, Math.ceil(delayMs / 1e3));
217306
+ const mode = sessionId ? "continuing existing session" : "starting a fresh session";
217307
+ return `retry ${nextAttempt}/${maxAttempts} in ${delaySeconds}s (${mode})`;
217308
+ };
217309
+ classifyRemoteCodexSetupFailure = ({
217310
+ execResult,
217311
+ lastMessageReadError
217312
+ }) => {
217313
+ const combinedOutputRaw = `${execResult.stdout}
217314
+ ${execResult.stderr}`;
217315
+ const combinedOutput = combinedOutputRaw.toLowerCase();
217316
+ const sessionId = execResult.threadId ?? extractCodexSessionId(combinedOutputRaw);
217317
+ if (combinedOutput.includes("401 unauthorized")) {
217318
+ return {
217319
+ error: new Error(
217320
+ "codex exec failed: remote Codex auth returned 401 unauthorized. Re-run `dvb setup --codex-auth byo` (or ensure proxy auth is configured), then retry with `dvb init --resume`."
217321
+ ),
217322
+ retryable: false,
217323
+ sessionId
217324
+ };
217325
+ }
217326
+ if (isRelayForbidden2(combinedOutputRaw)) {
217327
+ return {
217328
+ error: new Error(
217329
+ "codex exec failed: relay proxy returned 403 forbidden. Run `dvb setup --codex-auth byo` and retry with `dvb init --resume`."
217330
+ ),
217331
+ retryable: false,
217332
+ sessionId
217333
+ };
217334
+ }
217335
+ if (isRelayMissingOpenAiProxyConfiguration2(combinedOutputRaw)) {
217336
+ return {
217337
+ error: new Error(
217338
+ "codex exec failed: relay proxy is missing OPENAI_API_KEY configuration. Re-run `just dev` so the relay tunnel deploy includes OPENAI_API_KEY, then retry with `dvb init --resume`."
217339
+ ),
217340
+ retryable: false,
217341
+ sessionId
217342
+ };
217343
+ }
217344
+ if (execResult.exitCode === null) {
217345
+ const detail2 = summarizeCodexFailureDetail({
217346
+ combinedOutputRaw,
217347
+ sessionId
217348
+ });
217349
+ const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217350
+ return {
217351
+ error: new Error(
217352
+ `codex exec failed: remote exec stream closed before exit status.${detailSuffix2}`
217353
+ ),
217354
+ retryable: true,
217355
+ sessionId
217356
+ };
217357
+ }
217358
+ if (combinedOutput.includes("stream disconnected before completion")) {
217359
+ const requestUrl = extractRequestUrl2(combinedOutputRaw);
217360
+ const detail2 = extractStreamDisconnectDetail(combinedOutputRaw) ?? summarizeCodexOutputDetail(combinedOutputRaw);
217361
+ const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217362
+ if (requestUrl && isLoopbackRelayUrl2(requestUrl)) {
217363
+ return {
217364
+ error: new Error(
217365
+ `codex exec failed: local relay is unreachable at ${requestUrl}. Set a reachable remote relay URL (for example \`DEVBOX_REMOTE_RELAY_BASE_URL=https://relay.boxes.dev\`), run \`dvb setup\`, then retry with \`dvb init --resume\`.${detailSuffix2}`
217366
+ ),
217367
+ retryable: false,
217368
+ sessionId
217369
+ };
217370
+ }
217371
+ const requestTarget = requestUrl ?? "relay /v1/responses endpoint";
217372
+ return {
217373
+ error: new Error(
217374
+ `codex exec failed: proxy stream disconnected before completion while calling ${requestTarget}. Ensure relay connectivity from the remote devbox, then retry with \`dvb init --resume\`.${detailSuffix2}`
217375
+ ),
217376
+ retryable: true,
217377
+ sessionId
217378
+ };
217379
+ }
217380
+ if (combinedOutput.includes("no last agent message")) {
217381
+ const detail2 = summarizeCodexFailureDetail({
217382
+ combinedOutputRaw,
217383
+ sessionId
217384
+ });
217385
+ const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217386
+ return {
217387
+ error: new Error(
217388
+ `codex exec failed: Codex session ended without a final response.${detailSuffix2} Setup was not applied; retry with \`dvb init --resume\`.`
217389
+ ),
217390
+ retryable: true,
217391
+ sessionId
217392
+ };
217393
+ }
217394
+ if (lastMessageReadError) {
217395
+ const detail2 = summarizeCodexFailureDetail({
217396
+ combinedOutputRaw,
217397
+ lastMessageReadError,
217398
+ sessionId
217399
+ });
217400
+ const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217401
+ return {
217402
+ error: new Error(
217403
+ `codex exec failed: Codex session ended without writing the final response file.${detailSuffix2} Setup may be incomplete; retry with \`dvb init --resume\`.`
217404
+ ),
217405
+ retryable: true,
217406
+ sessionId
217407
+ };
217408
+ }
217409
+ if (execResult.exitCode !== 0) {
217410
+ const detail2 = summarizeCodexOutputDetail(combinedOutputRaw);
217411
+ const detailSuffix2 = detail2 ? `: ${detail2}` : "";
217412
+ return {
217413
+ error: new Error(
217414
+ `codex exec failed (exit ${String(execResult.exitCode)})${detailSuffix2}`
217415
+ ),
217416
+ retryable: false,
217417
+ sessionId
217418
+ };
217419
+ }
217420
+ const detail = summarizeCodexFailureDetail({
217421
+ combinedOutputRaw,
217422
+ sessionId
217423
+ });
217424
+ const detailSuffix = detail ? ` Detail: ${detail}` : "";
217425
+ return {
217426
+ error: new Error(
217427
+ `codex exec failed: Codex session ended without a final response.${detailSuffix} Setup was not applied; retry with \`dvb init --resume\`.`
217428
+ ),
217429
+ retryable: true,
217430
+ sessionId
217431
+ };
217432
+ };
217172
217433
  isLoopbackRelayUrl2 = (requestUrl) => {
217173
217434
  try {
217174
217435
  const url = new URL(requestUrl);
@@ -217697,44 +217958,59 @@ codex login`
217697
217958
  throw error2;
217698
217959
  }
217699
217960
  }
217700
- const remoteCodexExecCommand = `codex exec ${[
217961
+ const buildRemoteCodexExecArgs = ({
217962
+ prompt,
217963
+ resumeSessionId
217964
+ }) => resumeSessionId ? [
217701
217965
  ...buildCodexInitExecArgs(),
217966
+ "resume",
217702
217967
  "--dangerously-bypass-approvals-and-sandbox",
217968
+ "--json",
217703
217969
  "--output-last-message",
217704
217970
  codexLastMessagePath,
217705
- remotePrompt
217706
- ].map((arg2) => shellQuote5(arg2)).join(" ")}`;
217707
- const remoteCodexCommand = [
217708
- pathSetup,
217709
- ...proxyRoot && proxyTokenPath && proxyCodexHome ? [
217710
- `proxy_root=${shellQuote5(proxyRoot)}`,
217711
- `proxy_token=${shellQuote5(proxyTokenPath)}`,
217712
- `cleanup_proxy() { rm -rf "$proxy_root"; }`,
217713
- "trap cleanup_proxy EXIT",
217714
- 'export DEVBOX_TOKEN="$(cat "$proxy_token")"',
217715
- `export CODEX_HOME=${shellQuote5(proxyCodexHome)}`
217716
- ] : [],
217717
- `cd ${shellQuote5(expandedWorkdir)}`,
217718
- remoteCodexExecCommand
217719
- ].join("\n");
217720
- await client2.exec(spriteAlias, [
217721
- "/bin/bash",
217722
- "--noprofile",
217723
- "--norc",
217724
- "-e",
217725
- "-u",
217726
- "-o",
217727
- "pipefail",
217728
- "-c",
217729
- `rm -f ${shellQuote5(codexLastMessagePath)}`
217730
- ]).catch(() => {
217731
- });
217732
- let execResult = null;
217971
+ resumeSessionId,
217972
+ prompt
217973
+ ] : [
217974
+ ...buildCodexInitExecArgs(),
217975
+ "--dangerously-bypass-approvals-and-sandbox",
217976
+ "--json",
217977
+ "--output-last-message",
217978
+ codexLastMessagePath,
217979
+ prompt
217980
+ ];
217981
+ const buildRemoteCodexCommand = ({
217982
+ prompt,
217983
+ resumeSessionId
217984
+ }) => {
217985
+ const remoteCodexExecCommand = `codex exec ${buildRemoteCodexExecArgs({
217986
+ prompt,
217987
+ resumeSessionId
217988
+ }).map((arg2) => shellQuote5(arg2)).join(" ")}`;
217989
+ return [
217990
+ pathSetup,
217991
+ ...proxyRoot && proxyTokenPath && proxyCodexHome ? [
217992
+ `proxy_root=${shellQuote5(proxyRoot)}`,
217993
+ `proxy_token=${shellQuote5(proxyTokenPath)}`,
217994
+ `cleanup_proxy() { rm -rf "$proxy_root"; }`,
217995
+ "trap cleanup_proxy EXIT",
217996
+ 'export DEVBOX_TOKEN="$(cat "$proxy_token")"',
217997
+ `export CODEX_HOME=${shellQuote5(proxyCodexHome)}`
217998
+ ] : [],
217999
+ `cd ${shellQuote5(expandedWorkdir)}`,
218000
+ remoteCodexExecCommand
218001
+ ].join("\n");
218002
+ };
218003
+ let lastMessage = "";
217733
218004
  try {
217734
- execResult = await runRemoteCodexExec({
217735
- client: client2,
217736
- spriteAlias,
217737
- cmd: [
218005
+ let resumeSessionId = null;
218006
+ for (let attempt = 1; attempt <= DEFAULT_CODEX_EXEC_MAX_ATTEMPTS; attempt += 1) {
218007
+ const prompt = attempt === 1 ? remotePrompt : resumeSessionId ? "continue" : remotePrompt;
218008
+ const remoteCodexCommand = buildRemoteCodexCommand({
218009
+ prompt,
218010
+ resumeSessionId
218011
+ });
218012
+ status.stage("Apply setup plan");
218013
+ await client2.exec(spriteAlias, [
217738
218014
  "/bin/bash",
217739
218015
  "--noprofile",
217740
218016
  "--norc",
@@ -217743,13 +218019,60 @@ codex login`
217743
218019
  "-o",
217744
218020
  "pipefail",
217745
218021
  "-c",
217746
- remoteCodexCommand
217747
- ],
217748
- onProgress: (message) => {
217749
- const base = "Apply setup plan";
217750
- status.stage(`${base} - ${message}`);
218022
+ `rm -f ${shellQuote5(codexLastMessagePath)}`
218023
+ ]).catch(() => {
218024
+ });
218025
+ const execResult = await runRemoteCodexExec({
218026
+ client: client2,
218027
+ spriteAlias,
218028
+ cmd: [
218029
+ "/bin/bash",
218030
+ "--noprofile",
218031
+ "--norc",
218032
+ "-e",
218033
+ "-u",
218034
+ "-o",
218035
+ "pipefail",
218036
+ "-c",
218037
+ remoteCodexCommand
218038
+ ],
218039
+ onProgress: (message) => {
218040
+ status.stage(`Apply setup plan - ${message}`);
218041
+ }
218042
+ });
218043
+ let attemptLastMessage = "";
218044
+ let lastMessageReadError = null;
218045
+ try {
218046
+ const bytes = await client2.readFile(spriteAlias, {
218047
+ path: codexLastMessagePath
218048
+ });
218049
+ attemptLastMessage = Buffer.from(bytes).toString("utf8").trim();
218050
+ } catch (error2) {
218051
+ lastMessageReadError = error2 instanceof Error ? error2 : new Error(String(error2));
217751
218052
  }
217752
- });
218053
+ if (execResult.exitCode === 0 && attemptLastMessage) {
218054
+ lastMessage = attemptLastMessage;
218055
+ break;
218056
+ }
218057
+ const failure = classifyRemoteCodexSetupFailure({
218058
+ execResult,
218059
+ ...attemptLastMessage ? {} : { lastMessageReadError }
218060
+ });
218061
+ if (!failure.retryable || attempt >= DEFAULT_CODEX_EXEC_MAX_ATTEMPTS) {
218062
+ throw failure.error;
218063
+ }
218064
+ resumeSessionId = failure.sessionId ?? resumeSessionId;
218065
+ const delayMs = computeCodexExecRetryDelayMs(attempt);
218066
+ status.stage(
218067
+ `Apply setup plan - ${formatCodexRetryProgress2({
218068
+ attempt,
218069
+ maxAttempts: DEFAULT_CODEX_EXEC_MAX_ATTEMPTS,
218070
+ delayMs,
218071
+ sessionId: resumeSessionId
218072
+ })}`
218073
+ );
218074
+ await delay2(delayMs);
218075
+ }
217753
218076
  } finally {
217754
218077
  if (proxyRoot) {
217755
218078
  await client2.exec(spriteAlias, [
@@ -217766,65 +218089,8 @@ codex login`
217766
218089
  });
217767
218090
  }
217768
218091
  }
217769
- let lastMessage = "";
217770
- let lastMessageReadError = null;
217771
- try {
217772
- const bytes = await client2.readFile(spriteAlias, {
217773
- path: codexLastMessagePath
217774
- });
217775
- lastMessage = Buffer.from(bytes).toString("utf8").trim();
217776
- } catch (error2) {
217777
- lastMessageReadError = error2 instanceof Error ? error2 : new Error(String(error2));
217778
- }
217779
218092
  if (!lastMessage) {
217780
- const combinedOutputRaw = `${execResult?.stdout ?? ""}
217781
- ${execResult?.stderr ?? ""}`;
217782
- const combinedOutput = combinedOutputRaw.toLowerCase();
217783
- if (combinedOutput.includes("401 unauthorized")) {
217784
- throw new Error(
217785
- "codex exec failed: remote Codex auth returned 401 unauthorized. Re-run `dvb setup --codex-auth byo` (or ensure proxy auth is configured), then retry with `dvb init --resume`."
217786
- );
217787
- }
217788
- if (combinedOutput.includes("stream disconnected before completion")) {
217789
- const requestUrl = extractRequestUrl2(combinedOutputRaw);
217790
- const detail2 = extractStreamDisconnectDetail(combinedOutputRaw) ?? summarizeCodexOutputDetail(combinedOutputRaw);
217791
- const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217792
- if (requestUrl && isLoopbackRelayUrl2(requestUrl)) {
217793
- throw new Error(
217794
- `codex exec failed: local relay is unreachable at ${requestUrl}. Set a reachable remote relay URL (for example \`DEVBOX_REMOTE_RELAY_BASE_URL=https://relay.boxes.dev\`), run \`dvb setup\`, then retry with \`dvb init --resume\`.${detailSuffix2}`
217795
- );
217796
- }
217797
- const requestTarget = requestUrl ?? "relay /v1/responses endpoint";
217798
- throw new Error(
217799
- `codex exec failed: proxy stream disconnected before completion while calling ${requestTarget}. Ensure relay connectivity from the remote devbox, then retry with \`dvb init --resume\`.${detailSuffix2}`
217800
- );
217801
- }
217802
- if (combinedOutput.includes("no last agent message")) {
217803
- const detail2 = summarizeCodexFailureDetail({
217804
- combinedOutputRaw
217805
- });
217806
- const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217807
- throw new Error(
217808
- `codex exec failed: Codex session ended without a final response.${detailSuffix2} Setup was not applied; retry with \`dvb init --resume\`.`
217809
- );
217810
- }
217811
- if (lastMessageReadError) {
217812
- const detail2 = summarizeCodexFailureDetail({
217813
- combinedOutputRaw,
217814
- lastMessageReadError
217815
- });
217816
- const detailSuffix2 = detail2 ? ` Detail: ${detail2}` : "";
217817
- throw new Error(
217818
- `codex exec failed: Codex session ended without writing the final response file.${detailSuffix2} Setup may be incomplete; retry with \`dvb init --resume\`.`
217819
- );
217820
- }
217821
- const detail = summarizeCodexFailureDetail({
217822
- combinedOutputRaw
217823
- });
217824
- const detailSuffix = detail ? ` Detail: ${detail}` : "";
217825
- throw new Error(
217826
- `codex exec failed: Codex session ended without a final response.${detailSuffix} Setup was not applied; retry with \`dvb init --resume\`.`
217827
- );
218093
+ throw new Error("codex exec failed: remote apply exhausted retries.");
217828
218094
  }
217829
218095
  if (!emitCodexOutput) return;
217830
218096
  status.stop();
@@ -221771,7 +222037,7 @@ var init_provider = __esm({
221771
222037
  });
221772
222038
 
221773
222039
  // src/devbox/commands/init/index.ts
221774
- var import_node_path38, import_node_os21, requireDaemonJsonOk, resolveInitStatus, mergeLocalPaths, DEFAULT_INIT_STEP_RETRIES, INIT_STEP_RETRYABLE_STATUSES, INIT_EXEC_RETRYABLE_STATUSES, ALIAS_PATTERN3, RESERVED_ALIAS_PATTERN3, DEFAULT_COMPUTE_PROVIDER, delay2, normalizeAlias4, resolveComputeProvider, validateAlias, computeRetryDelayMs2, getErrorCode2, parseExecUnexpectedResponseStatus2, isRetryableInitError, retryInitStep, extractCheckpointId, throwInitCanceled, confirmDestroyExistingDevbox, runInit;
222040
+ var import_node_path38, import_node_os21, requireDaemonJsonOk, resolveInitStatus, mergeLocalPaths, DEFAULT_INIT_STEP_RETRIES, INIT_STEP_RETRYABLE_STATUSES, INIT_EXEC_RETRYABLE_STATUSES, ALIAS_PATTERN3, RESERVED_ALIAS_PATTERN3, DEFAULT_COMPUTE_PROVIDER, delay3, normalizeAlias4, resolveComputeProvider, validateAlias, computeRetryDelayMs2, getErrorCode2, parseExecUnexpectedResponseStatus2, isRetryableInitError, retryInitStep, extractCheckpointId, throwInitCanceled, confirmDestroyExistingDevbox, runInit;
221775
222041
  var init_init = __esm({
221776
222042
  "src/devbox/commands/init/index.ts"() {
221777
222043
  "use strict";
@@ -221842,7 +222108,7 @@ var init_init = __esm({
221842
222108
  ALIAS_PATTERN3 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
221843
222109
  RESERVED_ALIAS_PATTERN3 = /^dvb-[a-f0-9]{12}-/;
221844
222110
  DEFAULT_COMPUTE_PROVIDER = "modal";
221845
- delay2 = async (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
222111
+ delay3 = async (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
221846
222112
  normalizeAlias4 = (value) => value.trim().toLowerCase();
221847
222113
  resolveComputeProvider = ({
221848
222114
  requested,
@@ -221944,7 +222210,7 @@ var init_init = __esm({
221944
222210
  ...error2 instanceof SpritesApiError ? { status: error2.status } : {},
221945
222211
  ...parseExecUnexpectedResponseStatus2(error2) !== null ? { execStatus: parseExecUnexpectedResponseStatus2(error2) } : {}
221946
222212
  });
221947
- await delay2(computeRetryDelayMs2(retryIndex));
222213
+ await delay3(computeRetryDelayMs2(retryIndex));
221948
222214
  }
221949
222215
  }
221950
222216
  throw lastError instanceof Error ? lastError : new Error(`Init step failed: ${title}`);
@@ -229131,4 +229397,4 @@ smol-toml/dist/index.js:
229131
229397
  */
229132
229398
  //# sourceMappingURL=dvb.cjs.map
229133
229399
 
229134
- //# debugId=a741b1b2-865d-5d60-b44d-6259dcc3a122
229400
+ //# debugId=1518c9c7-f041-5409-b81f-b01b956a3638