@boxes-dev/dvb-runtime 1.0.957 → 1.0.959

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.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
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]="a55a831a-e9eb-5e0c-9e31-0c4bceb58a84")}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]="622a15c0-7c29-5be9-a35c-b1a193a6b0f0")}catch(e){}}();
4
4
  import { createRequire as __dvbCreateRequire } from "node:module";
5
5
  import { dirname as __dvbDirname } from "node:path";
6
6
  import { fileURLToPath as __dvbFileURLToPath } from "node:url";
@@ -101145,8 +101145,8 @@ var init_otel = __esm({
101145
101145
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
101146
101146
  };
101147
101147
  readBuildMetadata = () => {
101148
- const rawPackageVersion = "1.0.957";
101149
- const rawGitSha = "bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
101148
+ const rawPackageVersion = "1.0.959";
101149
+ const rawGitSha = "c5992d38486ffdbc188773dfe7556175ffb24abc";
101150
101150
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
101151
101151
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
101152
101152
  return { packageVersion, gitSha };
@@ -133552,9 +133552,9 @@ var init_sentry = __esm({
133552
133552
  uncaughtExceptionMonitorInstalled = false;
133553
133553
  currentDevboxSentryUser = null;
133554
133554
  readBuildMetadata2 = () => {
133555
- const rawPackageVersion = "1.0.957";
133556
- const rawGitSha = "bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
133557
- const rawSentryRelease = "boxes-dev-dvb@1.0.957+bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
133555
+ const rawPackageVersion = "1.0.959";
133556
+ const rawGitSha = "c5992d38486ffdbc188773dfe7556175ffb24abc";
133557
+ const rawSentryRelease = "boxes-dev-dvb@1.0.959+c5992d38486ffdbc188773dfe7556175ffb24abc";
133558
133558
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
133559
133559
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
133560
133560
  const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
@@ -138235,8 +138235,8 @@ var init_desktopSetupReview = __esm({
138235
138235
  const summary = uniqueNonEmpty(sourceParts).join(" \xB7 ");
138236
138236
  return summary || databaseSourceKindLabel(entry.source.kind);
138237
138237
  };
138238
- createItem = ({ detailLines = [], included = true, section, source, sourceIndex, subtitle = null, title, warning: warning3 = null }) => ({
138239
- id: itemId({ section, source, sourceIndex }),
138238
+ createItem = ({ detailLines = [], id: id2 = null, included = true, section, source, sourceIndex, subtitle = null, title, warning: warning3 = null }) => ({
138239
+ id: id2 ?? itemId({ section, source, sourceIndex }),
138240
138240
  section,
138241
138241
  source,
138242
138242
  sourceIndex,
@@ -138300,6 +138300,8 @@ var init_desktopSetupReview = __esm({
138300
138300
  }));
138301
138301
  case "databases":
138302
138302
  return plan.databaseCopies.map((entry, index) => createItem({
138303
+ id: `databases:database_copy:${encodeURIComponent(entry.id)}`,
138304
+ included: entry.canAutomate,
138303
138305
  section,
138304
138306
  source: "database_copy",
138305
138307
  sourceIndex: index,
@@ -138717,7 +138719,7 @@ var init_packageVersion = __esm({
138717
138719
  return path17.join(process.cwd(), "dvb");
138718
138720
  };
138719
138721
  readEmbeddedPackageVersion = () => {
138720
- const raw = "1.0.957";
138722
+ const raw = "1.0.959";
138721
138723
  return trimVersion(raw);
138722
138724
  };
138723
138725
  readNearestPackageMetadata = (basePath) => {
@@ -300601,7 +300603,7 @@ var init_scanOutputs = __esm({
300601
300603
  return false;
300602
300604
  }
300603
300605
  const resolved = source.resolvedNonSecret;
300604
- return typeof value.id === "string" && typeof value.engine === "string" && typeof value.displayLabel === "string" && typeof value.canAutomate === "boolean" && typeof value.confidence === "string" && Array.isArray(value.evidence) && typeof source.kind === "string" && Array.isArray(source.refs) && source.refs.every(isDatabaseSourceRef) && isObject8(resolved) && (resolved.host === null || typeof resolved.host === "string") && (resolved.port === null || typeof resolved.port === "number") && (resolved.database === null || typeof resolved.database === "string") && (resolved.username === null || typeof resolved.username === "string") && (resolved.schema === null || typeof resolved.schema === "string") && (resolved.sslMode === null || typeof resolved.sslMode === "string") && typeof source.locality === "string" && typeof target.mode === "string" && (target.ref === null || typeof target.ref === "string") && typeof restoreHint.commandFamily === "string" && typeof restoreHint.expectedFormat === "string" && (value.skipReason === null || typeof value.skipReason === "string");
300606
+ return typeof value.id === "string" && value.id.trim().length > 0 && typeof value.engine === "string" && typeof value.displayLabel === "string" && typeof value.canAutomate === "boolean" && typeof value.confidence === "string" && Array.isArray(value.evidence) && typeof source.kind === "string" && Array.isArray(source.refs) && source.refs.every(isDatabaseSourceRef) && isObject8(resolved) && (resolved.host === null || typeof resolved.host === "string") && (resolved.port === null || typeof resolved.port === "number") && (resolved.database === null || typeof resolved.database === "string") && (resolved.username === null || typeof resolved.username === "string") && (resolved.schema === null || typeof resolved.schema === "string") && (resolved.sslMode === null || typeof resolved.sslMode === "string") && typeof source.locality === "string" && typeof target.mode === "string" && (target.ref === null || typeof target.ref === "string") && typeof restoreHint.commandFamily === "string" && typeof restoreHint.expectedFormat === "string" && (value.skipReason === null || typeof value.skipReason === "string");
300605
300607
  };
300606
300608
  isManagedConfigPath = (value, rootName) => {
300607
300609
  const normalized = value.replaceAll("\\", "/").replace(/\/+$/u, "").trim();
@@ -300652,6 +300654,11 @@ var init_scanOutputs = __esm({
300652
300654
  if (!databaseCandidates.every(isDatabaseCopyCandidate)) {
300653
300655
  throw new Error("Invalid database candidate scan output.");
300654
300656
  }
300657
+ if (new Set(databaseCandidates.map((candidate) => candidate.id)).size !== databaseCandidates.length) {
300658
+ throw new Error(
300659
+ "Invalid database candidate scan output: ids must be unique."
300660
+ );
300661
+ }
300655
300662
  return {
300656
300663
  schemaVersion: parsed.schemaVersion,
300657
300664
  scanFullyCompleted: parsed.scanFullyCompleted,
@@ -303572,7 +303579,7 @@ import os25 from "node:os";
303572
303579
  import path51 from "node:path";
303573
303580
  import process25 from "node:process";
303574
303581
  import { pipeline } from "node:stream/promises";
303575
- var SNAPSHOT_VERSION, X25519_SPKI_DER_PREFIX, DATABASE_DUMP_TIMEOUT_MS, REPO_SSH_VERIFY_TIMEOUT_MS, DATABASE_DUMP_TOOL_MISSING_ERROR_CODE, DATABASE_DUMP_CLIENT_VERSION_MISMATCH_ERROR_CODE, DATABASE_DUMP_FAILED_ERROR_CODE, MULTIPART_UPLOAD_URL_REFRESH_SKEW_MS, nowIso7, trim10, toErrorMessage, toRedactedError, normalizeAgentConfigSelection2, createAgentConfigSnapshot, normalizeAgentThreadHistorySelection, normalizeAgentThreadImportWarning, normalizeAgentThreadImportScope, createAgentThreadHistorySnapshot, assertGitSigningReadyForBundle, shellQuote5, ensureDir7, pathExists4, readJsonFile2, writeJsonFile4, writeRepoMarker, runCommand7, runCommandToFile, formatMissingDatabaseDumpToolMessage, createMissingDatabaseDumpToolError, createPostgresDumpVersionMismatchError, createDatabaseDumpExecutionError, executeDatabaseDumpCommand, runDatabaseDumpCommand, spawnCommand, isRepoInitArtifactPath2, readDirtyWorktreeState, readProjectDirtyWorktreeState, hasGitHead, readGitHeadInfo, copyPathIntoRoot, isPathInside, copyLocalPath2, createUserFacingEnvFileError, deriveEnvStagingId, snapshotEnvStagingFile, deleteEnvStagingFile, pruneEnvStagingFilesExcept, copyStagedEditableSetupFile, createRepoPayloadOwnership, createProjectPayloadOwnership, relativeFromStagingRoot2, resolveRepoPayloadRoot, addCopiedInventoryLeaf2, copyPathWithInventory2, copyPathWithRepoPayloadExclusions, directorySize3, createInitialScanState, createApprovals, createUploadState, setUploadProgressState, createBundleOptions, createLfsWithoutRepoSshWarning, buildLocalPrepWarnings, createForkStartupScriptSetup, createDestroyedLocalPrepSnapshot, mergeSetupPlanForRescan, SETUP_REVIEW_SECTION_SCAN_CATEGORY, reviewStatusForScanStatus, buildReviewSectionStatusesFromScanState, buildReviewState, normalizeSetupReviewRescanRequest, getSetupReviewSectionsForScanCategories, normalizeSetupReviewRetryFailedScansRequest, assertRetryableInterruptedScanCategories, DESKTOP_INIT_SCAN_FOCUS_SET, createDesktopInitRequestValidationError, isDesktopInitRequestValidationError, normalizeDesktopInitScanFocus, normalizeLocalPrepScanCategories, hasStartedOrSkippedInitialScan, resolveLockedScanFocus, isInitialScanCategoryResolved, areInitialScanCategoriesResolved, getRunnableInitialScanCategories, getSkippableInitialScanCategories, applyRescanStateToReview, markScanCategories, normalizeDirtyWorktreeForSnapshot, normalizeScanStateForSnapshot, createSnapshotFromState, createLocalPrepState, buildSkippedRepoSshSetup, getRepoSshBundleDecisionKey, parseGitRemoteHost2, acquireLocalLock, releaseLocalLock, captureShellEnvironment, safeName2, resolveSetupArtifactSource, findOwningProjectLayoutRepo, gitCommandSucceeds, isIgnoredUntrackedRepoFile, resolveEnvFileArtifactSource, isEligibleAgentEnvFileSource, buildReviewEnvFileEntry, enrichSetupPlanEnvFiles, DESKTOP_SHELL_RC_IMPORTS, resolveShellRcSourcePath, deriveShellRcStagingId, resolvesToShellRcSource, enrichSetupPlanShellRcFiles, wrapSetupArtifactCopyError, copySetupArtifacts, collectRepoScopedSetupArtifactPaths, copyGitMetadata, copyGlobalGitConfig, ensureDevboxAccessPublicKey, writeDirtyPayloads, GIT_CHECK_ATTR_PATH_CHUNK_SIZE, forEachTrackedLfsManagedPath, createLfsWorktreePayloads, createRepoPayloads, createProjectRootPayloads, createAggregateRepoPayloadState, addRepoPayloadState, buildSkippedRepoSshSetupForLayoutRepo, shouldConvertHttpsRepoOriginToSsh, buildRepoSshSetupForLayoutRepo, getPreOwnedRepoPathsForLayoutRepo, createProjectRepoPayloads, stripEnvValueQuotes, readRawEnvFileValues, resolveLocalReferencePath, parseEnvFileRef, readDatabaseEnvFileValue, getDatabaseValueForRole, isSupportedDatabaseUrlProtocol, parseDatabaseUrlForDump, appendEnvValue, normalizeDatabasePort, resolveDatabaseConnectionFields, resolveDatabaseDumpCommand, safeDatabaseDumpBaseName, formatDatabaseDumpFailureMessage, createDatabaseDumpFailureError, preflightDatabaseDumpCandidates, createDatabasePayloads, stripLocalEnvFileReviewMetadata, stripLocalExternalConfigReviewMetadata, buildRemoteSetupPlan, createInnerBundleStaging, stageRepoSshSetup, createTarGz, sha256File2, encryptBundle, buildX25519PublicKey, createKeyEnvelope, createPrivatePublicX25519Pair, MULTIPART_UPLOAD_RECOVERY_ROUND_COUNT, MULTIPART_UPLOAD_RECOVERY_BASE_DELAY_MS, REMOTE_DESTROY_POLL_INTERVAL_MS, REMOTE_DESTROY_TIMEOUT_MS, sleep5, sanitizeMultipartUploadPartsForState, createMultipartUploadState, shouldRefreshMultipartUploadUrlsBeforeUpload, normalizeRepo, normalizeOptionalProjectInstanceTypeKey, normalizeSelectedProjectRepoRelPaths, buildDesktopProjectLayoutRepo, readGitConfigValues, unsetGitConfigIfExactlyMatches, removeEmptyDirectoryIfPresent, shouldCleanupProjectLayoutClaims, cleanupProjectLayoutClaims, resolveSelectedProjectRepoRelPaths, claimDesktopProjectLayout, buildLocalScanProjectLayoutContext, normalizeSelectedAgents, normalizeBackendJobReference, getRemoteDestroyFailureMessage, waitForRemoteDestroyCompletion, normalizeApprovedEnvFile, normalizeApprovedPlan, shouldPreserveVerifiedRepoSshSetup, normalizeManagedGithubAccessRepository, normalizeManagedGithubAccess, buildManagedGithubAccessForProjectLayout, createDesktopLocalPrepService;
303582
+ var SNAPSHOT_VERSION, X25519_SPKI_DER_PREFIX, DATABASE_DUMP_TIMEOUT_MS, DATABASE_APPROVAL_PREFLIGHT_TIMEOUT_MS, DATABASE_APPROVAL_PREFLIGHT_CONCURRENCY, REPO_SSH_VERIFY_TIMEOUT_MS, DATABASE_DUMP_TOOL_MISSING_ERROR_CODE, DATABASE_DUMP_CLIENT_VERSION_MISMATCH_ERROR_CODE, DATABASE_DUMP_FAILED_ERROR_CODE, MULTIPART_UPLOAD_URL_REFRESH_SKEW_MS, nowIso7, trim10, toErrorMessage, toRedactedError, normalizeAgentConfigSelection2, createAgentConfigSnapshot, normalizeAgentThreadHistorySelection, normalizeAgentThreadImportWarning, normalizeAgentThreadImportScope, createAgentThreadHistorySnapshot, assertGitSigningReadyForBundle, shellQuote5, ensureDir7, pathExists4, readJsonFile2, writeJsonFile4, writeRepoMarker, runCommand7, runCommandToFile, formatMissingDatabaseDumpToolMessage, createMissingDatabaseDumpToolError, createPostgresDumpVersionMismatchError, DATABASE_DUMP_FAILURE_USER_MESSAGES, createDatabaseDumpExecutionError, classifyDatabaseDumpFailure, executeDatabaseDumpCommand, runDatabaseDumpCommand, spawnCommand, isRepoInitArtifactPath2, readDirtyWorktreeState, readProjectDirtyWorktreeState, hasGitHead, readGitHeadInfo, copyPathIntoRoot, isPathInside, copyLocalPath2, createUserFacingEnvFileError, deriveEnvStagingId, snapshotEnvStagingFile, deleteEnvStagingFile, pruneEnvStagingFilesExcept, copyStagedEditableSetupFile, createRepoPayloadOwnership, createProjectPayloadOwnership, relativeFromStagingRoot2, resolveRepoPayloadRoot, addCopiedInventoryLeaf2, copyPathWithInventory2, copyPathWithRepoPayloadExclusions, directorySize3, createInitialScanState, createApprovals, createUploadState, setUploadProgressState, createBundleOptions, createLfsWithoutRepoSshWarning, buildLocalPrepWarnings, createForkStartupScriptSetup, createDestroyedLocalPrepSnapshot, mergeSetupPlanForRescan, SETUP_REVIEW_SECTION_SCAN_CATEGORY, reviewStatusForScanStatus, buildReviewSectionStatusesFromScanState, buildReviewState, normalizeSetupReviewRescanRequest, getSetupReviewSectionsForScanCategories, normalizeSetupReviewRetryFailedScansRequest, assertRetryableInterruptedScanCategories, DESKTOP_INIT_SCAN_FOCUS_SET, createDesktopInitRequestValidationError, isDesktopInitRequestValidationError, normalizeDesktopInitScanFocus, normalizeLocalPrepScanCategories, hasStartedOrSkippedInitialScan, resolveLockedScanFocus, isInitialScanCategoryResolved, areInitialScanCategoriesResolved, getRunnableInitialScanCategories, getSkippableInitialScanCategories, applyRescanStateToReview, markScanCategories, normalizeDirtyWorktreeForSnapshot, normalizeScanStateForSnapshot, createSnapshotFromState, createLocalPrepState, buildSkippedRepoSshSetup, getRepoSshBundleDecisionKey, parseGitRemoteHost2, acquireLocalLock, releaseLocalLock, captureShellEnvironment, safeName2, resolveSetupArtifactSource, findOwningProjectLayoutRepo, gitCommandSucceeds, isIgnoredUntrackedRepoFile, resolveEnvFileArtifactSource, isEligibleAgentEnvFileSource, buildReviewEnvFileEntry, enrichSetupPlanEnvFiles, DESKTOP_SHELL_RC_IMPORTS, resolveShellRcSourcePath, deriveShellRcStagingId, resolvesToShellRcSource, enrichSetupPlanShellRcFiles, wrapSetupArtifactCopyError, copySetupArtifacts, collectRepoScopedSetupArtifactPaths, copyGitMetadata, copyGlobalGitConfig, ensureDevboxAccessPublicKey, writeDirtyPayloads, GIT_CHECK_ATTR_PATH_CHUNK_SIZE, forEachTrackedLfsManagedPath, createLfsWorktreePayloads, createRepoPayloads, createProjectRootPayloads, createAggregateRepoPayloadState, addRepoPayloadState, buildSkippedRepoSshSetupForLayoutRepo, shouldConvertHttpsRepoOriginToSsh, buildRepoSshSetupForLayoutRepo, getPreOwnedRepoPathsForLayoutRepo, createProjectRepoPayloads, stripEnvValueQuotes, readRawEnvFileValues, resolveLocalReferencePath, parseEnvFileRef, readDatabaseEnvFileValue, createDatabaseSourceValidationError, getDatabaseValueForRole, isSupportedDatabaseUrlProtocol, parseDatabaseUrlForDump, appendEnvValue, normalizeDatabasePort, resolveDatabaseConnectionFields, resolveDatabaseDumpCommand, safeDatabaseDumpBaseName, formatDatabaseDumpFailureMessage, createPublicDatabaseDumpFailure, createDatabaseDumpFailureError, buildDatabasePreflightArgs, preflightDatabaseDumpCandidates, createDatabasePayloads, stripLocalEnvFileReviewMetadata, stripLocalExternalConfigReviewMetadata, buildRemoteSetupPlan, createInnerBundleStaging, stageRepoSshSetup, createTarGz, sha256File2, encryptBundle, buildX25519PublicKey, createKeyEnvelope, createPrivatePublicX25519Pair, MULTIPART_UPLOAD_RECOVERY_ROUND_COUNT, MULTIPART_UPLOAD_RECOVERY_BASE_DELAY_MS, REMOTE_DESTROY_POLL_INTERVAL_MS, REMOTE_DESTROY_TIMEOUT_MS, sleep5, sanitizeMultipartUploadPartsForState, createMultipartUploadState, shouldRefreshMultipartUploadUrlsBeforeUpload, normalizeRepo, normalizeOptionalProjectInstanceTypeKey, normalizeSelectedProjectRepoRelPaths, buildDesktopProjectLayoutRepo, readGitConfigValues, unsetGitConfigIfExactlyMatches, removeEmptyDirectoryIfPresent, shouldCleanupProjectLayoutClaims, cleanupProjectLayoutClaims, resolveSelectedProjectRepoRelPaths, claimDesktopProjectLayout, buildLocalScanProjectLayoutContext, normalizeSelectedAgents, normalizeBackendJobReference, getRemoteDestroyFailureMessage, waitForRemoteDestroyCompletion, normalizeApprovedEnvFile, normalizeApprovedPlan, shouldPreserveVerifiedRepoSshSetup, normalizeManagedGithubAccessRepository, normalizeManagedGithubAccess, buildManagedGithubAccessForProjectLayout, createDesktopLocalPrepService;
303576
303583
  var init_localPrepService = __esm({
303577
303584
  "../../../../shared/initPrep/src/localPrepService.mjs"() {
303578
303585
  "use strict";
@@ -303592,6 +303599,8 @@ var init_localPrepService = __esm({
303592
303599
  SNAPSHOT_VERSION = DESKTOP_INIT_CONTRACT_VERSION;
303593
303600
  X25519_SPKI_DER_PREFIX = Buffer.from("302a300506032b656e032100", "hex");
303594
303601
  DATABASE_DUMP_TIMEOUT_MS = 10 * 60 * 1e3;
303602
+ DATABASE_APPROVAL_PREFLIGHT_TIMEOUT_MS = 5 * 1e3;
303603
+ DATABASE_APPROVAL_PREFLIGHT_CONCURRENCY = 3;
303595
303604
  REPO_SSH_VERIFY_TIMEOUT_MS = 30 * 1e3;
303596
303605
  DATABASE_DUMP_TOOL_MISSING_ERROR_CODE = "desktop_database_dump_tool_missing";
303597
303606
  DATABASE_DUMP_CLIENT_VERSION_MISMATCH_ERROR_CODE = "desktop_database_dump_client_version_mismatch";
@@ -303606,7 +303615,8 @@ var init_localPrepService = __esm({
303606
303615
  reason: error55 instanceof Error && typeof error55.desktopInitErrorReason === "string" ? error55.desktopInitErrorReason : void 0,
303607
303616
  requestId: null,
303608
303617
  retryable: error55 instanceof Error && typeof error55.retryable === "boolean" ? error55.retryable : true,
303609
- userMessage: error55 instanceof Error && typeof error55.userMessage === "string" ? error55.userMessage : void 0
303618
+ userMessage: error55 instanceof Error && typeof error55.userMessage === "string" ? error55.userMessage : void 0,
303619
+ ...error55 instanceof Error && Array.isArray(error55.desktopDatabaseDumpFailures) ? { databaseDumpFailures: error55.desktopDatabaseDumpFailures } : {}
303610
303620
  });
303611
303621
  normalizeAgentConfigSelection2 = ({ agentConfig, selection }) => {
303612
303622
  const validItemIds = new Set(
@@ -303879,7 +303889,7 @@ var init_localPrepService = __esm({
303879
303889
  if (command === "pg_dump") {
303880
303890
  return [
303881
303891
  "boxes.dev could not find a usable pg_dump tool, so database copy was skipped.",
303882
- "Update or reinstall boxes.dev to restore its included PostgreSQL tools, or install PostgreSQL client tools and make sure pg_dump is on PATH, then retry bundle preparation.",
303892
+ "Update or reinstall boxes.dev to restore its included PostgreSQL tools, or install PostgreSQL client tools and make sure pg_dump is on PATH, then retry the database copy.",
303883
303893
  "On macOS: run `brew install libpq` and add `$(brew --prefix libpq)/bin` to PATH, or install Postgres.app and add `/Applications/Postgres.app/Contents/Versions/latest/bin` to PATH.",
303884
303894
  "Verify with `pg_dump --version`."
303885
303895
  ].join(" ");
@@ -303887,7 +303897,7 @@ var init_localPrepService = __esm({
303887
303897
  if (command === "mysqldump") {
303888
303898
  return [
303889
303899
  "mysqldump is not installed locally, so database copy was skipped.",
303890
- "Install MySQL or MariaDB client tools from the same database family and major or LTS release as the local server, make sure mysqldump is on PATH, then retry bundle preparation.",
303900
+ "Install MySQL or MariaDB client tools from the same database family and major or LTS release as the local server, make sure mysqldump is on PATH, then retry the database copy.",
303891
303901
  "Verify with `mysqldump --version`."
303892
303902
  ].join(" ");
303893
303903
  }
@@ -303897,7 +303907,7 @@ var init_localPrepService = __esm({
303897
303907
  const error55 = new Error(formatMissingDatabaseDumpToolMessage(command));
303898
303908
  error55.desktopInitErrorCode = DATABASE_DUMP_TOOL_MISSING_ERROR_CODE;
303899
303909
  error55.desktopInitErrorReason = command;
303900
- error55.userMessage = command === "pg_dump" ? "Update or reinstall boxes.dev to restore its included PostgreSQL tools, or install pg_dump and make sure it is available on PATH, then retry bundle preparation." : command === "mysqldump" ? "Install mysqldump from the same database family and major or LTS release as the local server, verify it with `mysqldump --version`, then retry. To proceed without local database data, change this database copy to skip." : `Install ${command}, make sure it is available on PATH, then retry bundle preparation.`;
303910
+ error55.userMessage = command === "pg_dump" ? "Update or reinstall boxes.dev to restore its included PostgreSQL tools, or install pg_dump and make sure it is available on PATH, then retry the database copy." : command === "mysqldump" ? "Install mysqldump from the same database family and major or LTS release as the local server, verify it with `mysqldump --version`, then retry the database copy. To proceed without local database data, skip this database." : `Install ${command}, make sure it is available on PATH, then retry the database copy.`;
303901
303911
  return error55;
303902
303912
  };
303903
303913
  createPostgresDumpVersionMismatchError = (stderr, { source = "system" } = {}) => {
@@ -303914,10 +303924,20 @@ var init_localPrepService = __esm({
303914
303924
  );
303915
303925
  error55.desktopInitErrorCode = DATABASE_DUMP_CLIENT_VERSION_MISMATCH_ERROR_CODE;
303916
303926
  error55.desktopInitErrorReason = "pg_dump";
303917
- error55.userMessage = source === "managed" ? "This PostgreSQL server is newer than the pg_dump included with this version of boxes.dev. Update boxes.dev or install a compatible client, then re-run `dvb agent-init check`." : "Install a pg_dump client at least as new as the PostgreSQL server, verify it with `pg_dump --version`, then re-run `dvb agent-init check`.";
303927
+ error55.userMessage = source === "managed" ? "This PostgreSQL server is newer than the pg_dump included with this version of boxes.dev. Update boxes.dev or install a compatible client, then retry the database copy." : "Install a pg_dump client at least as new as the PostgreSQL server, verify it with `pg_dump --version`, then retry the database copy.";
303918
303928
  return error55;
303919
303929
  };
303920
- createDatabaseDumpExecutionError = (toolName, { timedOut = false } = {}) => {
303930
+ DATABASE_DUMP_FAILURE_USER_MESSAGES = {
303931
+ authentication_failed: "The database rejected the selected credentials. Check the project\u2019s database settings, then retry.",
303932
+ connection_refused: "Nothing accepted the connection at the selected host and port. Start the database or update the connection, then retry.",
303933
+ database_missing: "The selected database does not exist. Update the database name, then retry.",
303934
+ host_unresolved: "This computer cannot resolve the selected database host. Use a host-reachable endpoint, then retry.",
303935
+ password_missing: "The connection needs a password, but the selected credential reference did not provide one. Update the database settings, then retry.",
303936
+ permission_denied: "The selected database user cannot read the database catalog. Grant dump access or use a different database user, then retry.",
303937
+ source_url_missing: "The selected database URL wasn\u2019t available from the project environment or an env file. Update the connection or skip this database.",
303938
+ timeout: "The database did not respond in time. Start it or make the selected endpoint reachable, then retry."
303939
+ };
303940
+ createDatabaseDumpExecutionError = (toolName, { failureKind = "unknown", timedOut = false } = {}) => {
303921
303941
  const summary = timedOut ? `${toolName} timed out while creating a database dump.` : `${toolName} failed while creating a database dump.`;
303922
303942
  const error55 = new Error(
303923
303943
  toolName === "mysqldump" ? [
@@ -303928,9 +303948,65 @@ var init_localPrepService = __esm({
303928
303948
  );
303929
303949
  error55.desktopInitErrorCode = DATABASE_DUMP_FAILED_ERROR_CODE;
303930
303950
  error55.desktopInitErrorReason = toolName;
303931
- error55.userMessage = toolName === "mysqldump" ? "Confirm the local MySQL or MariaDB server and credentials work. If needed, install mysqldump from the same database family and major or LTS release as the server, verify it with `mysqldump --version`, then re-run `dvb agent-init check`. To proceed without local database data, change this database copy to skip." : `Fix the ${toolName} failure, then retry. To proceed without local database data, change this database copy to skip.`;
303951
+ const effectiveFailureKind = timedOut ? "timeout" : failureKind;
303952
+ error55.desktopDatabaseFailureKind = effectiveFailureKind;
303953
+ error55.userMessage = DATABASE_DUMP_FAILURE_USER_MESSAGES[effectiveFailureKind] ?? (toolName === "mysqldump" ? "Confirm the local MySQL or MariaDB server and credentials work. If needed, install mysqldump from the same database family and major or LTS release as the server, verify it with `mysqldump --version`, then retry the database copy or skip this database." : `Fix the ${toolName} failure, then retry the database copy or skip this database.`);
303932
303954
  return error55;
303933
303955
  };
303956
+ classifyDatabaseDumpFailure = ({ stderr, toolName }) => {
303957
+ const normalized = trim10(stderr);
303958
+ if (!normalized) {
303959
+ return "unknown";
303960
+ }
303961
+ if (toolName === "pg_dump") {
303962
+ if (/could not translate host name/iu.test(normalized)) {
303963
+ return "host_unresolved";
303964
+ }
303965
+ if (/connection to server[\s\S]*failed:[\s\S]*Connection refused/iu.test(
303966
+ normalized
303967
+ )) {
303968
+ return "connection_refused";
303969
+ }
303970
+ if (/password authentication failed for user/iu.test(normalized)) {
303971
+ return "authentication_failed";
303972
+ }
303973
+ if (/(?:fe_sendauth: )?no password supplied/iu.test(normalized)) {
303974
+ return "password_missing";
303975
+ }
303976
+ if (/database [\s\S]+ does not exist/iu.test(normalized)) {
303977
+ return "database_missing";
303978
+ }
303979
+ if (/permission denied/iu.test(normalized)) {
303980
+ return "permission_denied";
303981
+ }
303982
+ return "unknown";
303983
+ }
303984
+ if (toolName === "mysqldump") {
303985
+ if (/Unknown MySQL server host|Name or service not known|nodename nor servname provided/iu.test(
303986
+ normalized
303987
+ )) {
303988
+ return "host_unresolved";
303989
+ }
303990
+ if (/Can(?:not|'t) connect to (?:local )?MySQL server|Connection refused/iu.test(
303991
+ normalized
303992
+ )) {
303993
+ return "connection_refused";
303994
+ }
303995
+ if (/Access denied for user[\s\S]*using password: NO/iu.test(normalized)) {
303996
+ return "password_missing";
303997
+ }
303998
+ if (/Access denied for user/iu.test(normalized)) {
303999
+ return "authentication_failed";
304000
+ }
304001
+ if (/Unknown database/iu.test(normalized)) {
304002
+ return "database_missing";
304003
+ }
304004
+ if (/command denied to user|permission denied/iu.test(normalized)) {
304005
+ return "permission_denied";
304006
+ }
304007
+ }
304008
+ return "unknown";
304009
+ };
303934
304010
  executeDatabaseDumpCommand = (command, args, {
303935
304011
  cwd: cwd2,
303936
304012
  env: env3,
@@ -303964,9 +304040,10 @@ var init_localPrepService = __esm({
303964
304040
  );
303965
304041
  return;
303966
304042
  }
304043
+ const stderrText = Buffer.isBuffer(stderr) ? stderr.toString("utf8") : "";
303967
304044
  if (toolName === "pg_dump") {
303968
304045
  const versionMismatch = createPostgresDumpVersionMismatchError(
303969
- Buffer.isBuffer(stderr) ? stderr.toString("utf8") : "",
304046
+ stderrText,
303970
304047
  { source }
303971
304048
  );
303972
304049
  if (versionMismatch) {
@@ -303974,7 +304051,14 @@ var init_localPrepService = __esm({
303974
304051
  return;
303975
304052
  }
303976
304053
  }
303977
- reject(createDatabaseDumpExecutionError(toolName));
304054
+ reject(
304055
+ createDatabaseDumpExecutionError(toolName, {
304056
+ failureKind: classifyDatabaseDumpFailure({
304057
+ stderr: stderrText,
304058
+ toolName
304059
+ })
304060
+ })
304061
+ );
303978
304062
  }
303979
304063
  );
303980
304064
  });
@@ -306523,6 +306607,16 @@ var init_localPrepService = __esm({
306523
306607
  }
306524
306608
  return null;
306525
306609
  };
306610
+ createDatabaseSourceValidationError = ({
306611
+ failureKind,
306612
+ message,
306613
+ userMessage
306614
+ }) => {
306615
+ const error55 = new Error(message);
306616
+ error55.desktopDatabaseFailureKind = failureKind;
306617
+ error55.userMessage = userMessage;
306618
+ return error55;
306619
+ };
306526
306620
  getDatabaseValueForRole = async ({
306527
306621
  databaseEnv,
306528
306622
  homeDir: homeDir2,
@@ -306630,7 +306724,11 @@ var init_localPrepService = __esm({
306630
306724
  role: "url"
306631
306725
  });
306632
306726
  if (!rawUrl) {
306633
- throw new Error("Missing database URL value.");
306727
+ throw createDatabaseSourceValidationError({
306728
+ failureKind: "source_url_missing",
306729
+ message: "Missing database URL value.",
306730
+ userMessage: DATABASE_DUMP_FAILURE_USER_MESSAGES.source_url_missing
306731
+ });
306634
306732
  }
306635
306733
  return parseDatabaseUrlForDump({ expectedEngine, rawUrl });
306636
306734
  }
@@ -306707,7 +306805,7 @@ var init_localPrepService = __esm({
306707
306805
  homeDir: homeDir2,
306708
306806
  repoRoot
306709
306807
  });
306710
- const envForDump2 = { ...databaseEnv };
306808
+ const envForDump2 = { ...databaseEnv, LC_ALL: "C" };
306711
306809
  appendEnvValue(envForDump2, "PGHOST", parsed2.host);
306712
306810
  appendEnvValue(envForDump2, "PGPORT", normalizeDatabasePort(parsed2.port));
306713
306811
  appendEnvValue(envForDump2, "PGDATABASE", parsed2.database);
@@ -306759,7 +306857,7 @@ var init_localPrepService = __esm({
306759
306857
  args.push(`--ssl-mode=${parsed.sslMode}`);
306760
306858
  }
306761
306859
  args.push(parsed.database);
306762
- const envForDump = { ...databaseEnv };
306860
+ const envForDump = { ...databaseEnv, LC_ALL: "C" };
306763
306861
  appendEnvValue(envForDump, "MYSQL_PWD", parsed.password);
306764
306862
  return {
306765
306863
  command: "mysqldump",
@@ -306775,8 +306873,19 @@ var init_localPrepService = __esm({
306775
306873
  }).join("; ");
306776
306874
  return `Database dump creation failed for ${failures.length === 1 ? "an approved database" : "approved databases"}: ${details}`;
306777
306875
  };
306876
+ createPublicDatabaseDumpFailure = ({ candidate, error: error55 }) => ({
306877
+ candidateId: typeof candidate?.id === "string" && candidate.id.trim() ? candidate.id : null,
306878
+ label: typeof candidate?.displayLabel === "string" && candidate.displayLabel.trim() ? candidate.displayLabel : candidate?.id ?? "database",
306879
+ engine: candidate?.engine === "postgres" || candidate?.engine === "mysql" ? candidate.engine : null,
306880
+ code: error55 instanceof Error && typeof error55.desktopInitErrorCode === "string" ? error55.desktopInitErrorCode : null,
306881
+ failureKind: error55 instanceof Error && typeof error55.desktopDatabaseFailureKind === "string" ? error55.desktopDatabaseFailureKind : null,
306882
+ userMessage: error55 instanceof Error && typeof error55.userMessage === "string" ? error55.userMessage : "Setup could not copy this database. Check that it is running and that the selected connection works, then retry."
306883
+ });
306778
306884
  createDatabaseDumpFailureError = (failures) => {
306779
306885
  const error55 = new Error(formatDatabaseDumpFailureMessage(failures));
306886
+ error55.desktopDatabaseDumpFailures = failures.map(
306887
+ createPublicDatabaseDumpFailure
306888
+ );
306780
306889
  if (failures.length === 1) {
306781
306890
  const failureError = failures[0].error;
306782
306891
  if (failureError instanceof Error && typeof failureError.desktopInitErrorCode === "string") {
@@ -306796,7 +306905,7 @@ var init_localPrepService = __esm({
306796
306905
  ];
306797
306906
  error55.desktopInitErrorCode = DATABASE_DUMP_TOOL_MISSING_ERROR_CODE;
306798
306907
  error55.desktopInitErrorReason = missingCommands.length === 1 ? missingCommands[0] : "multiple";
306799
- error55.userMessage = missingCommands.length === 1 ? createMissingDatabaseDumpToolError(missingCommands[0]).userMessage : "Install the missing database dump tools, make sure they are available on PATH, then retry bundle preparation.";
306908
+ error55.userMessage = missingCommands.length === 1 ? createMissingDatabaseDumpToolError(missingCommands[0]).userMessage : "Install the missing database dump tools, make sure they are available on PATH, then retry the database copy.";
306800
306909
  return error55;
306801
306910
  }
306802
306911
  const executionErrors = failures.map((failure) => failure.error).filter(
@@ -306814,53 +306923,100 @@ var init_localPrepService = __esm({
306814
306923
  }
306815
306924
  return error55;
306816
306925
  };
306926
+ buildDatabasePreflightArgs = ({ command, validationMode }) => {
306927
+ if (validationMode !== "connection") {
306928
+ return command.command === "pg_dump" ? ["--schema-only", ...command.args] : ["--no-data", ...command.args];
306929
+ }
306930
+ if (command.command === "pg_dump") {
306931
+ return ["--schema-only", "--exclude-schema=*", ...command.args];
306932
+ }
306933
+ const connectionArgs = [];
306934
+ for (let index = 0; index < command.args.length; index += 1) {
306935
+ const arg2 = command.args[index];
306936
+ if (arg2 === "--single-transaction" || arg2 === "--routines" || arg2 === "--events" || arg2 === "--triggers" || arg2 === "--skip-comments") {
306937
+ continue;
306938
+ }
306939
+ if (arg2 === "--result-file") {
306940
+ index += 1;
306941
+ continue;
306942
+ }
306943
+ if (arg2.startsWith("--result-file=")) {
306944
+ continue;
306945
+ }
306946
+ connectionArgs.push(arg2);
306947
+ }
306948
+ return [
306949
+ "--no-data",
306950
+ "--no-create-info",
306951
+ "--skip-lock-tables",
306952
+ ...connectionArgs
306953
+ ];
306954
+ };
306817
306955
  preflightDatabaseDumpCandidates = async ({
306818
306956
  candidates,
306819
306957
  databaseDumpToolResolver = null,
306820
306958
  databaseEnv,
306821
306959
  homeDir: homeDir2,
306822
- repoRoot
306960
+ repoRoot,
306961
+ validationMode = "schema"
306823
306962
  }) => {
306824
306963
  const tempRoot = await fs41.mkdtemp(
306825
306964
  path51.join(os25.tmpdir(), "boxes-database-preflight-")
306826
306965
  );
306827
- const failures = [];
306966
+ const selectedCandidates = candidates.filter(
306967
+ (candidate) => candidate?.canAutomate === true
306968
+ );
306969
+ const failuresByIndex = new Array(selectedCandidates.length).fill(null);
306970
+ let nextCandidateIndex = 0;
306828
306971
  try {
306829
- for (const candidate of candidates) {
306830
- if (candidate?.canAutomate !== true) {
306831
- continue;
306832
- }
306833
- try {
306834
- const outputPath = path51.join(
306835
- tempRoot,
306836
- `${safeDatabaseDumpBaseName(candidate)}.${candidate.engine === "postgres" ? "dump" : "sql"}`
306837
- );
306838
- const command = await resolveDatabaseDumpCommand({
306839
- candidate,
306840
- databaseEnv,
306841
- homeDir: homeDir2,
306842
- outputPath,
306843
- repoRoot
306844
- });
306845
- const preflightArgs = command.command === "pg_dump" ? ["--schema-only", ...command.args] : ["--no-data", ...command.args];
306846
- await runDatabaseDumpCommand(command.command, preflightArgs, {
306847
- cwd: repoRoot,
306848
- databaseDumpToolResolver,
306849
- env: command.env
306850
- });
306851
- } catch (error55) {
306852
- failures.push({
306853
- candidateId: candidate.id ?? null,
306854
- label: candidate.displayLabel ?? candidate.id ?? "database",
306855
- message: toErrorMessage(error55),
306856
- code: error55 instanceof Error && typeof error55.desktopInitErrorCode === "string" ? error55.desktopInitErrorCode : null,
306857
- userMessage: error55 instanceof Error && typeof error55.userMessage === "string" ? error55.userMessage : null
306858
- });
306972
+ const worker = async () => {
306973
+ while (nextCandidateIndex < selectedCandidates.length) {
306974
+ const candidateIndex = nextCandidateIndex;
306975
+ nextCandidateIndex += 1;
306976
+ const candidate = selectedCandidates[candidateIndex];
306977
+ try {
306978
+ const outputPath = path51.join(
306979
+ tempRoot,
306980
+ `${candidateIndex}-${safeDatabaseDumpBaseName(candidate)}.${candidate.engine === "postgres" ? "dump" : "sql"}`
306981
+ );
306982
+ const command = await resolveDatabaseDumpCommand({
306983
+ candidate,
306984
+ databaseEnv,
306985
+ homeDir: homeDir2,
306986
+ outputPath,
306987
+ repoRoot
306988
+ });
306989
+ await runDatabaseDumpCommand(
306990
+ command.command,
306991
+ buildDatabasePreflightArgs({ command, validationMode }),
306992
+ {
306993
+ cwd: repoRoot,
306994
+ databaseDumpToolResolver,
306995
+ env: command.env,
306996
+ timeoutMs: validationMode === "connection" ? DATABASE_APPROVAL_PREFLIGHT_TIMEOUT_MS : DATABASE_DUMP_TIMEOUT_MS
306997
+ }
306998
+ );
306999
+ } catch (error55) {
307000
+ failuresByIndex[candidateIndex] = {
307001
+ ...createPublicDatabaseDumpFailure({ candidate, error: error55 }),
307002
+ message: toErrorMessage(error55)
307003
+ };
307004
+ }
306859
307005
  }
306860
- }
307006
+ };
307007
+ const concurrency = validationMode === "connection" ? DATABASE_APPROVAL_PREFLIGHT_CONCURRENCY : 1;
307008
+ await Promise.all(
307009
+ Array.from(
307010
+ {
307011
+ length: Math.min(concurrency, selectedCandidates.length)
307012
+ },
307013
+ () => worker()
307014
+ )
307015
+ );
306861
307016
  } finally {
306862
307017
  await fs41.rm(tempRoot, { recursive: true, force: true });
306863
307018
  }
307019
+ const failures = failuresByIndex.filter(Boolean);
306864
307020
  return { ok: failures.length === 0, failures };
306865
307021
  };
306866
307022
  createDatabasePayloads = async ({
@@ -311112,7 +311268,8 @@ var init_localPrepService = __esm({
311112
311268
  databaseDumpToolResolver,
311113
311269
  databaseEnv: capturedEnv.env,
311114
311270
  homeDir: homeDir2,
311115
- repoRoot: repo.repoRoot
311271
+ repoRoot: repo.repoRoot,
311272
+ validationMode: request2.databaseValidationMode === "connection" ? "connection" : "schema"
311116
311273
  });
311117
311274
  }),
311118
311275
  async getSnapshot(request2) {
@@ -328237,7 +328394,7 @@ var init_plan = __esm({
328237
328394
  };
328238
328395
  isDatabaseCopyCandidate2 = (value) => {
328239
328396
  if (!isObject10(value)) return false;
328240
- if (typeof value.id !== "string" || typeof value.engine !== "string" || typeof value.displayLabel !== "string" || typeof value.canAutomate !== "boolean" || typeof value.confidence !== "string" || !Array.isArray(value.evidence)) {
328397
+ if (typeof value.id !== "string" || value.id.trim().length === 0 || typeof value.engine !== "string" || typeof value.displayLabel !== "string" || typeof value.canAutomate !== "boolean" || typeof value.confidence !== "string" || !Array.isArray(value.evidence)) {
328241
328398
  return false;
328242
328399
  }
328243
328400
  const source = value.source;
@@ -328273,7 +328430,8 @@ var init_plan = __esm({
328273
328430
  };
328274
328431
  isSetupDatabasesPlan = (value) => {
328275
328432
  if (!isObject10(value)) return false;
328276
- return typeof value.schemaVersion === "number" && typeof value.scanFullyCompleted === "boolean" && Array.isArray(value.databaseCandidates) && value.databaseCandidates.every(isDatabaseCopyCandidate2);
328433
+ const databaseCandidates = Array.isArray(value.databaseCandidates) ? value.databaseCandidates : null;
328434
+ return typeof value.schemaVersion === "number" && typeof value.scanFullyCompleted === "boolean" && databaseCandidates !== null && databaseCandidates.every(isDatabaseCopyCandidate2) && new Set(databaseCandidates.map((candidate) => candidate.id)).size === databaseCandidates.length;
328277
328435
  };
328278
328436
  isServicesPlan = (value) => {
328279
328437
  if (!isObject10(value)) return false;
@@ -357351,4 +357509,4 @@ react/cjs/react-jsx-runtime.development.js:
357351
357509
  *)
357352
357510
  */
357353
357511
 
357354
- //# debugId=a55a831a-e9eb-5e0c-9e31-0c4bceb58a84
357512
+ //# debugId=622a15c0-7c29-5be9-a35c-b1a193a6b0f0
package/dist/bin/dvbd.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
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]="9fe1a110-cbff-5659-8dbf-ea5f546fb817")}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]="273915e4-19f9-5515-bec4-e13639bb51de")}catch(e){}}();
4
4
  import { createRequire as __dvbCreateRequire } from "node:module";
5
5
  import { dirname as __dvbDirname } from "node:path";
6
6
  import { fileURLToPath as __dvbFileURLToPath } from "node:url";
@@ -96328,8 +96328,8 @@ var init_otel = __esm({
96328
96328
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
96329
96329
  };
96330
96330
  readBuildMetadata = () => {
96331
- const rawPackageVersion = "1.0.957";
96332
- const rawGitSha = "bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
96331
+ const rawPackageVersion = "1.0.959";
96332
+ const rawGitSha = "c5992d38486ffdbc188773dfe7556175ffb24abc";
96333
96333
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
96334
96334
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
96335
96335
  return { packageVersion, gitSha };
@@ -128624,9 +128624,9 @@ var init_sentry = __esm({
128624
128624
  uncaughtExceptionMonitorInstalled = false;
128625
128625
  currentDevboxSentryUser = null;
128626
128626
  readBuildMetadata2 = () => {
128627
- const rawPackageVersion = "1.0.957";
128628
- const rawGitSha = "bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
128629
- const rawSentryRelease = "boxes-dev-dvb@1.0.957+bd2eee580a498b70adca3fcd0e8c9d25eb248aaf";
128627
+ const rawPackageVersion = "1.0.959";
128628
+ const rawGitSha = "c5992d38486ffdbc188773dfe7556175ffb24abc";
128629
+ const rawSentryRelease = "boxes-dev-dvb@1.0.959+c5992d38486ffdbc188773dfe7556175ffb24abc";
128630
128630
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
128631
128631
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
128632
128632
  const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
@@ -130818,7 +130818,7 @@ var init_packageVersion = __esm({
130818
130818
  return path8.join(process.cwd(), "dvb");
130819
130819
  };
130820
130820
  readEmbeddedPackageVersion = () => {
130821
- const raw = "1.0.957";
130821
+ const raw = "1.0.959";
130822
130822
  return trimVersion(raw);
130823
130823
  };
130824
130824
  readNearestPackageMetadata = (basePath) => {
@@ -144013,4 +144013,4 @@ long/umd/index.js:
144013
144013
  *)
144014
144014
  */
144015
144015
 
144016
- //# debugId=9fe1a110-cbff-5659-8dbf-ea5f546fb817
144016
+ //# debugId=273915e4-19f9-5515-bec4-e13639bb51de
@@ -30,6 +30,10 @@ authority, and an unassociated box receives no targets.
30
30
 
31
31
  ## Current Box Role
32
32
 
33
+ Every managed agent, terminal, and child process receives `BOXES_DEVBOX=1` on
34
+ both Template boxes and ordinary devboxes. Use this presence flag when a tool
35
+ or skill only needs to know that it is running in a boxes.dev environment.
36
+
33
37
  An on-box agent can read whether it is running on the project's Template box or
34
38
  an ordinary devbox without contacting or waking another machine:
35
39
 
@@ -401,10 +405,11 @@ dvb-onbox threads read \
401
405
  --json
402
406
  ```
403
407
 
404
- This returns the durable boxes.dev transcript projection, thread status, and
405
- older-page cursor. It can briefly lag the live runtime. Pending Codex and Claude
406
- queue entries remain runtime state and do not appear as transcript messages
407
- until the provider accepts them as turns.
408
+ This returns a bounded preview of the durable boxes.dev transcript, thread
409
+ status, and older-page cursor. Long messages are marked as shortened. It can
410
+ briefly lag the live runtime. Pending Codex and Claude queue entries remain
411
+ runtime state and do not appear as transcript messages until the provider
412
+ accepts them as turns.
408
413
 
409
414
  List and observe that same source-scoped child pool without waking a child
410
415
  devbox:
@@ -412,6 +417,10 @@ devbox:
412
417
  ```bash
413
418
  dvb-onbox threads list [--include-archived] [--cursor <cursor> | --all] --json
414
419
 
420
+ dvb-onbox threads result <delegated-thread-id> \
421
+ --turn <turn-id> \
422
+ --json
423
+
415
424
  dvb-onbox threads wait <delegated-thread-id> \
416
425
  [--turn <turn-id>] \
417
426
  [--timeout <duration>] \
@@ -424,15 +433,19 @@ dvb-onbox threads events <delegated-thread-id> \
424
433
 
425
434
  `threads list` uses the current source box's project automatically and never
426
435
  shows other project threads, including children created by a different source
427
- box. `threads wait` snapshots the current active turn once when `--turn` is
428
- omitted; Ctrl+C stops only the local wait. `threads events` emits durable
429
- lifecycle events with an opaque resume cursor on every JSONL row. With no turn,
430
- cursor, or `--from-start`, it follows only events created after the command
431
- starts. An exact-turn stream ends after needs-input or a terminal event.
432
-
433
- Read, list, wait, and events operate on durable control-service state, so they
434
- can inspect archived, cold, and history-only children without waking their
435
- devboxes or claiming a live input surface. The source box's live **Create
436
+ box. `threads result` returns the complete stored final response for one exact
437
+ terminal turn and automatically assembles its transport pages. Use it instead
438
+ of asking the child to summarize a shortened `threads read` preview. When
439
+ `threads wait` omits `--turn`, it snapshots the current active turn once. A
440
+ completed wait includes that same complete response as `output.text`; Ctrl+C
441
+ stops only the local wait. `threads events` emits durable lifecycle events with
442
+ an opaque resume cursor on every JSONL row. With no turn, cursor, or
443
+ `--from-start`, it follows only events created after the command starts. An
444
+ exact-turn stream ends after needs-input or a terminal event.
445
+
446
+ Read, result, list, wait, and events operate on durable control-service state,
447
+ so they can inspect archived, cold, and history-only children without waking
448
+ their devboxes or claiming a live input surface. The source box's live **Create
436
449
  devboxes and threads** permission is checked on every observation and control.
437
450
  Prompt files are limited to 32 KiB.
438
451
 
@@ -395,6 +395,14 @@ The review page also has an optional freeform note for anything the setup coding
395
395
  agent should know; that note is included in the approved setup plan for the
396
396
  Template box setup thread.
397
397
 
398
+ When the user approves **Local database dumps**, desktop setup briefly checks
399
+ each selected PostgreSQL or MySQL/MariaDB connection without copying database
400
+ contents. If a database is stopped, missing, unreachable, or rejects the
401
+ selected credentials, that row stays unapproved and explains what went wrong.
402
+ The user can retry after starting the database, skip that database, or ask the
403
+ scan agent once to correct its connection finding. Agent repair receives only
404
+ credential-free connection diagnostics.
405
+
398
406
  When the scan finds an environment file, boxes.dev snapshots a copy of it at
399
407
  scan time and sends that copy to the Template box. Users can open any env file
400
408
  in an in-app editor and change exactly what gets sent (for example, removing a
@@ -448,12 +456,14 @@ copies. Setup continues to prefer a usable `pg_dump` already on `PATH`, then
448
456
  uses the included client when the host command is missing or is older than the
449
457
  source server. If the included payload is unavailable, or the Postgres server
450
458
  is newer than the included client, setup explains how to update or reinstall
451
- boxes.dev or use a compatible host client. The user can also continue without
452
- the database dump if the database copy is not essential. MySQL copies still
453
- require `mysqldump` on `PATH`. If a MySQL dump fails, setup explains how to use
454
- a client from the same MySQL or MariaDB family and major or LTS release as the
455
- local server. The user can retry after fixing the connection or client, or
456
- continue immediately without importing the local database data.
459
+ boxes.dev or use a compatible host client. The user can also skip that database
460
+ if its local data is not essential. MySQL copies still require `mysqldump` on
461
+ `PATH`. If a MySQL dump fails, setup explains how to use a client from the same
462
+ MySQL or MariaDB family and major or LTS release as the local server. The user
463
+ can retry after fixing the connection or client, or skip the failed database
464
+ and continue. When several database copies were selected, skipping removes only
465
+ the copies that failed; successful selections remain in the setup bundle. Every
466
+ full-dump failure is shown before upload rather than silently omitting its data.
457
467
 
458
468
  The bundle screen also shows size information and warns if the bundle is too
459
469
  large.
@@ -611,6 +621,15 @@ summary before it requests completion.
611
621
 
612
622
  Setup state is persisted so interrupted setup can usually be resumed.
613
623
 
624
+ Interrupted desktop setups appear under **Setups in progress** in two places:
625
+ below the setup options on the wizard's Project step, and in their own section
626
+ of the titlebar project selector. Choosing an entry in either place will
627
+ reopen setup at the step where it left off. The wizard row also offers
628
+ **Continue setup** and a delete button; deleting removes only the incomplete
629
+ setup state, and the local folder and its files won't be affected. A setup
630
+ waiting on a recoverable error shows **Needs attention** in the project
631
+ selector.
632
+
614
633
  Common recovery paths:
615
634
 
616
635
  - Existing completed project: open the existing project.
@@ -73,7 +73,7 @@ Return JSON with this shape:
73
73
 
74
74
  Each `databaseCandidates` entry must include:
75
75
 
76
- - `id`: stable short slug
76
+ - `id`: non-empty stable short slug, unique within `databaseCandidates`
77
77
  - `engine`: `postgres` or `mysql`
78
78
  - `displayLabel`: concise user-facing label for approval UI
79
79
  - `source`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxes-dev/dvb-runtime",
3
- "version": "1.0.957",
3
+ "version": "1.0.959",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "imports": {
@@ -77,5 +77,5 @@
77
77
  "e2b": "^2.18.0",
78
78
  "ink-testing-library": "^4.0.0"
79
79
  },
80
- "devboxReleasedAt": "2026-08-26T22:05:52Z"
80
+ "devboxReleasedAt": "2026-08-27T22:42:48Z"
81
81
  }