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 __defProp = Object.defineProperty;
@@ -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
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -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 __defProp = Object.defineProperty;
@@ -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;
@@ -2474,7 +2474,7 @@ async function waitForSootsimIdle(page, maxMs = 3e3, strict = false) {
2474
2474
  }
2475
2475
  async function findNodeByMatcher(matcher) {
2476
2476
  const page = getPage();
2477
- if (matcher.index !== void 0) {
2477
+ if (matcher.index !== void 0 || matcher.type === "text") {
2478
2478
  return page.evaluate(async (indexedMatcher) => {
2479
2479
  const filter = indexedMatcher.type === "id" ? { hasId: indexedMatcher.value } : indexedMatcher.type === "text" ? { hasText: indexedMatcher.value } : indexedMatcher.type === "label" ? { hasLabel: indexedMatcher.value } : indexedMatcher.type === "role" ? { hasRole: indexedMatcher.value } : { type: indexedMatcher.value };
2480
2480
  const results = await window.__sootsimTest.queryAll(filter);
@@ -2489,11 +2489,6 @@ async function findNodeByMatcher(matcher) {
2489
2489
  (id) => window.__sootsimTest.findByTestId(id),
2490
2490
  matcher.value
2491
2491
  );
2492
- } else if (matcher.type === "text") {
2493
- return page.evaluate(
2494
- (text) => window.__sootsimTest.findByText(text),
2495
- matcher.value
2496
- );
2497
2492
  } else if (matcher.type === "label") {
2498
2493
  return page.evaluate(
2499
2494
  (label) => window.__sootsimTest.findByLabel(label),
@@ -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 __defProp = Object.defineProperty;
@@ -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;
@@ -62,6 +62,7 @@ __export(home_paths_exports, {
62
62
  isDevWorkstation: () => isDevWorkstation,
63
63
  isOnboardingComplete: () => isOnboardingComplete,
64
64
  isSootsimDevCheckout: () => isSootsimDevCheckout,
65
+ playwrightCoreDir: () => playwrightCoreDir,
65
66
  profilesDir: () => profilesDir,
66
67
  readActiveRuntime: () => readActiveRuntime,
67
68
  readDaemonLockfile: () => readDaemonLockfile,
@@ -144,6 +145,9 @@ function electronUserDataDir() {
144
145
  function electronVersionDir(version) {
145
146
  return import_node_path.default.join(electronDir(), version);
146
147
  }
148
+ function playwrightCoreDir(version) {
149
+ return import_node_path.default.join(rnxHomeDir(), "playwright-core", version);
150
+ }
147
151
  function profilesDir() {
148
152
  return import_node_path.default.join(rnxHomeDir(), "profiles");
149
153
  }
@@ -226,7 +230,7 @@ function readPrivacyPreferences() {
226
230
  return {
227
231
  productAnalytics: typeof productAnalytics === "boolean" ? productAnalytics : false,
228
232
  crashReports: typeof crashReports === "boolean" ? crashReports : false,
229
- configured: typeof productAnalytics === "boolean" && typeof crashReports === "boolean"
233
+ configured: typeof productAnalytics === "boolean"
230
234
  };
231
235
  }
232
236
  function writePrivacyPreferences(preferences) {
@@ -238,10 +242,13 @@ function writePrivacyPreferences(preferences) {
238
242
  });
239
243
  }
240
244
  function readOrCreateAnonymousId() {
241
- const existing = readSharedConfig().anonymousId;
242
- if (typeof existing === "string" && existing.trim()) return existing;
245
+ const existing = readSharedConfig().settings?.anonymousId;
246
+ 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(
247
+ existing
248
+ ))
249
+ return existing;
243
250
  const created = `anon-cli-${(0, import_node_crypto.randomUUID)()}`;
244
- writeSharedConfig({ anonymousId: created });
251
+ writeSharedConfig({ settings: { anonymousId: created } });
245
252
  return created;
246
253
  }
247
254
  function readDefaultBox() {
@@ -610,6 +617,7 @@ function removeDevBridgeLockfile(owner) {
610
617
  isDevWorkstation,
611
618
  isOnboardingComplete,
612
619
  isSootsimDevCheckout,
620
+ playwrightCoreDir,
613
621
  profilesDir,
614
622
  readActiveRuntime,
615
623
  readDaemonLockfile,
@@ -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;
@@ -3949,39 +3949,82 @@ function detectFramework(deps) {
3949
3949
  return "unknown";
3950
3950
  }
3951
3951
  function detectProject(dir) {
3952
- const pkgPath = (0, import_path2.join)(dir, "package.json");
3953
- if (!(0, import_fs2.existsSync)(pkgPath)) return null;
3954
- let pkg;
3955
- try {
3956
- pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf8"));
3957
- } catch {
3958
- return null;
3959
- }
3952
+ const pkgPath = (0, import_node_path16.join)(dir, "package.json");
3953
+ if (!(0, import_node_fs15.existsSync)(pkgPath)) return null;
3954
+ const pkg = readProjectManifest(dir);
3955
+ if (!pkg) return null;
3960
3956
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
3957
+ const devCommand = metadataValue(
3958
+ metadataValue(readProjectJson(pkgPath), "scripts"),
3959
+ "dev"
3960
+ );
3961
3961
  const framework = detectFramework(deps);
3962
3962
  if (framework === "unknown") return null;
3963
3963
  return {
3964
3964
  dir,
3965
- name: pkg.name || (0, import_path2.basename)(dir),
3965
+ name: pkg.name || (0, import_node_path16.basename)(dir),
3966
3966
  framework,
3967
3967
  // a config file is a config file whatever module system it declares. real
3968
3968
  // apps write .cjs as often as .js, and missing one reads as "this project
3969
3969
  // has no bundler config" and sends the user to create a second one.
3970
3970
  hasViteConfig: CONFIG_EXTENSIONS.some(
3971
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `vite.config.${ext}`))
3971
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `vite.config.${ext}`))
3972
3972
  ),
3973
3973
  hasMetroConfig: CONFIG_EXTENSIONS.some(
3974
- (ext) => (0, import_fs2.existsSync)((0, import_path2.join)(dir, `metro.config.${ext}`))
3974
+ (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `metro.config.${ext}`))
3975
3975
  ),
3976
- devCommand: pkg.scripts?.dev || null
3976
+ devCommand: typeof devCommand === "string" ? devCommand : null
3977
3977
  };
3978
3978
  }
3979
- var import_fs2, import_path2, CONFIG_EXTENSIONS;
3979
+ function readProjectMetadata(path12) {
3980
+ try {
3981
+ const info = (0, import_node_fs15.lstatSync)(path12);
3982
+ if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
3983
+ return (0, import_node_fs15.readFileSync)(path12, "utf8");
3984
+ } catch {
3985
+ return null;
3986
+ }
3987
+ }
3988
+ function metadataValue(value, key) {
3989
+ if (!value || typeof value !== "object") return void 0;
3990
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
3991
+ }
3992
+ function readProjectJson(path12) {
3993
+ const text = readProjectMetadata(path12);
3994
+ if (text === null) return null;
3995
+ try {
3996
+ const value = JSON.parse(text);
3997
+ return value;
3998
+ } catch {
3999
+ return null;
4000
+ }
4001
+ }
4002
+ function readProjectManifest(dir) {
4003
+ const parsed = readProjectJson((0, import_node_path16.join)(dir, "package.json"));
4004
+ if (!parsed || typeof parsed !== "object") return null;
4005
+ const record = (value) => {
4006
+ if (!value || typeof value !== "object") return {};
4007
+ return Object.fromEntries(
4008
+ Object.entries(value).filter(
4009
+ (entry) => typeof entry[1] === "string" && /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/i.test(entry[0]) && entry[0] !== "." && entry[0] !== ".."
4010
+ )
4011
+ );
4012
+ };
4013
+ const name2 = metadataValue(parsed, "name");
4014
+ return {
4015
+ ...typeof name2 === "string" ? { name: name2 } : {},
4016
+ dependencies: record(metadataValue(parsed, "dependencies")),
4017
+ devDependencies: record(metadataValue(parsed, "devDependencies"))
4018
+ };
4019
+ }
4020
+ var import_node_fs15, import_node_path16, import_json5, import_yaml, CONFIG_EXTENSIONS;
3980
4021
  var init_detect = __esm({
3981
4022
  "cli/commands/detect.ts"() {
3982
4023
  "use strict";
3983
- import_fs2 = require("fs");
3984
- import_path2 = require("path");
4024
+ import_node_fs15 = require("node:fs");
4025
+ import_node_path16 = require("node:path");
4026
+ import_json5 = __toESM(require("json5"), 1);
4027
+ import_yaml = require("yaml");
3985
4028
  CONFIG_EXTENSIONS = ["ts", "js", "cjs", "mjs", "mts", "cts"];
3986
4029
  }
3987
4030
  });
@@ -4016,21 +4059,21 @@ function resolveCloudOrigin(value) {
4016
4059
  return normalizeCloudOrigin(source);
4017
4060
  }
4018
4061
  function readImmutableBundleSource(bundlePath) {
4019
- const filepath = (0, import_node_path16.resolve)(bundlePath);
4020
- if ((0, import_node_path16.extname)(filepath) !== ".js") {
4062
+ const filepath = (0, import_node_path17.resolve)(bundlePath);
4063
+ if ((0, import_node_path17.extname)(filepath) !== ".js") {
4021
4064
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
4022
4065
  }
4023
- const descriptor = (0, import_node_fs15.openSync)(filepath, "r");
4066
+ const descriptor = (0, import_node_fs16.openSync)(filepath, "r");
4024
4067
  try {
4025
- const before = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4068
+ const before = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
4026
4069
  if (!before.isFile()) {
4027
4070
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
4028
4071
  }
4029
4072
  if (before.size <= 0n) {
4030
4073
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
4031
4074
  }
4032
- const bytes = (0, import_node_fs15.readFileSync)(descriptor);
4033
- const after = (0, import_node_fs15.fstatSync)(descriptor, { bigint: true });
4075
+ const bytes = (0, import_node_fs16.readFileSync)(descriptor);
4076
+ const after = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
4034
4077
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
4035
4078
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
4036
4079
  }
@@ -4045,7 +4088,7 @@ function readImmutableBundleSource(bundlePath) {
4045
4088
  }
4046
4089
  return source;
4047
4090
  } finally {
4048
- (0, import_node_fs15.closeSync)(descriptor);
4091
+ (0, import_node_fs16.closeSync)(descriptor);
4049
4092
  }
4050
4093
  }
4051
4094
  async function fetchBundleSource(bundleUrl) {
@@ -4092,15 +4135,15 @@ async function loadBundleSource(bundleInput) {
4092
4135
  return readImmutableBundleSource(bundleInput);
4093
4136
  }
4094
4137
  function listMetroAssetDest(assetsPath) {
4095
- const directory = (0, import_node_path16.resolve)(assetsPath);
4096
- if (!(0, import_node_fs15.existsSync)(directory)) return { directory, files: [], truncated: false };
4097
- const skipNested = (0, import_node_fs15.existsSync)((0, import_node_path16.join)(directory, "package.json"));
4138
+ const directory = (0, import_node_path17.resolve)(assetsPath);
4139
+ if (!(0, import_node_fs16.existsSync)(directory)) return { directory, files: [], truncated: false };
4140
+ const skipNested = (0, import_node_fs16.existsSync)((0, import_node_path17.join)(directory, "package.json"));
4098
4141
  const files = [];
4099
4142
  let truncated = false;
4100
4143
  const walk = (dir, prefix) => {
4101
4144
  let entries;
4102
4145
  try {
4103
- entries = (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true });
4146
+ entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
4104
4147
  } catch {
4105
4148
  return;
4106
4149
  }
@@ -4112,7 +4155,7 @@ function listMetroAssetDest(assetsPath) {
4112
4155
  if (entry.isDirectory()) {
4113
4156
  if (entry.name === ".git") continue;
4114
4157
  if (skipNested && PROJECT_ONLY_DIRECTORIES.has(entry.name)) continue;
4115
- walk((0, import_node_path16.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4158
+ walk((0, import_node_path17.join)(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);
4116
4159
  } else if (entry.isFile()) {
4117
4160
  files.push(prefix ? `${prefix}/${entry.name}` : entry.name);
4118
4161
  }
@@ -4147,7 +4190,7 @@ function distinctByContent(directory, options) {
4147
4190
  for (const relative2 of options) {
4148
4191
  let bytes;
4149
4192
  try {
4150
- bytes = (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(directory, relative2));
4193
+ bytes = (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(directory, relative2));
4151
4194
  } catch {
4152
4195
  continue;
4153
4196
  }
@@ -4179,7 +4222,7 @@ function placeMetroDescriptor(listing, descriptor) {
4179
4222
  let bytes;
4180
4223
  try {
4181
4224
  bytes = combination.map(
4182
- (relative2) => (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(listing.directory, relative2))
4225
+ (relative2) => (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(listing.directory, relative2))
4183
4226
  );
4184
4227
  } catch {
4185
4228
  continue;
@@ -4205,26 +4248,26 @@ function placeMetroDescriptor(listing, descriptor) {
4205
4248
  }
4206
4249
  function unverifiedFileKey(dest) {
4207
4250
  return dest.placements.filter((placement) => !placement.verified).flatMap(
4208
- (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path16.join)(dest.directory, relative2))
4251
+ (placement) => [...placement.files.values()].map((relative2) => (0, import_node_path17.join)(dest.directory, relative2))
4209
4252
  ).sort().join("\n");
4210
4253
  }
4211
4254
  function searchMetroAssetDest(bundlePath, descriptors) {
4212
- const bundleDirectory = (0, import_node_path16.dirname)((0, import_node_path16.resolve)(bundlePath));
4255
+ const bundleDirectory = (0, import_node_path17.dirname)((0, import_node_path17.resolve)(bundlePath));
4213
4256
  const candidates = [
4214
- (0, import_node_path16.join)(bundleDirectory, "assets"),
4257
+ (0, import_node_path17.join)(bundleDirectory, "assets"),
4215
4258
  bundleDirectory,
4216
- (0, import_node_path16.resolve)(bundleDirectory, "..", "assets")
4259
+ (0, import_node_path17.resolve)(bundleDirectory, "..", "assets")
4217
4260
  ];
4218
4261
  const cwd = process.cwd();
4219
4262
  let projectDirectory = null;
4220
4263
  for (const start of [bundleDirectory, cwd]) {
4221
- let directory = (0, import_node_path16.resolve)(start);
4264
+ let directory = (0, import_node_path17.resolve)(start);
4222
4265
  while (true) {
4223
4266
  if (detectProject(directory)?.hasMetroConfig) {
4224
4267
  projectDirectory = directory;
4225
4268
  break;
4226
4269
  }
4227
- const parent = (0, import_node_path16.dirname)(directory);
4270
+ const parent = (0, import_node_path17.dirname)(directory);
4228
4271
  if (parent === directory) break;
4229
4272
  directory = parent;
4230
4273
  }
@@ -4232,11 +4275,11 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4232
4275
  }
4233
4276
  if (projectDirectory) {
4234
4277
  candidates.push(
4235
- (0, import_node_path16.join)(projectDirectory, "assets"),
4236
- (0, import_node_path16.join)(projectDirectory, "dist"),
4237
- (0, import_node_path16.join)(projectDirectory, "dist", "assets"),
4238
- (0, import_node_path16.join)(projectDirectory, "build"),
4239
- (0, import_node_path16.join)(projectDirectory, "build", "assets")
4278
+ (0, import_node_path17.join)(projectDirectory, "assets"),
4279
+ (0, import_node_path17.join)(projectDirectory, "dist"),
4280
+ (0, import_node_path17.join)(projectDirectory, "dist", "assets"),
4281
+ (0, import_node_path17.join)(projectDirectory, "build"),
4282
+ (0, import_node_path17.join)(projectDirectory, "build", "assets")
4240
4283
  );
4241
4284
  }
4242
4285
  const searched = [];
@@ -4244,7 +4287,7 @@ function searchMetroAssetDest(bundlePath, descriptors) {
4244
4287
  const stale = [];
4245
4288
  let truncated = false;
4246
4289
  for (const candidate of candidates) {
4247
- const directory = (0, import_node_path16.resolve)(candidate);
4290
+ const directory = (0, import_node_path17.resolve)(candidate);
4248
4291
  if (searched.includes(directory)) continue;
4249
4292
  searched.push(directory);
4250
4293
  const listing = listMetroAssetDest(directory);
@@ -4350,7 +4393,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4350
4393
  );
4351
4394
  }
4352
4395
  const relative2 = placement?.files.get(variant.scale);
4353
- if (relative2 && dest) return (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(dest.directory, relative2));
4396
+ if (relative2 && dest) return (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(dest.directory, relative2));
4354
4397
  if (placement && placement.files.size > 0) return null;
4355
4398
  if (placement && placement.ambiguous.length > 0 && dest) {
4356
4399
  throw new Error(
@@ -4379,7 +4422,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
4379
4422
  );
4380
4423
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
4381
4424
  throw new Error(
4382
- `${command} could not read ${(0, import_node_path16.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Rebuild with \`react-native bundle --assets-dest\`.`
4425
+ `${command} could not read ${(0, import_node_path17.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Rebuild with \`react-native bundle --assets-dest\`.`
4383
4426
  );
4384
4427
  });
4385
4428
  return {
@@ -4525,13 +4568,13 @@ async function createCloudBox(options) {
4525
4568
  warnings: artifact.warnings
4526
4569
  };
4527
4570
  }
4528
- var import_node_crypto6, import_node_fs15, import_node_path16, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4571
+ var import_node_crypto6, import_node_fs16, import_node_path17, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4529
4572
  var init_cloud_client = __esm({
4530
4573
  "cli/cloud-client.ts"() {
4531
4574
  "use strict";
4532
4575
  import_node_crypto6 = require("node:crypto");
4533
- import_node_fs15 = require("node:fs");
4534
- import_node_path16 = require("node:path");
4576
+ import_node_fs16 = require("node:fs");
4577
+ import_node_path17 = require("node:path");
4535
4578
  init_metroAssetArtifact();
4536
4579
  init_metroCloudArtifact();
4537
4580
  init_metro_fingerprint_registry_client();
@@ -4637,9 +4680,9 @@ __export(bridge_host_exports, {
4637
4680
  });
4638
4681
  module.exports = __toCommonJS(bridge_host_exports);
4639
4682
  var import_child_process3 = require("child_process");
4640
- var import_fs3 = __toESM(require("fs"), 1);
4683
+ var import_fs2 = __toESM(require("fs"), 1);
4641
4684
  var import_http4 = require("http");
4642
- var import_path3 = __toESM(require("path"), 1);
4685
+ var import_path2 = __toESM(require("path"), 1);
4643
4686
  var import_ws = require("ws");
4644
4687
 
4645
4688
  // scripts/dev-server-scanner.ts
@@ -6121,48 +6164,16 @@ function createRuntimeDelivery(product) {
6121
6164
  manifest
6122
6165
  };
6123
6166
  }
6124
- const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
6125
- const downloadDir = import_node_fs7.default.mkdtempSync(
6126
- import_node_path7.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
6127
- );
6128
- const runtimeArchivePath = import_node_path7.default.join(
6129
- downloadDir,
6130
- runtimeTarballCacheName(product, version)
6131
- );
6132
- const tmpDir = import_node_path7.default.join(
6133
- import_node_path7.default.dirname(destDir),
6134
- `.installing-${version}-${process.pid}`
6135
- );
6136
- import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6137
- try {
6138
- if (!opts.quiet)
6139
- process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
6167
+ if (!opts.quiet)
6168
+ process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
6140
6169
  `);
6141
- await downloadToFile(tarUrl, runtimeArchivePath);
6142
- if (!opts.quiet)
6143
- process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
6144
- `);
6145
- const actualSha = await sha256File(runtimeArchivePath);
6146
- if (actualSha !== entry.sha256) {
6147
- throw new Error(
6148
- `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
6149
- );
6150
- }
6151
- import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
6152
- await extractTarball(runtimeArchivePath, tmpDir);
6153
- if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, product.installedMarker))) {
6154
- throw new Error(
6155
- `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
6156
- );
6157
- }
6158
- import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
6159
- import_node_fs7.default.renameSync(tmpDir, destDir);
6160
- } catch (err) {
6161
- import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6162
- throw err;
6163
- } finally {
6164
- import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
6165
- }
6170
+ await installVerifiedTarball({
6171
+ url: entry.tarball || tarballUrl(version, cdnOrigin),
6172
+ digest: { algorithm: "sha256", encoding: "hex", value: entry.sha256 },
6173
+ destDir,
6174
+ installedMarker: product.installedMarker,
6175
+ label: `runtime ${version}`
6176
+ });
6166
6177
  if (setActive) product.writeActiveRuntime(version);
6167
6178
  pruneLocalRetention({ protectVersions });
6168
6179
  return {
@@ -6352,6 +6363,37 @@ function createRuntimeDelivery(product) {
6352
6363
  listInstalled: () => listInstalledRuntimes(product)
6353
6364
  };
6354
6365
  }
6366
+ async function installVerifiedTarball(tarball) {
6367
+ const { url, digest, destDir, installedMarker, label } = tarball;
6368
+ const downloadDir = import_node_fs7.default.mkdtempSync(import_node_path7.default.join(import_node_os2.default.tmpdir(), "runtime-delivery-download-"));
6369
+ const archivePath = import_node_path7.default.join(downloadDir, "archive.tar.gz");
6370
+ const tmpDir = import_node_path7.default.join(
6371
+ import_node_path7.default.dirname(destDir),
6372
+ `.installing-${import_node_path7.default.basename(destDir)}-${process.pid}`
6373
+ );
6374
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6375
+ try {
6376
+ await downloadToFile(url, archivePath);
6377
+ const actual = await digestFile(archivePath, digest.algorithm, digest.encoding);
6378
+ if (actual !== digest.value) {
6379
+ throw new Error(
6380
+ `${digest.algorithm} mismatch for ${label}: expected ${digest.value}, actual ${actual}`
6381
+ );
6382
+ }
6383
+ import_node_fs7.default.mkdirSync(tmpDir, { recursive: true });
6384
+ await extractTarball(archivePath, tmpDir, tarball.stripComponents ?? 0);
6385
+ if (!import_node_fs7.default.existsSync(import_node_path7.default.join(tmpDir, installedMarker))) {
6386
+ throw new Error(`extracted tarball for ${label} is missing ${installedMarker}`);
6387
+ }
6388
+ import_node_fs7.default.rmSync(destDir, { recursive: true, force: true });
6389
+ import_node_fs7.default.renameSync(tmpDir, destDir);
6390
+ } catch (err) {
6391
+ import_node_fs7.default.rmSync(tmpDir, { recursive: true, force: true });
6392
+ throw err;
6393
+ } finally {
6394
+ import_node_fs7.default.rmSync(downloadDir, { recursive: true, force: true });
6395
+ }
6396
+ }
6355
6397
  async function downloadToFile(url, destPath) {
6356
6398
  const res = await fetch(url);
6357
6399
  if (!res.ok || !res.body) {
@@ -6373,18 +6415,20 @@ async function downloadToFile(url, destPath) {
6373
6415
  throw err;
6374
6416
  }
6375
6417
  }
6376
- function sha256File(filePath) {
6418
+ function digestFile(filePath, algorithm, encoding) {
6377
6419
  return new Promise((resolve5, reject) => {
6378
- const hash = import_node_crypto2.default.createHash("sha256");
6420
+ const hash = import_node_crypto2.default.createHash(algorithm);
6379
6421
  const stream = import_node_fs7.default.createReadStream(filePath);
6380
6422
  stream.on("data", (chunk) => hash.update(chunk));
6381
6423
  stream.on("error", reject);
6382
- stream.on("end", () => resolve5(hash.digest("hex")));
6424
+ stream.on("end", () => resolve5(hash.digest(encoding)));
6383
6425
  });
6384
6426
  }
6385
- function extractTarball(tarPath, destDir) {
6427
+ function extractTarball(tarPath, destDir, stripComponents) {
6386
6428
  return new Promise((resolve5, reject) => {
6387
- const child = (0, import_node_child_process2.spawn)("tar", ["-xzf", tarPath, "-C", destDir], {
6429
+ const args = ["-xzf", tarPath, "-C", destDir];
6430
+ if (stripComponents > 0) args.push(`--strip-components=${stripComponents}`);
6431
+ const child = (0, import_node_child_process2.spawn)("tar", args, {
6388
6432
  stdio: ["ignore", "inherit", "inherit"]
6389
6433
  });
6390
6434
  child.on("error", reject);
@@ -9513,7 +9557,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
9513
9557
  async startAsync(options) {
9514
9558
  if (this.httpServer || this.wss) return this.effectivePort;
9515
9559
  this.refreshActiveRuntime();
9516
- this.bootstrapping = !this.activeRuntimeDirPath || !import_fs3.default.existsSync(import_path3.default.join(this.activeRuntimeDirPath, "index.html"));
9560
+ this.bootstrapping = !this.activeRuntimeDirPath || !import_fs2.default.existsSync(import_path2.default.join(this.activeRuntimeDirPath, "index.html"));
9517
9561
  for (let attempt = 0; attempt < this.portFallbackCount; attempt++) {
9518
9562
  const candidate = this.preferredPort + attempt;
9519
9563
  try {
@@ -10185,10 +10229,10 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10185
10229
  return;
10186
10230
  }
10187
10231
  const root = cameraFixturesDir();
10188
- const filePath = import_path3.default.join(root, name2);
10232
+ const filePath = import_path2.default.join(root, name2);
10189
10233
  let stats;
10190
10234
  try {
10191
- stats = import_fs3.default.lstatSync(filePath);
10235
+ stats = import_fs2.default.lstatSync(filePath);
10192
10236
  } catch {
10193
10237
  res.writeHead(404, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
10194
10238
  res.end("not found");
@@ -10199,7 +10243,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10199
10243
  res.end("forbidden");
10200
10244
  return;
10201
10245
  }
10202
- const contentType = HTTP_MIME_TYPES[import_path3.default.extname(filePath).toLowerCase()] || "application/octet-stream";
10246
+ const contentType = HTTP_MIME_TYPES[import_path2.default.extname(filePath).toLowerCase()] || "application/octet-stream";
10203
10247
  sendFileWithRanges(req, res, filePath, stats.size, {
10204
10248
  ...cors,
10205
10249
  "Content-Type": contentType
@@ -10576,34 +10620,34 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10576
10620
  return;
10577
10621
  }
10578
10622
  }
10579
- const resolved = import_path3.default.resolve(baseDir, "." + rel);
10580
- const baseWithSep = baseDir.endsWith(import_path3.default.sep) ? baseDir : baseDir + import_path3.default.sep;
10623
+ const resolved = import_path2.default.resolve(baseDir, "." + rel);
10624
+ const baseWithSep = baseDir.endsWith(import_path2.default.sep) ? baseDir : baseDir + import_path2.default.sep;
10581
10625
  if (!resolved.startsWith(baseWithSep) && resolved !== baseDir) {
10582
10626
  res.writeHead(403);
10583
10627
  res.end("forbidden");
10584
10628
  return;
10585
10629
  }
10586
- import_fs3.default.realpath(resolved, (realErr, realResolved) => {
10630
+ import_fs2.default.realpath(resolved, (realErr, realResolved) => {
10587
10631
  const servePath = realErr ? resolved : realResolved;
10588
- const servePathWithSep = servePath.endsWith(import_path3.default.sep) ? servePath : servePath + import_path3.default.sep;
10632
+ const servePathWithSep = servePath.endsWith(import_path2.default.sep) ? servePath : servePath + import_path2.default.sep;
10589
10633
  if (!realErr) {
10590
10634
  const realBaseWithSep = (() => {
10591
10635
  try {
10592
- const rb = import_fs3.default.realpathSync(baseDir);
10593
- return rb.endsWith(import_path3.default.sep) ? rb : rb + import_path3.default.sep;
10636
+ const rb = import_fs2.default.realpathSync(baseDir);
10637
+ return rb.endsWith(import_path2.default.sep) ? rb : rb + import_path2.default.sep;
10594
10638
  } catch {
10595
10639
  return baseWithSep;
10596
10640
  }
10597
10641
  })();
10598
- if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path3.default.sep !== realBaseWithSep) {
10642
+ if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path2.default.sep !== realBaseWithSep) {
10599
10643
  res.writeHead(403);
10600
10644
  res.end("forbidden");
10601
10645
  return;
10602
10646
  }
10603
10647
  }
10604
- import_fs3.default.stat(servePath, (err, stats) => {
10648
+ import_fs2.default.stat(servePath, (err, stats) => {
10605
10649
  if (err || !stats?.isFile()) {
10606
- const ext2 = import_path3.default.extname(rel).toLowerCase();
10650
+ const ext2 = import_path2.default.extname(rel).toLowerCase();
10607
10651
  if (ext2 && ext2 !== ".html") {
10608
10652
  res.writeHead(404);
10609
10653
  res.end("not found");
@@ -10614,8 +10658,8 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10614
10658
  res.end("not found");
10615
10659
  return;
10616
10660
  }
10617
- const indexPath = import_path3.default.join(baseDir, "index.html");
10618
- import_fs3.default.readFile(indexPath, (err2, data) => {
10661
+ const indexPath = import_path2.default.join(baseDir, "index.html");
10662
+ import_fs2.default.readFile(indexPath, (err2, data) => {
10619
10663
  if (err2) {
10620
10664
  res.writeHead(404);
10621
10665
  res.end("not found");
@@ -10635,7 +10679,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10635
10679
  });
10636
10680
  return;
10637
10681
  }
10638
- const ext = import_path3.default.extname(servePath).toLowerCase();
10682
+ const ext = import_path2.default.extname(servePath).toLowerCase();
10639
10683
  const contentType = HTTP_MIME_TYPES[ext] || "application/octet-stream";
10640
10684
  res.writeHead(200, {
10641
10685
  "Content-Type": contentType,
@@ -10646,7 +10690,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10646
10690
  return;
10647
10691
  }
10648
10692
  if (ext === ".html") {
10649
- import_fs3.default.readFile(servePath, (readErr, data) => {
10693
+ import_fs2.default.readFile(servePath, (readErr, data) => {
10650
10694
  if (readErr) {
10651
10695
  try {
10652
10696
  res.end();
@@ -10660,7 +10704,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
10660
10704
  });
10661
10705
  return;
10662
10706
  }
10663
- const stream = import_fs3.default.createReadStream(servePath);
10707
+ const stream = import_fs2.default.createReadStream(servePath);
10664
10708
  stream.pipe(res);
10665
10709
  stream.on("error", () => {
10666
10710
  try {
@@ -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;
@@ -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 __defProp = Object.defineProperty;
@@ -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
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";