rnxsim 0.1.458 → 0.1.459

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 (60) hide show
  1. package/cli/bridge-flow-runner.ts +13 -10
  2. package/cli/commands/inspect/actions.ts +20 -127
  3. package/cli/commands/inspect/core.ts +4 -19
  4. package/cli/commands/inspect/keyboard.ts +1 -0
  5. package/cli/commands/inspect/resolve-target.ts +3 -1
  6. package/cli/commands/inspect.ts +2 -0
  7. package/dist-lib/agent-daemon-client.cjs +1 -1
  8. package/dist-lib/agent-events.cjs +1 -1
  9. package/dist-lib/agent-identity.cjs +1 -1
  10. package/dist-lib/agent-sessions.cjs +1 -1
  11. package/dist-lib/attached-projects.cjs +1 -1
  12. package/dist-lib/auth/shared-session.cjs +1 -1
  13. package/dist-lib/backend-origin.cjs +1 -1
  14. package/dist-lib/beta.cjs +1 -1
  15. package/dist-lib/beta.mjs +1 -1
  16. package/dist-lib/bridge-constants.cjs +1 -1
  17. package/dist-lib/bridge-contract-input.cjs +24 -3
  18. package/dist-lib/bridge-contract-input.mjs +22 -2
  19. package/dist-lib/bridge-contract.cjs +1 -1
  20. package/dist-lib/bridge-contract.mjs +1 -1
  21. package/dist-lib/capture-contract.cjs +1 -1
  22. package/dist-lib/capture-contract.mjs +1 -1
  23. package/dist-lib/cli-constants.cjs +1 -1
  24. package/dist-lib/cloud-contract.cjs +1 -1
  25. package/dist-lib/cloud-contract.mjs +1 -1
  26. package/dist-lib/cloud.cjs +1 -1
  27. package/dist-lib/cloud.mjs +1 -1
  28. package/dist-lib/config.cjs +1 -1
  29. package/dist-lib/detox/index.cjs +1 -1
  30. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  31. package/dist-lib/home-paths.cjs +1 -1
  32. package/dist-lib/host/bridge-host.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  34. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  36. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  37. package/dist-lib/host/websocket-proxy.cjs +1 -1
  38. package/dist-lib/index.cjs +26 -72
  39. package/dist-lib/jump-to-source-babel.cjs +1 -1
  40. package/dist-lib/jump-to-source-native.cjs +1 -1
  41. package/dist-lib/menu.cjs +1 -1
  42. package/dist-lib/menu.mjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  45. package/dist-lib/metro-production-bundle.cjs +1 -1
  46. package/dist-lib/metro-production-bundle.mjs +1 -1
  47. package/dist-lib/metro.cjs +1 -1
  48. package/dist-lib/profiles.cjs +1 -1
  49. package/dist-lib/public-brand.cjs +1 -1
  50. package/dist-lib/react-native-host-modules.cjs +1 -1
  51. package/dist-lib/react-native-host-modules.mjs +1 -1
  52. package/dist-lib/render-mode.cjs +1 -1
  53. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  54. package/dist-lib/sdk.cjs +26 -72
  55. package/dist-lib/sdk.mjs +26 -72
  56. package/dist-lib/skills.cjs +755 -131
  57. package/dist-lib/vite.cjs +1 -1
  58. package/package.json +1 -1
  59. package/src/bridge-contract-input.ts +22 -2
  60. package/src/sim-client.ts +14 -2
@@ -17,6 +17,7 @@ import { MaestroJsContext, scriptConditionIsTruthy } from './maestro-js'
17
17
  import { ensureCliRecordingEntitlement } from './recording-access'
18
18
  import type { PerformResult, PerformStep, ResetResult } from '../src/bridge-contract'
19
19
  import type { WsBridge } from './ws-bridge'
