@boxes-dev/dvb-runtime 1.0.189 → 1.0.191

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/bin/dvb.cjs +488 -111
  2. package/dist/bin/dvb.cjs.map +1 -1
  3. package/dist/bin/dvbd.cjs +6 -6
  4. package/dist/devbox/commands/init/codex/events.d.ts +7 -1
  5. package/dist/devbox/commands/init/codex/events.d.ts.map +1 -1
  6. package/dist/devbox/commands/init/codex/events.js +228 -7
  7. package/dist/devbox/commands/init/codex/events.js.map +1 -1
  8. package/dist/devbox/commands/init/codex/index.js +2 -2
  9. package/dist/devbox/commands/init/codex/index.js.map +1 -1
  10. package/dist/devbox/commands/init/codex/local.d.ts +16 -5
  11. package/dist/devbox/commands/init/codex/local.d.ts.map +1 -1
  12. package/dist/devbox/commands/init/codex/local.js +174 -45
  13. package/dist/devbox/commands/init/codex/local.js.map +1 -1
  14. package/dist/devbox/commands/init/codex/remote.d.ts +2 -1
  15. package/dist/devbox/commands/init/codex/remote.d.ts.map +1 -1
  16. package/dist/devbox/commands/init/codex/remote.js +12 -8
  17. package/dist/devbox/commands/init/codex/remote.js.map +1 -1
  18. package/dist/devbox/commands/init/scanProgress.d.ts +18 -0
  19. package/dist/devbox/commands/init/scanProgress.d.ts.map +1 -0
  20. package/dist/devbox/commands/init/scanProgress.js +54 -0
  21. package/dist/devbox/commands/init/scanProgress.js.map +1 -0
  22. package/dist/devbox/commands/init/setupPlanFlow.d.ts.map +1 -1
  23. package/dist/devbox/commands/init/setupPlanFlow.js +22 -11
  24. package/dist/devbox/commands/init/setupPlanFlow.js.map +1 -1
  25. package/dist/prompts/local-scan-env-secrets.md +5 -1
  26. package/dist/prompts/local-scan-external.md +5 -1
  27. package/dist/prompts/local-scan-extra-artifacts.md +6 -2
  28. package/dist/prompts/local-services-scan.md +5 -2
  29. package/package.json +2 -2
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]="d891e41c-960d-5274-8d0e-b6e180994258")}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]="12cda96d-089f-5b95-b67d-05e388742689")}catch(e){}}();
4
4
 
5
5
  var __create = Object.create;
6
6
  var __defProp = Object.defineProperty;
