@boxes-dev/dvb 1.0.59 → 1.0.61

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 (38) hide show
  1. package/dist/bin/dvb.cjs +712 -246
  2. package/dist/bin/dvb.cjs.map +1 -1
  3. package/dist/bin/dvbd.cjs +5 -5
  4. package/dist/devbox/auth.d.ts +1 -0
  5. package/dist/devbox/auth.d.ts.map +1 -1
  6. package/dist/devbox/auth.js +2 -1
  7. package/dist/devbox/auth.js.map +1 -1
  8. package/dist/devbox/commands/connect.d.ts +2 -0
  9. package/dist/devbox/commands/connect.d.ts.map +1 -1
  10. package/dist/devbox/commands/connect.js +271 -181
  11. package/dist/devbox/commands/connect.js.map +1 -1
  12. package/dist/devbox/commands/init/codex/config.d.ts +6 -0
  13. package/dist/devbox/commands/init/codex/config.d.ts.map +1 -0
  14. package/dist/devbox/commands/init/codex/config.js +43 -0
  15. package/dist/devbox/commands/init/codex/config.js.map +1 -0
  16. package/dist/devbox/commands/init/finalizeFlow.d.ts.map +1 -1
  17. package/dist/devbox/commands/init/finalizeFlow.js +20 -1
  18. package/dist/devbox/commands/init/finalizeFlow.js.map +1 -1
  19. package/dist/devbox/commands/init/remote.d.ts +6 -1
  20. package/dist/devbox/commands/init/remote.d.ts.map +1 -1
  21. package/dist/devbox/commands/init/remote.js +30 -1
  22. package/dist/devbox/commands/init/remote.js.map +1 -1
  23. package/dist/devbox/commands/init/state.d.ts +2 -1
  24. package/dist/devbox/commands/init/state.d.ts.map +1 -1
  25. package/dist/devbox/commands/init/state.js +1 -0
  26. package/dist/devbox/commands/init/state.js.map +1 -1
  27. package/dist/devbox/commands/list.d.ts +18 -0
  28. package/dist/devbox/commands/list.d.ts.map +1 -1
  29. package/dist/devbox/commands/list.js +26 -7
  30. package/dist/devbox/commands/list.js.map +1 -1
  31. package/dist/devbox/commands/setup.d.ts.map +1 -1
  32. package/dist/devbox/commands/setup.js +11 -2
  33. package/dist/devbox/commands/setup.js.map +1 -1
  34. package/dist/devbox/controlPlane.d.ts.map +1 -1
  35. package/dist/devbox/controlPlane.js +125 -24
  36. package/dist/devbox/controlPlane.js.map +1 -1
  37. package/dist/prompts/remote-apply.md +8 -0
  38. package/package.json +1 -1
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]="2abd239d-3084-5a69-b772-ab46c3dbd477")}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]="b4643c26-df5e-5ece-b58a-108a9965ffde")}catch(e){}}();
4
4
 
5
5
  var __create = Object.create;
6
6
  var __defProp = Object.defineProperty;