20
+ import type { SootSimReplayTarget, SootSimTapResult } from '@rnx/globals'
20
21
  import type {
21
22
  SootSimExternalAppLifecycleOptions,
22
23
  SootSimLaunchArguments,
@@ -28,12 +29,8 @@ const scaledTimeout = (ms: number) => Math.round(ms * FLOW_TIMEOUT_SCALE)
28
29
  const SCREEN_W = 393
29
30
  const SCREEN_H = 852
30
31
  type FlowScreenshotPathMode = 'dir' | 'flow'
31
- type ReplayTapTarget = {
32
- id?: string | null
33
- testID?: string | null
34
- text?: string | null
35
- type?: string | null
36
- }
32
+ type ReplayTapTarget = SootSimReplayTarget
33
+
37
34
  type FlowTargetSelector = {
38
35
  id?: string
39
36
  text?: string
@@ -809,7 +806,9 @@ export class SootSimBridgeFlowRunner {
809
806
  }
810
807
  const matchesId = compile(${JSON.stringify(opts.id)})
811
808
  const matchesText = compile(${JSON.stringify(opts.text)})
812
- const all = ((await test.queryAll({})) || []).filter(
809
+ const all = ((await test.queryAll(${JSON.stringify(
810
+ opts.id && !opts.childOf ? { idPattern: opts.id } : {},
811
+ )})) || []).filter(
813
812
  (n) => n && n.absolutePosition && n.layout,
814
813
  )
815
814
  let candidates = all.filter((n) =>
@@ -944,14 +943,14 @@ export class SootSimBridgeFlowRunner {
944
943
  x: number,
945
944
  y: number,
946
945
  target?: ReplayTapTarget,
947
- ): Promise<{ hit?: boolean } | null> {
946
+ ): Promise<SootSimTapResult | null> {
948
947
  return (await this.bridge.send({
949
948
  type: 'tap',
950
949
  simId: this.opts.simId,
951
950
  x,
952
951
  y,
953
952
  target,
954
- })) as { hit?: boolean } | null
953
+ })) as SootSimTapResult | null
955
954
  }
956
955
 
957
956
  private async longPress(
@@ -1007,8 +1006,10 @@ export class SootSimBridgeFlowRunner {
1007
1006
  element: any,
1008
1007
  tapTarget?: any,
1009
1008
  ): ReplayTapTarget {
1009
+ const id = opts.id ?? tapTarget?.target?.id ?? element.id
1010
1010
  return {
1011
- id: opts.id ?? tapTarget?.target?.id ?? element.id ?? null,
1011
+ nodeId: tapTarget?.target?.nodeId ?? element.nodeId,
1012
+ id: typeof id === 'string' ? id : null,
1012
1013
  testID: opts.id ?? tapTarget?.target?.testID ?? element.testID ?? null,
1013
1014
  text:
1014
1015
  opts.text ??
@@ -1109,6 +1110,8 @@ export class SootSimBridgeFlowRunner {
1109
1110
  cy,
1110
1111
  this.replayTargetForElement(opts, current, tapTarget),
1111
1112
  )
1113
+ if (hit?.requestedTargetMatched === false)
1114
+ throw new Error(`tapOn refused: ${JSON.stringify(hit)}`)
1112
1115
  if (hit?.hit === true) {
1113
1116
  await sleep(300)
1114
1117
  if (!current.isTextInput) return
@@ -1,17 +1,12 @@
1
1
  import { inspectTree, type InspectBridge } from './core'
2
- import { resolveTargetCoords } from './resolve-target'
2
+ import { resolveTargetCoords, type ResolvedTargetCoords } from './resolve-target'
3
3
  import { waitForSootsimIdle } from './settling'
4
4
  import type { SimSemanticNode } from '../../../src/bridge-contract'
5
+ import type { SootSimReplayTarget } from '@rnx/globals'
5
6
 
6
7
  export type TapFailure = 'not-found' | 'missed' | 'special'
7
8
 
8
- export interface TapTargetSummary {
9
- nodeId: number | null
10
- id: string | null
11
- testID: string | null
12
- text: string | null
13
- type: string | null
14
- }
9
+ export type TapTargetSummary = SootSimReplayTarget
15
10
 
16
11
  export interface TapOutcome {
17
12
  payload: any
@@ -89,50 +84,6 @@ function offscreenPayload(
89
84
  return { offscreen: true, screen }
90
85
  }
91
86
 
92
- function geometryContains(geometry: SimSemanticNode['geometry'], x: number, y: number) {
93
- return (
94
- x >= geometry.x &&
95
- y >= geometry.y &&
96
- x <= geometry.x + geometry.width &&
97
- y <= geometry.y + geometry.height
98
- )
99
- }
100
-
101
- function hitTestSemanticTree(
102
- nodes: readonly SimSemanticNode[],
103
- x: number,
104
- y: number,
105
- ancestors: SimSemanticNode[] = [],
106
- ): { node: SimSemanticNode; ancestors: SimSemanticNode[] } | null {
107
- for (let index = nodes.length - 1; index >= 0; index--) {
108
- const node = nodes[index]
109
- if (!node || !geometryContains(node.geometry, x, y)) continue
110
- const childHit = node.children?.length
111
- ? hitTestSemanticTree(node.children, x, y, [...ancestors, node])
112
- : null
113
- return childHit ?? { node, ancestors }
114
- }
115
- return null
116
- }
117
-
118
- function nodeMatchesRequested(node: SimSemanticNode, requested: TapTargetSummary) {
119
- if (typeof requested.nodeId === 'number' && node.nodeId === requested.nodeId) {
120
- return true
121
- }
122
- if (requested.testID && node.testID === requested.testID) return true
123
- if (requested.id && node.testID === requested.id) return true
124
- return false
125
- }
126
-
127
- function coveringNodeSummary(node: SimSemanticNode) {
128
- return {
129
- nodeId: node.nodeId,
130
- testID: node.testID ?? null,
131
- text: node.text ?? node.label ?? null,
132
- type: node.type,
133
- }
134
- }
135
-
136
87
  const DEFAULT_AGENT_TIMING: Required<TapTimingOptions> = {
137
88
  initialWaitMs: 3000,
138
89
  deadlineMs: 5000,
@@ -170,10 +121,11 @@ export function tapTargetFromPayload(
170
121
  payload: any,
171
122
  textFallback?: string,
172
123
  ): TapTargetSummary {
124
+ const id = payload.target?.id ?? payload.match?.id ?? payload.node?.id
173
125
  return {
174
126
  nodeId:
175
127
  payload.target?.nodeId ?? payload.match?.nodeId ?? payload.node?.nodeId ?? null,
176
- id: payload.target?.id ?? payload.match?.id ?? payload.node?.id ?? null,
128
+ id: typeof id === 'string' ? id : null,
177
129
  testID:
178
130
  payload.target?.testID ?? payload.match?.testID ?? payload.node?.testID ?? null,
179
131
  text:
@@ -274,51 +226,17 @@ export async function tapResolvedTarget(
274
226
  } else {
275
227
  lastOffscreenAt = null
276
228
  const requestedTarget = tapTargetFromPayload(payload, args.textFallback)
277
- const { tree } = await inspectTree(bridge, 50)
278
- let moved = false
279
- if (Array.isArray(tree) && tree.length > 0) {
280
- const hit = hitTestSemanticTree(tree, payload.cx, payload.cy)
281
- const matched =
282
- hit !== null &&
283
- (nodeMatchesRequested(hit.node, requestedTarget) ||
284
- hit.ancestors.some((ancestor) =>
285
- nodeMatchesRequested(ancestor, requestedTarget),
286
- ))
287
- // a plain view over the point does not cover: the engine's hit-test
288
- // passes through unpainted, non-pressable views (a transparent modal
289
- // screen wrapping a dialog), and content behind an opaque surface is
290
- // already dropped from the tree. only a pressable in the hit chain
291
- // or a painted text leaf swallows the tap.
292
- const blocks =
293
- hit !== null &&
294
- (hit.node.type === 'text' ||
295
- hit.node.pressable === true ||
296
- hit.ancestors.some((ancestor) => ancestor.pressable === true))
297
- if (hit && !matched && blocks) {
298
- // the point landed inside the target's own container but not on
299
- // the target: it moved between the resolve and this inspect (a
300
- // sheet still animating in), which is a retry, not a cover.
301
- moved = subtreeMatchesRequested(hit.node, requestedTarget)
302
- lastResult = {
303
- hit: false,
304
- reason: moved ? 'target-moved' : 'target-covered',
305
- requestedTarget,
306
- coordinateTarget: coveringNodeSummary(hit.node),
307
- }
308
- if (!moved)
309
- return { payload, result: lastResult, attempts, failure: 'missed' }
310
- }
311
- }
312
- if (!moved) {
313
- const result = await tapCoordinates(
314
- bridge,
315
- payload.cx,
316
- payload.cy,
317
- requestedTarget,
318
- )
319
- lastResult = result
320
- if (isTapSuccess(result)) return { payload, result, attempts }
229
+ const result = await tapCoordinates(
230
+ bridge,
231
+ payload.cx,
232
+ payload.cy,
233
+ requestedTarget,
234
+ )
235
+ lastResult = result
236
+ if (result?.requestedTargetMatched === false) {
237
+ return { payload, result, attempts, failure: 'missed' }
321
238
  }
239
+ if (isTapSuccess(result)) return { payload, result, attempts }
322
240
  }
323
241
  }
324
242
 
@@ -350,20 +268,6 @@ export async function tapResolvedTarget(
350
268
  }
351
269
  }
352
270
 
353
- function subtreeMatchesRequested(
354
- node: SimSemanticNode,
355
- requested: TapTargetSummary,
356
- ): boolean {
357
- for (const child of node.children ?? []) {
358
- if (
359
- nodeMatchesRequested(child, requested) ||
360
- subtreeMatchesRequested(child, requested)
361
- )
362
- return true
363
- }
364
- return false
365
- }
366
-
367
271
  export async function tapCoordinates(
368
272
  bridge: InspectBridge,
369
273
  x: number,
@@ -379,19 +283,8 @@ export async function tapCoordinates(
379
283
  }
380
284
 
381
285
  function payloadFromResolved(
382
- resolved: {
383
- x: number
384
- y: number
385
- testID?: string | null
386
- text?: string | null
387
- type?: string | null
388
- },
389
- match: {
390
- nodeId?: number | null
391
- testID?: string | null
392
- text?: string | null
393
- type?: string | null
394
- },
286
+ resolved: ResolvedTargetCoords,
287
+ match: SootSimReplayTarget,
395
288
  extra: Record<string, unknown> = {},
396
289
  ) {
397
290
  return {
@@ -405,7 +298,7 @@ function payloadFromResolved(
405
298
  type: match.type ?? null,
406
299
  },
407
300
  target: {
408
- nodeId: match.nodeId ?? null,
301
+ nodeId: resolved.nodeId ?? match.nodeId ?? null,
409
302
  id: resolved.testID ?? match.testID ?? null,
410
303
  testID: resolved.testID ?? match.testID ?? null,
411
304
  text: resolved.text ?? match.text ?? null,
@@ -571,7 +464,7 @@ export async function tapBest(
571
464
  ...payloadFromResolved(byId, byId),
572
465
  strategy: 'testid',
573
466
  node: {
574
- nodeId: null,
467
+ nodeId: byId.nodeId ?? null,
575
468
  id: byId.testID ?? query,
576
469
  testID: byId.testID ?? query,
577
470
  type: byId.type ?? null,
@@ -585,7 +478,7 @@ export async function tapBest(
585
478
  ...payloadFromResolved(byText, byText),
586
479
  strategy: 'text',
587
480
  node: {
588
- nodeId: null,
481
+ nodeId: byText.nodeId ?? null,
589
482
  id: byText.testID ?? null,
590
483
  testID: byText.testID ?? null,
591
484
  type: byText.type ?? null,
@@ -34,6 +34,7 @@ import type {
34
34
  SootSimTimelineQueryResult,
35
35
  SootSimTimelineSummary,
36
36
  } from '@rnx/globals'
37
+ import type { KeyboardLayoutSnapshot } from 'sootsim-engine/render-worker/native-ui-protocol'
37
38
 
38
39
  // resolve a `--max-ms <n>` flag, tolerating the spellings agents and humans
39
40
  // actually type (`--maxMs`, `--maxms`, `--max_ms`). a silently-ignored
@@ -1575,25 +1576,9 @@ export async function inspectTimelineAdvanceCursor(
1575
1576
 
1576
1577
  // ─── keyboard ───
1577
1578
 
1578
- export interface KeyboardState {
1579
- visible: boolean
1580
- spec: {
1581
- keyboardType: string
1582
- returnKeyType: string
1583
- secureTextEntry: boolean
1584
- enablesReturnKeyAutomatically: boolean
1585
- autoCapitalize: string
1586
- autoCorrect: boolean
1587
- keyboardAppearance: string
1588
- accessoryBarId: string | null
1589
- currentTextIsEmpty: boolean
1590
- accessoryOffset: number
1591
- } | null
1592
- mode: string
1593
- shifted: boolean
1594
- capsLock: boolean
1595
- accessoryBarId: string | null
1596
- }
1579
+ // `__sootsimKeyboard.getLayout()` returns the shell's own snapshot, so the
1580
+ // engine's contract is the type. a copy here drifts from it silently.
1581
+ export type KeyboardState = KeyboardLayoutSnapshot
1597
1582
 
1598
1583
  // `get keyboard` — the live iOS keyboard state from `__sootsimKeyboard`,
1599
1584
  // populated by shell-worker `keyboard.layout` broadcasts. returns the raw
@@ -33,6 +33,7 @@ export async function runKeyboardSubcommand(
33
33
  lines.push(` returnKey: ${spec.returnKeyType}`)
34
34
  lines.push(` autoCap: ${spec.autoCapitalize}`)
35
35
  lines.push(` autoCorrect: ${spec.autoCorrect ? 'on' : 'off'}`)
36
+ lines.push(` spellCheck: ${spec.spellCheck ? 'on' : 'off'}`)
36
37
  lines.push(` appearance: ${spec.keyboardAppearance}`)
37
38
  if (spec.secureTextEntry) lines.push(` secureTextEntry: true`)
38
39
  if (spec.enablesReturnKeyAutomatically) {
@@ -27,6 +27,7 @@ export function readTargetFlag(
27
27
  }
28
28
 
29
29
  export interface ResolvedTargetCoords {
30
+ nodeId?: number
30
31
  x: number
31
32
  y: number
32
33
  testID?: string | null
@@ -62,11 +63,12 @@ export async function resolveTargetCoords(
62
63
  ) {
63
64
  throw new Error('resolve returned an invalid result')
64
65
  }
65
- const semanticMatch = semanticNodes[0]
66
+ const semanticMatch = semanticNodes[1]
66
67
  if (!semanticMatch) throw new Error('resolve returned an invalid result')
67
68
  return {
68
69
  x,
69
70
  y,
71
+ nodeId: semanticMatch.nodeId,
70
72
  testID: semanticMatch.testID ?? null,
71
73
  text:
72
74
  semanticMatch.text ?? (target.mode === 'text' ? target.value : semanticMatch.label),
@@ -1969,12 +1969,14 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1969
1969
  cx: resolved.x,
1970
1970
  cy: resolved.y,
1971
1971
  match: {
1972
+ nodeId: resolved.nodeId,
1972
1973
  testID:
1973
1974
  target.mode === 'testid' ? target.value : (resolved.testID ?? null),
1974
1975
  text: target.mode === 'text' ? target.value : (resolved.text ?? null),
1975
1976
  type: resolved.type ?? null,
1976
1977
  },
1977
1978
  target: {
1979
+ nodeId: resolved.nodeId,
1978
1980
  testID: resolved.testID ?? null,
1979
1981
  text: resolved.text ?? null,
1980
1982
  type: resolved.type ?? null,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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;
@@ -30,7 +30,8 @@ __export(bridge_contract_input_exports, {
30
30
  parseSemanticQuery: () => parseSemanticQuery,
31
31
  parseSemanticResolveSelector: () => parseSemanticResolveSelector,
32
32
  parseSemanticWaitOptions: () => parseSemanticWaitOptions,
33
- parseStateOptions: () => parseStateOptions
33
+ parseStateOptions: () => parseStateOptions,
34
+ parseTapTarget: () => parseTapTarget
34
35
  });
35
36
  module.exports = __toCommonJS(bridge_contract_input_exports);
36
37
 
@@ -110,6 +111,7 @@ function parsePerformStep(value, index) {
110
111
  case "tap":
111
112
  return {
112
113
  type,
114
+ target: parseTapTarget(step.target),
113
115
  x: numberValue(step.x, `${path}.x`),
114
116
  y: numberValue(step.y, `${path}.y`)
115
117
  };
@@ -345,6 +347,24 @@ function parseScreenshotOptions(value) {
345
347
  }
346
348
  };
347
349
  }
350
+ function parseTapTarget(value) {
351
+ if (value === void 0) return void 0;
352
+ const input = recordValue(value, "tap.target");
353
+ const target = {};
354
+ if (input.nodeId !== void 0 && input.nodeId !== null) {
355
+ const nodeId = numberValue(input.nodeId, "tap.target.nodeId");
356
+ if (!Number.isSafeInteger(nodeId))
357
+ validationFailure("tap.target.nodeId", "must be an integer");
358
+ target.nodeId = nodeId;
359
+ }
360
+ for (const key of ["id", "testID", "text", "type"]) {
361
+ if (input[key] !== void 0 && input[key] !== null)
362
+ target[key] = stringValue(input[key], `tap.target.${key}`);
363
+ }
364
+ if (target.nodeId === void 0 && !target.testID && !target.id)
365
+ validationFailure("tap.target", "requires nodeId, testID or id");
366
+ return target;
367
+ }
348
368
  // Annotate the CommonJS export names for ESM import in node:
349
369
  0 && (module.exports = {
350
370
  BridgeInputError,
@@ -355,5 +375,6 @@ function parseScreenshotOptions(value) {
355
375
  parseSemanticQuery,
356
376
  parseSemanticResolveSelector,
357
377
  parseSemanticWaitOptions,
358
- parseStateOptions
378
+ parseStateOptions,
379
+ parseTapTarget
359
380
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -76,6 +76,7 @@ function parsePerformStep(value, index) {
76
76
  case "tap":
77
77
  return {
78
78
  type,
79
+ target: parseTapTarget(step.target),
79
80
  x: numberValue(step.x, `${path}.x`),
80
81
  y: numberValue(step.y, `${path}.y`)
81
82
  };
@@ -311,6 +312,24 @@ function parseScreenshotOptions(value) {
311
312
  }
312
313
  };
313
314
  }
315
+ function parseTapTarget(value) {
316
+ if (value === void 0) return void 0;
317
+ const input = recordValue(value, "tap.target");
318
+ const target = {};
319
+ if (input.nodeId !== void 0 && input.nodeId !== null) {
320
+ const nodeId = numberValue(input.nodeId, "tap.target.nodeId");
321
+ if (!Number.isSafeInteger(nodeId))
322
+ validationFailure("tap.target.nodeId", "must be an integer");
323
+ target.nodeId = nodeId;
324
+ }
325
+ for (const key of ["id", "testID", "text", "type"]) {
326
+ if (input[key] !== void 0 && input[key] !== null)
327
+ target[key] = stringValue(input[key], `tap.target.${key}`);
328
+ }
329
+ if (target.nodeId === void 0 && !target.testID && !target.id)
330
+ validationFailure("tap.target", "requires nodeId, testID or id");
331
+ return target;
332
+ }
314
333
  export {
315
334
  BridgeInputError,
316
335
  SEMANTIC_WAIT_MAX_TIMEOUT_MS,
@@ -320,5 +339,6 @@ export {
320
339
  parseSemanticQuery,
321
340
  parseSemanticResolveSelector,
322
341
  parseSemanticWaitOptions,
323
- parseStateOptions
342
+ parseStateOptions,
343
+ parseTapTarget
324
344
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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.458 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.459 | (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;