@boxes-dev/dvb 0.2.35 → 0.2.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/dvb.cjs CHANGED
@@ -23228,7 +23228,6 @@ var init_state = __esm({
23228
23228
  "setupPlanScanned",
23229
23229
  "servicesPlanScanned",
23230
23230
  "setupPlanWritten",
23231
- "servicesPlanWritten",
23232
23231
  "servicesConfigWritten",
23233
23232
  "workdirProvisioned",
23234
23233
  "gitSafeDirectoryConfigured",
@@ -24310,7 +24309,7 @@ fi`
24310
24309
  });
24311
24310
 
24312
24311
  // src/devbox/commands/init/codex/plan.ts
24313
- var import_node_path18, import_promises24, resolveSchemaPath, writeSetupEnvSecretsSchema, writeSetupExternalSchema, writeSetupExtraArtifactsSchema, writeServicesSchema, isObject4, isSetupPlan, isSetupEnvSecretsPlan, isSetupExternalPlan, isSetupExtraArtifactsPlan, isServicesPlan, readSetupPlan, readSetupEnvSecretsPlan, readSetupExternalPlan, readSetupExtraArtifactsPlan, readServicesPlan, writeSetupPlan, mergeSetupScans, writeServicesPlan;
24312
+ var import_node_path18, import_promises24, resolveSchemaPath, writeSetupEnvSecretsSchema, writeSetupExternalSchema, writeSetupExtraArtifactsSchema, writeServicesSchema, isObject4, isServicesSelection, isSetupPlan, isSetupEnvSecretsPlan, isSetupExternalPlan, isSetupExtraArtifactsPlan, isServicesPlan, readSetupPlan, readSetupEnvSecretsPlan, readSetupExternalPlan, readSetupExtraArtifactsPlan, readServicesPlan, writeSetupPlan, mergeSetupScans;
24314
24313
  var init_plan = __esm({
24315
24314
  "src/devbox/commands/init/codex/plan.ts"() {
24316
24315
  "use strict";
@@ -24357,9 +24356,13 @@ var init_plan = __esm({
24357
24356
  return schemaPath;
24358
24357
  };
24359
24358
  isObject4 = (value) => typeof value === "object" && value !== null;
24359
+ isServicesSelection = (value) => {
24360
+ if (!isObject4(value)) return false;
24361
+ return Array.isArray(value.appEntrypoints) && Array.isArray(value.backgroundServices);
24362
+ };
24360
24363
  isSetupPlan = (value) => {
24361
24364
  if (!isObject4(value)) return false;
24362
- return typeof value.schemaVersion === "number" && Array.isArray(value.envFiles) && Array.isArray(value.secretFiles) && Array.isArray(value.extraArtifacts) && Array.isArray(value.externalDependencies) && Array.isArray(value.externalConfigs);
24365
+ return typeof value.schemaVersion === "number" && Array.isArray(value.envFiles) && Array.isArray(value.secretFiles) && Array.isArray(value.extraArtifacts) && Array.isArray(value.externalDependencies) && Array.isArray(value.externalConfigs) && isServicesSelection(value.services);
24363
24366
  };
24364
24367
  isSetupEnvSecretsPlan = (value) => {
24365
24368
  if (!isObject4(value)) return false;
@@ -24423,7 +24426,8 @@ var init_plan = __esm({
24423
24426
  mergeSetupScans = ({
24424
24427
  envSecrets,
24425
24428
  external,
24426
- extraArtifacts
24429
+ extraArtifacts,
24430
+ services
24427
24431
  }) => {
24428
24432
  const dedupeBy = (items, key) => {
24429
24433
  const seen = /* @__PURE__ */ new Set();
@@ -24457,17 +24461,15 @@ var init_plan = __esm({
24457
24461
  (entry) => entry.name
24458
24462
  ).sort((a2, b) => a2.name.localeCompare(b.name));
24459
24463
  return {
24460
- schemaVersion: 2,
24464
+ schemaVersion: 3,
24461
24465
  envFiles,
24462
24466
  secretFiles,
24463
24467
  extraArtifacts: mergedExtraArtifacts,
24464
24468
  externalDependencies,
24465
- externalConfigs
24469
+ externalConfigs,
24470
+ services
24466
24471
  };
24467
24472
  };
24468
- writeServicesPlan = async (servicesPath, plan) => {
24469
- await import_promises24.default.writeFile(servicesPath, JSON.stringify(plan, null, 2), "utf8");
24470
- };
24471
24473
  }
24472
24474
  });
24473
24475
 
@@ -24905,6 +24907,7 @@ var init_local = __esm({
24905
24907
  `codex-local-services-scan-${stamp}.meta.json`
24906
24908
  );
24907
24909
  await import_promises25.default.mkdir(logDir, { recursive: true, mode: 448 });
24910
+ await import_promises25.default.mkdir(import_node_path19.default.dirname(outputPath), { recursive: true, mode: 448 });
24908
24911
  try {
24909
24912
  await import_promises25.default.chmod(logDir, 448);
24910
24913
  } catch {
@@ -25050,12 +25053,13 @@ ${usageText}`;
25050
25053
  externalDependencies: plan.externalDependencies.filter(
25051
25054
  (entry) => externalDependencySet.has(entry.name)
25052
25055
  ),
25053
- externalConfigs: plan.externalConfigs.filter((entry) => externalConfigSet.has(entry.path))
25056
+ externalConfigs: plan.externalConfigs.filter((entry) => externalConfigSet.has(entry.path)),
25057
+ services: initialPlan?.services ?? plan.services
25054
25058
  };
25055
25059
  };
