rnxsim 0.1.499 → 0.1.501

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 (71) hide show
  1. package/README.md +1 -1
  2. package/cli/bridge-flow-runner.ts +6 -2
  3. package/cli/cloud-client.ts +90 -7
  4. package/cli/cloud-dispatch.ts +27 -27
  5. package/cli/cloud-session.ts +61 -6
  6. package/cli/commands/control.ts +33 -31
  7. package/cli/commands/detox.ts +157 -159
  8. package/cli/commands/inspect/core.ts +2 -0
  9. package/cli/commands/platform.ts +170 -48
  10. package/cli/commands/preview.ts +1 -1
  11. package/cli/commands/test.ts +403 -95
  12. package/cli/main.ts +11 -0
  13. package/cli/outbound-endpoints.ts +10 -0
  14. package/cli/ws-bridge.ts +18 -19
  15. package/detox/jest-preset.cjs +1 -6
  16. package/dist-lib/agent-daemon-client.cjs +1 -1
  17. package/dist-lib/agent-events.cjs +1 -1
  18. package/dist-lib/agent-identity.cjs +1 -1
  19. package/dist-lib/agent-sessions.cjs +1 -1
  20. package/dist-lib/attached-projects.cjs +1 -1
  21. package/dist-lib/auth/shared-session.cjs +1 -1
  22. package/dist-lib/backend-origin.cjs +1 -1
  23. package/dist-lib/beta.cjs +1 -1
  24. package/dist-lib/beta.mjs +1 -1
  25. package/dist-lib/bridge-constants.cjs +1 -1
  26. package/dist-lib/bridge-contract-input.cjs +1 -1
  27. package/dist-lib/bridge-contract-input.mjs +1 -1
  28. package/dist-lib/bridge-contract.cjs +1 -1
  29. package/dist-lib/bridge-contract.mjs +1 -1
  30. package/dist-lib/capture-contract.cjs +1 -1
  31. package/dist-lib/capture-contract.mjs +1 -1
  32. package/dist-lib/cli-constants.cjs +1 -1
  33. package/dist-lib/cloud-contract.cjs +7 -1
  34. package/dist-lib/cloud-contract.mjs +5 -1
  35. package/dist-lib/cloud.cjs +1 -1
  36. package/dist-lib/cloud.mjs +1 -1
  37. package/dist-lib/config.cjs +1 -1
  38. package/dist-lib/detox/index.cjs +1 -1
  39. package/dist-lib/detox/jest-preset.cjs +1 -6
  40. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  41. package/dist-lib/home-paths.cjs +1 -1
  42. package/dist-lib/host/bridge-host.cjs +54 -29
  43. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  44. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  45. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  46. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  47. package/dist-lib/host/websocket-proxy.cjs +1 -1
  48. package/dist-lib/index.cjs +52 -22
  49. package/dist-lib/jump-to-source-babel.cjs +1 -1
  50. package/dist-lib/jump-to-source-native.cjs +1 -1
  51. package/dist-lib/menu.cjs +1 -1
  52. package/dist-lib/menu.mjs +1 -1
  53. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  54. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  55. package/dist-lib/metro-production-bundle.cjs +1 -1
  56. package/dist-lib/metro-production-bundle.mjs +1 -1
  57. package/dist-lib/metro.cjs +1 -1
  58. package/dist-lib/profiles.cjs +1 -1
  59. package/dist-lib/public-brand.cjs +1 -1
  60. package/dist-lib/react-native-host-modules.cjs +1 -1
  61. package/dist-lib/react-native-host-modules.mjs +1 -1
  62. package/dist-lib/render-mode.cjs +1 -1
  63. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  64. package/dist-lib/sdk.cjs +7 -8
  65. package/dist-lib/sdk.mjs +7 -8
  66. package/dist-lib/skills.cjs +128 -63
  67. package/dist-lib/vite.cjs +1 -1
  68. package/package.json +1 -1
  69. package/skills/rnx-test/SKILL.md +2 -2
  70. package/src/cloud-contract.ts +2 -0
  71. package/src/sim-client.ts +8 -10
