rnxsim 0.1.380 → 0.1.382

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 (138) hide show
  1. package/README.md +43 -26
  2. package/cli/app-fonts.ts +1 -1
  3. package/cli/bin.ts +118 -26
  4. package/cli/bridge-diagnostics.ts +1 -1
  5. package/cli/bridge-flow-runner.ts +9 -9
  6. package/cli/browser-evals.ts +3 -3
  7. package/cli/cli-update.ts +261 -0
  8. package/cli/cloud-client.ts +407 -0
  9. package/cli/cloud-dispatch.ts +165 -0
  10. package/cli/cloud-session.ts +156 -0
  11. package/cli/command-contract.ts +2 -2
  12. package/cli/command-registry.ts +9 -0
  13. package/cli/commands/agent-wrapper.ts +4 -4
  14. package/cli/commands/agent.ts +3 -3
  15. package/cli/commands/box/checkout-plane.ts +16 -8
  16. package/cli/commands/box/rnx-command.ts +2 -2
  17. package/cli/commands/box/search-command.ts +2 -2
  18. package/cli/commands/box.ts +123 -70
  19. package/cli/commands/config.ts +3 -2
  20. package/cli/commands/control.ts +6 -6
  21. package/cli/commands/cpu-profile.ts +2 -2
  22. package/cli/commands/daemon.ts +7 -7
  23. package/cli/commands/debug.ts +2 -2
  24. package/cli/commands/detox.ts +7 -7
  25. package/cli/commands/diagnose.ts +1 -1
  26. package/cli/commands/electron.ts +1 -1
  27. package/cli/commands/film.ts +1 -1
  28. package/cli/commands/flow.ts +4 -4
  29. package/cli/commands/inspect/core.ts +58 -7
  30. package/cli/commands/inspect/env.ts +5 -3
  31. package/cli/commands/inspect/shared.ts +2 -1
  32. package/cli/commands/inspect/wait-event.ts +1 -1
  33. package/cli/commands/inspect/wait-ready.ts +15 -5
  34. package/cli/commands/inspect.ts +31 -9
  35. package/cli/commands/install-desktop.ts +2 -2
  36. package/cli/commands/maestro.ts +3 -3
  37. package/cli/commands/permissions.ts +1 -1
  38. package/cli/commands/platform.ts +91 -0
  39. package/cli/commands/record.ts +3 -3
  40. package/cli/commands/report-issue.ts +1 -1
  41. package/cli/commands/runtime.ts +1 -1
  42. package/cli/commands/screenshot-mode.ts +1 -1
  43. package/cli/commands/screenshot.ts +25 -0
  44. package/cli/commands/serve.ts +1 -1
  45. package/cli/commands/skills.ts +1 -1
  46. package/cli/commands/timeline.ts +1 -1
  47. package/cli/commands/upgrade.ts +8 -34
  48. package/cli/commands/upload.ts +3 -3
  49. package/cli/commands/version.ts +14 -3
  50. package/cli/commands/what-happened.ts +2 -2
  51. package/cli/current-sim.ts +43 -30
  52. package/cli/desktop-companion.ts +1 -1
  53. package/cli/drivers/electron.ts +1 -1
  54. package/cli/drivers/playwright.ts +3 -3
  55. package/cli/drivers/types.ts +4 -4
  56. package/cli/flow-file.ts +3 -3
  57. package/cli/help-core.ts +18 -11
  58. package/cli/hidden-runtime-alias.ts +1 -1
  59. package/cli/hints.ts +2 -2
  60. package/cli/maestro-js.ts +2 -2
  61. package/cli/outbound-endpoints.ts +40 -6
  62. package/cli/parse-args.ts +1 -1
  63. package/cli/registry.ts +1 -1
  64. package/cli/resolve-assets.ts +2 -2
  65. package/cli/secure-file.ts +31 -0
  66. package/cli/shell-init.ts +98 -0
  67. package/cli/ws-bridge.ts +18 -8
  68. package/detox/expectations.ts +1 -1
  69. package/detox/gestures.ts +3 -3
  70. package/detox/index.ts +3 -3
  71. package/dist-lib/agent-daemon-client.cjs +1 -1
  72. package/dist-lib/agent-events.cjs +1 -1
  73. package/dist-lib/agent-identity.cjs +1 -1
  74. package/dist-lib/agent-sessions.cjs +1 -1
  75. package/dist-lib/attached-projects.cjs +1 -1
  76. package/dist-lib/auth/shared-session.cjs +1 -1
  77. package/dist-lib/backend-origin.cjs +1 -1
  78. package/dist-lib/beta.cjs +1 -1
  79. package/dist-lib/beta.mjs +1 -1
  80. package/dist-lib/bridge-constants.cjs +1 -1
  81. package/dist-lib/bridge-contract-input.cjs +15 -8
  82. package/dist-lib/bridge-contract-input.mjs +15 -8
  83. package/dist-lib/bridge-contract.cjs +1 -1
  84. package/dist-lib/bridge-contract.mjs +1 -1
  85. package/dist-lib/capture-contract.cjs +107 -0
  86. package/dist-lib/capture-contract.mjs +80 -0
  87. package/dist-lib/cli-constants.cjs +1 -1
  88. package/dist-lib/cloud-contract.cjs +32 -0
  89. package/dist-lib/cloud-contract.mjs +7 -0
  90. package/dist-lib/config.cjs +1 -1
  91. package/dist-lib/detox/index.cjs +4 -4
  92. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  93. package/dist-lib/home-paths.cjs +9 -1
  94. package/dist-lib/host/bridge-host.cjs +15 -10
  95. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  96. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  97. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  98. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  99. package/dist-lib/host/websocket-proxy.cjs +1 -1
  100. package/dist-lib/index.cjs +248 -73
  101. package/dist-lib/jump-to-source-babel.cjs +1 -1
  102. package/dist-lib/menu.cjs +1 -1
  103. package/dist-lib/menu.mjs +1 -1
  104. package/dist-lib/metro-production-bundle.cjs +1 -1
  105. package/dist-lib/metro-production-bundle.mjs +1 -1
  106. package/dist-lib/metro.cjs +1 -1
  107. package/dist-lib/profiles.cjs +1 -1
  108. package/dist-lib/public-brand.cjs +1 -1
  109. package/dist-lib/react-native-host-modules.cjs +1 -1
  110. package/dist-lib/react-native-host-modules.mjs +1 -1
  111. package/dist-lib/render-mode.cjs +1 -1
  112. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  113. package/dist-lib/sdk.cjs +44 -6
  114. package/dist-lib/sdk.mjs +44 -6
  115. package/dist-lib/skills.cjs +435 -155
  116. package/dist-lib/vite.cjs +1 -1
  117. package/package.json +21 -5
  118. package/scripts/dev-server-scanner.ts +3 -3
  119. package/skills/contrast/SKILL.md +1 -1
  120. package/skills/rnx-perf/SKILL.md +68 -52
  121. package/src/app-url.ts +2 -3
  122. package/src/bridge-contract-input.ts +17 -6
  123. package/src/bridge-contract.ts +25 -4
  124. package/src/capture-contract.ts +423 -0
  125. package/src/cloud-contract.ts +15 -0
  126. package/src/home-paths.ts +9 -3
  127. package/src/host/agent-host.ts +1 -1
  128. package/src/host/bridge-host.ts +13 -11
  129. package/src/host/plane-host.ts +2 -2
  130. package/src/index.ts +21 -0
  131. package/src/native-dev-bundle-url.ts +2 -2
  132. package/src/screenshots/orchestrate.ts +1 -1
  133. package/src/screenshots/org-deck.ts +1 -1
  134. package/src/settings-bundle.ts +1 -1
  135. package/src/sim-client.ts +4 -0
  136. package/src/vite-plugin-one.ts +2 -2
  137. package/src/vite-plugin.ts +1 -1
  138. package/cli/commands/box/cloud-box.ts +0 -294
