rnxsim 0.1.442 → 0.1.444

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 (73) hide show
  1. package/cli/bin.ts +3 -1
  2. package/cli/cloud-client.ts +153 -17
  3. package/cli/cloud-dispatch.ts +15 -0
  4. package/cli/cloud-session.ts +69 -17
  5. package/cli/commands/box/bundle-plane.ts +71 -0
  6. package/cli/commands/box.ts +274 -115
  7. package/cli/commands/control.ts +1 -137
  8. package/cli/commands/flow.ts +1 -1
  9. package/cli/commands/inspect/list.ts +119 -2
  10. package/cli/commands/inspect.ts +3 -2
  11. package/cli/commands/platform.ts +95 -12
  12. package/cli/commands/reset.ts +7 -3
  13. package/cli/commands/state.ts +7 -3
  14. package/cli/flow-export.ts +55 -0
  15. package/cli/flow-session.ts +0 -47
  16. package/cli/outbound-endpoints.ts +7 -0
  17. package/cli/rnx-in-process.ts +98 -0
  18. package/cli/ws-bridge.ts +30 -0
  19. package/detox/jest-setup-after-env.cjs +4 -0
  20. package/detox/record-block-execution.cjs +78 -0
  21. package/dist-lib/agent-daemon-client.cjs +1 -1
  22. package/dist-lib/agent-events.cjs +1 -1
  23. package/dist-lib/agent-identity.cjs +1 -1
  24. package/dist-lib/agent-sessions.cjs +1 -1
  25. package/dist-lib/attached-projects.cjs +1 -1
  26. package/dist-lib/auth/shared-session.cjs +1 -1
  27. package/dist-lib/backend-origin.cjs +1 -1
  28. package/dist-lib/beta.cjs +1 -1
  29. package/dist-lib/beta.mjs +1 -1
  30. package/dist-lib/bridge-constants.cjs +1 -1
  31. package/dist-lib/bridge-contract-input.cjs +1 -1
  32. package/dist-lib/bridge-contract-input.mjs +1 -1
  33. package/dist-lib/bridge-contract.cjs +1 -1
  34. package/dist-lib/bridge-contract.mjs +1 -1
  35. package/dist-lib/capture-contract.cjs +1 -1
  36. package/dist-lib/capture-contract.mjs +1 -1
  37. package/dist-lib/cli-constants.cjs +1 -1
  38. package/dist-lib/cloud-contract.cjs +1 -1
  39. package/dist-lib/cloud-contract.mjs +1 -1
  40. package/dist-lib/cloud.cjs +1 -1
  41. package/dist-lib/cloud.mjs +1 -1
  42. package/dist-lib/config.cjs +1 -1
  43. package/dist-lib/detox/index.cjs +69 -14
  44. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  45. package/dist-lib/home-paths.cjs +17 -1
  46. package/dist-lib/host/bridge-host.cjs +43 -32
  47. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  48. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  49. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  50. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  51. package/dist-lib/host/websocket-proxy.cjs +1 -1
  52. package/dist-lib/index.cjs +1 -3
  53. package/dist-lib/jump-to-source-babel.cjs +1 -1
  54. package/dist-lib/menu.cjs +10 -19
  55. package/dist-lib/menu.mjs +10 -19
  56. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  57. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  58. package/dist-lib/metro-production-bundle.cjs +1 -1
  59. package/dist-lib/metro-production-bundle.mjs +1 -1
  60. package/dist-lib/metro.cjs +1 -1
  61. package/dist-lib/profiles.cjs +1 -1
  62. package/dist-lib/public-brand.cjs +1 -1
  63. package/dist-lib/react-native-host-modules.cjs +1 -1
  64. package/dist-lib/react-native-host-modules.mjs +1 -1
  65. package/dist-lib/render-mode.cjs +1 -1
  66. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  67. package/dist-lib/sdk.cjs +1 -1
  68. package/dist-lib/sdk.mjs +1 -1
  69. package/dist-lib/skills.cjs +586 -269
  70. package/dist-lib/vite.cjs +1 -1
  71. package/package.json +8 -1
  72. package/src/home-paths.ts +31 -1
  73. package/src/menu.ts +8 -17