@@ -1,6 +1,6 @@
1
1
  // jest preset for running existing detox suites against sootsim.
2
2
  //
3
- // users drop `preset: 'sootsim/detox/jest-preset'` into their jest config
3
+ // users drop `preset: 'rnxsim/detox'` into their jest config
4
4
  // (or `rnx-detox.config.cjs`) and their `import { by, device, element,
5
5
  // expect, waitFor } from 'detox'` calls resolve to the sootsim driver.
6
6
 
@@ -25,10 +25,5 @@ module.exports = {
25
25
  },
26
26
  moduleNameMapper: {
27
27
  '^detox$': DRIVER_ENTRY,
28
- // shared utils some external detox suites import relatively.
29
- '^\\.\\./utils/navigation$': path.join(PACKAGE_ROOT, 'detox', 'navigation.ts'),
30
- '^\\.\\./utils/colors$': path.join(PACKAGE_ROOT, 'detox', 'colors.ts'),
31
- '^\\./(utils/navigation)$': path.join(PACKAGE_ROOT, 'detox', 'navigation.ts'),
32
- '^\\./(utils/colors)$': path.join(PACKAGE_ROOT, 'detox', 'colors.ts'),
33
28
  },
34
29
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
@@ -26,12 +26,16 @@ __export(cloud_contract_exports, {
26
26
  RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES: () => RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
27
27
  RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES: () => RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
28
28
  RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES,
29
+ RNX_CLOUD_TEST_FILES_MAX_BYTES: () => RNX_CLOUD_TEST_FILES_MAX_BYTES,
30
+ RNX_CLOUD_TEST_FILES_MAX_COUNT: () => RNX_CLOUD_TEST_FILES_MAX_COUNT,
29
31
  isRnxCloudCommandType: () => isRnxCloudCommandType
30
32
  });
31
33
  module.exports = __toCommonJS(cloud_contract_exports);
32
34
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
33
35
  var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
34
36
  var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