package/cli/ws-bridge.ts CHANGED
@@ -1,10 +1,10 @@
1
- // sootsim CLI ↔ sim WS bridge
1
+ // rnx CLI ↔ sim WS bridge
2
2
  //
3
3
  // the rnx runtime opens a WebSocket server (default port 7668) that
4
4
  // accepts JSON commands like `{ type: 'evaluate', code: 'window.__sootsimTest.getNodeCount()' }`
5
5
  // or `{ type: 'call', path: 'SootSim.bridges.mainShell.launchApp', args: ['photos'] }`
6
6
  // and responds with `{ id, result }` or `{ id, error }`. CLI commands use
7
- // this to drive a running sootsim instance from the terminal.
7
+ // this to drive a running rnx instance from the terminal.
8
8
 
9
9
  import fs from 'node:fs'
10
10
  import path from 'node:path'
@@ -22,7 +22,13 @@ import {
22
22
  rnxHomeDir,
23
23
  type DevBridgeLockfile,
24
24
  } from '../src/home-paths'
25
- import { clearCurrentSimId, getCliIdentity, readCurrentSimId } from './current-sim'
25
+ import { createCloudBridgeForParsed } from './cloud-client'
26
+ import {
27
+ clearCurrentSimId,
28
+ getCliIdentity,
29
+ readCurrentSim,
30
+ readCurrentSimId,
31
+ } from './current-sim'
26
32
 