25056
25060
  promptForServicesApproval = async ({
25057
25061
  plan,
25058
- initialPlan
25062
+ initialSelection
25059
25063
  }) => {
25060
25064
  R2.step("Review run services findings");
25061
25065
  const appEntrypointOptions = plan.appEntrypoints.map((entry) => ({
@@ -25071,7 +25075,7 @@ ${usageText}`;
25071
25075
  const appEntrypointSelection = plan.appEntrypoints.length === 0 ? [] : await multiselectWithHelp({
25072
25076
  message: "Select app entrypoints to validate setup",
25073
25077
  options: appEntrypointOptions,
25074
- initialValues: initialPlan?.appEntrypoints.map((entry) => entry.command) ?? plan.appEntrypoints.map((entry) => entry.command),
25078
+ initialValues: initialSelection?.appEntrypoints.map((entry) => entry.command) ?? plan.appEntrypoints.map((entry) => entry.command),
25075
25079
  required: false
25076
25080
  });
25077
25081
  if (Ct(appEntrypointSelection)) {
@@ -25081,7 +25085,7 @@ ${usageText}`;
25081
25085
  const backgroundServiceSelection = plan.backgroundServices.length === 0 ? [] : await multiselectWithHelp({
25082
25086
  message: "Select background services to run in the devbox",
25083
25087
  options: backgroundServiceOptions,
25084
- initialValues: initialPlan?.backgroundServices.map((entry) => entry.name) ?? plan.backgroundServices.map((entry) => entry.name),
25088
+ initialValues: initialSelection?.backgroundServices.map((entry) => entry.name) ?? plan.backgroundServices.map((entry) => entry.name),
25085
25089
  required: false
25086
25090
  });
25087
25091
  if (Ct(backgroundServiceSelection)) {
@@ -25091,8 +25095,6 @@ ${usageText}`;
25091
25095
  const appEntrypointSet = new Set(appEntrypointSelection);
25092
25096
  const backgroundServiceSet = new Set(backgroundServiceSelection);
25093
25097
  return {
25094
- schemaVersion: plan.schemaVersion,
25095
- scanFullyCompleted: plan.scanFullyCompleted,
25096
25098
  appEntrypoints: plan.appEntrypoints.filter(
25097
25099
  (entry) => appEntrypointSet.has(entry.command)
25098
25100
  ),
@@ -26635,7 +26637,6 @@ var init_init = __esm({
26635
26637
  "box.json",
26636
26638
  "init-state.json",
26637
26639
  "setup.json",
26638
- "services.json",
26639
26640
  "setup-artifacts.tgz",
26640
26641
  "setup-artifacts.json",
26641
26642
  "scans",
@@ -26660,7 +26661,7 @@ var init_init = __esm({
26660
26661
  for (const service of services) {
26661
26662
  const name = service.name.trim();
26662
26663
  if (!name) {
26663
- throw new Error("Service name is required in services.json.");
26664
+ throw new Error("Service name is required in setup.json services.");
26664
26665
  }
26665
26666
  const parts = splitShellCommand(service.command ?? "");
26666
26667
  const [cmd, ...args] = parts;
@@ -26738,7 +26739,7 @@ var init_init = __esm({
26738
26739
  for (const service of services) {
26739
26740
  const name = service.name.trim();
26740
26741
  if (!name) {
26741
- throw new Error("Service name is required in services.json.");
26742
+ throw new Error("Service name is required in setup.json services.");
26742
26743
  }
26743
26744
  status?.stage(`Enabling service: ${name}`);
26744
26745
  const parts = splitShellCommand(service.command ?? "");
@@ -27237,13 +27238,11 @@ var init_init = __esm({
27237
27238
  }
27238
27239
  const setupDir2 = projectDir;
27239
27240
  const setupPath2 = import_node_path22.default.join(setupDir2, "setup.json");
27240
- const servicesPath2 = import_node_path22.default.join(setupDir2, "services.json");
27241
+ let setupPlan;
27241
27242
  try {
27242
- await import_promises28.default.access(setupPath2);
27243
+ setupPlan = await readSetupPlan(setupPath2);
27243
27244
  } catch {
27244
- throw new Error(
27245
- `Missing setup plan (${setupPath2}). Run \`dvb init\` first.`
27246
- );
27245
+ throw new Error(`Missing or invalid setup plan (${setupPath2}). Run \`dvb init\` first.`);
27247
27246
  }
27248
27247
  const localArtifactsBundlePath = import_node_path22.default.join(
27249
27248
  setupDir2,
@@ -27322,12 +27321,6 @@ var init_init = __esm({
27322
27321
  "setup-artifacts.json"
27323
27322
  );
27324
27323
  const pathSetup2 = 'export PATH="$(npm bin -g 2>/dev/null):$PATH"';
27325
- let servicesPlan = null;
27326
- try {
27327
- servicesPlan = await readServicesPlan(servicesPath2);
27328
- } catch {
27329
- servicesPlan = null;
27330
- }
27331
27324
  await runInitStep({
27332
27325
  enabled: progressEnabled,
27333
27326
  title: "Configuring git safe.directory",
@@ -27407,7 +27400,7 @@ var init_init = __esm({
27407
27400
  await enableRemoteServices({
27408
27401
  client: client2,
27409
27402
  canonical: canonical2,
27410
- services: servicesPlan?.backgroundServices ?? [],
27403
+ services: setupPlan.services.backgroundServices,
27411
27404
  status
27412
27405
  });
27413
27406
  }
@@ -27426,7 +27419,7 @@ var init_init = __esm({
27426
27419
  socketInfo: socketInfo2,
27427
27420
  status,
27428
27421
  pathSetup: pathSetup2,
27429
- entrypoints: servicesPlan?.appEntrypoints ?? []
27422
+ entrypoints: setupPlan.services.appEntrypoints
27430
27423
  });
27431
27424
  }
27432
27425
  });
@@ -27765,7 +27758,6 @@ var init_init = __esm({
27765
27758
  });
27766
27759
  const setupDir = projectDir;
27767
27760
  const setupPath = import_node_path22.default.join(setupDir, "setup.json");
27768
- const servicesPath = import_node_path22.default.join(setupDir, "services.json");
27769
27761
  const scansDir = import_node_path22.default.join(setupDir, "scans");
27770
27762
  const logDir = import_node_path22.default.join(setupDir, "logs");
27771
27763
  const setupEnvSecretsScanPath = import_node_path22.default.join(scansDir, "setup-env-secrets.json");
@@ -27774,16 +27766,15 @@ var init_init = __esm({
27774
27766
  scansDir,
27775
27767
  "setup-extra-artifacts.json"
27776
27768
  );
27769
+ const servicesScanPath = import_node_path22.default.join(scansDir, "services.json");
27777
27770
  let setupArtifacts = null;
27778
27771
  const nonInteractive = !process.stdin.isTTY || parsed.json;
27779
27772
  const skipSetupPlan = shouldResume && initState?.steps.setupPlanWritten;
27780
- const skipServicesPlan = shouldResume && initState?.steps.servicesPlanWritten;
27781
27773
  const skipServicesConfig = shouldResume && initState?.steps.servicesConfigWritten;
27782
27774
  const skipServicesEnable = shouldResume && initState?.steps.servicesEnabled;
27783
27775
  const skipSetupUpload = nonInteractive || shouldResume && initState?.steps.setupUploaded;
27784
27776
  const skipCodexApply = nonInteractive || shouldResume && initState?.steps.codexApplied;
27785
27777
  let approvedPlan = null;
27786
- let approvedServices = null;
27787
27778
  const setupTempDir = await import_promises28.default.mkdtemp(
27788
27779
  import_node_path22.default.join(import_node_os9.default.tmpdir(), "devbox-setup-")
27789
27780
  );
@@ -27802,7 +27793,7 @@ var init_init = __esm({
27802
27793
  };
27803
27794
  const tryReadServicesPlan = async () => {
27804
27795
  try {
27805
- return await readServicesPlan(servicesPath);
27796
+ return await readServicesPlan(servicesScanPath);
27806
27797
  } catch {
27807
27798
  return null;
27808
27799
  }
@@ -27830,8 +27821,8 @@ var init_init = __esm({
27830
27821
  };
27831
27822
  const shouldRetryCodexScan = (scanFullyCompleted, ...arrays) => !scanFullyCompleted && arrays.every((array) => array.length === 0);
27832
27823
  let setupPlan = skipSetupPlan || !shouldResume ? null : await tryReadSetupPlan();
27833
- let servicesPlan = skipServicesPlan || !shouldResume ? null : await tryReadServicesPlan();
27834
27824
  const needsSetupScan = !skipSetupPlan && !setupPlan;
27825
+ let servicesPlan = !needsSetupScan || !shouldResume ? null : await tryReadServicesPlan();
27835
27826
  let envSecretsScan = !needsSetupScan || !shouldResume ? null : await tryReadEnvSecretsScan();
27836
27827
  let externalScan = !needsSetupScan || !shouldResume ? null : await tryReadExternalScan();
27837
27828
  let extraArtifactsScan = !needsSetupScan || !shouldResume ? null : await tryReadExtraArtifactsScan();
@@ -27862,7 +27853,7 @@ var init_init = __esm({
27862
27853
  )) {
27863
27854
  extraArtifactsScan = null;
27864
27855
  }
27865
- const needsServicesScan = !skipServicesPlan && !servicesPlan;
27856
+ const needsServicesScan = needsSetupScan && !servicesPlan;
27866
27857
  const needsEnvSecretsScan = needsSetupScan && !envSecretsScan;
27867
27858
  const needsExternalScan = needsSetupScan && !externalScan;
27868
27859
  const needsExtraArtifactsScan = needsSetupScan && !extraArtifactsScan;
@@ -27983,12 +27974,12 @@ var init_init = __esm({
27983
27974
  cwd: repoRoot,
27984
27975
  logDir,
27985
27976
  schemaPath: servicesSchemaPath,
27986
- outputPath: servicesPath,
27977
+ outputPath: servicesScanPath,
27987
27978
  homeDir: localHomeDir,
27988
27979
  onProgress: updateServices
27989
27980
  }),
27990
- read: async () => await readServicesPlan(servicesPath),
27991
- outputPath: servicesPath,
27981
+ read: async () => await readServicesPlan(servicesScanPath),
27982
+ outputPath: servicesScanPath,
27992
27983
  update: updateServices,
27993
27984
  shouldRetry: (plan) => shouldRetryCodexScan(
27994
27985
  plan.scanFullyCompleted,
@@ -28004,7 +27995,7 @@ var init_init = __esm({
28004
27995
  ]);
28005
27996
  if (needsServicesScan) {
28006
27997
  if (!services) {
28007
- throw new Error("Services plan missing.");
27998
+ throw new Error("Services scan missing.");
28008
27999
  }
28009
28000
  servicesPlan = services;
28010
28001
  }
@@ -28018,11 +28009,18 @@ var init_init = __esm({
28018
28009
  if (!extraArtifacts) {
28019
28010
  throw new Error("Extra artifacts scan missing.");
28020
28011
  }
28012
+ if (!servicesPlan) {
28013
+ throw new Error("Services scan missing.");
28014
+ }
28021
28015
  updateEnvSecrets("merging setup plan");
28022
28016
  const merged = mergeSetupScans({
28023
28017
  envSecrets,
28024
28018
  external,
28025
- extraArtifacts
28019
+ extraArtifacts,
28020
+ services: {
28021
+ appEntrypoints: servicesPlan.appEntrypoints,
28022
+ backgroundServices: servicesPlan.backgroundServices
28023
+ }
28026
28024
  });
28027
28025
  await writeSetupPlan(setupPath, merged);
28028
28026
  setupPlan = merged;
@@ -28084,7 +28082,7 @@ var init_init = __esm({
28084
28082
  needsSetupScan ? needsExtraArtifactsScan ? "starting" : "cached" : "skipped"
28085
28083
  );
28086
28084
  updateServices(
28087
- skipServicesPlan ? "skipped" : needsServicesScan ? "starting" : "cached"
28085
+ needsServicesScan ? "starting" : "cached"
28088
28086
  );
28089
28087
  try {
28090
28088
  await runLocalEnvironmentAnalysis({
@@ -28105,15 +28103,9 @@ var init_init = __esm({
28105
28103
  if (!skipSetupPlan && !setupPlan) {
28106
28104
  setupPlan = await readSetupPlan(setupPath);
28107
28105
  }
28108
- if (!skipServicesPlan && !servicesPlan) {
28109
- servicesPlan = await readServicesPlan(servicesPath);
28110
- }
28111
28106
  if (!skipSetupPlan && !setupPlan) {
28112
28107
  throw new Error("Setup plan missing.");
28113
28108
  }
28114
- if (!skipServicesPlan && !servicesPlan) {
28115
- throw new Error("Services plan missing.");
28116
- }
28117
28109
  const scanStepUpdate = {};
28118
28110
  if (!skipSetupPlan && setupPlan) {
28119
28111
  if (!initState?.steps.setupEnvSecretsScanned) {
@@ -28128,9 +28120,9 @@ var init_init = __esm({
28128
28120
  if (!initState?.steps.setupPlanScanned) {
28129
28121
  scanStepUpdate.setupPlanScanned = true;
28130
28122
  }
28131
- }
28132
- if (!skipServicesPlan && servicesPlan && !initState?.steps.servicesPlanScanned) {
28133
- scanStepUpdate.servicesPlanScanned = true;
28123
+ if (!initState?.steps.servicesPlanScanned) {
28124
+ scanStepUpdate.servicesPlanScanned = true;
28125
+ }
28134
28126
  }
28135
28127
  if (Object.keys(scanStepUpdate).length > 0) {
28136
28128
  await updateInitState({ steps: scanStepUpdate });
@@ -28138,26 +28130,21 @@ var init_init = __esm({
28138
28130
  if (skipSetupPlan) {
28139
28131
  approvedPlan = await readSetupPlan(setupPath);
28140
28132
  }
28141
- if (skipServicesPlan) {
28142
- approvedServices = await readServicesPlan(servicesPath);
28143
- }
28144
- if (shouldResume && (approvedPlan || approvedServices)) {
28133
+ if (shouldResume && approvedPlan) {
28145
28134
  const backfillStepUpdate = {};
28146
- if (approvedPlan) {
28147
- if (!initState?.steps.setupEnvSecretsScanned) {
28148
- backfillStepUpdate.setupEnvSecretsScanned = true;
28149
- }
28150
- if (!initState?.steps.setupExternalScanned) {
28151
- backfillStepUpdate.setupExternalScanned = true;
28152
- }
28153
- if (!initState?.steps.setupExtraArtifactsScanned) {
28154
- backfillStepUpdate.setupExtraArtifactsScanned = true;
28155
- }
28156
- if (!initState?.steps.setupPlanScanned) {
28157
- backfillStepUpdate.setupPlanScanned = true;
28158
- }
28135
+ if (!initState?.steps.setupEnvSecretsScanned) {
28136
+ backfillStepUpdate.setupEnvSecretsScanned = true;
28159
28137
  }
28160
- if (approvedServices && !initState?.steps.servicesPlanScanned) {
28138
+ if (!initState?.steps.setupExternalScanned) {
28139
+ backfillStepUpdate.setupExternalScanned = true;
28140
+ }
28141
+ if (!initState?.steps.setupExtraArtifactsScanned) {
28142
+ backfillStepUpdate.setupExtraArtifactsScanned = true;
28143
+ }
28144
+ if (!initState?.steps.setupPlanScanned) {
28145
+ backfillStepUpdate.setupPlanScanned = true;
28146
+ }
28147
+ if (!initState?.steps.servicesPlanScanned) {
28161
28148
  backfillStepUpdate.servicesPlanScanned = true;
28162
28149
  }
28163
28150
  if (Object.keys(backfillStepUpdate).length > 0) {
@@ -28166,8 +28153,7 @@ var init_init = __esm({
28166
28153
  }
28167
28154
  if (nonInteractive) {
28168
28155
  if (setupPlan) approvedPlan = setupPlan;
28169
- if (servicesPlan) approvedServices = servicesPlan;
28170
- } else if (setupPlan || servicesPlan) {
28156
+ } else if (!skipSetupPlan && setupPlan) {
28171
28157
  if (!process.stdin.isTTY || parsed.json) {
28172
28158
  throw new Error("Interactive terminal required to approve setup.");
28173
28159
  }
@@ -28189,54 +28175,51 @@ var init_init = __esm({
28189
28175
  statCache.set(candidatePath, info);
28190
28176
  return info;
28191
28177
  };
28192
- const buildApprovalSummary = async ({
28193
- setup,
28194
- services
28195
- }) => {
28178
+ const buildApprovalSummary = async (plan) => {
28196
28179
  const lines = [];
28197
28180
  lines.push("Setup");
28198
- lines.push(`- .env files: ${setup.envFiles.length}`);
28199
- for (const entry of setup.envFiles) {
28181
+ lines.push(`- .env files: ${plan.envFiles.length}`);
28182
+ for (const entry of plan.envFiles) {
28200
28183
  lines.push(` - ${toRepoRelativePath2(repoRoot, entry.path)}`);
28201
28184
  }
28202
- lines.push(`- Secret/config files: ${setup.secretFiles.length}`);
28203
- for (const entry of setup.secretFiles) {
28185
+ lines.push(`- Secret/config files: ${plan.secretFiles.length}`);
28186
+ for (const entry of plan.secretFiles) {
28204
28187
  lines.push(` - ${toRepoRelativePath2(repoRoot, entry.path)}`);
28205
28188
  }
28206
- lines.push(`- Other artifacts: ${setup.extraArtifacts.length}`);
28207
- for (const entry of setup.extraArtifacts) {
28189
+ lines.push(`- Other artifacts: ${plan.extraArtifacts.length}`);
28190
+ for (const entry of plan.extraArtifacts) {
28208
28191
  lines.push(` - ${toRepoRelativePath2(repoRoot, entry.path)}`);
28209
28192
  }
28210
- lines.push(`- External dependencies: ${setup.externalDependencies.length}`);
28211
- for (const entry of setup.externalDependencies) {
28193
+ lines.push(`- External dependencies: ${plan.externalDependencies.length}`);
28194
+ for (const entry of plan.externalDependencies) {
28212
28195
  lines.push(
28213
28196
  ` - ${entry.version ? `${entry.name}@${entry.version}` : entry.name}`
28214
28197
  );
28215
28198
  }
28216
28199
  lines.push(
28217
- `- External config/secret files: ${setup.externalConfigs.length}`
28200
+ `- External config/secret files: ${plan.externalConfigs.length}`
28218
28201
  );
28219
- for (const entry of setup.externalConfigs) {
28202
+ for (const entry of plan.externalConfigs) {
28220
28203
  lines.push(` - ${toRepoRelativePath2(repoRoot, entry.path)}`);
28221
28204
  }
28222
28205
  lines.push("");
28223
28206
  lines.push("Services");
28224
- lines.push(`- App entrypoints: ${services.appEntrypoints.length}`);
28225
- for (const entry of services.appEntrypoints) {
28207
+ lines.push(`- App entrypoints: ${plan.services.appEntrypoints.length}`);
28208
+ for (const entry of plan.services.appEntrypoints) {
28226
28209
  lines.push(` - ${entry.command}`);
28227
28210
  }
28228
28211
  lines.push(
28229
- `- Background services: ${services.backgroundServices.length}`
28212
+ `- Background services: ${plan.services.backgroundServices.length}`
28230
28213
  );
28231
- for (const entry of services.backgroundServices) {
28214
+ for (const entry of plan.services.backgroundServices) {
28232
28215
  lines.push(` - ${entry.name}`);
28233
28216
  }
28234
28217
  const candidatePaths = /* @__PURE__ */ new Set();
28235
28218
  for (const entry of [
28236
- ...setup.envFiles,
28237
- ...setup.secretFiles,
28238
- ...setup.extraArtifacts,
28239
- ...setup.externalConfigs
28219
+ ...plan.envFiles,
28220
+ ...plan.secretFiles,
28221
+ ...plan.extraArtifacts,
28222
+ ...plan.externalConfigs
28240
28223
  ]) {
28241
28224
  candidatePaths.add(entry.path);
28242
28225
  }
@@ -28271,27 +28254,18 @@ var init_init = __esm({
28271
28254
  };
28272
28255
  };
28273
28256
  let draftSetup = setupPlan;
28274
- let draftServices = servicesPlan;
28275
28257
  while (true) {
28276
- const nextSetup = skipSetupPlan ? approvedPlan : await promptForPlanApproval({
28258
+ const nextSetup = await promptForPlanApproval({
28277
28259
  plan: setupPlan,
28278
28260
  repoRoot,
28279
28261
  initialPlan: draftSetup
28280
28262
  });
28281
- const nextServices = skipServicesPlan ? approvedServices : await promptForServicesApproval({
28282
- plan: servicesPlan,
28283
- initialPlan: draftServices
28284
- });
28285
- if (!nextSetup) {
28286
- throw new Error("Setup plan missing.");
28287
- }
28288
- if (!nextServices) {
28289
- throw new Error("Services plan missing.");
28290
- }
28291
- const { summary, warning, hasRisk } = await buildApprovalSummary({
28292
- setup: nextSetup,
28293
- services: nextServices
28263
+ const nextServices = await promptForServicesApproval({
28264
+ plan: setupPlan.services,
28265
+ initialSelection: draftSetup?.services ?? null
28294
28266
  });
28267
+ const nextPlan = { ...nextSetup, services: nextServices };
28268
+ const { summary, warning, hasRisk } = await buildApprovalSummary(nextPlan);
28295
28269
  kt2(summary, "Selected setup requirements");
28296
28270
  if (warning) {
28297
28271
  kt2(warning, "Special attention");
@@ -28309,8 +28283,7 @@ var init_init = __esm({
28309
28283
  throwInitCanceled();
28310
28284
  }
28311
28285
  if (decision === "edit") {
28312
- draftSetup = nextSetup;
28313
- draftServices = nextServices;
28286
+ draftSetup = nextPlan;
28314
28287
  continue;
28315
28288
  }
28316
28289
  if (hasRisk) {
@@ -28324,31 +28297,22 @@ var init_init = __esm({
28324
28297
  throwInitCanceled();
28325
28298
  }
28326
28299
  if (!confirmed) {
28327
- draftSetup = nextSetup;
28328
- draftServices = nextServices;
28300
+ draftSetup = nextPlan;
28329
28301
  continue;
28330
28302
  }
28331
28303
  }
28332
- approvedPlan = nextSetup;
28333
- approvedServices = nextServices;
28304
+ approvedPlan = nextPlan;
28334
28305
  break;
28335
28306
  }
28336
28307
  }
28337
28308
  if (!approvedPlan) {
28338
28309
  throw new Error("Setup plan missing.");
28339
28310
  }
28340
- if (!approvedServices) {
28341
- throw new Error("Services plan missing.");
28342
- }
28343
28311
  const ensuredPlan = approvedPlan;
28344
28312
  if (!skipSetupPlan) {
28345
28313
  await writeSetupPlan(setupPath, ensuredPlan);
28346
28314
  await updateInitState({ steps: { setupPlanWritten: true } });
28347
28315
  }
28348
- if (!skipServicesPlan) {
28349
- await writeServicesPlan(servicesPath, approvedServices);
28350
- await updateInitState({ steps: { servicesPlanWritten: true } });
28351
- }
28352
28316
  if (!skipSetupUpload) {
28353
28317
  setupArtifacts = await runInitStep({
28354
28318
  enabled: progressEnabled,
@@ -28365,6 +28329,9 @@ var init_init = __esm({
28365
28329
  } finally {
28366
28330
  await import_promises28.default.rm(setupTempDir, { recursive: true, force: true });
28367
28331
  }
28332
+ if (!approvedPlan) {
28333
+ throw new Error("Setup plan missing.");
28334
+ }
28368
28335
  const skipProvision = shouldResume && initState?.steps.workdirProvisioned;
28369
28336
  if (skipProvision && !skipSetupUpload) {
28370
28337
  await runInitStep({
@@ -28922,9 +28889,6 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
28922
28889
  });
28923
28890
  }
28924
28891
  if (!skipServicesConfig) {
28925
- if (!approvedServices) {
28926
- throw new Error("Missing services plan output.");
28927
- }
28928
28892
  await runInitStep({
28929
28893
  enabled: progressEnabled,
28930
28894
  title: "Writing devbox.toml services",
@@ -28933,7 +28897,7 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
28933
28897
  client,
28934
28898
  canonical,
28935
28899
  workdir: expandedWorkdir,
28936
- services: approvedServices.backgroundServices
28900
+ services: approvedPlan.services.backgroundServices
28937
28901
  });
28938
28902
  await updateInitState({ steps: { servicesConfigWritten: true } });
28939
28903
  }
@@ -29060,7 +29024,7 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
29060
29024
  await enableRemoteServices({
29061
29025
  client,
29062
29026
  canonical,
29063
- services: approvedServices?.backgroundServices ?? [],
29027
+ services: approvedPlan.services.backgroundServices,
29064
29028
  status
29065
29029
  });
29066
29030
  await updateInitState({ steps: { servicesEnabled: true } });
@@ -29081,7 +29045,7 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
29081
29045
  socketInfo,
29082
29046
  status,
29083
29047
  pathSetup,
29084
- entrypoints: approvedServices?.appEntrypoints ?? []
29048
+ entrypoints: approvedPlan.services.appEntrypoints
29085
29049
  });
29086
29050
  }
29087
29051
  });
@@ -1,4 +1,4 @@
1
- import type { ServicesPlan, SetupPlan } from "./plan.js";
1
+ import type { ServicesSelection, SetupPlan } from "./plan.js";
2
2
  declare const runLocalSetupEnvSecretsScan: ({ cwd, logDir, schemaPath, outputPath, onProgress, }: {
3
3
  cwd: string;
4
4
  logDir: string;
@@ -34,9 +34,9 @@ declare const promptForPlanApproval: ({ plan, repoRoot, initialPlan, }: {
34
34
  repoRoot: string;
35
35
  initialPlan?: SetupPlan | null;
36
36
  }) => Promise<SetupPlan>;
37
- declare const promptForServicesApproval: ({ plan, initialPlan, }: {
38
- plan: ServicesPlan;
39
- initialPlan?: ServicesPlan | null;
40
- }) => Promise<ServicesPlan>;
37
+ declare const promptForServicesApproval: ({ plan, initialSelection, }: {
38
+ plan: ServicesSelection;
39
+ initialSelection?: ServicesSelection | null;
40
+ }) => Promise<ServicesSelection>;
41
41
  export { promptForPlanApproval, promptForServicesApproval, runLocalServicesScan, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, };
42
42
  //# sourceMappingURL=local.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/local.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAMV,YAAY,EACZ,SAAS,EACV,MAAM,WAAW,CAAC;AA4HnB,QAAA,MAAM,2BAA2B,GAAU,sDAMxC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAkDA,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAU,+DAOtC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAmDA,CAAC;AAEF,QAAA,MAAM,+BAA+B,GAAU,sDAM5C;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAkDA,CAAC;AAEF,QAAA,MAAM,oBAAoB,GAAU,+DAOjC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAkDA,CAAC;AA2BF,QAAA,MAAM,qBAAqB,GAAU,kCAIlC;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAChC,KAAG,OAAO,CAAC,SAAS,CA6HpB,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAU,wBAGtC;IACD,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC,KAAG,OAAO,CAAC,YAAY,CA2DvB,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,+BAA+B,GAChC,CAAC"}
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/local.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAMV,iBAAiB,EACjB,SAAS,EACV,MAAM,WAAW,CAAC;AA4HnB,QAAA,MAAM,2BAA2B,GAAU,sDAMxC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAkDA,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAU,+DAOtC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAmDA,CAAC;AAEF,QAAA,MAAM,+BAA+B,GAAU,sDAM5C;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAkDA,CAAC;AAEF,QAAA,MAAM,oBAAoB,GAAU,+DAOjC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,kBAmDA,CAAC;AA2BF,QAAA,MAAM,qBAAqB,GAAU,kCAIlC;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAChC,KAAG,OAAO,CAAC,SAAS,CA8HpB,CAAC;AAEF,QAAA,MAAM,yBAAyB,GAAU,6BAGtC;IACD,IAAI,EAAE,iBAAiB,CAAC;IACxB,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C,KAAG,OAAO,CAAC,iBAAiB,CAyD5B,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,+BAA+B,GAChC,CAAC"}
@@ -213,6 +213,7 @@ const runLocalServicesScan = async ({ cwd, logDir, schemaPath, outputPath, homeD
213
213
  const stderrLogPath = path.join(logDir, `codex-local-services-scan-${stamp}.stderr.log`);
214
214
  const metaLogPath = path.join(logDir, `codex-local-services-scan-${stamp}.meta.json`);
215
215
  await fs.mkdir(logDir, { recursive: true, mode: 0o700 });
216
+ await fs.mkdir(path.dirname(outputPath), { recursive: true, mode: 0o700 });
216
217
  try {
217
218
  await fs.chmod(logDir, 0o700);
218
219
  }
@@ -362,9 +363,10 @@ const promptForPlanApproval = async ({ plan, repoRoot, initialPlan, }) => {
362
363
  extraArtifacts: plan.extraArtifacts.filter((entry) => extraArtifactSet.has(entry.path)),
363
364
  externalDependencies: plan.externalDependencies.filter((entry) => externalDependencySet.has(entry.name)),
364
365
  externalConfigs: plan.externalConfigs.filter((entry) => externalConfigSet.has(entry.path)),
366
+ services: initialPlan?.services ?? plan.services,
365
367
  };
366
368
  };
367
- const promptForServicesApproval = async ({ plan, initialPlan, }) => {
369
+ const promptForServicesApproval = async ({ plan, initialSelection, }) => {
368
370
  log.step("Review run services findings");
369
371
  const appEntrypointOptions = plan.appEntrypoints.map((entry) => ({
370
372
  value: entry.command,
@@ -381,7 +383,7 @@ const promptForServicesApproval = async ({ plan, initialPlan, }) => {
381
383
  : await multiselectWithHelp({
382
384
  message: "Select app entrypoints to validate setup",
383
385
  options: appEntrypointOptions,
384
- initialValues: initialPlan?.appEntrypoints.map((entry) => entry.command) ??
386
+ initialValues: initialSelection?.appEntrypoints.map((entry) => entry.command) ??
385
387
  plan.appEntrypoints.map((entry) => entry.command),
386
388
  required: false,
387
389
  });
@@ -394,7 +396,7 @@ const promptForServicesApproval = async ({ plan, initialPlan, }) => {
394
396
  : await multiselectWithHelp({
395
397
  message: "Select background services to run in the devbox",
396
398
  options: backgroundServiceOptions,
397
- initialValues: initialPlan?.backgroundServices.map((entry) => entry.name) ??
399
+ initialValues: initialSelection?.backgroundServices.map((entry) => entry.name) ??
398
400
  plan.backgroundServices.map((entry) => entry.name),
399
401
  required: false,
400
402
  });
@@ -405,8 +407,6 @@ const promptForServicesApproval = async ({ plan, initialPlan, }) => {
405
407
  const appEntrypointSet = new Set(appEntrypointSelection);
406
408
  const backgroundServiceSet = new Set(backgroundServiceSelection);
407
409
  return {
408
- schemaVersion: plan.schemaVersion,
409
- scanFullyCompleted: plan.scanFullyCompleted,
410
410
  appEntrypoints: plan.appEntrypoints.filter((entry) => appEntrypointSet.has(entry.command)),
411
411
  backgroundServices: plan.backgroundServices.filter((entry) => backgroundServiceSet.has(entry.name)),
412
412
  };