@@ -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.189";
88692
- const rawGitSha = "1ace2775538b3d0be8520ebddb5323148f994dd2";
88691
+ const rawPackageVersion = "1.0.191";
88692
+ const rawGitSha = "cfde4319652d34938c2d325010794ab69d2e8d60";
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 };
@@ -120881,9 +120881,9 @@ var init_sentry = __esm({
120881
120881
  sentryEnabled = false;
120882
120882
  uncaughtExceptionMonitorInstalled = false;
120883
120883
  readBuildMetadata2 = () => {
120884
- const rawPackageVersion = "1.0.189";
120885
- const rawGitSha = "1ace2775538b3d0be8520ebddb5323148f994dd2";
120886
- const rawSentryRelease = "boxes-dev-dvb@1.0.189+1ace2775538b3d0be8520ebddb5323148f994dd2";
120884
+ const rawPackageVersion = "1.0.191";
120885
+ const rawGitSha = "cfde4319652d34938c2d325010794ab69d2e8d60";
120886
+ const rawSentryRelease = "boxes-dev-dvb@1.0.191+cfde4319652d34938c2d325010794ab69d2e8d60";
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.189";
124883
+ const raw = "1.0.191";
124884
124884
  return trimVersion(raw);
124885
124885
  };
124886
124886
  readNearestPackageMetadata = (basePath) => {
@@ -215309,7 +215309,7 @@ var init_prompts = __esm({
215309
215309
  });
215310
215310
 
215311
215311
  // src/devbox/commands/init/codex/events.ts
215312
- var stripAnsi2, extractBoldText, normalizeProgressMessage, toRecord, extractTodoListProgress, extractProgressFromJsonLine, extractThreadIdFromJsonLine;
215312
+ var stripAnsi2, extractBoldText, normalizeProgressMessage, toRecord, toProgressUpdate, truncate2, stripShellWrapper, splitShellSegments, tokenizeShellSegment, unquoteToken, isEnvAssignment, isRedirectionToken, isPathLikeToken, isSimpleWordToken, isOptionToken, isInformativeSimpleToken, summarizeShellSegment, isNoopCommandSummary, summarizeCommandSequence, summarizeCommandExecution, extractCommandExecutionProgress, extractTodoListProgress, extractProgressUpdateFromJsonLine, extractThreadIdFromJsonLine, extractTurnFailureFromJsonLine;
215313
215313
  var init_events = __esm({
215314
215314
  "src/devbox/commands/init/codex/events.ts"() {
215315
215315
  "use strict";
@@ -215330,6 +215330,173 @@ var init_events = __esm({
215330
215330
  return normalized;
215331
215331
  };
215332
215332
  toRecord = (value) => typeof value === "object" && value !== null ? value : null;
215333
+ toProgressUpdate = (kind, value) => {
215334
+ const message = normalizeProgressMessage(value);
215335
+ return message ? { kind, message } : null;
215336
+ };
215337
+ truncate2 = (value, max = 72) => value.length <= max ? value : `${value.slice(0, max - 3).trimEnd()}...`;
215338
+ stripShellWrapper = (command) => {
215339
+ const trimmed = command.trim();
215340
+ const shellMatch = trimmed.match(/^\/bin\/(?:bash|zsh|sh)\s+-lc\s+([\s\S]+)$/);
215341
+ const unwrapped = shellMatch?.[1]?.trim() ?? trimmed;
215342
+ if (unwrapped.startsWith("'") && unwrapped.endsWith("'") || unwrapped.startsWith('"') && unwrapped.endsWith('"')) {
215343
+ return unwrapped.slice(1, -1).trim();
215344
+ }
215345
+ return unwrapped;
215346
+ };
215347
+ splitShellSegments = (script) => {
215348
+ const segments = [];
215349
+ let current = "";
215350
+ let quote = null;
215351
+ for (let idx = 0; idx < script.length; idx += 1) {
215352
+ const ch = script[idx];
215353
+ const next = script[idx + 1] ?? "";
215354
+ const prev = script[idx - 1] ?? "";
215355
+ if (quote) {
215356
+ current += ch;
215357
+ if (ch === quote && prev !== "\\") {
215358
+ quote = null;
215359
+ }
215360
+ continue;
215361
+ }
215362
+ if (ch === "'" || ch === '"' || ch === "`") {
215363
+ quote = ch;
215364
+ current += ch;
215365
+ continue;
215366
+ }
215367
+ if (ch === "\n" || ch === ";") {
215368
+ const segment = current.trim();
215369
+ if (segment) segments.push(segment);
215370
+ current = "";
215371
+ continue;
215372
+ }
215373
+ if ((ch === "&" || ch === "|") && next === ch) {
215374
+ const segment = current.trim();
215375
+ if (segment) segments.push(segment);
215376
+ current = "";
215377
+ idx += 1;
215378
+ continue;
215379
+ }
215380
+ if (ch === "|") {
215381
+ const segment = current.trim();
215382
+ if (segment) segments.push(segment);
215383
+ current = "";
215384
+ continue;
215385
+ }
215386
+ current += ch;
215387
+ }
215388
+ const tail = current.trim();
215389
+ if (tail) segments.push(tail);
215390
+ return segments;
215391
+ };
215392
+ tokenizeShellSegment = (segment) => {
215393
+ const tokens = [];
215394
+ let current = "";
215395
+ let quote = null;
215396
+ for (let idx = 0; idx < segment.length; idx += 1) {
215397
+ const ch = segment[idx];
215398
+ const prev = segment[idx - 1] ?? "";
215399
+ if (quote) {
215400
+ current += ch;
215401
+ if (ch === quote && prev !== "\\") {
215402
+ quote = null;
215403
+ }
215404
+ continue;
215405
+ }
215406
+ if (ch === "'" || ch === '"' || ch === "`") {
215407
+ quote = ch;
215408
+ current += ch;
215409
+ continue;
215410
+ }
215411
+ if (/\s/.test(ch)) {
215412
+ if (current) {
215413
+ tokens.push(current);
215414
+ current = "";
215415
+ }
215416
+ continue;
215417
+ }
215418
+ current += ch;
215419
+ }
215420
+ if (current) tokens.push(current);
215421
+ return tokens;
215422
+ };
215423
+ unquoteToken = (token) => {
215424
+ const trimmed = token.trim();
215425
+ const unwrapped = trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("`") && trimmed.endsWith("`") ? trimmed.slice(1, -1) : trimmed;
215426
+ return unwrapped.replace(/\\(["'`\\])/g, "$1").replace(/[\[\]{}]/g, "").trim();
215427
+ };
215428
+ isEnvAssignment = (token) => /^[A-Za-z_][A-Za-z0-9_]*=.*/.test(token);
215429
+ isRedirectionToken = (token) => token === "|" || token === "<" || token === ">" || token === ">>" || /^[0-9]*[<>]/.test(token);
215430
+ isPathLikeToken = (token) => !/\s/.test(token) && /[./]/.test(token) && !token.startsWith("!") && !/[*?()[\]{}|\\]/.test(token);
215431
+ isSimpleWordToken = (token) => /^[A-Za-z0-9_.:-]+$/.test(token) && !isPathLikeToken(token);
215432
+ isOptionToken = (token) => /^--?[A-Za-z0-9][A-Za-z0-9-]*$/.test(token);
215433
+ isInformativeSimpleToken = (token) => isSimpleWordToken(token) && !/^\d+$/.test(token) && token.length > 1;
215434
+ summarizeShellSegment = (segment) => {
215435
+ const tokens = tokenizeShellSegment(segment).map((token) => unquoteToken(token)).filter((token) => token.length > 0);
215436
+ if (tokens.length === 0) return "shell command";
215437
+ let start = 0;
215438
+ while (start < tokens.length && isEnvAssignment(tokens[start])) {
215439
+ start += 1;
215440
+ }
215441
+ const commandTokens = tokens.slice(start);
215442
+ if (commandTokens.length === 0) return "shell command";
215443
+ const executable = commandTokens[0];
215444
+ if (executable === "command" && commandTokens[1] === "-v" && commandTokens[2]) {
215445
+ return truncate2(`command -v ${commandTokens[2]}`);
215446
+ }
215447
+ const args = commandTokens.slice(1).filter((token) => !isRedirectionToken(token));
215448
+ const nonOptionArgs = args.filter((token) => !isOptionToken(token));
215449
+ const simpleSubcommand = nonOptionArgs.find((token) => isInformativeSimpleToken(token)) ?? null;
215450
+ if (simpleSubcommand) {
215451
+ return truncate2(`${executable} ${simpleSubcommand}`);
215452
+ }
215453
+ const pathArg = nonOptionArgs.find((token) => isPathLikeToken(token)) ?? null;
215454
+ if (pathArg) {
215455
+ return truncate2(`${executable} ${pathArg}`);
215456
+ }
215457
+ const optionArg = args.find((token) => isOptionToken(token)) ?? null;
215458
+ if (optionArg) {
215459
+ return truncate2(`${executable} ${optionArg}`);
215460
+ }
215461
+ return truncate2(executable);
215462
+ };
215463
+ isNoopCommandSummary = (summary) => summary === ":" || summary === "true";
215464
+ summarizeCommandSequence = (segments) => {
215465
+ const meaningful = segments.filter((segment) => !isNoopCommandSummary(segment));
215466
+ if (meaningful.length === 0) return "shell command";
215467
+ const probeTarget = meaningful[0]?.match(/^command -v (.+)$/)?.[1] ?? null;
215468
+ const reduced = probeTarget && meaningful[1]?.startsWith(`${probeTarget} `) ? meaningful.slice(1) : meaningful;
215469
+ if (reduced.length === 1) return reduced[0];
215470
+ const previewLimit = 3;
215471
+ const preview = reduced.slice(0, previewLimit).join("; ");
215472
+ if (reduced.length <= previewLimit) return truncate2(preview);
215473
+ return truncate2(`${preview}; +${reduced.length - previewLimit} more`);
215474
+ };
215475
+ summarizeCommandExecution = (command) => {
215476
+ const segments = splitShellSegments(stripShellWrapper(command)).map(
215477
+ summarizeShellSegment
215478
+ );
215479
+ return summarizeCommandSequence(segments);
215480
+ };
215481
+ extractCommandExecutionProgress = (record, item) => {
215482
+ if (item.type !== "command_execution" || typeof item.command !== "string") {
215483
+ return null;
215484
+ }
215485
+ const summary = summarizeCommandExecution(item.command);
215486
+ const exitCode = typeof item.exit_code === "number" ? item.exit_code : null;
215487
+ const recordType = typeof record.type === "string" ? record.type : null;
215488
+ const status = typeof item.status === "string" ? item.status : null;
215489
+ if (recordType === "item.completed" || status === "completed") {
215490
+ if (exitCode !== null && exitCode !== 0) {
215491
+ return toProgressUpdate("command", `failed ${summary} (exit ${exitCode})`);
215492
+ }
215493
+ return toProgressUpdate("command", `done ${summary}`);
215494
+ }
215495
+ if (recordType === "item.started" || status === "in_progress") {
215496
+ return toProgressUpdate("command", `run ${summary}`);
215497
+ }
215498
+ return null;
215499
+ };
215333
215500
  extractTodoListProgress = (item) => {
215334
215501
  if (item.type !== "todo_list" || !Array.isArray(item.items)) return null;
215335
215502
  const entries = item.items.map((entry) => toRecord(entry)).filter((entry) => entry !== null);
@@ -215340,9 +215507,9 @@ var init_events = __esm({
215340
215507
  const pending = entries.find((entry) => entry.completed !== true) ?? entries.at(-1) ?? null;
215341
215508
  const pendingText = pending && typeof pending.text === "string" ? pending.text : null;
215342
215509
  const summary = pendingText ? `${completedCount}/${entries.length} ${pendingText}` : `${completedCount}/${entries.length} todo items`;
215343
- return normalizeProgressMessage(summary);
215510
+ return toProgressUpdate("todo", summary);
215344
215511
  };
215345
- extractProgressFromJsonLine = (line) => {
215512
+ extractProgressUpdateFromJsonLine = (line) => {
215346
215513
  const trimmed = line.trim();
215347
215514
  if (!trimmed.startsWith("{")) return null;
215348
215515
  let parsed;
@@ -215354,23 +215521,28 @@ var init_events = __esm({
215354
215521
  const record = toRecord(parsed);
215355
215522
  if (!record) return null;
215356
215523
  if (record.type === "error" && typeof record.message === "string") {
215357
- return normalizeProgressMessage(record.message);
215524
+ return toProgressUpdate("command", record.message);
215358
215525
  }
215359
215526
  if (record.type === "reasoning") {
215360
- return normalizeProgressMessage(
215527
+ return toProgressUpdate(
215528
+ "reasoning",
215361
215529
  extractBoldText(String(record.text ?? "")) ?? String(record.text ?? "")
215362
215530
  );
215363
215531
  }
215364
215532
  const item = toRecord(record.item);
215365
215533
  if (!item) return null;
215366
215534
  if (item.type === "reasoning") {
215367
- return normalizeProgressMessage(
215535
+ return toProgressUpdate(
215536
+ "reasoning",
215368
215537
  extractBoldText(String(item.text ?? "")) ?? String(item.text ?? "")
215369
215538
  );
215370
215539
  }
215540
+ const commandProgress = extractCommandExecutionProgress(record, item);
215541
+ if (commandProgress) return commandProgress;
215371
215542
  const todoProgress = extractTodoListProgress(item);
215372
215543
  if (todoProgress) return todoProgress;
215373
- return normalizeProgressMessage(
215544
+ return toProgressUpdate(
215545
+ "reasoning",
215374
215546
  extractBoldText(String(item.text ?? "")) ?? String(item.text ?? "")
215375
215547
  );
215376
215548
  };
@@ -215388,6 +215560,26 @@ var init_events = __esm({
215388
215560
  const threadId2 = record.thread_id;
215389
215561
  return typeof threadId2 === "string" && threadId2.length > 0 ? threadId2 : null;
215390
215562
  };
215563
+ extractTurnFailureFromJsonLine = (line) => {
215564
+ const trimmed = line.trim();
215565
+ if (!trimmed.startsWith("{")) return null;
215566
+ let parsed;
215567
+ try {
215568
+ parsed = JSON.parse(trimmed);
215569
+ } catch {
215570
+ return null;
215571
+ }
215572
+ const record = toRecord(parsed);
215573
+ if (!record || record.type !== "turn.failed") return null;
215574
+ const error2 = toRecord(record.error);
215575
+ if (typeof error2?.message === "string" && error2.message.trim().length > 0) {
215576
+ return error2.message.trim();
215577
+ }
215578
+ if (typeof record.message === "string" && record.message.trim().length > 0) {
215579
+ return record.message.trim();
215580
+ }
215581
+ return "Codex turn failed.";
215582
+ };
215391
215583
  }
215392
215584
  });
215393
215585
 
@@ -215921,7 +216113,7 @@ fi`
215921
216113
  let stderrBuffer = "";
215922
216114
  let exitCode = null;
215923
216115
  let resolved = false;
215924
- let lastProgress = null;
216116
+ let lastProgressKey = null;
215925
216117
  let threadId2 = null;
215926
216118
  const handleLine = (line) => {
215927
216119
  const clean = stripAnsi2(line);
@@ -215932,18 +216124,21 @@ fi`
215932
216124
  }
215933
216125
  }
215934
216126
  if (!onProgress) return;
215935
- const parsed = extractProgressFromJsonLine(clean);
216127
+ const parsed = extractProgressUpdateFromJsonLine(clean);
215936
216128
  if (parsed) {
215937
- if (parsed === lastProgress) return;
215938
- lastProgress = parsed;
216129
+ const progressKey2 = `${parsed.kind}:${parsed.message}`;
216130
+ if (progressKey2 === lastProgressKey) return;
216131
+ lastProgressKey = progressKey2;
215939
216132
  onProgress(parsed);
215940
216133
  return;
215941
216134
  }
215942
216135
  if (clean.trimStart().startsWith("{")) return;
215943
216136
  const bold = normalizeProgressMessage(extractBoldText(clean));
215944
- if (!bold || bold === lastProgress) return;
215945
- lastProgress = bold;
215946
- onProgress(bold);
216137
+ if (!bold) return;
216138
+ const progressKey = `reasoning:${bold}`;
216139
+ if (progressKey === lastProgressKey) return;
216140
+ lastProgressKey = progressKey;
216141
+ onProgress({ kind: "reasoning", message: bold });
215947
216142
  };
215948
216143
  const handleChunk = (text, buffer, update, sink) => {
215949
216144
  let next = buffer + text;
@@ -216562,7 +216757,7 @@ ${bottom}
216562
216757
  });
216563
216758
 
216564
216759
  // src/devbox/commands/init/codex/local.ts
216565
- 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, formatCodexRetryProgress, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
216760
+ 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, LOOPBACK_RELAY_HEALTH_TIMEOUT_MS, loopbackRelayHealthChecks, buildRetryPrompt, formatCodexRetryProgress, describeLoopbackRelayHealthError, createLoopbackRelayHealthError, ensureLoopbackRelayHealthy, classifyCodexExecFailure, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
216566
216761
  var init_local = __esm({
216567
216762
  "src/devbox/commands/init/codex/local.ts"() {
216568
216763
  "use strict";
@@ -216598,6 +216793,8 @@ var init_local = __esm({
216598
216793
  return false;
216599
216794
  }
216600
216795
  };
216796
+ LOOPBACK_RELAY_HEALTH_TIMEOUT_MS = 3e3;
216797
+ loopbackRelayHealthChecks = /* @__PURE__ */ new Map();
216601
216798
  buildRetryPrompt = (basePrompt, retryFeedback) => retryFeedback ? [
216602
216799
  basePrompt,
216603
216800
  "",
@@ -216618,6 +216815,147 @@ var init_local = __esm({
216618
216815
  const mode = sessionId ? "continuing existing session" : "starting a fresh session";
216619
216816
  return `retry ${nextAttempt}/${maxAttempts} in ${delaySeconds}s (${mode}): ${formatRetryReason(reason)}`;
216620
216817
  };
216818
+ describeLoopbackRelayHealthError = (error2) => {
216819
+ if (error2 instanceof DOMException && error2.name === "TimeoutError") {
216820
+ return "timed out";
216821
+ }
216822
+ const code2 = error2?.code ?? error2?.cause?.code;
216823
+ if (code2 === "ECONNREFUSED") return "was refused";
216824
+ if (code2 === "ENOTFOUND" || code2 === "EAI_AGAIN" || code2 === "ETIMEDOUT") {
216825
+ return "was unreachable";
216826
+ }
216827
+ return error2 instanceof Error ? error2.message : String(error2);
216828
+ };
216829
+ createLoopbackRelayHealthError = ({
216830
+ healthUrl,
216831
+ detail
216832
+ }) => new Error(
216833
+ `Codex scan failed: local relay health check ${detail} at ${healthUrl}. Start or restart it with \`just dev\` and retry with \`dvb init --resume\`.`
216834
+ );
216835
+ ensureLoopbackRelayHealthy = async (relayBaseUrl) => {
216836
+ if (!isLoopbackRelayUrl(relayBaseUrl)) return;
216837
+ const normalizedRelayBaseUrl = new URL(relayBaseUrl).toString();
216838
+ const inFlight = loopbackRelayHealthChecks.get(normalizedRelayBaseUrl);
216839
+ if (inFlight) {
216840
+ return await inFlight;
216841
+ }
216842
+ const healthUrl = new URL("/health", normalizedRelayBaseUrl).toString();
216843
+ const check = (async () => {
216844
+ try {
216845
+ const response = await fetch(healthUrl, {
216846
+ method: "GET",
216847
+ signal: AbortSignal.timeout(LOOPBACK_RELAY_HEALTH_TIMEOUT_MS)
216848
+ });
216849
+ if (!response.ok) {
216850
+ throw createLoopbackRelayHealthError({
216851
+ healthUrl,
216852
+ detail: `returned HTTP ${response.status}`
216853
+ });
216854
+ }
216855
+ } catch (error2) {
216856
+ if (error2 instanceof Error && error2.message.includes("local relay health check")) {
216857
+ throw error2;
216858
+ }
216859
+ throw createLoopbackRelayHealthError({
216860
+ healthUrl,
216861
+ detail: describeLoopbackRelayHealthError(error2)
216862
+ });
216863
+ }
216864
+ })();
216865
+ loopbackRelayHealthChecks.set(normalizedRelayBaseUrl, check);
216866
+ try {
216867
+ await check;
216868
+ } catch (error2) {
216869
+ if (loopbackRelayHealthChecks.get(normalizedRelayBaseUrl) === check) {
216870
+ loopbackRelayHealthChecks.delete(normalizedRelayBaseUrl);
216871
+ }
216872
+ throw error2;
216873
+ }
216874
+ };
216875
+ classifyCodexExecFailure = ({
216876
+ combinedOutput,
216877
+ detail,
216878
+ exitCode,
216879
+ turnFailedMessage
216880
+ }) => {
216881
+ const failureOutput = turnFailedMessage ? `${combinedOutput}
216882
+ ${turnFailedMessage}` : combinedOutput;
216883
+ if (isRelayUsageLimitExceeded(failureOutput)) {
216884
+ return {
216885
+ error: new Error(
216886
+ "Codex scan failed: OpenAI usage limit exceeded. Run `dvb setup --codex-auth byo` to use your own Codex auth, then retry with `dvb init --resume`."
216887
+ ),
216888
+ retryable: false
216889
+ };
216890
+ }
216891
+ if (isRelayForbidden(failureOutput)) {
216892
+ return {
216893
+ error: new Error(
216894
+ "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`."
216895
+ ),
216896
+ retryable: false
216897
+ };
216898
+ }
216899
+ if (isRelayMissingOpenAiProxyConfiguration(failureOutput)) {
216900
+ return {
216901
+ error: new Error(
216902
+ "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`."
216903
+ ),
216904
+ retryable: false
216905
+ };
216906
+ }
216907
+ if (isStreamDisconnected(failureOutput)) {
216908
+ const requestUrl = extractRequestUrl(failureOutput);
216909
+ if (requestUrl && isLoopbackRelayUrl(requestUrl)) {
216910
+ return {
216911
+ error: new Error(
216912
+ `Codex scan failed: local relay is unreachable at ${requestUrl}. This dev CLI is configured for a local relay; start it with \`just dev\` and retry with \`dvb init --resume\`.`
216913
+ ),
216914
+ retryable: false
216915
+ };
216916
+ }
216917
+ const requestTarget = requestUrl ?? "relay /v1/responses endpoint";
216918
+ return {
216919
+ error: new Error(
216920
+ `Codex scan failed: transport disconnected while calling ${requestTarget}. Check relay health/auth and retry with \`dvb init --resume\`.`
216921
+ ),
216922
+ retryable: true
216923
+ };
216924
+ }
216925
+ if (/no last agent message/i.test(failureOutput)) {
216926
+ return {
216927
+ error: new Error(
216928
+ "Codex scan failed: Codex session ended without a final response. Retry with `dvb init --resume`."
216929
+ ),
216930
+ retryable: true
216931
+ };
216932
+ }
216933
+ if (turnFailedMessage) {
216934
+ const normalized = turnFailedMessage.trim();
216935
+ return {
216936
+ error: new Error(
216937
+ normalized ? `Codex scan failed: ${normalized}` : "Codex scan failed: Codex turn failed."
216938
+ ),
216939
+ retryable: true
216940
+ };
216941
+ }
216942
+ if (exitCode === null) {
216943
+ return {
216944
+ error: new Error(
216945
+ "Codex scan failed: Codex session ended before reporting an exit status. Retry with `dvb init --resume`."
216946
+ ),
216947
+ retryable: true
216948
+ };
216949
+ }
216950
+ if (exitCode === 0) {
216951
+ return null;
216952
+ }
216953
+ const suffix = detail ? `: ${detail}` : "";
216954
+ return {
216955
+ error: new Error(`codex exec failed (exit ${exitCode})${suffix}`),
216956
+ retryable: false
216957
+ };
216958
+ };
216621
216959
  runCodexExec = async (cwd, commandArgs, onProgress, logOptions = {}) => {
216622
216960
  const {
216623
216961
  stdoutLogPath,
@@ -216680,6 +217018,9 @@ var init_local = __esm({
216680
217018
  await new Promise((resolve2) => stream.end(() => resolve2()));
216681
217019
  };
216682
217020
  try {
217021
+ if (proxyOptions) {
217022
+ await ensureLoopbackRelayHealthy(proxyOptions.relayBaseUrl);
217023
+ }
216683
217024
  let resumeThreadId = commandArgs.resumeThreadId;
216684
217025
  let prompt = commandArgs.prompt;
216685
217026
  const runAttempt = async (attemptArgs, attemptResumeThreadId) => await new Promise((resolve2, reject) => {
@@ -216696,8 +217037,9 @@ var init_local = __esm({
216696
217037
  let stderr = "";
216697
217038
  let stdoutBuffer = "";
216698
217039
  let stderrBuffer = "";
216699
- let lastProgress = null;
217040
+ let lastProgressKey = null;
216700
217041
  let threadId2 = null;
217042
+ let turnFailedMessage = null;
216701
217043
  const handleLine = (line) => {
216702
217044
  const clean = stripAnsi2(line);
216703
217045
  if (!threadId2) {
@@ -216706,19 +217048,26 @@ var init_local = __esm({
216706
217048
  threadId2 = parsedThreadId;
216707
217049
  }
216708
217050
  }
217051
+ const parsedTurnFailure = extractTurnFailureFromJsonLine(clean);
217052
+ if (parsedTurnFailure && !turnFailedMessage) {
217053
+ turnFailedMessage = parsedTurnFailure;
217054
+ }
216709
217055
  if (!onProgress) return;
216710
- const parsed = extractProgressFromJsonLine(clean);
217056
+ const parsed = extractProgressUpdateFromJsonLine(clean);
216711
217057
  if (parsed) {
216712
- if (parsed === lastProgress) return;
216713
- lastProgress = parsed;
217058
+ const progressKey2 = `${parsed.kind}:${parsed.message}`;
217059
+ if (progressKey2 === lastProgressKey) return;
217060
+ lastProgressKey = progressKey2;
216714
217061
  onProgress(parsed);
216715
217062
  return;
216716
217063
  }
216717
217064
  if (clean.trimStart().startsWith("{")) return;
216718
217065
  const bold = normalizeProgressMessage(extractBoldText(clean));
216719
- if (!bold || bold === lastProgress) return;
216720
- lastProgress = bold;
216721
- onProgress(bold);
217066
+ if (!bold) return;
217067
+ const progressKey = `reasoning:${bold}`;
217068
+ if (progressKey === lastProgressKey) return;
217069
+ lastProgressKey = progressKey;
217070
+ onProgress({ kind: "reasoning", message: bold });
216722
217071
  };
216723
217072
  const consume = (chunk, buffer, update) => {
216724
217073
  let next = buffer + chunk.toString();
@@ -216749,79 +217098,25 @@ var init_local = __esm({
216749
217098
  child.on("close", (code2) => {
216750
217099
  if (stdoutBuffer) handleLine(stdoutBuffer);
216751
217100
  if (stderrBuffer) handleLine(stderrBuffer);
216752
- if (code2 === 0) {
216753
- resolve2({ threadId: threadId2 ?? attemptResumeThreadId });
216754
- return;
216755
- }
216756
217101
  const combinedOutput = `${stderr}
216757
217102
  ${stdout}`;
216758
217103
  const detail = stderr.trim() || stdout.trim();
216759
217104
  const sessionId = threadId2 ?? attemptResumeThreadId;
216760
- if (isRelayUsageLimitExceeded(combinedOutput)) {
216761
- reject(
216762
- new Error(
216763
- "Codex scan failed: OpenAI usage limit exceeded. Run `dvb setup --codex-auth byo` to use your own Codex auth, then retry with `dvb init --resume`."
216764
- )
216765
- );
216766
- return;
216767
- }
216768
- if (isRelayForbidden(combinedOutput)) {
216769
- reject(
216770
- new Error(
216771
- "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`."
216772
- )
216773
- );
216774
- return;
216775
- }
216776
- if (isRelayMissingOpenAiProxyConfiguration(combinedOutput)) {
216777
- reject(
216778
- new Error(
216779
- "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`."
216780
- )
216781
- );
216782
- return;
216783
- }
216784
- if (isStreamDisconnected(combinedOutput)) {
216785
- const requestUrl = extractRequestUrl(combinedOutput);
216786
- if (requestUrl && isLoopbackRelayUrl(requestUrl)) {
216787
- reject(
216788
- new Error(
216789
- `Codex scan failed: local relay is unreachable at ${requestUrl}. This dev CLI is configured for a local relay; start it with \`just dev\` and retry with \`dvb init --resume\`.`
216790
- )
216791
- );
216792
- return;
216793
- }
216794
- const requestTarget = requestUrl ?? "relay /v1/responses endpoint";
216795
- reject(
216796
- new RetryableCodexExecError(
216797
- `Codex scan failed: transport disconnected while calling ${requestTarget}. Check relay health/auth and retry with \`dvb init --resume\`.`,
216798
- sessionId
216799
- )
216800
- );
217105
+ const failure = classifyCodexExecFailure({
217106
+ combinedOutput,
217107
+ detail,
217108
+ exitCode: code2,
217109
+ turnFailedMessage
217110
+ });
217111
+ if (!failure) {
217112
+ resolve2({ threadId: sessionId });
216801
217113
  return;
216802
217114
  }
216803
- if (/no last agent message/i.test(combinedOutput)) {
216804
- reject(
216805
- new RetryableCodexExecError(
216806
- "Codex scan failed: Codex session ended without a final response. Retry with `dvb init --resume`.",
216807
- sessionId
216808
- )
216809
- );
217115
+ if (failure.retryable) {
217116
+ reject(new RetryableCodexExecError(failure.error.message, sessionId));
216810
217117
  return;
216811
217118
  }
216812
- if (code2 === null) {
216813
- reject(
216814
- new RetryableCodexExecError(
216815
- "Codex scan failed: Codex session ended before reporting an exit status. Retry with `dvb init --resume`.",
216816
- sessionId
216817
- )
216818
- );
216819
- return;
216820
- }
216821
- const suffix = detail ? `: ${detail}` : "";
216822
- reject(
216823
- new Error(`codex exec failed (exit ${code2 ?? "unknown"})${suffix}`)
216824
- );
217119
+ reject(failure.error);
216825
217120
  });
216826
217121
  });
216827
217122
  for (let attempt = 1; attempt <= DEFAULT_CODEX_EXEC_MAX_ATTEMPTS; attempt += 1) {
@@ -216922,7 +217217,10 @@ ${stdout}`;
216922
217217
  trustedPaths: [cwd],
216923
217218
  ...onProgress ? {
216924
217219
  onRetry: (info) => {
216925
- onProgress(formatCodexRetryProgress(info));
217220
+ onProgress({
217221
+ kind: "command",
217222
+ message: formatCodexRetryProgress(info)
217223
+ });
216926
217224
  }
216927
217225
  } : {}
216928
217226
  }
@@ -217003,7 +217301,10 @@ ${stdout}`;
217003
217301
  trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd],
217004
217302
  ...onProgress ? {
217005
217303
  onRetry: (info) => {
217006
- onProgress(formatCodexRetryProgress(info));
217304
+ onProgress({
217305
+ kind: "command",
217306
+ message: formatCodexRetryProgress(info)
217307
+ });
217007
217308
  }
217008
217309
  } : {}
217009
217310
  }
@@ -217075,7 +217376,10 @@ ${stdout}`;
217075
217376
  trustedPaths: [cwd],
217076
217377
  ...onProgress ? {
217077
217378
  onRetry: (info) => {
217078
- onProgress(formatCodexRetryProgress(info));
217379
+ onProgress({
217380
+ kind: "command",
217381
+ message: formatCodexRetryProgress(info)
217382
+ });
217079
217383
  }
217080
217384
  } : {}
217081
217385
  }
@@ -217156,7 +217460,10 @@ ${stdout}`;
217156
217460
  trustedPaths: homeDir2 ? [cwd, homeDir2] : [cwd],
217157
217461
  ...onProgress ? {
217158
217462
  onRetry: (info) => {
217159
- onProgress(formatCodexRetryProgress(info));
217463
+ onProgress({
217464
+ kind: "command",
217465
+ message: formatCodexRetryProgress(info)
217466
+ });
217160
217467
  }
217161
217468
  } : {}
217162
217469
  }
@@ -218442,8 +218749,8 @@ codex login`
218442
218749
  "-c",
218443
218750
  remoteCodexCommand
218444
218751
  ],
218445
- onProgress: (message) => {
218446
- status.stage(`Apply setup plan - ${message}`);
218752
+ onProgress: (update) => {
218753
+ status.stage(`Apply setup plan - ${update.message}`);
218447
218754
  }
218448
218755
  });
218449
218756
  let attemptLastMessage = "";
@@ -218507,6 +218814,66 @@ codex login`
218507
218814
  }
218508
218815
  });
218509
218816
 
218817
+ // src/devbox/commands/init/scanProgress.ts
218818
+ var createInitialScanRowState, applyScanRowStatus, applyScanRowProgressUpdate, formatScanRow;
218819
+ var init_scanProgress = __esm({
218820
+ "src/devbox/commands/init/scanProgress.ts"() {
218821
+ "use strict";
218822
+ createInitialScanRowState = (status) => ({
218823
+ status,
218824
+ todo: null,
218825
+ reasoning: null,
218826
+ command: null
218827
+ });
218828
+ applyScanRowStatus = (state, status) => ({
218829
+ status,
218830
+ todo: null,
218831
+ reasoning: null,
218832
+ command: null
218833
+ });
218834
+ applyScanRowProgressUpdate = (state, update) => {
218835
+ if (update.kind === "todo") {
218836
+ return {
218837
+ status: null,
218838
+ todo: update.message,
218839
+ reasoning: null,
218840
+ command: null
218841
+ };
218842
+ }
218843
+ if (update.kind === "reasoning") {
218844
+ return {
218845
+ ...state,
218846
+ status: null,
218847
+ reasoning: update.message,
218848
+ command: null
218849
+ };
218850
+ }
218851
+ return {
218852
+ ...state,
218853
+ status: null,
218854
+ command: update.message
218855
+ };
218856
+ };
218857
+ formatScanRow = ({
218858
+ label,
218859
+ state,
218860
+ formatLabel
218861
+ }) => {
218862
+ const primary = state.todo ?? state.status ?? state.reasoning ?? state.command ?? "starting";
218863
+ const lines = [primary];
218864
+ if (state.reasoning && state.reasoning !== primary) {
218865
+ lines.push(state.reasoning);
218866
+ }
218867
+ if (state.command && state.command !== primary && state.command !== state.reasoning) {
218868
+ lines.push(state.command);
218869
+ }
218870
+ const prefix = `${formatLabel(label)}: `;
218871
+ const indent = " ".repeat(label.length + 2);
218872
+ return lines.map((line, index) => `${index === 0 ? prefix : indent}${line}`).join("\n");
218873
+ };
218874
+ }
218875
+ });
218876
+
218510
218877
  // src/devbox/commands/init/setupArtifactsValidation.ts
218511
218878
  var import_promises28, import_node_path32, expandHomePath2, resolveArtifactSourcePath, isMissingPathError, addMissingForCategory, collectMissingSetupArtifacts, remapSelectedPathEntries;
218512
218879
  var init_setupArtifactsValidation = __esm({
@@ -218647,6 +219014,7 @@ var init_setupPlanFlow = __esm({
218647
219014
  init_codex();
218648
219015
  init_scanStatus();
218649
219016
  init_progress();
219017
+ init_scanProgress();
218650
219018
  init_setupArtifactsValidation();
218651
219019
  SETUP_ARTIFACT_REGEN_MAX_ATTEMPTS = 3;
218652
219020
  toPosixPath2 = (value) => value.split(import_node_path33.default.sep).join(import_node_path33.default.posix.sep);
@@ -219048,17 +219416,26 @@ var init_setupPlanFlow = __esm({
219048
219416
  const resetColor = "\x1B[39m";
219049
219417
  return `${undim}${teal}${bold}${label}${resetColor}${undim}${dim}`;
219050
219418
  };
219051
- const formatRow = (label, message) => {
219052
- const normalized = message.replace(/\r?\n/g, " ").trim();
219053
- return `${colorCategory(label)}: ${normalized}`;
219054
- };
219055
219419
  const envSecretsRow = log3.group("");
219056
219420
  const externalRow = log3.group("");
219057
219421
  const extraArtifactsRow = log3.group("");
219058
219422
  const servicesRow = log3.group("");
219059
- const makeUpdater = (row, label) => (message) => {
219060
- if (!active) return;
219061
- row.message(formatRow(label, message));
219423
+ const makeUpdater = (row, label) => {
219424
+ let state = createInitialScanRowState("starting");
219425
+ const render = () => {
219426
+ row.message(
219427
+ formatScanRow({
219428
+ label,
219429
+ state,
219430
+ formatLabel: colorCategory
219431
+ })
219432
+ );
219433
+ };
219434
+ return (message) => {
219435
+ if (!active) return;
219436
+ state = typeof message === "string" ? applyScanRowStatus(state, message) : applyScanRowProgressUpdate(state, message);
219437
+ render();
219438
+ };
219062
219439
  };
219063
219440
  const updateEnvSecrets = makeUpdater(envSecretsRow, "env/secrets");
219064
219441
  const updateExternal = makeUpdater(externalRow, "external");
@@ -219188,7 +219565,7 @@ var init_setupPlanFlow = __esm({
219188
219565
  envSecretsMissing
219189
219566
  ),
219190
219567
  ...initCodexProxyOptions ? { proxyOptions: initCodexProxyOptions } : {},
219191
- onProgress: (message) => status.stage(`Rescan env/secrets - ${message}`)
219568
+ onProgress: (update) => status.stage(`Rescan env/secrets - ${update.message}`)
219192
219569
  });
219193
219570
  saveScanThreadId("envSecretsThreadId", threadId2);
219194
219571
  },
@@ -219233,7 +219610,7 @@ var init_setupPlanFlow = __esm({
219233
219610
  externalMissing
219234
219611
  ),
219235
219612
  ...initCodexProxyOptions ? { proxyOptions: initCodexProxyOptions } : {},
219236
- onProgress: (message) => status.stage(`Rescan external - ${message}`)
219613
+ onProgress: (update) => status.stage(`Rescan external - ${update.message}`)
219237
219614
  });
219238
219615
  saveScanThreadId("externalThreadId", threadId2);
219239
219616
  },
@@ -219273,7 +219650,7 @@ var init_setupPlanFlow = __esm({
219273
219650
  extraArtifactsMissing
219274
219651
  ),
219275
219652
  ...initCodexProxyOptions ? { proxyOptions: initCodexProxyOptions } : {},
219276
- onProgress: (message) => status.stage(`Rescan extra artifacts - ${message}`)
219653
+ onProgress: (update) => status.stage(`Rescan extra artifacts - ${update.message}`)
219277
219654
  });
219278
219655
  saveScanThreadId("extraArtifactsThreadId", threadId2);
219279
219656
  },
@@ -229873,4 +230250,4 @@ smol-toml/dist/index.js:
229873
230250
  */
229874
230251
  //# sourceMappingURL=dvb.cjs.map
229875
230252
 
229876
- //# debugId=d891e41c-960d-5274-8d0e-b6e180994258
230253
+ //# debugId=12cda96d-089f-5b95-b67d-05e388742689