@@ -0,0 +1,98 @@
1
+ // running an rnx command inside the calling process instead of spawning the CLI.
2
+ //
3
+ // the parse and the dispatch here are the CLI's own: parseRnxArgs, the command
4
+ // registry behind it, and the same per-command handlers main.ts reaches. what
5
+ // changes is the transport and the boundary. the caller hands in the WsBridge,
6
+ // so one vocabulary and one parser run against three of them: the local ws
7
+ // daemon, a cloud box's commands route, and, inside a box shell in workerd, the
8
+ // Box Durable Object's own command router with no network hop.
9
+ //
10
+ // the boundary is run-rnx.ts: output comes back as a value rather than reaching
11
+ // a terminal, and a command that would have called process.exit throws instead,
12
+ // which is what makes this safe to call in workerd, where process.exit cancels
13
+ // the whole request.
14
+
15
+ import { parseRnxArgs, TOP_LEVEL_RUNTIME_COMMANDS } from './parse-args'
16
+ import { type RnxRunResult, runRnx } from './run-rnx'
17
+ import type { ParsedBridgeCliArgs, WsBridge } from './ws-bridge'
18
+
19
+ // the verbs that reach a simulator through the bridge and nothing else. every
20
+ // other registered command needs the machine rnx is installed on: a device to
21
+ // boot, a browser to open, a credential store, the bridge daemon, or the local
22
+ // filesystem. `state` and `reset` sit outside runInspect but take the same
23
+ // bridge, so they belong here too.
24
+ const IN_PROCESS_COMMANDS: ReadonlySet<string> = new Set([
25
+ ...TOP_LEVEL_RUNTIME_COMMANDS,
26
+ 'state',
27
+ 'reset',
28
+ ])
29
+
30
+ const RUNNABLE = [...IN_PROCESS_COMMANDS].sort().join(', ')
31
+
32
+ export interface RnxInProcessOptions {
33
+ /** the command and its arguments, with no node/script prefix. */
34
+ argv: string[]
35
+ /**
36
+ * the transport the command runs against. it takes the parsed bridge args
37
+ * because the local host builds its bridge out of `--sim`, `--port`, and
38
+ * `--timeout`, while a box ignores all three and answers on its own socket.
39
+ */
40
+ createBridge: (parsed: ParsedBridgeCliArgs) => WsBridge
41
+ }
42
+
43
+ export async function runRnxInProcess(
44
+ options: RnxInProcessOptions,
45
+ ): Promise<RnxRunResult> {
46
+ return runRnx(options.argv, async (argv) => {
47
+ const parsed = parseRnxArgs(argv)
48
+ for (const warning of parsed.warnings) console.error(warning)
49
+ const command = parsed.command
50
+ if (!command || !IN_PROCESS_COMMANDS.has(command)) {
51
+ const named = command ? `rnx ${command}` : 'rnx'
52
+ console.error(
53
+ ` ${named} is not available here; this rnx drives a simulator and has no machine to run on. runs here: ${RUNNABLE}`,
54
+ )
55
+ return 1
56
+ }
57
+
58
+ const simTarget = parsed.globalFlags['sim'] ?? parsed.globalFlags['session']
59
+ const commandArgs =
60
+ typeof simTarget === 'string'
61
+ ? ['--sim', simTarget, ...parsed.commandArgs]
62
+ : parsed.commandArgs
63
+ if (commandArgs.includes('--then')) {
64
+ console.error(
65
+ ' rnx do --then is not available here; a chain runs against a sim connection rather than the bridge. run the actions one at a time.',
66
+ )
67
+ return 1
68
+ }
69
+
70
+ const port = parsed.globalFlags['port']
71
+ const opts = {
72
+ ...(typeof port === 'number' ? { port } : {}),
73
+ createBridge: options.createBridge,
74
+ }
75
+ if (command === 'state') {
76
+ const { runState } = await import('./commands/state')
77
+ return runState(commandArgs, opts)
78
+ }
79
+ if (command === 'reset') {
80
+ const { runReset } = await import('./commands/reset')
81
+ return runReset(commandArgs, opts)
82
+ }
83
+ const { runInspect } = await import('./commands/inspect')
84
+ await runInspect([command, ...commandArgs], { ...opts, verbose: parsed.verbose })
85
+ return 0
86
+ })
87
+ }
88
+
89
+ // the transport contract and the command's own name, re-exported so a host
90
+ // that only wants to register this entry and supply a bridge (a Box Durable
91
+ // Object, say) has one module to import.
92
+ export { rnxPublicBrand } from '../src/public-brand'
93
+ export type {
94
+ BridgeClaimResult,
95
+ BridgeSimInfo,
96
+ ParsedBridgeCliArgs,
97
+ WsBridge,
98
+ } from './ws-bridge'
package/cli/ws-bridge.ts CHANGED
@@ -403,6 +403,26 @@ export interface BridgeSimInfo {
403
403
  meta?: Record<string, unknown>
404
404
  }
