peachsim 0.1.629 → 0.1.631

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 (128) hide show
  1. package/README.md +8 -4
  2. package/cli/app-fonts.ts +23 -4
  3. package/cli/bridge-flow-runner.ts +45 -31
  4. package/cli/cli-update.ts +2 -7
  5. package/cli/cloud-test-tunnel.ts +16 -3
  6. package/cli/command-registry.ts +1 -0
  7. package/cli/commands/compat.ts +11 -60
  8. package/cli/commands/config.ts +1 -1
  9. package/cli/commands/control.ts +40 -8
  10. package/cli/commands/daemon-mac-app.ts +4 -2
  11. package/cli/commands/daemon.ts +4 -4
  12. package/cli/commands/detect.ts +289 -26
  13. package/cli/commands/device.ts +2 -3
  14. package/cli/commands/inspect/actions.ts +125 -90
  15. package/cli/commands/inspect/core.ts +1 -1
  16. package/cli/commands/inspect.ts +10 -1
  17. package/cli/commands/maestro.ts +3 -1
  18. package/cli/commands/platform.ts +1 -1
  19. package/cli/commands/project-report.ts +386 -0
  20. package/cli/commands/projectReportContract.ts +42 -0
  21. package/cli/commands/report-issue.ts +38 -54
  22. package/cli/commands/screenshot-layers.ts +1 -1
  23. package/cli/commands/screenshot.ts +1 -1
  24. package/cli/commands/setup.ts +6 -4
  25. package/cli/commands/skills.ts +0 -31
  26. package/cli/commands/telemetry.ts +8 -3
  27. package/cli/commands/test.ts +347 -134
  28. package/cli/drivers/playwright-provisioning.ts +3 -2
  29. package/cli/drivers/playwright-sim-host.ts +25 -9
  30. package/cli/main.ts +19 -3
  31. package/cli/outbound-endpoints.ts +2 -5
  32. package/cli/privacy.ts +1 -2
  33. package/cli/runtime-diagnostics.ts +51 -0
  34. package/cli/telemetry.ts +78 -7
  35. package/detox/index.ts +77 -51
  36. package/dist-lib/agent-daemon-client.cjs +1 -1
  37. package/dist-lib/agent-events.cjs +1 -1
  38. package/dist-lib/agent-identity.cjs +1 -1
  39. package/dist-lib/agent-sessions.cjs +1 -1
  40. package/dist-lib/attached-projects.cjs +1 -1
  41. package/dist-lib/auth/shared-session.cjs +1 -1
  42. package/dist-lib/backend-origin.cjs +1 -1
  43. package/dist-lib/beta.cjs +1 -1
  44. package/dist-lib/beta.mjs +1 -1
  45. package/dist-lib/bridge-constants.cjs +1 -1
  46. package/dist-lib/bridge-contract-input.cjs +1 -1
  47. package/dist-lib/bridge-contract-input.mjs +1 -1
  48. package/dist-lib/bridge-contract.cjs +1 -1
  49. package/dist-lib/bridge-contract.mjs +1 -1
  50. package/dist-lib/capture-contract.cjs +1 -1
  51. package/dist-lib/capture-contract.mjs +1 -1
  52. package/dist-lib/cli-constants.cjs +1 -1
  53. package/dist-lib/cloud-contract.cjs +1 -1
  54. package/dist-lib/cloud-contract.mjs +1 -1
  55. package/dist-lib/cloud-test-args.cjs +1 -1
  56. package/dist-lib/cloud-test-args.mjs +1 -1
  57. package/dist-lib/cloud.cjs +1 -1
  58. package/dist-lib/cloud.mjs +1 -1
  59. package/dist-lib/config.cjs +1 -1
  60. package/dist-lib/detox/index.cjs +130 -33
  61. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  62. package/dist-lib/home-paths.cjs +8 -5
  63. package/dist-lib/host/bridge-host.cjs +353 -290
  64. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  65. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  66. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  67. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  68. package/dist-lib/host/websocket-proxy.cjs +1 -1
  69. package/dist-lib/index.cjs +257 -121
  70. package/dist-lib/jump-to-source-babel.cjs +1 -1
  71. package/dist-lib/jump-to-source-native.cjs +1 -1
  72. package/dist-lib/{vite-kotlin.cjs → kotlin-host.cjs} +130 -19
  73. package/dist-lib/menu.cjs +11 -1
  74. package/dist-lib/menu.mjs +11 -1
  75. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  76. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  77. package/dist-lib/metro-production-bundle.cjs +1 -1
  78. package/dist-lib/metro-production-bundle.mjs +1 -1
  79. package/dist-lib/metro.cjs +132 -9
  80. package/dist-lib/native-app-identity.cjs +278 -0
  81. package/dist-lib/native-app-identity.mjs +245 -0
  82. package/dist-lib/profiles.cjs +1 -1
  83. package/dist-lib/public-brand.cjs +1 -1
  84. package/dist-lib/react-native-host-modules.cjs +1 -1
  85. package/dist-lib/react-native-host-modules.mjs +1 -1
  86. package/dist-lib/render-mode.cjs +1 -1
  87. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  88. package/dist-lib/sdk.cjs +112 -87
  89. package/dist-lib/sdk.mjs +111 -87
  90. package/dist-lib/skills.cjs +1270 -709
  91. package/dist-lib/swift-compile.cjs +1 -1
  92. package/dist-lib/swift-compile.mjs +1 -1
  93. package/dist-lib/swift-package.cjs +1 -1
  94. package/dist-lib/swift-package.mjs +1 -1
  95. package/dist-lib/swift-submit.cjs +1 -1
  96. package/dist-lib/swift-submit.mjs +1 -1
  97. package/dist-lib/swift.cjs +672 -275
  98. package/dist-lib/vite-swift.cjs +1 -1
  99. package/dist-lib/vite.cjs +11 -28
  100. package/kotlin/README.md +32 -4
  101. package/kotlin/fixtures/counter/Counter.kt +26 -0
  102. package/kotlin/fixtures/counter/CounterScreen.kt +40 -0
  103. package/kotlin/fixtures/headless-counter/Headless.kt +228 -0
  104. package/kotlin/fixtures/runtime-state/RuntimeState.kt +200 -0
  105. package/kotlin/fork/LICENSE +178 -0
  106. package/kotlin/fork/NOTICE +25 -0
  107. package/kotlin/fork/README.md +59 -0
  108. package/kotlin/fork/build.sh +128 -0
  109. package/kotlin/fork/compose-worker-globals.patch +96 -0
  110. package/kotlin/fork/fork.json +33 -0
  111. package/kotlin/fork/publish.ts +77 -0
  112. package/kotlin/fork/skiko-worker-clock.patch +33 -0
  113. package/kotlin/toolchain.json +288 -0
  114. package/package.json +13 -5
  115. package/skills/contrast/SKILL.md +1 -0
  116. package/src/automatic-update-policy.ts +17 -0
  117. package/src/home-paths.ts +11 -9
  118. package/src/host/bridge-host.ts +3 -1
  119. package/src/{vite-plugin-kotlin.ts → kotlin-host.ts} +155 -12
  120. package/src/menu.ts +11 -0
  121. package/src/metro-plugin.ts +18 -0
  122. package/src/native-app-identity.ts +376 -0
  123. package/src/native-firebase-config.ts +90 -0
  124. package/src/screenshots/frame-compose.ts +1 -1
  125. package/src/screenshots/registry.ts +1 -1
  126. package/src/screenshots/schema.ts +2 -2
  127. package/src/vite-plugin-one.ts +11 -28
  128. package/src/vite-plugin.ts +6 -1
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.629 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.631 | (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";
@@ -2660,7 +2660,9 @@ async function minify(code, sourceLine, options, withMap) {
2660
2660
  }
2661
2661
  const map = withMap && typeof result.map === "string" ? result.map : null;
2662
2662
  if (withMap && map === null) {
2663
- 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
+ );
2664
2666
  }
2665
2667
  return { code: result.code.trimEnd(), map, sourceLine };
2666
2668
  }
@@ -2724,8 +2726,9 @@ async function readOrInferModuleIdentity(bundle, mode, inferModuleIdentity) {
2724
2726
  }
2725
2727
  async function buildRnxCloudArtifact(bundle, options = {}) {
2726
2728
  const mode = options.mode ?? "production";
2729
+ const nativeIdentity = (0, import_native_app_identity.detachNativeAppIdentityFooter)(bundle);
2727
2730
  const identity = await readOrInferModuleIdentity(
2728
- bundle,
2731
+ nativeIdentity.source,
2729
2732
  mode,
2730
2733
  options.inferModuleIdentity
2731
2734
  );
@@ -2751,7 +2754,7 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
2751
2754
  })
2752
2755
  ]);
2753
2756
  const body = pieces.map((piece) => piece.code).join("\n");
2754
- 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)({
2755
2758
  version: identity.version,
2756
2759
  identitySource: identity.identitySource,
2757
2760
  modulePaths: identity.modulePaths,
@@ -2814,11 +2817,12 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
2814
2817
  }
2815
2818
  };
2816
2819
  }
