peachsim 0.1.629 → 0.1.630

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +8 -4
  2. package/cli/bridge-flow-runner.ts +10 -3
  3. package/cli/cli-update.ts +2 -7
  4. package/cli/cloud-test-tunnel.ts +16 -3
  5. package/cli/commands/config.ts +1 -1
  6. package/cli/commands/control.ts +28 -3
  7. package/cli/commands/daemon-mac-app.ts +4 -2
  8. package/cli/commands/daemon.ts +4 -4
  9. package/cli/commands/device.ts +2 -3
  10. package/cli/commands/inspect/actions.ts +125 -90
  11. package/cli/commands/inspect.ts +6 -1
  12. package/cli/commands/platform.ts +1 -1
  13. package/cli/commands/screenshot-layers.ts +1 -1
  14. package/cli/commands/screenshot.ts +1 -1
  15. package/cli/commands/skills.ts +0 -31
  16. package/cli/drivers/playwright-provisioning.ts +3 -2
  17. package/cli/drivers/playwright-sim-host.ts +25 -9
  18. package/cli/main.ts +8 -2
  19. package/cli/outbound-endpoints.ts +0 -4
  20. package/detox/index.ts +74 -43
  21. package/dist-lib/agent-daemon-client.cjs +1 -1
  22. package/dist-lib/agent-events.cjs +1 -1
  23. package/dist-lib/agent-identity.cjs +1 -1
  24. package/dist-lib/agent-sessions.cjs +1 -1
  25. package/dist-lib/attached-projects.cjs +1 -1
  26. package/dist-lib/auth/shared-session.cjs +1 -1
  27. package/dist-lib/backend-origin.cjs +1 -1
  28. package/dist-lib/beta.cjs +1 -1
  29. package/dist-lib/beta.mjs +1 -1
  30. package/dist-lib/bridge-constants.cjs +1 -1
  31. package/dist-lib/bridge-contract-input.cjs +1 -1
  32. package/dist-lib/bridge-contract-input.mjs +1 -1
  33. package/dist-lib/bridge-contract.cjs +1 -1
  34. package/dist-lib/bridge-contract.mjs +1 -1
  35. package/dist-lib/capture-contract.cjs +1 -1
  36. package/dist-lib/capture-contract.mjs +1 -1
  37. package/dist-lib/cli-constants.cjs +1 -1
  38. package/dist-lib/cloud-contract.cjs +1 -1
  39. package/dist-lib/cloud-contract.mjs +1 -1
  40. package/dist-lib/cloud-test-args.cjs +1 -1
  41. package/dist-lib/cloud-test-args.mjs +1 -1
  42. package/dist-lib/cloud.cjs +1 -1
  43. package/dist-lib/cloud.mjs +1 -1
  44. package/dist-lib/config.cjs +1 -1
  45. package/dist-lib/detox/index.cjs +129 -27
  46. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  47. package/dist-lib/home-paths.cjs +1 -1
  48. package/dist-lib/host/bridge-host.cjs +275 -255
  49. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  50. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  51. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  52. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  53. package/dist-lib/host/websocket-proxy.cjs +1 -1
  54. package/dist-lib/index.cjs +253 -121
  55. package/dist-lib/jump-to-source-babel.cjs +1 -1
  56. package/dist-lib/jump-to-source-native.cjs +1 -1
  57. package/dist-lib/{vite-kotlin.cjs → kotlin-host.cjs} +130 -19
  58. package/dist-lib/menu.cjs +1 -1
  59. package/dist-lib/menu.mjs +1 -1
  60. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  61. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  62. package/dist-lib/metro-production-bundle.cjs +1 -1
  63. package/dist-lib/metro-production-bundle.mjs +1 -1
  64. package/dist-lib/metro.cjs +132 -9
  65. package/dist-lib/native-app-identity.cjs +278 -0
  66. package/dist-lib/native-app-identity.mjs +245 -0
  67. package/dist-lib/profiles.cjs +1 -1
  68. package/dist-lib/public-brand.cjs +1 -1
  69. package/dist-lib/react-native-host-modules.cjs +1 -1
  70. package/dist-lib/react-native-host-modules.mjs +1 -1
  71. package/dist-lib/render-mode.cjs +1 -1
  72. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  73. package/dist-lib/sdk.cjs +110 -87
  74. package/dist-lib/sdk.mjs +110 -87
  75. package/dist-lib/skills.cjs +822 -582
  76. package/dist-lib/swift-compile.cjs +1 -1
  77. package/dist-lib/swift-compile.mjs +1 -1
  78. package/dist-lib/swift-package.cjs +1 -1
  79. package/dist-lib/swift-package.mjs +1 -1
  80. package/dist-lib/swift-submit.cjs +1 -1
  81. package/dist-lib/swift-submit.mjs +1 -1
  82. package/dist-lib/swift.cjs +234 -109
  83. package/dist-lib/vite-swift.cjs +1 -1
  84. package/dist-lib/vite.cjs +11 -28
  85. package/kotlin/README.md +32 -4
  86. package/kotlin/fixtures/counter/Counter.kt +26 -0
  87. package/kotlin/fixtures/counter/CounterScreen.kt +40 -0
  88. package/kotlin/fixtures/headless-counter/Headless.kt +228 -0
  89. package/kotlin/fixtures/runtime-state/RuntimeState.kt +200 -0
  90. package/kotlin/fork/LICENSE +178 -0
  91. package/kotlin/fork/NOTICE +25 -0
  92. package/kotlin/fork/README.md +59 -0
  93. package/kotlin/fork/build.sh +128 -0
  94. package/kotlin/fork/compose-worker-globals.patch +96 -0
  95. package/kotlin/fork/fork.json +33 -0
  96. package/kotlin/fork/publish.ts +77 -0
  97. package/kotlin/fork/skiko-worker-clock.patch +33 -0
  98. package/kotlin/toolchain.json +288 -0
  99. package/package.json +12 -5
  100. package/src/automatic-update-policy.ts +17 -0
  101. package/src/host/bridge-host.ts +3 -1
  102. package/src/{vite-plugin-kotlin.ts → kotlin-host.ts} +155 -12
  103. package/src/metro-plugin.ts +18 -0
  104. package/src/native-app-identity.ts +376 -0
  105. package/src/native-firebase-config.ts +90 -0
  106. package/src/screenshots/frame-compose.ts +1 -1
  107. package/src/screenshots/registry.ts +1 -1
  108. package/src/screenshots/schema.ts +2 -2
  109. package/src/vite-plugin-one.ts +11 -28
  110. 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.630 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -120,23 +120,6 @@ var init_optional_demo_registry = __esm({
120
120
  }
121
121
  });
122
122
 
123
- // src/public-brand.ts
124
- var name, peachPublicBrand, rnxPublicBrand;
125
- var init_public_brand = __esm({
126
- "src/public-brand.ts"() {
127
- "use strict";
128
- name = "Peach";
129
- peachPublicBrand = Object.freeze({
130
- name,
131
- packageName: "peachsim",
132
- commandName: "peach",
133
- domain: "peachsim.com",
134
- origin: "https://peachsim.com"
135
- });
136
- rnxPublicBrand = peachPublicBrand;
137
- }
138
- });
139
-
140
123
  // src/home-paths.ts
