peachsim 0.1.628 → 0.1.630

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 (111) hide show
  1. package/README.md +8 -4
  2. package/cli/bridge-flow-runner.ts +10 -3
  3. package/cli/cli-update.ts +2 -7
  4. package/cli/cloud-test-tunnel.ts +16 -3
  5. package/cli/commands/config.ts +1 -1
  6. package/cli/commands/control.ts +28 -3
  7. package/cli/commands/daemon-mac-app.ts +4 -2
  8. package/cli/commands/daemon.ts +4 -4
  9. package/cli/commands/device.ts +2 -3
  10. package/cli/commands/inspect/actions.ts +125 -90
  11. package/cli/commands/inspect/core.ts +5 -0
  12. package/cli/commands/inspect.ts +27 -13
  13. package/cli/commands/platform.ts +1 -1
  14. package/cli/commands/screenshot-layers.ts +1 -1
  15. package/cli/commands/screenshot.ts +1 -1
  16. package/cli/commands/skills.ts +0 -31
  17. package/cli/drivers/playwright-provisioning.ts +3 -2
  18. package/cli/drivers/playwright-sim-host.ts +25 -9
  19. package/cli/main.ts +8 -2
  20. package/cli/outbound-endpoints.ts +0 -4
  21. package/detox/index.ts +74 -43
  22. package/dist-lib/agent-daemon-client.cjs +1 -1
  23. package/dist-lib/agent-events.cjs +1 -1
  24. package/dist-lib/agent-identity.cjs +1 -1
  25. package/dist-lib/agent-sessions.cjs +1 -1
  26. package/dist-lib/attached-projects.cjs +1 -1
  27. package/dist-lib/auth/shared-session.cjs +1 -1
  28. package/dist-lib/backend-origin.cjs +1 -1
  29. package/dist-lib/beta.cjs +1 -1
  30. package/dist-lib/beta.mjs +1 -1
  31. package/dist-lib/bridge-constants.cjs +1 -1
  32. package/dist-lib/bridge-contract-input.cjs +1 -1
  33. package/dist-lib/bridge-contract-input.mjs +1 -1
  34. package/dist-lib/bridge-contract.cjs +1 -1
  35. package/dist-lib/bridge-contract.mjs +1 -1
  36. package/dist-lib/capture-contract.cjs +1 -1
  37. package/dist-lib/capture-contract.mjs +1 -1
  38. package/dist-lib/cli-constants.cjs +1 -1
  39. package/dist-lib/cloud-contract.cjs +1 -1
  40. package/dist-lib/cloud-contract.mjs +1 -1
  41. package/dist-lib/cloud-test-args.cjs +1 -1
  42. package/dist-lib/cloud-test-args.mjs +1 -1
  43. package/dist-lib/cloud.cjs +1 -1
  44. package/dist-lib/cloud.mjs +1 -1
  45. package/dist-lib/config.cjs +1 -1
  46. package/dist-lib/detox/index.cjs +129 -27
  47. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  48. package/dist-lib/home-paths.cjs +1 -1
  49. package/dist-lib/host/bridge-host.cjs +290 -315
  50. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  51. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  52. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  53. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  54. package/dist-lib/host/websocket-proxy.cjs +1 -1
  55. package/dist-lib/index.cjs +253 -121
  56. package/dist-lib/jump-to-source-babel.cjs +1 -1
  57. package/dist-lib/jump-to-source-native.cjs +1 -1
  58. package/dist-lib/{vite-kotlin.cjs → kotlin-host.cjs} +130 -19
  59. package/dist-lib/menu.cjs +1 -1
  60. package/dist-lib/menu.mjs +1 -1
  61. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  62. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  63. package/dist-lib/metro-production-bundle.cjs +1 -1
  64. package/dist-lib/metro-production-bundle.mjs +1 -1
  65. package/dist-lib/metro.cjs +132 -9
  66. package/dist-lib/native-app-identity.cjs +278 -0
  67. package/dist-lib/native-app-identity.mjs +245 -0
  68. package/dist-lib/profiles.cjs +1 -1
  69. package/dist-lib/public-brand.cjs +1 -1
  70. package/dist-lib/react-native-host-modules.cjs +1 -1
  71. package/dist-lib/react-native-host-modules.mjs +1 -1
  72. package/dist-lib/render-mode.cjs +1 -1
  73. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  74. package/dist-lib/sdk.cjs +110 -87
  75. package/dist-lib/sdk.mjs +110 -87
  76. package/dist-lib/skills.cjs +841 -643
  77. package/dist-lib/swift-compile.cjs +1 -1
  78. package/dist-lib/swift-compile.mjs +1 -1
  79. package/dist-lib/swift-package.cjs +1 -1
  80. package/dist-lib/swift-package.mjs +1 -1
  81. package/dist-lib/swift-submit.cjs +1 -1
  82. package/dist-lib/swift-submit.mjs +1 -1
  83. package/dist-lib/swift.cjs +282 -177
  84. package/dist-lib/vite-swift.cjs +1 -1
  85. package/dist-lib/vite.cjs +11 -28
  86. package/kotlin/README.md +32 -4
  87. package/kotlin/fixtures/counter/Counter.kt +26 -0
  88. package/kotlin/fixtures/counter/CounterScreen.kt +40 -0
  89. package/kotlin/fixtures/headless-counter/Headless.kt +228 -0
  90. package/kotlin/fixtures/runtime-state/RuntimeState.kt +200 -0
  91. package/kotlin/fork/LICENSE +178 -0
  92. package/kotlin/fork/NOTICE +25 -0
  93. package/kotlin/fork/README.md +59 -0
  94. package/kotlin/fork/build.sh +128 -0
  95. package/kotlin/fork/compose-worker-globals.patch +96 -0
  96. package/kotlin/fork/fork.json +33 -0
  97. package/kotlin/fork/publish.ts +77 -0
  98. package/kotlin/fork/skiko-worker-clock.patch +33 -0
  99. package/kotlin/toolchain.json +288 -0
  100. package/package.json +12 -5
  101. package/src/automatic-update-policy.ts +17 -0
  102. package/src/host/bridge-host.ts +3 -1
  103. package/src/{vite-plugin-kotlin.ts → kotlin-host.ts} +155 -12
  104. package/src/metro-plugin.ts +18 -0
  105. package/src/native-app-identity.ts +376 -0
  106. package/src/native-firebase-config.ts +90 -0
  107. package/src/screenshots/frame-compose.ts +5 -2
  108. package/src/screenshots/registry.ts +1 -1
  109. package/src/screenshots/schema.ts +2 -2
  110. package/src/vite-plugin-one.ts +11 -28
  111. package/src/vite-plugin.ts +6 -1
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -120,23 +120,6 @@ var init_optional_demo_registry = __esm({
120
120
  }
121
121
  });
122
122
 
123
- // src/public-brand.ts
124
- var name, peachPublicBrand, rnxPublicBrand;
125
- var init_public_brand = __esm({
126
- "src/public-brand.ts"() {
127
- "use strict";
128
- name = "Peach";
129
- peachPublicBrand = Object.freeze({
130
- name,
131
- packageName: "peachsim",
132
- commandName: "peach",
133
- domain: "peachsim.com",
134
- origin: "https://peachsim.com"
135
- });
136
- rnxPublicBrand = peachPublicBrand;
137
- }
138
- });
139
-
140
123
  // src/home-paths.ts