37
+ var RNX_CLOUD_TEST_FILES_MAX_COUNT = 256;
38
+ var RNX_CLOUD_TEST_FILES_MAX_BYTES = 5e5;
35
39
  var RNX_CLOUD_COMMAND_TYPES = Object.freeze([
36
40
  "state",
37
41
  "query",
@@ -61,5 +65,7 @@ function isRnxCloudCommandType(value) {
61
65
  RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
62
66
  RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
63
67
  RNX_CLOUD_MAX_ARTIFACT_BYTES,
68
+ RNX_CLOUD_TEST_FILES_MAX_BYTES,
69
+ RNX_CLOUD_TEST_FILES_MAX_COUNT,
64
70
  isRnxCloudCommandType
65
71
  });
@@ -1,9 +1,11 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
5
5
  var RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256;
6
6
  var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
7
+ var RNX_CLOUD_TEST_FILES_MAX_COUNT = 256;
8
+ var RNX_CLOUD_TEST_FILES_MAX_BYTES = 5e5;
7
9
  var RNX_CLOUD_COMMAND_TYPES = Object.freeze([
8
10
  "state",
9
11
  "query",
@@ -32,5 +34,7 @@ export {
32
34
  RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES,
33
35
  RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES,
34
36
  RNX_CLOUD_MAX_ARTIFACT_BYTES,
37
+ RNX_CLOUD_TEST_FILES_MAX_BYTES,
38
+ RNX_CLOUD_TEST_FILES_MAX_COUNT,
35
39
  isRnxCloudCommandType
36
40
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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,6 +1,6 @@
1
1
  // jest preset for running existing detox suites against sootsim.
2
2
  //
3
- // users drop `preset: 'sootsim/detox/jest-preset'` into their jest config
3
+ // users drop `preset: 'rnxsim/detox'` into their jest config
4
4
  // (or `rnx-detox.config.cjs`) and their `import { by, device, element,
5
5
  // expect, waitFor } from 'detox'` calls resolve to the sootsim driver.
6
6
 
@@ -25,10 +25,5 @@ module.exports = {
25
25
  },
26
26
  moduleNameMapper: {
27
27
  '^detox$': DRIVER_ENTRY,
28
- // shared utils some external detox suites import relatively.
29
- '^\\.\\./utils/navigation$': path.join(PACKAGE_ROOT, 'detox', 'navigation.ts'),
30
- '^\\.\\./utils/colors$': path.join(PACKAGE_ROOT, 'detox', 'colors.ts'),
31
- '^\\./(utils/navigation)$': path.join(PACKAGE_ROOT, 'detox', 'navigation.ts'),
32
- '^\\./(utils/colors)$': path.join(PACKAGE_ROOT, 'detox', 'colors.ts'),
33
28
  },
34
29
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
@@ -3466,7 +3466,10 @@ function createCloudSession(input) {
3466
3466
  simId: input.simId.trim(),
3467
3467
  apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim()),
3468
3468
  claimId: input.claimId.trim(),
3469
- token: input.token
3469
+ token: input.token,
3470
+ ...input.platform ? { platform: input.platform } : {},
3471
+ ...input.device?.trim() ? { device: input.device.trim() } : {},
3472
+ ...input.artifact ? { artifact: input.artifact } : {}
3470
3473
  };
3471
3474
  if (!session.boxId || !session.boxToken || !session.simId || !session.claimId || !session.token) {
3472
3475
  throw new Error("cloud session requires box, simulator, origin, claim, and tokens");
@@ -3487,26 +3490,6 @@ var init_cloud_session = __esm({
3487
3490
  });
3488
3491
 
3489
3492
  // cli/commands/detect.ts
3490
- function findProjectRoot(cwd) {
3491
- let dir = cwd;
3492
- while (true) {
3493
- if ((0, import_fs2.existsSync)((0, import_path2.join)(dir, "turbo.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "nx.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "lerna.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "pnpm-workspace.yaml"))) {
3494
- return dir;
3495
- }
3496
- const pkgPath = (0, import_path2.join)(dir, "package.json");
3497
- if ((0, import_fs2.existsSync)(pkgPath)) {
3498
- try {
3499
- const pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf8"));
3500
- if (pkg.workspaces) return dir;
3501
- } catch {
3502
- }
3503
- }
3504
- const parent = (0, import_path2.dirname)(dir);
3505
- if (parent === dir) break;
3506
- dir = parent;
3507
- }
3508
- return cwd;
3509
- }
3510
3493
  function detectFramework(deps) {
3511
3494
  if (deps.one) return "one";
3512
3495
  if (deps.expo) return "expo";
@@ -3783,9 +3766,28 @@ function searchMetroAssetDest(bundlePath, descriptors) {
3783
3766
  (0, import_node_path15.resolve)(bundleDirectory, "..", "assets")
3784
3767
  ];
3785
3768
  const cwd = process.cwd();
3786
- if (detectProject(cwd)?.hasMetroConfig) {
3787
- const root = findProjectRoot(cwd);
3788
- candidates.push((0, import_node_path15.join)(root, "dist"), (0, import_node_path15.join)(root, "build"));
3769
+ let projectDirectory = null;
3770
+ for (const start of [bundleDirectory, cwd]) {
3771
+ let directory = (0, import_node_path15.resolve)(start);
3772
+ while (true) {
3773
+ if (detectProject(directory)?.hasMetroConfig) {
3774
+ projectDirectory = directory;
3775
+ break;
3776
+ }
3777
+ const parent = (0, import_node_path15.dirname)(directory);
3778
+ if (parent === directory) break;
3779
+ directory = parent;
3780
+ }
3781
+ if (projectDirectory) break;
3782
+ }
3783
+ if (projectDirectory) {
3784
+ candidates.push(
3785
+ (0, import_node_path15.join)(projectDirectory, "assets"),
3786
+ (0, import_node_path15.join)(projectDirectory, "dist"),
3787
+ (0, import_node_path15.join)(projectDirectory, "dist", "assets"),
3788
+ (0, import_node_path15.join)(projectDirectory, "build"),
3789
+ (0, import_node_path15.join)(projectDirectory, "build", "assets")
3790
+ );
3789
3791
  }
3790
3792
  const searched = [];
3791
3793
  const holders = [];
@@ -3982,6 +3984,10 @@ function readCreateResponse(value, expectedBytes, expectedSha256) {
3982
3984
  };
3983
3985
  }
3984
3986
  async function createCloudBox(options) {
3987
+ const platform = options.platform ?? "ios";
3988
+ if (platform === "android") {
3989
+ throw new UnsupportedRemoteHostError("android", "nano");
3990
+ }
3985
3991
  const apiOrigin = resolveCloudOrigin(options.apiOrigin);
3986
3992
  const artifact = await produceCloudArtifact(options.bundlePath);
3987
3993
  const boxName = options.boxName?.trim();
@@ -3989,7 +3995,7 @@ async function createCloudBox(options) {
3989
3995
  authorization: options.authorization,
3990
3996
  "x-rnx-box-size": "nano",
3991
3997
  "x-rnx-artifact-sha256": artifact.sha256,
3992
- "x-rnx-platform": "ios",
3998
+ "x-rnx-platform": platform,
3993
3999
  "x-rnx-device": options.device,
3994
4000
  ...options.accountId ? { "x-rnx-account-id": options.accountId } : null,
3995
4001
  ...boxName ? { "x-rnx-box-name": boxName } : null
@@ -4035,7 +4041,13 @@ async function createCloudBox(options) {
4035
4041
  simId: created.receipt.simulator.simId,
4036
4042
  apiOrigin,
4037
4043
  claimId: created.receipt.simulator.claim.id,
4038
- token: created.simulatorToken
4044
+ token: created.simulatorToken,
4045
+ platform,
4046
+ device: options.device,
4047
+ artifact: {
4048
+ sha256: artifact.sha256,
4049
+ bytes: artifact.bytes.length
4050
+ }
4039
4051
  });
4040
4052
  return {
4041
4053
  receipt: created.receipt,
@@ -4045,7 +4057,7 @@ async function createCloudBox(options) {
4045
4057
  warnings: artifact.warnings
4046
4058
  };
4047
4059
  }
4048
- var import_node_crypto5, import_node_fs14, import_node_path15, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4060
+ var import_node_crypto5, import_node_fs14, import_node_path15, UnsupportedRemoteHostError, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS;
4049
4061
  var init_cloud_client = __esm({
4050
4062
  "cli/cloud-client.ts"() {
4051
4063
  "use strict";
@@ -4063,9 +4075,22 @@ var init_cloud_client = __esm({
4063
4075
  init_auth();
4064
4076
  init_cloud_session();
4065
4077
  init_detect();
4078
+ UnsupportedRemoteHostError = class extends Error {
4079
+ code = "unsupported_host";
4080
+ platform;
4081
+ host;
4082
+ constructor(platform, host, message) {
4083
+ super(
4084
+ message ?? `rnx remote ${platform} does not support --${host}: rnxsim/cloud only creates iOS simulators`
4085
+ );
4086
+ this.name = "UnsupportedRemoteHostError";
4087
+ this.platform = platform;
4088
+ this.host = host;
4089
+ }
4090
+ };
4066
4091
  DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
4067
4092
  MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
4068
- REMOTE_COMMAND = "rnx ios --remote";
4093
+ REMOTE_COMMAND = "rnx remote";
4069
4094
  MAX_ASSET_DEST_FILES = 25e3;
4070
4095
  ACCOUNT_CHOICE_REFUSALS = /* @__PURE__ */ new Set([
4071
4096
  "accountId is required",
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
@@ -297,7 +297,10 @@ function createCloudSession(input) {
297
297
  simId: input.simId.trim(),
298
298
  apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim()),
299
299
  claimId: input.claimId.trim(),
300
- token: input.token
300
+ token: input.token,
301
+ ...input.platform ? { platform: input.platform } : {},
302
+ ...input.device?.trim() ? { device: input.device.trim() } : {},
303
+ ...input.artifact ? { artifact: input.artifact } : {}
301
304
  };
302
305
  if (!session.boxId || !session.boxToken || !session.simId || !session.claimId || !session.token) {
303
306
  throw new Error("cloud session requires box, simulator, origin, claim, and tokens");
@@ -310,7 +313,10 @@ function createCloudBoxSession(input) {
310
313
  service: "box",
311
314
  boxId: input.boxId.trim(),
312
315
  boxToken: input.boxToken,
313
- apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim())
316
+ apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim()),
317
+ ...input.platform ? { platform: input.platform } : {},
318
+ ...input.device?.trim() ? { device: input.device.trim() } : {},
319
+ ...input.artifact ? { artifact: input.artifact } : {}
314
320
  };
315
321
  if (!session.boxId || !session.boxToken) {
316
322
  throw new Error("cloud box session requires a box, an origin, and a box token");
@@ -341,9 +347,22 @@ function parseCloudSession(encoded) {
341
347
  if (typeof boxId !== "string" || typeof boxToken !== "string" || typeof apiOrigin !== "string") {
342
348
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
343
349
  }
350
+ const platform = parsed.platform === "ios" || parsed.platform === "android" ? parsed.platform : void 0;
351
+ const device = typeof parsed.device === "string" ? parsed.device : void 0;
352
+ const artifact = isRecord(parsed.artifact) && typeof parsed.artifact.sha256 === "string" ? {
353
+ sha256: parsed.artifact.sha256,
354
+ bytes: typeof parsed.artifact.bytes === "number" ? parsed.artifact.bytes : void 0
355
+ } : void 0;
344
356
  try {
345
357
  if (parsed.service === "box") {
346
- return createCloudBoxSession({ boxId, boxToken, apiOrigin });
358
+ return createCloudBoxSession({
359
+ boxId,
360
+ boxToken,
361
+ apiOrigin,
362
+ platform,
363
+ device,
364
+ artifact
365
+ });
347
366
  }
348
367
  const simId = parsed.simId;
349
368
  const claimId = parsed.claimId;
@@ -351,7 +370,17 @@ function parseCloudSession(encoded) {
351
370
  if (parsed.service !== "sim" || typeof simId !== "string" || typeof claimId !== "string" || typeof token !== "string") {
352
371
  throw new Error("unreadable cloud session");
353
372
  }
354
- return createCloudSession({ boxId, boxToken, simId, apiOrigin, claimId, token });
373
+ return createCloudSession({
374
+ boxId,
375
+ boxToken,
376
+ simId,
377
+ apiOrigin,
378
+ claimId,
379
+ token,
380
+ platform,
381
+ device,
382
+ artifact
383
+ });
355
384
  } catch {
356
385
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
357
386
  }
@@ -1065,15 +1094,17 @@ function createBridge(wsPort, opts = {}) {
1065
1094
  let noticedTarget = false;
1066
1095
  const hostPidBySimId = /* @__PURE__ */ new Map();
1067
1096
  const lineageLookupBySimId = /* @__PURE__ */ new Map();
1068
- function pickReloadedSuccessor(sims, retiredSimId) {
1097
+ function pickReloadedTarget(sims, retiredSimId) {
1069
1098
  const pinnedHostPid = hostPidBySimId.get(retiredSimId);
1070
1099
  if (pinnedHostPid === void 0) return null;
1071
- const successors = (Array.isArray(sims) ? sims : []).filter(
1072
- (sim) => sim.id !== retiredSimId && sim.readyState === "open" && sim.meta?.sootsimHostPid === pinnedHostPid
1100
+ const matches = (Array.isArray(sims) ? sims : []).filter(
1101
+ (sim) => sim.readyState === "open" && sim.meta?.sootsimHostPid === pinnedHostPid
1073
1102
  );
1074
- if (successors.length !== 1) return null;
1075
- hostPidBySimId.set(successors[0].id, pinnedHostPid);
1076
- return successors[0].id;
1103
+ const restored = matches.find((sim) => sim.id === retiredSimId);
1104
+ if (restored) return restored.id;
1105
+ if (matches.length !== 1) return null;
1106
+ hostPidBySimId.set(matches[0].id, pinnedHostPid);
1107
+ return matches[0].id;
1077
1108
  }
1078
1109
  function maybeNoticeTarget(cmdType, simId) {
1079
1110
  if (noticedTarget) return;
@@ -1191,7 +1222,7 @@ function createBridge(wsPort, opts = {}) {
1191
1222
  const message = error instanceof Error ? error.message : String(error);
1192
1223
  const missingSimMessage = `no sim connected with id ${sentSimId}`;
1193
1224
  if (opts.simIdSource !== "flag" && sentSimId && cmd.simId === void 0 && (message === missingSimMessage || message.startsWith(`${missingSimMessage};`))) {
1194
- const successor = pickReloadedSuccessor(
1225
+ const successor = pickReloadedTarget(
1195
1226
  await sendOnce(void 0, { type: "bridge:list-sims" }),
1196
1227
  sentSimId
1197
1228
  );
@@ -1217,10 +1248,10 @@ function createBridge(wsPort, opts = {}) {
1217
1248
  },
1218
1249
  // a caller holding its own pinned sim id (a flow runner sets simId on every
1219
1250
  // command, so it never reaches the pin-following path in send) asks here
1220
- // after a reload retires that id. null means nothing proves what replaced
1221
- // it, and the caller must fail rather than guess.
1251
+ // after a reload retires its socket. the page can reconnect under a new id
1252
+ // or restore the old id; null means no unique same-host target exists.
1222
1253
  async resolveReloadedSim(retiredSimId) {
1223
- return pickReloadedSuccessor(await this.listSims(), retiredSimId);
1254
+ return pickReloadedTarget(await this.listSims(), retiredSimId);
1224
1255
  },
1225
1256
  async focusSim(simId) {
1226
1257
  return this.send({ type: "focus", simId });
@@ -1739,6 +1770,7 @@ async function inspectWaitReady(bridge, timeoutMs = 2e4, options = {}) {
1739
1770
  result = await bridge.send(
1740
1771
  {
1741
1772
  type: "waitFor",
1773
+ ...options.simId ? { simId: options.simId } : {},
1742
1774
  waitForOptions: { condition: { type: "ready" }, timeoutMs }
1743
1775
  },
1744
1776
  { timeoutMs: timeoutMs + 1e3 }
@@ -2642,21 +2674,19 @@ var SimClient = class {
2642
2674
  `sim ${this.simId} reported no URL to derive the shell from`
2643
2675
  );
2644
2676
  }
2645
- const nextUrl = buildSimOpenUrl(currentUrl, target);
2646
- const expected = new URL(nextUrl);
2677
+ const nextUrl = new URL(buildSimOpenUrl(currentUrl, target));
2678
+ const token = `sim-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
2679
+ nextUrl.searchParams.set("inspectOpen", token);
2647
2680
  await this.send({
2648
2681
  type: "evaluate",
2649
- code: `window.location.href = ${JSON.stringify(nextUrl)}`
2682
+ code: `window.location.href = ${JSON.stringify(nextUrl.toString())}`
2650
2683
  });
2651
2684
  const deadline = Date.now() + (opts.timeoutMs ?? 3e4);
2652
2685
  while (Date.now() < deadline) {
2653
2686
  await sleep(250);
2654
2687
  try {
2655
2688
  const { url } = await inspectUrl(this);
2656
- const current = new URL(url);
2657
- if (current.pathname === expected.pathname && current.searchParams.get("open") === expected.searchParams.get("open")) {
2658
- return;
2659
- }
2689
+ if (new URL(url).searchParams.get("inspectOpen") === token) return;
2660
2690
  } catch {
2661
2691
  }
2662
2692
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.499 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;