27
33
  // --- bridge world resolution ---------------------------------------------
28
34
  //
@@ -279,6 +285,7 @@ export function printBridgeWorldNotice(
279
285
  }
280
286
 
281
287
  export interface WsBridge {
288
+ readonly plane?: 'local' | 'cloud'
282
289
  // `opts.timeoutMs` overrides the bridge-wide commandTimeoutMs for a single
283
290
  // call — used for fast readiness probes so a dead/unresponsive sim fails in
284
291
  // seconds instead of stalling the full command timeout.
@@ -423,7 +430,7 @@ export function parseBridgeCliArgs(
423
430
  continue
424
431
  }
425
432
  // `--sim` is the canonical target flag; `--session` / `--tab` are
426
- // documented aliases (CLAUDE.md, the SootSim agent skills, and engine docs all
433
+ // documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
427
434
  // say `--session <id>`). without these aliases an agent following the docs
428
435
  // would have `--session ef` silently ignored and get the *currently
429
436
  // pinned* sim's tree instead — wrong-app data with no error. accept the
@@ -465,9 +472,9 @@ export function parseBridgeCliArgs(
465
472
  }
466
473
 
467
474
  if (!simId) {
468
- const savedSimId = readCurrentSimId()
469
- if (savedSimId) {
470
- simId = savedSimId.trim() || undefined
475
+ const savedSim = readCurrentSim()
476
+ if (savedSim) {
477
+ simId = savedSim.simId.trim() || undefined
471
478
  simIdSource = 'saved'
472
479
  }
473
480
  }
@@ -601,6 +608,7 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
601
608
  })
602
609
 