405
405
 
406
+ // a lock owner is either a friendly cli label ("active user") or a raw cli
407
+ // identity key ("CLAUDE_CODE_SESSION_ID:<uuid>", "gppid-1234"). keep the list
408
+ // readable by collapsing a "<source>:<value>" identity to a short form that
409
+ // still says which agent holds it.
410
+ export function formatLockOwner(owner: string): string {
411
+ const colon = owner.indexOf(':')
412
+ if (colon <= 0) return owner.length > 24 ? `${owner.slice(0, 21)}…` : owner
413
+ const source = owner.slice(0, colon)
414
+ const value = owner.slice(colon + 1)
415
+ const short = value.length > 12 ? `${value.slice(0, 8)}…` : value
416
+ if (
417
+ source === 'TM_SESSION' ||
418
+ source === 'CLAUDE_CODE_SESSION_ID' ||
419
+ source === 'CODEX_THREAD_ID'
420
+ ) {
421
+ return `agent ${short}`
422
+ }
423
+ return `${source} ${short}`
424
+ }
425
+
406
426
  interface ParseBridgeCliArgsOptions {
407
427
  port?: number
408
428
  commandTimeoutMs?: number
@@ -769,6 +789,16 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
769
789
  }
770
790
  }
771
791
 
792
+ /**
793
+ * how a command reaches a simulator. left out, it resolves the way the host
794
+ * CLI always has: the cloud box route when a box session is set, otherwise the
795
+ * local ws daemon. a box shell passes its own bridge so the same command runs
796
+ * in the calling process against the box's own simulator.
797
+ */
798
+ export interface BridgeTransportOption {
799
+ createBridge?: (parsed: ParsedBridgeCliArgs) => WsBridge
800
+ }
801
+
772
802
  export function createBridgeFromParsed(parsed: ParsedBridgeCliArgs): WsBridge {
773
803
  const cloudBridge = createCloudBridgeForParsed(parsed)
774
804
  if (cloudBridge) return cloudBridge
@@ -11,6 +11,10 @@
11
11
  // force-reaps its tree. registering it here means no suite has to remember an
12
12
  // afterAll of its own.
13
13
 
14
+ // records which test bodies actually ran, so a downstream reader can tell a
15
+ // setup failure from a behavior failure. no-op unless the run asks for it.
16
+ require('./record-block-execution.cjs')
17
+
14
18
  const { cleanup } = require('rnxsim/detox')
15
19
 
16
20
  afterAll(async () => {
@@ -0,0 +1,78 @@
1
+ // producer half of the paired test-block execution contract. jest's own JSON
2
+ // reporter cannot say whether a failed block failed in its body or never got
3
+ // there: a `beforeAll`/`beforeEach` throw and a failed `expect` inside the body
4
+ // produce assertion results identical in status, duration, invocations,
5
+ // numPassingAsserts and retryReasons. only the failure message text differs, and
6
+ // attributing behavior on message text is the fuzzy join this whole bridge
7
+ // exists to remove.
8
+ //
9
+ // so the suite records it directly. this module wraps the globals the
10
+ // conformance catalogs register their blocks with, and appends one line per
11
+ // block whose body actually started, naming how that body finished. a block
12
+ // whose hooks failed produces no line at all, which is what makes a setup loss
13
+ // distinguishable from a behavior failure downstream.
14
+ //
15
+ // the rnx suites get it through `jest-setup-after-env.cjs`, which this preset
16
+ // already loads; the native detox suites name it in `setupFilesAfterEnv`
17
+ // directly. either way it does nothing until CONFORMANCE_BLOCK_EXECUTION_FILE
18
+ // is set, so an unwired run behaves exactly as before.
19
+ //
20
+ // `scripts/lib/paired-conformance-test-outcomes.ts` reads what this writes.
21
+
22
+ const { appendFileSync } = require('node:fs')
23
+ // the global `expect` is not jest's here: detox's core listener overwrites it
24
+ // with its own element matcher on the circus `setup` event, which fires before
25
+ // setup files are required. `@jest/globals` is served by the jest runtime
26
+ // itself and always hands back the same jest expect the runner set `testPath`
27
+ // on, whatever a runner did to the globals.
28
+ const { expect: jestExpect } = require('@jest/globals')
29
+
30
+ const outputFile = process.env.CONFORMANCE_BLOCK_EXECUTION_FILE
31
+
32
+ if (outputFile) {
33
+ const testFile = jestExpect.getState().testPath
34
+
35
+ // a retried block runs its body more than once. numbering the invocations
36
+ // makes the retry explicit, so a reader can take the last attempt instead of
37
+ // guessing which of two identical lines was terminal.
38
+ const attempts = new Map()
39
+
40
+ const record = (title, bodyOutcome) => {
41
+ const attempt = (attempts.get(title) ?? 0) + 1
42
+ attempts.set(title, attempt)
43
+ appendFileSync(
44
+ outputFile,
45
+ `${JSON.stringify({ attempt, bodyOutcome, testFile, title })}\n`,
46
+ )
47
+ }
48
+
49
+ // jest workers each append to the same file. these lines are far below the
50
+ // atomic-append size, so interleaving splits between lines, never inside one.
51
+ const wrap = (raw) => {
52
+ const wrapped = function wrapped(title, body, timeout) {
53
+ if (typeof body !== 'function') return raw(title, body, timeout)
54
+ return raw(
55
+ title,
56
+ async function recordedBody(...args) {
57
+ let bodyOutcome = 'failed'
58
+ try {
59
+ const value = await body.apply(this, args)
60
+ bodyOutcome = 'passed'
61
+ return value
62
+ } finally {
63
+ record(title, bodyOutcome)
64
+ }
65
+ },
66
+ timeout,
67
+ )
68
+ }
69
+ // carries over each/skip/todo/failing/concurrent; `only` is wrapped too so a
70
+ // focused run still records its bodies.
71
+ Object.assign(wrapped, raw)
72
+ if (typeof raw.only === 'function') wrapped.only = wrap(raw.only)
73
+ return wrapped
74
+ }
75
+
76
+ globalThis.it = wrap(globalThis.it)
77
+ globalThis.test = wrap(globalThis.test)
78
+ }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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;
@@ -299,6 +299,16 @@ function assertGpuBrowserCommand(command, runtime = currentRuntime()) {
299
299
  `[reap-browser] Chrome process did not retain the required ${angle} GPU arguments`
300
300
  );
301
301
  }
302
+ for (const name of ["--enable-features=", "--disable-features="]) {
303
+ const lists = args.filter((arg) => arg.startsWith(name)).map((arg) => arg.slice(name.length).split(",").filter(Boolean));
304
+ const kept = new Set(lists.at(-1) ?? []);
305
+ const dropped = lists.slice(0, -1).flat().filter((feature) => !kept.has(feature));
306
+ if (dropped.length > 0) {
307
+ throw new Error(
308
+ `[reap-browser] Chrome keeps only its last ${name.slice(0, -1)} switch, which dropped ${dropped.join(",")}; add them to the merged list in scripts/lib/reap-browser.ts`
309
+ );
310
+ }
311
+ }
302
312
  if (runtime.platform === "darwin" && command.includes("/Applications/Google Chrome.app/")) {
303
313
  throw new Error(
304
314
  "[reap-browser] refused the user's installed Google Chrome; use Playwright channel chromium"
@@ -568,6 +578,46 @@ function gpuChromeArgs(platform = process.platform) {
568
578
  "--ignore-gpu-blocklist"
569
579
  ];
570
580
  }
581
+ var PLAYWRIGHT_DISABLED_FEATURES = [
582
+ "AvoidUnnecessaryBeforeUnloadCheckSync",
583
+ "BoundaryEventDispatchTracksNodeRemoval",
584
+ "DestroyProfileOnBrowserClose",
585
+ "DialMediaRouteProvider",
586
+ "GlobalMediaControls",
587
+ "HttpsUpgrades",
588
+ "LensOverlay",
589
+ "MediaRouter",
590
+ "PaintHolding",
591
+ "ThirdPartyStoragePartitioning",
592
+ "Translate",
593
+ "AutoDeElevate",
594
+ "RenderDocument",
595
+ "OptimizationHints",
596
+ "msForceBrowserSignIn",
597
+ "msEdgeUpdateLaunchServicesPreferredVersion"
598
+ ];
599
+ var PLAYWRIGHT_ENABLED_FEATURES = ["CDPScreenshotNewSurface"];
600
+ var DISABLED_FEATURES = ["NetworkTimeServiceQuerying"];
601
+ function mergeFeatureSwitches(args, enabled = []) {
602
+ const enable = /* @__PURE__ */ new Set([...PLAYWRIGHT_ENABLED_FEATURES, ...enabled]);
603
+ const disable = /* @__PURE__ */ new Set([...PLAYWRIGHT_DISABLED_FEATURES, ...DISABLED_FEATURES]);
604
+ const rest = [];
605
+ for (const arg of args) {
606
+ const match = /^--(enable|disable)-features=(.*)$/.exec(arg);
607
+ if (!match) {
608
+ rest.push(arg);
609
+ continue;
610
+ }
611
+ for (const feature of match[2].split(",")) {
612
+ if (feature) (match[1] === "enable" ? enable : disable).add(feature);
613
+ }
614
+ }
615
+ return [
616
+ ...rest,
617
+ `--enable-features=${[...enable].join(",")}`,
618
+ `--disable-features=${[...disable].join(",")}`
619
+ ];
620
+ }
571
621
  function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
572
622
  const callerArgs = Array.isArray(opts.args) ? opts.args : [];
573
623
  const unsafe = callerArgs.find(isSoftwareRendererArgument);
@@ -608,7 +658,10 @@ function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
608
658
  // com.google.chrome.for.testing, so automation cannot become the target of
609
659
  // Dock open/quit events intended for the user's com.google.Chrome browser.
610
660
  channel: "chromium",
611
- args: [...unmanagedCallerArgs, ...gpuChromeArgs(runtime.platform)],
661
+ args: mergeFeatureSwitches([
662
+ ...unmanagedCallerArgs,
663
+ ...gpuChromeArgs(runtime.platform)
664
+ ]),
612
665
  ignoreDefaultArgs: ignoredDefaults
613
666
  };
614
667
  }
@@ -656,21 +709,23 @@ function softwareChromeLaunchOptions(opts) {
656
709
  }
657
710
  const callerArgs = Array.isArray(opts.args) ? opts.args.map(String) : [];
658
711
  const unmanagedCallerArgs = callerArgs.filter((arg) => {
659
- return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-features=(?:Vulkan|WebGPU)(?:,(?:Vulkan|WebGPU))*$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
712
+ return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
660
713
  });
661
714
  const software = {
662
715
  ...opts,
663
- args: [
664
- ...unmanagedCallerArgs,
665
- "--use-angle=swiftshader",
666
- "--enable-unsafe-swiftshader",
667
- // playwright's bundled software chromium exposes no navigator.gpu without
668
- // these two, and the compositor's only backend is webgpu. emitted here
669
- // rather than per caller so a hosted-linux launch and a local gpu launch
670
- // agree on what a sim needs.
671
- "--enable-unsafe-webgpu",
672
- "--enable-features=Vulkan"
673
- ]
716
+ // playwright's bundled software chromium exposes no navigator.gpu without
717
+ // --enable-unsafe-webgpu plus the Vulkan feature, and the compositor's only
718
+ // backend is webgpu. emitted here rather than per caller so a hosted-linux
719
+ // launch and a local gpu launch agree on what a sim needs.
720
+ args: mergeFeatureSwitches(
721
+ [
722
+ ...unmanagedCallerArgs,
723
+ "--use-angle=swiftshader",
724
+ "--enable-unsafe-swiftshader",
725
+ "--enable-unsafe-webgpu"
726
+ ],
727
+ ["Vulkan"]
728
+ )
674
729
  };
675
730
  delete software.channel;
676
731
  delete software.executablePath;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (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;
@@ -65,6 +65,7 @@ __export(home_paths_exports, {
65
65
  profilesDir: () => profilesDir,
66
66
  readActiveRuntime: () => readActiveRuntime,
67
67
  readDaemonLockfile: () => readDaemonLockfile,
68
+ readDefaultBox: () => readDefaultBox,
68
69
  readDevBridgeLockfiles: () => readDevBridgeLockfiles,
69
70
  readLiveRuntimeVersions: () => readLiveRuntimeVersions,
70
71
  readOrCreateAnonymousId: () => readOrCreateAnonymousId,
@@ -80,6 +81,7 @@ __export(home_paths_exports, {
80
81
  shouldSkipPersistentDaemon: () => shouldSkipPersistentDaemon,
81
82
  writeActiveRuntime: () => writeActiveRuntime,
82
83
  writeDaemonLockfile: () => writeDaemonLockfile,
84
+ writeDefaultBox: () => writeDefaultBox,
83
85
  writeDevBridgeLockfile: () => writeDevBridgeLockfile,
84
86
  writeOnboardingPreferences: () => writeOnboardingPreferences,
85
87
  writePrivacyPreferences: () => writePrivacyPreferences,
@@ -242,6 +244,18 @@ function readOrCreateAnonymousId() {
242
244
  writeSharedConfig({ anonymousId: created });
243
245
  return created;
244
246
  }
247
+ function readDefaultBox() {
248
+ const stored = readSharedConfig().defaultBox;
249
+ if (typeof stored !== "object" || stored === null) return null;
250
+ if (!("boxId" in stored) || typeof stored.boxId !== "string" || !stored.boxId) {
251
+ return null;
252
+ }
253
+ const name = "name" in stored && typeof stored.name === "string" ? stored.name : null;
254
+ return { boxId: stored.boxId, name };
255
+ }
256
+ function writeDefaultBox(box) {
257
+ writeSharedConfig({ defaultBox: box });
258
+ }
245
259
  function runtimeUpgradeNoticePath() {
246
260
  return import_node_path.default.join(rnxHomeDir(), "runtime-upgraded.json");
247
261
  }
@@ -599,6 +613,7 @@ function removeDevBridgeLockfile(owner) {
599
613
  profilesDir,
600
614
  readActiveRuntime,
601
615
  readDaemonLockfile,
616
+ readDefaultBox,
602
617
  readDevBridgeLockfiles,
603
618
  readLiveRuntimeVersions,
604
619
  readOrCreateAnonymousId,
@@ -614,6 +629,7 @@ function removeDevBridgeLockfile(owner) {
614
629
  shouldSkipPersistentDaemon,
615
630
  writeActiveRuntime,
616
631
  writeDaemonLockfile,
632
+ writeDefaultBox,
617
633
  writeDevBridgeLockfile,
618
634
  writeOnboardingPreferences,
619
635
  writePrivacyPreferences,