141
124
  function rnxHomeDir() {
142
125
  const override = process.env[PEACH_HOME_ENV];
@@ -151,7 +134,7 @@ function isSootsimDevCheckout() {
151
134
  const argv1 = process.argv[1];
152
135
  if (!argv1) return false;
153
136
  try {
154
- const real = import_node_fs4.default.realpathSync(argv1);
137
+ const real = import_node_fs3.default.realpathSync(argv1);
155
138
  return real.includes(`${import_node_path4.default.sep}packages${import_node_path4.default.sep}peachsim${import_node_path4.default.sep}`);
156
139
  } catch {
157
140
  return false;
@@ -198,7 +181,7 @@ function configFilePath() {
198
181
  }
199
182
  function readSharedConfig() {
200
183
  try {
201
- const raw = import_node_fs4.default.readFileSync(configFilePath(), "utf8");
184
+ const raw = import_node_fs3.default.readFileSync(configFilePath(), "utf8");
202
185
  const parsed = JSON.parse(raw);
203
186
  return parsed && typeof parsed === "object" ? parsed : {};
204
187
  } catch {
@@ -216,9 +199,9 @@ function writeSharedConfig(patch) {
216
199
  };
217
200
  }
218
201
  const tmp = `${configFilePath()}.tmp`;
219
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
202
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
220
203
  `, "utf8");
221
- import_node_fs4.default.renameSync(tmp, configFilePath());
204
+ import_node_fs3.default.renameSync(tmp, configFilePath());
222
205
  return next;
223
206
  }
224
207
  function runtimeUpgradeNoticePath() {
@@ -227,28 +210,28 @@ function runtimeUpgradeNoticePath() {
227
210
  function writeRuntimeUpgradeNotice(notice) {
228
211
  ensureRnxHome();
229
212
  const tmp = `${runtimeUpgradeNoticePath()}.tmp`;
230
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(notice)}
213
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(notice)}
231
214
  `, "utf8");
232
- import_node_fs4.default.renameSync(tmp, runtimeUpgradeNoticePath());
215
+ import_node_fs3.default.renameSync(tmp, runtimeUpgradeNoticePath());
233
216
  }
234
217
  function ensureRnxHome() {
235
- import_node_fs4.default.mkdirSync(rnxHomeDir(), { recursive: true });
236
- import_node_fs4.default.mkdirSync(runtimesDir(), { recursive: true });
237
- import_node_fs4.default.mkdirSync(electronDir(), { recursive: true });
238
- import_node_fs4.default.mkdirSync(profilesDir(), { recursive: true });
239
- import_node_fs4.default.mkdirSync(cacheDir(), { recursive: true });
218
+ import_node_fs3.default.mkdirSync(rnxHomeDir(), { recursive: true });
219
+ import_node_fs3.default.mkdirSync(runtimesDir(), { recursive: true });
220
+ import_node_fs3.default.mkdirSync(electronDir(), { recursive: true });
221
+ import_node_fs3.default.mkdirSync(profilesDir(), { recursive: true });
222
+ import_node_fs3.default.mkdirSync(cacheDir(), { recursive: true });
240
223
  }
241
224
  function readActiveRuntime() {
242
225
  try {
243
- const value = import_node_fs4.default.readFileSync(activeRuntimeFile(), "utf8").trim();
226
+ const value = import_node_fs3.default.readFileSync(activeRuntimeFile(), "utf8").trim();
244
227
  return value.length > 0 ? value : null;
245
228
  } catch {
246
229
  return null;
247
230
  }
248
231
  }
249
232
  function writeActiveRuntime(version) {
250
- import_node_fs4.default.mkdirSync(runtimesDir(), { recursive: true });
251
- import_node_fs4.default.writeFileSync(activeRuntimeFile(), `${version}
233
+ import_node_fs3.default.mkdirSync(runtimesDir(), { recursive: true });
234
+ import_node_fs3.default.writeFileSync(activeRuntimeFile(), `${version}
252
235
  `, "utf8");
253
236
  }
254
237
  function activeRuntimeDir() {
@@ -256,17 +239,17 @@ function activeRuntimeDir() {
256
239
  if (!version) return null;
257
240
  const dir = runtimeDir(version);
258
241
  try {
259
- if (import_node_fs4.default.statSync(dir).isDirectory()) return dir;
242
+ if (import_node_fs3.default.statSync(dir).isDirectory()) return dir;
260
243
  } catch {
261
244
  }
262
245
  return null;
263
246
  }
264
247
  function readDaemonLockfile() {
265
248
  try {
266
- const fd = import_node_fs4.default.openSync(daemonLockfilePath(), "r");
249
+ const fd = import_node_fs3.default.openSync(daemonLockfilePath(), "r");
267
250
  try {
268
251
  const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
269
- const bytesRead = import_node_fs4.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
252
+ const bytesRead = import_node_fs3.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
270
253
  const raw = buf.subarray(0, bytesRead).toString("utf8");
271
254
  const parsed = JSON.parse(raw);
272
255
  if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
@@ -274,7 +257,7 @@ function readDaemonLockfile() {
274
257
  }
275
258
  return null;
276
259
  } finally {
277
- import_node_fs4.default.closeSync(fd);
260
+ import_node_fs3.default.closeSync(fd);
278
261
  }
279
262
  } catch {
280
263
  return null;
@@ -313,28 +296,28 @@ function writeDaemonLockfile(data) {
313
296
  throw new Error("refusing to overwrite another peach daemon lockfile");
314
297
  }
315
298
  const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
316
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
299
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
317
300
  `, "utf8");
318
301
  try {
319
302
  const current = readDaemonLockfile();
320
303
  if (!current || !sameDaemonOwner(current, data)) {
321
304
  throw new Error("peach daemon lock ownership changed during heartbeat");
322
305
  }
323
- import_node_fs4.default.renameSync(tmp, lockfilePath);
306
+ import_node_fs3.default.renameSync(tmp, lockfilePath);
324
307
  } finally {
325
308
  try {
326
- import_node_fs4.default.unlinkSync(tmp);
309
+ import_node_fs3.default.unlinkSync(tmp);
327
310
  } catch {
328
311
  }
329
312
  }
330
313
  }
331
314
  function writeDevBridgeLockfile(data) {
332
- import_node_fs4.default.mkdirSync(devBridgesDir(), { recursive: true });
315
+ import_node_fs3.default.mkdirSync(devBridgesDir(), { recursive: true });
333
316
  const lockfilePath = devBridgeLockfilePath(data.bridgePort);
334
317
  const tmp = `${lockfilePath}.${data.pid}.tmp`;
335
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
318
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
336
319
  `, "utf8");
337
- import_node_fs4.default.renameSync(tmp, lockfilePath);
320
+ import_node_fs3.default.renameSync(tmp, lockfilePath);
338
321
  }
339
322
  function sameDaemonOwner(left, right) {
340
323
  return left.pid === right.pid && left.startedAt === right.startedAt;
@@ -345,17 +328,17 @@ function isAlreadyExists(error) {
345
328
  function createDaemonLockfileExclusive(data) {
346
329
  const lockfilePath = daemonLockfilePath();
347
330
  const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.claim`;
348
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
331
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
349
332
  `, "utf8");
350
333
  try {
351
- import_node_fs4.default.linkSync(tmp, lockfilePath);
334
+ import_node_fs3.default.linkSync(tmp, lockfilePath);
352
335
  return true;
353
336
  } catch (error) {
354
337
  if (isAlreadyExists(error)) return false;
355
338
  throw error;
356
339
  } finally {
357
340
  try {
358
- import_node_fs4.default.unlinkSync(tmp);
341
+ import_node_fs3.default.unlinkSync(tmp);
359
342
  } catch {
360
343
  }
361
344
  }
@@ -379,7 +362,7 @@ function parseDaemonClaim(raw) {
379
362
  }
380
363
  function readDaemonClaim() {
381
364
  try {
382
- return parseDaemonClaim(import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8"));
365
+ return parseDaemonClaim(import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8"));
383
366
  } catch {
384
367
  return null;
385
368
  }
@@ -403,7 +386,7 @@ function acquireDaemonClaim(data) {
403
386
  `;
404
387
  for (let attempt = 0; attempt < 8; attempt++) {
405
388
  try {
406
- import_node_fs4.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
389
+ import_node_fs3.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
407
390
  return true;
408
391
  } catch (error) {
409
392
  if (!isAlreadyExists(error)) throw error;
@@ -413,11 +396,11 @@ function acquireDaemonClaim(data) {
413
396
  if (existing && isDaemonClaimFresh(existing)) return false;
414
397
  let before;
415
398
  try {
416
- before = import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8");
399
+ before = import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8");
417
400
  const latest = parseDaemonClaim(before);
418
401
  if (latest && isDaemonClaimFresh(latest)) return false;
419
- if (import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
420
- import_node_fs4.default.unlinkSync(daemonClaimPath());
402
+ if (import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
403
+ import_node_fs3.default.unlinkSync(daemonClaimPath());
421
404
  } catch {
422
405
  }
423
406
  }
@@ -427,7 +410,7 @@ function releaseDaemonClaim(owner) {
427
410
  try {
428
411
  const claim = readDaemonClaim();
429
412
  if (!claim || !sameDaemonOwner(claim, owner)) return;
430
- import_node_fs4.default.unlinkSync(daemonClaimPath());
413
+ import_node_fs3.default.unlinkSync(daemonClaimPath());
431
414
  } catch {
432
415
  }
433
416
  }
@@ -446,7 +429,7 @@ function claimDaemonLockfile(data) {
446
429
  if (!latest || !sameDaemonOwner(latest, existing)) return false;
447
430
  if (isDaemonLockfileFresh(latest)) return false;
448
431
  try {
449
- import_node_fs4.default.unlinkSync(daemonLockfilePath());
432
+ import_node_fs3.default.unlinkSync(daemonLockfilePath());
450
433
  } catch {
451
434
  return false;
452
435
  }
@@ -460,25 +443,25 @@ function removeDaemonLockfile(owner) {
460
443
  try {
461
444
  const lockfile = readDaemonLockfile();
462
445
  if (!lockfile || !sameDaemonOwner(lockfile, owner)) return;
463
- import_node_fs4.default.unlinkSync(daemonLockfilePath());
446
+ import_node_fs3.default.unlinkSync(daemonLockfilePath());
464
447
  } catch {
465
448
  }
466
449
  }
467
450
  function removeDevBridgeLockfile(owner) {
468
451
  try {
469
452
  const lockfilePath = devBridgeLockfilePath(owner.bridgePort);
470
- const lockfile = parseDevBridgeLockfile(import_node_fs4.default.readFileSync(lockfilePath, "utf8"));
453
+ const lockfile = parseDevBridgeLockfile(import_node_fs3.default.readFileSync(lockfilePath, "utf8"));
471
454
  if (lockfile?.pid !== owner.pid || lockfile.startedAt !== owner.startedAt) return;
472
- import_node_fs4.default.unlinkSync(lockfilePath);
455
+ import_node_fs3.default.unlinkSync(lockfilePath);
473
456
  } catch {
474
457
  }
475
458
  }
476
- var import_node_crypto, import_node_fs4, import_node_os, import_node_path4, PEACH_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
459
+ var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, PEACH_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
477
460
  var init_home_paths = __esm({
478
461
  "src/home-paths.ts"() {
479
462
  "use strict";
480
463
  import_node_crypto = require("node:crypto");
481
- import_node_fs4 = __toESM(require("node:fs"), 1);
464
+ import_node_fs3 = __toESM(require("node:fs"), 1);
482
465
  import_node_os = require("node:os");
483
466
  import_node_path4 = __toESM(require("node:path"), 1);
484
467
  PEACH_HOME_ENV = "PEACH_HOME";
@@ -492,6 +475,23 @@ var init_home_paths = __esm({
492
475
  }
493
476
  });
494
477
 
478
+ // src/public-brand.ts
479
+ var name, peachPublicBrand, rnxPublicBrand;
480
+ var init_public_brand = __esm({
481
+ "src/public-brand.ts"() {
482
+ "use strict";
483
+ name = "Peach";
484
+ peachPublicBrand = Object.freeze({
485
+ name,
486
+ packageName: "peachsim",
487
+ commandName: "peach",
488
+ domain: "peachsim.com",
489
+ origin: "https://peachsim.com"
490
+ });
491
+ rnxPublicBrand = peachPublicBrand;
492
+ }
493
+ });
494
+
495
495
  // src/auth/shared-session.ts
496
496
  function sharedDesktopAuthAccounts(user) {
497
497
  return [
@@ -502,14 +502,14 @@ function sharedDesktopAuthAccounts(user) {
502
502
  function getBaseDir() {
503
503
  const explicit = process.env[SESSION_FILE_ENV];
504
504
  if (explicit?.trim()) {
505
- return (0, import_node_path14.dirname)((0, import_node_path14.resolve)(explicit));
505
+ return (0, import_node_path15.dirname)((0, import_node_path15.resolve)(explicit));
506
506
  }
507
507
  return electronUserDataDir();
508
508
  }
509
509
  function getSharedDesktopAuthFilePath() {
510
510
  const explicit = process.env[SESSION_FILE_ENV];
511
- if (explicit?.trim()) return (0, import_node_path14.resolve)(explicit);
512
- return (0, import_node_path14.join)(getBaseDir(), "desktop-auth.json");
511
+ if (explicit?.trim()) return (0, import_node_path15.resolve)(explicit);
512
+ return (0, import_node_path15.join)(getBaseDir(), "desktop-auth.json");
513
513
  }
514
514
  function normalizeUser(input) {
515
515
  if (!input || typeof input !== "object") return null;
@@ -559,26 +559,26 @@ function normalizeSession(input) {
559
559
  }
560
560
  function readSharedDesktopAuthSession() {
561
561
  const filepath = getSharedDesktopAuthFilePath();
562
- if (!(0, import_node_fs13.existsSync)(filepath)) return null;
562
+ if (!(0, import_node_fs14.existsSync)(filepath)) return null;
563
563
  try {
564
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)(filepath, "utf8"));
564
+ const parsed = JSON.parse((0, import_node_fs14.readFileSync)(filepath, "utf8"));
565
565
  const normalized = normalizeSession(parsed);
566
566
  if (!normalized) {
567
- (0, import_node_fs13.rmSync)(filepath, { force: true });
567
+ (0, import_node_fs14.rmSync)(filepath, { force: true });
568
568
  return null;
569
569
  }
570
570
  return normalized;
571
571
  } catch {
572
- (0, import_node_fs13.rmSync)(filepath, { force: true });
572
+ (0, import_node_fs14.rmSync)(filepath, { force: true });
573
573
  return null;
574
574
  }
575
575
  }
576
- var import_node_fs13, import_node_path14, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
576
+ var import_node_fs14, import_node_path15, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
577
577
  var init_shared_session = __esm({
578
578
  "src/auth/shared-session.ts"() {
579
579
  "use strict";
580
- import_node_fs13 = require("node:fs");
581
- import_node_path14 = require("node:path");
580
+ import_node_fs14 = require("node:fs");
581
+ import_node_path15 = require("node:path");
582
582
  init_home_paths();
583
583
  SESSION_VERSION = 1;
584
584
  SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
@@ -939,7 +939,7 @@ function rotateDevice(device, side) {
939
939
  const barrelProtrusion = device.housing?.hingeBarrel?.protrusion ?? 0;
940
940
  if (side === "left") insets.top += barrelProtrusion;
941
941
  else insets.bottom += barrelProtrusion;
942
- const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 20, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
942
+ const safeArea = device.model === "ipad-pro-11" ? { top: 10, bottom: 20, left: 0, right: 0 } : device.model === "iphone-duo" ? { top: 0, bottom: 34, left: 0, right: 84 } : device.platform === "ios" && device.homeIndicatorHeight > 0 ? {
943
943
  top: 0,
944
944
  bottom: 20,
945
945
  left: device.safeAreaInsets.top,
@@ -974,71 +974,24 @@ function rotateDevice(device, side) {
974
974
  // the bars stay on the interface's top and bottom; a cutout's inset moves
975
975
  // to whichever side the cutout turned to.
976
976
  safeAreaInsets: side === "left" ? safeArea : { ...safeArea, left: safeArea.right, right: safeArea.left },
977
- statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" && device.model !== "iphone-duo" ? 0 : device.statusBarHeight,
978
- homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? 20 : device.homeIndicatorHeight
977
+ statusBarHeight: device.platform === "ios" && device.model !== "ipad-pro-11" ? 0 : device.statusBarHeight,
978
+ // the indicator's band is the landscape bottom inset
979
+ homeIndicatorHeight: device.platform === "ios" && device.homeIndicatorHeight > 0 ? safeArea.bottom : device.homeIndicatorHeight
979
980
  };
980
981
  }
981
- function getDevice(model, posture, orientation, landscapeSide = "left") {
982
+ function defaultLandscapeSide(model, posture) {
983
+ return model === "iphone-duo" && resolveDevicePosture(model, posture) === "closed" ? "right" : "left";
984
+ }
985
+ function getDevice(model, posture, orientation, landscapeSide) {
982
986
  const device = devices[model];
987
+ const side = landscapeSide ?? defaultLandscapeSide(model, posture);
983
988
  if (!device.supportedPostures) {
984
- return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, landscapeSide) : device;
989
+ return orientation === "landscape" && model !== "canvas-workspace" ? rotateDevice(device, side) : device;
985
990
  }
986
991
  const resolvedPosture = resolveDevicePosture(model, posture);
987
992
  const resolvedOrientation = orientation ?? deviceDefaultOrientation(model, resolvedPosture);
988
993
  if (resolvedPosture === "closed") {
989
- if (resolvedOrientation === "portrait") return device;
990
- const insets = device.frameInsets;
991
- const radii = device.cornerRadius;
992
- const body = device.frameCornerRadius ?? resolveDeviceFrameCorners(device).frameRadius;
993
- const housing = device.housing;
994
- const protrusion = housing?.hingeBarrel?.protrusion ?? 0;
995
- return {
996
- ...device,
997
- width: device.height,
998
- height: device.width,
999
- orientation: "landscape",
1000
- cornerRadius: {
1001
- topLeft: radii.topRight,
1002
- topRight: radii.bottomRight,
1003
- bottomRight: radii.bottomLeft,
1004
- bottomLeft: radii.topLeft
1005
- },
1006
- continuousCornerRadius: {
1007
- topLeft: device.continuousCornerRadius.topRight,
1008
- topRight: device.continuousCornerRadius.bottomRight,
1009
- bottomRight: device.continuousCornerRadius.bottomLeft,
1010
- bottomLeft: device.continuousCornerRadius.topLeft
1011
- },
1012
- frameInsets: {
1013
- top: insets.right,
1014
- right: insets.bottom,
1015
- bottom: insets.left + protrusion,
1016
- left: insets.top
1017
- },
1018
- frameCornerRadius: {
1019
- topLeft: body.topRight,
1020
- topRight: body.bottomRight,
1021
- bottomRight: body.bottomLeft,
1022
- bottomLeft: body.topLeft
1023
- },
1024
- housing: housing ? {
1025
- rail: {
1026
- top: housing.rail.right,
1027
- right: housing.rail.bottom,
1028
- bottom: housing.rail.left,
1029
- left: housing.rail.top
1030
- },
1031
- hingeBarrel: null
1032
- } : void 0,
1033
- cameraCutout: device.cameraCutout ? {
1034
- diameter: device.cameraCutout.diameter,
1035
- top: device.cameraCutout.top,
1036
- leading: device.cameraCutout.trailing
1037
- } : null,
1038
- safeAreaInsets: { top: 0, bottom: 34, left: 84, right: 0 },
1039
- // vertically compact, so the status bar is hidden.
1040
- statusBarHeight: 0
1041
- };
994
+ return resolvedOrientation === "portrait" ? device : rotateDevice(device, side);
1042
995
  }
1043
996
  const isRotatedPortrait = resolvedOrientation === "portrait";
1044
997
  return {
@@ -1565,10 +1518,12 @@ var init_devices = __esm({
1565
1518
  posture: "closed",
1566
1519
  supportedPostures: ["closed", "open"]
1567
1520
  }),
1521
+ // the ios 27.1 simulator's camera occlusion region: 37pt, 29 1/3 in from
1522
+ // the top and trailing edges
1568
1523
  cameraCutout: {
1569
1524
  diameter: 37,
1570
- top: 29,
1571
- trailing: 29
1525
+ top: 88 / 3,
1526
+ trailing: 88 / 3
1572
1527
  }
1573
1528
  },
1574
1529
  "ipad-pro-11": {
@@ -2705,7 +2660,9 @@ async function minify(code, sourceLine, options, withMap) {
2705
2660
  }
2706
2661
  const map = withMap && typeof result.map === "string" ? result.map : null;
2707
2662
  if (withMap && map === null) {
2708
- throw new Error(`peach Cloud got no source map for the statement at line ${sourceLine}`);
2663
+ throw new Error(
2664
+ `peach Cloud got no source map for the statement at line ${sourceLine}`
2665
+ );
2709
2666
  }
2710
2667
  return { code: result.code.trimEnd(), map, sourceLine };
2711
2668
  }
@@ -2769,8 +2726,9 @@ async function readOrInferModuleIdentity(bundle, mode, inferModuleIdentity) {
2769
2726
  }
2770
2727
  async function buildRnxCloudArtifact(bundle, options = {}) {
2771
2728
  const mode = options.mode ?? "production";
2729
+ const nativeIdentity = (0, import_native_app_identity.detachNativeAppIdentityFooter)(bundle);
2772
2730
  const identity = await readOrInferModuleIdentity(
2773
- bundle,
2731
+ nativeIdentity.source,
2774
2732
  mode,
2775
2733
  options.inferModuleIdentity
2776
2734
  );
@@ -2796,7 +2754,7 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
2796
2754
  })
2797
2755
  ]);
2798
2756
  const body = pieces.map((piece) => piece.code).join("\n");
2799
- const code = body + (0, import_metro_production_bundle.createRNXMetroModuleIdentityFooter)({
2757
+ const code = body + (nativeIdentity.identity ? (0, import_native_app_identity.createNativeAppIdentityFooter)(nativeIdentity.identity) : "") + (0, import_metro_production_bundle.createRNXMetroModuleIdentityFooter)({
2800
2758
  version: identity.version,
2801
2759
  identitySource: identity.identitySource,
2802
2760
  modulePaths: identity.modulePaths,
@@ -2859,11 +2817,12 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
2859
2817
  }
2860
2818
  };
2861
2819
  }
2862
- var import_metro_production_bundle, import_terser, MODULE_PATHS_REQUIRED, SOURCE_MAP_REQUIRED, MINIFY_OPTIONS;
2820
+ var import_metro_production_bundle, import_native_app_identity, import_terser, MODULE_PATHS_REQUIRED, SOURCE_MAP_REQUIRED, MINIFY_OPTIONS;
2863
2821
  var init_metroCloudArtifact = __esm({
2864
2822
  "../contrast-bundler/src/metroCloudArtifact.ts"() {
2865
2823
  "use strict";
2866
2824
  import_metro_production_bundle = require("peachsim/metro-production-bundle");
2825
+ import_native_app_identity = require("peachsim/native-app-identity");
2867
2826
  import_terser = require("terser");
2868
2827
  init_metroAssetArtifact();
2869
2828
  init_metroDebugSourceMap();
@@ -3092,6 +3051,12 @@ var init_stub_manifest = __esm({
3092
3051
  runtimeTier: "core",
3093
3052
  buildResolvers: ["vite", "dep-prebundle"]
3094
3053
  },
3054
+ vendorEventEmitter: {
3055
+ specifier: "react-native/Libraries/vendor/emitter/EventEmitter",
3056
+ stubFile: "rn-libraries/EventEmitter.ts",
3057
+ runtimeTier: "core",
3058
+ buildResolvers: ["vite", "dep-prebundle"]
3059
+ },
3095
3060
  rctDeviceEventEmitter: {
3096
3061
  specifier: "react-native/Libraries/EventEmitter/RCTDeviceEventEmitter",
3097
3062
  stubFile: "rn-libraries/RCTDeviceEventEmitter.ts",
@@ -4051,21 +4016,21 @@ function resolveCloudOrigin(value) {
4051
4016
  return normalizeCloudOrigin(source);
4052
4017
  }
4053
4018
  function readImmutableBundleSource(bundlePath) {
4054
- const filepath = (0, import_node_path15.resolve)(bundlePath);
4055
- if ((0, import_node_path15.extname)(filepath) !== ".js") {
4019
+ const filepath = (0, import_node_path16.resolve)(bundlePath);
4020
+ if ((0, import_node_path16.extname)(filepath) !== ".js") {
4056
4021
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
4057
4022
  }
4058
- const descriptor = (0, import_node_fs14.openSync)(filepath, "r");
4023
+ const descriptor = (0, import_node_fs15.openSync)(filepath, "r");
4059
4024
  try {
4060
- const before = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4025
+ const before = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4061
4026
  if (!before.isFile()) {
4062
4027
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
4063
4028
  }
4064
4029
  if (before.size <= 0n) {
4065
4030
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
4066
4031
  }
4067
- const bytes = (0, import_node_fs14.readFileSync)(descriptor);
4068
- const after = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4032
+ const bytes = (0, import_node_fs15.readFileSync)(descriptor);
4033
+ const after = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4069
4034
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
4070
4035
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
4071
4036
  }
@@ -4080,7 +4045,7 @@ function readImmutableBundleSource(bundlePath) {
4080
4045
  }
4081
4046
  return source;
4082
4047
  } finally {
4083
- (0, import_node_fs14.closeSync)(descriptor);
4048
+ (0, import_node_fs15.closeSync)(descriptor);
4084
4049
  }
4085
4050
  }
4086
4051
  async function fetchBundleSource(bundleUrl) {
@@ -4127,15 +4092,15 @@ async function loadBundleSource(bundleInput) {
4127
4092
  return readImmutableBundleSource(bundleInput);
4128
4093
  }
4129
4094
  function listMetroAssetDest(assetsPath) {
4130
- const directory = (0, import_node_path15.resolve)(assetsPath);
4131
- if (!(0, import_node_fs14.existsSync)(directory)) return { directory, files: [], truncated: false };
4132
- const skipNested = (0, import_node_fs14.existsSync)((0, import_node_path15.join)(directory, "package.json"));
4095
+ const directory = (0, import_node_path16.resolve)(assetsPath);
4096
+ if (!(0, import_node_fs15.existsSync)(directory)) return { directory, files: [], truncated: false };
4097
+ const skipNested = (0, import_node_fs15.existsSync)((0, import_node_path16.join)(directory, "package.json"));
4133
4098
  const files = [];
4134
4099
  let truncated = false;
4135
4100
  const walk = (dir, prefix) => {
4136
4101
  let entries;
4137
4102
  try {
4138
- entries = (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true });
4103
+ entries = (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true });
4139
4104
  } catch {
4140
4105
  return;
4141
4106
  }
@@ -4147,7 +4112,7 @@ function listMetroAssetDest(assetsPath) {
4147
4112
  if (entry.isDirectory()) {
4148
4113
  if (entry.name === ".git") continue;
4149
4114
  if (skipNested && PROJECT_ONLY_DIRECTORIES.has(entry.name)) continue;
4150
- walk((0, import_node_path15.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4115
+ walk((0, import_node_path16.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4151
4116
  } else if (entry.isFile()) {
4152
4117
  files.push(prefix ? `${prefix}/${entry.name}` : entry.name);
4153
4118
  }
@@ -4182,7 +4147,7 @@ function distinctByContent(directory, options) {
4182
4147
  for (const relative2 of options) {
4183
4148
  let bytes;
4184
4149
  try {
4185
- bytes = (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(directory, relative2));
4150
+ bytes = (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(directory, relative2));
4186
4151
  } catch {
4187
4152
  continue;
4188
4153
  }
@@ -4214,7 +4179,7 @@ function placeMetroDescriptor(listing, descriptor) {
4214
4179
  let bytes;
4215
4180
  try {
4216
4181
  bytes = combination.map(
4217
- (relative2) => (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(listing.directory, relative2))
4182
+ (relative2) => (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(listing.directory, relative2))
4218
4183
  );
4219
4184
  } catch {
4220
4185
  continue;
@@ -4240,26 +4205,26 @@ function placeMetroDescriptor(listing, descriptor) {
4240
4205
  }
4241
4206
  function unverifiedFileKey(dest) {
4242
4207
  return dest.placements.filter((placement) => !placement.verified).flatMap(
4243
- (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path15.join)(dest.directory, relative2))
4208
+ (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path16.join)(dest.directory, relative2))
4244
4209
  ).sort().join("\n");
4245
4210
  }
4246
4211
  function searchMetroAssetDest(bundlePath, descriptors) {
4247
- const bundleDirectory = (0, import_node_path15.dirname)((0, import_node_path15.resolve)(bundlePath));
4212
+ const bundleDirectory = (0, import_node_path16.dirname)((0, import_node_path16.resolve)(bundlePath));
4248
4213
  const candidates = [
4249
- (0, import_node_path15.join)(bundleDirectory, "assets"),
4214
+ (0, import_node_path16.join)(bundleDirectory, "assets"),
4250
4215
  bundleDirectory,
4251
- (0, import_node_path15.resolve)(bundleDirectory, "..", "assets")
4216
+ (0, import_node_path16.resolve)(bundleDirectory, "..", "assets")
4252
4217
  ];
4253
4218
  const cwd = process.cwd();
4254
4219
  let projectDirectory = null;
4255
4220
  for (const start of [bundleDirectory, cwd]) {
4256
- let directory = (0, import_node_path15.resolve)(start);
4221
+ let directory = (0, import_node_path16.resolve)(start);
4257
4222
  while (true) {
4258
4223
  if (detectProject(directory)?.hasMetroConfig) {
4259
4224
  projectDirectory = directory;
4260
4225
  break;
4261
4226
  }
4262
- const parent = (0, import_node_path15.dirname)(directory);
4227
+ const parent = (0, import_node_path16.dirname)(directory);
4263
4228
  if (parent === directory) break;
4264
4229
  directory = parent;
4265
4230
  }
@@ -4267,11 +4232,11 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4267
4232
  }
4268
4233
  if (projectDirectory) {
4269
4234
  candidates.push(
4270
- (0, import_node_path15.join)(projectDirectory, "assets"),
4271
- (0, import_node_path15.join)(projectDirectory, "dist"),
4272
- (0, import_node_path15.join)(projectDirectory, "dist", "assets"),
4273
- (0, import_node_path15.join)(projectDirectory, "build"),
4274
- (0, import_node_path15.join)(projectDirectory, "build", "assets")
4235
+ (0, import_node_path16.join)(projectDirectory, "assets"),
4236
+ (0, import_node_path16.join)(projectDirectory, "dist"),
4237
+ (0, import_node_path16.join)(projectDirectory, "dist", "assets"),
4238
+ (0, import_node_path16.join)(projectDirectory, "build"),
4239
+ (0, import_node_path16.join)(projectDirectory, "build", "assets")
4275
4240
  );
4276
4241
  }
4277
4242
  const searched = [];
@@ -4279,7 +4244,7 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4279
4244
  const stale = [];
4280
4245
  let truncated = false;
4281
4246
  for (const candidate of candidates) {
4282
- const directory = (0, import_node_path15.resolve)(candidate);
4247
+ const directory = (0, import_node_path16.resolve)(candidate);
4283
4248
  if (searched.includes(directory)) continue;
4284
4249
  searched.push(directory);
4285
4250
  const listing = listMetroAssetDest(directory);
@@ -4385,7 +4350,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4385
4350
  );
4386
4351
  }
4387
4352
  const relative2 = placement?.files.get(variant.scale);
4388
- if (relative2 && dest) return (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(dest.directory, relative2));
4353
+ if (relative2 && dest) return (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(dest.directory, relative2));
4389
4354
  if (placement && placement.files.size > 0) return null;
4390
4355
  if (placement && placement.ambiguous.length > 0 && dest) {
4391
4356
  throw new Error(
@@ -4414,7 +4379,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4414
4379
  );
4415
4380
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
4416
4381
  throw new Error(
4417
- `${command} could not read ${(0, import_node_path15.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Rebuild with \`react-native bundle --assets-dest\`.`
4382
+ `${command} could not read ${(0, import_node_path16.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Rebuild with \`react-native bundle --assets-dest\`.`
4418
4383
  );
4419
4384
  });
4420
4385
  return {
@@ -4560,13 +4525,13 @@ async function createCloudBox(options) {
4560
4525
  warnings: artifact.warnings
4561
4526
  };
4562
4527
  }
4563
- var import_node_crypto6, import_node_fs14, import_node_path15, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4528
+ var import_node_crypto6, import_node_fs15, import_node_path16, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4564
4529
  var init_cloud_client = __esm({
4565
4530
  "cli/cloud-client.ts"() {
4566
4531
  "use strict";
4567
4532
  import_node_crypto6 = require("node:crypto");
4568
- import_node_fs14 = require("node:fs");
4569
- import_node_path15 = require("node:path");
4533
+ import_node_fs15 = require("node:fs");
4534
+ import_node_path16 = require("node:path");
4570
4535
  init_metroAssetArtifact();
4571
4536
  init_metroCloudArtifact();
4572
4537
  init_metro_fingerprint_registry_client();
@@ -5962,6 +5927,15 @@ async function scanDevServers(opts = {}) {
5962
5927
  // src/host/bridge-host.ts
5963
5928
  init_backend_origin();
5964
5929
 
5930
+ // src/automatic-update-policy.ts
5931
+ var import_node_fs4 = require("node:fs");
5932
+ var import_node_path5 = require("node:path");
5933
+ init_home_paths();
5934
+ function automaticPeachUpdatesEnabled(env = process.env) {
5935
+ const value = env.PEACH_UPDATE_CHECK?.toLowerCase();
5936
+ return value !== "0" && value !== "false" && value !== "off" && !(0, import_node_fs4.existsSync)((0, import_node_path5.join)(rnxHomeDir(), "runtime-update-disabled"));
5937
+ }
5938
+
5965
5939
  // src/bridge-constants.ts
5966
5940
  var DEFAULT_SOOTSIM_BRIDGE_PORT = 7668;
5967
5941
  var DEFAULT_SOOTSIM_BRIDGE_URL = `http://localhost:${DEFAULT_SOOTSIM_BRIDGE_PORT}/`;
@@ -5970,7 +5944,7 @@ var SOOTSIM_BRIDGE_SIM_CLOSE_REASON = "sootsim close";
5970
5944
  var AUTOMATION_SIM_IDLE_REAP_TTL_MS = 5 * 6e4;
5971
5945
 
5972
5946
  // src/cli-version.ts
5973
- var import_node_fs3 = require("node:fs");
5947
+ var import_node_fs5 = require("node:fs");
5974
5948
  var import_node_url2 = require("node:url");
5975
5949
  init_public_brand();
5976
5950
  var import_meta = {};
@@ -5987,7 +5961,7 @@ function getCliVersion() {
5987
5961
  ];
5988
5962
  for (const resolve5 of candidates) {
5989
5963
  try {
5990
- const version = JSON.parse((0, import_node_fs3.readFileSync)(resolve5(), "utf8")).version;
5964
+ const version = JSON.parse((0, import_node_fs5.readFileSync)(resolve5(), "utf8")).version;
5991
5965
  if (typeof version === "string" && version) {
5992
5966
  cached2 = version;
5993
5967
  return cached2;
@@ -6011,27 +5985,27 @@ var import_url = require("url");
6011
5985
  // ../contrast-runtime-delivery/src/index.ts
6012
5986
  var import_node_child_process2 = require("node:child_process");
6013
5987
  var import_node_crypto2 = __toESM(require("node:crypto"), 1);
6014
- var import_node_fs6 = __toESM(require("node:fs"), 1);
5988
+ var import_node_fs7 = __toESM(require("node:fs"), 1);
6015
5989
  var import_node_os2 = __toESM(require("node:os"), 1);
6016
- var import_node_path6 = __toESM(require("node:path"), 1);
5990
+ var import_node_path7 = __toESM(require("node:path"), 1);
6017
5991
  var import_node_stream = require("node:stream");
6018
5992
  var import_promises3 = require("node:stream/promises");
6019
5993
 
6020
5994
  // ../contrast-runtime-delivery/src/product.ts
6021
- var import_node_fs5 = __toESM(require("node:fs"), 1);
6022
- var import_node_path5 = __toESM(require("node:path"), 1);
5995
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
5996
+ var import_node_path6 = __toESM(require("node:path"), 1);
6023
5997
  function isValidRuntimeVersion(value) {
6024
5998
  return value.length <= 100 && /^[0-9A-Za-z][0-9A-Za-z._+-]*$/.test(value);
6025
5999
  }
6026
6000
  function listInstalledRuntimes(product) {
6027
6001
  try {
6028
- return import_node_fs5.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
6002
+ return import_node_fs6.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
6029
6003
  } catch {
6030
6004
  return [];
6031
6005
  }
6032
6006
  }
6033
6007
  function runtimeTarballCacheName(product, version) {
6034
- return import_node_path5.default.posix.basename(product.tarballPath(version));
6008
+ return import_node_path6.default.posix.basename(product.tarballPath(version));
6035
6009
  }
6036
6010
  function compareSemver(a, b) {
6037
6011
  const parse2 = (v) => {
@@ -6061,7 +6035,7 @@ function createRuntimeDelivery(product) {
6061
6035
  function readConfig() {
6062
6036
  try {
6063
6037
  const parsed = JSON.parse(
6064
- import_node_fs6.default.readFileSync(product.configFile(), "utf8")
6038
+ import_node_fs7.default.readFileSync(product.configFile(), "utf8")
6065
6039
  );
6066
6040
  return parsed && typeof parsed === "object" ? parsed : {};
6067
6041
  } catch {
@@ -6134,7 +6108,7 @@ function createRuntimeDelivery(product) {
6134
6108
  const setActive = opts.setActive !== false;
6135
6109
  const protectVersions = [version, ...opts.protectVersions ?? []];
6136
6110
  pruneLocalRetention({ protectVersions });
6137
- if (!opts.force && import_node_fs6.default.existsSync(import_node_path6.default.join(destDir, product.installedMarker))) {
6111
+ if (!opts.force && import_node_fs7.default.existsSync(import_node_path7.default.join(destDir, product.installedMarker))) {
6138
6112
  if (setActive) product.writeActiveRuntime(version);
6139
6113
  pruneLocalRetention({ protectVersions });
6140
6114
  return {
@@ -6148,18 +6122,18 @@ function createRuntimeDelivery(product) {
6148
6122
  };
6149
6123
  }
6150
6124
  const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
6151
- const downloadDir = import_node_fs6.default.mkdtempSync(
6152
- import_node_path6.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6125
+ const downloadDir = import_node_fs7.default.mkdtempSync(
6126
+ import_node_path7.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6153
6127
  );
6154
- const runtimeArchivePath = import_node_path6.default.join(
6128
+ const runtimeArchivePath = import_node_path7.default.join(
6155
6129
  downloadDir,
6156
6130
  runtimeTarballCacheName(product, version)
6157
6131
  );
6158
- const tmpDir = import_node_path6.default.join(
6159
- import_node_path6.default.dirname(destDir),
6132
+ const tmpDir = import_node_path7.default.join(
6133
+ import_node_path7.default.dirname(destDir),
6160
6134
  `.installing-${version}-${process.pid}`
6161
6135
  );
6162
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6136
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6163
6137
  try {
6164
6138
  if (!opts.quiet)
6165
6139
  process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
@@ -6174,20 +6148,20 @@ function createRuntimeDelivery(product) {
6174
6148
  `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
6175
6149
  );
6176
6150
  }
6177
- import_node_fs6.default.mkdirSync(tmpDir, { recursive: true });
6151
+ import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
6178
6152
  await extractTarball(runtimeArchivePath, tmpDir);
6179
- if (!import_node_fs6.default.existsSync(import_node_path6.default.join(tmpDir, product.installedMarker))) {
6153
+ if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, product.installedMarker))) {
6180
6154
  throw new Error(
6181
6155
  `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
6182
6156
  );
6183
6157
  }
6184
- import_node_fs6.default.rmSync(destDir, { recursive: true, force: true });
6185
- import_node_fs6.default.renameSync(tmpDir, destDir);
6158
+ import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
6159
+ import_node_fs7.default.renameSync(tmpDir, destDir);
6186
6160
  } catch (err) {
6187
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6161
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6188
6162
  throw err;
6189
6163
  } finally {
6190
- import_node_fs6.default.rmSync(downloadDir, { recursive: true, force: true });
6164
+ import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
6191
6165
  }
6192
6166
  if (setActive) product.writeActiveRuntime(version);
6193
6167
  pruneLocalRetention({ protectVersions });
@@ -6209,8 +6183,8 @@ function createRuntimeDelivery(product) {
6209
6183
  const pin = resolvePin();
6210
6184
  if (pin) {
6211
6185
  const activeVersion2 = product.readActiveRuntime();
6212
- const pinInstalled = import_node_fs6.default.existsSync(
6213
- import_node_path6.default.join(product.runtimeDir(pin), product.installedMarker)
6186
+ const pinInstalled = import_node_fs7.default.existsSync(
6187
+ import_node_path7.default.join(product.runtimeDir(pin), product.installedMarker)
6214
6188
  );
6215
6189
  if (activeVersion2 === pin && pinInstalled) {
6216
6190
  return {
@@ -6259,7 +6233,7 @@ function createRuntimeDelivery(product) {
6259
6233
  }
6260
6234
  const activeVersion = product.readActiveRuntime();
6261
6235
  const activeDir = activeVersion ? product.runtimeDir(activeVersion) : null;
6262
- const activeInstalled = activeDir ? import_node_fs6.default.existsSync(import_node_path6.default.join(activeDir, product.installedMarker)) : false;
6236
+ const activeInstalled = activeDir ? import_node_fs7.default.existsSync(import_node_path7.default.join(activeDir, product.installedMarker)) : false;
6263
6237
  const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
6264
6238
  if (!shouldInstall) {
6265
6239
  return {
@@ -6334,12 +6308,12 @@ function createRuntimeDelivery(product) {
6334
6308
  let removeCacheFiles = [];
6335
6309
  if (markerOffset >= 0) {
6336
6310
  try {
6337
- removeCacheFiles = import_node_fs6.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6311
+ removeCacheFiles = import_node_fs7.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6338
6312
  if (!entry.isFile()) return false;
6339
6313
  const complete = entry.name.startsWith(cachePrefix) && entry.name.endsWith(cacheSuffix);
6340
6314
  const partial = entry.name.startsWith(cachePrefix) && entry.name.endsWith(`${cacheSuffix}.partial`);
6341
6315
  return complete || partial;
6342
- }).map((entry) => import_node_path6.default.join(product.cacheDir(), entry.name)).sort();
6316
+ }).map((entry) => import_node_path7.default.join(product.cacheDir(), entry.name)).sort();
6343
6317
  } catch {
6344
6318
  }
6345
6319
  }
@@ -6354,10 +6328,10 @@ function createRuntimeDelivery(product) {
6354
6328
  function pruneLocalRetention(opts = {}) {
6355
6329
  const plan = planLocalRetention(opts);
6356
6330
  for (const version of plan.removeVersions) {
6357
- import_node_fs6.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6331
+ import_node_fs7.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6358
6332
  }
6359
6333
  for (const cacheFile of plan.removeCacheFiles) {
6360
- import_node_fs6.default.rmSync(cacheFile, { force: true });
6334
+ import_node_fs7.default.rmSync(cacheFile, { force: true });
6361
6335
  }
6362
6336
  return plan;
6363
6337
  }
@@ -6383,17 +6357,17 @@ async function downloadToFile(url, destPath) {
6383
6357
  if (!res.ok || !res.body) {
6384
6358
  throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`);
6385
6359
  }
6386
- import_node_fs6.default.mkdirSync(import_node_path6.default.dirname(destPath), { recursive: true });
6360
+ import_node_fs7.default.mkdirSync(import_node_path7.default.dirname(destPath), { recursive: true });
6387
6361
  const tmp = `${destPath}.partial`;
6388
6362
  try {
6389
6363
  await (0, import_promises3.pipeline)(
6390
6364
  import_node_stream.Readable.fromWeb(res.body),
6391
- import_node_fs6.default.createWriteStream(tmp)
6365
+ import_node_fs7.default.createWriteStream(tmp)
6392
6366
  );
6393
- import_node_fs6.default.renameSync(tmp, destPath);
6367
+ import_node_fs7.default.renameSync(tmp, destPath);
6394
6368
  } catch (err) {
6395
6369
  try {
6396
- import_node_fs6.default.unlinkSync(tmp);
6370
+ import_node_fs7.default.unlinkSync(tmp);
6397
6371
  } catch {
6398
6372
  }
6399
6373
  throw err;
@@ -6402,7 +6376,7 @@ async function downloadToFile(url, destPath) {
6402
6376
  function sha256File(filePath) {
6403
6377
  return new Promise((resolve5, reject) => {
6404
6378
  const hash = import_node_crypto2.default.createHash("sha256");
6405
- const stream = import_node_fs6.default.createReadStream(filePath);
6379
+ const stream = import_node_fs7.default.createReadStream(filePath);
6406
6380
  stream.on("data", (chunk) => hash.update(chunk));
6407
6381
  stream.on("error", reject);
6408
6382
  stream.on("end", () => resolve5(hash.digest("hex")));
@@ -6551,19 +6525,19 @@ var rnxRuntime = createRuntimeDelivery(RNX_RUNTIME_PRODUCT);
6551
6525
 
6552
6526
  // src/host/agent-host.ts
6553
6527
  var import_node_crypto5 = require("node:crypto");
6554
- var import_node_fs10 = __toESM(require("node:fs"), 1);
6555
- var import_node_path10 = __toESM(require("node:path"), 1);
6528
+ var import_node_fs11 = __toESM(require("node:fs"), 1);
6529
+ var import_node_path11 = __toESM(require("node:path"), 1);
6556
6530
 
6557
6531
  // src/agent-sessions.ts
6558
6532
  var import_node_child_process3 = require("node:child_process");
6559
6533
  var import_node_crypto4 = require("node:crypto");
6560
- var import_node_fs9 = __toESM(require("node:fs"), 1);
6561
- var import_node_path9 = __toESM(require("node:path"), 1);
6534
+ var import_node_fs10 = __toESM(require("node:fs"), 1);
6535
+ var import_node_path10 = __toESM(require("node:path"), 1);
6562
6536
  var import_node_readline = __toESM(require("node:readline"), 1);
6563
6537
 
6564
6538
  // cli/self-invocation.ts
6565
- var import_node_fs7 = require("node:fs");
6566
- var import_node_path7 = require("node:path");
6539
+ var import_node_fs8 = require("node:fs");
6540
+ var import_node_path8 = require("node:path");
6567
6541
  var import_node_url3 = require("node:url");
6568
6542
  init_public_brand();
6569
6543
 
@@ -6573,14 +6547,14 @@ var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_S
6573
6547
  // cli/self-invocation.ts
6574
6548
  function sourceEntryPath() {
6575
6549
  try {
6576
- const candidate = (0, import_node_path7.join)((0, import_node_path7.dirname)((0, import_node_url3.fileURLToPath)(__sootsim_import_meta_url)), "bin.ts");
6577
- return (0, import_node_fs7.existsSync)(candidate) ? candidate : null;
6550
+ const candidate = (0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_url3.fileURLToPath)(__sootsim_import_meta_url)), "bin.ts");
6551
+ return (0, import_node_fs8.existsSync)(candidate) ? candidate : null;
6578
6552
  } catch {
6579
6553
  return null;
6580
6554
  }
6581
6555
  }
6582
6556
  function isCliEntry(path12) {
6583
- const name2 = (0, import_node_path7.basename)(path12);
6557
+ const name2 = (0, import_node_path8.basename)(path12);
6584
6558
  return name2 === "bin.ts" || name2 === "bin.js";
6585
6559
  }
6586
6560
  function rnxSelfInvocation() {
@@ -6640,8 +6614,8 @@ function encodeAgentPromptEnvelope(input) {
6640
6614
 
6641
6615
  // src/attached-projects.ts
6642
6616
  var import_node_crypto3 = require("node:crypto");
6643
- var import_node_fs8 = __toESM(require("node:fs"), 1);
6644
- var import_node_path8 = __toESM(require("node:path"), 1);
6617
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
6618
+ var import_node_path9 = __toESM(require("node:path"), 1);
6645
6619
  init_home_paths();
6646
6620
  var overrideDir = null;
6647
6621
  function userDataDir() {
@@ -6654,7 +6628,7 @@ function getUserDataDir() {
6654
6628
  return userDataDir();
6655
6629
  }
6656
6630
  function storeFile() {
6657
- return import_node_path8.default.join(userDataDir(), "attached-projects.json");
6631
+ return import_node_path9.default.join(userDataDir(), "attached-projects.json");
6658
6632
  }
6659
6633
  function cloneEmpty() {
6660
6634
  return {
@@ -6668,7 +6642,7 @@ function loadStore() {
6668
6642
  const file = storeFile();
6669
6643
  let raw;
6670
6644
  try {
6671
- raw = import_node_fs8.default.readFileSync(file, "utf8");
6645
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
6672
6646
  } catch (err) {
6673
6647
  if (err.code === "ENOENT") return cloneEmpty();
6674
6648
  throw err;
@@ -6685,7 +6659,7 @@ function loadStore() {
6685
6659
  } catch (err) {
6686
6660
  const quarantine = `${file}.corrupt-${Date.now()}`;
6687
6661
  try {
6688
- import_node_fs8.default.renameSync(file, quarantine);
6662
+ import_node_fs9.default.renameSync(file, quarantine);
6689
6663
  console.warn(
6690
6664
  `[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
6691
6665
  );
@@ -6696,16 +6670,16 @@ function loadStore() {
6696
6670
  }
6697
6671
  function writeStore(store) {
6698
6672
  const file = storeFile();
6699
- import_node_fs8.default.mkdirSync(import_node_path8.default.dirname(file), { recursive: true });
6673
+ import_node_fs9.default.mkdirSync(import_node_path9.default.dirname(file), { recursive: true });
6700
6674
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
6701
- const fd = import_node_fs8.default.openSync(tmp, "w", 384);
6675
+ const fd = import_node_fs9.default.openSync(tmp, "w", 384);
6702
6676
  try {
6703
- import_node_fs8.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6704
- import_node_fs8.default.fsyncSync(fd);
6677
+ import_node_fs9.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6678
+ import_node_fs9.default.fsyncSync(fd);
6705
6679
  } finally {
6706
- import_node_fs8.default.closeSync(fd);
6680
+ import_node_fs9.default.closeSync(fd);
6707
6681
  }
6708
- import_node_fs8.default.renameSync(tmp, file);
6682
+ import_node_fs9.default.renameSync(tmp, file);
6709
6683
  }
6710
6684
  function mutateStore(fn) {
6711
6685
  const store = loadStore();
@@ -6714,13 +6688,13 @@ function mutateStore(fn) {
6714
6688
  return store;
6715
6689
  }
6716
6690
  function projectIdForCwd(cwd) {
6717
- return (0, import_node_crypto3.createHash)("sha256").update(import_node_path8.default.resolve(cwd)).digest("hex").slice(0, 16);
6691
+ return (0, import_node_crypto3.createHash)("sha256").update(import_node_path9.default.resolve(cwd)).digest("hex").slice(0, 16);
6718
6692
  }
6719
6693
  function newSessionId() {
6720
6694
  return `s_${(0, import_node_crypto3.randomBytes)(10).toString("hex")}`;
6721
6695
  }
6722
6696
  function upsertProject(input) {
6723
- const cwd = import_node_path8.default.resolve(input.cwd);
6697
+ const cwd = import_node_path9.default.resolve(input.cwd);
6724
6698
  const id = projectIdForCwd(cwd);
6725
6699
  let result;
6726
6700
  mutateStore((store) => {
@@ -6746,7 +6720,7 @@ function upsertProject(input) {
6746
6720
  const now = Date.now();
6747
6721
  const created = {
6748
6722
  id,
6749
- name: input.name ?? import_node_path8.default.basename(cwd),
6723
+ name: input.name ?? import_node_path9.default.basename(cwd),
6750
6724
  cwd,
6751
6725
  repoRoot: input.repoRoot,
6752
6726
  sourceRoots: input.sourceRoots ?? [cwd],
@@ -6892,8 +6866,8 @@ async function seedFromDemoAppRegistry() {
6892
6866
  if (apps.length === 0) return;
6893
6867
  mutateStore((store) => {
6894
6868
  for (const app of apps) {
6895
- if (!import_node_fs8.default.existsSync(app.dir)) continue;
6896
- const cwd = import_node_path8.default.resolve(app.dir);
6869
+ if (!import_node_fs9.default.existsSync(app.dir)) continue;
6870
+ const cwd = import_node_path9.default.resolve(app.dir);
6897
6871
  const id = projectIdForCwd(cwd);
6898
6872
  if (store.attachedProjects.some((p) => p.id === id)) continue;
6899
6873
  const now = Date.now();
@@ -6918,16 +6892,16 @@ async function seedFromDemoAppRegistry() {
6918
6892
  // src/agent-sessions.ts
6919
6893
  init_public_brand();
6920
6894
  function sessionDir(sessionId) {
6921
- return import_node_path9.default.join(getUserDataDir(), "sessions", sessionId);
6895
+ return import_node_path10.default.join(getUserDataDir(), "sessions", sessionId);
6922
6896
  }
6923
6897
  function promptFifoPath(sessionId) {
6924
- return import_node_path9.default.join(sessionDir(sessionId), "prompt.in");
6898
+ return import_node_path10.default.join(sessionDir(sessionId), "prompt.in");
6925
6899
  }
6926
6900
  function eventsFifoPath(sessionId) {
6927
- return import_node_path9.default.join(sessionDir(sessionId), "events.out");
6901
+ return import_node_path10.default.join(sessionDir(sessionId), "events.out");
6928
6902
  }
6929
6903
  function transcriptPath(sessionId) {
6930
- return import_node_path9.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6904
+ return import_node_path10.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6931
6905
  }
6932
6906
  function pidIsAlive(pid, sessionId) {
6933
6907
  if (!pid) return false;
@@ -6937,7 +6911,7 @@ function pidIsAlive(pid, sessionId) {
6937
6911
  return false;
6938
6912
  }
6939
6913
  if (sessionId) {
6940
- if (!import_node_fs9.default.existsSync(sessionDir(sessionId))) return false;
6914
+ if (!import_node_fs10.default.existsSync(sessionDir(sessionId))) return false;
6941
6915
  }
6942
6916
  return true;
6943
6917
  }
@@ -6950,11 +6924,11 @@ function resolveSootsimInvocation() {
6950
6924
  const resourcesPath = process.resourcesPath;
6951
6925
  if (resourcesPath) {
6952
6926
  const candidates = [
6953
- import_node_path9.default.join(resourcesPath, "bin", "sootsim"),
6954
- import_node_path9.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6927
+ import_node_path10.default.join(resourcesPath, "bin", "sootsim"),
6928
+ import_node_path10.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6955
6929
  ];
6956
6930
  for (const c of candidates) {
6957
- if (import_node_fs9.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6931
+ if (import_node_fs10.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6958
6932
  }
6959
6933
  }
6960
6934
  }
@@ -6973,15 +6947,15 @@ function tryWorkspaceSootsim() {
6973
6947
  const sootsimDir = resolveSootsimPackageDir();
6974
6948
  if (!sootsimDir) return null;
6975
6949
  const binaryName = `peach-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`;
6976
- const distBinary = import_node_path9.default.join(sootsimDir, "dist-bin", binaryName);
6977
- if (import_node_fs9.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
6978
- const distBin = import_node_path9.default.join(sootsimDir, "dist-cli", "bin.js");
6979
- if (import_node_fs9.default.existsSync(distBin)) {
6950
+ const distBinary = import_node_path10.default.join(sootsimDir, "dist-bin", binaryName);
6951
+ if (import_node_fs10.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
6952
+ const distBin = import_node_path10.default.join(sootsimDir, "dist-cli", "bin.js");
6953
+ if (import_node_fs10.default.existsSync(distBin)) {
6980
6954
  try {
6981
- const src = import_node_path9.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
6982
- if (import_node_fs9.default.existsSync(src)) {
6983
- const srcMtime = import_node_fs9.default.statSync(src).mtimeMs;
6984
- const buildMtime = import_node_fs9.default.statSync(distBin).mtimeMs;
6955
+ const src = import_node_path10.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
6956
+ if (import_node_fs10.default.existsSync(src)) {
6957
+ const srcMtime = import_node_fs10.default.statSync(src).mtimeMs;
6958
+ const buildMtime = import_node_fs10.default.statSync(distBin).mtimeMs;
6985
6959
  if (buildMtime < srcMtime) {
6986
6960
  console.warn(
6987
6961
  `[peach] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/peachsim build:cli\`.`
@@ -7000,22 +6974,22 @@ function tryWorkspaceSootsim() {
7000
6974
  function resolveSootsimPackageDir() {
7001
6975
  try {
7002
6976
  const resolved = require.resolve(`${rnxPublicBrand.packageName}/package.json`);
7003
- return import_node_path9.default.dirname(resolved);
6977
+ return import_node_path10.default.dirname(resolved);
7004
6978
  } catch {
7005
6979
  }
7006
6980
  const here = fileFromImportMeta();
7007
6981
  if (!here) return null;
7008
- let cur = import_node_path9.default.dirname(here);
6982
+ let cur = import_node_path10.default.dirname(here);
7009
6983
  for (let i = 0; i < 8; i++) {
7010
- const pkg = import_node_path9.default.join(cur, "package.json");
6984
+ const pkg = import_node_path10.default.join(cur, "package.json");
7011
6985
  try {
7012
- if (import_node_fs9.default.existsSync(pkg)) {
7013
- const parsed = JSON.parse(import_node_fs9.default.readFileSync(pkg, "utf8"));
6986
+ if (import_node_fs10.default.existsSync(pkg)) {
6987
+ const parsed = JSON.parse(import_node_fs10.default.readFileSync(pkg, "utf8"));
7014
6988
  if (parsed.name === rnxPublicBrand.packageName) return cur;
7015
6989
  }
7016
6990
  } catch {
7017
6991
  }
7018
- const parent = import_node_path9.default.dirname(cur);
6992
+ const parent = import_node_path10.default.dirname(cur);
7019
6993
  if (parent === cur) break;
7020
6994
  cur = parent;
7021
6995
  }
@@ -7031,28 +7005,28 @@ function fileFromImportMeta() {
7031
7005
  }
7032
7006
  }
7033
7007
  async function withStartLock(projectId, provider, fn) {
7034
- const lockDir = import_node_path9.default.join(getUserDataDir(), "locks");
7035
- import_node_fs9.default.mkdirSync(lockDir, { recursive: true });
7008
+ const lockDir = import_node_path10.default.join(getUserDataDir(), "locks");
7009
+ import_node_fs10.default.mkdirSync(lockDir, { recursive: true });
7036
7010
  try {
7037
- import_node_fs9.default.chmodSync(lockDir, 448);
7011
+ import_node_fs10.default.chmodSync(lockDir, 448);
7038
7012
  } catch {
7039
7013
  }
7040
- const lockPath = import_node_path9.default.join(lockDir, `start-${projectId}-${provider}.lock`);
7014
+ const lockPath = import_node_path10.default.join(lockDir, `start-${projectId}-${provider}.lock`);
7041
7015
  const deadline = Date.now() + 4e3;
7042
7016
  let fd = null;
7043
7017
  while (fd === null) {
7044
7018
  try {
7045
- fd = import_node_fs9.default.openSync(
7019
+ fd = import_node_fs10.default.openSync(
7046
7020
  lockPath,
7047
- import_node_fs9.constants.O_WRONLY | import_node_fs9.constants.O_CREAT | import_node_fs9.constants.O_EXCL,
7021
+ import_node_fs10.constants.O_WRONLY | import_node_fs10.constants.O_CREAT | import_node_fs10.constants.O_EXCL,
7048
7022
  384
7049
7023
  );
7050
7024
  } catch (err) {
7051
7025
  if (err.code !== "EEXIST") throw err;
7052
7026
  try {
7053
- const stale = Number(import_node_fs9.default.readFileSync(lockPath, "utf8").trim());
7027
+ const stale = Number(import_node_fs10.default.readFileSync(lockPath, "utf8").trim());
7054
7028
  if (stale && !isProcessAlive(stale)) {
7055
- import_node_fs9.default.unlinkSync(lockPath);
7029
+ import_node_fs10.default.unlinkSync(lockPath);
7056
7030
  continue;
7057
7031
  }
7058
7032
  } catch {
@@ -7066,15 +7040,15 @@ async function withStartLock(projectId, provider, fn) {
7066
7040
  }
7067
7041
  }
7068
7042
  try {
7069
- import_node_fs9.default.writeFileSync(fd, String(process.pid));
7043
+ import_node_fs10.default.writeFileSync(fd, String(process.pid));
7070
7044
  return await fn();
7071
7045
  } finally {
7072
7046
  try {
7073
- import_node_fs9.default.closeSync(fd);
7047
+ import_node_fs10.default.closeSync(fd);
7074
7048
  } catch {
7075
7049
  }
7076
7050
  try {
7077
- import_node_fs9.default.unlinkSync(lockPath);
7051
+ import_node_fs10.default.unlinkSync(lockPath);
7078
7052
  } catch {
7079
7053
  }
7080
7054
  }
@@ -7088,25 +7062,25 @@ function isProcessAlive(pid) {
7088
7062
  }
7089
7063
  }
7090
7064
  function mkfifoSync(p) {
7091
- const parent = import_node_path9.default.dirname(p);
7092
- import_node_fs9.default.mkdirSync(parent, { recursive: true });
7065
+ const parent = import_node_path10.default.dirname(p);
7066
+ import_node_fs10.default.mkdirSync(parent, { recursive: true });
7093
7067
  try {
7094
- import_node_fs9.default.chmodSync(parent, 448);
7068
+ import_node_fs10.default.chmodSync(parent, 448);
7095
7069
  } catch {
7096
7070
  }
7097
- if (import_node_fs9.default.existsSync(p)) {
7071
+ if (import_node_fs10.default.existsSync(p)) {
7098
7072
  try {
7099
- const stat2 = import_node_fs9.default.statSync(p);
7073
+ const stat2 = import_node_fs10.default.statSync(p);
7100
7074
  if (stat2.isFIFO()) {
7101
7075
  try {
7102
- import_node_fs9.default.chmodSync(p, 384);
7076
+ import_node_fs10.default.chmodSync(p, 384);
7103
7077
  } catch {
7104
7078
  }
7105
7079
  return;
7106
7080
  }
7107
- import_node_fs9.default.unlinkSync(p);
7081
+ import_node_fs10.default.unlinkSync(p);
7108
7082
  } catch {
7109
- import_node_fs9.default.unlinkSync(p);
7083
+ import_node_fs10.default.unlinkSync(p);
7110
7084
  }
7111
7085
  }
7112
7086
  const result = (0, import_node_child_process3.spawnSync)("mkfifo", ["-m", "600", p]);
@@ -7153,10 +7127,10 @@ async function startSession(opts) {
7153
7127
  const transcript = transcriptPath(session.id);
7154
7128
  mkfifoSync(promptIn);
7155
7129
  mkfifoSync(eventsOut);
7156
- const transcriptDir = import_node_path9.default.dirname(transcript);
7157
- import_node_fs9.default.mkdirSync(transcriptDir, { recursive: true });
7130
+ const transcriptDir = import_node_path10.default.dirname(transcript);
7131
+ import_node_fs10.default.mkdirSync(transcriptDir, { recursive: true });
7158
7132
  try {
7159
- import_node_fs9.default.chmodSync(transcriptDir, 448);
7133
+ import_node_fs10.default.chmodSync(transcriptDir, 448);
7160
7134
  } catch {
7161
7135
  }
7162
7136
  const { executable, prefixArgs } = resolveSootsimInvocation();
@@ -7207,7 +7181,7 @@ async function startSession(opts) {
7207
7181
  }
7208
7182
  }
7209
7183
  try {
7210
- import_node_fs9.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7184
+ import_node_fs10.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7211
7185
  } catch {
7212
7186
  }
7213
7187
  updateSessionStatus(session.id, { status: "ended" });
@@ -7235,18 +7209,18 @@ async function sendPrompt(sessionId, prompt) {
7235
7209
  );
7236
7210
  }
7237
7211
  const fifo = promptFifoPath(sessionId);
7238
- if (!import_node_fs9.default.existsSync(fifo)) {
7212
+ if (!import_node_fs10.default.existsSync(fifo)) {
7239
7213
  throw new AgentSessionError("NO_FIFO", `prompt FIFO missing: ${fifo}`);
7240
7214
  }
7241
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_WRONLY);
7215
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_WRONLY);
7242
7216
  try {
7243
7217
  const wireText = encodeAgentPromptEnvelope(prompt);
7244
7218
  if (!wireText) {
7245
7219
  throw new AgentSessionError("EMPTY_PROMPT", "prompt text is empty");
7246
7220
  }
7247
- import_node_fs9.default.writeSync(fd, wireText + "\n");
7221
+ import_node_fs10.default.writeSync(fd, wireText + "\n");
7248
7222
  } finally {
7249
- import_node_fs9.default.closeSync(fd);
7223
+ import_node_fs10.default.closeSync(fd);
7250
7224
  }
7251
7225
  updateSessionStatus(sessionId, {
7252
7226
  lastPrompt: prompt.displayText ?? prompt.text,
@@ -7268,7 +7242,7 @@ async function endSession(sessionId) {
7268
7242
  const base = getUserDataDir();
7269
7243
  if (dir.startsWith(base)) {
7270
7244
  try {
7271
- import_node_fs9.default.rmSync(dir, { recursive: true, force: true });
7245
+ import_node_fs10.default.rmSync(dir, { recursive: true, force: true });
7272
7246
  } catch {
7273
7247
  }
7274
7248
  }
@@ -7276,11 +7250,11 @@ async function endSession(sessionId) {
7276
7250
  }
7277
7251
  function subscribeEvents(sessionId, onEvent) {
7278
7252
  const fifo = eventsFifoPath(sessionId);
7279
- if (!import_node_fs9.default.existsSync(fifo)) {
7253
+ if (!import_node_fs10.default.existsSync(fifo)) {
7280
7254
  throw new AgentSessionError("NO_FIFO", `events FIFO missing: ${fifo}`);
7281
7255
  }
7282
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_RDWR);
7283
- const stream = import_node_fs9.default.createReadStream("", { fd, autoClose: true });
7256
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR);
7257
+ const stream = import_node_fs10.default.createReadStream("", { fd, autoClose: true });
7284
7258
  const rl = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
7285
7259
  rl.on("line", (line) => {
7286
7260
  const event = parseAgentEventLine(line);
@@ -7291,7 +7265,7 @@ function subscribeEvents(sessionId, onEvent) {
7291
7265
  if (closed) return;
7292
7266
  closed = true;
7293
7267
  try {
7294
- import_node_fs9.default.writeSync(fd, "\n");
7268
+ import_node_fs10.default.writeSync(fd, "\n");
7295
7269
  } catch {
7296
7270
  }
7297
7271
  try {
@@ -7305,7 +7279,7 @@ function subscribeEvents(sessionId, onEvent) {
7305
7279
  };
7306
7280
  }
7307
7281
  async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7308
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_RDWR | import_node_fs9.constants.O_NONBLOCK);
7282
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR | import_node_fs10.constants.O_NONBLOCK);
7309
7283
  const buf = Buffer.alloc(8192);
7310
7284
  let leftover = "";
7311
7285
  const deadline = Date.now() + timeoutMs;
@@ -7313,7 +7287,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7313
7287
  while (Date.now() < deadline) {
7314
7288
  let n = 0;
7315
7289
  try {
7316
- n = import_node_fs9.default.readSync(fd, buf, 0, buf.length, null);
7290
+ n = import_node_fs10.default.readSync(fd, buf, 0, buf.length, null);
7317
7291
  } catch (err) {
7318
7292
  if (err.code !== "EAGAIN") throw err;
7319
7293
  n = 0;
@@ -7333,7 +7307,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7333
7307
  }
7334
7308
  return null;
7335
7309
  } finally {
7336
- import_node_fs9.default.closeSync(fd);
7310
+ import_node_fs10.default.closeSync(fd);
7337
7311
  }
7338
7312
  }
7339
7313
 
@@ -7587,7 +7561,7 @@ var AgentHost = class {
7587
7561
  );
7588
7562
  const project = upsertProject({
7589
7563
  cwd: match.cwd,
7590
- name: match.projectName ?? import_node_path10.default.basename(match.cwd),
7564
+ name: match.projectName ?? import_node_path11.default.basename(match.cwd),
7591
7565
  preferredProvider: input.provider ?? existing?.preferredProvider,
7592
7566
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
7593
7567
  knownBundleUrls,
@@ -7598,18 +7572,18 @@ var AgentHost = class {
7598
7572
  }
7599
7573
  getTranscript(sessionId) {
7600
7574
  const p = transcriptPath(sessionId);
7601
- if (!import_node_fs10.default.existsSync(p)) {
7575
+ if (!import_node_fs11.default.existsSync(p)) {
7602
7576
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
7603
7577
  }
7604
- return import_node_fs10.default.readFileSync(p, "utf8");
7578
+ return import_node_fs11.default.readFileSync(p, "utf8");
7605
7579
  }
7606
7580
  getPaths() {
7607
7581
  const dir = getUserDataDir();
7608
7582
  return {
7609
7583
  userDataDir: dir,
7610
- storeFile: import_node_path10.default.join(dir, "attached-projects.json"),
7611
- sessionsDir: import_node_path10.default.join(dir, "sessions"),
7612
- transcriptsDir: import_node_path10.default.join(dir, "transcripts")
7584
+ storeFile: import_node_path11.default.join(dir, "attached-projects.json"),
7585
+ sessionsDir: import_node_path11.default.join(dir, "sessions"),
7586
+ transcriptsDir: import_node_path11.default.join(dir, "transcripts")
7613
7587
  };
7614
7588
  }
7615
7589
  // --- subscription management ---
@@ -8316,8 +8290,8 @@ async function openUrl(url, options = {}) {
8316
8290
  }
8317
8291
 
8318
8292
  // src/host/plane-host.ts
8319
- var import_node_fs12 = __toESM(require("node:fs"), 1);
8320
- var import_node_path12 = __toESM(require("node:path"), 1);
8293
+ var import_node_fs13 = __toESM(require("node:fs"), 1);
8294
+ var import_node_path13 = __toESM(require("node:path"), 1);
8321
8295
 
8322
8296
  // ../peach-box/src/planeProtocol.ts
8323
8297
  var PLANE_FLAG_READ_ONLY = 1;
@@ -8397,8 +8371,8 @@ async function dispatchPlaneCommand(plane, type, msg, mutationOptions) {
8397
8371
 
8398
8372
  // cli/commands/box/checkout-plane.ts
8399
8373
  var import_node_child_process4 = require("node:child_process");
8400
- var import_node_fs11 = __toESM(require("node:fs"), 1);
8401
- var import_node_path11 = __toESM(require("node:path"), 1);
8374
+ var import_node_fs12 = __toESM(require("node:fs"), 1);
8375
+ var import_node_path12 = __toESM(require("node:path"), 1);
8402
8376
  var CheckoutRequiresGitError = class extends Error {
8403
8377
  };
8404
8378
  var BINARY_SNIFF_BYTES = 8192;
@@ -8409,14 +8383,14 @@ function looksBinary(filePath, size) {
8409
8383
  if (size === 0) return false;
8410
8384
  let fd;
8411
8385
  try {
8412
- fd = import_node_fs11.default.openSync(filePath, "r");
8386
+ fd = import_node_fs12.default.openSync(filePath, "r");
8413
8387
  const buffer = Buffer.alloc(Math.min(BINARY_SNIFF_BYTES, size));
8414
- const read = import_node_fs11.default.readSync(fd, buffer, 0, buffer.length, 0);
8388
+ const read = import_node_fs12.default.readSync(fd, buffer, 0, buffer.length, 0);
8415
8389
  return buffer.subarray(0, read).includes(0);
8416
8390
  } catch {
8417
8391
  return false;
8418
8392
  } finally {
8419
- if (fd !== void 0) import_node_fs11.default.closeSync(fd);
8393
+ if (fd !== void 0) import_node_fs12.default.closeSync(fd);
8420
8394
  }
8421
8395
  }
8422
8396
  var CheckoutFilePlane = class {
@@ -8429,7 +8403,7 @@ var CheckoutFilePlane = class {
8429
8403
  listTimeoutMs;
8430
8404
  trackedOnly;
8431
8405
  constructor(root, options = {}) {
8432
- this.root = import_node_path11.default.resolve(root);
8406
+ this.root = import_node_path12.default.resolve(root);
8433
8407
  this.listTimeoutMs = options.listTimeoutMs ?? LIST_FILES_TIMEOUT_MS;
8434
8408
  this.trackedOnly = options.trackedOnly ?? false;
8435
8409
  }
@@ -8491,13 +8465,13 @@ var CheckoutFilePlane = class {
8491
8465
  if (!relative2) continue;
8492
8466
  let stat2;
8493
8467
  try {
8494
- stat2 = import_node_fs11.default.statSync(import_node_path11.default.join(this.root, relative2));
8468
+ stat2 = import_node_fs12.default.statSync(import_node_path12.default.join(this.root, relative2));
8495
8469
  } catch {
8496
8470
  continue;
8497
8471
  }
8498
8472
  if (!stat2.isFile()) continue;
8499
8473
  const seen = this.sniffed.get(relative2);
8500
- const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path11.default.join(this.root, relative2), stat2.size);
8474
+ const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path12.default.join(this.root, relative2), stat2.size);
8501
8475
  nextSniffed.set(relative2, { size: stat2.size, mtimeMs: stat2.mtimeMs, binary });
8502
8476
  next.set(relative2, {
8503
8477
  size: stat2.size,
@@ -8511,22 +8485,22 @@ var CheckoutFilePlane = class {
8511
8485
  this.sniffed = nextSniffed;
8512
8486
  }
8513
8487
  absolute(planePath) {
8514
- const resolved = import_node_path11.default.resolve(this.root, planePath);
8515
- if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path11.default.sep}`)) {
8488
+ const resolved = import_node_path12.default.resolve(this.root, planePath);
8489
+ if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path12.default.sep}`)) {
8516
8490
  throw new Error(`path escapes the project: ${planePath}`);
8517
8491
  }
8518
8492
  return resolved;
8519
8493
  }
8520
8494
  async read(planePath) {
8521
- return import_node_fs11.default.promises.readFile(this.absolute(planePath), "utf8");
8495
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath), "utf8");
8522
8496
  }
8523
8497
  async readBytes(planePath) {
8524
- return import_node_fs11.default.promises.readFile(this.absolute(planePath));
8498
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath));
8525
8499
  }
8526
8500
  async write(planePath, content) {
8527
8501
  const absolute = this.absolute(planePath);
8528
- await import_node_fs11.default.promises.mkdir(import_node_path11.default.dirname(absolute), { recursive: true });
8529
- await import_node_fs11.default.promises.writeFile(absolute, content);
8502
+ await import_node_fs12.default.promises.mkdir(import_node_path12.default.dirname(absolute), { recursive: true });
8503
+ await import_node_fs12.default.promises.writeFile(absolute, content);
8530
8504
  this.entries.set(planePath, {
8531
8505
  size: content.byteLength,
8532
8506
  readOnly: false,
@@ -8535,7 +8509,7 @@ var CheckoutFilePlane = class {
8535
8509
  });
8536
8510
  }
8537
8511
  async delete(planePath) {
8538
- await import_node_fs11.default.promises.rm(this.absolute(planePath), { force: true });
8512
+ await import_node_fs12.default.promises.rm(this.absolute(planePath), { force: true });
8539
8513
  this.entries.delete(planePath);
8540
8514
  }
8541
8515
  };
@@ -8661,14 +8635,14 @@ var PlaneHost = class {
8661
8635
  // root and an opened one cannot disagree about the same directory.
8662
8636
  realRoot(root) {
8663
8637
  if (!root) throw new Error("root is required");
8664
- const resolved = import_node_path12.default.resolve(root);
8638
+ const resolved = import_node_path13.default.resolve(root);
8665
8639
  let real;
8666
8640
  try {
8667
- real = import_node_fs12.default.realpathSync(resolved);
8641
+ real = import_node_fs13.default.realpathSync(resolved);
8668
8642
  } catch {
8669
8643
  throw new Error(`no such directory: ${resolved}`);
8670
8644
  }
8671
- if (!import_node_fs12.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8645
+ if (!import_node_fs13.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8672
8646
  return real;
8673
8647
  }
8674
8648
  respond(ws, id, result) {
@@ -8689,7 +8663,7 @@ var PlaneHost = class {
8689
8663
 
8690
8664
  // src/host/replacement-module-handler.ts
8691
8665
  var import_promises5 = __toESM(require("node:fs/promises"), 1);
8692
- var import_node_path13 = __toESM(require("node:path"), 1);
8666
+ var import_node_path14 = __toESM(require("node:path"), 1);
8693
8667
 
8694
8668
  // ../contrast-bundler/src/replacementModule.ts
8695
8669
  var import_dist = require("sucrase/dist/index.js");
@@ -8728,7 +8702,7 @@ function normalize(p) {
8728
8702
  if (trailingSlash) joined += "/";
8729
8703
  return absolute ? "/" + joined : joined;
8730
8704
  }
8731
- function join4(...parts) {
8705
+ function join5(...parts) {
8732
8706
  const present = parts.filter((part) => part.length > 0);
8733
8707
  if (present.length === 0) return ".";
8734
8708
  return normalize(present.join("/"));
@@ -8785,7 +8759,7 @@ var posix = {
8785
8759
  delimiter,
8786
8760
  isAbsolute,
8787
8761
  normalize,
8788
- join: join4,
8762
+ join: join5,
8789
8763
  resolve: resolve2,
8790
8764
  dirname: dirname3,
8791
8765
  basename: basename3,
@@ -9043,13 +9017,13 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9043
9017
  res.end("missing path param");
9044
9018
  return true;
9045
9019
  }
9046
- const extension = import_node_path13.default.extname(targetPath).toLowerCase();
9020
+ const extension = import_node_path14.default.extname(targetPath).toLowerCase();
9047
9021
  if (!REPLACEMENT_MODULE_EXTENSIONS.some((allowed) => allowed === extension)) {
9048
9022
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9049
9023
  res.end(`replacement files must be ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")}`);
9050
9024
  return true;
9051
9025
  }
9052
- if (!import_node_path13.default.isAbsolute(targetPath)) {
9026
+ if (!import_node_path14.default.isAbsolute(targetPath)) {
9053
9027
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9054
9028
  res.end("replacement file path must be absolute");
9055
9029
  return true;
@@ -9057,10 +9031,10 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9057
9031
  const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
9058
9032
  let resolvedProjectRoot;
9059
9033
  if (options.projectRoot) {
9060
- const lexicalProjectRoot = import_node_path13.default.resolve(options.projectRoot);
9034
+ const lexicalProjectRoot = import_node_path14.default.resolve(options.projectRoot);
9061
9035
  resolvedProjectRoot = await import_promises5.default.realpath(options.projectRoot);
9062
- const lexicalTarget = import_node_path13.default.relative(lexicalProjectRoot, targetPath);
9063
- if (lexicalTarget.startsWith("..") || import_node_path13.default.isAbsolute(lexicalTarget)) {
9036
+ const lexicalTarget = import_node_path14.default.relative(lexicalProjectRoot, targetPath);
9037
+ if (lexicalTarget.startsWith("..") || import_node_path14.default.isAbsolute(lexicalTarget)) {
9064
9038
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9065
9039
  res.end("replacement file must be inside the project root");
9066
9040
  return true;
@@ -9076,8 +9050,8 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9076
9050
  return true;
9077
9051
  }
9078
9052
  if (resolvedProjectRoot) {
9079
- const relativeTarget = import_node_path13.default.relative(resolvedProjectRoot, resolvedTargetPath);
9080
- if (relativeTarget.startsWith("..") || import_node_path13.default.isAbsolute(relativeTarget)) {
9053
+ const relativeTarget = import_node_path14.default.relative(resolvedProjectRoot, resolvedTargetPath);
9054
+ if (relativeTarget.startsWith("..") || import_node_path14.default.isAbsolute(relativeTarget)) {
9081
9055
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9082
9056
  res.end("replacement file must be inside the project root");
9083
9057
  return true;
@@ -10259,7 +10233,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10259
10233
  }
10260
10234
  startRuntimeUpdater() {
10261
10235
  if (!this.shouldWriteLockfile || this.runtimeUpdateTimer) return;
10262
- if (import_fs3.default.existsSync(import_path3.default.join(rnxHomeDir(), "runtime-update-disabled"))) {
10236
+ if (!automaticPeachUpdatesEnabled()) {
10263
10237
  this.bootstrapping = false;
10264
10238
  if (this.httpServer) this.writeLockfileSnapshot();
10265
10239
  return;
@@ -10275,6 +10249,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10275
10249
  this.runtimeUpdateTimer.unref();
10276
10250
  }
10277
10251
  runRuntimeUpdate(reason) {
10252
+ if (!automaticPeachUpdatesEnabled()) return Promise.resolve();
10278
10253
  if (this.runtimeUpdateInFlight) return this.runtimeUpdateInFlight;
10279
10254
  this.runtimeUpdateInFlight = (async () => {
10280
10255
  try {