peachsim 0.1.630 → 0.1.632

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 (96) hide show
  1. package/README.md +9 -1
  2. package/cli/app-fonts.ts +23 -4
  3. package/cli/bridge-flow-runner.ts +35 -28
  4. package/cli/command-registry.ts +1 -0
  5. package/cli/commands/compat.ts +11 -60
  6. package/cli/commands/control.ts +12 -5
  7. package/cli/commands/detect.ts +289 -26
  8. package/cli/commands/inspect/core.ts +1 -1
  9. package/cli/commands/inspect.ts +4 -0
  10. package/cli/commands/maestro.ts +8 -2
  11. package/cli/commands/project-report.ts +386 -0
  12. package/cli/commands/projectReportContract.ts +42 -0
  13. package/cli/commands/report-issue.ts +38 -54
  14. package/cli/commands/setup.ts +6 -4
  15. package/cli/commands/telemetry.ts +8 -3
  16. package/cli/commands/test.ts +374 -133
  17. package/cli/drivers/playwright-core-pin.ts +10 -0
  18. package/cli/drivers/playwright-provisioning.ts +36 -1
  19. package/cli/drivers/playwright.ts +26 -19
  20. package/cli/main.ts +11 -1
  21. package/cli/outbound-endpoints.ts +2 -1
  22. package/cli/privacy.ts +1 -2
  23. package/cli/runtime-diagnostics.ts +51 -0
  24. package/cli/shell-init.ts +6 -1
  25. package/cli/telemetry.ts +78 -7
  26. package/cli/ws-bridge.ts +8 -2
  27. package/detox/index.ts +3 -8
  28. package/dist-lib/agent-daemon-client.cjs +1 -1
  29. package/dist-lib/agent-events.cjs +1 -1
  30. package/dist-lib/agent-identity.cjs +1 -1
  31. package/dist-lib/agent-sessions.cjs +1 -1
  32. package/dist-lib/attached-projects.cjs +1 -1
  33. package/dist-lib/auth/shared-session.cjs +1 -1
  34. package/dist-lib/backend-origin.cjs +1 -1
  35. package/dist-lib/beta.cjs +1 -1
  36. package/dist-lib/beta.mjs +1 -1
  37. package/dist-lib/bridge-constants.cjs +1 -1
  38. package/dist-lib/bridge-contract-input.cjs +1 -1
  39. package/dist-lib/bridge-contract-input.mjs +1 -1
  40. package/dist-lib/bridge-contract.cjs +1 -1
  41. package/dist-lib/bridge-contract.mjs +1 -1
  42. package/dist-lib/capture-contract.cjs +1 -1
  43. package/dist-lib/capture-contract.mjs +1 -1
  44. package/dist-lib/cli-constants.cjs +1 -1
  45. package/dist-lib/cloud-contract.cjs +1 -1
  46. package/dist-lib/cloud-contract.mjs +1 -1
  47. package/dist-lib/cloud-test-args.cjs +17 -5
  48. package/dist-lib/cloud-test-args.mjs +17 -5
  49. package/dist-lib/cloud.cjs +1 -1
  50. package/dist-lib/cloud.mjs +1 -1
  51. package/dist-lib/config.cjs +1 -1
  52. package/dist-lib/detox/index.cjs +2 -7
  53. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  54. package/dist-lib/home-paths.cjs +13 -5
  55. package/dist-lib/host/bridge-host.cjs +157 -113
  56. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  57. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  58. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  59. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  60. package/dist-lib/host/websocket-proxy.cjs +1 -1
  61. package/dist-lib/index.cjs +11 -2
  62. package/dist-lib/jump-to-source-babel.cjs +1 -1
  63. package/dist-lib/jump-to-source-native.cjs +1 -1
  64. package/dist-lib/kotlin-host.cjs +1 -1
  65. package/dist-lib/menu.cjs +11 -1
  66. package/dist-lib/menu.mjs +11 -1
  67. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  68. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  69. package/dist-lib/metro-production-bundle.cjs +1 -1
  70. package/dist-lib/metro-production-bundle.mjs +1 -1
  71. package/dist-lib/metro.cjs +1 -1
  72. package/dist-lib/native-app-identity.cjs +1 -1
  73. package/dist-lib/native-app-identity.mjs +1 -1
  74. package/dist-lib/profiles.cjs +1 -1
  75. package/dist-lib/public-brand.cjs +1 -1
  76. package/dist-lib/react-native-host-modules.cjs +1 -1
  77. package/dist-lib/react-native-host-modules.mjs +1 -1
  78. package/dist-lib/render-mode.cjs +1 -1
  79. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  80. package/dist-lib/sdk.cjs +3 -1
  81. package/dist-lib/sdk.mjs +2 -1
  82. package/dist-lib/skills.cjs +700 -329
  83. package/dist-lib/swift-compile.cjs +1 -1
  84. package/dist-lib/swift-compile.mjs +1 -1
  85. package/dist-lib/swift-package.cjs +1 -1
  86. package/dist-lib/swift-package.mjs +1 -1
  87. package/dist-lib/swift-submit.cjs +1 -1
  88. package/dist-lib/swift-submit.mjs +1 -1
  89. package/dist-lib/swift.cjs +443 -173
  90. package/dist-lib/vite-swift.cjs +1 -1
  91. package/dist-lib/vite.cjs +1 -1
  92. package/package.json +2 -1
  93. package/skills/contrast/SKILL.md +1 -0
  94. package/src/cloud-test-args.ts +18 -6
  95. package/src/home-paths.ts +19 -9
  96. package/src/menu.ts +11 -0
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.630 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.632 | (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;
@@ -20487,6 +20487,7 @@ __export(home_paths_exports, {
20487
20487
  isDevWorkstation: () => isDevWorkstation,
20488
20488
  isOnboardingComplete: () => isOnboardingComplete,
20489
20489
  isSootsimDevCheckout: () => isSootsimDevCheckout,
20490
+ playwrightCoreDir: () => playwrightCoreDir,
20490
20491
  profilesDir: () => profilesDir,
20491
20492
  readActiveRuntime: () => readActiveRuntime,
20492
20493
  readDaemonLockfile: () => readDaemonLockfile,
@@ -20557,6 +20558,9 @@ function electronUserDataDir() {
20557
20558
  function electronVersionDir(version) {
20558
20559
  return import_node_path4.default.join(electronDir(), version);
20559
20560
  }
20561
+ function playwrightCoreDir(version) {
20562
+ return import_node_path4.default.join(rnxHomeDir(), "playwright-core", version);
20563
+ }
20560
20564
  function profilesDir() {
20561
20565
  return import_node_path4.default.join(rnxHomeDir(), "profiles");
20562
20566
  }
@@ -20638,7 +20642,7 @@ function readPrivacyPreferences() {
20638
20642
  return {
20639
20643
  productAnalytics: typeof productAnalytics === "boolean" ? productAnalytics : false,
20640
20644
  crashReports: typeof crashReports === "boolean" ? crashReports : false,
20641
- configured: typeof productAnalytics === "boolean" && typeof crashReports === "boolean"
20645
+ configured: typeof productAnalytics === "boolean"
20642
20646
  };
20643
20647
  }
20644
20648
  function writePrivacyPreferences(preferences) {
@@ -20650,10 +20654,13 @@ function writePrivacyPreferences(preferences) {
20650
20654
  });
20651
20655
  }
20652
20656
  function readOrCreateAnonymousId() {
20653
- const existing = readSharedConfig().anonymousId;
20654
- if (typeof existing === "string" && existing.trim()) return existing;
20657
+ const existing = readSharedConfig().settings?.anonymousId;
20658
+ if (typeof existing === "string" && /^anon-cli-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(
20659
+ existing
20660
+ ))
20661
+ return existing;
20655
20662
  const created = `anon-cli-${(0, import_node_crypto.randomUUID)()}`;
20656
- writeSharedConfig({ anonymousId: created });
20663
+ writeSharedConfig({ settings: { anonymousId: created } });
20657
20664
  return created;
20658
20665
  }
20659
20666
  function readDefaultBox() {
@@ -21212,48 +21219,16 @@ function createRuntimeDelivery(product) {
21212
21219
  manifest
21213
21220
  };
21214
21221
  }
21215
- const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
21216
- const downloadDir = import_node_fs7.default.mkdtempSync(
21217
- import_node_path7.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
21218
- );
21219
- const runtimeArchivePath = import_node_path7.default.join(
21220
- downloadDir,
21221
- runtimeTarballCacheName(product, version)
21222
- );
21223
- const tmpDir = import_node_path7.default.join(
21224
- import_node_path7.default.dirname(destDir),
21225
- `.installing-${version}-${process.pid}`
21226
- );
21227
- import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
21228
- try {
21229
- if (!opts.quiet)
21230
- process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
21222
+ if (!opts.quiet)
21223
+ process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
21231
21224
  `);
21232
- await downloadToFile(tarUrl, runtimeArchivePath);
21233
- if (!opts.quiet)
21234
- process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
21235
- `);
21236
- const actualSha = await sha256File(runtimeArchivePath);
21237
- if (actualSha !== entry.sha256) {
21238
- throw new Error(
21239
- `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
21240
- );
21241
- }
21242
- import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
21243
- await extractTarball(runtimeArchivePath, tmpDir);
21244
- if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, product.installedMarker))) {
21245
- throw new Error(
21246
- `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
21247
- );
21248
- }
21249
- import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
21250
- import_node_fs7.default.renameSync(tmpDir, destDir);
21251
- } catch (err) {
21252
- import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
21253
- throw err;
21254
- } finally {
21255
- import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
21256
- }
21225
+ await installVerifiedTarball({
21226
+ url: entry.tarball || tarballUrl(version, cdnOrigin),
21227
+ digest: { algorithm: "sha256", encoding: "hex", value: entry.sha256 },
21228
+ destDir,
21229
+ installedMarker: product.installedMarker,
21230
+ label: `runtime ${version}`
21231
+ });
21257
21232
  if (setActive) product.writeActiveRuntime(version);
21258
21233
  pruneLocalRetention({ protectVersions });
21259
21234
  return {
@@ -21443,6 +21418,37 @@ function createRuntimeDelivery(product) {
21443
21418
  listInstalled: () => listInstalledRuntimes(product)
21444
21419
  };
21445
21420
  }
21421
+ async function installVerifiedTarball(tarball) {
21422
+ const { url, digest, destDir, installedMarker, label } = tarball;
21423
+ const downloadDir = import_node_fs7.default.mkdtempSync(import_node_path7.default.join(import_node_os2.default.tmpdir(), "runtime-delivery-download-"));
21424
+ const archivePath = import_node_path7.default.join(downloadDir, "archive.tar.gz");
21425
+ const tmpDir = import_node_path7.default.join(
21426
+ import_node_path7.default.dirname(destDir),
21427
+ `.installing-${import_node_path7.default.basename(destDir)}-${process.pid}`
21428
+ );
21429
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
21430
+ try {
21431
+ await downloadToFile(url, archivePath);
21432
+ const actual = await digestFile(archivePath, digest.algorithm, digest.encoding);
21433
+ if (actual !== digest.value) {
21434
+ throw new Error(
21435
+ `${digest.algorithm} mismatch for ${label}: expected ${digest.value}, actual ${actual}`
21436
+ );
21437
+ }
21438
+ import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
21439
+ await extractTarball(archivePath, tmpDir, tarball.stripComponents ?? 0);
21440
+ if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, installedMarker))) {
21441
+ throw new Error(`extracted tarball for ${label} is missing ${installedMarker}`);
21442
+ }
21443
+ import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
21444
+ import_node_fs7.default.renameSync(tmpDir, destDir);
21445
+ } catch (err) {
21446
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
21447
+ throw err;
21448
+ } finally {
21449
+ import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
21450
+ }
21451
+ }
21446
21452
  async function downloadToFile(url, destPath) {
21447
21453
  const res = await fetch(url);
21448
21454
  if (!res.ok || !res.body) {
@@ -21464,18 +21470,20 @@ async function downloadToFile(url, destPath) {
21464
21470
  throw err;
21465
21471
  }
21466
21472
  }
21467
- function sha256File(filePath) {
21473
+ function digestFile(filePath, algorithm, encoding) {
21468
21474
  return new Promise((resolve9, reject) => {
21469
- const hash = import_node_crypto2.default.createHash("sha256");
21475
+ const hash = import_node_crypto2.default.createHash(algorithm);
21470
21476
  const stream = import_node_fs7.default.createReadStream(filePath);
21471
21477
  stream.on("data", (chunk) => hash.update(chunk));
21472
21478
  stream.on("error", reject);
21473
- stream.on("end", () => resolve9(hash.digest("hex")));
21479
+ stream.on("end", () => resolve9(hash.digest(encoding)));
21474
21480
  });
21475
21481
  }
21476
- function extractTarball(tarPath, destDir) {
21482
+ function extractTarball(tarPath, destDir, stripComponents) {
21477
21483
  return new Promise((resolve9, reject) => {
21478
- const child = (0, import_node_child_process3.spawn)("tar", ["-xzf", tarPath, "-C", destDir], {
21484
+ const args = ["-xzf", tarPath, "-C", destDir];
21485
+ if (stripComponents > 0) args.push(`--strip-components=${stripComponents}`);
21486
+ const child = (0, import_node_child_process3.spawn)("tar", args, {
21479
21487
  stdio: ["ignore", "inherit", "inherit"]
21480
21488
  });
21481
21489
  child.on("error", reject);
@@ -22679,10 +22687,10 @@ var init_agent_host = __esm({
22679
22687
  return simId;
22680
22688
  }
22681
22689
  listenForInspect(socket, simId) {
22682
- const queue = this.inspectQueues.get(simId);
22683
- const queued = queue?.shift();
22684
- if (queued && queue) {
22685
- if (queue.length === 0) this.inspectQueues.delete(simId);
22690
+ const queue2 = this.inspectQueues.get(simId);
22691
+ const queued = queue2?.shift();
22692
+ if (queued && queue2) {
22693
+ if (queue2.length === 0) this.inspectQueues.delete(simId);
22686
22694
  return Promise.resolve(queued);
22687
22695
  }
22688
22696
  return new Promise((resolve9, reject) => {
@@ -22708,9 +22716,9 @@ var init_agent_host = __esm({
22708
22716
  listener.resolve(message);
22709
22717
  return { ok: true, queued: false, messageId: message.id };
22710
22718
  }
22711
- const queue = this.inspectQueues.get(simId) ?? [];
22712
- queue.push(message);
22713
- this.inspectQueues.set(simId, queue);
22719
+ const queue2 = this.inspectQueues.get(simId) ?? [];
22720
+ queue2.push(message);
22721
+ this.inspectQueues.set(simId, queue2);
22714
22722
  return { ok: true, queued: true, messageId: message.id };
22715
22723
  }
22716
22724
  async doStartSession(input) {
@@ -27601,13 +27609,13 @@ function embedTemplateRoot(args) {
27601
27609
  const root = template.roots[args.rootIndex];
27602
27610
  const moduleIdsByNode = /* @__PURE__ */ new Map([[root.node, args.bundleRoot.moduleId]]);
27603
27611
  const nodesByModuleId = /* @__PURE__ */ new Map([[args.bundleRoot.moduleId, root.node]]);
27604
- const queue = [root.node];
27612
+ const queue2 = [root.node];
27605
27613
  let exactFactoryMatches = 0;
27606
27614
  let uniqueChildFactoryMatches = 0;
27607
27615
  let uniqueChildAtomMatches = 0;
27608
27616
  let weakRootMatch = false;
27609
- for (let cursor = 0; cursor < queue.length; cursor++) {
27610
- const nodeIndex = queue[cursor];
27617
+ for (let cursor = 0; cursor < queue2.length; cursor++) {
27618
+ const nodeIndex = queue2[cursor];
27611
27619
  const moduleId = moduleIdsByNode.get(nodeIndex);
27612
27620
  if (moduleId === void 0) return null;
27613
27621
  const bundleModule = args.bundleById.get(moduleId);
@@ -27646,7 +27654,7 @@ function embedTemplateRoot(args) {
27646
27654
  if (existingModuleId === void 0) {
27647
27655
  moduleIdsByNode.set(edge.node, dependencyId);
27648
27656
  nodesByModuleId.set(dependencyId, edge.node);
27649
- queue.push(edge.node);
27657
+ queue2.push(edge.node);
27650
27658
  }
27651
27659
  }
27652
27660
  }
@@ -28175,39 +28183,82 @@ function detectFramework2(deps) {
28175
28183
  return "unknown";
28176
28184
  }
28177
28185
  function detectProject(dir) {
28178
- const pkgPath = (0, import_path2.join)(dir, "package.json");
28179
- if (!(0, import_fs2.existsSync)(pkgPath)) return null;
28180
- let pkg;
28181
- try {
28182
- pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf8"));
28183
- } catch {
28184
- return null;
28185
- }
28186
+ const pkgPath = (0, import_node_path16.join)(dir, "package.json");
28187
+ if (!(0, import_node_fs15.existsSync)(pkgPath)) return null;
28188
+ const pkg = readProjectManifest(dir);
28189
+ if (!pkg) return null;
28186
28190
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
28191
+ const devCommand = metadataValue(
28192
+ metadataValue(readProjectJson(pkgPath), "scripts"),
28193
+ "dev"
28194
+ );
28187
28195
  const framework = detectFramework2(deps);
28188
28196
  if (framework === "unknown") return null;
28189
28197
  return {
28190
28198
  dir,
28191
- name: pkg.name || (0, import_path2.basename)(dir),
28199
+ name: pkg.name || (0, import_node_path16.basename)(dir),
28192
28200
  framework,
28193
28201
  // a config file is a config file whatever module system it declares. real
28194
28202
  // apps write .cjs as often as .js, and missing one reads as "this project
28195
28203
  // has no bundler config" and sends the user to create a second one.
28196
28204
  hasViteConfig: CONFIG_EXTENSIONS.some(
28197
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `vite.config.${ext}`))
28205
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `vite.config.${ext}`))
28198
28206
  ),
28199
28207
  hasMetroConfig: CONFIG_EXTENSIONS.some(
28200
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `metro.config.${ext}`))
28208
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `metro.config.${ext}`))
28201
28209
  ),
28202
- devCommand: pkg.scripts?.dev || null
28210
+ devCommand: typeof devCommand === "string" ? devCommand : null
28203
28211
  };
28204
28212
  }
28205
- var import_fs2, import_path2, CONFIG_EXTENSIONS;
28213
+ function readProjectMetadata(path22) {
28214
+ try {
28215
+ const info = (0, import_node_fs15.lstatSync)(path22);
28216
+ if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
28217
+ return (0, import_node_fs15.readFileSync)(path22, "utf8");
28218
+ } catch {
28219
+ return null;
28220
+ }
28221
+ }
28222
+ function metadataValue(value, key) {
28223
+ if (!value || typeof value !== "object") return void 0;
28224
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
28225
+ }
28226
+ function readProjectJson(path22) {
28227
+ const text = readProjectMetadata(path22);
28228
+ if (text === null) return null;
28229
+ try {
28230
+ const value = JSON.parse(text);
28231
+ return value;
28232
+ } catch {
28233
+ return null;
28234
+ }
28235
+ }
28236
+ function readProjectManifest(dir) {
28237
+ const parsed = readProjectJson((0, import_node_path16.join)(dir, "package.json"));
28238
+ if (!parsed || typeof parsed !== "object") return null;
28239
+ const record = (value) => {
28240
+ if (!value || typeof value !== "object") return {};
28241
+ return Object.fromEntries(
28242
+ Object.entries(value).filter(
28243
+ (entry) => typeof entry[1] === "string" && /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/i.test(entry[0]) && entry[0] !== "." && entry[0] !== ".."
28244
+ )
28245
+ );
28246
+ };
28247
+ const name2 = metadataValue(parsed, "name");
28248
+ return {
28249
+ ...typeof name2 === "string" ? { name: name2 } : {},
28250
+ dependencies: record(metadataValue(parsed, "dependencies")),
28251
+ devDependencies: record(metadataValue(parsed, "devDependencies"))
28252
+ };
28253
+ }
28254
+ var import_node_fs15, import_node_path16, import_json5, import_yaml, CONFIG_EXTENSIONS;
28206
28255
  var init_detect = __esm({
28207
28256
  "cli/commands/detect.ts"() {
28208
28257
  "use strict";
28209
- import_fs2 = require("fs");
28210
- import_path2 = require("path");
28258
+ import_node_fs15 = require("node:fs");
28259
+ import_node_path16 = require("node:path");
28260
+ import_json5 = __toESM(require("json5"), 1);
28261
+ import_yaml = require("yaml");
28211
28262
  CONFIG_EXTENSIONS = ["ts", "js", "cjs", "mjs", "mts", "cts"];
28212
28263
  }
28213
28264
  });
@@ -28242,21 +28293,21 @@ function resolveCloudOrigin(value) {
28242
28293
  return normalizeCloudOrigin(source);
28243
28294
  }
28244
28295
  function readImmutableBundleSource(bundlePath) {
28245
- const filepath = (0, import_node_path16.resolve)(bundlePath);
28246
- if ((0, import_node_path16.extname)(filepath) !== ".js") {
28296
+ const filepath = (0, import_node_path17.resolve)(bundlePath);
28297
+ if ((0, import_node_path17.extname)(filepath) !== ".js") {
28247
28298
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
28248
28299
  }
28249
- const descriptor = (0, import_node_fs15.openSync)(filepath, "r");
28300
+ const descriptor = (0, import_node_fs16.openSync)(filepath, "r");
28250
28301
  try {
28251
- const before = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
28302
+ const before = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
28252
28303
  if (!before.isFile()) {
28253
28304
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
28254
28305
  }
28255
28306
  if (before.size <= 0n) {
28256
28307
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
28257
28308
  }
28258
- const bytes = (0, import_node_fs15.readFileSync)(descriptor);
28259
- const after = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
28309
+ const bytes = (0, import_node_fs16.readFileSync)(descriptor);
28310
+ const after = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
28260
28311
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
28261
28312
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
28262
28313
  }
@@ -28271,7 +28322,7 @@ function readImmutableBundleSource(bundlePath) {
28271
28322
  }
28272
28323
  return source;
28273
28324
  } finally {
28274
- (0, import_node_fs15.closeSync)(descriptor);
28325
+ (0, import_node_fs16.closeSync)(descriptor);
28275
28326
  }
28276
28327
  }
28277
28328
  async function fetchBundleSource(bundleUrl) {
@@ -28318,15 +28369,15 @@ async function loadBundleSource(bundleInput) {
28318
28369
  return readImmutableBundleSource(bundleInput);
28319
28370
  }
28320
28371
  function listMetroAssetDest(assetsPath) {
28321
- const directory = (0, import_node_path16.resolve)(assetsPath);
28322
- if (!(0, import_node_fs15.existsSync)(directory)) return { directory, files: [], truncated: false };
28323
- const skipNested = (0, import_node_fs15.existsSync)((0, import_node_path16.join)(directory, "package.json"));
28372
+ const directory = (0, import_node_path17.resolve)(assetsPath);
28373
+ if (!(0, import_node_fs16.existsSync)(directory)) return { directory, files: [], truncated: false };
28374
+ const skipNested = (0, import_node_fs16.existsSync)((0, import_node_path17.join)(directory, "package.json"));
28324
28375
  const files = [];
28325
28376
  let truncated = false;
28326
28377
  const walk = (dir, prefix) => {
28327
28378
  let entries;
28328
28379
  try {
28329
- entries = (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true });
28380
+ entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
28330
28381
  } catch {
28331
28382
  return;
28332
28383
  }
@@ -28338,7 +28389,7 @@ function listMetroAssetDest(assetsPath) {
28338
28389
  if (entry.isDirectory()) {
28339
28390
  if (entry.name === ".git") continue;
28340
28391
  if (skipNested && PROJECT_ONLY_DIRECTORIES.has(entry.name)) continue;
28341
- walk((0, import_node_path16.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
28392
+ walk((0, import_node_path17.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
28342
28393
  } else if (entry.isFile()) {
28343
28394
  files.push(prefix ? `${prefix}/${entry.name}` : entry.name);
28344
28395
  }
@@ -28373,7 +28424,7 @@ function distinctByContent(directory, options) {
28373
28424
  for (const relative2 of options) {
28374
28425
  let bytes;
28375
28426
  try {
28376
- bytes = (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(directory, relative2));
28427
+ bytes = (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(directory, relative2));
28377
28428
  } catch {
28378
28429
  continue;
28379
28430
  }
@@ -28405,7 +28456,7 @@ function placeMetroDescriptor(listing, descriptor) {
28405
28456
  let bytes;
28406
28457
  try {
28407
28458
  bytes = combination.map(
28408
- (relative2) => (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(listing.directory, relative2))
28459
+ (relative2) => (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(listing.directory, relative2))
28409
28460
  );
28410
28461
  } catch {
28411
28462
  continue;
@@ -28431,26 +28482,26 @@ function placeMetroDescriptor(listing, descriptor) {
28431
28482
  }
28432
28483
  function unverifiedFileKey(dest) {
28433
28484
  return dest.placements.filter((placement) => !placement.verified).flatMap(
28434
- (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path16.join)(dest.directory, relative2))
28485
+ (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path17.join)(dest.directory, relative2))
28435
28486
  ).sort().join("\n");
28436
28487
  }
28437
28488
  function searchMetroAssetDest(bundlePath, descriptors) {
28438
- const bundleDirectory = (0, import_node_path16.dirname)((0, import_node_path16.resolve)(bundlePath));
28489
+ const bundleDirectory = (0, import_node_path17.dirname)((0, import_node_path17.resolve)(bundlePath));
28439
28490
  const candidates = [
28440
- (0, import_node_path16.join)(bundleDirectory, "assets"),
28491
+ (0, import_node_path17.join)(bundleDirectory, "assets"),
28441
28492
  bundleDirectory,
28442
- (0, import_node_path16.resolve)(bundleDirectory, "..", "assets")
28493
+ (0, import_node_path17.resolve)(bundleDirectory, "..", "assets")
28443
28494
  ];
28444
28495
  const cwd = process.cwd();
28445
28496
  let projectDirectory = null;
28446
28497
  for (const start of [bundleDirectory, cwd]) {
28447
- let directory = (0, import_node_path16.resolve)(start);
28498
+ let directory = (0, import_node_path17.resolve)(start);
28448
28499
  while (true) {
28449
28500
  if (detectProject(directory)?.hasMetroConfig) {
28450
28501
  projectDirectory = directory;
28451
28502
  break;
28452
28503
  }
28453
- const parent = (0, import_node_path16.dirname)(directory);
28504
+ const parent = (0, import_node_path17.dirname)(directory);
28454
28505
  if (parent === directory) break;
28455
28506
  directory = parent;
28456
28507
  }
@@ -28458,11 +28509,11 @@ function searchMetroAssetDest(bundlePath, descriptors) {
28458
28509
  }
28459
28510
  if (projectDirectory) {
28460
28511
  candidates.push(
28461
- (0, import_node_path16.join)(projectDirectory, "assets"),
28462
- (0, import_node_path16.join)(projectDirectory, "dist"),
28463
- (0, import_node_path16.join)(projectDirectory, "dist", "assets"),
28464
- (0, import_node_path16.join)(projectDirectory, "build"),
28465
- (0, import_node_path16.join)(projectDirectory, "build", "assets")
28512
+ (0, import_node_path17.join)(projectDirectory, "assets"),
28513
+ (0, import_node_path17.join)(projectDirectory, "dist"),
28514
+ (0, import_node_path17.join)(projectDirectory, "dist", "assets"),
28515
+ (0, import_node_path17.join)(projectDirectory, "build"),
28516
+ (0, import_node_path17.join)(projectDirectory, "build", "assets")
28466
28517
  );
28467
28518
  }
28468
28519
  const searched = [];
@@ -28470,7 +28521,7 @@ function searchMetroAssetDest(bundlePath, descriptors) {
28470
28521
  const stale = [];
28471
28522
  let truncated = false;
28472
28523
  for (const candidate of candidates) {
28473
- const directory = (0, import_node_path16.resolve)(candidate);
28524
+ const directory = (0, import_node_path17.resolve)(candidate);
28474
28525
  if (searched.includes(directory)) continue;
28475
28526
  searched.push(directory);
28476
28527
  const listing = listMetroAssetDest(directory);
@@ -28576,7 +28627,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
28576
28627
  );
28577
28628
  }
28578
28629
  const relative2 = placement?.files.get(variant.scale);
28579
- if (relative2 && dest) return (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(dest.directory, relative2));
28630
+ if (relative2 && dest) return (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(dest.directory, relative2));
28580
28631
  if (placement && placement.files.size > 0) return null;
28581
28632
  if (placement && placement.ambiguous.length > 0 && dest) {
28582
28633
  throw new Error(
@@ -28605,7 +28656,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
28605
28656
  );
28606
28657
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
28607
28658
  throw new Error(
28608
- `${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\`.`
28659
+ `${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\`.`
28609
28660
  );
28610
28661
  });
28611
28662
  return {
@@ -28791,13 +28842,13 @@ function createCloudBridgeForParsed(parsed) {
28791
28842
  if (!session) return null;
28792
28843
  return session.service === "box" ? new CloudBoxBridge(session) : new CloudBridge(session);
28793
28844
  }
28794
- 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, CloudBridge, CloudBoxBridge;
28845
+ 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, CloudBridge, CloudBoxBridge;
28795
28846
  var init_cloud_client = __esm({
28796
28847
  "cli/cloud-client.ts"() {
28797
28848
  "use strict";
28798
28849
  import_node_crypto6 = require("node:crypto");
28799
- import_node_fs15 = require("node:fs");
28800
- import_node_path16 = require("node:path");
28850
+ import_node_fs16 = require("node:fs");
28851
+ import_node_path17 = require("node:path");
28801
28852
  init_metroAssetArtifact();
28802
28853
  init_metroCloudArtifact();
28803
28854
  init_metro_fingerprint_registry_client();
@@ -29068,14 +29119,14 @@ function unrefTimer(timer) {
29068
29119
  timer.unref();
29069
29120
  }
29070
29121
  }
29071
- var import_child_process3, import_fs3, import_http4, import_path3, import_ws, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, CAMERA_FIXTURE_ROUTE, CAMERA_FIXTURE_NAME_RE, SootSimBridgeHost;
29122
+ var import_child_process3, import_fs2, import_http4, import_path2, import_ws, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, CAMERA_FIXTURE_ROUTE, CAMERA_FIXTURE_NAME_RE, SootSimBridgeHost;
29072
29123
  var init_bridge_host = __esm({
29073
29124
  "src/host/bridge-host.ts"() {
29074
29125
  "use strict";
29075
29126
  import_child_process3 = require("child_process");
29076
- import_fs3 = __toESM(require("fs"), 1);
29127
+ import_fs2 = __toESM(require("fs"), 1);
29077
29128
  import_http4 = require("http");
29078
- import_path3 = __toESM(require("path"), 1);
29129
+ import_path2 = __toESM(require("path"), 1);
29079
29130
  import_ws = require("ws");
29080
29131
  init_dev_server_scanner();
29081
29132
  init_backend_origin();
@@ -29233,7 +29284,7 @@ var init_bridge_host = __esm({
29233
29284
  async startAsync(options) {
29234
29285
  if (this.httpServer || this.wss) return this.effectivePort;
29235
29286
  this.refreshActiveRuntime();
29236
- this.bootstrapping = !this.activeRuntimeDirPath || !import_fs3.default.existsSync(import_path3.default.join(this.activeRuntimeDirPath, "index.html"));
29287
+ this.bootstrapping = !this.activeRuntimeDirPath || !import_fs2.default.existsSync(import_path2.default.join(this.activeRuntimeDirPath, "index.html"));
29237
29288
  for (let attempt = 0; attempt < this.portFallbackCount; attempt++) {
29238
29289
  const candidate = this.preferredPort + attempt;
29239
29290
  try {
@@ -29905,10 +29956,10 @@ var init_bridge_host = __esm({
29905
29956
  return;
29906
29957
  }
29907
29958
  const root = cameraFixturesDir();
29908
- const filePath = import_path3.default.join(root, name2);
29959
+ const filePath = import_path2.default.join(root, name2);
29909
29960
  let stats;
29910
29961
  try {
29911
- stats = import_fs3.default.lstatSync(filePath);
29962
+ stats = import_fs2.default.lstatSync(filePath);
29912
29963
  } catch {
29913
29964
  res.writeHead(404, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
29914
29965
  res.end("not found");
@@ -29919,7 +29970,7 @@ var init_bridge_host = __esm({
29919
29970
  res.end("forbidden");
29920
29971
  return;
29921
29972
  }
29922
- const contentType = HTTP_MIME_TYPES[import_path3.default.extname(filePath).toLowerCase()] || "application/octet-stream";
29973
+ const contentType = HTTP_MIME_TYPES[import_path2.default.extname(filePath).toLowerCase()] || "application/octet-stream";
29923
29974
  sendFileWithRanges(req, res, filePath, stats.size, {
29924
29975
  ...cors,
29925
29976
  "Content-Type": contentType
@@ -30296,34 +30347,34 @@ var init_bridge_host = __esm({
30296
30347
  return;
30297
30348
  }
30298
30349
  }
30299
- const resolved = import_path3.default.resolve(baseDir, "." + rel);
30300
- const baseWithSep = baseDir.endsWith(import_path3.default.sep) ? baseDir : baseDir + import_path3.default.sep;
30350
+ const resolved = import_path2.default.resolve(baseDir, "." + rel);
30351
+ const baseWithSep = baseDir.endsWith(import_path2.default.sep) ? baseDir : baseDir + import_path2.default.sep;
30301
30352
  if (!resolved.startsWith(baseWithSep) && resolved !== baseDir) {
30302
30353
  res.writeHead(403);
30303
30354
  res.end("forbidden");
30304
30355
  return;
30305
30356
  }
30306
- import_fs3.default.realpath(resolved, (realErr, realResolved) => {
30357
+ import_fs2.default.realpath(resolved, (realErr, realResolved) => {
30307
30358
  const servePath = realErr ? resolved : realResolved;
30308
- const servePathWithSep = servePath.endsWith(import_path3.default.sep) ? servePath : servePath + import_path3.default.sep;
30359
+ const servePathWithSep = servePath.endsWith(import_path2.default.sep) ? servePath : servePath + import_path2.default.sep;
30309
30360
  if (!realErr) {
30310
30361
  const realBaseWithSep = (() => {
30311
30362
  try {
30312
- const rb = import_fs3.default.realpathSync(baseDir);
30313
- return rb.endsWith(import_path3.default.sep) ? rb : rb + import_path3.default.sep;
30363
+ const rb = import_fs2.default.realpathSync(baseDir);
30364
+ return rb.endsWith(import_path2.default.sep) ? rb : rb + import_path2.default.sep;
30314
30365
  } catch {
30315
30366
  return baseWithSep;
30316
30367
  }
30317
30368
  })();
30318
- if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path3.default.sep !== realBaseWithSep) {
30369
+ if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path2.default.sep !== realBaseWithSep) {
30319
30370
  res.writeHead(403);
30320
30371
  res.end("forbidden");
30321
30372
  return;
30322
30373
  }
30323
30374
  }
30324
- import_fs3.default.stat(servePath, (err, stats) => {
30375
+ import_fs2.default.stat(servePath, (err, stats) => {
30325
30376
  if (err || !stats?.isFile()) {
30326
- const ext2 = import_path3.default.extname(rel).toLowerCase();
30377
+ const ext2 = import_path2.default.extname(rel).toLowerCase();
30327
30378
  if (ext2 && ext2 !== ".html") {
30328
30379
  res.writeHead(404);
30329
30380
  res.end("not found");
@@ -30334,8 +30385,8 @@ var init_bridge_host = __esm({
30334
30385
  res.end("not found");
30335
30386
  return;
30336
30387
  }
30337
- const indexPath = import_path3.default.join(baseDir, "index.html");
30338
- import_fs3.default.readFile(indexPath, (err2, data) => {
30388
+ const indexPath = import_path2.default.join(baseDir, "index.html");
30389
+ import_fs2.default.readFile(indexPath, (err2, data) => {
30339
30390
  if (err2) {
30340
30391
  res.writeHead(404);
30341
30392
  res.end("not found");
@@ -30355,7 +30406,7 @@ var init_bridge_host = __esm({
30355
30406
  });
30356
30407
  return;
30357
30408
  }
30358
- const ext = import_path3.default.extname(servePath).toLowerCase();
30409
+ const ext = import_path2.default.extname(servePath).toLowerCase();
30359
30410
  const contentType = HTTP_MIME_TYPES[ext] || "application/octet-stream";
30360
30411
  res.writeHead(200, {
30361
30412
  "Content-Type": contentType,
@@ -30366,7 +30417,7 @@ var init_bridge_host = __esm({
30366
30417
  return;
30367
30418
  }
30368
30419
  if (ext === ".html") {
30369
- import_fs3.default.readFile(servePath, (readErr, data) => {
30420
+ import_fs2.default.readFile(servePath, (readErr, data) => {
30370
30421
  if (readErr) {
30371
30422
  try {
30372
30423
  res.end();
@@ -30380,7 +30431,7 @@ var init_bridge_host = __esm({
30380
30431
  });
30381
30432
  return;
30382
30433
  }
30383
- const stream = import_fs3.default.createReadStream(servePath);
30434
+ const stream = import_fs2.default.createReadStream(servePath);
30384
30435
  stream.pipe(res);
30385
30436
  stream.on("error", () => {
30386
30437
  try {
@@ -31067,7 +31118,7 @@ function buildComm() {
31067
31118
  if (process.platform === "linux") {
31068
31119
  return (pid) => {
31069
31120
  try {
31070
- return (0, import_fs4.readFileSync)(`/proc/${pid}/comm`, "utf8").trim() || null;
31121
+ return (0, import_fs3.readFileSync)(`/proc/${pid}/comm`, "utf8").trim() || null;
31071
31122
  } catch {
31072
31123
  return null;
31073
31124
  }
@@ -31125,7 +31176,7 @@ function readProcessTable() {
31125
31176
  function buildLinux() {
31126
31177
  return (pid) => {
31127
31178
  try {
31128
- const raw = (0, import_fs4.readFileSync)(`/proc/${pid}/stat`, "utf8");
31179
+ const raw = (0, import_fs3.readFileSync)(`/proc/${pid}/stat`, "utf8");
31129
31180
  const end = raw.lastIndexOf(")");
31130
31181
  if (end < 0) return null;
31131
31182
  const rest = raw.slice(end + 1).trim().split(/\s+/);
@@ -31186,12 +31237,12 @@ function tryBuildDarwinCommFfi() {
31186
31237
  return null;
31187
31238
  }
31188
31239
  }
31189
- var import_child_process4, import_fs4, import_module, cached3, cachedComm, PROCESS_TABLE_TTL_MS, processTable, PROC_PIDTBSDINFO, PROC_BSDINFO_SIZE, PBI_PPID_OFFSET, PBI_COMM_OFFSET, PBI_COMM_LEN;
31240
+ var import_child_process4, import_fs3, import_module, cached3, cachedComm, PROCESS_TABLE_TTL_MS, processTable, PROC_PIDTBSDINFO, PROC_BSDINFO_SIZE, PBI_PPID_OFFSET, PBI_COMM_OFFSET, PBI_COMM_LEN;
31190
31241
  var init_parent_pid = __esm({
31191
31242
  "cli/parent-pid.ts"() {
31192
31243
  "use strict";
31193
31244
  import_child_process4 = require("child_process");
31194
- import_fs4 = require("fs");
31245
+ import_fs3 = require("fs");
31195
31246
  import_module = require("module");
31196
31247
  cached3 = null;
31197
31248
  cachedComm = null;
@@ -31207,31 +31258,31 @@ var init_parent_pid = __esm({
31207
31258
 
31208
31259
  // cli/secure-file.ts
31209
31260
  function writeSecureJsonAtomic(filepath, value) {
31210
- (0, import_node_fs16.mkdirSync)((0, import_node_path17.dirname)(filepath), { recursive: true });
31261
+ (0, import_node_fs17.mkdirSync)((0, import_node_path18.dirname)(filepath), { recursive: true });
31211
31262
  const temporary = `${filepath}.tmp-${process.pid}-${(0, import_node_crypto7.randomUUID)()}`;
31212
31263
  let descriptor = null;
31213
31264
  try {
31214
- descriptor = (0, import_node_fs16.openSync)(temporary, "wx", 384);
31215
- (0, import_node_fs16.fchmodSync)(descriptor, 384);
31216
- (0, import_node_fs16.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
31265
+ descriptor = (0, import_node_fs17.openSync)(temporary, "wx", 384);
31266
+ (0, import_node_fs17.fchmodSync)(descriptor, 384);
31267
+ (0, import_node_fs17.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
31217
31268
  `);
31218
- (0, import_node_fs16.fsyncSync)(descriptor);
31219
- (0, import_node_fs16.closeSync)(descriptor);
31269
+ (0, import_node_fs17.fsyncSync)(descriptor);
31270
+ (0, import_node_fs17.closeSync)(descriptor);
31220
31271
  descriptor = null;
31221
- (0, import_node_fs16.renameSync)(temporary, filepath);
31272
+ (0, import_node_fs17.renameSync)(temporary, filepath);
31222
31273
  } catch (error) {
31223
- if (descriptor !== null) (0, import_node_fs16.closeSync)(descriptor);
31224
- (0, import_node_fs16.rmSync)(temporary, { force: true });
31274
+ if (descriptor !== null) (0, import_node_fs17.closeSync)(descriptor);
31275
+ (0, import_node_fs17.rmSync)(temporary, { force: true });
31225
31276
  throw error;
31226
31277
  }
31227
31278
  }
31228
- var import_node_crypto7, import_node_fs16, import_node_path17;
31279
+ var import_node_crypto7, import_node_fs17, import_node_path18;
31229
31280
  var init_secure_file = __esm({
31230
31281
  "cli/secure-file.ts"() {
31231
31282
  "use strict";
31232
31283
  import_node_crypto7 = require("node:crypto");
31233
- import_node_fs16 = require("node:fs");
31234
- import_node_path17 = require("node:path");
31284
+ import_node_fs17 = require("node:fs");
31285
+ import_node_path18 = require("node:path");
31235
31286
  }
31236
31287
  });
31237
31288
 
@@ -31276,22 +31327,22 @@ function getStableOwnerPid() {
31276
31327
  }
31277
31328
  function getCurrentSimPath() {
31278
31329
  if (process.env[CURRENT_SIM_PATH_ENV]) {
31279
- return (0, import_path4.resolve)(process.env[CURRENT_SIM_PATH_ENV]);
31330
+ return (0, import_path3.resolve)(process.env[CURRENT_SIM_PATH_ENV]);
31280
31331
  }
31281
31332
  const key = getCliIdentityKey();
31282
- return (0, import_path4.join)((0, import_os.tmpdir)(), `peach-current-sim-${key}.json`);
31333
+ return (0, import_path3.join)((0, import_os.tmpdir)(), `peach-current-sim-${key}.json`);
31283
31334
  }
31284
31335
  function legacyCloudCredentialDirectory(filepath) {
31285
- return (0, import_path4.join)((0, import_path4.dirname)(filepath), `${(0, import_path4.basename)(filepath)}.credentials`);
31336
+ return (0, import_path3.join)((0, import_path3.dirname)(filepath), `${(0, import_path3.basename)(filepath)}.credentials`);
31286
31337
  }
31287
31338
  function readCurrentTarget() {
31288
31339
  const filepath = getCurrentSimPath();
31289
- (0, import_fs5.rmSync)(legacyCloudCredentialDirectory(filepath), { recursive: true, force: true });
31290
- if (!(0, import_fs5.existsSync)(filepath)) return null;
31340
+ (0, import_fs4.rmSync)(legacyCloudCredentialDirectory(filepath), { recursive: true, force: true });
31341
+ if (!(0, import_fs4.existsSync)(filepath)) return null;
31291
31342
  try {
31292
- const parsed = JSON.parse((0, import_fs5.readFileSync)(filepath, "utf8"));
31343
+ const parsed = JSON.parse((0, import_fs4.readFileSync)(filepath, "utf8"));
31293
31344
  if (parsed === null || typeof parsed !== "object") {
31294
- (0, import_fs5.rmSync)(filepath, { force: true });
31345
+ (0, import_fs4.rmSync)(filepath, { force: true });
31295
31346
  return null;
31296
31347
  }
31297
31348
  const version = Reflect.get(parsed, "version");
@@ -31299,7 +31350,7 @@ function readCurrentTarget() {
31299
31350
  const simId = Reflect.get(parsed, "simId");
31300
31351
  const updatedAt = Reflect.get(parsed, "updatedAt");
31301
31352
  if (version !== 1 && version !== CURRENT_SIM_VERSION || version === CURRENT_SIM_VERSION && plane !== "local" || typeof simId !== "string" || !simId.trim() || typeof updatedAt !== "string") {
31302
- (0, import_fs5.rmSync)(filepath, { force: true });
31353
+ (0, import_fs4.rmSync)(filepath, { force: true });
31303
31354
  return null;
31304
31355
  }
31305
31356
  const target = {
@@ -31311,7 +31362,7 @@ function readCurrentTarget() {
31311
31362
  if (version === 1) writeSecureJsonAtomic(filepath, target);
31312
31363
  return target;
31313
31364
  } catch {
31314
- (0, import_fs5.rmSync)(filepath, { force: true });
31365
+ (0, import_fs4.rmSync)(filepath, { force: true });
31315
31366
  return null;
31316
31367
  }
31317
31368
  }
@@ -31329,15 +31380,15 @@ function saveCurrentSimId(simId) {
31329
31380
  });
31330
31381
  }
31331
31382
  function clearCurrentSimId() {
31332
- (0, import_fs5.rmSync)(getCurrentSimPath(), { force: true });
31383
+ (0, import_fs4.rmSync)(getCurrentSimPath(), { force: true });
31333
31384
  }
31334
- var import_fs5, import_os, import_path4, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, readCurrentSim;
31385
+ var import_fs4, import_os, import_path3, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, readCurrentSim;
31335
31386
  var init_current_sim = __esm({
31336
31387
  "cli/current-sim.ts"() {
31337
31388
  "use strict";
31338
- import_fs5 = require("fs");
31389
+ import_fs4 = require("fs");
31339
31390
  import_os = require("os");
31340
- import_path4 = require("path");
31391
+ import_path3 = require("path");
31341
31392
  init_parent_pid();
31342
31393
  init_secure_file();
31343
31394
  CURRENT_SIM_VERSION = 2;
@@ -31406,17 +31457,17 @@ function liveDevBridgeLockfiles() {
31406
31457
  return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
31407
31458
  }
31408
31459
  function checkoutRoot(cwd) {
31409
- let current = import_node_path18.default.resolve(cwd);
31460
+ let current = import_node_path19.default.resolve(cwd);
31410
31461
  while (true) {
31411
- if (import_node_fs17.default.existsSync(import_node_path18.default.join(current, ".git"))) return current;
31412
- const parent = import_node_path18.default.dirname(current);
31462
+ if (import_node_fs18.default.existsSync(import_node_path19.default.join(current, ".git"))) return current;
31463
+ const parent = import_node_path19.default.dirname(current);
31413
31464
  if (parent === current) return null;
31414
31465
  current = parent;
31415
31466
  }
31416
31467
  }
31417
31468
  function pathContains(parent, child) {
31418
- const relative2 = import_node_path18.default.relative(parent, child);
31419
- return relative2 === "" || relative2 !== ".." && !relative2.startsWith(`..${import_node_path18.default.sep}`) && !import_node_path18.default.isAbsolute(relative2);
31469
+ const relative2 = import_node_path19.default.relative(parent, child);
31470
+ return relative2 === "" || relative2 !== ".." && !relative2.startsWith(`..${import_node_path19.default.sep}`) && !import_node_path19.default.isAbsolute(relative2);
31420
31471
  }
31421
31472
  function resolveDefaultDevBridgeLockfile() {
31422
31473
  const lockfiles = liveDevBridgeLockfiles();
@@ -31644,7 +31695,12 @@ function createBridge(wsPort, opts = {}) {
31644
31695
  });
31645
31696
  ws.on("error", (err) => {
31646
31697
  const cause = err.message ? `: ${err.message}` : "";
31647
- reject(new Error(`could not connect to ${bridgeWsUrl(wsPort)}${cause}`));
31698
+ reject(
31699
+ new Error(
31700
+ `could not connect to ${bridgeWsUrl(wsPort)}${cause}
31701
+ for sandboxed or agent runners, keep \`peach serve --port ${wsPort}\` running in a persistent terminal or background task.`
31702
+ )
31703
+ );
31648
31704
  });
31649
31705
  });
31650
31706
  ready.catch(() => {
@@ -31914,12 +31970,12 @@ async function callInBridge(bridge, path22, ...args) {
31914
31970
  async function callInBridgeWrite(bridge, path22, ...args) {
31915
31971
  return bridge.send({ type: "call", path: path22, args, acquireLock: true });
31916
31972
  }
31917
- var import_node_fs17, import_node_path18, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
31973
+ var import_node_fs18, import_node_path19, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
31918
31974
  var init_ws_bridge = __esm({
31919
31975
  "cli/ws-bridge.ts"() {
31920
31976
  "use strict";
31921
- import_node_fs17 = __toESM(require("node:fs"), 1);
31922
- import_node_path18 = __toESM(require("node:path"), 1);
31977
+ import_node_fs18 = __toESM(require("node:fs"), 1);
31978
+ import_node_path19 = __toESM(require("node:path"), 1);
31923
31979
  import_ws2 = require("ws");
31924
31980
  init_bridge_constants();
31925
31981
  init_cli_constants();
@@ -32231,9 +32287,9 @@ function readNativeFirebaseConfig(projectRoot) {
32231
32287
  "app.config.ts",
32232
32288
  "app.config.cjs",
32233
32289
  "app.config.mjs"
32234
- ].some((name2) => import_node_fs18.default.existsSync(import_node_path19.default.join(projectRoot, name2))))
32290
+ ].some((name2) => import_node_fs19.default.existsSync(import_node_path20.default.join(projectRoot, name2))))
32235
32291
  return result;
32236
- const require5 = (0, import_node_module.createRequire)(import_node_path19.default.join(projectRoot, "package.json"));
32292
+ const require5 = (0, import_node_module.createRequire)(import_node_path20.default.join(projectRoot, "package.json"));
32237
32293
  const configModule = require5("@expo/config");
32238
32294
  if (!isRecord(configModule) || typeof configModule.getConfig !== "function") {
32239
32295
  throw new Error("Expo native configuration is unavailable.");
@@ -32247,8 +32303,8 @@ function readNativeFirebaseConfig(projectRoot) {
32247
32303
  const native = config[platform];
32248
32304
  if (!isRecord(native) || typeof native.googleServicesFile !== "string") continue;
32249
32305
  try {
32250
- const source = import_node_fs18.default.readFileSync(
32251
- import_node_path19.default.resolve(projectRoot, native.googleServicesFile),
32306
+ const source = import_node_fs19.default.readFileSync(
32307
+ import_node_path20.default.resolve(projectRoot, native.googleServicesFile),
32252
32308
  "utf8"
32253
32309
  );
32254
32310
  const parsed = platform === "ios" ? parsePlistSource(source) : JSON.parse(source);
@@ -32300,13 +32356,13 @@ function readNativeFirebaseConfig(projectRoot) {
32300
32356
  }
32301
32357
  return result;
32302
32358
  }
32303
- var import_node_fs18, import_node_module, import_node_path19;
32359
+ var import_node_fs19, import_node_module, import_node_path20;
32304
32360
  var init_native_firebase_config = __esm({
32305
32361
  "src/native-firebase-config.ts"() {
32306
32362
  "use strict";
32307
- import_node_fs18 = __toESM(require("node:fs"), 1);
32363
+ import_node_fs19 = __toESM(require("node:fs"), 1);
32308
32364
  import_node_module = require("node:module");
32309
- import_node_path19 = __toESM(require("node:path"), 1);
32365
+ import_node_path20 = __toESM(require("node:path"), 1);
32310
32366
  init_is_record();
32311
32367
  init_plist();
32312
32368
  }
@@ -32325,15 +32381,15 @@ function normalizeProfileId(input) {
32325
32381
  return id;
32326
32382
  }
32327
32383
  function profileIndexPath() {
32328
- return import_path5.default.join(profilesDir(), PROFILE_INDEX_FILE);
32384
+ return import_path4.default.join(profilesDir(), PROFILE_INDEX_FILE);
32329
32385
  }
32330
32386
  function playwrightProfileUserDataDir(profileId) {
32331
- return import_path5.default.join(profilesDir(), "playwright", normalizeProfileId(profileId));
32387
+ return import_path4.default.join(profilesDir(), "playwright", normalizeProfileId(profileId));
32332
32388
  }
32333
32389
  function readIndexRaw() {
32334
32390
  try {
32335
32391
  const parsed = JSON.parse(
32336
- import_fs6.default.readFileSync(profileIndexPath(), "utf8")
32392
+ import_fs5.default.readFileSync(profileIndexPath(), "utf8")
32337
32393
  );
32338
32394
  if (!parsed || parsed.version !== PROFILE_INDEX_VERSION) {
32339
32395
  return { version: PROFILE_INDEX_VERSION, profiles: [] };
@@ -32374,9 +32430,9 @@ function writeIndex(index) {
32374
32430
  ensureRnxHome();
32375
32431
  const next = withDefault(index);
32376
32432
  const tmp = `${profileIndexPath()}.tmp`;
32377
- import_fs6.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
32433
+ import_fs5.default.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}
32378
32434
  `, "utf8");
32379
- import_fs6.default.renameSync(tmp, profileIndexPath());
32435
+ import_fs5.default.renameSync(tmp, profileIndexPath());
32380
32436
  return next;
32381
32437
  }
32382
32438
  function listProfiles() {
@@ -32403,12 +32459,12 @@ function createProfile(id) {
32403
32459
  writeIndex({ version: PROFILE_INDEX_VERSION, profiles: [...index.profiles, profile] });
32404
32460
  return profile;
32405
32461
  }
32406
- var import_fs6, import_path5, DEFAULT_PROFILE_ID, PROFILE_INDEX_FILE, PROFILE_INDEX_VERSION;
32462
+ var import_fs5, import_path4, DEFAULT_PROFILE_ID, PROFILE_INDEX_FILE, PROFILE_INDEX_VERSION;
32407
32463
  var init_profiles = __esm({
32408
32464
  "src/profiles.ts"() {
32409
32465
  "use strict";
32410
- import_fs6 = __toESM(require("fs"), 1);
32411
- import_path5 = __toESM(require("path"), 1);
32466
+ import_fs5 = __toESM(require("fs"), 1);
32467
+ import_path4 = __toESM(require("path"), 1);
32412
32468
  init_home_paths();
32413
32469
  DEFAULT_PROFILE_ID = "default";
32414
32470
  PROFILE_INDEX_FILE = "profiles.json";
@@ -32518,59 +32574,59 @@ var init_bundleAssets = __esm({
32518
32574
  // cli/app-catalog.ts
32519
32575
  function listDir(dir) {
32520
32576
  try {
32521
- return import_node_fs19.default.readdirSync(dir, { withFileTypes: true });
32577
+ return import_node_fs20.default.readdirSync(dir, { withFileTypes: true });
32522
32578
  } catch {
32523
32579
  return [];
32524
32580
  }
32525
32581
  }
32526
32582
  function readText(file) {
32527
32583
  try {
32528
- return import_node_fs19.default.readFileSync(file, "utf8");
32584
+ return import_node_fs20.default.readFileSync(file, "utf8");
32529
32585
  } catch {
32530
32586
  return null;
32531
32587
  }
32532
32588
  }
32533
32589
  function catalogFiles(dir, found) {
32534
32590
  for (const entry of listDir(dir)) {
32535
- const full = import_node_path20.default.join(dir, entry.name);
32591
+ const full = import_node_path21.default.join(dir, entry.name);
32536
32592
  if (entry.isDirectory()) catalogFiles(full, found);
32537
32593
  else if (entry.name === "Contents.json") found.push(full);
32538
32594
  }
32539
32595
  }
32540
32596
  function discoverAppCatalog(appDir) {
32541
- const iosDir = import_node_path20.default.join(appDir, "ios");
32597
+ const iosDir = import_node_path21.default.join(appDir, "ios");
32542
32598
  const target = listDir(iosDir).find(
32543
- (entry) => entry.isDirectory() && entry.name !== "Pods" && listDir(import_node_path20.default.join(iosDir, entry.name)).some(
32599
+ (entry) => entry.isDirectory() && entry.name !== "Pods" && listDir(import_node_path21.default.join(iosDir, entry.name)).some(
32544
32600
  (file) => /^AppDelegate\.(swift|mm|m)$/.test(file.name)
32545
32601
  )
32546
32602
  );
32547
32603
  if (!target) return null;
32548
- const targetDir = import_node_path20.default.join(iosDir, target.name);
32604
+ const targetDir = import_node_path21.default.join(iosDir, target.name);
32549
32605
  const files = [];
32550
32606
  for (const entry of listDir(targetDir)) {
32551
32607
  if (entry.isDirectory() && entry.name.endsWith(".xcassets"))
32552
- catalogFiles(import_node_path20.default.join(targetDir, entry.name), files);
32608
+ catalogFiles(import_node_path21.default.join(targetDir, entry.name), files);
32553
32609
  }
32554
32610
  const relative2 = files.map(
32555
- (file) => import_node_path20.default.relative(targetDir, file).split(import_node_path20.default.sep).join(import_node_path20.default.posix.sep)
32611
+ (file) => import_node_path21.default.relative(targetDir, file).split(import_node_path21.default.sep).join(import_node_path21.default.posix.sep)
32556
32612
  );
32557
32613
  const colors = enumerateBundleColors(
32558
32614
  relative2,
32559
- (candidate) => candidate.endsWith("Contents.json") ? readText(import_node_path20.default.join(targetDir, candidate)) : null
32615
+ (candidate) => candidate.endsWith("Contents.json") ? readText(import_node_path21.default.join(targetDir, candidate)) : null
32560
32616
  );
32561
32617
  const pbxproj = listDir(iosDir).find((entry) => entry.name.endsWith(".xcodeproj"));
32562
- const accentName = readText(import_node_path20.default.join(targetDir, "Info.plist"))?.match(PLIST_ACCENT)?.[1] ?? (pbxproj ? readText(import_node_path20.default.join(iosDir, pbxproj.name, "project.pbxproj"))?.match(
32618
+ const accentName = readText(import_node_path21.default.join(targetDir, "Info.plist"))?.match(PLIST_ACCENT)?.[1] ?? (pbxproj ? readText(import_node_path21.default.join(iosDir, pbxproj.name, "project.pbxproj"))?.match(
32563
32619
  ACCENT_BUILD_SETTING
32564
32620
  )?.[1] : void 0) ?? null;
32565
32621
  if (accentName === null && Object.keys(colors).length === 0) return null;
32566
32622
  return { colors, accentName };
32567
32623
  }
32568
- var import_node_fs19, import_node_path20, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32624
+ var import_node_fs20, import_node_path21, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32569
32625
  var init_app_catalog = __esm({
32570
32626
  "cli/app-catalog.ts"() {
32571
32627
  "use strict";
32572
- import_node_fs19 = __toESM(require("node:fs"), 1);
32573
- import_node_path20 = __toESM(require("node:path"), 1);
32628
+ import_node_fs20 = __toESM(require("node:fs"), 1);
32629
+ import_node_path21 = __toESM(require("node:path"), 1);
32574
32630
  init_bundleAssets();
32575
32631
  ACCENT_BUILD_SETTING = /ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "?([^";]+)"?;/;
32576
32632
  PLIST_ACCENT = /<key>NSAccentColorName<\/key>\s*<string>([^<]+)<\/string>/;
@@ -32580,9 +32636,9 @@ var init_app_catalog = __esm({
32580
32636
  // cli/app-project.ts
32581
32637
  function firstNamedFile(dir, names) {
32582
32638
  for (const name2 of names) {
32583
- const candidate = import_node_path21.default.join(dir, name2);
32639
+ const candidate = import_node_path22.default.join(dir, name2);
32584
32640
  try {
32585
- if (import_node_fs20.default.statSync(candidate).isFile()) return candidate;
32641
+ if (import_node_fs21.default.statSync(candidate).isFile()) return candidate;
32586
32642
  } catch {
32587
32643
  }
32588
32644
  }
@@ -32595,24 +32651,24 @@ function findRNXAppConfig(dir) {
32595
32651
  return firstNamedFile(dir, RNX_APP_CONFIG_NAMES);
32596
32652
  }
32597
32653
  function resolveAppProject(projectRoot) {
32598
- const appDir = import_node_path21.default.resolve(projectRoot);
32654
+ const appDir = import_node_path22.default.resolve(projectRoot);
32599
32655
  try {
32600
- if (!import_node_fs20.default.statSync(appDir).isDirectory()) return null;
32656
+ if (!import_node_fs21.default.statSync(appDir).isDirectory()) return null;
32601
32657
  } catch {
32602
32658
  return null;
32603
32659
  }
32604
32660
  const configPath = findRNXAppConfig(appDir);
32605
- if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs20.default.existsSync(import_node_path21.default.join(appDir, "package.json"))) {
32661
+ if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs21.default.existsSync(import_node_path22.default.join(appDir, "package.json"))) {
32606
32662
  return null;
32607
32663
  }
32608
32664
  return { appDir, configPath };
32609
32665
  }
32610
- var import_node_fs20, import_node_path21, EXPO_APP_CONFIG_NAMES, RNX_APP_CONFIG_NAMES;
32666
+ var import_node_fs21, import_node_path22, EXPO_APP_CONFIG_NAMES, RNX_APP_CONFIG_NAMES;
32611
32667
  var init_app_project = __esm({
32612
32668
  "cli/app-project.ts"() {
32613
32669
  "use strict";
32614
- import_node_fs20 = __toESM(require("node:fs"), 1);
32615
- import_node_path21 = __toESM(require("node:path"), 1);
32670
+ import_node_fs21 = __toESM(require("node:fs"), 1);
32671
+ import_node_path22 = __toESM(require("node:path"), 1);
32616
32672
  EXPO_APP_CONFIG_NAMES = [
32617
32673
  "app.config.js",
32618
32674
  "app.config.ts",
@@ -32641,13 +32697,13 @@ function isRNXConfig(value) {
32641
32697
  }
32642
32698
  function resolveConfigReplacementFiles(config, configPath) {
32643
32699
  if (!config.modules) return config;
32644
- const configDir = import_node_path22.default.dirname(configPath);
32700
+ const configDir = import_node_path23.default.dirname(configPath);
32645
32701
  return {
32646
32702
  ...config,
32647
32703
  modules: Object.fromEntries(
32648
32704
  Object.entries(config.modules).map(([name2, resolution]) => [
32649
32705
  name2,
32650
- resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path22.default.resolve(configDir, resolution.file) } : resolution
32706
+ resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path23.default.resolve(configDir, resolution.file) } : resolution
32651
32707
  ])
32652
32708
  )
32653
32709
  };
@@ -32677,12 +32733,12 @@ async function resolveRNXAppConfig(startDir = process.cwd()) {
32677
32733
  const project = resolveAppProject(startDir);
32678
32734
  return { project, config: await loadRNXAppConfig(project) };
32679
32735
  }
32680
- var import_node_module2, import_node_path22, import_jiti, require2;
32736
+ var import_node_module2, import_node_path23, import_jiti, require2;
32681
32737
  var init_app_config = __esm({
32682
32738
  "cli/app-config.ts"() {
32683
32739
  "use strict";
32684
32740
  import_node_module2 = require("node:module");
32685
- import_node_path22 = __toESM(require("node:path"), 1);
32741
+ import_node_path23 = __toESM(require("node:path"), 1);
32686
32742
  init_src();
32687
32743
  import_jiti = require("jiti");
32688
32744
  init_public_brand();
@@ -32739,13 +32795,13 @@ function discoverNativeLinkedAppFonts(opts) {
32739
32795
  scannedFontDirectories++;
32740
32796
  let entries;
32741
32797
  try {
32742
- entries = import_node_fs21.default.readdirSync(current.dir, { withFileTypes: true });
32798
+ entries = import_node_fs22.default.readdirSync(current.dir, { withFileTypes: true });
32743
32799
  } catch {
32744
32800
  continue;
32745
32801
  }
32746
32802
  for (const entry of entries) {
32747
32803
  if (entry.isSymbolicLink()) continue;
32748
- const fullPath = import_node_path23.default.join(current.dir, entry.name);
32804
+ const fullPath = import_node_path24.default.join(current.dir, entry.name);
32749
32805
  if (entry.isDirectory()) {
32750
32806
  if (current.depth < 4 && pending.length < 64 && !entry.name.startsWith(".")) {
32751
32807
  pending.push({ dir: fullPath, depth: current.depth + 1 });
@@ -32753,15 +32809,15 @@ function discoverNativeLinkedAppFonts(opts) {
32753
32809
  continue;
32754
32810
  }
32755
32811
  if (!entry.isFile() || !/\.(ttf|otf|woff|woff2)$/i.test(entry.name)) continue;
32756
- const relative2 = import_node_path23.default.relative(root, fullPath).split(import_node_path23.default.sep).join("/");
32757
- fontPaths.push(import_node_path23.default.posix.join(metroPathPrefix, relative2));
32812
+ const relative2 = import_node_path24.default.relative(root, fullPath).split(import_node_path24.default.sep).join("/");
32813
+ fontPaths.push(import_node_path24.default.posix.join(metroPathPrefix, relative2));
32758
32814
  if (fontPaths.length >= 256) break;
32759
32815
  }
32760
32816
  }
32761
32817
  };
32762
32818
  try {
32763
32819
  const packageJson = JSON.parse(
32764
- import_node_fs21.default.readFileSync(import_node_path23.default.join(selectedAppDir, "package.json"), "utf8")
32820
+ import_node_fs22.default.readFileSync(import_node_path24.default.join(selectedAppDir, "package.json"), "utf8")
32765
32821
  );
32766
32822
  const dependencyNames = /* @__PURE__ */ new Set();
32767
32823
  for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
@@ -32776,25 +32832,34 @@ function discoverNativeLinkedAppFonts(opts) {
32776
32832
  const config = Reflect.get(packageJson, "reactNativeVectorIcons");
32777
32833
  const configuredFontDir = config && typeof config === "object" ? Reflect.get(config, "fontDir") : null;
32778
32834
  const configuredDir = typeof configuredFontDir === "string" ? configuredFontDir : "rnvi-fonts";
32779
- const root = import_node_path23.default.resolve(selectedAppDir, configuredDir);
32780
- const relativeRoot = import_node_path23.default.relative(selectedAppDir, root);
32781
- if (!relativeRoot.startsWith("..") && !import_node_path23.default.isAbsolute(relativeRoot)) {
32782
- collectFontFiles(root, relativeRoot.split(import_node_path23.default.sep).join("/"));
32783
- }
32784
- const vectorIconRequire = (0, import_node_module3.createRequire)(import_node_path23.default.join(selectedAppDir, "package.json"));
32835
+ const root = import_node_path24.default.resolve(selectedAppDir, configuredDir);
32836
+ const relativeRoot = import_node_path24.default.relative(selectedAppDir, root);
32837
+ if (!relativeRoot.startsWith("..") && !import_node_path24.default.isAbsolute(relativeRoot)) {
32838
+ collectFontFiles(root, relativeRoot.split(import_node_path24.default.sep).join("/"));
32839
+ }
32840
+ const bundleDir = import_node_path24.default.posix.dirname(new URL(opts.bundleUrl).pathname).replace(/^\/+/, "");
32841
+ const appRelativeDir = bundleDir.split("/").join(import_node_path24.default.sep);
32842
+ const metroRootCandidates = [selectedAppDir];
32843
+ if (bundleDir && selectedAppDir.endsWith(import_node_path24.default.sep + appRelativeDir)) {
32844
+ metroRootCandidates.push(selectedAppDir.slice(0, -appRelativeDir.length - 1));
32845
+ }
32846
+ const vectorIconRequire = (0, import_node_module3.createRequire)(import_node_path24.default.join(selectedAppDir, "package.json"));
32785
32847
  for (const dependencyName of vectorIconDependencies) {
32786
32848
  try {
32787
32849
  const entryPath = vectorIconRequire.resolve(dependencyName);
32788
- const dependencyPath = dependencyName.split("/").join(import_node_path23.default.sep);
32789
- const marker = `${import_node_path23.default.sep}node_modules${import_node_path23.default.sep}${dependencyPath}${import_node_path23.default.sep}`;
32850
+ const dependencyPath = dependencyName.split("/").join(import_node_path24.default.sep);
32851
+ const marker = `${import_node_path24.default.sep}node_modules${import_node_path24.default.sep}${dependencyPath}${import_node_path24.default.sep}`;
32790
32852
  const markerIndex = entryPath.lastIndexOf(marker);
32791
32853
  if (markerIndex === -1) continue;
32792
32854
  const packageRoot = entryPath.slice(0, markerIndex + marker.length - 1);
32793
32855
  const fontsDir = dependencyName === "react-native-vector-icons" ? "Fonts" : "fonts";
32794
- collectFontFiles(
32795
- import_node_path23.default.join(packageRoot, fontsDir),
32796
- import_node_path23.default.posix.join("node_modules", dependencyName, fontsDir)
32797
- );
32856
+ const fontsRoot = import_node_path24.default.join(packageRoot, fontsDir);
32857
+ for (const metroRoot of metroRootCandidates) {
32858
+ collectFontFiles(
32859
+ fontsRoot,
32860
+ import_node_path24.default.relative(metroRoot, fontsRoot).split(import_node_path24.default.sep).join("/")
32861
+ );
32862
+ }
32798
32863
  } catch {
32799
32864
  }
32800
32865
  }
@@ -32802,37 +32867,37 @@ function discoverNativeLinkedAppFonts(opts) {
32802
32867
  } catch {
32803
32868
  }
32804
32869
  try {
32805
- const configPath = import_node_path23.default.join(selectedAppDir, "react-native.config.js");
32806
- if (import_node_fs21.default.statSync(configPath).isFile()) {
32807
- const appConfigRequire = (0, import_node_module3.createRequire)(import_node_path23.default.join(selectedAppDir, "package.json"));
32870
+ const configPath = import_node_path24.default.join(selectedAppDir, "react-native.config.js");
32871
+ if (import_node_fs22.default.statSync(configPath).isFile()) {
32872
+ const appConfigRequire = (0, import_node_module3.createRequire)(import_node_path24.default.join(selectedAppDir, "package.json"));
32808
32873
  const rnConfig = appConfigRequire(configPath);
32809
32874
  const assets = rnConfig && typeof rnConfig === "object" ? Reflect.get(rnConfig, "assets") : null;
32810
32875
  if (Array.isArray(assets)) {
32811
32876
  for (const assetDir of assets) {
32812
32877
  if (typeof assetDir !== "string") continue;
32813
- const root = import_node_path23.default.resolve(selectedAppDir, assetDir);
32814
- const relativeRoot = import_node_path23.default.relative(selectedAppDir, root);
32815
- if (relativeRoot.startsWith("..") || import_node_path23.default.isAbsolute(relativeRoot)) continue;
32816
- collectFontFiles(root, relativeRoot.split(import_node_path23.default.sep).join("/"));
32878
+ const root = import_node_path24.default.resolve(selectedAppDir, assetDir);
32879
+ const relativeRoot = import_node_path24.default.relative(selectedAppDir, root);
32880
+ if (relativeRoot.startsWith("..") || import_node_path24.default.isAbsolute(relativeRoot)) continue;
32881
+ collectFontFiles(root, relativeRoot.split(import_node_path24.default.sep).join("/"));
32817
32882
  }
32818
32883
  }
32819
32884
  }
32820
32885
  } catch {
32821
32886
  }
32822
32887
  if (platform === "ios") {
32823
- const iosDir = import_node_path23.default.join(selectedAppDir, "ios");
32888
+ const iosDir = import_node_path24.default.join(selectedAppDir, "ios");
32824
32889
  try {
32825
- const targetDirs = import_node_fs21.default.readdirSync(iosDir, { withFileTypes: true }).filter(
32890
+ const targetDirs = import_node_fs22.default.readdirSync(iosDir, { withFileTypes: true }).filter(
32826
32891
  (entry) => entry.isDirectory() && !entry.isSymbolicLink() && entry.name !== "Pods" && entry.name !== "build" && !entry.name.startsWith(".")
32827
32892
  ).slice(0, 64);
32828
- const plistPaths = [import_node_path23.default.join(iosDir, "Info.plist")];
32893
+ const plistPaths = [import_node_path24.default.join(iosDir, "Info.plist")];
32829
32894
  for (const entry of targetDirs) {
32830
- plistPaths.push(import_node_path23.default.join(iosDir, entry.name, "Info.plist"));
32895
+ plistPaths.push(import_node_path24.default.join(iosDir, entry.name, "Info.plist"));
32831
32896
  }
32832
32897
  for (const plistPath of plistPaths) {
32833
32898
  let parsed;
32834
32899
  try {
32835
- parsed = parsePlistSource(import_node_fs21.default.readFileSync(plistPath, "utf8"));
32900
+ parsed = parsePlistSource(import_node_fs22.default.readFileSync(plistPath, "utf8"));
32836
32901
  } catch {
32837
32902
  continue;
32838
32903
  }
@@ -32842,21 +32907,21 @@ function discoverNativeLinkedAppFonts(opts) {
32842
32907
  for (const declaredFont of declaredFonts) {
32843
32908
  if (typeof declaredFont !== "string") continue;
32844
32909
  const candidates = [
32845
- import_node_path23.default.resolve(import_node_path23.default.dirname(plistPath), declaredFont),
32846
- import_node_path23.default.resolve(iosDir, declaredFont)
32910
+ import_node_path24.default.resolve(import_node_path24.default.dirname(plistPath), declaredFont),
32911
+ import_node_path24.default.resolve(iosDir, declaredFont)
32847
32912
  ];
32848
32913
  const fontPath = candidates.find((candidate) => {
32849
- const relative2 = import_node_path23.default.relative(selectedAppDir, candidate);
32850
- if (relative2.startsWith("..") || import_node_path23.default.isAbsolute(relative2)) return false;
32914
+ const relative2 = import_node_path24.default.relative(selectedAppDir, candidate);
32915
+ if (relative2.startsWith("..") || import_node_path24.default.isAbsolute(relative2)) return false;
32851
32916
  try {
32852
- return import_node_fs21.default.statSync(candidate).isFile();
32917
+ return import_node_fs22.default.statSync(candidate).isFile();
32853
32918
  } catch {
32854
32919
  return false;
32855
32920
  }
32856
32921
  });
32857
32922
  if (!fontPath) continue;
32858
32923
  fontPaths.push(
32859
- import_node_path23.default.relative(selectedAppDir, fontPath).split(import_node_path23.default.sep).join("/")
32924
+ import_node_path24.default.relative(selectedAppDir, fontPath).split(import_node_path24.default.sep).join("/")
32860
32925
  );
32861
32926
  }
32862
32927
  }
@@ -32895,13 +32960,13 @@ async function resolveMetroProjectRoot(bundleUrl, opts) {
32895
32960
  function encodeAppFontsWire(specs) {
32896
32961
  return specs.map((spec) => `${encodeURIComponent(spec.url)}::${encodeURIComponent(spec.family)}`).join(",");
32897
32962
  }
32898
- var import_node_fs21, import_node_module3, import_node_path23, import_config_plugin_fonts, require3;
32963
+ var import_node_fs22, import_node_module3, import_node_path24, import_config_plugin_fonts, require3;
32899
32964
  var init_app_fonts = __esm({
32900
32965
  "cli/app-fonts.ts"() {
32901
32966
  "use strict";
32902
- import_node_fs21 = __toESM(require("node:fs"), 1);
32967
+ import_node_fs22 = __toESM(require("node:fs"), 1);
32903
32968
  import_node_module3 = require("node:module");
32904
- import_node_path23 = __toESM(require("node:path"), 1);
32969
+ import_node_path24 = __toESM(require("node:path"), 1);
32905
32970
  import_config_plugin_fonts = require("peach-engine/engine/config-plugin-fonts");
32906
32971
  init_dev_server_scanner();
32907
32972
  init_backend_origin();
@@ -33760,7 +33825,7 @@ var init_bridge_diagnostics = __esm({
33760
33825
  function getSootsimRoot() {
33761
33826
  if (_sootsimRoot !== void 0) return _sootsimRoot;
33762
33827
  try {
33763
- _sootsimRoot = (0, import_path6.dirname)(
33828
+ _sootsimRoot = (0, import_path5.dirname)(
33764
33829
  (0, import_url2.fileURLToPath)(import_meta2.resolve("peach-engine/package.json"))
33765
33830
  );
33766
33831
  } catch {
@@ -33771,8 +33836,8 @@ function getSootsimRoot() {
33771
33836
  function findDevElectron() {
33772
33837
  const engineDir = getSootsimRoot();
33773
33838
  if (!engineDir) return null;
33774
- const engineMain = (0, import_path6.join)(engineDir, "dist-electron/main.cjs");
33775
- if (!(0, import_fs7.existsSync)(engineMain)) return null;
33839
+ const engineMain = (0, import_path5.join)(engineDir, "dist-electron/main.cjs");
33840
+ if (!(0, import_fs6.existsSync)(engineMain)) return null;
33776
33841
  const electronBin = findElectronBin(engineDir);
33777
33842
  if (!electronBin) return null;
33778
33843
  return {
@@ -33785,14 +33850,14 @@ function findDevElectron() {
33785
33850
  function isInRepoCheckout() {
33786
33851
  const root = getSootsimRoot();
33787
33852
  if (!root) return false;
33788
- return (0, import_fs7.existsSync)((0, import_path6.join)(root, "src-electron/main.ts"));
33853
+ return (0, import_fs6.existsSync)((0, import_path5.join)(root, "src-electron/main.ts"));
33789
33854
  }
33790
33855
  function findElectronBin(startDir) {
33791
33856
  let dir = startDir;
33792
33857
  for (let i = 0; i < 6; i++) {
33793
- const candidate = (0, import_path6.join)(dir, "node_modules/.bin/electron");
33794
- if ((0, import_fs7.existsSync)(candidate)) return candidate;
33795
- const parent = (0, import_path6.dirname)(dir);
33858
+ const candidate = (0, import_path5.join)(dir, "node_modules/.bin/electron");
33859
+ if ((0, import_fs6.existsSync)(candidate)) return candidate;
33860
+ const parent = (0, import_path5.dirname)(dir);
33796
33861
  if (parent === dir) break;
33797
33862
  dir = parent;
33798
33863
  }
@@ -33801,9 +33866,9 @@ function findElectronBin(startDir) {
33801
33866
  function findInstalledMacApp() {
33802
33867
  const candidates = [
33803
33868
  "/Applications/peach.app",
33804
- (0, import_path6.resolve)(process.env.HOME || "", "Applications/peach.app")
33869
+ (0, import_path5.resolve)(process.env.HOME || "", "Applications/peach.app")
33805
33870
  ];
33806
- const found = candidates.find((candidate) => (0, import_fs7.existsSync)(candidate));
33871
+ const found = candidates.find((candidate) => (0, import_fs6.existsSync)(candidate));
33807
33872
  if (found) {
33808
33873
  return {
33809
33874
  path: found,
@@ -33817,8 +33882,8 @@ function findMacApp() {
33817
33882
  const installed2 = findInstalledMacApp();
33818
33883
  if (installed2) return installed2;
33819
33884
  const root = getSootsimRoot();
33820
- const builtApp = root ? (0, import_path6.resolve)(root, "app/peach.app") : null;
33821
- if (builtApp && (0, import_fs7.existsSync)(builtApp)) {
33885
+ const builtApp = root ? (0, import_path5.resolve)(root, "app/peach.app") : null;
33886
+ if (builtApp && (0, import_fs6.existsSync)(builtApp)) {
33822
33887
  return { path: builtApp, platform: "darwin", kind: "mac-app" };
33823
33888
  }
33824
33889
  try {
@@ -33839,18 +33904,18 @@ function findMacApp() {
33839
33904
  return null;
33840
33905
  }
33841
33906
  function findFirstAppImage(dir) {
33842
- if (!(0, import_fs7.existsSync)(dir)) return null;
33843
- const match = (0, import_fs7.readdirSync)(dir).filter((entry) => entry.startsWith("peach") && entry.endsWith(".AppImage")).sort().reverse()[0];
33844
- return match ? (0, import_path6.join)(dir, match) : null;
33907
+ if (!(0, import_fs6.existsSync)(dir)) return null;
33908
+ const match = (0, import_fs6.readdirSync)(dir).filter((entry) => entry.startsWith("peach") && entry.endsWith(".AppImage")).sort().reverse()[0];
33909
+ return match ? (0, import_path5.join)(dir, match) : null;
33845
33910
  }
33846
33911
  function findInstalledLinuxApp() {
33847
33912
  const directCandidates = [
33848
- (0, import_path6.resolve)(process.env.HOME || "", "Applications/peach.AppImage"),
33849
- (0, import_path6.resolve)(process.env.HOME || "", ".local/bin/peach.AppImage"),
33913
+ (0, import_path5.resolve)(process.env.HOME || "", "Applications/peach.AppImage"),
33914
+ (0, import_path5.resolve)(process.env.HOME || "", ".local/bin/peach.AppImage"),
33850
33915
  "/opt/peach/peach.AppImage",
33851
33916
  "/opt/peach/peach"
33852
33917
  ];
33853
- const directMatch = directCandidates.find((candidate) => (0, import_fs7.existsSync)(candidate));
33918
+ const directMatch = directCandidates.find((candidate) => (0, import_fs6.existsSync)(candidate));
33854
33919
  if (directMatch) {
33855
33920
  return {
33856
33921
  path: directMatch,
@@ -33864,8 +33929,8 @@ function findLinuxInstall() {
33864
33929
  const installed2 = findInstalledLinuxApp();
33865
33930
  if (installed2) return installed2;
33866
33931
  const root = getSootsimRoot();
33867
- const directCandidates = root ? [(0, import_path6.resolve)(root, "app/peach.AppImage"), (0, import_path6.resolve)(root, "release/linux-unpacked/peach")] : [];
33868
- const directMatch = directCandidates.find((candidate) => (0, import_fs7.existsSync)(candidate));
33932
+ const directCandidates = root ? [(0, import_path5.resolve)(root, "app/peach.AppImage"), (0, import_path5.resolve)(root, "release/linux-unpacked/peach")] : [];
33933
+ const directMatch = directCandidates.find((candidate) => (0, import_fs6.existsSync)(candidate));
33869
33934
  if (directMatch) {
33870
33935
  return {
33871
33936
  path: directMatch,
@@ -33873,7 +33938,7 @@ function findLinuxInstall() {
33873
33938
  kind: directMatch.endsWith(".AppImage") ? "linux-appimage" : "linux-binary"
33874
33939
  };
33875
33940
  }
33876
- const scannedMatch = root ? findFirstAppImage((0, import_path6.resolve)(root, "app")) || findFirstAppImage((0, import_path6.resolve)(root, "release")) : null;
33941
+ const scannedMatch = root ? findFirstAppImage((0, import_path5.resolve)(root, "app")) || findFirstAppImage((0, import_path5.resolve)(root, "release")) : null;
33877
33942
  if (!scannedMatch) return null;
33878
33943
  return {
33879
33944
  path: scannedMatch,
@@ -33890,7 +33955,7 @@ function findWindowsInstall() {
33890
33955
  { encoding: "utf8", timeout: 3e3 }
33891
33956
  );
33892
33957
  const executable = /"([^"\r\n]+\.exe)"/i.exec(output)?.[1];
33893
- if (executable && (0, import_fs7.existsSync)(executable)) {
33958
+ if (executable && (0, import_fs6.existsSync)(executable)) {
33894
33959
  return { path: executable, platform: "win32", kind: "win-exe" };
33895
33960
  }
33896
33961
  } catch {
@@ -33903,8 +33968,8 @@ function findDesktopCompanion() {
33903
33968
  if (dev) return dev;
33904
33969
  if (isInRepoCheckout()) {
33905
33970
  const engineDir = getSootsimRoot();
33906
- const engineMain = (0, import_path6.join)(engineDir, "dist-electron/main.cjs");
33907
- if (!(0, import_fs7.existsSync)(engineMain)) {
33971
+ const engineMain = (0, import_path5.join)(engineDir, "dist-electron/main.cjs");
33972
+ if (!(0, import_fs6.existsSync)(engineMain)) {
33908
33973
  console.error(
33909
33974
  ` dist-electron/main.cjs missing in ${engineDir}.
33910
33975
  run: bun run --cwd packages/peach-engine build:electron-main
@@ -33975,13 +34040,13 @@ function buildMacLaunchUrl(url, opts) {
33975
34040
  }
33976
34041
  return deepLink.toString();
33977
34042
  }
33978
- var import_child_process5, import_fs7, import_path6, import_url2, import_meta2, _sootsimRoot, PEACH_BUNDLE_ID;
34043
+ var import_child_process5, import_fs6, import_path5, import_url2, import_meta2, _sootsimRoot, PEACH_BUNDLE_ID;
33979
34044
  var init_desktop_companion = __esm({
33980
34045
  "cli/desktop-companion.ts"() {
33981
34046
  "use strict";
33982
34047
  import_child_process5 = require("child_process");
33983
- import_fs7 = require("fs");
33984
- import_path6 = require("path");
34048
+ import_fs6 = require("fs");
34049
+ import_path5 = require("path");
33985
34050
  import_url2 = require("url");
33986
34051
  import_meta2 = {};
33987
34052
  PEACH_BUNDLE_ID = "dev.peachsim.simulator";
@@ -34077,11 +34142,24 @@ var init_internal_child = __esm({
34077
34142
  }
34078
34143
  });
34079
34144
 
34145
+ // cli/drivers/playwright-core-pin.ts
34146
+ var PINNED_PLAYWRIGHT_CORE;
34147
+ var init_playwright_core_pin = __esm({
34148
+ "cli/drivers/playwright-core-pin.ts"() {
34149
+ "use strict";
34150
+ PINNED_PLAYWRIGHT_CORE = {
34151
+ version: "1.61.0",
34152
+ integrity: "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA=="
34153
+ };
34154
+ }
34155
+ });
34156
+
34080
34157
  // cli/drivers/playwright-provisioning.ts
34081
34158
  function resolvePlaywright() {
34082
34159
  const roots = [`${process.cwd()}/`];
34083
34160
  const self = rnxSelfInvocation();
34084
34161
  roots.push(self.prefixArgs[0] ?? self.executable);
34162
+ roots.push(`${playwrightCoreDir(PINNED_PLAYWRIGHT_CORE.version)}/`);
34085
34163
  for (const root of roots) {
34086
34164
  try {
34087
34165
  const requireFromRoot = (0, import_node_module5.createRequire)(root);
@@ -34089,7 +34167,7 @@ function resolvePlaywright() {
34089
34167
  try {
34090
34168
  const modulePath = requireFromRoot.resolve(spec);
34091
34169
  const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
34092
- const parsed = JSON.parse((0, import_node_fs22.readFileSync)(packageJsonPath, "utf8"));
34170
+ const parsed = JSON.parse((0, import_node_fs23.readFileSync)(packageJsonPath, "utf8"));
34093
34171
  if (!isRecord(parsed) || typeof parsed.version !== "string") continue;
34094
34172
  const bin = parsed.bin;
34095
34173
  let binPath = null;
@@ -34101,8 +34179,8 @@ function resolvePlaywright() {
34101
34179
  binPath = typeof named === "string" ? named : typeof first === "string" ? first : null;
34102
34180
  }
34103
34181
  if (!binPath) continue;
34104
- const cliPath = (0, import_node_path24.join)((0, import_node_path24.dirname)(packageJsonPath), binPath);
34105
- if (!(0, import_node_fs22.existsSync)(cliPath)) continue;
34182
+ const cliPath = (0, import_node_path25.join)((0, import_node_path25.dirname)(packageJsonPath), binPath);
34183
+ if (!(0, import_node_fs23.existsSync)(cliPath)) continue;
34106
34184
  return {
34107
34185
  spec,
34108
34186
  modulePath,
@@ -34117,6 +34195,33 @@ function resolvePlaywright() {
34117
34195
  }
34118
34196
  return null;
34119
34197
  }
34198
+ async function provisionPlaywright() {
34199
+ const existing = resolvePlaywright();
34200
+ if (existing) return existing;
34201
+ const { version, integrity } = PINNED_PLAYWRIGHT_CORE;
34202
+ const [algorithm, digest] = integrity.split("-", 2);
34203
+ if (algorithm !== "sha512" || !digest) {
34204
+ throw new Error(`pinned playwright-core integrity is not sha512: ${integrity}`);
34205
+ }
34206
+ process.stderr.write(`peach: installing playwright-core ${version}\u2026
34207
+ `);
34208
+ await installVerifiedTarball({
34209
+ url: `https://registry.npmjs.org/playwright-core/-/playwright-core-${version}.tgz`,
34210
+ digest: { algorithm, encoding: "base64", value: digest },
34211
+ destDir: (0, import_node_path25.join)(playwrightCoreDir(version), "node_modules", "playwright-core"),
34212
+ installedMarker: "package.json",
34213
+ // npm tarballs hold the package under a leading `package/`
34214
+ stripComponents: 1,
34215
+ label: `playwright-core ${version}`
34216
+ });
34217
+ const installed2 = resolvePlaywright();
34218
+ if (!installed2) {
34219
+ throw new Error(
34220
+ `playwright-core ${version} installed to ${playwrightCoreDir(version)} but does not resolve`
34221
+ );
34222
+ }
34223
+ return installed2;
34224
+ }
34120
34225
  function probeBrowser(resolved, env) {
34121
34226
  const self = rnxSelfInvocation();
34122
34227
  const probe3 = (0, import_node_child_process6.spawnSync)(
@@ -34146,7 +34251,7 @@ function probeBrowser(resolved, env) {
34146
34251
  return {
34147
34252
  ok: true,
34148
34253
  executablePath: parsed.executablePath,
34149
- exists: parsed.exists && (0, import_node_fs22.existsSync)(parsed.executablePath)
34254
+ exists: parsed.exists && (0, import_node_fs23.existsSync)(parsed.executablePath)
34150
34255
  };
34151
34256
  } catch (error) {
34152
34257
  return {
@@ -34197,33 +34302,30 @@ ${detail}` : ""}`
34197
34302
  }
34198
34303
  return { ok: true, executablePath: after.executablePath, installed: true };
34199
34304
  }
34200
- var import_node_child_process6, import_node_fs22, import_node_module5, import_node_path24;
34305
+ var import_node_child_process6, import_node_fs23, import_node_module5, import_node_path25;
34201
34306
  var init_playwright_provisioning = __esm({
34202
34307
  "cli/drivers/playwright-provisioning.ts"() {
34203
34308
  "use strict";
34204
34309
  import_node_child_process6 = require("node:child_process");
34205
- import_node_fs22 = require("node:fs");
34310
+ import_node_fs23 = require("node:fs");
34206
34311
  import_node_module5 = require("node:module");
34207
- import_node_path24 = require("node:path");
34312
+ import_node_path25 = require("node:path");
34313
+ init_src();
34314
+ init_home_paths();
34208
34315
  init_is_record();
34209
34316
  init_internal_child();
34210
34317
  init_self_invocation();
34318
+ init_playwright_core_pin();
34211
34319
  }
34212
34320
  });
34213
34321
 
34214
34322
  // cli/drivers/playwright.ts
34215
34323
  function probe2() {
34216
34324
  const resolved = resolvePlaywright();
34217
- if (!resolved) {
34218
- return {
34219
- available: false,
34220
- reason: "playwright not installed in the current workspace"
34221
- };
34222
- }
34223
34325
  return {
34224
34326
  available: true,
34225
34327
  reason: null,
34226
- detail: `resolved via ${resolved.spec}@${resolved.version}`
34328
+ detail: resolved ? `resolved via ${resolved.spec}@${resolved.version}` : `installs playwright-core@${PINNED_PLAYWRIGHT_CORE.version} on first launch`
34227
34329
  };
34228
34330
  }
34229
34331
  function headlessHintForLinuxFailure(opts, detail) {
@@ -34240,18 +34342,11 @@ function resolveUserDataDir(opts) {
34240
34342
  return playwrightProfileUserDataDir(ensureProfile(opts.profileId).id);
34241
34343
  }
34242
34344
  if (opts.ephemeralProfile) {
34243
- return (0, import_fs8.mkdtempSync)((0, import_path7.join)((0, import_os2.tmpdir)(), "peach-playwright-profile-"));
34345
+ return (0, import_fs7.mkdtempSync)((0, import_path6.join)((0, import_os2.tmpdir)(), "peach-playwright-profile-"));
34244
34346
  }
34245
34347
  return "";
34246
34348
  }
34247
34349
  async function launch2(opts) {
34248
- const resolved = resolvePlaywright();
34249
- if (!resolved) {
34250
- return {
34251
- launched: false,
34252
- message: "playwright not installed \u2014 run `bun add -D playwright` first"
34253
- };
34254
- }
34255
34350
  if (!opts.url) {
34256
34351
  return { launched: false, message: "playwright driver requires a target url" };
34257
34352
  }
@@ -34262,6 +34357,15 @@ async function launch2(opts) {
34262
34357
  message: "playwright driver requires a valid owning session process"
34263
34358
  };
34264
34359
  }
34360
+ let resolved;
34361
+ try {
34362
+ resolved = await provisionPlaywright();
34363
+ } catch (error) {
34364
+ return {
34365
+ launched: false,
34366
+ message: `playwright provisioning failed: ${error instanceof Error ? error.message : String(error)}`
34367
+ };
34368
+ }
34265
34369
  const playwrightEnv = { ...process.env };
34266
34370
  const provisioning = ensurePlaywrightBrowser(resolved, playwrightEnv);
34267
34371
  if (!provisioning.ok) {
@@ -34270,9 +34374,9 @@ async function launch2(opts) {
34270
34374
  message: `playwright browser provisioning failed: ${provisioning.message}`
34271
34375
  };
34272
34376
  }
34273
- const errLog = (0, import_path7.join)((0, import_os2.tmpdir)(), playwrightHostLogName(Date.now(), process.pid));
34377
+ const errLog = (0, import_path6.join)((0, import_os2.tmpdir)(), playwrightHostLogName(Date.now(), process.pid));
34274
34378
  const connectAckFile = `${errLog}.connected`;
34275
- const errFd = (0, import_fs8.openSync)(errLog, "a");
34379
+ const errFd = (0, import_fs7.openSync)(errLog, "a");
34276
34380
  try {
34277
34381
  const self = rnxSelfInvocation();
34278
34382
  const child = (0, import_child_process6.spawn)(
@@ -34308,7 +34412,7 @@ async function launch2(opts) {
34308
34412
  });
34309
34413
  });
34310
34414
  if (earlyExit !== null) {
34311
- const detail = (0, import_fs8.readFileSync)(errLog, "utf8").trim();
34415
+ const detail = (0, import_fs7.readFileSync)(errLog, "utf8").trim();
34312
34416
  const hint = headlessHintForLinuxFailure(opts, detail);
34313
34417
  return {
34314
34418
  launched: false,
@@ -34335,23 +34439,24 @@ ${hint}` : ""}`
34335
34439
  message: `playwright launch failed: ${err instanceof Error ? err.message : String(err)}`
34336
34440
  };
34337
34441
  } finally {
34338
- (0, import_fs8.closeSync)(errFd);
34442
+ (0, import_fs7.closeSync)(errFd);
34339
34443
  }
34340
34444
  }
34341
- var import_child_process6, import_fs8, import_os2, import_path7, playwrightDriver;
34445
+ var import_child_process6, import_fs7, import_os2, import_path6, playwrightDriver;
34342
34446
  var init_playwright = __esm({
34343
34447
  "cli/drivers/playwright.ts"() {
34344
34448
  "use strict";
34345
34449
  import_child_process6 = require("child_process");
34346
- import_fs8 = require("fs");
34450
+ import_fs7 = require("fs");
34347
34451
  import_os2 = require("os");
34348
- import_path7 = require("path");
34452
+ import_path6 = require("path");
34349
34453
  init_bridge_constants();
34350
34454
  init_playwright_host_log();
34351
34455
  init_profiles();
34352
34456
  init_internal_child();
34353
34457
  init_parent_pid();
34354
34458
  init_self_invocation();
34459
+ init_playwright_core_pin();
34355
34460
  init_playwright_provisioning();
34356
34461
  playwrightDriver = {
34357
34462
  id: "playwright",
@@ -34412,6 +34517,264 @@ var init_env = __esm({
34412
34517
  }
34413
34518
  });
34414
34519
 
34520
+ // cli/ui.ts
34521
+ var init_ui = __esm({
34522
+ "cli/ui.ts"() {
34523
+ "use strict";
34524
+ }
34525
+ });
34526
+
34527
+ // cli/prompt.ts
34528
+ var init_prompt = __esm({
34529
+ "cli/prompt.ts"() {
34530
+ "use strict";
34531
+ init_ui();
34532
+ }
34533
+ });
34534
+
34535
+ // cli/privacy.ts
34536
+ function diagnosticsAllowedForCurrentProcess(preferences = readPrivacyPreferences()) {
34537
+ const doNotTrack = process.env.DO_NOT_TRACK;
34538
+ if (doNotTrack === "1" || doNotTrack === "true") return false;
34539
+ return preferences.configured && preferences.productAnalytics;
34540
+ }
34541
+ var init_privacy = __esm({
34542
+ "cli/privacy.ts"() {
34543
+ "use strict";
34544
+ init_home_paths();
34545
+ init_env();
34546
+ init_prompt();
34547
+ }
34548
+ });
34549
+
34550
+ // cli/command-registry.ts
34551
+ var NODE_COMMAND_NAMES, BROWSER_FAMILIES, registrations, RNX_COMMAND_NAMES, RNX_NODE_COMMAND_NAMES;
34552
+ var init_command_registry = __esm({
34553
+ "cli/command-registry.ts"() {
34554
+ "use strict";
34555
+ NODE_COMMAND_NAMES = [
34556
+ "test",
34557
+ "detox",
34558
+ "maestro",
34559
+ "record",
34560
+ "film",
34561
+ "storage",
34562
+ "permissions",
34563
+ "perf",
34564
+ "screenshot",
34565
+ "state",
34566
+ "reset",
34567
+ "camera",
34568
+ "mode",
34569
+ "debug",
34570
+ "timeline",
34571
+ "what-happened",
34572
+ "shell",
34573
+ "assert",
34574
+ "device",
34575
+ "open",
34576
+ "ios",
34577
+ "android",
34578
+ "remote",
34579
+ "preview",
34580
+ "box",
34581
+ "list",
34582
+ "use",
34583
+ "claim",
34584
+ "close",
34585
+ "compat",
34586
+ "project-report",
34587
+ "report-issue",
34588
+ "desktop",
34589
+ "login",
34590
+ "logout",
34591
+ "auth",
34592
+ "cli",
34593
+ "setup",
34594
+ "serve",
34595
+ "daemon",
34596
+ "runtime",
34597
+ "upgrade",
34598
+ "version",
34599
+ "skill",
34600
+ "config",
34601
+ "cleanup",
34602
+ "app-fonts",
34603
+ "agent-wrapper",
34604
+ "agent",
34605
+ "describe",
34606
+ "find",
34607
+ "get",
34608
+ "do",
34609
+ "wait",
34610
+ "network",
34611
+ "logs"
34612
+ ];
34613
+ BROWSER_FAMILIES = /* @__PURE__ */ new Map([
34614
+ ["web", "preview"],
34615
+ ["ios", "preview"],
34616
+ ["android", "preview"],
34617
+ ["list", "runtime"],
34618
+ ["use", "runtime"],
34619
+ ["state", "runtime"],
34620
+ ["describe", "tree"],
34621
+ ["find", "find"],
34622
+ ["get", "runtime"],
34623
+ ["wait", "wait"],
34624
+ ["do", "action"],
34625
+ ["shell", "action"],
34626
+ ["reset", "action"],
34627
+ ["screenshot", "screenshot"],
34628
+ ["logs", "logs"],
34629
+ ["network", "network"],
34630
+ ["storage", "storage"],
34631
+ ["timeline", "history"],
34632
+ ["what-happened", "history"],
34633
+ ["assert", "evidence"],
34634
+ ["debug", "evidence"],
34635
+ ["perf", "evidence"]
34636
+ ]);
34637
+ registrations = [
34638
+ .../* @__PURE__ */ new Set([...NODE_COMMAND_NAMES, "web"])
34639
+ ].map((name2) => ({
34640
+ name: name2,
34641
+ node: name2 !== "web",
34642
+ browserFamily: BROWSER_FAMILIES.get(name2) ?? null
34643
+ }));
34644
+ RNX_COMMAND_NAMES = new Set(registrations.map((entry) => entry.name));
34645
+ RNX_NODE_COMMAND_NAMES = new Set(NODE_COMMAND_NAMES);
34646
+ }
34647
+ });
34648
+
34649
+ // cli/parse-args.ts
34650
+ var GLOBAL_FLAGS, GLOBAL_FLAG_TAKES_VALUE, COMMANDS;
34651
+ var init_parse_args = __esm({
34652
+ "cli/parse-args.ts"() {
34653
+ "use strict";
34654
+ init_command_registry();
34655
+ GLOBAL_FLAGS = {
34656
+ "--help": { type: "boolean", short: "-h" },
34657
+ "--version": { type: "boolean", short: "-V" },
34658
+ "--verbose": { type: "boolean", short: "-v" },
34659
+ "--port": { type: "number", short: "-p" },
34660
+ "--device": { type: "string", short: "-d" },
34661
+ "--theme": { type: "string", short: "-t" },
34662
+ "--headless": { type: "boolean" },
34663
+ "--driver": { type: "string" },
34664
+ "--sim": { type: "string" },
34665
+ // documented aliases for --sim (CLAUDE.md / skills / engine docs say
34666
+ // `--session <id>`). normalized to the sim target in bin.ts.
34667
+ "--session": { type: "string" },
34668
+ "--tab": { type: "string" }
34669
+ };
34670
+ GLOBAL_FLAG_TAKES_VALUE = new Map(
34671
+ Object.entries(GLOBAL_FLAGS).flatMap(([name2, def]) => {
34672
+ const takesValue = def.type !== "boolean";
34673
+ return def.short ? [
34674
+ [name2, takesValue],
34675
+ [def.short, takesValue]
34676
+ ] : [[name2, takesValue]];
34677
+ })
34678
+ );
34679
+ COMMANDS = new Set(RNX_NODE_COMMAND_NAMES);
34680
+ }
34681
+ });
34682
+
34683
+ // cli/telemetry.ts
34684
+ function sanitizeDiagnosticMessage(value) {
34685
+ const firstLine = value.slice(0, 2048).split(/[\r\n\u2028\u2029]/, 1)[0] ?? "";
34686
+ return firstLine.split((0, import_node_os3.homedir)()).join("<home>").replace(
34687
+ /<package:(?:@[\w.-]+\/)?[\w.-]+>|(?:https?:\/\/|file:\/\/|[A-Za-z]:[\\/]|<home>[\\/]|\/|\.{1,2}[\\/]|\b[\w.-]+[\\/])[^\s"'<>]+/g,
34688
+ (location2) => {
34689
+ if (location2.startsWith("<package:")) return location2;
34690
+ const dependency = /(?:^|[\\/])node_modules[\\/]((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(
34691
+ location2
34692
+ );
34693
+ return dependency ? `<package:${dependency[1]?.replace(/\\/g, "/")}>` : "<path>";
34694
+ }
34695
+ ).replace(/\b[\w.-]+\.(?:tsx?|jsx?|swift|m|mm|kt|java)(?::\d+(?::\d+)?)?/g, "<source>").replace(/\{.*$|\[(?:\s*["'{\d]|$).*$/g, "<data>").replace(
34696
+ /\b(?:const|let|var)\s+\w+\s*=.*$|\b(?:function|class)\s+\w+.*$|\b(?:import|export)\s+.*$|\breturn\s*[({<].*$/g,
34697
+ "<source>"
34698
+ ).replace(/^\s*at\s+.*$|\bat\s+[\w.$<>]+\s*\([^)]*\)/g, "<stack>").trim().slice(0, 300);
34699
+ }
34700
+ function diagnosticVersion(version) {
34701
+ return version && version.length <= 80 && /^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version) ? version : null;
34702
+ }
34703
+ function setDiagnosticRuntimeVersion(version) {
34704
+ observedRuntimeVersion = diagnosticVersion(version);
34705
+ }
34706
+ function trackCliDiagnostic(diagnostic) {
34707
+ if (!diagnosticsAllowedForCurrentProcess()) return;
34708
+ if (queue.length >= 50) return;
34709
+ const entry = diagnostic.kind === "package_incompatibility" ? diagnostic : { ...diagnostic, message: sanitizeDiagnosticMessage(diagnostic.message) };
34710
+ if (queue.some((queued) => JSON.stringify(queued) === JSON.stringify(entry))) return;
34711
+ queue.push(entry);
34712
+ }
34713
+ var import_node_os3, observedRuntimeVersion, queue;
34714
+ var init_telemetry = __esm({
34715
+ "cli/telemetry.ts"() {
34716
+ "use strict";
34717
+ import_node_os3 = require("node:os");
34718
+ init_cli_version();
34719
+ init_home_paths();
34720
+ init_parse_args();
34721
+ init_privacy();
34722
+ observedRuntimeVersion = null;
34723
+ queue = [];
34724
+ }
34725
+ });
34726
+
34727
+ // cli/runtime-diagnostics.ts
34728
+ async function collectRuntimeDiagnostics(bridge) {
34729
+ if (!diagnosticsAllowedForCurrentProcess()) return;
34730
+ try {
34731
+ const result = await bridge.send(
34732
+ {
34733
+ type: "evaluate",
34734
+ code: `(() => {
34735
+ const messages = []
34736
+ const add = (kind, message) => {
34737
+ if (typeof message === 'string' && message) messages.push({ kind, message: message.slice(0, 2048) })
34738
+ }
34739
+ const obs = window.__sootsimObservability
34740
+ for (const e of (obs?.reportedErrors?.getSnapshot?.() || []).slice(-20)) add('runtime_error', e.message)
34741
+ for (const [kind, entries] of [
34742
+ ['runtime_error', ${consoleEntriesEval("error", 20)}],
34743
+ ['runtime_warning', ${consoleEntriesEval("warn", 20)}],
34744
+ ]) {
34745
+ for (const e of entries) {
34746
+ const parts = e.args.map(a => typeof a === 'string' ? a : typeof a?.message === 'string' ? a.message : '').filter(Boolean)
34747
+ add(kind, parts.join(' '))
34748
+ }
34749
+ }
34750
+ return { runtimeVersion: window.__sootsimRuntimeVersion, messages: messages.slice(0, 50) }
34751
+ })()`
34752
+ },
34753
+ { timeoutMs: 1e3 }
34754
+ );
34755
+ if (!result || typeof result !== "object") return;
34756
+ if ("runtimeVersion" in result && typeof result.runtimeVersion === "string") {
34757
+ setDiagnosticRuntimeVersion(result.runtimeVersion);
34758
+ }
34759
+ if (!("messages" in result) || !Array.isArray(result.messages)) return;
34760
+ for (const entry of result.messages.slice(0, 50)) {
34761
+ if (!entry || typeof entry !== "object") continue;
34762
+ if ((entry.kind === "runtime_error" || entry.kind === "runtime_warning") && typeof entry.message === "string") {
34763
+ trackCliDiagnostic({ kind: entry.kind, message: entry.message });
34764
+ }
34765
+ }
34766
+ } catch {
34767
+ }
34768
+ }
34769
+ var init_runtime_diagnostics = __esm({
34770
+ "cli/runtime-diagnostics.ts"() {
34771
+ "use strict";
34772
+ init_core();
34773
+ init_privacy();
34774
+ init_telemetry();
34775
+ }
34776
+ });
34777
+
34415
34778
  // cli/runtime-notes.ts
34416
34779
  function isChangelogEntry(value) {
34417
34780
  if (!value || typeof value !== "object") return false;
@@ -34667,11 +35030,11 @@ async function runtimeRemove(args) {
34667
35030
  rnxExit(1);
34668
35031
  }
34669
35032
  const dir = runtimeDir(version);
34670
- if (!import_fs9.default.existsSync(dir)) {
35033
+ if (!import_fs8.default.existsSync(dir)) {
34671
35034
  console.error(` ${version} is not installed`);
34672
35035
  return;
34673
35036
  }
34674
- import_fs9.default.rmSync(dir, { recursive: true, force: true });
35037
+ import_fs8.default.rmSync(dir, { recursive: true, force: true });
34675
35038
  console.log(` removed ${version}`);
34676
35039
  }
34677
35040
  async function runtimeWhich() {
@@ -34726,11 +35089,11 @@ function describeError(err) {
34726
35089
  if (err instanceof Error) return err.message;
34727
35090
  return String(err);
34728
35091
  }
34729
- var import_fs9, import_ws3;
35092
+ var import_fs8, import_ws3;
34730
35093
  var init_runtime = __esm({
34731
35094
  "cli/commands/runtime.ts"() {
34732
35095
  "use strict";
34733
- import_fs9 = __toESM(require("fs"), 1);
35096
+ import_fs8 = __toESM(require("fs"), 1);
34734
35097
  init_src();
34735
35098
  import_ws3 = require("ws");
34736
35099
  init_home_paths();
@@ -34873,7 +35236,7 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
34873
35236
  async function ensureRuntimeForOpen() {
34874
35237
  if (resolveDevCheckoutRuntimeRoot()) return;
34875
35238
  const active = readActiveRuntime();
34876
- if (active && import_node_fs23.default.existsSync(runtimeDir(active))) return;
35239
+ if (active && import_node_fs24.default.existsSync(runtimeDir(active))) return;
34877
35240
  console.error(" installing peach engine runtime...");
34878
35241
  const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
34879
35242
  await runRuntime2(["install"], {});
@@ -35027,10 +35390,10 @@ async function buildResolvedBundleOpenUrl(target, baseUrl, opts = {}) {
35027
35390
  }
35028
35391
  function normalizeReplacementPath(filePath) {
35029
35392
  if (filePath.startsWith("~/")) {
35030
- return import_node_path25.default.join(import_node_os3.default.homedir(), filePath.slice(2));
35393
+ return import_node_path26.default.join(import_node_os4.default.homedir(), filePath.slice(2));
35031
35394
  }
35032
- if (import_node_path25.default.isAbsolute(filePath)) return filePath;
35033
- return import_node_path25.default.resolve(process.cwd(), filePath);
35395
+ if (import_node_path26.default.isAbsolute(filePath)) return filePath;
35396
+ return import_node_path26.default.resolve(process.cwd(), filePath);
35034
35397
  }
35035
35398
  function parseOpenRuntimeConfig(args) {
35036
35399
  const modules = {};
@@ -35049,7 +35412,7 @@ function parseOpenRuntimeConfig(args) {
35049
35412
  }
35050
35413
  const moduleName = raw.slice(0, eqIndex).trim();
35051
35414
  const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
35052
- if (!import_node_fs23.default.existsSync(filePath)) {
35415
+ if (!import_node_fs24.default.existsSync(filePath)) {
35053
35416
  console.error(` peach open: replacement file not found: ${filePath}`);
35054
35417
  rnxExit(1);
35055
35418
  }
@@ -35080,7 +35443,7 @@ async function resolveAppProjectForBundleUrl(bundleUrl) {
35080
35443
  return advertisedRoot ? resolveAppProject(advertisedRoot) : null;
35081
35444
  }
35082
35445
  async function ensureConfiguredRuntime(version) {
35083
- if (import_node_fs23.default.existsSync(import_node_path25.default.join(runtimeDir(version), "index.html"))) return;
35446
+ if (import_node_fs24.default.existsSync(import_node_path26.default.join(runtimeDir(version), "index.html"))) return;
35084
35447
  console.error(` installing configured engine runtime ${version}...`);
35085
35448
  const result = await rnxRuntime.install({
35086
35449
  version,
@@ -35145,11 +35508,11 @@ async function filterReachableAppFonts(specs) {
35145
35508
  }
35146
35509
  })
35147
35510
  );
35148
- const reachable = [];
35511
+ const reachable = /* @__PURE__ */ new Map();
35149
35512
  for (const spec of results) {
35150
- if (spec !== null) reachable.push(spec);
35513
+ if (spec !== null && !reachable.has(spec.family)) reachable.set(spec.family, spec);
35151
35514
  }
35152
- return reachable;
35515
+ return [...reachable.values()];
35153
35516
  }
35154
35517
  async function resolveShellUrl(target, baseUrl, opts = {}) {
35155
35518
  if (!target) {
@@ -35394,7 +35757,7 @@ function playwrightHostPidForSim(sim) {
35394
35757
  function signalDriverLaunchConnected(result) {
35395
35758
  if (!result.connectAckFile) return false;
35396
35759
  try {
35397
- import_node_fs23.default.writeFileSync(
35760
+ import_node_fs24.default.writeFileSync(
35398
35761
  result.connectAckFile,
35399
35762
  `${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
35400
35763
  `,
@@ -35408,19 +35771,19 @@ function signalDriverLaunchConnected(result) {
35408
35771
  function printDriverDiagnosticLogTail(result) {
35409
35772
  if (!result.diagnosticLogPath) return;
35410
35773
  try {
35411
- const detail = import_node_fs23.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
35774
+ const detail = import_node_fs24.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
35412
35775
  if (!detail) {
35413
- console.error(` ${import_node_path25.default.basename(result.diagnosticLogPath)} was empty`);
35776
+ console.error(` ${import_node_path26.default.basename(result.diagnosticLogPath)} was empty`);
35414
35777
  return;
35415
35778
  }
35416
35779
  const shown = detail.length > 4e3 ? `\u2026
35417
35780
  ${detail.slice(-4e3)}` : detail;
35418
- console.error(` ${import_node_path25.default.basename(result.diagnosticLogPath)}:`);
35781
+ console.error(` ${import_node_path26.default.basename(result.diagnosticLogPath)}:`);
35419
35782
  console.error(shown);
35420
35783
  } catch (err) {
35421
35784
  const message = err instanceof Error ? err.message : String(err);
35422
35785
  console.error(
35423
- ` failed to read ${import_node_path25.default.basename(result.diagnosticLogPath)}: ${message}`
35786
+ ` failed to read ${import_node_path26.default.basename(result.diagnosticLogPath)}: ${message}`
35424
35787
  );
35425
35788
  }
35426
35789
  }
@@ -35541,11 +35904,12 @@ function printAgentListenHint(quiet) {
35541
35904
  }
35542
35905
  }
35543
35906
  async function maybeDescribeAfterOpen(wsPort, simId, args) {
35544
- if (args.includes("--no-describe")) return;
35907
+ const noDescribe = args.includes("--no-describe");
35908
+ if (noDescribe && !diagnosticsAllowedForCurrentProcess()) return;
35545
35909
  const prevQuiet = process.env.SOOTSIM_QUIET_TARGET_NOTICE;
35546
35910
  process.env.SOOTSIM_QUIET_TARGET_NOTICE = "1";
35547
35911
  try {
35548
- await waitForTreeStable(wsPort, simId, { stableMs: 150, maxMs: 400 });
35912
+ if (!noDescribe) await waitForTreeStable(wsPort, simId, { stableMs: 150, maxMs: 400 });
35549
35913
  const bridge = createBridge(wsPort, {
35550
35914
  commandTimeoutMs: 3e3,
35551
35915
  simId,
@@ -35553,6 +35917,7 @@ async function maybeDescribeAfterOpen(wsPort, simId, args) {
35553
35917
  simIdSource: "flag"
35554
35918
  });
35555
35919
  try {
35920
+ if (noDescribe) return;
35556
35921
  let readyProbe = null;
35557
35922
  try {
35558
35923
  readyProbe = await inspectWaitReady(bridge, 1);
@@ -35579,6 +35944,7 @@ async function maybeDescribeAfterOpen(wsPort, simId, args) {
35579
35944
  console.log("");
35580
35945
  console.log(result.tree);
35581
35946
  } finally {
35947
+ await collectRuntimeDiagnostics(bridge);
35582
35948
  bridge.close();
35583
35949
  }
35584
35950
  } catch {
@@ -36350,14 +36716,14 @@ async function runCloseCommand(args, opts = {}) {
36350
36716
  bridge.close();
36351
36717
  }
36352
36718
  }
36353
- var import_node_child_process7, import_node_fs23, import_node_os3, import_node_path25, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
36719
+ var import_node_child_process7, import_node_fs24, import_node_os4, import_node_path26, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
36354
36720
  var init_control = __esm({
36355
36721
  "cli/commands/control.ts"() {
36356
36722
  "use strict";
36357
36723
  import_node_child_process7 = require("node:child_process");
36358
- import_node_fs23 = __toESM(require("node:fs"), 1);
36359
- import_node_os3 = __toESM(require("node:os"), 1);
36360
- import_node_path25 = __toESM(require("node:path"), 1);
36724
+ import_node_fs24 = __toESM(require("node:fs"), 1);
36725
+ import_node_os4 = __toESM(require("node:os"), 1);
36726
+ import_node_path26 = __toESM(require("node:path"), 1);
36361
36727
  import_app_catalog_wire = require("peach-engine/engine/app-catalog-wire");
36362
36728
  import_devices2 = require("peach-engine/settings/devices");
36363
36729
  import_ws4 = require("ws");
@@ -36385,7 +36751,9 @@ var init_control = __esm({
36385
36751
  init_current_sim();
36386
36752
  init_registry2();
36387
36753
  init_open_url2();
36754
+ init_privacy();
36388
36755
  init_run_rnx();
36756
+ init_runtime_diagnostics();
36389
36757
  init_self_invocation();
36390
36758
  init_ws_bridge();
36391
36759
  init_core();
@@ -37544,17 +37912,17 @@ function normalizeBareStringStep(verb) {
37544
37912
  function parseFlowSteps(content) {
37545
37913
  const parts = content.split(/^---$/m);
37546
37914
  const candidate = parts.length > 1 ? parts[parts.length - 1] : content;
37547
- const parsed = import_yaml.default.parse(candidate);
37915
+ const parsed = import_yaml2.default.parse(candidate);
37548
37916
  return Array.isArray(parsed) ? parsed : [];
37549
37917
  }
37550
- var fs20, path20, import_devices4, import_yaml, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
37918
+ var fs20, path20, import_devices4, import_yaml2, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
37551
37919
  var init_bridge_flow_runner = __esm({
37552
37920
  "cli/bridge-flow-runner.ts"() {
37553
37921
  "use strict";
37554
37922
  fs20 = __toESM(require("fs"), 1);
37555
37923
  path20 = __toESM(require("path"), 1);
37556
37924
  import_devices4 = require("peach-engine/settings/devices");
37557
- import_yaml = __toESM(require("yaml"), 1);
37925
+ import_yaml2 = __toESM(require("yaml"), 1);
37558
37926
  import_proof_frame = __toESM(require_proof_frame(), 1);
37559
37927
  init_flow_timeout_scale();
37560
37928
  init_frame_compose();
@@ -39284,7 +39652,10 @@ var init_bridge_flow_runner = __esm({
39284
39652
  }
39285
39653
  }
39286
39654
  try {
39287
- const hasExplicitWait = !!(step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || step.runFlow || // retry reruns its body on failure, so its wall time is the body's
39655
+ const hasBoundedWait = !!// taps combine bounded lookup, settling and delivery. a wall-clock
39656
+ // watchdog can finish the step while that action is still running.
39657
+ // let these operations finish before starting the next command.
39658
+ (step.tapOn || step.doubleTapOn || step.longPressOn || step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || step.runFlow || // retry reruns its body on failure, so its wall time is the body's
39288
39659
  // times the retry count — the 10s no-progress watchdog is the wrong
39289
39660
  // budget and would report "bridge probably hung" for a slow retry.
39290
39661
  step.retry || // runScript http calls are synchronous with a 5-minute upstream
@@ -39300,7 +39671,7 @@ var init_bridge_flow_runner = __esm({
39300
39671
  const STEP_WATCHDOG_MS = 1e4;
39301
39672
  const body = this.runStepInner(step);
39302
39673
  let screenshotPath;
39303
- if (hasExplicitWait) {
39674
+ if (hasBoundedWait) {
39304
39675
  const result = await body;
39305
39676
  if (typeof result === "string") screenshotPath = result;
39306
39677
  } else {