2817
- 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;
2818
2821
  var init_metroCloudArtifact = __esm({
2819
2822
  "../contrast-bundler/src/metroCloudArtifact.ts"() {
2820
2823
  "use strict";
2821
2824
  import_metro_production_bundle = require("peachsim/metro-production-bundle");
2825
+ import_native_app_identity = require("peachsim/native-app-identity");
2822
2826
  import_terser = require("terser");
2823
2827
  init_metroAssetArtifact();
2824
2828
  init_metroDebugSourceMap();
@@ -3047,6 +3051,12 @@ var init_stub_manifest = __esm({
3047
3051
  runtimeTier: "core",
3048
3052
  buildResolvers: ["vite", "dep-prebundle"]
3049
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
+ },
3050
3060
  rctDeviceEventEmitter: {
3051
3061
  specifier: "react-native/Libraries/EventEmitter/RCTDeviceEventEmitter",
3052
3062
  stubFile: "rn-libraries/RCTDeviceEventEmitter.ts",
@@ -3939,39 +3949,82 @@ function detectFramework(deps) {
3939
3949
  return "unknown";
3940
3950
  }
3941
3951
  function detectProject(dir) {
3942
- const pkgPath = (0, import_path2.join)(dir, "package.json");
3943
- if (!(0, import_fs2.existsSync)(pkgPath)) return null;
3944
- let pkg;
3945
- try {
3946
- pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf8"));
3947
- } catch {
3948
- return null;
3949
- }
3952
+ const pkgPath = (0, import_node_path16.join)(dir, "package.json");
3953
+ if (!(0, import_node_fs15.existsSync)(pkgPath)) return null;
3954
+ const pkg = readProjectManifest(dir);
3955
+ if (!pkg) return null;
3950
3956
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
3957
+ const devCommand = metadataValue(
3958
+ metadataValue(readProjectJson(pkgPath), "scripts"),
3959
+ "dev"
3960
+ );
3951
3961
  const framework = detectFramework(deps);
3952
3962
  if (framework === "unknown") return null;
3953
3963
  return {
3954
3964
  dir,
3955
- name: pkg.name || (0, import_path2.basename)(dir),
3965
+ name: pkg.name || (0, import_node_path16.basename)(dir),
3956
3966
  framework,
3957
3967
  // a config file is a config file whatever module system it declares. real
3958
3968
  // apps write .cjs as often as .js, and missing one reads as "this project
3959
3969
  // has no bundler config" and sends the user to create a second one.
3960
3970
  hasViteConfig: CONFIG_EXTENSIONS.some(
3961
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `vite.config.${ext}`))
3971
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `vite.config.${ext}`))
3962
3972
  ),
3963
3973
  hasMetroConfig: CONFIG_EXTENSIONS.some(
3964
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `metro.config.${ext}`))
3974
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `metro.config.${ext}`))
3965
3975
  ),
3966
- devCommand: pkg.scripts?.dev || null
3976
+ devCommand: typeof devCommand === "string" ? devCommand : null
3967
3977
  };
3968
3978
  }
3969
- var import_fs2, import_path2, CONFIG_EXTENSIONS;
3979
+ function readProjectMetadata(path12) {
3980
+ try {
3981
+ const info = (0, import_node_fs15.lstatSync)(path12);
3982
+ if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
3983
+ return (0, import_node_fs15.readFileSync)(path12, "utf8");
3984
+ } catch {
3985
+ return null;
3986
+ }
3987
+ }
3988
+ function metadataValue(value, key) {
3989
+ if (!value || typeof value !== "object") return void 0;
3990
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
3991
+ }
3992
+ function readProjectJson(path12) {
3993
+ const text = readProjectMetadata(path12);
3994
+ if (text === null) return null;
3995
+ try {
3996
+ const value = JSON.parse(text);
3997
+ return value;
3998
+ } catch {
3999
+ return null;
4000
+ }
4001
+ }
4002
+ function readProjectManifest(dir) {
4003
+ const parsed = readProjectJson((0, import_node_path16.join)(dir, "package.json"));
4004
+ if (!parsed || typeof parsed !== "object") return null;
4005
+ const record = (value) => {
4006
+ if (!value || typeof value !== "object") return {};
4007
+ return Object.fromEntries(
4008
+ Object.entries(value).filter(
4009
+ (entry) => typeof entry[1] === "string" && /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/i.test(entry[0]) && entry[0] !== "." && entry[0] !== ".."
4010
+ )
4011
+ );
4012
+ };
4013
+ const name2 = metadataValue(parsed, "name");
4014
+ return {
4015
+ ...typeof name2 === "string" ? { name: name2 } : {},
4016
+ dependencies: record(metadataValue(parsed, "dependencies")),
4017
+ devDependencies: record(metadataValue(parsed, "devDependencies"))
4018
+ };
4019
+ }
4020
+ var import_node_fs15, import_node_path16, import_json5, import_yaml, CONFIG_EXTENSIONS;
3970
4021
  var init_detect = __esm({
3971
4022
  "cli/commands/detect.ts"() {
3972
4023
  "use strict";
3973
- import_fs2 = require("fs");
3974
- import_path2 = require("path");
4024
+ import_node_fs15 = require("node:fs");
4025
+ import_node_path16 = require("node:path");
4026
+ import_json5 = __toESM(require("json5"), 1);
4027
+ import_yaml = require("yaml");
3975
4028
  CONFIG_EXTENSIONS = ["ts", "js", "cjs", "mjs", "mts", "cts"];
3976
4029
  }
3977
4030
  });
@@ -4006,21 +4059,21 @@ function resolveCloudOrigin(value) {
4006
4059
  return normalizeCloudOrigin(source);
4007
4060
  }
4008
4061
  function readImmutableBundleSource(bundlePath) {
4009
- const filepath = (0, import_node_path15.resolve)(bundlePath);
4010
- if ((0, import_node_path15.extname)(filepath) !== ".js") {
4062
+ const filepath = (0, import_node_path17.resolve)(bundlePath);
4063
+ if ((0, import_node_path17.extname)(filepath) !== ".js") {
4011
4064
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
4012
4065
  }
4013
- const descriptor = (0, import_node_fs14.openSync)(filepath, "r");
4066
+ const descriptor = (0, import_node_fs16.openSync)(filepath, "r");
4014
4067
  try {
4015
- const before = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4068
+ const before = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
4016
4069
  if (!before.isFile()) {
4017
4070
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
4018
4071
  }
4019
4072
  if (before.size <= 0n) {
4020
4073
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
4021
4074
  }
4022
- const bytes = (0, import_node_fs14.readFileSync)(descriptor);
4023
- const after = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4075
+ const bytes = (0, import_node_fs16.readFileSync)(descriptor);
4076
+ const after = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
4024
4077
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
4025
4078
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
4026
4079
  }
@@ -4035,7 +4088,7 @@ function readImmutableBundleSource(bundlePath) {
4035
4088
  }
4036
4089
  return source;
4037
4090
  } finally {
4038
- (0, import_node_fs14.closeSync)(descriptor);
4091
+ (0, import_node_fs16.closeSync)(descriptor);
4039
4092
  }
4040
4093
  }