141
124
  function rnxHomeDir() {
142
125
  const override = process.env[PEACH_HOME_ENV];
@@ -151,7 +134,7 @@ function isSootsimDevCheckout() {
151
134
  const argv1 = process.argv[1];
152
135
  if (!argv1) return false;
153
136
  try {
154
- const real = import_node_fs4.default.realpathSync(argv1);
137
+ const real = import_node_fs3.default.realpathSync(argv1);
155
138
  return real.includes(`${import_node_path4.default.sep}packages${import_node_path4.default.sep}peachsim${import_node_path4.default.sep}`);
156
139
  } catch {
157
140
  return false;
@@ -198,7 +181,7 @@ function configFilePath() {
198
181
  }
199
182
  function readSharedConfig() {
200
183
  try {
201
- const raw = import_node_fs4.default.readFileSync(configFilePath(), "utf8");
184
+ const raw = import_node_fs3.default.readFileSync(configFilePath(), "utf8");
202
185
  const parsed = JSON.parse(raw);
203
186
  return parsed && typeof parsed === "object" ? parsed : {};
204
187
  } catch {
@@ -216,9 +199,9 @@ function writeSharedConfig(patch) {
216
199
  };
217
200
  }
218
201
  const tmp = `${configFilePath()}.tmp`;
219
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
202
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
220
203
  `, "utf8");
221
- import_node_fs4.default.renameSync(tmp, configFilePath());
204
+ import_node_fs3.default.renameSync(tmp, configFilePath());
222
205
  return next;
223
206
  }
224
207
  function runtimeUpgradeNoticePath() {
@@ -227,28 +210,28 @@ function runtimeUpgradeNoticePath() {
227
210
  function writeRuntimeUpgradeNotice(notice) {
228
211
  ensureRnxHome();
229
212
  const tmp = `${runtimeUpgradeNoticePath()}.tmp`;
230
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(notice)}
213
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(notice)}
231
214
  `, "utf8");
232
- import_node_fs4.default.renameSync(tmp, runtimeUpgradeNoticePath());
215
+ import_node_fs3.default.renameSync(tmp, runtimeUpgradeNoticePath());
233
216
  }
234
217
  function ensureRnxHome() {
235
- import_node_fs4.default.mkdirSync(rnxHomeDir(), { recursive: true });
236
- import_node_fs4.default.mkdirSync(runtimesDir(), { recursive: true });
237
- import_node_fs4.default.mkdirSync(electronDir(), { recursive: true });
238
- import_node_fs4.default.mkdirSync(profilesDir(), { recursive: true });
239
- import_node_fs4.default.mkdirSync(cacheDir(), { recursive: true });
218
+ import_node_fs3.default.mkdirSync(rnxHomeDir(), { recursive: true });
219
+ import_node_fs3.default.mkdirSync(runtimesDir(), { recursive: true });
220
+ import_node_fs3.default.mkdirSync(electronDir(), { recursive: true });
221
+ import_node_fs3.default.mkdirSync(profilesDir(), { recursive: true });
222
+ import_node_fs3.default.mkdirSync(cacheDir(), { recursive: true });
240
223
  }
241
224
  function readActiveRuntime() {
242
225
  try {
243
- const value = import_node_fs4.default.readFileSync(activeRuntimeFile(), "utf8").trim();
226
+ const value = import_node_fs3.default.readFileSync(activeRuntimeFile(), "utf8").trim();
244
227
  return value.length > 0 ? value : null;
245
228
  } catch {
246
229
  return null;
247
230
  }
248
231
  }
249
232
  function writeActiveRuntime(version) {
250
- import_node_fs4.default.mkdirSync(runtimesDir(), { recursive: true });
251
- import_node_fs4.default.writeFileSync(activeRuntimeFile(), `${version}
233
+ import_node_fs3.default.mkdirSync(runtimesDir(), { recursive: true });
234
+ import_node_fs3.default.writeFileSync(activeRuntimeFile(), `${version}
252
235
  `, "utf8");
253
236
  }
254
237
  function activeRuntimeDir() {
@@ -256,17 +239,17 @@ function activeRuntimeDir() {
256
239
  if (!version) return null;
257
240
  const dir = runtimeDir(version);
258
241
  try {
259
- if (import_node_fs4.default.statSync(dir).isDirectory()) return dir;
242
+ if (import_node_fs3.default.statSync(dir).isDirectory()) return dir;
260
243
  } catch {
261
244
  }
262
245
  return null;
263
246
  }
264
247
  function readDaemonLockfile() {
265
248
  try {
266
- const fd = import_node_fs4.default.openSync(daemonLockfilePath(), "r");
249
+ const fd = import_node_fs3.default.openSync(daemonLockfilePath(), "r");
267
250
  try {
268
251
  const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
269
- const bytesRead = import_node_fs4.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
252
+ const bytesRead = import_node_fs3.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
270
253
  const raw = buf.subarray(0, bytesRead).toString("utf8");
271
254
  const parsed = JSON.parse(raw);
272
255
  if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
@@ -274,7 +257,7 @@ function readDaemonLockfile() {
274
257
  }
275
258
  return null;
276
259
  } finally {
277
- import_node_fs4.default.closeSync(fd);
260
+ import_node_fs3.default.closeSync(fd);
278
261
  }
279
262
  } catch {
280
263
  return null;
@@ -313,28 +296,28 @@ function writeDaemonLockfile(data) {
313
296
  throw new Error("refusing to overwrite another peach daemon lockfile");
314
297
  }
315
298
  const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
316
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
299
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
317
300
  `, "utf8");
318
301
  try {
319
302
  const current = readDaemonLockfile();
320
303
  if (!current || !sameDaemonOwner(current, data)) {
321
304
  throw new Error("peach daemon lock ownership changed during heartbeat");
322
305
  }
323
- import_node_fs4.default.renameSync(tmp, lockfilePath);
306
+ import_node_fs3.default.renameSync(tmp, lockfilePath);
324
307
  } finally {
325
308
  try {
326
- import_node_fs4.default.unlinkSync(tmp);
309
+ import_node_fs3.default.unlinkSync(tmp);
327
310
  } catch {
328
311
  }
329
312
  }
330
313
  }
331
314
  function writeDevBridgeLockfile(data) {
332
- import_node_fs4.default.mkdirSync(devBridgesDir(), { recursive: true });
315
+ import_node_fs3.default.mkdirSync(devBridgesDir(), { recursive: true });
333
316
  const lockfilePath = devBridgeLockfilePath(data.bridgePort);
334
317
  const tmp = `${lockfilePath}.${data.pid}.tmp`;
335
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
318
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
336
319
  `, "utf8");
337
- import_node_fs4.default.renameSync(tmp, lockfilePath);
320
+ import_node_fs3.default.renameSync(tmp, lockfilePath);
338
321
  }
339
322
  function sameDaemonOwner(left, right) {
340
323
  return left.pid === right.pid && left.startedAt === right.startedAt;
@@ -345,17 +328,17 @@ function isAlreadyExists(error) {
345
328
  function createDaemonLockfileExclusive(data) {
346
329
  const lockfilePath = daemonLockfilePath();
347
330
  const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.claim`;
348
- import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
331
+ import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
349
332
  `, "utf8");
350
333
  try {
351
- import_node_fs4.default.linkSync(tmp, lockfilePath);
334
+ import_node_fs3.default.linkSync(tmp, lockfilePath);
352
335
  return true;
353
336
  } catch (error) {
354
337
  if (isAlreadyExists(error)) return false;
355
338
  throw error;
356
339
  } finally {
357
340
  try {
358
- import_node_fs4.default.unlinkSync(tmp);
341
+ import_node_fs3.default.unlinkSync(tmp);
359
342
  } catch {
360
343
  }
361
344
  }
@@ -379,7 +362,7 @@ function parseDaemonClaim(raw) {
379
362
  }
380
363
  function readDaemonClaim() {
381
364
  try {
382
- return parseDaemonClaim(import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8"));
365
+ return parseDaemonClaim(import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8"));
383
366
  } catch {
384
367
  return null;
385
368
  }
@@ -403,7 +386,7 @@ function acquireDaemonClaim(data) {
403
386
  `;
404
387
  for (let attempt = 0; attempt < 8; attempt++) {
405
388
  try {
406
- import_node_fs4.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
389
+ import_node_fs3.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
407
390
  return true;
408
391
  } catch (error) {
409
392
  if (!isAlreadyExists(error)) throw error;
@@ -413,11 +396,11 @@ function acquireDaemonClaim(data) {
413
396
  if (existing && isDaemonClaimFresh(existing)) return false;
414
397
  let before;
415
398
  try {
416
- before = import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8");
399
+ before = import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8");
417
400
  const latest = parseDaemonClaim(before);
418
401
  if (latest && isDaemonClaimFresh(latest)) return false;
419
- if (import_node_fs4.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
420
- import_node_fs4.default.unlinkSync(daemonClaimPath());
402
+ if (import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
403
+ import_node_fs3.default.unlinkSync(daemonClaimPath());
421
404
  } catch {
422
405
  }
423
406
  }
@@ -427,7 +410,7 @@ function releaseDaemonClaim(owner) {
427
410
  try {
428
411
  const claim = readDaemonClaim();
429
412
  if (!claim || !sameDaemonOwner(claim, owner)) return;
430
- import_node_fs4.default.unlinkSync(daemonClaimPath());
413
+ import_node_fs3.default.unlinkSync(daemonClaimPath());
431
414
  } catch {
432
415
  }
433
416
  }
@@ -446,7 +429,7 @@ function claimDaemonLockfile(data) {
446
429
  if (!latest || !sameDaemonOwner(latest, existing)) return false;
447
430
  if (isDaemonLockfileFresh(latest)) return false;
448
431
  try {
449
- import_node_fs4.default.unlinkSync(daemonLockfilePath());
432
+ import_node_fs3.default.unlinkSync(daemonLockfilePath());
450
433
  } catch {
451
434
  return false;
452
435
  }
@@ -460,25 +443,25 @@ function removeDaemonLockfile(owner) {
460
443
  try {
461
444
  const lockfile = readDaemonLockfile();
462
445
  if (!lockfile || !sameDaemonOwner(lockfile, owner)) return;
463
- import_node_fs4.default.unlinkSync(daemonLockfilePath());
446
+ import_node_fs3.default.unlinkSync(daemonLockfilePath());
464
447
  } catch {
465
448
  }
466
449
  }
467
450
  function removeDevBridgeLockfile(owner) {
468
451
  try {
469
452
  const lockfilePath = devBridgeLockfilePath(owner.bridgePort);
470
- const lockfile = parseDevBridgeLockfile(import_node_fs4.default.readFileSync(lockfilePath, "utf8"));
453
+ const lockfile = parseDevBridgeLockfile(import_node_fs3.default.readFileSync(lockfilePath, "utf8"));
471
454
  if (lockfile?.pid !== owner.pid || lockfile.startedAt !== owner.startedAt) return;
472
- import_node_fs4.default.unlinkSync(lockfilePath);
455
+ import_node_fs3.default.unlinkSync(lockfilePath);
473
456
  } catch {
474
457
  }
475
458
  }
476
- var import_node_crypto, import_node_fs4, import_node_os, import_node_path4, PEACH_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
459
+ var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, PEACH_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
477
460
  var init_home_paths = __esm({
478
461
  "src/home-paths.ts"() {
479
462
  "use strict";
480
463
  import_node_crypto = require("node:crypto");
481
- import_node_fs4 = __toESM(require("node:fs"), 1);
464
+ import_node_fs3 = __toESM(require("node:fs"), 1);
482
465
  import_node_os = require("node:os");
483
466
  import_node_path4 = __toESM(require("node:path"), 1);
484
467
  PEACH_HOME_ENV = "PEACH_HOME";
@@ -492,6 +475,23 @@ var init_home_paths = __esm({
492
475
  }
493
476
  });
494
477
 
478
+ // src/public-brand.ts
479
+ var name, peachPublicBrand, rnxPublicBrand;
480
+ var init_public_brand = __esm({
481
+ "src/public-brand.ts"() {
482
+ "use strict";
483
+ name = "Peach";
484
+ peachPublicBrand = Object.freeze({
485
+ name,
486
+ packageName: "peachsim",
487
+ commandName: "peach",
488
+ domain: "peachsim.com",
489
+ origin: "https://peachsim.com"
490
+ });
491
+ rnxPublicBrand = peachPublicBrand;
492
+ }
493
+ });
494
+
495
495
  // src/auth/shared-session.ts
496
496
  function sharedDesktopAuthAccounts(user) {
497
497
  return [
@@ -502,14 +502,14 @@ function sharedDesktopAuthAccounts(user) {
502
502
  function getBaseDir() {
503
503
  const explicit = process.env[SESSION_FILE_ENV];
504
504
  if (explicit?.trim()) {
505
- return (0, import_node_path14.dirname)((0, import_node_path14.resolve)(explicit));
505
+ return (0, import_node_path15.dirname)((0, import_node_path15.resolve)(explicit));
506
506
  }
507
507
  return electronUserDataDir();
508
508
  }
509
509
  function getSharedDesktopAuthFilePath() {
510
510
  const explicit = process.env[SESSION_FILE_ENV];
511
- if (explicit?.trim()) return (0, import_node_path14.resolve)(explicit);
512
- return (0, import_node_path14.join)(getBaseDir(), "desktop-auth.json");
511
+ if (explicit?.trim()) return (0, import_node_path15.resolve)(explicit);
512
+ return (0, import_node_path15.join)(getBaseDir(), "desktop-auth.json");
513
513
  }
514
514
  function normalizeUser(input) {
515
515
  if (!input || typeof input !== "object") return null;
@@ -559,26 +559,26 @@ function normalizeSession(input) {
559
559
  }
560
560
  function readSharedDesktopAuthSession() {
561
561
  const filepath = getSharedDesktopAuthFilePath();
562
- if (!(0, import_node_fs13.existsSync)(filepath)) return null;
562
+ if (!(0, import_node_fs14.existsSync)(filepath)) return null;
563
563
  try {
564
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)(filepath, "utf8"));
564
+ const parsed = JSON.parse((0, import_node_fs14.readFileSync)(filepath, "utf8"));
565
565
  const normalized = normalizeSession(parsed);
566
566
  if (!normalized) {
567
- (0, import_node_fs13.rmSync)(filepath, { force: true });
567
+ (0, import_node_fs14.rmSync)(filepath, { force: true });
568
568
  return null;
569
569
  }
570
570
  return normalized;
571
571
  } catch {
572
- (0, import_node_fs13.rmSync)(filepath, { force: true });
572
+ (0, import_node_fs14.rmSync)(filepath, { force: true });
573
573
  return null;
574
574
  }
575
575
  }
576
- var import_node_fs13, import_node_path14, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
576
+ var import_node_fs14, import_node_path15, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
577
577
  var init_shared_session = __esm({
578
578
  "src/auth/shared-session.ts"() {
579
579
  "use strict";
580
- import_node_fs13 = require("node:fs");
581
- import_node_path14 = require("node:path");
580
+ import_node_fs14 = require("node:fs");
581
+ import_node_path15 = require("node:path");
582
582
  init_home_paths();
583
583
  SESSION_VERSION = 1;
584
584
  SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
@@ -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",
@@ -4006,21 +4016,21 @@ function resolveCloudOrigin(value) {
4006
4016
  return normalizeCloudOrigin(source);
4007
4017
  }
4008
4018
  function readImmutableBundleSource(bundlePath) {
4009
- const filepath = (0, import_node_path15.resolve)(bundlePath);
4010
- if ((0, import_node_path15.extname)(filepath) !== ".js") {
4019
+ const filepath = (0, import_node_path16.resolve)(bundlePath);
4020
+ if ((0, import_node_path16.extname)(filepath) !== ".js") {
4011
4021
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
4012
4022
  }
4013
- const descriptor = (0, import_node_fs14.openSync)(filepath, "r");
4023
+ const descriptor = (0, import_node_fs15.openSync)(filepath, "r");
4014
4024
  try {
4015
- const before = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4025
+ const before = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4016
4026
  if (!before.isFile()) {
4017
4027
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
4018
4028
  }
4019
4029
  if (before.size <= 0n) {
4020
4030
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
4021
4031
  }
4022
- const bytes = (0, import_node_fs14.readFileSync)(descriptor);
4023
- const after = (0, import_node_fs14.fstatSync)(descriptor, { bigint: true });
4032
+ const bytes = (0, import_node_fs15.readFileSync)(descriptor);
4033
+ const after = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4024
4034
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
4025
4035
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
4026
4036
  }
@@ -4035,7 +4045,7 @@ function readImmutableBundleSource(bundlePath) {
4035
4045
  }
4036
4046
  return source;
4037
4047
  } finally {
4038
- (0, import_node_fs14.closeSync)(descriptor);
4048
+ (0, import_node_fs15.closeSync)(descriptor);
4039
4049
  }
4040
4050
  }
4041
4051
  async function fetchBundleSource(bundleUrl) {
@@ -4082,15 +4092,15 @@ async function loadBundleSource(bundleInput) {
4082
4092
  return readImmutableBundleSource(bundleInput);
4083
4093
  }
4084
4094
  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"));
4095
+ const directory = (0, import_node_path16.resolve)(assetsPath);
4096
+ if (!(0, import_node_fs15.existsSync)(directory)) return { directory, files: [], truncated: false };
4097
+ const skipNested = (0, import_node_fs15.existsSync)((0, import_node_path16.join)(directory, "package.json"));
4088
4098
  const files = [];
4089
4099
  let truncated = false;
4090
4100
  const walk = (dir, prefix) => {
4091
4101
  let entries;
4092
4102
  try {
4093
- entries = (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true });
4103
+ entries = (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true });
4094
4104
  } catch {
4095
4105
  return;
4096
4106
  }
@@ -4102,7 +4112,7 @@ function listMetroAssetDest(assetsPath) {
4102
4112
  if (entry.isDirectory()) {
4103
4113
  if (entry.name === ".git") continue;
4104
4114
  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);
4115
+ walk((0, import_node_path16.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4106
4116
  } else if (entry.isFile()) {
4107
4117
  files.push(prefix ? `${prefix}/${entry.name}` : entry.name);
4108
4118
  }
@@ -4137,7 +4147,7 @@ function distinctByContent(directory, options) {
4137
4147
  for (const relative2 of options) {
4138
4148
  let bytes;
4139
4149
  try {
4140
- bytes = (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(directory, relative2));
4150
+ bytes = (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(directory, relative2));
4141
4151
  } catch {
4142
4152
  continue;
4143
4153
  }
@@ -4169,7 +4179,7 @@ function placeMetroDescriptor(listing, descriptor) {
4169
4179
  let bytes;
4170
4180
  try {
4171
4181
  bytes = combination.map(
4172
- (relative2) => (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(listing.directory, relative2))
4182
+ (relative2) => (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(listing.directory, relative2))
4173
4183
  );
4174
4184
  } catch {
4175
4185
  continue;
@@ -4195,26 +4205,26 @@ function placeMetroDescriptor(listing, descriptor) {
4195
4205
  }
4196
4206
  function unverifiedFileKey(dest) {
4197
4207
  return dest.placements.filter((placement) => !placement.verified).flatMap(
4198
- (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path15.join)(dest.directory, relative2))
4208
+ (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path16.join)(dest.directory, relative2))
4199
4209
  ).sort().join("\n");
4200
4210
  }
4201
4211
  function searchMetroAssetDest(bundlePath, descriptors) {
4202
- const bundleDirectory = (0, import_node_path15.dirname)((0, import_node_path15.resolve)(bundlePath));
4212
+ const bundleDirectory = (0, import_node_path16.dirname)((0, import_node_path16.resolve)(bundlePath));
4203
4213
  const candidates = [
4204
- (0, import_node_path15.join)(bundleDirectory, "assets"),
4214
+ (0, import_node_path16.join)(bundleDirectory, "assets"),
4205
4215
  bundleDirectory,
4206
- (0, import_node_path15.resolve)(bundleDirectory, "..", "assets")
4216
+ (0, import_node_path16.resolve)(bundleDirectory, "..", "assets")
4207
4217
  ];
4208
4218
  const cwd = process.cwd();
4209
4219
  let projectDirectory = null;
4210
4220
  for (const start of [bundleDirectory, cwd]) {
4211
- let directory = (0, import_node_path15.resolve)(start);
4221
+ let directory = (0, import_node_path16.resolve)(start);
4212
4222
  while (true) {
4213
4223
  if (detectProject(directory)?.hasMetroConfig) {
4214
4224
  projectDirectory = directory;
4215
4225
  break;
4216
4226
  }
4217
- const parent = (0, import_node_path15.dirname)(directory);
4227
+ const parent = (0, import_node_path16.dirname)(directory);
4218
4228
  if (parent === directory) break;
4219
4229
  directory = parent;
4220
4230
  }
@@ -4222,11 +4232,11 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4222
4232
  }
4223
4233
  if (projectDirectory) {
4224
4234
  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")
4235
+ (0, import_node_path16.join)(projectDirectory, "assets"),
4236
+ (0, import_node_path16.join)(projectDirectory, "dist"),
4237
+ (0, import_node_path16.join)(projectDirectory, "dist", "assets"),
4238
+ (0, import_node_path16.join)(projectDirectory, "build"),
4239
+ (0, import_node_path16.join)(projectDirectory, "build", "assets")
4230
4240
  );
4231
4241
  }
4232
4242
  const searched = [];
@@ -4234,7 +4244,7 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4234
4244
  const stale = [];
4235
4245
  let truncated = false;
4236
4246
  for (const candidate of candidates) {
4237
- const directory = (0, import_node_path15.resolve)(candidate);
4247
+ const directory = (0, import_node_path16.resolve)(candidate);
4238
4248
  if (searched.includes(directory)) continue;
4239
4249
  searched.push(directory);
4240
4250
  const listing = listMetroAssetDest(directory);
@@ -4340,7 +4350,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4340
4350
  );
4341
4351
  }
4342
4352
  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));
4353
+ if (relative2 && dest) return (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(dest.directory, relative2));
4344
4354
  if (placement && placement.files.size > 0) return null;
4345
4355
  if (placement && placement.ambiguous.length > 0 && dest) {
4346
4356
  throw new Error(
@@ -4369,7 +4379,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4369
4379
  );
4370
4380
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
4371
4381
  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\`.`
4382
+ `${command} could not read ${(0, import_node_path16.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Rebuild with \`react-native bundle --assets-dest\`.`
4373
4383
  );
4374
4384
  });
4375
4385
  return {
@@ -4515,13 +4525,13 @@ async function createCloudBox(options) {
4515
4525
  warnings: artifact.warnings
4516
4526
  };
4517
4527
  }
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;
4528
+ var import_node_crypto6, import_node_fs15, import_node_path16, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4519
4529
  var init_cloud_client = __esm({
4520
4530
  "cli/cloud-client.ts"() {
4521
4531
  "use strict";
4522
4532
  import_node_crypto6 = require("node:crypto");
4523
- import_node_fs14 = require("node:fs");
4524
- import_node_path15 = require("node:path");
4533
+ import_node_fs15 = require("node:fs");
4534
+ import_node_path16 = require("node:path");
4525
4535
  init_metroAssetArtifact();
4526
4536
  init_metroCloudArtifact();
4527
4537
  init_metro_fingerprint_registry_client();
@@ -5917,6 +5927,15 @@ async function scanDevServers(opts = {}) {
5917
5927
  // src/host/bridge-host.ts
5918
5928
  init_backend_origin();
5919
5929
 
5930
+ // src/automatic-update-policy.ts
5931
+ var import_node_fs4 = require("node:fs");
5932
+ var import_node_path5 = require("node:path");
5933
+ init_home_paths();
5934
+ function automaticPeachUpdatesEnabled(env = process.env) {
5935
+ const value = env.PEACH_UPDATE_CHECK?.toLowerCase();
5936
+ return value !== "0" && value !== "false" && value !== "off" && !(0, import_node_fs4.existsSync)((0, import_node_path5.join)(rnxHomeDir(), "runtime-update-disabled"));
5937
+ }
5938
+
5920
5939
  // src/bridge-constants.ts
5921
5940
  var DEFAULT_SOOTSIM_BRIDGE_PORT = 7668;
5922
5941
  var DEFAULT_SOOTSIM_BRIDGE_URL = `http://localhost:${DEFAULT_SOOTSIM_BRIDGE_PORT}/`;
@@ -5925,7 +5944,7 @@ var SOOTSIM_BRIDGE_SIM_CLOSE_REASON = "sootsim close";
5925
5944
  var AUTOMATION_SIM_IDLE_REAP_TTL_MS = 5 * 6e4;
5926
5945
 
5927
5946
  // src/cli-version.ts
5928
- var import_node_fs3 = require("node:fs");
5947
+ var import_node_fs5 = require("node:fs");
5929
5948
  var import_node_url2 = require("node:url");
5930
5949
  init_public_brand();
5931
5950
  var import_meta = {};
@@ -5942,7 +5961,7 @@ function getCliVersion() {
5942
5961
  ];
5943
5962
  for (const resolve5 of candidates) {
5944
5963
  try {
5945
- const version = JSON.parse((0, import_node_fs3.readFileSync)(resolve5(), "utf8")).version;
5964
+ const version = JSON.parse((0, import_node_fs5.readFileSync)(resolve5(), "utf8")).version;
5946
5965
  if (typeof version === "string" && version) {
5947
5966
  cached2 = version;
5948
5967
  return cached2;
@@ -5966,27 +5985,27 @@ var import_url = require("url");
5966
5985
  // ../contrast-runtime-delivery/src/index.ts
5967
5986
  var import_node_child_process2 = require("node:child_process");
5968
5987
  var import_node_crypto2 = __toESM(require("node:crypto"), 1);
5969
- var import_node_fs6 = __toESM(require("node:fs"), 1);
5988
+ var import_node_fs7 = __toESM(require("node:fs"), 1);
5970
5989
  var import_node_os2 = __toESM(require("node:os"), 1);
5971
- var import_node_path6 = __toESM(require("node:path"), 1);
5990
+ var import_node_path7 = __toESM(require("node:path"), 1);
5972
5991
  var import_node_stream = require("node:stream");
5973
5992
  var import_promises3 = require("node:stream/promises");
5974
5993
 
5975
5994
  // ../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);
5995
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
5996
+ var import_node_path6 = __toESM(require("node:path"), 1);
5978
5997
  function isValidRuntimeVersion(value) {
5979
5998
  return value.length <= 100 && /^[0-9A-Za-z][0-9A-Za-z._+-]*$/.test(value);
5980
5999
  }
5981
6000
  function listInstalledRuntimes(product) {
5982
6001
  try {
5983
- return import_node_fs5.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
6002
+ return import_node_fs6.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
5984
6003
  } catch {
5985
6004
  return [];
5986
6005
  }
5987
6006
  }
5988
6007
  function runtimeTarballCacheName(product, version) {
5989
- return import_node_path5.default.posix.basename(product.tarballPath(version));
6008
+ return import_node_path6.default.posix.basename(product.tarballPath(version));
5990
6009
  }
5991
6010
  function compareSemver(a, b) {
5992
6011
  const parse2 = (v) => {
@@ -6016,7 +6035,7 @@ function createRuntimeDelivery(product) {
6016
6035
  function readConfig() {
6017
6036
  try {
6018
6037
  const parsed = JSON.parse(
6019
- import_node_fs6.default.readFileSync(product.configFile(), "utf8")
6038
+ import_node_fs7.default.readFileSync(product.configFile(), "utf8")
6020
6039
  );
6021
6040
  return parsed && typeof parsed === "object" ? parsed : {};
6022
6041
  } catch {
@@ -6089,7 +6108,7 @@ function createRuntimeDelivery(product) {
6089
6108
  const setActive = opts.setActive !== false;
6090
6109
  const protectVersions = [version, ...opts.protectVersions ?? []];
6091
6110
  pruneLocalRetention({ protectVersions });
6092
- if (!opts.force && import_node_fs6.default.existsSync(import_node_path6.default.join(destDir, product.installedMarker))) {
6111
+ if (!opts.force && import_node_fs7.default.existsSync(import_node_path7.default.join(destDir, product.installedMarker))) {
6093
6112
  if (setActive) product.writeActiveRuntime(version);
6094
6113
  pruneLocalRetention({ protectVersions });
6095
6114
  return {
@@ -6103,18 +6122,18 @@ function createRuntimeDelivery(product) {
6103
6122
  };
6104
6123
  }
6105
6124
  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-`)
6125
+ const downloadDir = import_node_fs7.default.mkdtempSync(
6126
+ import_node_path7.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6108
6127
  );
6109
- const runtimeArchivePath = import_node_path6.default.join(
6128
+ const runtimeArchivePath = import_node_path7.default.join(
6110
6129
  downloadDir,
6111
6130
  runtimeTarballCacheName(product, version)
6112
6131
  );
6113
- const tmpDir = import_node_path6.default.join(
6114
- import_node_path6.default.dirname(destDir),
6132
+ const tmpDir = import_node_path7.default.join(
6133
+ import_node_path7.default.dirname(destDir),
6115
6134
  `.installing-${version}-${process.pid}`
6116
6135
  );
6117
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6136
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6118
6137
  try {
6119
6138
  if (!opts.quiet)
6120
6139
  process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
@@ -6129,20 +6148,20 @@ function createRuntimeDelivery(product) {
6129
6148
  `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
6130
6149
  );
6131
6150
  }
6132
- import_node_fs6.default.mkdirSync(tmpDir, { recursive: true });
6151
+ import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
6133
6152
  await extractTarball(runtimeArchivePath, tmpDir);
6134
- if (!import_node_fs6.default.existsSync(import_node_path6.default.join(tmpDir, product.installedMarker))) {
6153
+ if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, product.installedMarker))) {
6135
6154
  throw new Error(
6136
6155
  `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
6137
6156
  );
6138
6157
  }
6139
- import_node_fs6.default.rmSync(destDir, { recursive: true, force: true });
6140
- import_node_fs6.default.renameSync(tmpDir, destDir);
6158
+ import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
6159
+ import_node_fs7.default.renameSync(tmpDir, destDir);
6141
6160
  } catch (err) {
6142
- import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
6161
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6143
6162
  throw err;
6144
6163
  } finally {
6145
- import_node_fs6.default.rmSync(downloadDir, { recursive: true, force: true });
6164
+ import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
6146
6165
  }
6147
6166
  if (setActive) product.writeActiveRuntime(version);
6148
6167
  pruneLocalRetention({ protectVersions });
@@ -6164,8 +6183,8 @@ function createRuntimeDelivery(product) {
6164
6183
  const pin = resolvePin();
6165
6184
  if (pin) {
6166
6185
  const activeVersion2 = product.readActiveRuntime();
6167
- const pinInstalled = import_node_fs6.default.existsSync(
6168
- import_node_path6.default.join(product.runtimeDir(pin), product.installedMarker)
6186
+ const pinInstalled = import_node_fs7.default.existsSync(
6187
+ import_node_path7.default.join(product.runtimeDir(pin), product.installedMarker)
6169
6188
  );
6170
6189
  if (activeVersion2 === pin && pinInstalled) {
6171
6190
  return {
@@ -6214,7 +6233,7 @@ function createRuntimeDelivery(product) {
6214
6233
  }
6215
6234
  const activeVersion = product.readActiveRuntime();
6216
6235
  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;
6236
+ const activeInstalled = activeDir ? import_node_fs7.default.existsSync(import_node_path7.default.join(activeDir, product.installedMarker)) : false;
6218
6237
  const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
6219
6238
  if (!shouldInstall) {
6220
6239
  return {
@@ -6289,12 +6308,12 @@ function createRuntimeDelivery(product) {
6289
6308
  let removeCacheFiles = [];
6290
6309
  if (markerOffset >= 0) {
6291
6310
  try {
6292
- removeCacheFiles = import_node_fs6.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6311
+ removeCacheFiles = import_node_fs7.default.readdirSync(product.cacheDir(), { withFileTypes: true }).filter((entry) => {
6293
6312
  if (!entry.isFile()) return false;
6294
6313
  const complete = entry.name.startsWith(cachePrefix) && entry.name.endsWith(cacheSuffix);
6295
6314
  const partial = entry.name.startsWith(cachePrefix) && entry.name.endsWith(`${cacheSuffix}.partial`);
6296
6315
  return complete || partial;
6297
- }).map((entry) => import_node_path6.default.join(product.cacheDir(), entry.name)).sort();
6316
+ }).map((entry) => import_node_path7.default.join(product.cacheDir(), entry.name)).sort();
6298
6317
  } catch {
6299
6318
  }
6300
6319
  }
@@ -6309,10 +6328,10 @@ function createRuntimeDelivery(product) {
6309
6328
  function pruneLocalRetention(opts = {}) {
6310
6329
  const plan = planLocalRetention(opts);
6311
6330
  for (const version of plan.removeVersions) {
6312
- import_node_fs6.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6331
+ import_node_fs7.default.rmSync(product.runtimeDir(version), { recursive: true, force: true });
6313
6332
  }
6314
6333
  for (const cacheFile of plan.removeCacheFiles) {
6315
- import_node_fs6.default.rmSync(cacheFile, { force: true });
6334
+ import_node_fs7.default.rmSync(cacheFile, { force: true });
6316
6335
  }
6317
6336
  return plan;
6318
6337
  }
@@ -6338,17 +6357,17 @@ async function downloadToFile(url, destPath) {
6338
6357
  if (!res.ok || !res.body) {
6339
6358
  throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`);
6340
6359
  }
6341
- import_node_fs6.default.mkdirSync(import_node_path6.default.dirname(destPath), { recursive: true });
6360
+ import_node_fs7.default.mkdirSync(import_node_path7.default.dirname(destPath), { recursive: true });
6342
6361
  const tmp = `${destPath}.partial`;
6343
6362
  try {
6344
6363
  await (0, import_promises3.pipeline)(
6345
6364
  import_node_stream.Readable.fromWeb(res.body),
6346
- import_node_fs6.default.createWriteStream(tmp)
6365
+ import_node_fs7.default.createWriteStream(tmp)
6347
6366
  );
6348
- import_node_fs6.default.renameSync(tmp, destPath);
6367
+ import_node_fs7.default.renameSync(tmp, destPath);
6349
6368
  } catch (err) {
6350
6369
  try {
6351
- import_node_fs6.default.unlinkSync(tmp);
6370
+ import_node_fs7.default.unlinkSync(tmp);
6352
6371
  } catch {
6353
6372
  }
6354
6373
  throw err;
@@ -6357,7 +6376,7 @@ async function downloadToFile(url, destPath) {
6357
6376
  function sha256File(filePath) {
6358
6377
  return new Promise((resolve5, reject) => {
6359
6378
  const hash = import_node_crypto2.default.createHash("sha256");
6360
- const stream = import_node_fs6.default.createReadStream(filePath);
6379
+ const stream = import_node_fs7.default.createReadStream(filePath);
6361
6380
  stream.on("data", (chunk) => hash.update(chunk));
6362
6381
  stream.on("error", reject);
6363
6382
  stream.on("end", () => resolve5(hash.digest("hex")));
@@ -6506,19 +6525,19 @@ var rnxRuntime = createRuntimeDelivery(RNX_RUNTIME_PRODUCT);
6506
6525
 
6507
6526
  // src/host/agent-host.ts
6508
6527
  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);
6528
+ var import_node_fs11 = __toESM(require("node:fs"), 1);
6529
+ var import_node_path11 = __toESM(require("node:path"), 1);
6511
6530
 
6512
6531
  // src/agent-sessions.ts
6513
6532
  var import_node_child_process3 = require("node:child_process");
6514
6533
  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);
6534
+ var import_node_fs10 = __toESM(require("node:fs"), 1);
6535
+ var import_node_path10 = __toESM(require("node:path"), 1);
6517
6536
  var import_node_readline = __toESM(require("node:readline"), 1);
6518
6537
 
6519
6538
  // cli/self-invocation.ts
6520
- var import_node_fs7 = require("node:fs");
6521
- var import_node_path7 = require("node:path");
6539
+ var import_node_fs8 = require("node:fs");
6540
+ var import_node_path8 = require("node:path");
6522
6541
  var import_node_url3 = require("node:url");
6523
6542
  init_public_brand();
6524
6543
 
@@ -6528,14 +6547,14 @@ var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_S
6528
6547
  // cli/self-invocation.ts
6529
6548
  function sourceEntryPath() {
6530
6549
  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;
6550
+ const candidate = (0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_url3.fileURLToPath)(__sootsim_import_meta_url)), "bin.ts");
6551
+ return (0, import_node_fs8.existsSync)(candidate) ? candidate : null;
6533
6552
  } catch {
6534
6553
  return null;
6535
6554
  }
6536
6555
  }
6537
6556
  function isCliEntry(path12) {
6538
- const name2 = (0, import_node_path7.basename)(path12);
6557
+ const name2 = (0, import_node_path8.basename)(path12);
6539
6558
  return name2 === "bin.ts" || name2 === "bin.js";
6540
6559
  }
6541
6560
  function rnxSelfInvocation() {
@@ -6595,8 +6614,8 @@ function encodeAgentPromptEnvelope(input) {
6595
6614
 
6596
6615
  // src/attached-projects.ts
6597
6616
  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);
6617
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
6618
+ var import_node_path9 = __toESM(require("node:path"), 1);
6600
6619
  init_home_paths();
6601
6620
  var overrideDir = null;
6602
6621
  function userDataDir() {
@@ -6609,7 +6628,7 @@ function getUserDataDir() {
6609
6628
  return userDataDir();
6610
6629
  }
6611
6630
  function storeFile() {
6612
- return import_node_path8.default.join(userDataDir(), "attached-projects.json");
6631
+ return import_node_path9.default.join(userDataDir(), "attached-projects.json");
6613
6632
  }
6614
6633
  function cloneEmpty() {
6615
6634
  return {
@@ -6623,7 +6642,7 @@ function loadStore() {
6623
6642
  const file = storeFile();
6624
6643
  let raw;
6625
6644
  try {
6626
- raw = import_node_fs8.default.readFileSync(file, "utf8");
6645
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
6627
6646
  } catch (err) {
6628
6647
  if (err.code === "ENOENT") return cloneEmpty();
6629
6648
  throw err;
@@ -6640,7 +6659,7 @@ function loadStore() {
6640
6659
  } catch (err) {
6641
6660
  const quarantine = `${file}.corrupt-${Date.now()}`;
6642
6661
  try {
6643
- import_node_fs8.default.renameSync(file, quarantine);
6662
+ import_node_fs9.default.renameSync(file, quarantine);
6644
6663
  console.warn(
6645
6664
  `[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
6646
6665
  );
@@ -6651,16 +6670,16 @@ function loadStore() {
6651
6670
  }
6652
6671
  function writeStore(store) {
6653
6672
  const file = storeFile();
6654
- import_node_fs8.default.mkdirSync(import_node_path8.default.dirname(file), { recursive: true });
6673
+ import_node_fs9.default.mkdirSync(import_node_path9.default.dirname(file), { recursive: true });
6655
6674
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
6656
- const fd = import_node_fs8.default.openSync(tmp, "w", 384);
6675
+ const fd = import_node_fs9.default.openSync(tmp, "w", 384);
6657
6676
  try {
6658
- import_node_fs8.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6659
- import_node_fs8.default.fsyncSync(fd);
6677
+ import_node_fs9.default.writeFileSync(fd, JSON.stringify(store, null, 2));
6678
+ import_node_fs9.default.fsyncSync(fd);
6660
6679
  } finally {
6661
- import_node_fs8.default.closeSync(fd);
6680
+ import_node_fs9.default.closeSync(fd);
6662
6681
  }
6663
- import_node_fs8.default.renameSync(tmp, file);
6682
+ import_node_fs9.default.renameSync(tmp, file);
6664
6683
  }
6665
6684
  function mutateStore(fn) {
6666
6685
  const store = loadStore();
@@ -6669,13 +6688,13 @@ function mutateStore(fn) {
6669
6688
  return store;
6670
6689
  }
6671
6690
  function projectIdForCwd(cwd) {
6672
- return (0, import_node_crypto3.createHash)("sha256").update(import_node_path8.default.resolve(cwd)).digest("hex").slice(0, 16);
6691
+ return (0, import_node_crypto3.createHash)("sha256").update(import_node_path9.default.resolve(cwd)).digest("hex").slice(0, 16);
6673
6692
  }
6674
6693
  function newSessionId() {
6675
6694
  return `s_${(0, import_node_crypto3.randomBytes)(10).toString("hex")}`;
6676
6695
  }
6677
6696
  function upsertProject(input) {
6678
- const cwd = import_node_path8.default.resolve(input.cwd);
6697
+ const cwd = import_node_path9.default.resolve(input.cwd);
6679
6698
  const id = projectIdForCwd(cwd);
6680
6699
  let result;
6681
6700
  mutateStore((store) => {
@@ -6701,7 +6720,7 @@ function upsertProject(input) {
6701
6720
  const now = Date.now();
6702
6721
  const created = {
6703
6722
  id,
6704
- name: input.name ?? import_node_path8.default.basename(cwd),
6723
+ name: input.name ?? import_node_path9.default.basename(cwd),
6705
6724
  cwd,
6706
6725
  repoRoot: input.repoRoot,
6707
6726
  sourceRoots: input.sourceRoots ?? [cwd],
@@ -6847,8 +6866,8 @@ async function seedFromDemoAppRegistry() {
6847
6866
  if (apps.length === 0) return;
6848
6867
  mutateStore((store) => {
6849
6868
  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);
6869
+ if (!import_node_fs9.default.existsSync(app.dir)) continue;
6870
+ const cwd = import_node_path9.default.resolve(app.dir);
6852
6871
  const id = projectIdForCwd(cwd);
6853
6872
  if (store.attachedProjects.some((p) => p.id === id)) continue;
6854
6873
  const now = Date.now();
@@ -6873,16 +6892,16 @@ async function seedFromDemoAppRegistry() {
6873
6892
  // src/agent-sessions.ts
6874
6893
  init_public_brand();
6875
6894
  function sessionDir(sessionId) {
6876
- return import_node_path9.default.join(getUserDataDir(), "sessions", sessionId);
6895
+ return import_node_path10.default.join(getUserDataDir(), "sessions", sessionId);
6877
6896
  }
6878
6897
  function promptFifoPath(sessionId) {
6879
- return import_node_path9.default.join(sessionDir(sessionId), "prompt.in");
6898
+ return import_node_path10.default.join(sessionDir(sessionId), "prompt.in");
6880
6899
  }
6881
6900
  function eventsFifoPath(sessionId) {
6882
- return import_node_path9.default.join(sessionDir(sessionId), "events.out");
6901
+ return import_node_path10.default.join(sessionDir(sessionId), "events.out");
6883
6902
  }
6884
6903
  function transcriptPath(sessionId) {
6885
- return import_node_path9.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6904
+ return import_node_path10.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
6886
6905
  }
6887
6906
  function pidIsAlive(pid, sessionId) {
6888
6907
  if (!pid) return false;
@@ -6892,7 +6911,7 @@ function pidIsAlive(pid, sessionId) {
6892
6911
  return false;
6893
6912
  }
6894
6913
  if (sessionId) {
6895
- if (!import_node_fs9.default.existsSync(sessionDir(sessionId))) return false;
6914
+ if (!import_node_fs10.default.existsSync(sessionDir(sessionId))) return false;
6896
6915
  }
6897
6916
  return true;
6898
6917
  }
@@ -6905,11 +6924,11 @@ function resolveSootsimInvocation() {
6905
6924
  const resourcesPath = process.resourcesPath;
6906
6925
  if (resourcesPath) {
6907
6926
  const candidates = [
6908
- import_node_path9.default.join(resourcesPath, "bin", "sootsim"),
6909
- import_node_path9.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6927
+ import_node_path10.default.join(resourcesPath, "bin", "sootsim"),
6928
+ import_node_path10.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
6910
6929
  ];
6911
6930
  for (const c of candidates) {
6912
- if (import_node_fs9.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6931
+ if (import_node_fs10.default.existsSync(c)) return { executable: c, prefixArgs: [] };
6913
6932
  }
6914
6933
  }
6915
6934
  }
@@ -6928,15 +6947,15 @@ function tryWorkspaceSootsim() {
6928
6947
  const sootsimDir = resolveSootsimPackageDir();
6929
6948
  if (!sootsimDir) return null;
6930
6949
  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)) {
6950
+ const distBinary = import_node_path10.default.join(sootsimDir, "dist-bin", binaryName);
6951
+ if (import_node_fs10.default.existsSync(distBinary)) return { executable: distBinary, prefixArgs: [] };
6952
+ const distBin = import_node_path10.default.join(sootsimDir, "dist-cli", "bin.js");
6953
+ if (import_node_fs10.default.existsSync(distBin)) {
6935
6954
  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;
6955
+ const src = import_node_path10.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
6956
+ if (import_node_fs10.default.existsSync(src)) {
6957
+ const srcMtime = import_node_fs10.default.statSync(src).mtimeMs;
6958
+ const buildMtime = import_node_fs10.default.statSync(distBin).mtimeMs;
6940
6959
  if (buildMtime < srcMtime) {
6941
6960
  console.warn(
6942
6961
  `[peach] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/peachsim build:cli\`.`
@@ -6955,22 +6974,22 @@ function tryWorkspaceSootsim() {
6955
6974
  function resolveSootsimPackageDir() {
6956
6975
  try {
6957
6976
  const resolved = require.resolve(`${rnxPublicBrand.packageName}/package.json`);
6958
- return import_node_path9.default.dirname(resolved);
6977
+ return import_node_path10.default.dirname(resolved);
6959
6978
  } catch {
6960
6979
  }
6961
6980
  const here = fileFromImportMeta();
6962
6981
  if (!here) return null;
6963
- let cur = import_node_path9.default.dirname(here);
6982
+ let cur = import_node_path10.default.dirname(here);
6964
6983
  for (let i = 0; i < 8; i++) {
6965
- const pkg = import_node_path9.default.join(cur, "package.json");
6984
+ const pkg = import_node_path10.default.join(cur, "package.json");
6966
6985
  try {
6967
- if (import_node_fs9.default.existsSync(pkg)) {
6968
- const parsed = JSON.parse(import_node_fs9.default.readFileSync(pkg, "utf8"));
6986
+ if (import_node_fs10.default.existsSync(pkg)) {
6987
+ const parsed = JSON.parse(import_node_fs10.default.readFileSync(pkg, "utf8"));
6969
6988
  if (parsed.name === rnxPublicBrand.packageName) return cur;
6970
6989
  }
6971
6990
  } catch {
6972
6991
  }
6973
- const parent = import_node_path9.default.dirname(cur);
6992
+ const parent = import_node_path10.default.dirname(cur);
6974
6993
  if (parent === cur) break;
6975
6994
  cur = parent;
6976
6995
  }
@@ -6986,28 +7005,28 @@ function fileFromImportMeta() {
6986
7005
  }
6987
7006
  }
6988
7007
  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 });
7008
+ const lockDir = import_node_path10.default.join(getUserDataDir(), "locks");
7009
+ import_node_fs10.default.mkdirSync(lockDir, { recursive: true });
6991
7010
  try {
6992
- import_node_fs9.default.chmodSync(lockDir, 448);
7011
+ import_node_fs10.default.chmodSync(lockDir, 448);
6993
7012
  } catch {
6994
7013
  }
6995
- const lockPath = import_node_path9.default.join(lockDir, `start-${projectId}-${provider}.lock`);
7014
+ const lockPath = import_node_path10.default.join(lockDir, `start-${projectId}-${provider}.lock`);
6996
7015
  const deadline = Date.now() + 4e3;
6997
7016
  let fd = null;
6998
7017
  while (fd === null) {
6999
7018
  try {
7000
- fd = import_node_fs9.default.openSync(
7019
+ fd = import_node_fs10.default.openSync(
7001
7020
  lockPath,
7002
- import_node_fs9.constants.O_WRONLY | import_node_fs9.constants.O_CREAT | import_node_fs9.constants.O_EXCL,
7021
+ import_node_fs10.constants.O_WRONLY | import_node_fs10.constants.O_CREAT | import_node_fs10.constants.O_EXCL,
7003
7022
  384
7004
7023
  );
7005
7024
  } catch (err) {
7006
7025
  if (err.code !== "EEXIST") throw err;
7007
7026
  try {
7008
- const stale = Number(import_node_fs9.default.readFileSync(lockPath, "utf8").trim());
7027
+ const stale = Number(import_node_fs10.default.readFileSync(lockPath, "utf8").trim());
7009
7028
  if (stale && !isProcessAlive(stale)) {
7010
- import_node_fs9.default.unlinkSync(lockPath);
7029
+ import_node_fs10.default.unlinkSync(lockPath);
7011
7030
  continue;
7012
7031
  }
7013
7032
  } catch {
@@ -7021,15 +7040,15 @@ async function withStartLock(projectId, provider, fn) {
7021
7040
  }
7022
7041
  }
7023
7042
  try {
7024
- import_node_fs9.default.writeFileSync(fd, String(process.pid));
7043
+ import_node_fs10.default.writeFileSync(fd, String(process.pid));
7025
7044
  return await fn();
7026
7045
  } finally {
7027
7046
  try {
7028
- import_node_fs9.default.closeSync(fd);
7047
+ import_node_fs10.default.closeSync(fd);
7029
7048
  } catch {
7030
7049
  }
7031
7050
  try {
7032
- import_node_fs9.default.unlinkSync(lockPath);
7051
+ import_node_fs10.default.unlinkSync(lockPath);
7033
7052
  } catch {
7034
7053
  }
7035
7054
  }
@@ -7043,25 +7062,25 @@ function isProcessAlive(pid) {
7043
7062
  }
7044
7063
  }
7045
7064
  function mkfifoSync(p) {
7046
- const parent = import_node_path9.default.dirname(p);
7047
- import_node_fs9.default.mkdirSync(parent, { recursive: true });
7065
+ const parent = import_node_path10.default.dirname(p);
7066
+ import_node_fs10.default.mkdirSync(parent, { recursive: true });
7048
7067
  try {
7049
- import_node_fs9.default.chmodSync(parent, 448);
7068
+ import_node_fs10.default.chmodSync(parent, 448);
7050
7069
  } catch {
7051
7070
  }
7052
- if (import_node_fs9.default.existsSync(p)) {
7071
+ if (import_node_fs10.default.existsSync(p)) {
7053
7072
  try {
7054
- const stat2 = import_node_fs9.default.statSync(p);
7073
+ const stat2 = import_node_fs10.default.statSync(p);
7055
7074
  if (stat2.isFIFO()) {
7056
7075
  try {
7057
- import_node_fs9.default.chmodSync(p, 384);
7076
+ import_node_fs10.default.chmodSync(p, 384);
7058
7077
  } catch {
7059
7078
  }
7060
7079
  return;
7061
7080
  }
7062
- import_node_fs9.default.unlinkSync(p);
7081
+ import_node_fs10.default.unlinkSync(p);
7063
7082
  } catch {
7064
- import_node_fs9.default.unlinkSync(p);
7083
+ import_node_fs10.default.unlinkSync(p);
7065
7084
  }
7066
7085
  }
7067
7086
  const result = (0, import_node_child_process3.spawnSync)("mkfifo", ["-m", "600", p]);
@@ -7108,10 +7127,10 @@ async function startSession(opts) {
7108
7127
  const transcript = transcriptPath(session.id);
7109
7128
  mkfifoSync(promptIn);
7110
7129
  mkfifoSync(eventsOut);
7111
- const transcriptDir = import_node_path9.default.dirname(transcript);
7112
- import_node_fs9.default.mkdirSync(transcriptDir, { recursive: true });
7130
+ const transcriptDir = import_node_path10.default.dirname(transcript);
7131
+ import_node_fs10.default.mkdirSync(transcriptDir, { recursive: true });
7113
7132
  try {
7114
- import_node_fs9.default.chmodSync(transcriptDir, 448);
7133
+ import_node_fs10.default.chmodSync(transcriptDir, 448);
7115
7134
  } catch {
7116
7135
  }
7117
7136
  const { executable, prefixArgs } = resolveSootsimInvocation();
@@ -7162,7 +7181,7 @@ async function startSession(opts) {
7162
7181
  }
7163
7182
  }
7164
7183
  try {
7165
- import_node_fs9.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7184
+ import_node_fs10.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
7166
7185
  } catch {
7167
7186
  }
7168
7187
  updateSessionStatus(session.id, { status: "ended" });
@@ -7190,18 +7209,18 @@ async function sendPrompt(sessionId, prompt) {
7190
7209
  );
7191
7210
  }
7192
7211
  const fifo = promptFifoPath(sessionId);
7193
- if (!import_node_fs9.default.existsSync(fifo)) {
7212
+ if (!import_node_fs10.default.existsSync(fifo)) {
7194
7213
  throw new AgentSessionError("NO_FIFO", `prompt FIFO missing: ${fifo}`);
7195
7214
  }
7196
- const fd = import_node_fs9.default.openSync(fifo, import_node_fs9.constants.O_WRONLY);
7215
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_WRONLY);
7197
7216
  try {
7198
7217
  const wireText = encodeAgentPromptEnvelope(prompt);
7199
7218
  if (!wireText) {
7200
7219
  throw new AgentSessionError("EMPTY_PROMPT", "prompt text is empty");
7201
7220
  }
7202
- import_node_fs9.default.writeSync(fd, wireText + "\n");
7221
+ import_node_fs10.default.writeSync(fd, wireText + "\n");
7203
7222
  } finally {
7204
- import_node_fs9.default.closeSync(fd);
7223
+ import_node_fs10.default.closeSync(fd);
7205
7224
  }
7206
7225
  updateSessionStatus(sessionId, {
7207
7226
  lastPrompt: prompt.displayText ?? prompt.text,
@@ -7223,7 +7242,7 @@ async function endSession(sessionId) {
7223
7242
  const base = getUserDataDir();
7224
7243
  if (dir.startsWith(base)) {
7225
7244
  try {
7226
- import_node_fs9.default.rmSync(dir, { recursive: true, force: true });
7245
+ import_node_fs10.default.rmSync(dir, { recursive: true, force: true });
7227
7246
  } catch {
7228
7247
  }
7229
7248
  }
@@ -7231,11 +7250,11 @@ async function endSession(sessionId) {
7231
7250
  }
7232
7251
  function subscribeEvents(sessionId, onEvent) {
7233
7252
  const fifo = eventsFifoPath(sessionId);
7234
- if (!import_node_fs9.default.existsSync(fifo)) {
7253
+ if (!import_node_fs10.default.existsSync(fifo)) {
7235
7254
  throw new AgentSessionError("NO_FIFO", `events FIFO missing: ${fifo}`);
7236
7255
  }
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 });
7256
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR);
7257
+ const stream = import_node_fs10.default.createReadStream("", { fd, autoClose: true });
7239
7258
  const rl = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
7240
7259
  rl.on("line", (line) => {
7241
7260
  const event = parseAgentEventLine(line);
@@ -7246,7 +7265,7 @@ function subscribeEvents(sessionId, onEvent) {
7246
7265
  if (closed) return;
7247
7266
  closed = true;
7248
7267
  try {
7249
- import_node_fs9.default.writeSync(fd, "\n");
7268
+ import_node_fs10.default.writeSync(fd, "\n");
7250
7269
  } catch {
7251
7270
  }
7252
7271
  try {
@@ -7260,7 +7279,7 @@ function subscribeEvents(sessionId, onEvent) {
7260
7279
  };
7261
7280
  }
7262
7281
  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);
7282
+ const fd = import_node_fs10.default.openSync(fifo, import_node_fs10.constants.O_RDWR | import_node_fs10.constants.O_NONBLOCK);
7264
7283
  const buf = Buffer.alloc(8192);
7265
7284
  let leftover = "";
7266
7285
  const deadline = Date.now() + timeoutMs;
@@ -7268,7 +7287,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7268
7287
  while (Date.now() < deadline) {
7269
7288
  let n = 0;
7270
7289
  try {
7271
- n = import_node_fs9.default.readSync(fd, buf, 0, buf.length, null);
7290
+ n = import_node_fs10.default.readSync(fd, buf, 0, buf.length, null);
7272
7291
  } catch (err) {
7273
7292
  if (err.code !== "EAGAIN") throw err;
7274
7293
  n = 0;
@@ -7288,7 +7307,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
7288
7307
  }
7289
7308
  return null;
7290
7309
  } finally {
7291
- import_node_fs9.default.closeSync(fd);
7310
+ import_node_fs10.default.closeSync(fd);
7292
7311
  }
7293
7312
  }
7294
7313
 
@@ -7542,7 +7561,7 @@ var AgentHost = class {
7542
7561
  );
7543
7562
  const project = upsertProject({
7544
7563
  cwd: match.cwd,
7545
- name: match.projectName ?? import_node_path10.default.basename(match.cwd),
7564
+ name: match.projectName ?? import_node_path11.default.basename(match.cwd),
7546
7565
  preferredProvider: input.provider ?? existing?.preferredProvider,
7547
7566
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
7548
7567
  knownBundleUrls,
@@ -7553,18 +7572,18 @@ var AgentHost = class {
7553
7572
  }
7554
7573
  getTranscript(sessionId) {
7555
7574
  const p = transcriptPath(sessionId);
7556
- if (!import_node_fs10.default.existsSync(p)) {
7575
+ if (!import_node_fs11.default.existsSync(p)) {
7557
7576
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
7558
7577
  }
7559
- return import_node_fs10.default.readFileSync(p, "utf8");
7578
+ return import_node_fs11.default.readFileSync(p, "utf8");
7560
7579
  }
7561
7580
  getPaths() {
7562
7581
  const dir = getUserDataDir();
7563
7582
  return {
7564
7583
  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")
7584
+ storeFile: import_node_path11.default.join(dir, "attached-projects.json"),
7585
+ sessionsDir: import_node_path11.default.join(dir, "sessions"),
7586
+ transcriptsDir: import_node_path11.default.join(dir, "transcripts")
7568
7587
  };
7569
7588
  }
7570
7589
  // --- subscription management ---
@@ -8271,8 +8290,8 @@ async function openUrl(url, options = {}) {
8271
8290
  }
8272
8291
 
8273
8292
  // 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);
8293
+ var import_node_fs13 = __toESM(require("node:fs"), 1);
8294
+ var import_node_path13 = __toESM(require("node:path"), 1);
8276
8295
 
8277
8296
  // ../peach-box/src/planeProtocol.ts
8278
8297
  var PLANE_FLAG_READ_ONLY = 1;
@@ -8352,8 +8371,8 @@ async function dispatchPlaneCommand(plane, type, msg, mutationOptions) {
8352
8371
 
8353
8372
  // cli/commands/box/checkout-plane.ts
8354
8373
  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);
8374
+ var import_node_fs12 = __toESM(require("node:fs"), 1);
8375
+ var import_node_path12 = __toESM(require("node:path"), 1);
8357
8376
  var CheckoutRequiresGitError = class extends Error {
8358
8377
  };
8359
8378
  var BINARY_SNIFF_BYTES = 8192;
@@ -8364,14 +8383,14 @@ function looksBinary(filePath, size) {
8364
8383
  if (size === 0) return false;
8365
8384
  let fd;
8366
8385
  try {
8367
- fd = import_node_fs11.default.openSync(filePath, "r");
8386
+ fd = import_node_fs12.default.openSync(filePath, "r");
8368
8387
  const buffer = Buffer.alloc(Math.min(BINARY_SNIFF_BYTES, size));
8369
- const read = import_node_fs11.default.readSync(fd, buffer, 0, buffer.length, 0);
8388
+ const read = import_node_fs12.default.readSync(fd, buffer, 0, buffer.length, 0);
8370
8389
  return buffer.subarray(0, read).includes(0);
8371
8390
  } catch {
8372
8391
  return false;
8373
8392
  } finally {
8374
- if (fd !== void 0) import_node_fs11.default.closeSync(fd);
8393
+ if (fd !== void 0) import_node_fs12.default.closeSync(fd);
8375
8394
  }
8376
8395
  }
8377
8396
  var CheckoutFilePlane = class {
@@ -8384,7 +8403,7 @@ var CheckoutFilePlane = class {
8384
8403
  listTimeoutMs;
8385
8404
  trackedOnly;
8386
8405
  constructor(root, options = {}) {
8387
- this.root = import_node_path11.default.resolve(root);
8406
+ this.root = import_node_path12.default.resolve(root);
8388
8407
  this.listTimeoutMs = options.listTimeoutMs ?? LIST_FILES_TIMEOUT_MS;
8389
8408
  this.trackedOnly = options.trackedOnly ?? false;
8390
8409
  }
@@ -8446,13 +8465,13 @@ var CheckoutFilePlane = class {
8446
8465
  if (!relative2) continue;
8447
8466
  let stat2;
8448
8467
  try {
8449
- stat2 = import_node_fs11.default.statSync(import_node_path11.default.join(this.root, relative2));
8468
+ stat2 = import_node_fs12.default.statSync(import_node_path12.default.join(this.root, relative2));
8450
8469
  } catch {
8451
8470
  continue;
8452
8471
  }
8453
8472
  if (!stat2.isFile()) continue;
8454
8473
  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);
8474
+ const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path12.default.join(this.root, relative2), stat2.size);
8456
8475
  nextSniffed.set(relative2, { size: stat2.size, mtimeMs: stat2.mtimeMs, binary });
8457
8476
  next.set(relative2, {
8458
8477
  size: stat2.size,
@@ -8466,22 +8485,22 @@ var CheckoutFilePlane = class {
8466
8485
  this.sniffed = nextSniffed;
8467
8486
  }
8468
8487
  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}`)) {
8488
+ const resolved = import_node_path12.default.resolve(this.root, planePath);
8489
+ if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path12.default.sep}`)) {
8471
8490
  throw new Error(`path escapes the project: ${planePath}`);
8472
8491
  }
8473
8492
  return resolved;
8474
8493
  }
8475
8494
  async read(planePath) {
8476
- return import_node_fs11.default.promises.readFile(this.absolute(planePath), "utf8");
8495
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath), "utf8");
8477
8496
  }
8478
8497
  async readBytes(planePath) {
8479
- return import_node_fs11.default.promises.readFile(this.absolute(planePath));
8498
+ return import_node_fs12.default.promises.readFile(this.absolute(planePath));
8480
8499
  }
8481
8500
  async write(planePath, content) {
8482
8501
  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);
8502
+ await import_node_fs12.default.promises.mkdir(import_node_path12.default.dirname(absolute), { recursive: true });
8503
+ await import_node_fs12.default.promises.writeFile(absolute, content);
8485
8504
  this.entries.set(planePath, {
8486
8505
  size: content.byteLength,
8487
8506
  readOnly: false,
@@ -8490,7 +8509,7 @@ var CheckoutFilePlane = class {
8490
8509
  });
8491
8510
  }
8492
8511
  async delete(planePath) {
8493
- await import_node_fs11.default.promises.rm(this.absolute(planePath), { force: true });
8512
+ await import_node_fs12.default.promises.rm(this.absolute(planePath), { force: true });
8494
8513
  this.entries.delete(planePath);
8495
8514
  }
8496
8515
  };
@@ -8616,14 +8635,14 @@ var PlaneHost = class {
8616
8635
  // root and an opened one cannot disagree about the same directory.
8617
8636
  realRoot(root) {
8618
8637
  if (!root) throw new Error("root is required");
8619
- const resolved = import_node_path12.default.resolve(root);
8638
+ const resolved = import_node_path13.default.resolve(root);
8620
8639
  let real;
8621
8640
  try {
8622
- real = import_node_fs12.default.realpathSync(resolved);
8641
+ real = import_node_fs13.default.realpathSync(resolved);
8623
8642
  } catch {
8624
8643
  throw new Error(`no such directory: ${resolved}`);
8625
8644
  }
8626
- if (!import_node_fs12.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8645
+ if (!import_node_fs13.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
8627
8646
  return real;
8628
8647
  }
8629
8648
  respond(ws, id, result) {
@@ -8644,7 +8663,7 @@ var PlaneHost = class {
8644
8663
 
8645
8664
  // src/host/replacement-module-handler.ts
8646
8665
  var import_promises5 = __toESM(require("node:fs/promises"), 1);
8647
- var import_node_path13 = __toESM(require("node:path"), 1);
8666
+ var import_node_path14 = __toESM(require("node:path"), 1);
8648
8667
 
8649
8668
  // ../contrast-bundler/src/replacementModule.ts
8650
8669
  var import_dist = require("sucrase/dist/index.js");
@@ -8683,7 +8702,7 @@ function normalize(p) {
8683
8702
  if (trailingSlash) joined += "/";
8684
8703
  return absolute ? "/" + joined : joined;
8685
8704
  }
8686
- function join4(...parts) {
8705
+ function join5(...parts) {
8687
8706
  const present = parts.filter((part) => part.length > 0);
8688
8707
  if (present.length === 0) return ".";
8689
8708
  return normalize(present.join("/"));
@@ -8740,7 +8759,7 @@ var posix = {
8740
8759
  delimiter,
8741
8760
  isAbsolute,
8742
8761
  normalize,
8743
- join: join4,
8762
+ join: join5,
8744
8763
  resolve: resolve2,
8745
8764
  dirname: dirname3,
8746
8765
  basename: basename3,
@@ -8998,13 +9017,13 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
8998
9017
  res.end("missing path param");
8999
9018
  return true;
9000
9019
  }
9001
- const extension = import_node_path13.default.extname(targetPath).toLowerCase();
9020
+ const extension = import_node_path14.default.extname(targetPath).toLowerCase();
9002
9021
  if (!REPLACEMENT_MODULE_EXTENSIONS.some((allowed) => allowed === extension)) {
9003
9022
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9004
9023
  res.end(`replacement files must be ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")}`);
9005
9024
  return true;
9006
9025
  }
9007
- if (!import_node_path13.default.isAbsolute(targetPath)) {
9026
+ if (!import_node_path14.default.isAbsolute(targetPath)) {
9008
9027
  res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
9009
9028
  res.end("replacement file path must be absolute");
9010
9029
  return true;
@@ -9012,10 +9031,10 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9012
9031
  const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
9013
9032
  let resolvedProjectRoot;
9014
9033
  if (options.projectRoot) {
9015
- const lexicalProjectRoot = import_node_path13.default.resolve(options.projectRoot);
9034
+ const lexicalProjectRoot = import_node_path14.default.resolve(options.projectRoot);
9016
9035
  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)) {
9036
+ const lexicalTarget = import_node_path14.default.relative(lexicalProjectRoot, targetPath);
9037
+ if (lexicalTarget.startsWith("..") || import_node_path14.default.isAbsolute(lexicalTarget)) {
9019
9038
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9020
9039
  res.end("replacement file must be inside the project root");
9021
9040
  return true;
@@ -9031,8 +9050,8 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
9031
9050
  return true;
9032
9051
  }
9033
9052
  if (resolvedProjectRoot) {
9034
- const relativeTarget = import_node_path13.default.relative(resolvedProjectRoot, resolvedTargetPath);
9035
- if (relativeTarget.startsWith("..") || import_node_path13.default.isAbsolute(relativeTarget)) {
9053
+ const relativeTarget = import_node_path14.default.relative(resolvedProjectRoot, resolvedTargetPath);
9054
+ if (relativeTarget.startsWith("..") || import_node_path14.default.isAbsolute(relativeTarget)) {
9036
9055
  res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
9037
9056
  res.end("replacement file must be inside the project root");
9038
9057
  return true;
@@ -10214,7 +10233,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10214
10233
  }
10215
10234
  startRuntimeUpdater() {
10216
10235
  if (!this.shouldWriteLockfile || this.runtimeUpdateTimer) return;
10217
- if (import_fs3.default.existsSync(import_path3.default.join(rnxHomeDir(), "runtime-update-disabled"))) {
10236
+ if (!automaticPeachUpdatesEnabled()) {
10218
10237
  this.bootstrapping = false;
10219
10238
  if (this.httpServer) this.writeLockfileSnapshot();
10220
10239
  return;
@@ -10230,6 +10249,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10230
10249
  this.runtimeUpdateTimer.unref();
10231
10250
  }
10232
10251
  runRuntimeUpdate(reason) {
10252
+ if (!automaticPeachUpdatesEnabled()) return Promise.resolve();
10233
10253
  if (this.runtimeUpdateInFlight) return this.runtimeUpdateInFlight;
10234
10254
  this.runtimeUpdateInFlight = (async () => {
10235
10255
  try {