603
610
  return {
611
+ plane: 'local',
604
612
  async send(cmd, callOpts) {
605
613
  // NOTE: `opts` (the createBridge closure arg) carries simId; do not
606
614
  // shadow it with the per-call arg.
@@ -711,6 +719,8 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
711
719
  }
712
720
 
713
721
  export function createBridgeFromParsed(parsed: ParsedBridgeCliArgs): WsBridge {
722
+ const cloudBridge = createCloudBridgeForParsed(parsed)
723
+ if (cloudBridge) return cloudBridge
714
724
  return createBridge(parsed.wsPort, {
715
725
  commandTimeoutMs: parsed.commandTimeoutMs,
716
726
  simId: parsed.simId,
@@ -792,7 +802,7 @@ export async function checkSimHealth(
792
802
  }
793
803
 
794
804
  /**
795
- * Convenience: run arbitrary JavaScript in the sootsim page and return the
805
+ * Convenience: run arbitrary JavaScript in the rnx page and return the
796
806
  * result. Hides the `type: 'evaluate'` message shape. Read-only by default —
797
807
  * pass `{ acquireLock: true }` when the eval mutates user-facing state so
798
808
  * the server takes/refreshes the cli lease and blocks concurrent agents.
@@ -5,7 +5,7 @@
5
5
  import { dragScrollNode } from './gestures'
6
6
  import type { SootSimElement } from './element-types'
7
7
  import type { Matcher } from './matchers'
8
- import type { SootSimNodeInfo } from '@sootsim/globals'
8
+ import type { SootSimNodeInfo } from '@rnx/globals'
9
9
  import type { Page } from 'playwright'
10
10
 
11
11
  type FindFn = (matcher: Matcher) => Promise<any>
package/detox/gestures.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { pollUntil } from '../src/poll-until'
2
- // pull in @sootsim/globals so window.__sootsimTest and
2
+ // pull in @rnx/globals so window.__sootsimTest and
3
3
  // window.__sootsimFindInteractiveCanvas are typed inside page.evaluate
4
4
  // bodies. all sootsim-namespaced globals are declared canonically there —
5
- // add new entries to packages/sootsim-globals/src/index.ts, not here.
6
- import type {} from '@sootsim/globals'
5
+ // add new entries to packages/rnx-globals/src/index.ts, not here.
6
+ import type {} from '@rnx/globals'
7
7
  import type { Page } from 'playwright'
8
8
 
9
9
  // shape of the surface-metrics bridge response we care about. the bridge
package/detox/index.ts CHANGED
@@ -1427,8 +1427,8 @@ export const device = {
1427
1427
  },
1428
1428
 
1429
1429
  // record the SootSim canvas via the engine's headless recorder
1430
- // (window.__sootsimRecorder — @sootsim/plugin-recording). this is the
1431
- // SAME code path `sootsim record video` drives, NOT the rail-button
1430
+ // (window.__sootsimRecorder — @rnx/plugin-recording). this is the
1431
+ // SAME code path `rnx record video` drives, NOT the rail-button
1432
1432
  // path (SootSim.bridges.startRecording wires the dialog state machine
1433
1433
  // and never stashes the resulting blob into __sootsimRecorder.lastBlob,
1434
1434
  // which is what getBlobBase64 streams from).
@@ -1471,7 +1471,7 @@ export const device = {
1471
1471
  },
1472
1472
 
1473
1473
  // stop the headless recorder, stream the resulting blob in chunks (same
1474
- // protocol as `sootsim record`), and write the webm to outPath.
1474
+ // protocol as `rnx record`), and write the webm to outPath.
1475
1475
  async stopAndSaveBridgeRecording(outPath: string): Promise<string> {
1476
1476
  const page = getPage()
1477
1477
  const stopResult = await page.evaluate(async () => {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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;
@@ -197,8 +197,10 @@ function parseStateOptions(value) {
197
197
  const input = recordValue(value, "state");
198
198
  const route = optionalBoolean(input, "route", "state");
199
199
  const errors = optionalBoolean(input, "errors", "state");
200
+ const logs = optionalBoolean(input, "logs", "state");
200
201
  const depth = optionalNumber(input, "depth", "state");
201
202
  const errorLimit = optionalNumber(input, "errorLimit", "state");
203
+ const logLimit = optionalNumber(input, "logLimit", "state");
202
204
  const layers = input.layers === void 0 ? void 0 : stringValue(input.layers, "state.layers");
203
205
  if (layers !== void 0 && layers !== "full" && layers !== "tenant" && layers !== "shell") {
204
206
  return validationFailure("state.layers", "must be full, tenant, or shell");
@@ -208,9 +210,11 @@ function parseStateOptions(value) {
208
210
  tree: optionalBoolean(input, "tree", "state") ?? true,
209
211
  ...route === void 0 ? {} : { route },
210
212
  ...errors === void 0 ? {} : { errors },
213
+ ...logs === void 0 ? {} : { logs },
211
214
  ...depth === void 0 ? {} : { depth },
212
215
  ...layers === void 0 ? {} : { layers },
213
- ...errorLimit === void 0 ? {} : { errorLimit }
216
+ ...errorLimit === void 0 ? {} : { errorLimit },
217
+ ...logLimit === void 0 ? {} : { logLimit }
214
218
  };
215
219
  }
216
220
  function parseSemanticSelector(value, path) {
@@ -257,15 +261,18 @@ function parseSemanticQuery(value) {
257
261
  }
258
262
  return validationFailure("query.kind", "must be tree, find, or count");
259
263
  }
260
- function parseSemanticResolveSelector(value) {
261
- const selector = recordValue(value, "selector");
264
+ function semanticResolveSelector(value, path) {
265
+ const selector = recordValue(value, path);
262
266
  if (selector.testID !== void 0) {
263
- return { testID: stringValue(selector.testID, "selector.testID") };
267
+ return { testID: stringValue(selector.testID, `${path}.testID`) };
264
268
  }
265
269
  if (selector.text !== void 0) {
266
- return { text: stringValue(selector.text, "selector.text") };
270
+ return { text: stringValue(selector.text, `${path}.text`) };
267
271
  }
268
- return validationFailure("selector", "must select testID or text");
272
+ return validationFailure(path, "must select testID or text");
273
+ }
274
+ function parseSemanticResolveSelector(value) {
275
+ return semanticResolveSelector(value, "selector");
269
276
  }
270
277
  function parseSemanticWaitOptions(value) {
271
278
  const input = recordValue(value, "waitFor");
@@ -287,7 +294,7 @@ function parseSemanticWaitOptions(value) {
287
294
  return {
288
295
  condition: {
289
296
  type,
290
- testID: stringValue(condition.testID, "waitFor.condition.testID")
297
+ selector: semanticResolveSelector(condition.selector, "waitFor.condition.selector")
291
298
  },
292
299
  ...timeoutMs === void 0 ? {} : { timeoutMs }
293
300
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract-input.ts
4
4
  var BridgeInputError = class extends Error {
@@ -165,8 +165,10 @@ function parseStateOptions(value) {
165
165
  const input = recordValue(value, "state");
166
166
  const route = optionalBoolean(input, "route", "state");
167
167
  const errors = optionalBoolean(input, "errors", "state");
168
+ const logs = optionalBoolean(input, "logs", "state");
168
169
  const depth = optionalNumber(input, "depth", "state");
169
170
  const errorLimit = optionalNumber(input, "errorLimit", "state");
171
+ const logLimit = optionalNumber(input, "logLimit", "state");
170
172
  const layers = input.layers === void 0 ? void 0 : stringValue(input.layers, "state.layers");
171
173
  if (layers !== void 0 && layers !== "full" && layers !== "tenant" && layers !== "shell") {
172
174
  return validationFailure("state.layers", "must be full, tenant, or shell");
@@ -176,9 +178,11 @@ function parseStateOptions(value) {
176
178
  tree: optionalBoolean(input, "tree", "state") ?? true,
177
179
  ...route === void 0 ? {} : { route },
178
180
  ...errors === void 0 ? {} : { errors },
181
+ ...logs === void 0 ? {} : { logs },
179
182
  ...depth === void 0 ? {} : { depth },
180
183
  ...layers === void 0 ? {} : { layers },
181
- ...errorLimit === void 0 ? {} : { errorLimit }
184
+ ...errorLimit === void 0 ? {} : { errorLimit },
185
+ ...logLimit === void 0 ? {} : { logLimit }
182
186
  };
183
187
  }
184
188
  function parseSemanticSelector(value, path) {
@@ -225,15 +229,18 @@ function parseSemanticQuery(value) {
225
229
  }
226
230
  return validationFailure("query.kind", "must be tree, find, or count");
227
231
  }
228
- function parseSemanticResolveSelector(value) {
229
- const selector = recordValue(value, "selector");
232
+ function semanticResolveSelector(value, path) {
233
+ const selector = recordValue(value, path);
230
234
  if (selector.testID !== void 0) {
231
- return { testID: stringValue(selector.testID, "selector.testID") };
235
+ return { testID: stringValue(selector.testID, `${path}.testID`) };
232
236
  }
233
237
  if (selector.text !== void 0) {
234
- return { text: stringValue(selector.text, "selector.text") };
238
+ return { text: stringValue(selector.text, `${path}.text`) };
235
239
  }
236
- return validationFailure("selector", "must select testID or text");
240
+ return validationFailure(path, "must select testID or text");
241
+ }
242
+ function parseSemanticResolveSelector(value) {
243
+ return semanticResolveSelector(value, "selector");
237
244
  }
238
245
  function parseSemanticWaitOptions(value) {
239
246
  const input = recordValue(value, "waitFor");
@@ -255,7 +262,7 @@ function parseSemanticWaitOptions(value) {
255
262
  return {
256
263
  condition: {
257
264
  type,
258
- testID: stringValue(condition.testID, "waitFor.condition.testID")
265
+ selector: semanticResolveSelector(condition.selector, "waitFor.condition.selector")
259
266
  },
260
267
  ...timeoutMs === void 0 ? {} : { timeoutMs }
261
268
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
@@ -0,0 +1,107 @@
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
+ "use strict";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/capture-contract.ts
23
+ var capture_contract_exports = {};
24
+ __export(capture_contract_exports, {
25
+ RNX_SCREEN_CAPTURE_VERSION: () => RNX_SCREEN_CAPTURE_VERSION,
26
+ isRnxCaptureRegionAtlas: () => isRnxCaptureRegionAtlas,
27
+ isRnxScreenCapture: () => isRnxScreenCapture
28
+ });
29
+ module.exports = __toCommonJS(capture_contract_exports);
30
+ var RNX_SCREEN_CAPTURE_VERSION = 1;
31
+ function captureRecord(value) {
32
+ return value !== null && typeof value === "object" && !Array.isArray(value);
33
+ }
34
+ function captureInteger(value) {
35
+ return typeof value === "number" && Number.isSafeInteger(value);
36
+ }
37
+ function captureNumber(value) {
38
+ return typeof value === "number" && Number.isFinite(value);
39
+ }
40
+ function captureNullableString(value) {
41
+ return value === null || typeof value === "string";
42
+ }
43
+ function captureRect(value) {
44
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y) && captureNumber(value.width) && captureNumber(value.height);
45
+ }
46
+ function captureOptionalString(value) {
47
+ return value === void 0 || typeof value === "string";
48
+ }
49
+ function captureOptionalNullableString(value) {
50
+ return value === void 0 || captureNullableString(value);
51
+ }
52
+ function captureFontRegistration(value) {
53
+ return captureRecord(value) && typeof value.family === "string" && value.family.length > 0 && captureOptionalString(value.url) && captureOptionalString(value.sourceLabel) && captureOptionalNullableString(value.parsedFamily) && captureOptionalNullableString(value.parsedPostScript) && captureOptionalNullableString(value.fullName);
54
+ }
55
+ function capturePoint(value) {
56
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y);
57
+ }
58
+ function captureNode(value) {
59
+ if (!captureRecord(value) || !captureInteger(value.nodeId) || !(value.parentNodeId === null || captureInteger(value.parentNodeId)) || !Array.isArray(value.childNodeIds) || !value.childNodeIds.every(captureInteger) || !captureInteger(value.paintIndex) || typeof value.type !== "string" || !captureNullableString(value.id) || !captureNullableString(value.testID) || !captureNullableString(value.text) || !captureInteger(value.childCount) || !captureRecord(value.accessibility) || !captureRecord(value.interaction) || !captureRecord(value.layout) || !captureRecord(value.style) || !captureRecord(value.source) || !captureRecord(value.props) || !captureRecord(value.inspection)) {
60
+ return false;
61
+ }
62
+ const accessibility = value.accessibility;
63
+ if (typeof accessibility.accessible !== "boolean" || !captureNullableString(accessibility.label) || !captureNullableString(accessibility.role) || !captureNullableString(accessibility.hint) || !(accessibility.liveRegion === null || accessibility.liveRegion === "none" || accessibility.liveRegion === "polite" || accessibility.liveRegion === "assertive") || !(accessibility.state === null || captureRecord(accessibility.state)) || !(accessibility.value === null || captureRecord(accessibility.value))) {
64
+ return false;
65
+ }
66
+ const interaction = value.interaction;
67
+ if (typeof interaction.pressed !== "boolean" || typeof interaction.pressable !== "boolean" || typeof interaction.textInput !== "boolean" || !(interaction.textSelection === null || captureRecord(interaction.textSelection)) || typeof interaction.secureTextEntry !== "boolean" || !captureNullableString(interaction.placeholder) || !capturePoint(interaction.scrollOffset) || !(interaction.zoomScale === null || captureNumber(interaction.zoomScale)) || typeof interaction.nativePinchEnabled !== "boolean" || !(interaction.contentOffsetProp === null || captureRecord(interaction.contentOffsetProp)) || !(interaction.strokeDashoffsetProp === null || captureNumber(interaction.strokeDashoffsetProp))) {
68
+ return false;
69
+ }
70
+ const layout = value.layout;
71
+ if (!captureRect(layout.local) || !(layout.frame === null || captureRect(layout.frame)) || !capturePoint(layout.absolutePosition) || !(layout.visibleFrame === null || captureRect(layout.visibleFrame))) {
72
+ return false;
73
+ }
74
+ const style = value.style;
75
+ return captureRecord(style.resolved) && captureRecord(style.authored) && captureRecord(style.computed) && captureRecord(style.tokenBindings) && (value.textLines === void 0 || Array.isArray(value.textLines));
76
+ }
77
+ function isRnxScreenCapture(value) {
78
+ if (!captureRecord(value) || value.contractVersion !== RNX_SCREEN_CAPTURE_VERSION || !captureInteger(value.capturedAt) || !captureRecord(value.tree) || !(value.fonts === void 0 || Array.isArray(value.fonts) && value.fonts.length <= 200 && value.fonts.every(captureFontRegistration)) || !(value.visual === void 0 || captureRecord(value.visual))) {
79
+ return false;
80
+ }
81
+ const tree = value.tree;
82
+ const visual = value.visual;
83
+ return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
84
+ }
85
+ function isRnxCaptureRegionAtlas(value) {
86
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
87
+ return false;
88
+ }
89
+ const scale = value.pixelWidth / value.width;
90
+ if (!Number.isInteger(scale) || scale < 1 || scale > 4 || Math.abs(value.height * scale - value.pixelHeight) > 1e-6) {
91
+ return false;
92
+ }
93
+ const keys = /* @__PURE__ */ new Set();
94
+ for (const region of value.regions) {
95
+ if (!captureRecord(region) || typeof region.key !== "string" || region.key.length === 0 || keys.has(region.key) || !captureInteger(region.nodeId) || region.nodeId <= 0 || !captureRect(region.frame) || region.frame.width <= 0 || region.frame.height <= 0 || !captureRect(region.source) || region.source.x < 0 || region.source.y < 0 || region.source.width !== region.frame.width || region.source.height !== region.frame.height || region.source.x + region.source.width > value.width || region.source.y + region.source.height > value.height) {
96
+ return false;
97
+ }
98
+ keys.add(region.key);
99
+ }
100
+ return true;
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ RNX_SCREEN_CAPTURE_VERSION,
105
+ isRnxCaptureRegionAtlas,
106
+ isRnxScreenCapture
107
+ });
@@ -0,0 +1,80 @@
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+
3
+ // src/capture-contract.ts
4
+ var RNX_SCREEN_CAPTURE_VERSION = 1;
5
+ function captureRecord(value) {
6
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7
+ }
8
+ function captureInteger(value) {
9
+ return typeof value === "number" && Number.isSafeInteger(value);
10
+ }
11
+ function captureNumber(value) {
12
+ return typeof value === "number" && Number.isFinite(value);
13
+ }
14
+ function captureNullableString(value) {
15
+ return value === null || typeof value === "string";
16
+ }
17
+ function captureRect(value) {
18
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y) && captureNumber(value.width) && captureNumber(value.height);
19
+ }
20
+ function captureOptionalString(value) {
21
+ return value === void 0 || typeof value === "string";
22
+ }
23
+ function captureOptionalNullableString(value) {
24
+ return value === void 0 || captureNullableString(value);
25
+ }
26
+ function captureFontRegistration(value) {
27
+ return captureRecord(value) && typeof value.family === "string" && value.family.length > 0 && captureOptionalString(value.url) && captureOptionalString(value.sourceLabel) && captureOptionalNullableString(value.parsedFamily) && captureOptionalNullableString(value.parsedPostScript) && captureOptionalNullableString(value.fullName);
28
+ }
29
+ function capturePoint(value) {
30
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y);
31
+ }
32
+ function captureNode(value) {
33
+ if (!captureRecord(value) || !captureInteger(value.nodeId) || !(value.parentNodeId === null || captureInteger(value.parentNodeId)) || !Array.isArray(value.childNodeIds) || !value.childNodeIds.every(captureInteger) || !captureInteger(value.paintIndex) || typeof value.type !== "string" || !captureNullableString(value.id) || !captureNullableString(value.testID) || !captureNullableString(value.text) || !captureInteger(value.childCount) || !captureRecord(value.accessibility) || !captureRecord(value.interaction) || !captureRecord(value.layout) || !captureRecord(value.style) || !captureRecord(value.source) || !captureRecord(value.props) || !captureRecord(value.inspection)) {
34
+ return false;
35
+ }
36
+ const accessibility = value.accessibility;
37
+ if (typeof accessibility.accessible !== "boolean" || !captureNullableString(accessibility.label) || !captureNullableString(accessibility.role) || !captureNullableString(accessibility.hint) || !(accessibility.liveRegion === null || accessibility.liveRegion === "none" || accessibility.liveRegion === "polite" || accessibility.liveRegion === "assertive") || !(accessibility.state === null || captureRecord(accessibility.state)) || !(accessibility.value === null || captureRecord(accessibility.value))) {
38
+ return false;
39
+ }
40
+ const interaction = value.interaction;
41
+ if (typeof interaction.pressed !== "boolean" || typeof interaction.pressable !== "boolean" || typeof interaction.textInput !== "boolean" || !(interaction.textSelection === null || captureRecord(interaction.textSelection)) || typeof interaction.secureTextEntry !== "boolean" || !captureNullableString(interaction.placeholder) || !capturePoint(interaction.scrollOffset) || !(interaction.zoomScale === null || captureNumber(interaction.zoomScale)) || typeof interaction.nativePinchEnabled !== "boolean" || !(interaction.contentOffsetProp === null || captureRecord(interaction.contentOffsetProp)) || !(interaction.strokeDashoffsetProp === null || captureNumber(interaction.strokeDashoffsetProp))) {
42
+ return false;
43
+ }
44
+ const layout = value.layout;
45
+ if (!captureRect(layout.local) || !(layout.frame === null || captureRect(layout.frame)) || !capturePoint(layout.absolutePosition) || !(layout.visibleFrame === null || captureRect(layout.visibleFrame))) {
46
+ return false;
47
+ }
48
+ const style = value.style;
49
+ return captureRecord(style.resolved) && captureRecord(style.authored) && captureRecord(style.computed) && captureRecord(style.tokenBindings) && (value.textLines === void 0 || Array.isArray(value.textLines));
50
+ }
51
+ function isRnxScreenCapture(value) {
52
+ if (!captureRecord(value) || value.contractVersion !== RNX_SCREEN_CAPTURE_VERSION || !captureInteger(value.capturedAt) || !captureRecord(value.tree) || !(value.fonts === void 0 || Array.isArray(value.fonts) && value.fonts.length <= 200 && value.fonts.every(captureFontRegistration)) || !(value.visual === void 0 || captureRecord(value.visual))) {
53
+ return false;
54
+ }
55
+ const tree = value.tree;
56
+ const visual = value.visual;
57
+ return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
58
+ }
59
+ function isRnxCaptureRegionAtlas(value) {
60
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
61
+ return false;
62
+ }
63
+ const scale = value.pixelWidth / value.width;
64
+ if (!Number.isInteger(scale) || scale < 1 || scale > 4 || Math.abs(value.height * scale - value.pixelHeight) > 1e-6) {
65
+ return false;
66
+ }
67
+ const keys = /* @__PURE__ */ new Set();
68
+ for (const region of value.regions) {
69
+ if (!captureRecord(region) || typeof region.key !== "string" || region.key.length === 0 || keys.has(region.key) || !captureInteger(region.nodeId) || region.nodeId <= 0 || !captureRect(region.frame) || region.frame.width <= 0 || region.frame.height <= 0 || !captureRect(region.source) || region.source.x < 0 || region.source.y < 0 || region.source.width !== region.frame.width || region.source.height !== region.frame.height || region.source.x + region.source.width > value.width || region.source.y + region.source.height > value.height) {
70
+ return false;
71
+ }
72
+ keys.add(region.key);
73
+ }
74
+ return true;
75
+ }
76
+ export {
77
+ RNX_SCREEN_CAPTURE_VERSION,
78
+ isRnxCaptureRegionAtlas,
79
+ isRnxScreenCapture
80
+ };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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;
@@ -0,0 +1,32 @@
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
+ "use strict";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/cloud-contract.ts
23
+ var cloud_contract_exports = {};
24
+ __export(cloud_contract_exports, {
25
+ RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES
26
+ });
27
+ module.exports = __toCommonJS(cloud_contract_exports);
28
+ var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ RNX_CLOUD_MAX_ARTIFACT_BYTES
32
+ });
@@ -0,0 +1,7 @@
1
+ /*! rnx v0.1.382 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+
3
+ // src/cloud-contract.ts
4
+ var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
5
+ export {
6
+ RNX_CLOUD_MAX_ARTIFACT_BYTES
7
+ };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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;
@@ -2536,8 +2536,8 @@ var device = {
2536
2536
  return screenshotPath;
2537
2537
  },
2538
2538
  // record the SootSim canvas via the engine's headless recorder
2539
- // (window.__sootsimRecorder — @sootsim/plugin-recording). this is the
2540
- // SAME code path `sootsim record video` drives, NOT the rail-button
2539
+ // (window.__sootsimRecorder — @rnx/plugin-recording). this is the
2540
+ // SAME code path `rnx record video` drives, NOT the rail-button
2541
2541
  // path (SootSim.bridges.startRecording wires the dialog state machine
2542
2542
  // and never stashes the resulting blob into __sootsimRecorder.lastBlob,
2543
2543
  // which is what getBlobBase64 streams from).
@@ -2567,7 +2567,7 @@ var device = {
2567
2567
  }
2568
2568
  },
2569
2569
  // stop the headless recorder, stream the resulting blob in chunks (same
2570
- // protocol as `sootsim record`), and write the webm to outPath.
2570
+ // protocol as `rnx record`), and write the webm to outPath.
2571
2571
  async stopAndSaveBridgeRecording(outPath) {
2572
2572
  const page = getPage();
2573
2573
  const stopResult = await page.evaluate(async () => {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.380 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.382 | (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;