4041
4094
  async function fetchBundleSource(bundleUrl) {
@@ -4082,15 +4135,15 @@ async function loadBundleSource(bundleInput) {
4082
4135
  return readImmutableBundleSource(bundleInput);
4083
4136
  }
4084
4137
  function listMetroAssetDest(assetsPath) {
4085
- const directory = (0, import_node_path15.resolve)(assetsPath);
4086
- if (!(0, import_node_fs14.existsSync)(directory)) return { directory, files: [], truncated: false };
4087
- const skipNested = (0, import_node_fs14.existsSync)((0, import_node_path15.join)(directory, "package.json"));
4138
+ const directory = (0, import_node_path17.resolve)(assetsPath);
4139
+ if (!(0, import_node_fs16.existsSync)(directory)) return { directory, files: [], truncated: false };
4140
+ const skipNested = (0, import_node_fs16.existsSync)((0, import_node_path17.join)(directory, "package.json"));
4088
4141
  const files = [];
4089
4142
  let truncated = false;
4090
4143
  const walk = (dir, prefix) => {
4091
4144
  let entries;
4092
4145
  try {
4093
- entries = (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true });
4146
+ entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
4094
4147
  } catch {
4095
4148
  return;
4096
4149
  }
@@ -4102,7 +4155,7 @@ function listMetroAssetDest(assetsPath) {
4102
4155
  if (entry.isDirectory()) {
4103
4156
  if (entry.name === ".git") continue;
4104
4157
  if (skipNested && PROJECT_ONLY_DIRECTORIES.has(entry.name)) continue;
4105
- walk((0, import_node_path15.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4158
+ walk((0, import_node_path17.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4106
4159
  } else if (entry.isFile()) {
4107
4160
  files.push(prefix ? `${prefix}/${entry.name}` : entry.name);
4108
4161
  }
@@ -4137,7 +4190,7 @@ function distinctByContent(directory, options) {
4137
4190
  for (const relative2 of options) {
4138
4191
  let bytes;
4139
4192
  try {
4140
- bytes = (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(directory, relative2));
4193
+ bytes = (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(directory, relative2));
4141
4194
  } catch {
4142
4195
  continue;
4143
4196
  }
@@ -4169,7 +4222,7 @@ function placeMetroDescriptor(listing, descriptor) {
4169
4222
  let bytes;
4170
4223
  try {
4171
4224
  bytes = combination.map(
4172
- (relative2) => (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(listing.directory, relative2))
4225
+ (relative2) => (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(listing.directory, relative2))
4173
4226
  );
4174
4227
  } catch {
4175
4228
  continue;
@@ -4195,26 +4248,26 @@ function placeMetroDescriptor(listing, descriptor) {
4195
4248
  }
4196
4249
  function unverifiedFileKey(dest) {
4197
4250
  return dest.placements.filter((placement) => !placement.verified).flatMap(
4198
- (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path15.join)(dest.directory, relative2))
4251
+ (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path17.join)(dest.directory, relative2))
4199
4252
  ).sort().join("\n");
4200
4253
  }
4201
4254
  function searchMetroAssetDest(bundlePath, descriptors) {
4202
- const bundleDirectory = (0, import_node_path15.dirname)((0, import_node_path15.resolve)(bundlePath));
4255
+ const bundleDirectory = (0, import_node_path17.dirname)((0, import_node_path17.resolve)(bundlePath));
4203
4256
  const candidates = [
4204
- (0, import_node_path15.join)(bundleDirectory, "assets"),
4257
+ (0, import_node_path17.join)(bundleDirectory, "assets"),
4205
4258
  bundleDirectory,
4206
- (0, import_node_path15.resolve)(bundleDirectory, "..", "assets")
4259
+ (0, import_node_path17.resolve)(bundleDirectory, "..", "assets")
4207
4260
  ];
4208
4261
  const cwd = process.cwd();
4209
4262
  let projectDirectory = null;
4210
4263
  for (const start of [bundleDirectory, cwd]) {
4211
- let directory = (0, import_node_path15.resolve)(start);
4264
+ let directory = (0, import_node_path17.resolve)(start);
4212
4265
  while (true) {
4213
4266
  if (detectProject(directory)?.hasMetroConfig) {
4214
4267
  projectDirectory = directory;
4215
4268
  break;
4216
4269
  }
4217
- const parent = (0, import_node_path15.dirname)(directory);
4270
+ const parent = (0, import_node_path17.dirname)(directory);
4218
4271
  if (parent === directory) break;
4219
4272
  directory = parent;
4220
4273
  }
@@ -4222,11 +4275,11 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4222
4275
  }
4223
4276
  if (projectDirectory) {
4224
4277
  candidates.push(
4225
- (0, import_node_path15.join)(projectDirectory, "assets"),
4226
- (0, import_node_path15.join)(projectDirectory, "dist"),
4227
- (0, import_node_path15.join)(projectDirectory, "dist", "assets"),
4228
- (0, import_node_path15.join)(projectDirectory, "build"),
4229
- (0, import_node_path15.join)(projectDirectory, "build", "assets")
4278
+ (0, import_node_path17.join)(projectDirectory, "assets"),
4279
+ (0, import_node_path17.join)(projectDirectory, "dist"),
4280
+ (0, import_node_path17.join)(projectDirectory, "dist", "assets"),
4281
+ (0, import_node_path17.join)(projectDirectory, "build"),
4282
+ (0, import_node_path17.join)(projectDirectory, "build", "assets")
4230
4283
  );
4231
4284
  }
4232
4285
  const searched = [];
@@ -4234,7 +4287,7 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4234
4287
  const stale = [];
4235
4288
  let truncated = false;
4236
4289
  for (const candidate of candidates) {
4237
- const directory = (0, import_node_path15.resolve)(candidate);
4290
+ const directory = (0, import_node_path17.resolve)(candidate);
4238
4291
  if (searched.includes(directory)) continue;
4239
4292
  searched.push(directory);
4240
4293
  const listing = listMetroAssetDest(directory);
@@ -4340,7 +4393,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4340
4393
  );
4341
4394
  }
4342
4395
  const relative2 = placement?.files.get(variant.scale);
4343
- if (relative2 && dest) return (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(dest.directory, relative2));
4396
+ if (relative2 && dest) return (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(dest.directory, relative2));
4344
4397
  if (placement && placement.files.size > 0) return null;
4345
4398
  if (placement && placement.ambiguous.length > 0 && dest) {
4346
4399
  throw new Error(
@@ -4369,7 +4422,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4369
4422
  );
4370
4423
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
4371
4424
  throw new Error(
4372
- `${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\`.`
4425
+ `${command} could not read ${(0, import_node_path17.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\`.`
4373
4426
  );
4374
4427
  });
4375
4428
  return {
@@ -4515,13 +4568,13 @@ async function createCloudBox(options) {
4515
4568
  warnings: artifact.warnings
4516
4569
  };
4517
4570
  }
4518
- 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;
4571
+ var import_node_crypto6, import_node_fs16, import_node_path17, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4519
4572
  var init_cloud_client = __esm({
4520
4573
  "cli/cloud-client.ts"() {
4521
4574
  "use strict";
4522
4575
  import_node_crypto6 = require("node:crypto");
4523
- import_node_fs14 = require("node:fs");
4524
- import_node_path15 = require("node:path");
4576
+ import_node_fs16 = require("node:fs");
4577
+ import_node_path17 = require("node:path");
4525
4578
  init_metroAssetArtifact();
4526
4579
  init_metroCloudArtifact();
4527
4580
  init_metro_fingerprint_registry_client();
@@ -4627,9 +4680,9 @@ __export(bridge_host_exports, {
4627
4680
  });
4628
4681
  module.exports = __toCommonJS(bridge_host_exports);
4629
4682
  var import_child_process3 = require("child_process");
4630
- var import_fs3 = __toESM(require("fs"), 1);
4683
+ var import_fs2 = __toESM(require("fs"), 1);
4631
4684
  var import_http4 = require("http");
4632
- var import_path3 = __toESM(require("path"), 1);
4685
+ var import_path2 = __toESM(require("path"), 1);
4633
4686
  var import_ws = require("ws");
4634
4687
 
4635
4688
  // scripts/dev-server-scanner.ts
@@ -5917,6 +5970,15 @@ async function scanDevServers(opts = {}) {
5917
5970
  // src/host/bridge-host.ts
5918
5971
  init_backend_origin();
5919
5972
 
5973
+ // src/automatic-update-policy.ts
5974
+ var import_node_fs4 = require("node:fs");
5975
+ var import_node_path5 = require("node:path");
5976
+ init_home_paths();
5977
+ function automaticPeachUpdatesEnabled(env = process.env) {
5978
+ const value = env.PEACH_UPDATE_CHECK?.toLowerCase();
5979
+ return value !== "0" && value !== "false" && value !== "off" && !(0, import_node_fs4.existsSync)((0, import_node_path5.join)(rnxHomeDir(), "runtime-update-disabled"));
5980
+ }
5981
+
5920
5982
  // src/bridge-constants.ts
5921
5983
  var DEFAULT_SOOTSIM_BRIDGE_PORT = 7668;
5922
5984
  var DEFAULT_SOOTSIM_BRIDGE_URL = `http://localhost:${DEFAULT_SOOTSIM_BRIDGE_PORT}/`;
@@ -5925,7 +5987,7 @@ var SOOTSIM_BRIDGE_SIM_CLOSE_REASON = "sootsim close";
5925
5987
  var AUTOMATION_SIM_IDLE_REAP_TTL_MS = 5 * 6e4;
5926
5988
 
5927
5989
  // src/cli-version.ts
5928
- var import_node_fs3 = require("node:fs");
5990
+ var import_node_fs5 = require("node:fs");
5929
5991
  var import_node_url2 = require("node:url");
5930
5992
  init_public_brand();
5931
5993
  var import_meta = {};
@@ -5942,7 +6004,7 @@ function getCliVersion() {
5942
6004
  ];
5943
6005
  for (const resolve5 of candidates) {
5944
6006
  try {
5945
- const version = JSON.parse((0, import_node_fs3.readFileSync)(resolve5(), "utf8")).version;
6007
+ const version = JSON.parse((0, import_node_fs5.readFileSync)(resolve5(), "utf8")).version;
5946
6008
  if (typeof version === "string" && version) {
5947
6009
  cached2 = version;
5948
6010
  return cached2;
@@ -5966,27 +6028,27 @@ var import_url = require("url");
5966
6028
  // ../contrast-runtime-delivery/src/index.ts
5967
6029
  var import_node_child_process2 = require("node:child_process");
5968
6030
  var import_node_crypto2 = __toESM(require("node:crypto"), 1);
5969
- var import_node_fs6 = __toESM(require("node:fs"), 1);
6031
+ var import_node_fs7 = __toESM(require("node:fs"), 1);
5970
6032
  var import_node_os2 = __toESM(require("node:os"), 1);
5971
- var import_node_path6 = __toESM(require("node:path"), 1);
6033
+ var import_node_path7 = __toESM(require("node:path"), 1);
5972
6034
  var import_node_stream = require("node:stream");
5973
6035
  var import_promises3 = require("node:stream/promises");
5974
6036
 
5975
6037
  // ../contrast-runtime-delivery/src/product.ts
5976
- var import_node_fs5 = __toESM(require("node:fs"), 1);
5977
- var import_node_path5 = __toESM(require("node:path"), 1);
6038
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
6039
+ var import_node_path6 = __toESM(require("node:path"), 1);
5978
6040
  function isValidRuntimeVersion(value) {
5979
6041
  return value.length <= 100 && /^[0-9A-Za-z][0-9A-Za-z._+-]*$/.test(value);
5980
6042
  }
5981
6043
  function listInstalledRuntimes(product) {
5982
6044
  try {
5983
- return import_node_fs5.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
6045
+ return import_node_fs6.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
5984
6046
  } catch {
5985
6047
  return [];
5986
6048
  }
5987
6049
  }
5988
6050
  function runtimeTarballCacheName(product, version) {
5989
- return import_node_path5.default.posix.basename(product.tarballPath(version));
6051
+ return import_node_path6.default.posix.basename(product.tarballPath(version));
5990
6052
  }
5991
6053
  function compareSemver(a, b) {
5992
6054
  const parse2 = (v) => {
@@ -6016,7 +6078,7 @@ function createRuntimeDelivery(product) {
6016
6078
  function readConfig() {
6017
6079
  try {
6018
6080
  const parsed = JSON.parse(
6019
- import_node_fs6.default.readFileSync(product.configFile(), "utf8")
6081
+ import_node_fs7.default.readFileSync(product.configFile(), "utf8")
6020
6082
  );
6021
6083
  return parsed && typeof parsed === "object" ? parsed : {};
6022
6084
  } catch {
@@ -6089,7 +6151,7 @@ function createRuntimeDelivery(product) {
6089
6151
  const setActive = opts.setActive !== false;
6090
6152
  const protectVersions = [version, ...opts.protectVersions ?? []];
6091
6153
  pruneLocalRetention({ protectVersions });
6092
- if (!opts.force && import_node_fs6.default.existsSync(import_node_path6.default.join(destDir, product.installedMarker))) {
6154
+ if (!opts.force && import_node_fs7.default.existsSync(import_node_path7.default.join(destDir, product.installedMarker))) {
6093
6155
  if (setActive) product.writeActiveRuntime(version);
6094
6156
  pruneLocalRetention({ protectVersions });
6095
6157
  return {
@@ -6103,18 +6165,18 @@ function createRuntimeDelivery(product) {
6103
6165
  };
6104
6166
  }
6105
6167
  const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
6106
- const downloadDir = import_node_fs6.default.mkdtempSync(
6107
- import_node_path6.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6168
+ const downloadDir = import_node_fs7.default.mkdtempSync(
6169
+ import_node_path7.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6108
6170
  );
6109
- const runtimeArchivePath = import_node_path6.default.join(
6171
+ const runtimeArchivePath = import_node_path7.default.join(
6110
6172
  downloadDir,
6111
6173
  runtimeTarballCacheName(product, version)
6112
6174
  );
6113
- const tmpDir = import_node_path6.default.join(
6114
- import_node_path6.default.dirname(destDir),
6175
+ const tmpDir = import_node_path7.default.join(
6176
+ import_node_path7.default.dirname(destDir),
6115
6177
  `.installing-${version}-${process.pid}`
6116
6178
  );
6117
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6179
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6118
6180
  try {
6119
6181
  if (!opts.quiet)
6120
6182
  process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
@@ -6129,20 +6191,20 @@ function createRuntimeDelivery(product) {
6129
6191
  `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
6130
6192
  );
6131
6193
  }
6132
- import_node_fs6.default.mkdirSync(tmpDir, { recursive: true });
6194
+ import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
6133
6195
  await extractTarball(runtimeArchivePath, tmpDir);
6134
- if (!import_node_fs6.default.existsSync(import_node_path6.default.join(tmpDir, product.installedMarker))) {
6196
+ if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, product.installedMarker))) {
6135
6197
  throw new Error(
6136
6198
  `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
6137
6199
  );
6138
6200
  }
6139
- import_node_fs6.default.rmSync(destDir, { recursive: true, force: true });
6140
- import_node_fs6.default.renameSync(tmpDir, destDir);
6201
+ import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
6202
+ import_node_fs7.default.renameSync(tmpDir, destDir);
6141
6203
  } catch (err) {
6142
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6204
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6143
6205
  throw err;
6144
6206
  } finally {
6145
- import_node_fs6.default.rmSync(downloadDir, { recursive: true, force: true });
6207
+ import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
6146
6208
  }
6147
6209
  if (setActive) product.writeActiveRuntime(version);
6148
6210
  pruneLocalRetention({ protectVersions });
@@ -6164,8 +6226,8 @@ function createRuntimeDelivery(product) {
6164
6226
  const pin = resolvePin();
6165
6227
  if (pin) {
6166
6228
  const activeVersion2 = product.readActiveRuntime();
6167
- const pinInstalled = import_node_fs6.default.existsSync(
6168
- import_node_path6.default.join(product.runtimeDir(pin), product.installedMarker)
6229
+ const pinInstalled = import_node_fs7.default.existsSync(
6230
+ import_node_path7.default.join(product.runtimeDir(pin), product.installedMarker)
6169
6231
  );
6170
6232
  if (activeVersion2 === pin && pinInstalled) {
6171
6233
  return {
@@ -6214,7 +6276,7 @@ function createRuntimeDelivery(product) {
6214
6276
  }
6215
6277
  const activeVersion = product.readActiveRuntime();
6216
6278
  const activeDir = activeVersion ? product.runtimeDir(activeVersion) : null;
6217
- const activeInstalled = activeDir ? import_node_fs6.default.existsSync(import_node_path6.default.join(activeDir, product.installedMarker)) : false;
6279
+ const activeInstalled = activeDir ? import_node_fs7.default.existsSync(import_node_path7.default.join(activeDir, product.installedMarker)) : false;
6218
6280
  const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
6219
6281
  if (!shouldInstall) {
6220
6282
  return {
@@ -6289,12 +6351,12 @@ function createRuntimeDelivery(product) {
6289
6351
  let removeCacheFiles = [];
6290
6352
  if (markerOffset >= 0) {
6291
6353
  try {
6292
- removeCacheFiles = import_node_fs6.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6354
+ removeCacheFiles = import_node_fs7.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6293
6355
  if (!entry.isFile()) return false;
6294
6356
  const complete = entry.name.startsWith(cachePrefix) && entry.name.endsWith(cacheSuffix);
6295
6357
  const partial = entry.name.startsWith(cachePrefix) && entry.name.endsWith(`${cacheSuffix}.partial`);
6296
6358
  return complete || partial;
6297
- }).map((entry) => import_node_path6.default.join(product.cacheDir(), entry.name)).sort();
6359
+ }).map((entry) => import_node_path7.default.join(product.cacheDir(), entry.name)).sort();
6298
6360
  } catch {
6299
6361
  }
6300
6362
  }
@@ -6309,10 +6371,10 @@ function createRuntimeDelivery(product) {
6309
6371
  function pruneLocalRetention(opts = {}) {
6310
6372
  const plan = planLocalRetention(opts);
6311
6373
  for (const version of plan.removeVersions) {
6312
- import_node_fs6.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6374
+ import_node_fs7.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6313
6375
  }
6314
6376
  for (const cacheFile of plan.removeCacheFiles) {
6315
- import_node_fs6.default.rmSync(cacheFile, { force: true });
6377
+ import_node_fs7.default.rmSync(cacheFile, { force: true });
6316
6378
  }
6317
6379
  return plan;
6318
6380
  }
@@ -6338,17 +6400,17 @@ async function downloadToFile(url, destPath) {
6338
6400
  if (!res.ok || !res.body) {
6339
6401
  throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`);
6340
6402
  }
6341
- import_node_fs6.default.mkdirSync(import_node_path6.default.dirname(destPath), { recursive: true });
6403
+ import_node_fs7.default.mkdirSync(import_node_path7.default.dirname(destPath), { recursive: true });
6342
6404
  const tmp = `${destPath}.partial`;
6343
6405
  try {
6344
6406
  await (0, import_promises3.pipeline)(
6345
6407
  import_node_stream.Readable.fromWeb(res.body),
6346
- import_node_fs6.default.createWriteStream(tmp)
6408
+ import_node_fs7.default.createWriteStream(tmp)
6347
6409
  );
6348
- import_node_fs6.default.renameSync(tmp, destPath);
6410
+ import_node_fs7.default.renameSync(tmp, destPath);
6349
6411
  } catch (err) {
6350
6412
  try {
6351
- import_node_fs6.default.unlinkSync(tmp);
6413
+ import_node_fs7.default.unlinkSync(tmp);
6352
6414
  } catch {
6353
6415
  }
6354
6416
  throw err;
@@ -6357,7 +6419,7 @@ async function downloadToFile(url, destPath) {
6357
6419
  function sha256File(filePath) {
6358
6420
  return new Promise((resolve5, reject) => {
6359
6421
  const hash = import_node_crypto2.default.createHash("sha256");
6360
- const stream = import_node_fs6.default.createReadStream(filePath);
6422
+ const stream = import_node_fs7.default.createReadStream(filePath);
6361
6423
  stream.on("data", (chunk) => hash.update(chunk));
6362
6424
  stream.on("error", reject);
6363
6425
  stream.on("end", () => resolve5(hash.digest("hex")));
@@ -6506,19 +6568,19 @@ var rnxRuntime = createRuntimeDelivery(RNX_RUNTIME_PRODUCT);
6506
6568
 
6507
6569
  // src/host/agent-host.ts
6508
6570
  var import_node_crypto5 = require("node:crypto");
6509
- var import_node_fs10 = __toESM(require("node:fs"), 1);
6510
- var import_node_path10 = __toESM(require("node:path"), 1);
6571
+ var import_node_fs11 = __toESM(require("node:fs"), 1);
6572
+ var import_node_path11 = __toESM(require("node:path"), 1);
6511
6573
 
6512
6574
  // src/agent-sessions.ts
6513
6575
  var import_node_child_process3 = require("node:child_process");
6514
6576
  var import_node_crypto4 = require("node:crypto");
6515
- var import_node_fs9 = __toESM(require("node:fs"), 1);
6516
- var import_node_path9 = __toESM(require("node:path"), 1);
6577
+ var import_node_fs10 = __toESM(require("node:fs"), 1);
6578
+ var import_node_path10 = __toESM(require("node:path"), 1);
6517
6579
  var import_node_readline = __toESM(require("node:readline"), 1);
6518
6580
 
6519
6581
  // cli/self-invocation.ts
6520
- var import_node_fs7 = require("node:fs");
6521
- var import_node_path7 = require("node:path");
6582
+ var import_node_fs8 = require("node:fs");
6583
+ var import_node_path8 = require("node:path");
6522
6584
  var import_node_url3 = require("node:url");
6523
6585
  init_public_brand();
6524
6586
 
@@ -6528,14 +6590,14 @@ var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_S
6528
6590
  // cli/self-invocation.ts
6529
6591
  function sourceEntryPath() {
6530
6592
  try {
6531
- const candidate = (0, import_node_path7.join)((0, import_node_path7.dirname)((0, import_node_url3.fileURLToPath)(__sootsim_import_meta_url)), "bin.ts");
6532
- return (0, import_node_fs7.existsSync)(candidate) ? candidate : null;
6593
+ const candidate = (0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_url3.fileURLToPath)(__sootsim_import_meta_url)), "bin.ts");
6594
+ return (0, import_node_fs8.existsSync)(candidate) ? candidate : null;
6533
6595
  } catch {
6534
6596
  return null;
6535
6597
  }
6536
6598
  }
6537
6599
  function isCliEntry(path12) {
6538
- const name2 = (0, import_node_path7.basename)(path12);
6600
+ const name2 = (0, import_node_path8.basename)(path12);
6539
6601
  return name2 === "bin.ts" || name2 === "bin.js";
6540
6602
  }
6541
6603
  function rnxSelfInvocation() {
@@ -6595,8 +6657,8 @@ function encodeAgentPromptEnvelope(input) {
6595
6657
 
6596
6658
  // src/attached-projects.ts
6597
6659
  var import_node_crypto3 = require("node:crypto");
6598
- var import_node_fs8 = __toESM(require("node:fs"), 1);
6599
- var import_node_path8 = __toESM(require("node:path"), 1);
6660
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
6661
+ var import_node_path9 = __toESM(require("node:path"), 1);
6600
6662
  init_home_paths();
6601
6663
  var overrideDir = null;
6602
6664
  function userDataDir() {
@@ -6609,7 +6671,7 @@ function getUserDataDir() {
6609
6671
  return userDataDir();
6610
6672
  }
6611
6673
  function storeFile() {
6612
- return import_node_path8.default.join(userDataDir(), "attached-projects.json");
6674
+ return import_node_path9.default.join(userDataDir(), "attached-projects.json");
6613
6675
  }
6614
6676
  function cloneEmpty() {
6615
6677
  return {
@@ -6623,7 +6685,7 @@ function loadStore() {
6623
6685
  const file = storeFile();
6624
6686
  let raw;
6625
6687
  try {
6626
- raw = import_node_fs8.default.readFileSync(file, "utf8");
6688
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
6627
6689
  } catch (err) {
6628
6690
  if (err.code === "ENOENT") return cloneEmpty();
6629
6691
  throw err;
@@ -6640,7 +6702,7 @@ function loadStore() {
6640
6702
  } catch (err) {
6641
6703
  const quarantine = `${file}.corrupt-${Date.now()}`;
6642
6704
  try {
6643
- import_node_fs8.default.renameSync(file, quarantine);
6705
+ import_node_fs9.default.renameSync(file, quarantine);
6644
6706
  console.warn(
6645
6707
  `[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
6646
6708
  );
@@ -6651,16 +6713,16 @@ function loadStore() {
6651
6713
  }
6652
6714
  function writeStore(store) {
6653
6715
  const file = storeFile();
6654
- import_node_fs8.default.mkdirSync(import_node_path8.default.dirname(file), { recursive: true });
6716
+ import_node_fs9.default.mkdirSync(import_node_path9.default.dirname(file), { recursive: true });
6655
6717
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
6656
- const fd = import_node_fs8.default.openSync(tmp, "w", 384);
6718
+ const fd = import_node_fs9.default.openSync(tmp, "w", 384);
6657
6719
  try {
6658
- import_node_fs8.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6659
- import_node_fs8.default.fsyncSync(fd);
6720
+ import_node_fs9.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6721
+ import_node_fs9.default.fsyncSync(fd);
6660
6722
  } finally {
6661
- import_node_fs8.default.closeSync(fd);
6723
+ import_node_fs9.default.closeSync(fd);
6662
6724
  }
6663
- import_node_fs8.default.renameSync(tmp, file);
6725
+ import_node_fs9.default.renameSync(tmp, file);
6664
6726
  }
6665
6727
  function mutateStore(fn) {
6666
6728
  const store = loadStore();
@@ -6669,13 +6731,13 @@ function mutateStore(fn) {
6669
6731
  return store;
6670
6732
  }
6671
6733
  function projectIdForCwd(cwd) {
6672
- return (0, import_node_crypto3.createHash)("sha256").update(import_node_path8.default.resolve(cwd)).digest("hex").slice(0, 16);
6734
+ return (0, import_node_crypto3.createHash)("sha256").update(import_node_path9.default.resolve(cwd)).digest("hex").slice(0, 16);
6673
6735
  }
6674
6736
  function newSessionId() {
6675
6737
  return `s_${(0, import_node_crypto3.randomBytes)(10).toString("hex")}`;
6676
6738
  }
6677
6739
  function upsertProject(input) {
6678
- const cwd = import_node_path8.default.resolve(input.cwd);
6740
+ const cwd = import_node_path9.default.resolve(input.cwd);
6679
6741
  const id = projectIdForCwd(cwd);
6680
6742
  let result;
6681
6743
  mutateStore((store) => {
@@ -6701,7 +6763,7 @@ function upsertProject(input) {
6701
6763
  const now = Date.now();
6702
6764
  const created = {
6703
6765
  id,
6704
- name: input.name ?? import_node_path8.default.basename(cwd),
6766
+ name: input.name ?? import_node_path9.default.basename(cwd),
6705
6767
  cwd,
6706
6768
  repoRoot: input.repoRoot,
6707
6769
  sourceRoots: input.sourceRoots ?? [cwd],
@@ -6847,8 +6909,8 @@ async function seedFromDemoAppRegistry() {
6847
6909
  if (apps.length === 0) return;
6848
6910
  mutateStore((store) => {
6849
6911
  for (const app of apps) {
6850
- if (!import_node_fs8.default.existsSync(app.dir)) continue;
6851
- const cwd = import_node_path8.default.resolve(app.dir);
6912
+ if (!import_node_fs9.default.existsSync(app.dir)) continue;
6913
+ const cwd = import_node_path9.default.resolve(app.dir);
6852
6914
  const id = projectIdForCwd(cwd);
6853
6915
  if (store.attachedProjects.some((p) => p.id === id)) continue;
6854
6916
  const now = Date.now();
@@ -6873,16 +6935,16 @@ async function seedFromDemoAppRegistry() {
6873
6935
  // src/agent-sessions.ts
6874
6936
  init_public_brand();
6875
6937
  function sessionDir(sessionId) {
6876
- return import_node_path9.default.join(getUserDataDir(), "sessions", sessionId);
6938
+ return import_node_path10.default.join(getUserDataDir(), "sessions", sessionId);
6877
6939
  }
6878
6940
  function promptFifoPath(sessionId) {
6879
- return import_node_path9.default.join(sessionDir(sessionId), "prompt.in");
6941
+ return import_node_path10.default.join(sessionDir(sessionId), "prompt.in");
6880
6942
  }
6881
6943
  function eventsFifoPath(sessionId) {
6882
- return import_node_path9.default.join(sessionDir(sessionId), "events.out");
6944
+ return import_node_path10.default.join(sessionDir(sessionId), "events.out");
6883
6945
  }
6884
6946
  function transcriptPath(sessionId) {
6885
- return import_node_path9.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6947
+ return import_node_path10.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6886
6948
  }
6887
6949
  function pidIsAlive(pid, sessionId) {
6888
6950
  if (!pid) return false;
@@ -6892,7 +6954,7 @@ function pidIsAlive(pid, sessionId) {
6892
6954
  return false;
6893
6955
  }
6894
6956
  if (sessionId) {
6895
- if (!import_node_fs9.default.existsSync(sessionDir(sessionId))) return false;
6957
+ if (!import_node_fs10.default.existsSync(sessionDir(sessionId))) return false;
6896
6958
  }
6897
6959
  return true;
6898
6960
  }
@@ -6905,11 +6967,11 @@ function resolveSootsimInvocation() {
6905
6967
  const resourcesPath = process.resourcesPath;
6906
6968
  if (resourcesPath) {
6907
6969
  const candidates = [
6908
- import_node_path9.default.join(resourcesPath, "bin", "sootsim"),
6909
- import_node_path9.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6970
+ import_node_path10.default.join(resourcesPath, "bin", "sootsim"),
6971
+ import_node_path10.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6910
6972
  ];
6911
6973
  for (const c of candidates) {
6912
- if (import_node_fs9.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6974
+ if (import_node_fs10.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6913
6975
  }
6914
6976
  }
6915
6977
  }
@@ -6928,15 +6990,15 @@ function tryWorkspaceSootsim() {
6928
6990
  const sootsimDir = resolveSootsimPackageDir();
6929
6991
  if (!sootsimDir) return null;
6930
6992
  const binaryName = `peach-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`;
6931
- const distBinary = import_node_path9.default.join(sootsimDir, "dist-bin", binaryName);
6932
- if (import_node_fs9.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
6933
- const distBin = import_node_path9.default.join(sootsimDir, "dist-cli", "bin.js");
6934
- if (import_node_fs9.default.existsSync(distBin)) {
6993
+ const distBinary = import_node_path10.default.join(sootsimDir, "dist-bin", binaryName);
6994
+ if (import_node_fs10.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
6995
+ const distBin = import_node_path10.default.join(sootsimDir, "dist-cli", "bin.js");
6996
+ if (import_node_fs10.default.existsSync(distBin)) {
6935
6997
  try {
6936
- const src = import_node_path9.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
6937
- if (import_node_fs9.default.existsSync(src)) {
6938
- const srcMtime = import_node_fs9.default.statSync(src).mtimeMs;
6939
- const buildMtime = import_node_fs9.default.statSync(distBin).mtimeMs;
6998
+ const src = import_node_path10.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
6999
+ if (import_node_fs10.default.existsSync(src)) {
7000
+ const srcMtime = import_node_fs10.default.statSync(src).mtimeMs;
7001
+ const buildMtime = import_node_fs10.default.statSync(distBin).mtimeMs;
6940
7002
  if (buildMtime < srcMtime) {
6941
7003
  console.warn(
6942
7004
  `[peach] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/peachsim build:cli\`.`
@@ -6955,22 +7017,22 @@ function tryWorkspaceSootsim() {
6955
7017
  function resolveSootsimPackageDir() {
6956
7018
  try {
6957
7019
  const resolved = require.resolve(`${rnxPublicBrand.packageName}/package.json`);
6958
- return import_node_path9.default.dirname(resolved);
7020
+ return import_node_path10.default.dirname(resolved);
6959
7021
  } catch {
6960
7022
  }
6961
7023
  const here = fileFromImportMeta();
6962
7024
  if (!here) return null;
6963
- let cur = import_node_path9.default.dirname(here);
7025
+ let cur = import_node_path10.default.dirname(here);
6964
7026
  for (let i = 0; i < 8; i++) {
6965
- const pkg = import_node_path9.default.join(cur, "package.json");
7027
+ const pkg = import_node_path10.default.join(cur, "package.json");
6966
7028
  try {
6967
- if (import_node_fs9.default.existsSync(pkg)) {
6968
- const parsed = JSON.parse(import_node_fs9.default.readFileSync(pkg, "utf8"));
7029
+ if (import_node_fs10.default.existsSync(pkg)) {
7030
+ const parsed = JSON.parse(import_node_fs10.default.readFileSync(pkg, "utf8"));
6969
7031
  if (parsed.name === rnxPublicBrand.packageName) return cur;
6970
7032
  }
6971
7033
  } catch {
6972
7034
  }
6973
- const parent = import_node_path9.default.dirname(cur);
7035
+ const parent = import_node_path10.default.dirname(cur);
6974
7036
  if (parent === cur) break;
6975
7037
  cur = parent;
6976
7038
  }
@@ -6986,28 +7048,28 @@ function fileFromImportMeta() {
6986
7048
  }
6987
7049
  }
6988
7050
  async function withStartLock(projectId, provider, fn) {
6989
- const lockDir = import_node_path9.default.join(getUserDataDir(), "locks");
6990
- import_node_fs9.default.mkdirSync(lockDir, { recursive: true });
7051
+ const lockDir = import_node_path10.default.join(getUserDataDir(), "locks");
7052
+ import_node_fs10.default.mkdirSync(lockDir, { recursive: true });
6991
7053
  try {
6992
- import_node_fs9.default.chmodSync(lockDir, 448);
7054
+ import_node_fs10.default.chmodSync(lockDir, 448);
6993
7055
  } catch {
6994
7056
  }
6995
- const lockPath = import_node_path9.default.join(lockDir, `start-${projectId}-${provider}.lock`);
7057
+ const lockPath = import_node_path10.default.join(lockDir, `start-${projectId}-${provider}.lock`);
6996
7058
  const deadline = Date.now() + 4e3;
6997
7059
  let fd = null;
6998
7060
  while (fd === null) {
6999
7061
  try {
7000
- fd = import_node_fs9.default.openSync(
7062
+ fd = import_node_fs10.default.openSync(
7001
7063
  lockPath,
7002
- import_node_fs9.constants.O_WRONLY | import_node_fs9.constants.O_CREAT | import_node_fs9.constants.O_EXCL,
7064
+ import_node_fs10.constants.O_WRONLY | import_node_fs10.constants.O_CREAT | import_node_fs10.constants.O_EXCL,
7003
7065
  384
7004
7066
  );
7005
7067
  } catch (err) {
7006
7068
  if (err.code !== "EEXIST") throw err;
7007
7069
  try {
7008
- const stale = Number(import_node_fs9.default.readFileSync(lockPath, "utf8").trim());
7070
+ const stale = Number(import_node_fs10.default.readFileSync(lockPath, "utf8").trim());
7009
7071
  if (stale && !isProcessAlive(stale)) {
7010
- import_node_fs9.default.unlinkSync(lockPath);
7072
+ import_node_fs10.default.unlinkSync(lockPath);
7011
7073
  continue;
7012
7074
  }
7013
7075
  } catch {
@@ -7021,15 +7083,15 @@ async function withStartLock(projectId, provider, fn) {
7021
7083
  }
7022
7084
  }
7023
7085
  try {
7024
- import_node_fs9.default.writeFileSync(fd, String(process.pid));
7086
+ import_node_fs10.default.writeFileSync(fd, String(process.pid));
7025
7087
  return await fn();
7026
7088
  } finally {
7027
7089
  try {
7028
- import_node_fs9.default.closeSync(fd);
7090
+ import_node_fs10.default.closeSync(fd);
7029
7091
  } catch {
7030
7092
  }
7031
7093
  try {
7032
- import_node_fs9.default.unlinkSync(lockPath);
7094
+ import_node_fs10.default.unlinkSync(lockPath);
7033
7095
  } catch {
7034
7096
  }
7035
7097
  }
@@ -7043,25 +7105,25 @@ function isProcessAlive(pid) {
7043
7105
  }
7044
7106
  }
7045
7107
  function mkfifoSync(p) {
7046
- const parent = import_node_path9.default.dirname(p);
7047
- import_node_fs9.default.mkdirSync(parent, { recursive: true });
7108
+ const parent = import_node_path10.default.dirname(p);
7109
+ import_node_fs10.default.mkdirSync(parent, { recursive: true });
7048
7110
  try {
7049
- import_node_fs9.default.chmodSync(parent, 448);
7111
+ import_node_fs10.default.chmodSync(parent, 448);
7050
7112
  } catch {
7051
7113
  }
7052
- if (import_node_fs9.default.existsSync(p)) {
7114
+ if (import_node_fs10.default.existsSync(p)) {
7053
7115
  try {
7054
- const stat2 = import_node_fs9.default.statSync(p);
7116
+ const stat2 = import_node_fs10.default.statSync(p);
7055
7117
  if (stat2.isFIFO()) {
7056
7118
  try {
7057
- import_node_fs9.default.chmodSync(p, 384);
7119
+ import_node_fs10.default.chmodSync(p, 384);
7058
7120
  } catch {
7059
7121
  }
7060
7122
  return;
7061
7123
  }
7062
- import_node_fs9.default.unlinkSync(p);
7124
+ import_node_fs10.default.unlinkSync(p);
7063
7125
  } catch {
7064
- import_node_fs9.default.unlinkSync(p);
7126
+ import_node_fs10.default.unlinkSync(p);
7065
7127
  }
7066
7128
  }
7067
7129
  const result = (0, import_node_child_process3.spawnSync)("mkfifo", ["-m", "600", p]);
@@ -7108,10 +7170,10 @@ async function startSession(opts) {
7108
7170
  const transcript = transcriptPath(session.id);
7109
7171
  mkfifoSync(promptIn);
7110
7172
  mkfifoSync(eventsOut);
7111
- const transcriptDir = import_node_path9.default.dirname(transcript);
7112
- import_node_fs9.default.mkdirSync(transcriptDir, { recursive: true });
7173
+ const transcriptDir = import_node_path10.default.dirname(transcript);
7174
+ import_node_fs10.default.mkdirSync(transcriptDir, { recursive: true });
7113
7175
  try {
7114
- import_node_fs9.default.chmodSync(transcriptDir, 448);
7176
+ import_node_fs10.default.chmodSync(transcriptDir, 448);
7115
7177
  } catch {
7116
7178
  }
7117
7179
  const { executable, prefixArgs } = resolveSootsimInvocation();
@@ -7162,7 +7224,7 @@ async function startSession(opts) {
7162
7224
  }
7163
7225
  }
7164
7226
  try {
7165
- import_node_fs9.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7227
+ import_node_fs10.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7166
7228
  } catch {
7167
7229
  }
7168
7230
  updateSessionStatus(session.id, { status: "ended" });
@@ -7190,18 +7252,18 @@ async function sendPrompt(sessionId, prompt) {
7190
7252
  );
7191
7253
  }
7192
7254
  const fifo = promptFifoPath(sessionId);
7193
- if (!import_node_fs9.default.existsSync(fifo)) {
7255
+ if (!import_node_fs10.default.existsSync(fifo)) {
7194
7256
  throw new AgentSessionError("NO_FIFO", `prompt FIFO missing: ${fifo}`);
7195
7257
  }
7196
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_WRONLY);
7258
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_WRONLY);
7197
7259
  try {
7198
7260
  const wireText = encodeAgentPromptEnvelope(prompt);
7199
7261
  if (!wireText) {
7200
7262
  throw new AgentSessionError("EMPTY_PROMPT", "prompt text is empty");
7201
7263
  }
7202
- import_node_fs9.default.writeSync(fd, wireText + "\n");
7264
+ import_node_fs10.default.writeSync(fd, wireText + "\n");
7203
7265
  } finally {
7204
- import_node_fs9.default.closeSync(fd);
7266
+ import_node_fs10.default.closeSync(fd);
7205
7267
  }
7206
7268
  updateSessionStatus(sessionId, {
7207
7269
  lastPrompt: prompt.displayText ?? prompt.text,
@@ -7223,7 +7285,7 @@ async function endSession(sessionId) {
7223
7285
  const base = getUserDataDir();
7224
7286
  if (dir.startsWith(base)) {
7225
7287
  try {
7226
- import_node_fs9.default.rmSync(dir, { recursive: true, force: true });
7288
+ import_node_fs10.default.rmSync(dir, { recursive: true, force: true });
7227
7289
  } catch {
7228
7290
  }
7229
7291
  }
@@ -7231,11 +7293,11 @@ async function endSession(sessionId) {
7231
7293
  }
7232
7294
  function subscribeEvents(sessionId, onEvent) {
7233
7295
  const fifo = eventsFifoPath(sessionId);
7234
- if (!import_node_fs9.default.existsSync(fifo)) {
7296
+ if (!import_node_fs10.default.existsSync(fifo)) {
7235
7297
  throw new AgentSessionError("NO_FIFO", `events FIFO missing: ${fifo}`);
7236
7298
  }
7237
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_RDWR);
7238
- const stream = import_node_fs9.default.createReadStream("", { fd, autoClose: true });
7299
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR);
7300
+ const stream = import_node_fs10.default.createReadStream("", { fd, autoClose: true });
7239
7301
  const rl = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
7240
7302
  rl.on("line", (line) => {
7241
7303
  const event = parseAgentEventLine(line);
@@ -7246,7 +7308,7 @@ function subscribeEvents(sessionId, onEvent) {
7246
7308
  if (closed) return;
7247
7309
  closed = true;
7248
7310
  try {
7249
- import_node_fs9.default.writeSync(fd, "\n");
7311
+ import_node_fs10.default.writeSync(fd, "\n");
7250
7312
  } catch {
7251
7313
  }
7252
7314
  try {
@@ -7260,7 +7322,7 @@ function subscribeEvents(sessionId, onEvent) {
7260
7322
  };
7261
7323
  }
7262
7324
  async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7263
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_RDWR | import_node_fs9.constants.O_NONBLOCK);
7325
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR | import_node_fs10.constants.O_NONBLOCK);
7264
7326
  const buf = Buffer.alloc(8192);
7265
7327
  let leftover = "";
7266
7328
  const deadline = Date.now() + timeoutMs;
@@ -7268,7 +7330,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7268
7330
  while (Date.now() < deadline) {
7269
7331
  let n = 0;
7270
7332
  try {
7271
- n = import_node_fs9.default.readSync(fd, buf, 0, buf.length, null);
7333
+ n = import_node_fs10.default.readSync(fd, buf, 0, buf.length, null);
7272
7334
  } catch (err) {
7273
7335
  if (err.code !== "EAGAIN") throw err;
7274
7336
  n = 0;
@@ -7288,7 +7350,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7288
7350
  }
7289
7351
  return null;
7290
7352
  } finally {
7291
- import_node_fs9.default.closeSync(fd);
7353
+ import_node_fs10.default.closeSync(fd);
7292
7354
  }
7293
7355
  }
7294
7356
 
@@ -7542,7 +7604,7 @@ var AgentHost = class {
7542
7604
  );
7543
7605
  const project = upsertProject({
7544
7606
  cwd: match.cwd,
7545
- name: match.projectName ?? import_node_path10.default.basename(match.cwd),
7607
+ name: match.projectName ?? import_node_path11.default.basename(match.cwd),
7546
7608
  preferredProvider: input.provider ?? existing?.preferredProvider,
7547
7609
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
7548
7610
  knownBundleUrls,
@@ -7553,18 +7615,18 @@ var AgentHost = class {
7553
7615
  }
7554
7616
  getTranscript(sessionId) {
7555
7617
  const p = transcriptPath(sessionId);
7556
- if (!import_node_fs10.default.existsSync(p)) {
7618
+ if (!import_node_fs11.default.existsSync(p)) {
7557
7619
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
7558
7620
  }
7559
- return import_node_fs10.default.readFileSync(p, "utf8");
7621
+ return import_node_fs11.default.readFileSync(p, "utf8");
7560
7622
  }
7561
7623
  getPaths() {
7562
7624
  const dir = getUserDataDir();
7563
7625
  return {
7564
7626
  userDataDir: dir,
7565
- storeFile: import_node_path10.default.join(dir, "attached-projects.json"),
7566
- sessionsDir: import_node_path10.default.join(dir, "sessions"),
7567
- transcriptsDir: import_node_path10.default.join(dir, "transcripts")
7627
+ storeFile: import_node_path11.default.join(dir, "attached-projects.json"),
7628
+ sessionsDir: import_node_path11.default.join(dir, "sessions"),
7629
+ transcriptsDir: import_node_path11.default.join(dir, "transcripts")
7568
7630
  };
7569
7631
  }
7570
7632
  // --- subscription management ---
@@ -8271,8 +8333,8 @@ async function openUrl(url, options = {}) {
8271
8333
  }
8272
8334
 
8273
8335
  // src/host/plane-host.ts
8274
- var import_node_fs12 = __toESM(require("node:fs"), 1);
8275
- var import_node_path12 = __toESM(require("node:path"), 1);
8336
+ var import_node_fs13 = __toESM(require("node:fs"), 1);
8337
+ var import_node_path13 = __toESM(require("node:path"), 1);
8276
8338
 
8277
8339
  // ../peach-box/src/planeProtocol.ts
8278
8340
  var PLANE_FLAG_READ_ONLY = 1;
@@ -8352,8 +8414,8 @@ async function dispatchPlaneCommand(plane, type, msg, mutationOptions) {
8352
8414
 
8353
8415
  // cli/commands/box/checkout-plane.ts
8354
8416
  var import_node_child_process4 = require("node:child_process");
8355
- var import_node_fs11 = __toESM(require("node:fs"), 1);
8356
- var import_node_path11 = __toESM(require("node:path"), 1);
8417
+ var import_node_fs12 = __toESM(require("node:fs"), 1);
8418
+ var import_node_path12 = __toESM(require("node:path"), 1);
8357
8419
  var CheckoutRequiresGitError = class extends Error {
8358
8420
  };
8359
8421
  var BINARY_SNIFF_BYTES = 8192;
@@ -8364,14 +8426,14 @@ function looksBinary(filePath, size) {
8364
8426
  if (size === 0) return false;
8365
8427
  let fd;
8366
8428
  try {
8367
- fd = import_node_fs11.default.openSync(filePath, "r");
8429
+ fd = import_node_fs12.default.openSync(filePath, "r");
8368
8430
  const buffer = Buffer.alloc(Math.min(BINARY_SNIFF_BYTES, size));
8369
- const read = import_node_fs11.default.readSync(fd, buffer, 0, buffer.length, 0);
8431
+ const read = import_node_fs12.default.readSync(fd, buffer, 0, buffer.length, 0);
8370
8432
  return buffer.subarray(0, read).includes(0);
8371
8433
  } catch {
8372
8434
  return false;
8373
8435
  } finally {
8374
- if (fd !== void 0) import_node_fs11.default.closeSync(fd);
8436
+ if (fd !== void 0) import_node_fs12.default.closeSync(fd);
8375
8437
  }
8376
8438
  }
8377
8439
  var CheckoutFilePlane = class {
@@ -8384,7 +8446,7 @@ var CheckoutFilePlane = class {
8384
8446
  listTimeoutMs;
8385
8447
  trackedOnly;
8386
8448
  constructor(root, options = {}) {
8387
- this.root = import_node_path11.default.resolve(root);
8449
+ this.root = import_node_path12.default.resolve(root);
8388
8450
  this.listTimeoutMs = options.listTimeoutMs ?? LIST_FILES_TIMEOUT_MS;
8389
8451
  this.trackedOnly = options.trackedOnly ?? false;
8390
8452
  }
@@ -8446,13 +8508,13 @@ var CheckoutFilePlane = class {
8446
8508
  if (!relative2) continue;
8447
8509
  let stat2;
8448
8510
  try {
8449
- stat2 = import_node_fs11.default.statSync(import_node_path11.default.join(this.root, relative2));
8511
+ stat2 = import_node_fs12.default.statSync(import_node_path12.default.join(this.root, relative2));
8450
8512
  } catch {
8451
8513
  continue;
8452
8514
  }
8453
8515
  if (!stat2.isFile()) continue;
8454
8516
  const seen = this.sniffed.get(relative2);
8455
- const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path11.default.join(this.root, relative2), stat2.size);
8517
+ const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path12.default.join(this.root, relative2), stat2.size);
8456
8518
  nextSniffed.set(relative2, { size: stat2.size, mtimeMs: stat2.mtimeMs, binary });
8457
8519
  next.set(relative2, {
8458
8520
  size: stat2.size,
@@ -8466,22 +8528,22 @@ var CheckoutFilePlane = class {
8466
8528
  this.sniffed = nextSniffed;
8467
8529
  }
8468
8530
  absolute(planePath) {
8469
- const resolved = import_node_path11.default.resolve(this.root, planePath);
8470
- if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path11.default.sep}`)) {
8531
+ const resolved = import_node_path12.default.resolve(this.root, planePath);
8532
+ if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path12.default.sep}`)) {
8471
8533
  throw new Error(`path escapes the project: ${planePath}`);
8472
8534
  }
8473
8535
  return resolved;
8474
8536
  }
8475
8537
  async read(planePath) {
8476
- return import_node_fs11.default.promises.readFile(this.absolute(planePath), "utf8");
8538
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath), "utf8");
8477
8539
  }
8478
8540
  async readBytes(planePath) {
8479
- return import_node_fs11.default.promises.readFile(this.absolute(planePath));
8541
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath));
8480
8542
  }
8481
8543
  async write(planePath, content) {
8482
8544
  const absolute = this.absolute(planePath);
8483
- await import_node_fs11.default.promises.mkdir(import_node_path11.default.dirname(absolute), { recursive: true });
8484
- await import_node_fs11.default.promises.writeFile(absolute, content);
8545
+ await import_node_fs12.default.promises.mkdir(import_node_path12.default.dirname(absolute), { recursive: true });
8546
+ await import_node_fs12.default.promises.writeFile(absolute, content);
8485
8547
  this.entries.set(planePath, {
8486
8548
  size: content.byteLength,
8487
8549
  readOnly: false,
@@ -8490,7 +8552,7 @@ var CheckoutFilePlane = class {
8490
8552
  });
8491
8553
  }
8492
8554
  async delete(planePath) {
8493
- await import_node_fs11.default.promises.rm(this.absolute(planePath), { force: true });
8555
+ await import_node_fs12.default.promises.rm(this.absolute(planePath), { force: true });
8494
8556
  this.entries.delete(planePath);
8495
8557
  }
8496
8558
  };
@@ -8616,14 +8678,14 @@ var PlaneHost = class {
8616
8678
  // root and an opened one cannot disagree about the same directory.
8617
8679
  realRoot(root) {
8618
8680
  if (!root) throw new Error("root is required");
8619
- const resolved = import_node_path12.default.resolve(root);
8681
+ const resolved = import_node_path13.default.resolve(root);
8620
8682
  let real;
8621
8683
  try {
8622
- real = import_node_fs12.default.realpathSync(resolved);
8684
+ real = import_node_fs13.default.realpathSync(resolved);
8623
8685
  } catch {
8624
8686
  throw new Error(`no such directory: ${resolved}`);
8625
8687
  }
8626
- if (!import_node_fs12.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8688
+ if (!import_node_fs13.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8627
8689
  return real;
8628
8690
  }
8629
8691
  respond(ws, id, result) {
@@ -8644,7 +8706,7 @@ var PlaneHost = class {
8644
8706
 
8645
8707
  // src/host/replacement-module-handler.ts
8646
8708
  var import_promises5 = __toESM(require("node:fs/promises"), 1);
8647
- var import_node_path13 = __toESM(require("node:path"), 1);
8709
+ var import_node_path14 = __toESM(require("node:path"), 1);
8648
8710
 
8649
8711
  // ../contrast-bundler/src/replacementModule.ts
8650
8712
  var import_dist = require("sucrase/dist/index.js");
@@ -8683,7 +8745,7 @@ function normalize(p) {
8683
8745
  if (trailingSlash) joined += "/";
8684
8746
  return absolute ? "/" + joined : joined;
8685
8747
  }
8686
- function join4(...parts) {
8748
+ function join5(...parts) {
8687
8749
  const present = parts.filter((part) => part.length > 0);
8688
8750
  if (present.length === 0) return ".";
8689
8751
  return normalize(present.join("/"));
@@ -8740,7 +8802,7 @@ var posix = {
8740
8802
  delimiter,
8741
8803
  isAbsolute,
8742
8804
  normalize,
8743
- join: join4,
8805
+ join: join5,
8744
8806
  resolve: resolve2,
8745
8807
  dirname: dirname3,
8746
8808
  basename: basename3,
@@ -8998,13 +9060,13 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
8998
9060
  res.end("missing path param");
8999
9061
  return true;
9000
9062
  }
9001
- const extension = import_node_path13.default.extname(targetPath).toLowerCase();
9063
+ const extension = import_node_path14.default.extname(targetPath).toLowerCase();
9002
9064
  if (!REPLACEMENT_MODULE_EXTENSIONS.some((allowed) => allowed === extension)) {
9003
9065
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9004
9066
  res.end(`replacement files must be ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")}`);
9005
9067
  return true;
9006
9068
  }
9007
- if (!import_node_path13.default.isAbsolute(targetPath)) {
9069
+ if (!import_node_path14.default.isAbsolute(targetPath)) {
9008
9070
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9009
9071
  res.end("replacement file path must be absolute");
9010
9072
  return true;
@@ -9012,10 +9074,10 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9012
9074
  const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
9013
9075
  let resolvedProjectRoot;
9014
9076
  if (options.projectRoot) {
9015
- const lexicalProjectRoot = import_node_path13.default.resolve(options.projectRoot);
9077
+ const lexicalProjectRoot = import_node_path14.default.resolve(options.projectRoot);
9016
9078
  resolvedProjectRoot = await import_promises5.default.realpath(options.projectRoot);
9017
- const lexicalTarget = import_node_path13.default.relative(lexicalProjectRoot, targetPath);
9018
- if (lexicalTarget.startsWith("..") || import_node_path13.default.isAbsolute(lexicalTarget)) {
9079
+ const lexicalTarget = import_node_path14.default.relative(lexicalProjectRoot, targetPath);
9080
+ if (lexicalTarget.startsWith("..") || import_node_path14.default.isAbsolute(lexicalTarget)) {
9019
9081
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9020
9082
  res.end("replacement file must be inside the project root");
9021
9083
  return true;
@@ -9031,8 +9093,8 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9031
9093
  return true;
9032
9094
  }
9033
9095
  if (resolvedProjectRoot) {
9034
- const relativeTarget = import_node_path13.default.relative(resolvedProjectRoot, resolvedTargetPath);
9035
- if (relativeTarget.startsWith("..") || import_node_path13.default.isAbsolute(relativeTarget)) {
9096
+ const relativeTarget = import_node_path14.default.relative(resolvedProjectRoot, resolvedTargetPath);
9097
+ if (relativeTarget.startsWith("..") || import_node_path14.default.isAbsolute(relativeTarget)) {
9036
9098
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9037
9099
  res.end("replacement file must be inside the project root");
9038
9100
  return true;
@@ -9494,7 +9556,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
9494
9556
  async startAsync(options) {
9495
9557
  if (this.httpServer || this.wss) return this.effectivePort;
9496
9558
  this.refreshActiveRuntime();
9497
- this.bootstrapping = !this.activeRuntimeDirPath || !import_fs3.default.existsSync(import_path3.default.join(this.activeRuntimeDirPath, "index.html"));
9559
+ this.bootstrapping = !this.activeRuntimeDirPath || !import_fs2.default.existsSync(import_path2.default.join(this.activeRuntimeDirPath, "index.html"));
9498
9560
  for (let attempt = 0; attempt < this.portFallbackCount; attempt++) {
9499
9561
  const candidate = this.preferredPort + attempt;
9500
9562
  try {
@@ -10166,10 +10228,10 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10166
10228
  return;
10167
10229
  }
10168
10230
  const root = cameraFixturesDir();
10169
- const filePath = import_path3.default.join(root, name2);
10231
+ const filePath = import_path2.default.join(root, name2);
10170
10232
  let stats;
10171
10233
  try {
10172
- stats = import_fs3.default.lstatSync(filePath);
10234
+ stats = import_fs2.default.lstatSync(filePath);
10173
10235
  } catch {
10174
10236
  res.writeHead(404, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
10175
10237
  res.end("not found");
@@ -10180,7 +10242,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10180
10242
  res.end("forbidden");
10181
10243
  return;
10182
10244
  }
10183
- const contentType = HTTP_MIME_TYPES[import_path3.default.extname(filePath).toLowerCase()] || "application/octet-stream";
10245
+ const contentType = HTTP_MIME_TYPES[import_path2.default.extname(filePath).toLowerCase()] || "application/octet-stream";
10184
10246
  sendFileWithRanges(req, res, filePath, stats.size, {
10185
10247
  ...cors,
10186
10248
  "Content-Type": contentType
@@ -10214,7 +10276,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10214
10276
  }
10215
10277
  startRuntimeUpdater() {
10216
10278
  if (!this.shouldWriteLockfile || this.runtimeUpdateTimer) return;
10217
- if (import_fs3.default.existsSync(import_path3.default.join(rnxHomeDir(), "runtime-update-disabled"))) {
10279
+ if (!automaticPeachUpdatesEnabled()) {
10218
10280
  this.bootstrapping = false;
10219
10281
  if (this.httpServer) this.writeLockfileSnapshot();
10220
10282
  return;
@@ -10230,6 +10292,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10230
10292
  this.runtimeUpdateTimer.unref();
10231
10293
  }
10232
10294
  runRuntimeUpdate(reason) {
10295
+ if (!automaticPeachUpdatesEnabled()) return Promise.resolve();
10233
10296
  if (this.runtimeUpdateInFlight) return this.runtimeUpdateInFlight;
10234
10297
  this.runtimeUpdateInFlight = (async () => {
10235
10298
  try {
@@ -10556,34 +10619,34 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10556
10619
  return;
10557
10620
  }
10558
10621
  }
10559
- const resolved = import_path3.default.resolve(baseDir, "." + rel);
10560
- const baseWithSep = baseDir.endsWith(import_path3.default.sep) ? baseDir : baseDir + import_path3.default.sep;
10622
+ const resolved = import_path2.default.resolve(baseDir, "." + rel);
10623
+ const baseWithSep = baseDir.endsWith(import_path2.default.sep) ? baseDir : baseDir + import_path2.default.sep;
10561
10624
  if (!resolved.startsWith(baseWithSep) && resolved !== baseDir) {
10562
10625
  res.writeHead(403);
10563
10626
  res.end("forbidden");
10564
10627
  return;
10565
10628
  }
10566
- import_fs3.default.realpath(resolved, (realErr, realResolved) => {
10629
+ import_fs2.default.realpath(resolved, (realErr, realResolved) => {
10567
10630
  const servePath = realErr ? resolved : realResolved;
10568
- const servePathWithSep = servePath.endsWith(import_path3.default.sep) ? servePath : servePath + import_path3.default.sep;
10631
+ const servePathWithSep = servePath.endsWith(import_path2.default.sep) ? servePath : servePath + import_path2.default.sep;
10569
10632
  if (!realErr) {
10570
10633
  const realBaseWithSep = (() => {
10571
10634
  try {
10572
- const rb = import_fs3.default.realpathSync(baseDir);
10573
- return rb.endsWith(import_path3.default.sep) ? rb : rb + import_path3.default.sep;
10635
+ const rb = import_fs2.default.realpathSync(baseDir);
10636
+ return rb.endsWith(import_path2.default.sep) ? rb : rb + import_path2.default.sep;
10574
10637
  } catch {
10575
10638
  return baseWithSep;
10576
10639
  }
10577
10640
  })();
10578
- if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path3.default.sep !== realBaseWithSep) {
10641
+ if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path2.default.sep !== realBaseWithSep) {
10579
10642
  res.writeHead(403);
10580
10643
  res.end("forbidden");
10581
10644
  return;
10582
10645
  }
10583
10646
  }
10584
- import_fs3.default.stat(servePath, (err, stats) => {
10647
+ import_fs2.default.stat(servePath, (err, stats) => {
10585
10648
  if (err || !stats?.isFile()) {
10586
- const ext2 = import_path3.default.extname(rel).toLowerCase();
10649
+ const ext2 = import_path2.default.extname(rel).toLowerCase();
10587
10650
  if (ext2 && ext2 !== ".html") {
10588
10651
  res.writeHead(404);
10589
10652
  res.end("not found");
@@ -10594,8 +10657,8 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10594
10657
  res.end("not found");
10595
10658
  return;
10596
10659
  }
10597
- const indexPath = import_path3.default.join(baseDir, "index.html");
10598
- import_fs3.default.readFile(indexPath, (err2, data) => {
10660
+ const indexPath = import_path2.default.join(baseDir, "index.html");
10661
+ import_fs2.default.readFile(indexPath, (err2, data) => {
10599
10662
  if (err2) {
10600
10663
  res.writeHead(404);
10601
10664
  res.end("not found");
@@ -10615,7 +10678,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10615
10678
  });
10616
10679
  return;
10617
10680
  }
10618
- const ext = import_path3.default.extname(servePath).toLowerCase();
10681
+ const ext = import_path2.default.extname(servePath).toLowerCase();
10619
10682
  const contentType = HTTP_MIME_TYPES[ext] || "application/octet-stream";
10620
10683
  res.writeHead(200, {
10621
10684
  "Content-Type": contentType,
@@ -10626,7 +10689,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10626
10689
  return;
10627
10690
  }
10628
10691
  if (ext === ".html") {
10629
- import_fs3.default.readFile(servePath, (readErr, data) => {
10692
+ import_fs2.default.readFile(servePath, (readErr, data) => {
10630
10693
  if (readErr) {
10631
10694
  try {
10632
10695
  res.end();
@@ -10640,7 +10703,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10640
10703
  });
10641
10704
  return;
10642
10705
  }
10643
- const stream = import_fs3.default.createReadStream(servePath);
10706
+ const stream = import_fs2.default.createReadStream(servePath);
10644
10707
  stream.pipe(res);
10645
10708
  stream.on("error", () => {
10646
10709
  try {