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
@@ -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/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.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;
@@ -1931,11 +1931,12 @@ async function resolveTargetCoords(bridge, target) {
1931
1931
  if (!isSimSemanticTree(semanticNodes) || typeof x !== "number" || !Number.isFinite(x) || typeof y !== "number" || !Number.isFinite(y)) {
1932
1932
  throw new Error("resolve returned an invalid result");
1933
1933
  }
1934
- const semanticMatch = semanticNodes[0];
1934
+ const semanticMatch = semanticNodes[1];
1935
1935
  if (!semanticMatch) throw new Error("resolve returned an invalid result");
1936
1936
  return {
1937
1937
  x,
1938
1938
  y,
1939
+ nodeId: semanticMatch.nodeId,
1939
1940
  testID: semanticMatch.testID ?? null,
1940
1941
  text: semanticMatch.text ?? (target.mode === "text" ? target.value : semanticMatch.label),
1941
1942
  type: semanticMatch.type
@@ -2147,34 +2148,6 @@ function offscreenPayload(cx, cy, screen) {
2147
2148
  }
2148
2149
  return { offscreen: true, screen };
2149
2150
  }
2150
- function geometryContains(geometry, x, y) {
2151
- return x >= geometry.x && y >= geometry.y && x <= geometry.x + geometry.width && y <= geometry.y + geometry.height;
2152
- }
2153
- function hitTestSemanticTree(nodes, x, y, ancestors = []) {
2154
- for (let index = nodes.length - 1; index >= 0; index--) {
2155
- const node = nodes[index];
2156
- if (!node || !geometryContains(node.geometry, x, y)) continue;
2157
- const childHit = node.children?.length ? hitTestSemanticTree(node.children, x, y, [...ancestors, node]) : null;
2158
- return childHit ?? { node, ancestors };
2159
- }
2160
- return null;
2161
- }
2162
- function nodeMatchesRequested(node, requested) {
2163
- if (typeof requested.nodeId === "number" && node.nodeId === requested.nodeId) {
2164
- return true;
2165
- }
2166
- if (requested.testID && node.testID === requested.testID) return true;
2167
- if (requested.id && node.testID === requested.id) return true;
2168
- return false;
2169
- }
2170
- function coveringNodeSummary(node) {
2171
- return {
2172
- nodeId: node.nodeId,
2173
- testID: node.testID ?? null,
2174
- text: node.text ?? node.label ?? null,
2175
- type: node.type
2176
- };
2177
- }
2178
2151
  var DEFAULT_AGENT_TIMING = {
2179
2152
  initialWaitMs: 3e3,
2180
2153
  deadlineMs: 5e3,
@@ -2201,9 +2174,10 @@ function isTapSuccess(result) {
2201
2174
  return true;
2202
2175
  }
2203
2176
  function tapTargetFromPayload(payload, textFallback) {
2177
+ const id = payload.target?.id ?? payload.match?.id ?? payload.node?.id;
2204
2178
  return {
2205
2179
  nodeId: payload.target?.nodeId ?? payload.match?.nodeId ?? payload.node?.nodeId ?? null,
2206
- id: payload.target?.id ?? payload.match?.id ?? payload.node?.id ?? null,
2180
+ id: typeof id === "string" ? id : null,
2207
2181
  testID: payload.target?.testID ?? payload.match?.testID ?? payload.node?.testID ?? null,
2208
2182
  text: payload.target?.text ?? payload.target?.accessibilityLabel ?? payload.match?.text ?? payload.match?.accessibilityLabel ?? payload.node?.text ?? textFallback ?? null,
2209
2183
  type: payload.target?.type ?? payload.match?.type ?? payload.node?.type ?? null
@@ -2261,36 +2235,17 @@ async function tapResolvedTarget(bridge, args) {
2261
2235
  } else {
2262
2236
  lastOffscreenAt = null;
2263
2237
  const requestedTarget = tapTargetFromPayload(payload, args.textFallback);
2264
- const { tree } = await inspectTree(bridge, 50);
2265
- let moved = false;
2266
- if (Array.isArray(tree) && tree.length > 0) {
2267
- const hit = hitTestSemanticTree(tree, payload.cx, payload.cy);
2268
- const matched = hit !== null && (nodeMatchesRequested(hit.node, requestedTarget) || hit.ancestors.some(
2269
- (ancestor) => nodeMatchesRequested(ancestor, requestedTarget)
2270
- ));
2271
- const blocks = hit !== null && (hit.node.type === "text" || hit.node.pressable === true || hit.ancestors.some((ancestor) => ancestor.pressable === true));
2272
- if (hit && !matched && blocks) {
2273
- moved = subtreeMatchesRequested(hit.node, requestedTarget);
2274
- lastResult = {
2275
- hit: false,
2276
- reason: moved ? "target-moved" : "target-covered",
2277
- requestedTarget,
2278
- coordinateTarget: coveringNodeSummary(hit.node)
2279
- };
2280
- if (!moved)
2281
- return { payload, result: lastResult, attempts, failure: "missed" };
2282
- }
2283
- }
2284
- if (!moved) {
2285
- const result = await tapCoordinates(
2286
- bridge,
2287
- payload.cx,
2288
- payload.cy,
2289
- requestedTarget
2290
- );
2291
- lastResult = result;
2292
- if (isTapSuccess(result)) return { payload, result, attempts };
2238
+ const result = await tapCoordinates(
2239
+ bridge,
2240
+ payload.cx,
2241
+ payload.cy,
2242
+ requestedTarget
2243
+ );
2244
+ lastResult = result;
2245
+ if (result?.requestedTargetMatched === false) {
2246
+ return { payload, result, attempts, failure: "missed" };
2293
2247
  }
2248
+ if (isTapSuccess(result)) return { payload, result, attempts };
2294
2249
  }
2295
2250
  }
2296
2251
  const remaining = deadline - Date.now();
@@ -2319,13 +2274,6 @@ async function tapResolvedTarget(bridge, args) {
2319
2274
  failure: lastPayload && typeof lastPayload.cx === "number" ? "missed" : "not-found"
2320
2275
  };
2321
2276
  }
2322
- function subtreeMatchesRequested(node, requested) {
2323
- for (const child of node.children ?? []) {
2324
- if (nodeMatchesRequested(child, requested) || subtreeMatchesRequested(child, requested))
2325
- return true;
2326
- }
2327
- return false;
2328
- }
2329
2277
  async function tapCoordinates(bridge, x, y, target) {
2330
2278
  return bridge.send({
2331
2279
  type: "tap",
@@ -2346,7 +2294,7 @@ function payloadFromResolved(resolved, match, extra = {}) {
2346
2294
  type: match.type ?? null
2347
2295
  },
2348
2296
  target: {
2349
- nodeId: match.nodeId ?? null,
2297
+ nodeId: resolved.nodeId ?? match.nodeId ?? null,
2350
2298
  id: resolved.testID ?? match.testID ?? null,
2351
2299
  testID: resolved.testID ?? match.testID ?? null,
2352
2300
  text: resolved.text ?? match.text ?? null,
@@ -2478,7 +2426,7 @@ async function tapBest(bridge, query, opts = {}) {
2478
2426
  ...payloadFromResolved(byId, byId),
2479
2427
  strategy: "testid",
2480
2428
  node: {
2481
- nodeId: null,
2429
+ nodeId: byId.nodeId ?? null,
2482
2430
  id: byId.testID ?? query,
2483
2431
  testID: byId.testID ?? query,
2484
2432
  type: byId.type ?? null,
@@ -2492,7 +2440,7 @@ async function tapBest(bridge, query, opts = {}) {
2492
2440
  ...payloadFromResolved(byText, byText),
2493
2441
  strategy: "text",
2494
2442
  node: {
2495
- nodeId: null,
2443
+ nodeId: byText.nodeId ?? null,
2496
2444
  id: byText.testID ?? null,
2497
2445
  testID: byText.testID ?? null,
2498
2446
  type: byText.type ?? null,
@@ -2811,11 +2759,16 @@ var SimClient = class {
2811
2759
  const { text, ...textOpts } = target;
2812
2760
  return this.throwUnlessTapped(await tapByText(this, text, textOpts), text);
2813
2761
  }
2814
- if ("testID" in target && typeof target.testID === "string") {
2762
+ if ("testID" in target && typeof target.testID === "string" && typeof target.nodeId !== "number") {
2815
2763
  return this.throwUnlessTapped(await tapById(this, target.testID), target.testID);
2816
2764
  }
2817
2765
  const coords = this.coordsForTapTarget(target);
2818
- const result = await this.send({ type: "tap", x: coords.x, y: coords.y });
2766
+ const result = await this.send({
2767
+ type: "tap",
2768
+ x: coords.x,
2769
+ y: coords.y,
2770
+ ..."nodeId" in target && typeof target.nodeId === "number" ? { target: { nodeId: target.nodeId } } : {}
2771
+ });
2819
2772
  if (!isTapSuccess(result)) {
2820
2773
  throw new SimTapError(
2821
2774
  `tap at ${coords.x},${coords.y} missed: ${JSON.stringify(result)}`
@@ -2878,6 +2831,7 @@ var SimClient = class {
2878
2831
  x: target.x,
2879
2832
  y: target.y,
2880
2833
  target: {
2834
+ nodeId: target.nodeId,
2881
2835
  testID: target.testID ?? void 0,
2882
2836
  text: target.text ?? void 0,
2883
2837
  type: target.type ?? void 0
@@ -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;
package/dist-lib/menu.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/menu.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/public-brand.ts
4
4
  var name = "rnx";
@@ -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/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -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/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -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;
@@ -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/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -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;
package/dist-lib/sdk.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;
@@ -1349,11 +1349,12 @@ async function resolveTargetCoords(bridge, target) {
1349
1349
  if (!isSimSemanticTree(semanticNodes) || typeof x !== "number" || !Number.isFinite(x) || typeof y !== "number" || !Number.isFinite(y)) {
1350
1350
  throw new Error("resolve returned an invalid result");
1351
1351
  }
1352
- const semanticMatch = semanticNodes[0];
1352
+ const semanticMatch = semanticNodes[1];
1353
1353
  if (!semanticMatch) throw new Error("resolve returned an invalid result");
1354
1354
  return {
1355
1355
  x,
1356
1356
  y,
1357
+ nodeId: semanticMatch.nodeId,
1357
1358
  testID: semanticMatch.testID ?? null,
1358
1359
  text: semanticMatch.text ?? (target.mode === "text" ? target.value : semanticMatch.label),
1359
1360
  type: semanticMatch.type
@@ -1565,34 +1566,6 @@ function offscreenPayload(cx, cy, screen) {
1565
1566
  }
1566
1567
  return { offscreen: true, screen };
1567
1568
  }
1568
- function geometryContains(geometry, x, y) {
1569
- return x >= geometry.x && y >= geometry.y && x <= geometry.x + geometry.width && y <= geometry.y + geometry.height;
1570
- }
1571
- function hitTestSemanticTree(nodes, x, y, ancestors = []) {
1572
- for (let index = nodes.length - 1; index >= 0; index--) {
1573
- const node = nodes[index];
1574
- if (!node || !geometryContains(node.geometry, x, y)) continue;
1575
- const childHit = node.children?.length ? hitTestSemanticTree(node.children, x, y, [...ancestors, node]) : null;
1576
- return childHit ?? { node, ancestors };
1577
- }
1578
- return null;
1579
- }
1580
- function nodeMatchesRequested(node, requested) {
1581
- if (typeof requested.nodeId === "number" && node.nodeId === requested.nodeId) {
1582
- return true;
1583
- }
1584
- if (requested.testID && node.testID === requested.testID) return true;
1585
- if (requested.id && node.testID === requested.id) return true;
1586
- return false;
1587
- }
1588
- function coveringNodeSummary(node) {
1589
- return {
1590
- nodeId: node.nodeId,
1591
- testID: node.testID ?? null,
1592
- text: node.text ?? node.label ?? null,
1593
- type: node.type
1594
- };
1595
- }
1596
1569
  var DEFAULT_AGENT_TIMING = {
1597
1570
  initialWaitMs: 3e3,
1598
1571
  deadlineMs: 5e3,
@@ -1619,9 +1592,10 @@ function isTapSuccess(result) {
1619
1592
  return true;
1620
1593
  }
1621
1594
  function tapTargetFromPayload(payload, textFallback) {
1595
+ const id = payload.target?.id ?? payload.match?.id ?? payload.node?.id;
1622
1596
  return {
1623
1597
  nodeId: payload.target?.nodeId ?? payload.match?.nodeId ?? payload.node?.nodeId ?? null,
1624
- id: payload.target?.id ?? payload.match?.id ?? payload.node?.id ?? null,
1598
+ id: typeof id === "string" ? id : null,
1625
1599
  testID: payload.target?.testID ?? payload.match?.testID ?? payload.node?.testID ?? null,
1626
1600
  text: payload.target?.text ?? payload.target?.accessibilityLabel ?? payload.match?.text ?? payload.match?.accessibilityLabel ?? payload.node?.text ?? textFallback ?? null,
1627
1601
  type: payload.target?.type ?? payload.match?.type ?? payload.node?.type ?? null
@@ -1679,36 +1653,17 @@ async function tapResolvedTarget(bridge, args) {
1679
1653
  } else {
1680
1654
  lastOffscreenAt = null;
1681
1655
  const requestedTarget = tapTargetFromPayload(payload, args.textFallback);
1682
- const { tree } = await inspectTree(bridge, 50);
1683
- let moved = false;
1684
- if (Array.isArray(tree) && tree.length > 0) {
1685
- const hit = hitTestSemanticTree(tree, payload.cx, payload.cy);
1686
- const matched = hit !== null && (nodeMatchesRequested(hit.node, requestedTarget) || hit.ancestors.some(
1687
- (ancestor) => nodeMatchesRequested(ancestor, requestedTarget)
1688
- ));
1689
- const blocks = hit !== null && (hit.node.type === "text" || hit.node.pressable === true || hit.ancestors.some((ancestor) => ancestor.pressable === true));
1690
- if (hit && !matched && blocks) {
1691
- moved = subtreeMatchesRequested(hit.node, requestedTarget);
1692
- lastResult = {
1693
- hit: false,
1694
- reason: moved ? "target-moved" : "target-covered",
1695
- requestedTarget,
1696
- coordinateTarget: coveringNodeSummary(hit.node)
1697
- };
1698
- if (!moved)
1699
- return { payload, result: lastResult, attempts, failure: "missed" };
1700
- }
1701
- }
1702
- if (!moved) {
1703
- const result = await tapCoordinates(
1704
- bridge,
1705
- payload.cx,
1706
- payload.cy,
1707
- requestedTarget
1708
- );
1709
- lastResult = result;
1710
- if (isTapSuccess(result)) return { payload, result, attempts };
1656
+ const result = await tapCoordinates(
1657
+ bridge,
1658
+ payload.cx,
1659
+ payload.cy,
1660
+ requestedTarget
1661
+ );
1662
+ lastResult = result;
1663
+ if (result?.requestedTargetMatched === false) {
1664
+ return { payload, result, attempts, failure: "missed" };
1711
1665
  }
1666
+ if (isTapSuccess(result)) return { payload, result, attempts };
1712
1667
  }
1713
1668
  }
1714
1669
  const remaining = deadline - Date.now();
@@ -1737,13 +1692,6 @@ async function tapResolvedTarget(bridge, args) {
1737
1692
  failure: lastPayload && typeof lastPayload.cx === "number" ? "missed" : "not-found"
1738
1693
  };
1739
1694
  }
1740
- function subtreeMatchesRequested(node, requested) {
1741
- for (const child of node.children ?? []) {
1742
- if (nodeMatchesRequested(child, requested) || subtreeMatchesRequested(child, requested))
1743
- return true;
1744
- }
1745
- return false;
1746
- }
1747
1695
  async function tapCoordinates(bridge, x, y, target) {
1748
1696
  return bridge.send({
1749
1697
  type: "tap",
@@ -1764,7 +1712,7 @@ function payloadFromResolved(resolved, match, extra = {}) {
1764
1712
  type: match.type ?? null
1765
1713
  },
1766
1714
  target: {
1767
- nodeId: match.nodeId ?? null,
1715
+ nodeId: resolved.nodeId ?? match.nodeId ?? null,
1768
1716
  id: resolved.testID ?? match.testID ?? null,
1769
1717
  testID: resolved.testID ?? match.testID ?? null,
1770
1718
  text: resolved.text ?? match.text ?? null,
@@ -1896,7 +1844,7 @@ async function tapBest(bridge, query, opts = {}) {
1896
1844
  ...payloadFromResolved(byId, byId),
1897
1845
  strategy: "testid",
1898
1846
  node: {
1899
- nodeId: null,
1847
+ nodeId: byId.nodeId ?? null,
1900
1848
  id: byId.testID ?? query,
1901
1849
  testID: byId.testID ?? query,
1902
1850
  type: byId.type ?? null,
@@ -1910,7 +1858,7 @@ async function tapBest(bridge, query, opts = {}) {
1910
1858
  ...payloadFromResolved(byText, byText),
1911
1859
  strategy: "text",
1912
1860
  node: {
1913
- nodeId: null,
1861
+ nodeId: byText.nodeId ?? null,
1914
1862
  id: byText.testID ?? null,
1915
1863
  testID: byText.testID ?? null,
1916
1864
  type: byText.type ?? null,
@@ -2229,11 +2177,16 @@ var SimClient = class {
2229
2177
  const { text, ...textOpts } = target;
2230
2178
  return this.throwUnlessTapped(await tapByText(this, text, textOpts), text);
2231
2179
  }
2232
- if ("testID" in target && typeof target.testID === "string") {
2180
+ if ("testID" in target && typeof target.testID === "string" && typeof target.nodeId !== "number") {
2233
2181
  return this.throwUnlessTapped(await tapById(this, target.testID), target.testID);
2234
2182
  }
2235
2183
  const coords = this.coordsForTapTarget(target);
2236
- const result = await this.send({ type: "tap", x: coords.x, y: coords.y });
2184
+ const result = await this.send({
2185
+ type: "tap",
2186
+ x: coords.x,
2187
+ y: coords.y,
2188
+ ..."nodeId" in target && typeof target.nodeId === "number" ? { target: { nodeId: target.nodeId } } : {}
2189
+ });
2237
2190
  if (!isTapSuccess(result)) {
2238
2191
  throw new SimTapError(
2239
2192
  `tap at ${coords.x},${coords.y} missed: ${JSON.stringify(result)}`
@@ -2296,6 +2249,7 @@ var SimClient = class {
2296
2249
  x: target.x,
2297
2250
  y: target.y,
2298
2251
  target: {
2252
+ nodeId: target.nodeId,
2299
2253
  testID: target.testID ?? void 0,
2300
2254
  text: target.text ?? void 0,
2301
2255
  type: target.type ?? void 0