@@ -88683,8 +88683,8 @@ var init_otel = __esm({
88683
88683
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
88684
88684
  };
88685
88685
  readBuildMetadata = () => {
88686
- const rawPackageVersion = "1.0.59";
88687
- const rawGitSha = "9310fc020995a5ac4c4f9ee04ca291a3799a24c1";
88686
+ const rawPackageVersion = "1.0.61";
88687
+ const rawGitSha = "ef3417e1e95b9ccc6114ef7c44fa645a1704b688";
88688
88688
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
88689
88689
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
88690
88690
  return { packageVersion, gitSha };
@@ -120672,9 +120672,9 @@ var init_sentry = __esm({
120672
120672
  sentryEnabled = false;
120673
120673
  uncaughtExceptionMonitorInstalled = false;
120674
120674
  readBuildMetadata2 = () => {
120675
- const rawPackageVersion = "1.0.59";
120676
- const rawGitSha = "9310fc020995a5ac4c4f9ee04ca291a3799a24c1";
120677
- const rawSentryRelease = "boxes-dev-dvb@1.0.59+9310fc020995a5ac4c4f9ee04ca291a3799a24c1";
120675
+ const rawPackageVersion = "1.0.61";
120676
+ const rawGitSha = "ef3417e1e95b9ccc6114ef7c44fa645a1704b688";
120677
+ const rawSentryRelease = "boxes-dev-dvb@1.0.61+ef3417e1e95b9ccc6114ef7c44fa645a1704b688";
120678
120678
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
120679
120679
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
120680
120680
  const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
@@ -129291,8 +129291,148 @@ var init_parse = __esm({
129291
129291
  });
129292
129292
 
129293
129293
  // ../../node_modules/smol-toml/dist/stringify.js
129294
+ function extendedTypeOf(obj) {
129295
+ let type = typeof obj;
129296
+ if (type === "object") {
129297
+ if (Array.isArray(obj))
129298
+ return "array";
129299
+ if (obj instanceof Date)
129300
+ return "date";
129301
+ }
129302
+ return type;
129303
+ }
129304
+ function isArrayOfTables(obj) {
129305
+ for (let i2 = 0; i2 < obj.length; i2++) {
129306
+ if (extendedTypeOf(obj[i2]) !== "object")
129307
+ return false;
129308
+ }
129309
+ return obj.length != 0;
129310
+ }
129311
+ function formatString(s2) {
129312
+ return JSON.stringify(s2).replace(/\x7f/g, "\\u007f");
129313
+ }
129314
+ function stringifyValue2(val, type, depth, numberAsFloat) {
129315
+ if (depth === 0) {
129316
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
129317
+ }
129318
+ if (type === "number") {
129319
+ if (isNaN(val))
129320
+ return "nan";
129321
+ if (val === Infinity)
129322
+ return "inf";
129323
+ if (val === -Infinity)
129324
+ return "-inf";
129325
+ if (numberAsFloat && Number.isInteger(val))
129326
+ return val.toFixed(1);
129327
+ return val.toString();
129328
+ }
129329
+ if (type === "bigint" || type === "boolean") {
129330
+ return val.toString();
129331
+ }
129332
+ if (type === "string") {
129333
+ return formatString(val);
129334
+ }
129335
+ if (type === "date") {
129336
+ if (isNaN(val.getTime())) {
129337
+ throw new TypeError("cannot serialize invalid date");
129338
+ }
129339
+ return val.toISOString();
129340
+ }
129341
+ if (type === "object") {
129342
+ return stringifyInlineTable(val, depth, numberAsFloat);
129343
+ }
129344
+ if (type === "array") {
129345
+ return stringifyArray(val, depth, numberAsFloat);
129346
+ }
129347
+ }
129348
+ function stringifyInlineTable(obj, depth, numberAsFloat) {
129349
+ let keys = Object.keys(obj);
129350
+ if (keys.length === 0)
129351
+ return "{}";
129352
+ let res = "{ ";
129353
+ for (let i2 = 0; i2 < keys.length; i2++) {
129354
+ let k3 = keys[i2];
129355
+ if (i2)
129356
+ res += ", ";
129357
+ res += BARE_KEY.test(k3) ? k3 : formatString(k3);
129358
+ res += " = ";
129359
+ res += stringifyValue2(obj[k3], extendedTypeOf(obj[k3]), depth - 1, numberAsFloat);
129360
+ }
129361
+ return res + " }";
129362
+ }
129363
+ function stringifyArray(array, depth, numberAsFloat) {
129364
+ if (array.length === 0)
129365
+ return "[]";
129366
+ let res = "[ ";
129367
+ for (let i2 = 0; i2 < array.length; i2++) {
129368
+ if (i2)
129369
+ res += ", ";
129370
+ if (array[i2] === null || array[i2] === void 0) {
129371
+ throw new TypeError("arrays cannot contain null or undefined values");
129372
+ }
129373
+ res += stringifyValue2(array[i2], extendedTypeOf(array[i2]), depth - 1, numberAsFloat);
129374
+ }
129375
+ return res + " ]";
129376
+ }
129377
+ function stringifyArrayTable(array, key, depth, numberAsFloat) {
129378
+ if (depth === 0) {
129379
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
129380
+ }
129381
+ let res = "";
129382
+ for (let i2 = 0; i2 < array.length; i2++) {
129383
+ res += `${res && "\n"}[[${key}]]
129384
+ `;
129385
+ res += stringifyTable(0, array[i2], key, depth, numberAsFloat);
129386
+ }
129387
+ return res;
129388
+ }
129389
+ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
129390
+ if (depth === 0) {
129391
+ throw new Error("Could not stringify the object: maximum object depth exceeded");
129392
+ }
129393
+ let preamble = "";
129394
+ let tables = "";
129395
+ let keys = Object.keys(obj);
129396
+ for (let i2 = 0; i2 < keys.length; i2++) {
129397
+ let k3 = keys[i2];
129398
+ if (obj[k3] !== null && obj[k3] !== void 0) {
129399
+ let type = extendedTypeOf(obj[k3]);
129400
+ if (type === "symbol" || type === "function") {
129401
+ throw new TypeError(`cannot serialize values of type '${type}'`);
129402
+ }
129403
+ let key = BARE_KEY.test(k3) ? k3 : formatString(k3);
129404
+ if (type === "array" && isArrayOfTables(obj[k3])) {
129405
+ tables += (tables && "\n") + stringifyArrayTable(obj[k3], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
129406
+ } else if (type === "object") {
129407
+ let tblKey = prefix ? `${prefix}.${key}` : key;
129408
+ tables += (tables && "\n") + stringifyTable(tblKey, obj[k3], tblKey, depth - 1, numberAsFloat);
129409
+ } else {
129410
+ preamble += key;
129411
+ preamble += " = ";
129412
+ preamble += stringifyValue2(obj[k3], type, depth, numberAsFloat);
129413
+ preamble += "\n";
129414
+ }
129415
+ }
129416
+ }
129417
+ if (tableKey && (preamble || !tables))
129418
+ preamble = preamble ? `[${tableKey}]
129419
+ ${preamble}` : `[${tableKey}]`;
129420
+ return preamble && tables ? `${preamble}
129421
+ ${tables}` : preamble || tables;
129422
+ }
129423
+ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
129424
+ if (extendedTypeOf(obj) !== "object") {
129425
+ throw new TypeError("stringify can only be called with an object");
129426
+ }
129427
+ let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat);
129428
+ if (str[str.length - 1] !== "\n")
129429
+ return str + "\n";
129430
+ return str;
129431
+ }
129432
+ var BARE_KEY;
129294
129433
  var init_stringify2 = __esm({
129295
129434
  "../../node_modules/smol-toml/dist/stringify.js"() {
129435
+ BARE_KEY = /^[a-z0-9-_]+$/i;
129296
129436
  }
129297
129437
  });
129298
129438
 
@@ -189911,21 +190051,8 @@ var init_logger3 = __esm({
189911
190051
  }
189912
190052
  });
189913
190053
 
189914
- // src/devbox/ui/copyableUrl.ts
189915
- var showCopyableUrl;
189916
- var init_copyableUrl = __esm({
189917
- "src/devbox/ui/copyableUrl.ts"() {
189918
- "use strict";
189919
- init_dist5();
189920
- showCopyableUrl = (url, label) => {
189921
- R2.info(`${label}:`);
189922
- R2.message(url, { withGuide: false, spacing: 0 });
189923
- };
189924
- }
189925
- });
189926
-
189927
190054
  // src/devbox/controlPlane.ts
189928
- var import_node_http2, import_node_crypto6, import_node_child_process2, resolveControlPlaneUrl2, resolveConvexUrl2, openBrowser, escapeHtml, CALLBACK_LOGO_MARK, CALLBACK_FULL_LOGO, renderCallbackPage, requestJson2, startCallbackServer, getControlPlaneUrl, getConvexUrl, signInWithBrowser, spriteTokenGet, spriteTokenSet, spriteTokenClear, modalTokenGet, modalTokenSet, modalTokenClear, modalTokenResolvedGet2, modalDevboxUpsert, modalDevboxRemove, modalDevboxEnsureActive2, modalDevboxShellConnectionOpened, modalDevboxShellConnectionClosed, modalDevboxProxyConnectionOpened2, modalDevboxProxyConnectionClosed2, modalDevboxStatusesList, spriteDaemonReleaseGet, spriteDaemonTokenIssue, spriteDaemonSessionSummariesList, spriteDaemonSessionsList, helloViewerGet, withConvexClient, fetchSpriteTokenStatus, fetchResolvedModalCredentials2, fetchViewerIdentity, storeSpriteToken, clearSpriteToken, storeModalCredentials, clearModalCredentials, upsertModalDevboxLifecycle, ensureModalDevboxActive2, fetchSpriteDaemonRelease, issueSpriteDaemonToken, listSpriteDaemonSessionSummaries, listSpriteDaemonSessions, signOutControlPlane, refreshControlPlaneSession;
190055
+ var import_node_http2, import_node_crypto6, import_node_child_process2, resolveControlPlaneUrl2, resolveConvexUrl2, openBrowser, waitForAnyKeypress, escapeHtml, CALLBACK_LOGO_MARK, CALLBACK_FULL_LOGO, renderCallbackPage, requestJson2, startCallbackServer, getControlPlaneUrl, getConvexUrl, signInWithBrowser, spriteTokenGet, spriteTokenSet, spriteTokenClear, modalTokenGet, modalTokenSet, modalTokenClear, modalTokenResolvedGet2, modalDevboxUpsert, modalDevboxRemove, modalDevboxEnsureActive2, modalDevboxShellConnectionOpened, modalDevboxShellConnectionClosed, modalDevboxProxyConnectionOpened2, modalDevboxProxyConnectionClosed2, modalDevboxStatusesList, spriteDaemonReleaseGet, spriteDaemonTokenIssue, spriteDaemonSessionSummariesList, spriteDaemonSessionsList, helloViewerGet, withConvexClient, fetchSpriteTokenStatus, fetchResolvedModalCredentials2, fetchViewerIdentity, storeSpriteToken, clearSpriteToken, storeModalCredentials, clearModalCredentials, upsertModalDevboxLifecycle, ensureModalDevboxActive2, fetchSpriteDaemonRelease, issueSpriteDaemonToken, listSpriteDaemonSessionSummaries, listSpriteDaemonSessions, signOutControlPlane, refreshControlPlaneSession;
189929
190056
  var init_controlPlane = __esm({
189930
190057
  "src/devbox/controlPlane.ts"() {
189931
190058
  "use strict";
@@ -189936,7 +190063,6 @@ var init_controlPlane = __esm({
189936
190063
  init_index_node();
189937
190064
  init_server();
189938
190065
  init_logger3();
189939
- init_copyableUrl();
189940
190066
  resolveControlPlaneUrl2 = () => {
189941
190067
  const envOverride = process.env.DEVBOX_CONTROL_PLANE_URL ?? process.env.CONVEX_SITE_URL;
189942
190068
  if (envOverride && envOverride.trim().length > 0) {
@@ -189980,6 +190106,70 @@ var init_controlPlane = __esm({
189980
190106
  return false;
189981
190107
  }
189982
190108
  };
190109
+ waitForAnyKeypress = () => {
190110
+ const stdin = process.stdin;
190111
+ const wasPaused = stdin.isPaused();
190112
+ let stopRawMode = null;
190113
+ let stopped = false;
190114
+ let resolvePromise = null;
190115
+ let rejectPromise = null;
190116
+ const stop = () => {
190117
+ if (stopped) return;
190118
+ stopped = true;
190119
+ stdin.off("data", onData);
190120
+ stdin.off("error", onError);
190121
+ stopRawMode?.();
190122
+ if (wasPaused) {
190123
+ stdin.pause();
190124
+ }
190125
+ };
190126
+ const settle = (value) => {
190127
+ if (stopped) return;
190128
+ const resolve2 = resolvePromise;
190129
+ stop();
190130
+ resolve2?.(value);
190131
+ };
190132
+ const reject = (error2) => {
190133
+ if (stopped) return;
190134
+ const rejectFn = rejectPromise;
190135
+ stop();
190136
+ rejectFn?.(error2);
190137
+ };
190138
+ const onData = (chunk) => {
190139
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
190140
+ if (buffer.includes(3)) {
190141
+ settle("cancel");
190142
+ return;
190143
+ }
190144
+ settle("open_browser");
190145
+ };
190146
+ const onError = (error2) => {
190147
+ reject(error2);
190148
+ };
190149
+ const promise = new Promise((resolve2, reject2) => {
190150
+ resolvePromise = resolve2;
190151
+ rejectPromise = reject2;
190152
+ });
190153
+ if (stdin.isTTY) {
190154
+ const wasRaw = stdin.isRaw;
190155
+ if (wasRaw !== true) {
190156
+ try {
190157
+ stdin.setRawMode(true);
190158
+ stopRawMode = () => {
190159
+ try {
190160
+ stdin.setRawMode(false);
190161
+ } catch {
190162
+ }
190163
+ };
190164
+ } catch {
190165
+ }
190166
+ }
190167
+ }
190168
+ stdin.resume();
190169
+ stdin.on("data", onData);
190170
+ stdin.on("error", onError);
190171
+ return { promise, stop };
190172
+ };
189983
190173
  escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
189984
190174
  CALLBACK_LOGO_MARK = `<svg viewBox="0 0 48 48" aria-hidden="true" focusable="false">
189985
190175
  <rect x="1.5" y="1.5" width="45" height="45" rx="8" fill="#111" />
@@ -190246,34 +190436,50 @@ var init_controlPlane = __esm({
190246
190436
  if (!start.redirect || !start.verifier) {
190247
190437
  throw new Error("Control plane sign-in failed to start.");
190248
190438
  }
190249
- showCopyableUrl(start.redirect, "Login URL");
190250
- const action = await qt({
190251
- message: "Open the login URL in your browser?",
190252
- options: [
190253
- { value: "open", label: "Open in browser" },
190254
- { value: "skip", label: "Skip" }
190255
- ],
190256
- initialValue: "open"
190257
- });
190258
- if (Ct(action)) {
190259
- Pt("Sign-in canceled.");
190260
- throw new Error("Control plane sign-in cancelled.");
190261
- }
190262
- if (action === "open") {
190263
- const opened = openBrowser(start.redirect);
190264
- if (!opened) {
190265
- R2.warn("Unable to open the browser automatically.");
190266
- R2.info("Open the URL above to continue login.");
190267
- }
190268
- } else {
190269
- R2.warn(
190270
- "Skipping browser open. Open the URL above to continue login."
190439
+ R2.info("Sign in to boxes.dev to continue. Log in here:");
190440
+ R2.message(start.redirect, { withGuide: false, spacing: 0 });
190441
+ const codePromise = callback.waitForCode();
190442
+ const keypress = waitForAnyKeypress();
190443
+ const listeningSpinner = Ie();
190444
+ let code2 = "";
190445
+ try {
190446
+ listeningSpinner.start(
190447
+ "Listening for login. Press any key to open in your browser..."
190271
190448
  );
190449
+ const firstResult = await Promise.race([
190450
+ codePromise.then((value) => ({ type: "code", value })),
190451
+ keypress.promise.then((value) => ({
190452
+ type: "keypress",
190453
+ value
190454
+ }))
190455
+ ]);
190456
+ listeningSpinner.clear();
190457
+ if (firstResult.type === "code") {
190458
+ code2 = firstResult.value;
190459
+ } else {
190460
+ if (firstResult.value === "cancel") {
190461
+ Pt("Sign-in canceled.");
190462
+ throw new Error("Control plane sign-in cancelled.");
190463
+ }
190464
+ const opened = openBrowser(start.redirect);
190465
+ if (!opened) {
190466
+ R2.warn("Unable to open the browser automatically.");
190467
+ R2.info("Open the URL above to continue login.");
190468
+ }
190469
+ const waitSpinner = Ie();
190470
+ waitSpinner.start(
190471
+ "Listening for login. Complete sign-in in your browser..."
190472
+ );
190473
+ try {
190474
+ code2 = await codePromise;
190475
+ } finally {
190476
+ waitSpinner.clear();
190477
+ }
190478
+ }
190479
+ } finally {
190480
+ listeningSpinner.clear();
190481
+ keypress.stop();
190272
190482
  }
190273
- R2.step(
190274
- "Waiting for browser login. Complete sign-in in your browser."
190275
- );
190276
- const code2 = await callback.waitForCode();
190277
190483
  const finish = await requestJson2(
190278
190484
  baseUrl,
190279
190485
  "POST",
@@ -190286,6 +190492,18 @@ var init_controlPlane = __esm({
190286
190492
  if (!finish.token) {
190287
190493
  throw new Error("Control plane sign-in failed to complete.");
190288
190494
  }
190495
+ const viewer = await fetchViewerIdentity(finish.token).catch((error2) => {
190496
+ logger7.warn("control_plane_viewer_identity_failed", {
190497
+ error: error2 instanceof Error ? error2.message : String(error2)
190498
+ });
190499
+ return null;
190500
+ });
190501
+ const email = typeof viewer?.email === "string" ? viewer.email.trim() : "";
190502
+ if (email.length > 0) {
190503
+ R2.success(`Signed in as ${email}.`);
190504
+ } else {
190505
+ R2.success("Signed in.");
190506
+ }
190289
190507
  return finish.refresh_token ? { token: finish.token, refreshToken: finish.refresh_token } : { token: finish.token };
190290
190508
  } finally {
190291
190509
  await callback.close();
@@ -190966,13 +191184,14 @@ var init_daemonClient = __esm({
190966
191184
  });
190967
191185
 
190968
191186
  // src/devbox/auth.ts
190969
- var TOKEN_REFRESH_BUFFER_MS2, decodeJwtPayload4, parseTokenExpiresAt2, shouldRefreshToken2, isUnauthorizedError2, clearControlPlaneSession2, updateControlPlaneSession, refreshControlPlaneToken, ensureControlPlaneToken, ensureSpritesToken;
191187
+ var CONTROL_PLANE_INTERACTIVE_SIGNIN_STAGE, TOKEN_REFRESH_BUFFER_MS2, decodeJwtPayload4, parseTokenExpiresAt2, shouldRefreshToken2, isUnauthorizedError2, clearControlPlaneSession2, updateControlPlaneSession, refreshControlPlaneToken, ensureControlPlaneToken, ensureSpritesToken;
190970
191188
  var init_auth = __esm({
190971
191189
  "src/devbox/auth.ts"() {
190972
191190
  "use strict";
190973
191191
  init_src();
190974
191192
  init_logger3();
190975
191193
  init_controlPlane();
191194
+ CONTROL_PLANE_INTERACTIVE_SIGNIN_STAGE = "Opening browser to sign in";
190976
191195
  TOKEN_REFRESH_BUFFER_MS2 = 5 * 60 * 1e3;
190977
191196
  decodeJwtPayload4 = (token) => {
190978
191197
  const parts = token.split(".");
@@ -191070,7 +191289,7 @@ var init_auth = __esm({
191070
191289
  if (!process.stdin.isTTY) {
191071
191290
  return null;
191072
191291
  }
191073
- stage?.("Opening browser to sign in");
191292
+ stage?.(CONTROL_PLANE_INTERACTIVE_SIGNIN_STAGE);
191074
191293
  const tokens = await signInWithBrowser();
191075
191294
  await updateControlPlaneSession(store, tokens.token, tokens.refreshToken);
191076
191295
  logger7.info("control_plane_signed_in");
@@ -199212,7 +199431,7 @@ var init_sessionUtils = __esm({
199212
199431
  });
199213
199432
 
199214
199433
  // src/devbox/commands/connect.ts
199215
- var import_node_child_process4, import_node_crypto9, import_node_os10, import_node_path17, import_node_readline3, import_promises13, resolveInitialSessionId, shouldAttachToExistingSession, resolveSessionSpecifierFromExplicitTarget, isAttachReplacedCloseCode, DEFAULT_TTY_COLS, DEFAULT_TTY_ROWS, DEFAULT_MODAL_APP_NAME, TERMINAL_INPUT_MODE_RESET, resetTerminalInputModes, openBrowser2, warnSetupStatus, resolveTtyEnv, formatEnvExports, parseEnvSize, readStreamSize, resolveTtySize, resolveSessionEnv, parseReachabilityState, runCommand, checkReachability, watchReachabilityWithScutil, watchReachabilityWithNotifyutil, waitForNetworkOnline, parseConnectArgs, parseConnectTarget, isSessionNotFoundError, SESSION_NAME_TOKEN_KEY, encodeSessionNameToken, decodeSessionNameToken, extractSessionNameFromCommand, SESSION_LOG_FLUSH_BYTES, SESSION_LOG_EOF_MARKER, createRemoteSessionLogSink, CONNECT_SHELL_CANDIDATES, resolveConnectShell, confirmNewSession, promptRenameSession, HEARTBEAT_INTERVAL_MS, HEARTBEAT_TIMEOUT_MS, INPUT_PROBE_TIMEOUT_MS, WS_OPEN_STATE, streamExecSession, runConnect;
199434
+ var import_node_child_process4, import_node_crypto9, import_node_os10, import_node_path17, import_node_readline3, import_promises13, resolveInitialSessionId, shouldAttachToExistingSession, resolveSessionSpecifierFromExplicitTarget, isAttachReplacedCloseCode, shouldCancelConnectOnSigint, DEFAULT_TTY_COLS, DEFAULT_TTY_ROWS, DEFAULT_MODAL_APP_NAME, TERMINAL_INPUT_MODE_RESET, resetTerminalInputModes, openBrowser2, warnSetupStatus, resolveTtyEnv, formatEnvExports, parseEnvSize, readStreamSize, resolveTtySize, resolveSessionEnv, parseReachabilityState, runCommand, checkReachability, watchReachabilityWithScutil, watchReachabilityWithNotifyutil, waitForNetworkOnline, parseConnectArgs, parseConnectTarget, isSessionNotFoundError, SESSION_NAME_TOKEN_KEY, encodeSessionNameToken, decodeSessionNameToken, extractSessionNameFromCommand, SESSION_LOG_FLUSH_BYTES, SESSION_LOG_EOF_MARKER, createRemoteSessionLogSink, CONNECT_SHELL_CANDIDATES, resolveConnectShell, confirmNewSession, promptRenameSession, HEARTBEAT_INTERVAL_MS, HEARTBEAT_TIMEOUT_MS, INPUT_PROBE_TIMEOUT_MS, CONNECT_OPEN_TIMEOUT_MS, WS_OPEN_STATE, streamExecSession, runConnect;
199216
199435
  var init_connect2 = __esm({
199217
199436
  "src/devbox/commands/connect.ts"() {
199218
199437
  "use strict";
@@ -199270,6 +199489,7 @@ var init_connect2 = __esm({
199270
199489
  return { sessionName: void 0, sessionIdOverride: match2.id };
199271
199490
  };
199272
199491
  isAttachReplacedCloseCode = (closeCode) => closeCode === 1012;
199492
+ shouldCancelConnectOnSigint = (phase) => phase !== "attached";
199273
199493
  DEFAULT_TTY_COLS = 80;
199274
199494
  DEFAULT_TTY_ROWS = 24;
199275
199495
  DEFAULT_MODAL_APP_NAME = "sandbox-modal-smoke";
@@ -199755,6 +199975,7 @@ var init_connect2 = __esm({
199755
199975
  HEARTBEAT_INTERVAL_MS = 4e3;
199756
199976
  HEARTBEAT_TIMEOUT_MS = 8e3;
199757
199977
  INPUT_PROBE_TIMEOUT_MS = 1e3;
199978
+ CONNECT_OPEN_TIMEOUT_MS = 2e4;
199758
199979
  WS_OPEN_STATE = 1;
199759
199980
  streamExecSession = async (ws, options) => new Promise((resolve2, reject) => {
199760
199981
  let exitCode = null;
@@ -199767,6 +199988,7 @@ var init_connect2 = __esm({
199767
199988
  let lastSeenAt = Date.now();
199768
199989
  let heartbeatTimer = null;
199769
199990
  let inputProbeTimer = null;
199991
+ let openTimer = null;
199770
199992
  let inputProbeStamp = 0;
199771
199993
  let disconnectNoted = false;
199772
199994
  let errorMessage;
@@ -199994,6 +200216,12 @@ var init_connect2 = __esm({
199994
200216
  inputProbeTimer = null;
199995
200217
  }
199996
200218
  };
200219
+ const stopOpenTimer = () => {
200220
+ if (openTimer) {
200221
+ clearTimeout(openTimer);
200222
+ openTimer = null;
200223
+ }
200224
+ };
199997
200225
  const onPong = () => {
199998
200226
  markAlive();
199999
200227
  latency?.notePong();
@@ -200088,6 +200316,7 @@ var init_connect2 = __esm({
200088
200316
  ws.removeEventListener("error", onError);
200089
200317
  ws.removeEventListener("open", onOpen);
200090
200318
  stopInputProbe();
200319
+ stopOpenTimer();
200091
200320
  stopHeartbeat();
200092
200321
  stopInput();
200093
200322
  };
@@ -200131,6 +200360,7 @@ var init_connect2 = __esm({
200131
200360
  resolve2(result);
200132
200361
  };
200133
200362
  const onOpen = () => {
200363
+ stopOpenTimer();
200134
200364
  opened = true;
200135
200365
  markAlive();
200136
200366
  latency?.noteConnectOpen();
@@ -200145,6 +200375,20 @@ var init_connect2 = __esm({
200145
200375
  ws.addEventListener("error", onError);
200146
200376
  ws.addEventListener("open", onOpen);
200147
200377
  sendResize();
200378
+ const openTimeoutMs = options.openTimeoutMs ?? CONNECT_OPEN_TIMEOUT_MS;
200379
+ if (openTimeoutMs > 0) {
200380
+ openTimer = setTimeout(() => {
200381
+ if (resolved || opened) return;
200382
+ noteDisconnect();
200383
+ forceClose();
200384
+ onError({
200385
+ data: new Error(
200386
+ `Timed out waiting for session connection after ${openTimeoutMs}ms.`
200387
+ )
200388
+ });
200389
+ }, openTimeoutMs);
200390
+ openTimer.unref();
200391
+ }
200148
200392
  });
200149
200393
  runConnect = async (args, overrides) => {
200150
200394
  const parsed = parseConnectArgs(args);
@@ -200690,6 +200934,11 @@ var init_connect2 = __esm({
200690
200934
  let retryDelayMs = 250;
200691
200935
  let printedSessionInfo = false;
200692
200936
  let sawOutput = false;
200937
+ let connectPhase = "connecting";
200938
+ let activeSocket = null;
200939
+ let localCancelRequested = false;
200940
+ let attemptedAttach = false;
200941
+ let sigintListenerInstalled = false;
200693
200942
  const printSessionInfo = (message) => {
200694
200943
  if (process.stderr.isTTY && process.stdout.isTTY) {
200695
200944
  process.stderr.write(`\x1B7\r
@@ -200717,208 +200966,262 @@ ${message}\r
200717
200966
  status.stop();
200718
200967
  }
200719
200968
  };
200720
- while (true) {
200969
+ const onSigint = () => {
200970
+ localCancelRequested = true;
200971
+ if (!activeSocket) return;
200721
200972
  try {
200722
- await refreshSessionMapping();
200723
- } catch (error2) {
200724
- logger7.warn("session_refresh_failed", { error: String(error2) });
200725
- }
200726
- if (explicitName && sessionName && !sessionId && !confirmedCreateExplicit) {
200727
- pauseStatus();
200728
- const confirmed = await confirmNewSession(sessionName);
200729
- if (!confirmed) {
200730
- throw new Error(`Session "${sessionName}" not created.`);
200731
- }
200732
- confirmedCreateExplicit = true;
200733
- }
200734
- let createdNew = false;
200735
- let mappingWrite = null;
200736
- latency?.noteConnectStart();
200737
- const canAttach = shouldAttachToExistingSession({
200738
- supportsAttachExecSession,
200739
- sessionId,
200740
- requireFreshSessionOpen
200741
- });
200742
- stage(canAttach ? "Attaching to session" : "Opening session");
200743
- let ws;
200744
- if (canAttach) {
200745
- if (!sessionId) {
200746
- throw new Error("Missing session id for attach.");
200747
- }
200748
- ws = client2.attachExecSession(spriteAlias, sessionId);
200749
- } else {
200750
- createdNew = true;
200751
- ws = client2.openExecSession(spriteAlias, {
200752
- cmd: execCommand2,
200753
- tty: isTty,
200754
- stdin: openStdin,
200755
- ...ttySize ? { cols: ttySize.cols, rows: ttySize.rows } : {},
200756
- ...modalSessionLogPath ? { logPath: modalSessionLogPath } : {}
200757
- });
200973
+ activeSocket.terminate?.();
200974
+ } catch {
200758
200975
  }
200759
- const shouldSendInitialInput = createdNew && Boolean(pendingInitialInput);
200760
- const initialInputToSend = shouldSendInitialInput ? pendingInitialInput : void 0;
200761
- const result = await streamExecSession(ws, {
200762
- tty: isTty,
200763
- stdin: localStdin,
200764
- supportsResizeControlMessages,
200765
- ...latency ? { latency } : {},
200766
- onOutput: noteOutput,
200767
- onOutputChunk: (chunk) => {
200768
- sessionLogSink?.write(chunk);
200769
- },
200770
- onInputChunk: (chunk) => {
200771
- sessionLogSink?.write(chunk);
200772
- },
200773
- onOpen: () => {
200774
- if (shouldSendInitialInput) {
200775
- pendingInitialInput = void 0;
200776
- }
200777
- if (sessionId) {
200778
- reportSessionInfo(sessionId);
200976
+ try {
200977
+ activeSocket.close();
200978
+ } catch {
200979
+ }
200980
+ };
200981
+ const setConnectPhase = (phase) => {
200982
+ connectPhase = phase;
200983
+ const shouldInstallListener = shouldReconnect && shouldCancelConnectOnSigint(connectPhase);
200984
+ if (shouldInstallListener && !sigintListenerInstalled) {
200985
+ process.on("SIGINT", onSigint);
200986
+ sigintListenerInstalled = true;
200987
+ return;
200988
+ }
200989
+ if (!shouldInstallListener && sigintListenerInstalled) {
200990
+ process.removeListener("SIGINT", onSigint);
200991
+ sigintListenerInstalled = false;
200992
+ }
200993
+ };
200994
+ setConnectPhase("connecting");
200995
+ try {
200996
+ while (true) {
200997
+ if (localCancelRequested) {
200998
+ process.exitCode = 130;
200999
+ break;
201000
+ }
201001
+ setConnectPhase(attemptedAttach ? "reconnecting" : "connecting");
201002
+ attemptedAttach = true;
201003
+ try {
201004
+ await refreshSessionMapping();
201005
+ } catch (error2) {
201006
+ logger7.warn("session_refresh_failed", { error: String(error2) });
201007
+ }
201008
+ if (explicitName && sessionName && !sessionId && !confirmedCreateExplicit) {
201009
+ pauseStatus();
201010
+ const confirmed = await confirmNewSession(sessionName);
201011
+ if (!confirmed) {
201012
+ throw new Error(`Session "${sessionName}" not created.`);
200779
201013
  }
200780
- },
200781
- ...initialInputToSend ? { initialInput: initialInputToSend } : {},
200782
- onSessionInfo: (id) => {
200783
- if (supportsAttachExecSession) {
200784
- if (createdNew) {
200785
- requireFreshSessionOpen = false;
200786
- }
200787
- sessionId = sessionId ?? id;
201014
+ confirmedCreateExplicit = true;
201015
+ }
201016
+ let createdNew = false;
201017
+ let mappingWrite = null;
201018
+ latency?.noteConnectStart();
201019
+ const canAttach = shouldAttachToExistingSession({
201020
+ supportsAttachExecSession,
201021
+ sessionId,
201022
+ requireFreshSessionOpen
201023
+ });
201024
+ stage(canAttach ? "Attaching to session" : "Opening session");
201025
+ let ws;
201026
+ if (canAttach) {
201027
+ if (!sessionId) {
201028
+ throw new Error("Missing session id for attach.");
200788
201029
  }
200789
- if (sessionName && createdNew) {
200790
- if (autoNamed) {
200791
- mappingWrite = finalizeAutoSession(id);
200792
- if (mappingWrite) {
200793
- mappingWrite.then(() => {
200794
- reportSessionInfo(id);
200795
- }).catch((error2) => {
200796
- logger7.warn("session_auto_rename_failed", {
200797
- error: String(error2)
200798
- });
201030
+ ws = client2.attachExecSession(spriteAlias, sessionId);
201031
+ } else {
201032
+ createdNew = true;
201033
+ ws = client2.openExecSession(spriteAlias, {
201034
+ cmd: execCommand2,
201035
+ tty: isTty,
201036
+ stdin: openStdin,
201037
+ ...ttySize ? { cols: ttySize.cols, rows: ttySize.rows } : {},
201038
+ ...modalSessionLogPath ? { logPath: modalSessionLogPath } : {}
201039
+ });
201040
+ }
201041
+ activeSocket = ws;
201042
+ const shouldSendInitialInput = createdNew && Boolean(pendingInitialInput);
201043
+ const initialInputToSend = shouldSendInitialInput ? pendingInitialInput : void 0;
201044
+ let result;
201045
+ try {
201046
+ result = await streamExecSession(ws, {
201047
+ tty: isTty,
201048
+ stdin: localStdin,
201049
+ supportsResizeControlMessages,
201050
+ ...latency ? { latency } : {},
201051
+ openTimeoutMs: CONNECT_OPEN_TIMEOUT_MS,
201052
+ onOutput: noteOutput,
201053
+ onOutputChunk: (chunk) => {
201054
+ sessionLogSink?.write(chunk);
201055
+ },
201056
+ onInputChunk: (chunk) => {
201057
+ sessionLogSink?.write(chunk);
201058
+ },
201059
+ onOpen: () => {
201060
+ setConnectPhase("attached");
201061
+ if (shouldSendInitialInput) {
201062
+ pendingInitialInput = void 0;
201063
+ }
201064
+ if (sessionId) {
201065
+ reportSessionInfo(sessionId);
201066
+ }
201067
+ },
201068
+ ...initialInputToSend ? { initialInput: initialInputToSend } : {},
201069
+ onSessionInfo: (id) => {
201070
+ if (supportsAttachExecSession) {
201071
+ if (createdNew) {
201072
+ requireFreshSessionOpen = false;
201073
+ }
201074
+ sessionId = sessionId ?? id;
201075
+ }
201076
+ if (sessionName && createdNew) {
201077
+ if (autoNamed) {
201078
+ mappingWrite = finalizeAutoSession(id);
201079
+ if (mappingWrite) {
201080
+ mappingWrite.then(() => {
201081
+ reportSessionInfo(id);
201082
+ }).catch((error2) => {
201083
+ logger7.warn("session_auto_rename_failed", {
201084
+ error: String(error2)
201085
+ });
201086
+ reportSessionInfo(id);
201087
+ });
201088
+ } else {
201089
+ reportSessionInfo(id);
201090
+ }
201091
+ } else {
201092
+ sessions[sessionName] = id;
201093
+ mappingWrite = writeSpriteSessions(
201094
+ client2,
201095
+ spriteAlias,
201096
+ sessions
201097
+ );
200799
201098
  reportSessionInfo(id);
200800
- });
201099
+ }
200801
201100
  } else {
200802
201101
  reportSessionInfo(id);
200803
201102
  }
200804
- } else {
200805
- sessions[sessionName] = id;
200806
- mappingWrite = writeSpriteSessions(
200807
- client2,
200808
- spriteAlias,
200809
- sessions
200810
- );
200811
- reportSessionInfo(id);
200812
- }
200813
- } else {
200814
- reportSessionInfo(id);
200815
- }
200816
- if (isDetached) {
200817
- ws.close();
201103
+ if (isDetached) {
201104
+ ws.close();
201105
+ }
201106
+ },
201107
+ onPortEvent: notifyPortEvent,
201108
+ ...shouldReconnect ? {
201109
+ onDisconnectNotice: () => {
201110
+ setConnectPhase("reconnecting");
201111
+ resetTerminalInputModes();
201112
+ if (!reconnectNoticeShown) {
201113
+ console.error(
201114
+ "Connection lost. Reconnecting... (Ctrl+C to cancel)"
201115
+ );
201116
+ reconnectNoticeShown = true;
201117
+ }
201118
+ }
201119
+ } : {}
201120
+ });
201121
+ } finally {
201122
+ activeSocket = null;
201123
+ }
201124
+ if (mappingWrite) {
201125
+ try {
201126
+ await mappingWrite;
201127
+ } catch (error2) {
201128
+ logger7.warn("session_write_failed", { error: String(error2) });
200818
201129
  }
200819
- },
200820
- onPortEvent: notifyPortEvent,
200821
- ...shouldReconnect ? {
200822
- onDisconnectNotice: () => {
200823
- resetTerminalInputModes();
200824
- if (!reconnectNoticeShown) {
200825
- console.error(
200826
- "Connection lost. Reconnecting... (Ctrl+C to cancel)"
200827
- );
200828
- reconnectNoticeShown = true;
201130
+ }
201131
+ if (localCancelRequested) {
201132
+ process.exitCode = 130;
201133
+ break;
201134
+ }
201135
+ if (result.kind === "exit") {
201136
+ process.exitCode = result.code;
201137
+ break;
201138
+ }
201139
+ if (result.kind === "detach") {
201140
+ if (autoNamed && sessionName && sessionId) {
201141
+ const nextName = await promptRenameSession(sessionName);
201142
+ if (nextName && nextName !== sessionName) {
201143
+ try {
201144
+ await renameSessionMapping(sessionName, nextName, sessionId);
201145
+ } catch (error2) {
201146
+ console.error(
201147
+ `Failed to rename session: ${error2 instanceof Error ? error2.message : String(error2)}`
201148
+ );
201149
+ }
200829
201150
  }
200830
201151
  }
200831
- } : {}
200832
- });
200833
- if (mappingWrite) {
200834
- try {
200835
- await mappingWrite;
200836
- } catch (error2) {
200837
- logger7.warn("session_write_failed", { error: String(error2) });
201152
+ process.exitCode = 0;
201153
+ break;
200838
201154
  }
200839
- }
200840
- if (result.kind === "exit") {
200841
- process.exitCode = result.code;
200842
- break;
200843
- }
200844
- if (result.kind === "detach") {
200845
- if (autoNamed && sessionName && sessionId) {
200846
- const nextName = await promptRenameSession(sessionName);
200847
- if (nextName && nextName !== sessionName) {
200848
- try {
200849
- await renameSessionMapping(sessionName, nextName, sessionId);
200850
- } catch (error2) {
200851
- console.error(
200852
- `Failed to rename session: ${error2 instanceof Error ? error2.message : String(error2)}`
200853
- );
200854
- }
201155
+ if (isDetached) {
201156
+ process.exitCode = 0;
201157
+ break;
201158
+ }
201159
+ if (isAttachReplacedCloseCode(result.closeCode)) {
201160
+ resetTerminalInputModes();
201161
+ console.error(
201162
+ "Session attached from another client. Closing this window."
201163
+ );
201164
+ process.exitCode = 0;
201165
+ break;
201166
+ }
201167
+ if (!shouldReconnect) {
201168
+ if (result.errorMessage) {
201169
+ throw new Error(`Connection lost: ${result.errorMessage}`);
200855
201170
  }
201171
+ throw new Error("Connection lost.");
200856
201172
  }
200857
- process.exitCode = 0;
200858
- break;
200859
- }
200860
- if (isDetached) {
200861
- process.exitCode = 0;
200862
- break;
200863
- }
200864
- if (isAttachReplacedCloseCode(result.closeCode)) {
201173
+ setConnectPhase("reconnecting");
200865
201174
  resetTerminalInputModes();
200866
- console.error(
200867
- "Session attached from another client. Closing this window."
200868
- );
200869
- process.exitCode = 0;
200870
- break;
200871
- }
200872
- if (!shouldReconnect) {
200873
- if (result.errorMessage) {
200874
- throw new Error(`Connection lost: ${result.errorMessage}`);
201175
+ if (!reconnectNoticeShown) {
201176
+ console.error(
201177
+ "Connection lost. Reconnecting... (Ctrl+C to cancel)"
201178
+ );
201179
+ reconnectNoticeShown = true;
200875
201180
  }
200876
- throw new Error("Connection lost.");
200877
- }
200878
- resetTerminalInputModes();
200879
- if (!reconnectNoticeShown) {
200880
- console.error("Connection lost. Reconnecting... (Ctrl+C to cancel)");
200881
- reconnectNoticeShown = true;
200882
- }
200883
- if (sessionId && supportsAttachExecSession) {
200884
- if (computeProvider === "modal" && isSessionNotFoundError(result.errorMessage)) {
200885
- if (sessionName) {
200886
- delete sessions[sessionName];
200887
- await writeSpriteSessions(client2, spriteAlias, sessions);
200888
- }
200889
- sessionId = void 0;
200890
- } else if (computeProvider !== "modal" && result.opened === false && supportsListExecSessions) {
200891
- try {
200892
- const available = await client2.listExecSessions(spriteAlias);
200893
- const match2 = available.find(
200894
- (session) => session.id === sessionId
200895
- );
200896
- if (!match2 || match2.tty === false) {
200897
- if (sessionName) {
200898
- delete sessions[sessionName];
200899
- await writeSpriteSessions(client2, spriteAlias, sessions);
201181
+ if (sessionId && supportsAttachExecSession) {
201182
+ if (computeProvider === "modal" && isSessionNotFoundError(result.errorMessage)) {
201183
+ if (sessionName) {
201184
+ delete sessions[sessionName];
201185
+ await writeSpriteSessions(client2, spriteAlias, sessions);
201186
+ }
201187
+ sessionId = void 0;
201188
+ } else if (computeProvider !== "modal" && result.opened === false && supportsListExecSessions) {
201189
+ try {
201190
+ const available = await client2.listExecSessions(spriteAlias);
201191
+ const match2 = available.find(
201192
+ (session) => session.id === sessionId
201193
+ );
201194
+ if (!match2 || match2.tty === false) {
201195
+ if (sessionName) {
201196
+ delete sessions[sessionName];
201197
+ await writeSpriteSessions(client2, spriteAlias, sessions);
201198
+ }
201199
+ sessionId = void 0;
200900
201200
  }
200901
- sessionId = void 0;
201201
+ } catch (error2) {
201202
+ logger7.warn("session_lookup_failed", { error: String(error2) });
200902
201203
  }
200903
- } catch (error2) {
200904
- logger7.warn("session_lookup_failed", { error: String(error2) });
200905
201204
  }
200906
201205
  }
201206
+ const networkWait = await waitForNetworkOnline({
201207
+ targetHost: networkTargetHost,
201208
+ onStatus: stage,
201209
+ onNotice: (message) => console.error(message)
201210
+ });
201211
+ if (networkWait === "aborted" || localCancelRequested) {
201212
+ process.exitCode = 130;
201213
+ break;
201214
+ }
201215
+ if (networkWait === "waited") {
201216
+ retryDelayMs = 250;
201217
+ }
201218
+ await new Promise((resolve2) => setTimeout(resolve2, retryDelayMs));
201219
+ retryDelayMs = Math.min(5e3, Math.round(retryDelayMs * 1.6));
200907
201220
  }
200908
- const networkWait = await waitForNetworkOnline({
200909
- targetHost: networkTargetHost,
200910
- onStatus: stage,
200911
- onNotice: (message) => console.error(message)
200912
- });
200913
- if (networkWait === "aborted") {
200914
- process.exitCode = 130;
200915
- break;
200916
- }
200917
- if (networkWait === "waited") {
200918
- retryDelayMs = 250;
201221
+ } finally {
201222
+ if (sigintListenerInstalled) {
201223
+ process.removeListener("SIGINT", onSigint);
200919
201224
  }
200920
- await new Promise((resolve2) => setTimeout(resolve2, retryDelayMs));
200921
- retryDelayMs = Math.min(5e3, Math.round(retryDelayMs * 1.6));
200922
201225
  }
200923
201226
  } finally {
200924
201227
  const exitCode = typeof process.exitCode === "number" ? process.exitCode : void 0;
@@ -201797,6 +202100,7 @@ var init_state = __esm({
201797
202100
  "workdirProvisioned",
201798
202101
  "gitSafeDirectoryConfigured",
201799
202102
  "setupUploaded",
202103
+ "codexConfigUpdated",
201800
202104
  "setupArtifactsStaged",
201801
202105
  "servicesEnabled",
201802
202106
  "codexCliEnsured",
@@ -202459,14 +202763,64 @@ var init_weztermMux = __esm({
202459
202763
  }
202460
202764
  });
202461
202765
 
202766
+ // src/devbox/commands/init/codex/config.ts
202767
+ var isRecord, parseExistingConfig, normalizeTrustedPaths, ensureNoticeConfig, ensureTrustedProjects, mergeCodexInitConfig;
202768
+ var init_config2 = __esm({
202769
+ "src/devbox/commands/init/codex/config.ts"() {
202770
+ "use strict";
202771
+ init_dist2();
202772
+ isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
202773
+ parseExistingConfig = (content) => {
202774
+ if (!content) return {};
202775
+ try {
202776
+ const parsed = parse(content);
202777
+ return isRecord(parsed) ? { ...parsed } : {};
202778
+ } catch {
202779
+ return {};
202780
+ }
202781
+ };
202782
+ normalizeTrustedPaths = (trustedPaths) => [
202783
+ ...new Set(trustedPaths.map((path38) => path38.trim()).filter(Boolean))
202784
+ ];
202785
+ ensureNoticeConfig = (config4) => {
202786
+ const notice = isRecord(config4.notice) ? { ...config4.notice } : {};
202787
+ notice.hide_full_access_warning = true;
202788
+ config4.notice = notice;
202789
+ };
202790
+ ensureTrustedProjects = (config4, trustedPaths) => {
202791
+ const projects = isRecord(config4.projects) ? { ...config4.projects } : {};
202792
+ for (const trustedPath of normalizeTrustedPaths(trustedPaths)) {
202793
+ const existingProject = isRecord(projects[trustedPath]) ? { ...projects[trustedPath] } : {};
202794
+ existingProject.trust_level = "trusted";
202795
+ projects[trustedPath] = existingProject;
202796
+ }
202797
+ config4.projects = projects;
202798
+ };
202799
+ mergeCodexInitConfig = ({
202800
+ existingContent,
202801
+ trustedPaths
202802
+ }) => {
202803
+ const config4 = parseExistingConfig(existingContent);
202804
+ config4.approval_policy = "never";
202805
+ config4.sandbox_mode = "danger-full-access";
202806
+ ensureNoticeConfig(config4);
202807
+ ensureTrustedProjects(config4, trustedPaths);
202808
+ const rendered = stringify(config4);
202809
+ return rendered.endsWith("\n") ? rendered : `${rendered}
202810
+ `;
202811
+ };
202812
+ }
202813
+ });
202814
+
202462
202815
  // src/devbox/commands/init/remote.ts
202463
- var import_node_crypto11, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, MODAL_DAEMON_HEALTH_PORT, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS, BOOTSTRAP_EXEC_HANDSHAKE_TIMEOUT_MS, BASHRC_PATH, ZSHRC_PATH, BASIC_ALIASES_MARKER, LEGACY_BASH_TRAP, SAFE_BASH_TRAP, BASH_HISTORY_BLOCK, ZSH_HISTORY_BLOCK, HISTORY_BLOCK_PATTERN, BASH_HISTORY_LINE_PATTERN, ZSH_HISTORY_LINE_PATTERN, logger8, truncateTail, shellQuote4, expandHome2, execWithLog, writeRemoteFile, readRemoteFile, ensureTrailingNewline, upsertHistoryBlock, patchBashrcContent, patchZshrcContent, bootstrapDevbox, buildWeztermMuxConfig, buildWeztermMuxRunner, patchRemoteRcFile, patchBashrc, patchZshrc, stageRemoteSetupArtifacts, resolveDaemonUrl, fetchDaemonBinary, buildDaemonConfig, buildDaemonWrapperScript, isSameArgs, ensureSpriteDaemonService, installWeztermMux, ensureWeztermMuxService, hasWeztermMuxBinary, isWeztermMuxHealthy, installSpriteDaemon;
202816
+ var import_node_crypto11, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, MODAL_DAEMON_HEALTH_PORT, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS, BOOTSTRAP_EXEC_HANDSHAKE_TIMEOUT_MS, BASHRC_PATH, ZSHRC_PATH, CODEX_CONFIG_DIR, CODEX_CONFIG_PATH, BASIC_ALIASES_MARKER, LEGACY_BASH_TRAP, SAFE_BASH_TRAP, BASH_HISTORY_BLOCK, ZSH_HISTORY_BLOCK, HISTORY_BLOCK_PATTERN, BASH_HISTORY_LINE_PATTERN, ZSH_HISTORY_LINE_PATTERN, logger8, truncateTail, shellQuote4, expandHome2, execWithLog, writeRemoteFile, readRemoteFile, ensureTrailingNewline, upsertHistoryBlock, patchBashrcContent, patchZshrcContent, bootstrapDevbox, buildWeztermMuxConfig, buildWeztermMuxRunner, patchRemoteRcFile, patchBashrc, patchZshrc, ensureRemoteCodexConfig, stageRemoteSetupArtifacts, resolveDaemonUrl, fetchDaemonBinary, buildDaemonConfig, buildDaemonWrapperScript, isSameArgs, ensureSpriteDaemonService, installWeztermMux, ensureWeztermMuxService, hasWeztermMuxBinary, isWeztermMuxHealthy, installSpriteDaemon;
202464
202817
  var init_remote = __esm({
202465
202818
  "src/devbox/commands/init/remote.ts"() {
202466
202819
  "use strict";
202467
202820
  import_node_crypto11 = require("node:crypto");
202468
202821
  init_src();
202469
202822
  init_weztermMux();
202823
+ init_config2();
202470
202824
  DAEMON_DIR = "/home/sprite/.devbox/daemon";
202471
202825
  DAEMON_TARBALL = `${DAEMON_DIR}/sprite-daemon.tar.gz`;
202472
202826
  DAEMON_BUNDLE_DIR = `${DAEMON_DIR}/bundle`;
@@ -202481,6 +202835,8 @@ var init_remote = __esm({
202481
202835
  BOOTSTRAP_EXEC_HANDSHAKE_TIMEOUT_MS = 2e4;
202482
202836
  BASHRC_PATH = "/home/sprite/.bashrc";
202483
202837
  ZSHRC_PATH = "/home/sprite/.zshrc";
202838
+ CODEX_CONFIG_DIR = "/home/sprite/.codex";
202839
+ CODEX_CONFIG_PATH = `${CODEX_CONFIG_DIR}/config.toml`;
202484
202840
  BASIC_ALIASES_MARKER = "\n# Basic aliases";
202485
202841
  LEGACY_BASH_TRAP = `trap 'echo -ne "\\033]0;\${BASH_COMMAND}\\007"' DEBUG`;
202486
202842
  SAFE_BASH_TRAP = `trap 'printf "\\033]0;%s\\007" "\${BASH_COMMAND//[^[:print:]]/}"' DEBUG`;
@@ -202896,6 +203252,59 @@ ${canonicalBlock}
202896
203252
  errorLabel: "zshrc",
202897
203253
  transform: patchZshrcContent
202898
203254
  });
203255
+ ensureRemoteCodexConfig = async ({
203256
+ client: client2,
203257
+ spriteAlias,
203258
+ trustedPaths
203259
+ }) => {
203260
+ const mkdirResult = await execWithLog(
203261
+ client2,
203262
+ spriteAlias,
203263
+ [
203264
+ "set -euo pipefail",
203265
+ `mkdir -p ${shellQuote4(CODEX_CONFIG_DIR)}`,
203266
+ `chmod 700 ${shellQuote4(CODEX_CONFIG_DIR)}`
203267
+ ].join("\n"),
203268
+ "codex-config-mkdir"
203269
+ );
203270
+ if (mkdirResult.exitCode !== 0) {
203271
+ const details = mkdirResult.stderr || mkdirResult.stdout || "";
203272
+ throw new Error(
203273
+ details ? `codex config mkdir failed: ${details}` : `codex config mkdir failed (exit ${mkdirResult.exitCode})`
203274
+ );
203275
+ }
203276
+ const existing = await readRemoteFile(
203277
+ client2,
203278
+ spriteAlias,
203279
+ CODEX_CONFIG_PATH,
203280
+ "codex-config-read"
203281
+ );
203282
+ const next = mergeCodexInitConfig({
203283
+ existingContent: existing,
203284
+ trustedPaths
203285
+ });
203286
+ await writeRemoteFile(
203287
+ client2,
203288
+ spriteAlias,
203289
+ CODEX_CONFIG_PATH,
203290
+ next,
203291
+ "codex-config-write"
203292
+ );
203293
+ const chmodResult = await execWithLog(
203294
+ client2,
203295
+ spriteAlias,
203296
+ ["set -euo pipefail", `chmod 600 ${shellQuote4(CODEX_CONFIG_PATH)}`].join(
203297
+ "\n"
203298
+ ),
203299
+ "codex-config-chmod"
203300
+ );
203301
+ if (chmodResult.exitCode !== 0) {
203302
+ const details = chmodResult.stderr || chmodResult.stdout || "";
203303
+ throw new Error(
203304
+ details ? `codex config chmod failed: ${details}` : `codex config chmod failed (exit ${chmodResult.exitCode})`
203305
+ );
203306
+ }
203307
+ };
202899
203308
  stageRemoteSetupArtifacts = async ({
202900
203309
  client: client2,
202901
203310
  spriteAlias,
@@ -204003,6 +204412,19 @@ ${combined}` : "";
204003
204412
  }
204004
204413
  });
204005
204414
 
204415
+ // src/devbox/ui/copyableUrl.ts
204416
+ var showCopyableUrl;
204417
+ var init_copyableUrl = __esm({
204418
+ "src/devbox/ui/copyableUrl.ts"() {
204419
+ "use strict";
204420
+ init_dist5();
204421
+ showCopyableUrl = (url, label) => {
204422
+ R2.info(`${label}:`);
204423
+ R2.message(url, { withGuide: false, spacing: 0 });
204424
+ };
204425
+ }
204426
+ });
204427
+
204006
204428
  // src/devbox/commands/init/codex/template.ts
204007
204429
  var renderTemplate;
204008
204430
  var init_template = __esm({
@@ -208618,7 +209040,7 @@ ${sshResult.stderr}`.trim();
208618
209040
  });
208619
209041
 
208620
209042
  // src/devbox/commands/servicesToml.ts
208621
- var splitShellCommand, normalizeSectionName, isRecord, asString2, asStringArray, asNumber, parseServicesToml, formatSectionName, renderServiceBlock, mergeServicesToml;
209043
+ var splitShellCommand, normalizeSectionName, isRecord2, asString2, asStringArray, asNumber, parseServicesToml, formatSectionName, renderServiceBlock, mergeServicesToml;
208622
209044
  var init_servicesToml = __esm({
208623
209045
  "src/devbox/commands/servicesToml.ts"() {
208624
209046
  "use strict";
@@ -208674,7 +209096,7 @@ var init_servicesToml = __esm({
208674
209096
  }
208675
209097
  return trimmed;
208676
209098
  };
208677
- isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
209099
+ isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
208678
209100
  asString2 = (value) => typeof value === "string" ? value : null;
208679
209101
  asStringArray = (value) => {
208680
209102
  if (!Array.isArray(value)) return null;
@@ -208698,14 +209120,14 @@ var init_servicesToml = __esm({
208698
209120
  };
208699
209121
  parseServicesToml = (content) => {
208700
209122
  const parsed = parse(content);
208701
- if (!isRecord(parsed)) return {};
209123
+ if (!isRecord2(parsed)) return {};
208702
209124
  const servicesRoot = parsed.services;
208703
- if (!isRecord(servicesRoot)) return {};
209125
+ if (!isRecord2(servicesRoot)) return {};
208704
209126
  const services = {};
208705
209127
  for (const [rawName, value] of Object.entries(servicesRoot)) {
208706
209128
  const name = String(rawName);
208707
209129
  if (!name) continue;
208708
- if (!isRecord(value)) continue;
209130
+ if (!isRecord2(value)) continue;
208709
209131
  const entry = { name };
208710
209132
  const cmd = asString2(value.cmd);
208711
209133
  if (cmd) entry.cmd = cmd;
@@ -209383,6 +209805,27 @@ var init_finalizeFlow = __esm({
209383
209805
  });
209384
209806
  }
209385
209807
  });
209808
+ const skipCodexConfigUpdate = Boolean(
209809
+ shouldResume && getInitState()?.steps.codexConfigUpdated
209810
+ );
209811
+ if (!skipCodexConfigUpdate) {
209812
+ await runInitStep({
209813
+ enabled: progressEnabled,
209814
+ title: "Updating Codex config",
209815
+ fn: async ({ status }) => {
209816
+ await retryInitStep2({
209817
+ status,
209818
+ title: "Updating Codex config",
209819
+ fn: async () => await ensureRemoteCodexConfig({
209820
+ client: client2,
209821
+ spriteAlias,
209822
+ trustedPaths: ["/home/sprite", expandedWorkdir]
209823
+ })
209824
+ });
209825
+ }
209826
+ });
209827
+ await updateInitState({ steps: { codexConfigUpdated: true } });
209828
+ }
209386
209829
  const skipSetupArtifactsStage = Boolean(
209387
209830
  skipCodexApply || shouldResume && getInitState()?.steps.setupArtifactsStaged
209388
209831
  );
@@ -211246,7 +211689,7 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
211246
211689
  });
211247
211690
 
211248
211691
  // src/devbox/commands/list.ts
211249
- var buildListColumns, parseListArgs, resolveBoxStateStyle, resolveBoxStatus, resolveSetupCell, fetchSpritesRemoteStates, resolveRemoteStates, runList;
211692
+ var buildListColumns, parseListArgs, resolveBoxStateStyle, resolveBoxStatus, resolveSetupCell, resolveSpritesLookupAlias, fetchSpritesRemoteStates, resolveRemoteStates, runList;
211250
211693
  var init_list = __esm({
211251
211694
  "src/devbox/commands/list.ts"() {
211252
211695
  "use strict";
@@ -211323,17 +211766,32 @@ var init_list = __esm({
211323
211766
  }
211324
211767
  return makeCell("-", colors.dim);
211325
211768
  };
211769
+ resolveSpritesLookupAlias = (box) => {
211770
+ const alias = box.alias?.trim();
211771
+ return alias ? alias : null;
211772
+ };
211326
211773
  fetchSpritesRemoteStates = async (client2, boxes) => {
211327
211774
  const states = /* @__PURE__ */ new Map();
211328
- const canonicals = Array.from(
211329
- new Set(
211330
- boxes.filter((box) => box.computeProvider !== "modal").map((box) => box.canonical).filter((canonical) => canonical.trim().length > 0)
211331
- )
211332
- );
211775
+ const canonicalLookups = /* @__PURE__ */ new Map();
211776
+ for (const box of boxes) {
211777
+ if (box.computeProvider === "modal") continue;
211778
+ const canonical = box.canonical.trim();
211779
+ if (!canonical || canonicalLookups.has(canonical)) continue;
211780
+ const lookupAlias = resolveSpritesLookupAlias(box);
211781
+ if (!lookupAlias) {
211782
+ logger7.warn("sprites_status_lookup_missing_alias", { canonical });
211783
+ states.set(canonical, {
211784
+ remote: "error",
211785
+ note: "alias metadata missing"
211786
+ });
211787
+ continue;
211788
+ }
211789
+ canonicalLookups.set(canonical, lookupAlias);
211790
+ }
211333
211791
  await Promise.all(
211334
- canonicals.map(async (canonical) => {
211792
+ [...canonicalLookups.entries()].map(async ([canonical, lookupName]) => {
211335
211793
  try {
211336
- const sprite = await client2.getSprite(canonical);
211794
+ const sprite = await client2.getSprite(lookupName);
211337
211795
  if (!sprite) {
211338
211796
  states.set(canonical, { remote: "missing" });
211339
211797
  return;
@@ -211345,6 +211803,7 @@ var init_list = __esm({
211345
211803
  } catch (error2) {
211346
211804
  logger7.warn("sprites_status_lookup_failed", {
211347
211805
  canonical,
211806
+ lookupName,
211348
211807
  error: String(error2)
211349
211808
  });
211350
211809
  states.set(canonical, { remote: "error" });
@@ -215124,9 +215583,16 @@ var init_setup = __esm({
215124
215583
  const store = await createSecretStore(void 0, storeOptions);
215125
215584
  const apiBaseUrl = resolveSpritesApiUrl(existingConfig);
215126
215585
  const requireControlPlaneToken2 = parsed.spriteAuthMode ? true : parsed.verify;
215586
+ const authStage = (message) => {
215587
+ if (message === CONTROL_PLANE_INTERACTIVE_SIGNIN_STAGE) {
215588
+ status.stop();
215589
+ return;
215590
+ }
215591
+ status.stage(message);
215592
+ };
215127
215593
  const tokenResult = await ensureSpritesToken(
215128
215594
  store,
215129
- (message) => status.stage(message),
215595
+ authStage,
215130
215596
  parsed.token ? {
215131
215597
  tokenOverride: parsed.token,
215132
215598
  requireControlPlaneToken: requireControlPlaneToken2,
@@ -216968,4 +217434,4 @@ smol-toml/dist/index.js:
216968
217434
  */
216969
217435
  //# sourceMappingURL=dvb.cjs.map
216970
217436
 
216971
- //# debugId=2abd239d-3084-5a69-b772-ab46c3dbd477
217437
+ //# debugId=b4643c26-df5e-5ece-b58a-108a9965ffde