rnxsim 0.0.0 → 0.1.312

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 (228) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/detox/colors.ts +54 -0
  4. package/detox/config-loader.ts +135 -0
  5. package/detox/element-types.ts +39 -0
  6. package/detox/expectations.ts +537 -0
  7. package/detox/gestures.ts +480 -0
  8. package/detox/index.ts +2118 -0
  9. package/detox/jest-preset.cjs +51 -0
  10. package/detox/jest-setup-after-env.cjs +18 -0
  11. package/detox/matchers.ts +30 -0
  12. package/detox/motion-change.cjs +109 -0
  13. package/detox/motion-change.d.cts +35 -0
  14. package/detox/navigation.ts +43 -0
  15. package/detox/screenshots/animated-color-test-rest-norngh.png +0 -0
  16. package/detox/screenshots/color-test-after-drag-norngh.png +0 -0
  17. package/detox/screenshots/color-test-rest-norngh.png +0 -0
  18. package/detox/screenshots/theme-blue-toggle.png +0 -0
  19. package/detox/screenshots/theme-blue.png +0 -0
  20. package/detox/screenshots/theme-red-toggle.png +0 -0
  21. package/detox/screenshots/theme-red.png +0 -0
  22. package/dist-cli/bin.js +15 -0
  23. package/dist-cli/chunks/agent-NXVDDCFG.js +48 -0
  24. package/dist-cli/chunks/agent-wrapper-DXJCFKL3.js +17 -0
  25. package/dist-cli/chunks/app-fonts-W5AJZQJF.js +4 -0
  26. package/dist-cli/chunks/assert-3LOJEUDT.js +49 -0
  27. package/dist-cli/chunks/auth-MFTYYPNX.js +12 -0
  28. package/dist-cli/chunks/beta-GT3NN67B.js +4 -0
  29. package/dist-cli/chunks/camera-6EAK7CUL.js +22 -0
  30. package/dist-cli/chunks/chunk-274UD5FD.js +4 -0
  31. package/dist-cli/chunks/chunk-2SA2VTGP.js +5 -0
  32. package/dist-cli/chunks/chunk-33FKQH54.js +5 -0
  33. package/dist-cli/chunks/chunk-37I5AIS7.js +3 -0
  34. package/dist-cli/chunks/chunk-3D57IBPC.js +4 -0
  35. package/dist-cli/chunks/chunk-4BXCZHAU.js +4 -0
  36. package/dist-cli/chunks/chunk-5OX7ANRA.js +5 -0
  37. package/dist-cli/chunks/chunk-66NF2KNG.js +9 -0
  38. package/dist-cli/chunks/chunk-6UKJB2VC.js +125 -0
  39. package/dist-cli/chunks/chunk-7INBNA3U.js +26 -0
  40. package/dist-cli/chunks/chunk-7VWOSTD5.js +5 -0
  41. package/dist-cli/chunks/chunk-AY47WKS5.js +23 -0
  42. package/dist-cli/chunks/chunk-B7KMNHX7.js +4 -0
  43. package/dist-cli/chunks/chunk-BKNOLP3J.js +4 -0
  44. package/dist-cli/chunks/chunk-BRIZOR4K.js +28 -0
  45. package/dist-cli/chunks/chunk-DM6KUAOZ.js +4 -0
  46. package/dist-cli/chunks/chunk-EUAVBTKU.js +4 -0
  47. package/dist-cli/chunks/chunk-FTC4M26Q.js +4 -0
  48. package/dist-cli/chunks/chunk-FWYYCUAZ.js +4 -0
  49. package/dist-cli/chunks/chunk-G74YIEVS.js +7 -0
  50. package/dist-cli/chunks/chunk-GZDHEONW.js +507 -0
  51. package/dist-cli/chunks/chunk-HG7ORJMT.js +5 -0
  52. package/dist-cli/chunks/chunk-HMDOLCKG.js +15 -0
  53. package/dist-cli/chunks/chunk-JG6S4RSH.js +4 -0
  54. package/dist-cli/chunks/chunk-KR5BGMBZ.js +4 -0
  55. package/dist-cli/chunks/chunk-KZW5WBGU.js +983 -0
  56. package/dist-cli/chunks/chunk-L24Z3CRS.js +30 -0
  57. package/dist-cli/chunks/chunk-LDQ7HVCW.js +4 -0
  58. package/dist-cli/chunks/chunk-MENV7VLD.js +4 -0
  59. package/dist-cli/chunks/chunk-MNGQ42QE.js +568 -0
  60. package/dist-cli/chunks/chunk-N6A3SXMR.js +4 -0
  61. package/dist-cli/chunks/chunk-NLEMQ4PY.js +6 -0
  62. package/dist-cli/chunks/chunk-NPVGMH2N.js +101 -0
  63. package/dist-cli/chunks/chunk-OR3XTXEB.js +107 -0
  64. package/dist-cli/chunks/chunk-PEPUGJVI.js +4 -0
  65. package/dist-cli/chunks/chunk-Q3RGLERJ.js +142 -0
  66. package/dist-cli/chunks/chunk-SI3BUTQR.js +4 -0
  67. package/dist-cli/chunks/chunk-T4FT6CM7.js +4 -0
  68. package/dist-cli/chunks/chunk-TBMVBI26.js +7 -0
  69. package/dist-cli/chunks/chunk-TCWQJILS.js +5 -0
  70. package/dist-cli/chunks/chunk-TGQNQ6XT.js +766 -0
  71. package/dist-cli/chunks/chunk-TYE3WBSR.js +5 -0
  72. package/dist-cli/chunks/chunk-U4PN6JOT.js +6 -0
  73. package/dist-cli/chunks/chunk-VUFRB347.js +4 -0
  74. package/dist-cli/chunks/chunk-VZBLFMYC.js +10 -0
  75. package/dist-cli/chunks/chunk-WBT32R6N.js +25 -0
  76. package/dist-cli/chunks/chunk-XRGEEPJ5.js +38 -0
  77. package/dist-cli/chunks/chunk-Y2FSZSO7.js +71 -0
  78. package/dist-cli/chunks/chunk-YRV7HR3P.js +74 -0
  79. package/dist-cli/chunks/chunk-YZRFF4YA.js +14 -0
  80. package/dist-cli/chunks/chunk-ZMZTHU7V.js +4 -0
  81. package/dist-cli/chunks/cleanup-H3GWQB63.js +25 -0
  82. package/dist-cli/chunks/cli-version-3QPAJ3LC.js +4 -0
  83. package/dist-cli/chunks/compat-5WG2XJV7.js +20 -0
  84. package/dist-cli/chunks/config-ANMBVVLL.js +13 -0
  85. package/dist-cli/chunks/control-NSGNQFJG.js +4 -0
  86. package/dist-cli/chunks/daemon-JHF4BJ3U.js +4 -0
  87. package/dist-cli/chunks/debug-CHV2O2KF.js +200 -0
  88. package/dist-cli/chunks/desktop-FIPIK4CH.js +31 -0
  89. package/dist-cli/chunks/detox-CVUJP7K6.js +52 -0
  90. package/dist-cli/chunks/device-6WCUM4W6.js +18 -0
  91. package/dist-cli/chunks/diagnose-I6EMWEII.js +43 -0
  92. package/dist-cli/chunks/disk-cleanup-P27CYFTN.js +4 -0
  93. package/dist-cli/chunks/drivers-HQ6AKZT6.js +4 -0
  94. package/dist-cli/chunks/film-UOQFFYNF.js +74 -0
  95. package/dist-cli/chunks/flow-N27MRRNL.js +4 -0
  96. package/dist-cli/chunks/help-SF6FEGEE.js +4 -0
  97. package/dist-cli/chunks/hidden-runtime-alias-NJYFSJKZ.js +4 -0
  98. package/dist-cli/chunks/home-paths-XOV44JEF.js +4 -0
  99. package/dist-cli/chunks/inspect-CWFRFQTY.js +4 -0
  100. package/dist-cli/chunks/install-desktop-KLQDNXZQ.js +4 -0
  101. package/dist-cli/chunks/login-BPFQENCX.js +28 -0
  102. package/dist-cli/chunks/logout-5A45ZGY7.js +4 -0
  103. package/dist-cli/chunks/maestro-E4CSDMLM.js +104 -0
  104. package/dist-cli/chunks/maestro-generate-CKMOJQX2.js +36 -0
  105. package/dist-cli/chunks/mode-SZYNMIQF.js +26 -0
  106. package/dist-cli/chunks/optional-demo-registry-FRH4SFVG.js +4 -0
  107. package/dist-cli/chunks/perf-VXU2XJAX.js +48 -0
  108. package/dist-cli/chunks/permissions-IRIAOVND.js +13 -0
  109. package/dist-cli/chunks/record-RY7FPLLH.js +72 -0
  110. package/dist-cli/chunks/report-issue-KNWXOE53.js +29 -0
  111. package/dist-cli/chunks/runtime-AR3GJTGK.js +4 -0
  112. package/dist-cli/chunks/screenshot-command-QLALR6GY.js +159 -0
  113. package/dist-cli/chunks/screenshot-layers-OQFMFVRL.js +20 -0
  114. package/dist-cli/chunks/screenshots-capture-6TSRJFGB.js +42 -0
  115. package/dist-cli/chunks/serve-F54J2NQO.js +44 -0
  116. package/dist-cli/chunks/setup-7V6UKX4U.js +32 -0
  117. package/dist-cli/chunks/skills-QQBOSETH.js +50 -0
  118. package/dist-cli/chunks/storage-TAPMKK5O.js +37 -0
  119. package/dist-cli/chunks/store-7NX3S43H.js +4 -0
  120. package/dist-cli/chunks/telemetry-E7BUK6RA.js +4 -0
  121. package/dist-cli/chunks/timeline-IAM564NA.js +24 -0
  122. package/dist-cli/chunks/upgrade-CD55QXIX.js +7 -0
  123. package/dist-cli/chunks/upload-GZ6LIMYM.js +4 -0
  124. package/dist-cli/chunks/version-3DYJ5AS3.js +6 -0
  125. package/dist-cli/chunks/web-6NW6YLPI.js +4 -0
  126. package/dist-cli/chunks/what-happened-CZZDOOVG.js +25 -0
  127. package/dist-lib/agent-daemon-client.cjs +468 -0
  128. package/dist-lib/agent-events.cjs +48 -0
  129. package/dist-lib/agent-identity.cjs +53 -0
  130. package/dist-lib/agent-sessions.cjs +725 -0
  131. package/dist-lib/attached-projects.cjs +526 -0
  132. package/dist-lib/auth/shared-session.cjs +195 -0
  133. package/dist-lib/backend-origin.cjs +70 -0
  134. package/dist-lib/beta.cjs +41 -0
  135. package/dist-lib/beta.mjs +13 -0
  136. package/dist-lib/bridge-constants.cjs +161 -0
  137. package/dist-lib/cli-constants.cjs +32 -0
  138. package/dist-lib/config.cjs +96 -0
  139. package/dist-lib/detox/index.cjs +2863 -0
  140. package/dist-lib/detox/jest-preset.cjs +51 -0
  141. package/dist-lib/dev-bundle-resolution.cjs +223 -0
  142. package/dist-lib/home-paths.cjs +421 -0
  143. package/dist-lib/host/bridge-host.cjs +5600 -0
  144. package/dist-lib/host/fetch-proxy-handler.cjs +373 -0
  145. package/dist-lib/host/fetch-proxy-overrides.cjs +63 -0
  146. package/dist-lib/host/fetch-proxy-overrides.mjs +37 -0
  147. package/dist-lib/host/websocket-proxy.cjs +214 -0
  148. package/dist-lib/index.cjs +513 -0
  149. package/dist-lib/jump-to-source-babel.cjs +93 -0
  150. package/dist-lib/menu.cjs +620 -0
  151. package/dist-lib/menu.mjs +581 -0
  152. package/dist-lib/metro.cjs +297 -0
  153. package/dist-lib/profiles.cjs +246 -0
  154. package/dist-lib/public-brand.cjs +39 -0
  155. package/dist-lib/render-mode.cjs +54 -0
  156. package/dist-lib/scripts/dev-server-scanner.cjs +1034 -0
  157. package/dist-lib/sdk.cjs +2333 -0
  158. package/dist-lib/sdk.mjs +2240 -0
  159. package/dist-lib/skills.cjs +23911 -0
  160. package/dist-lib/vite.cjs +358 -0
  161. package/package.json +189 -18
  162. package/scripts/dev-server-scanner.ts +941 -0
  163. package/scripts/optional-demo-registry.ts +113 -0
  164. package/scripts/postinstall.cjs +3 -0
  165. package/scripts/preuninstall.cjs +118 -0
  166. package/skills/contrast/SKILL.md +171 -0
  167. package/skills/rnx-debug/SKILL.md +425 -0
  168. package/skills/rnx-perf/SKILL.md +295 -0
  169. package/skills/rnx-setup/SKILL.md +160 -0
  170. package/skills/rnx-test/SKILL.md +292 -0
  171. package/skills/rnx-visual/SKILL.md +122 -0
  172. package/src/agent-daemon-client.ts +410 -0
  173. package/src/agent-events.ts +71 -0
  174. package/src/agent-identity.ts +23 -0
  175. package/src/agent-prompt.ts +71 -0
  176. package/src/agent-sessions.ts +573 -0
  177. package/src/attached-projects.ts +539 -0
  178. package/src/auth/shared-session.ts +204 -0
  179. package/src/backend-origin.ts +49 -0
  180. package/src/beta.ts +19 -0
  181. package/src/bridge-constants.ts +171 -0
  182. package/src/browser-cache.ts +16 -0
  183. package/src/cli-constants.ts +1 -0
  184. package/src/cli-version.ts +32 -0
  185. package/src/codex-client.ts +215 -0
  186. package/src/config.ts +134 -0
  187. package/src/dev-bundle-resolution.ts +236 -0
  188. package/src/disk-cleanup.ts +466 -0
  189. package/src/home-paths.ts +552 -0
  190. package/src/host/agent-host.ts +666 -0
  191. package/src/host/bridge-host.ts +2626 -0
  192. package/src/host/fetch-proxy-handler.ts +397 -0
  193. package/src/host/fetch-proxy-overrides.ts +51 -0
  194. package/src/host/open-url.ts +89 -0
  195. package/src/host/websocket-proxy.ts +210 -0
  196. package/src/index.ts +12 -705
  197. package/src/jump-to-source-babel.ts +135 -0
  198. package/src/menu.ts +734 -0
  199. package/src/metro-plugin.ts +139 -0
  200. package/src/native-dev-bundle-url.ts +96 -0
  201. package/src/native-seam-manifest.ts +341 -0
  202. package/src/plist.ts +27 -0
  203. package/src/poll-until.ts +92 -0
  204. package/src/profiles.ts +179 -0
  205. package/src/public-brand.ts +9 -0
  206. package/src/render-mode.ts +27 -0
  207. package/src/runtime-assets.ts +228 -0
  208. package/src/runtime-delivery.ts +54 -0
  209. package/src/screenshots/compose.ts +422 -0
  210. package/src/screenshots/frame-compose.ts +454 -0
  211. package/src/screenshots/orchestrate.ts +256 -0
  212. package/src/screenshots/org-deck.ts +91 -0
  213. package/src/screenshots/registry.ts +58 -0
  214. package/src/screenshots/schema.ts +364 -0
  215. package/src/sdk.ts +7 -0
  216. package/src/settings-bundle.ts +418 -0
  217. package/src/skills/builtin/a11y-review.ts +132 -0
  218. package/src/skills/builtin/compat-check.ts +71 -0
  219. package/src/skills/builtin/maestro-test.ts +121 -0
  220. package/src/skills/builtin/perf-profile.ts +90 -0
  221. package/src/skills/builtin/screenshot-all.ts +52 -0
  222. package/src/skills/builtin/visual-diff.ts +100 -0
  223. package/src/skills/registry.ts +107 -0
  224. package/src/skills/types.ts +41 -0
  225. package/src/team-machine-prompt.ts +73 -0
  226. package/src/vite-plugin-one.ts +190 -0
  227. package/src/vite-plugin.ts +1750 -0
  228. package/src/worklets-babel.ts +134 -0
@@ -0,0 +1,766 @@
1
+ /*! rnx v0.1.312 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import { createRequire as __sootsimCreateRequire } from 'node:module'
3
+ var require = __sootsimCreateRequire(import.meta.url)
4
+ function Q(t,e){let r=["--max-ms","--maxMs","--maxms","--max_ms"];for(let n of r){let o=t.indexOf(n);if(o>=0&&t[o+1]){let s=Number(t[o+1]);if(Number.isFinite(s))return Math.max(100,s)}}return e}var P=new Set(["tap","double-tap","tap-text","tap-id","long-press","touch"]);function N(t){return typeof t=="string"&&P.has(t)}async function M(t){return await t.send({type:"evaluate",code:"window.__sootsimEngineState?.inspectActive === true"})===!0}async function X(t,e){if(!N(e))return!1;try{return await M(t)}catch{return!1}}async function Z(t){let e=await t.send({type:"evaluate",code:"(async () => await window.__sootsimTest.getNodeCount())()"});return{nodes:typeof e=="number"?e:0}}async function ee(t,e=5,r){let n=r?.format?`, ${JSON.stringify(r)}`:"",o=await t.send({type:"evaluate",code:`(async () => await window.__sootsimTest.dumpTree(${e}${n}))()`});if(r?.format==="boxes"&&typeof o=="string")try{return{depth:e,tree:JSON.parse(o)}}catch{return{depth:e,tree:o}}return{depth:e,tree:o}}async function te(t){let e=await t.send({type:"evaluate",code:"window.location.href"});return{url:typeof e=="string"?e:""}}async function ne(t,e){let r=`(async () => {
5
+ const t = window.__sootsimTest
6
+ const mainShell = window.SootSim?.bridges?.mainShell
7
+ const kb = window.__sootsimKeyboard
8
+ if (!t) return { error: 'no test bridge' }
9
+
10
+ let shell = null
11
+ try {
12
+ shell = typeof mainShell?.getState === 'function' ? await mainShell.getState() : null
13
+ } catch {}
14
+
15
+ const opts = ${JSON.stringify(e)}
16
+ const needsRecursiveDump = opts.verbose || opts.subtreeRoot || opts.includeOccluded
17
+ const globToRegex = (glob) => {
18
+ const escaped = String(glob).replace(/[.+^$(){}|[\\]\\\\]/g, '\\\\$&')
19
+ const body = escaped.replace(/\\*/g, '.*').replace(/\\?/g, '.')
20
+ return new RegExp('^' + body + '$', 'i')
21
+ }
22
+ // clipping a describe line is a DISPLAY decision. opts.fullText (set by
23
+ // \`describe --json\`) keeps the real string, so a bundle-eval stack or a
24
+ // red-box message reaches the caller whole instead of ending in an
25
+ // ellipsis nothing downstream can undo.
26
+ const clipForDisplay = (value, max) => {
27
+ const text = typeof value === 'string' ? value.replace(/\\s+/g, ' ').trim() : ''
28
+ if (opts.fullText || text.length <= max) return text
29
+ return text.slice(0, max - 1).trimEnd() + '\u2026'
30
+ }
31
+ const formatInspectableTree = async () => {
32
+ if (typeof t.listInspectable !== 'function') return null
33
+ const list = await t.listInspectable({})
34
+ if (!Array.isArray(list)) return null
35
+ const filter = typeof opts.filter === 'string' ? opts.filter.toLowerCase() : ''
36
+ const testIdRegex = opts.testIdLike ? globToRegex(opts.testIdLike) : null
37
+ const onlyRegex = opts.onlyGlob ? globToRegex(opts.onlyGlob) : null
38
+ const lines = []
39
+ let matched = 0
40
+ for (const node of list) {
41
+ const testID = node?.testID || node?.testId || ''
42
+ const role = node?.role || ''
43
+ const label = node?.accessibilityLabel || node?.label || ''
44
+ const text = node?.text || ''
45
+ if (testIdRegex && !testIdRegex.test(testID)) continue
46
+ const joined = [role, label, text, testID].filter(Boolean).join(' ')
47
+ if (onlyRegex && !onlyRegex.test(joined)) continue
48
+ if (filter && !joined.toLowerCase().includes(filter)) continue
49
+ matched++
50
+
51
+ const type = String(node?.type || 'node').toLowerCase()
52
+ const handlers = Array.isArray(node?.handlers) ? node.handlers : []
53
+ const parts = []
54
+ if (role) parts.push('[' + role + ']')
55
+ else if (handlers.length > 0) parts.push('[tap]')
56
+ else parts.push('<' + type + '>')
57
+ const visibleText = clipForDisplay(text, 50)
58
+ if (visibleText) parts.push(JSON.stringify(visibleText))
59
+ if (testID) parts.push('#' + testID)
60
+ if (label && label !== text) {
61
+ parts.push('label=' + JSON.stringify(clipForDisplay(label, 50)))
62
+ }
63
+ if (!opts.hideXy) {
64
+ const abs = node?.absolute || {}
65
+ const layout = node?.layout || {}
66
+ const x = Math.round(Number(abs.x) || 0)
67
+ const y = Math.round(Number(abs.y) || 0)
68
+ const w = Math.round(Number(layout.width) || 0)
69
+ const h = Math.round(Number(layout.height) || 0)
70
+ parts.push('@(' + x + ',' + y + ') ' + w + 'x' + h)
71
+ }
72
+ if (handlers.length > 0) parts.push('(tap)')
73
+ lines.push(' ' + parts.join(' '))
74
+ }
75
+ return { tree: lines.join('\\n'), matched }
76
+ }
77
+
78
+ let tree = ''
79
+ const compactResult = needsRecursiveDump ? null : await formatInspectableTree()
80
+ if (compactResult) {
81
+ tree = compactResult.tree
82
+ } else {
83
+ tree = await t.dumpTree(12, opts)
84
+ }
85
+ const nodeCount = (await t.getNodeCount?.()) || 0
86
+ const keyboard = kb && typeof kb.getLayout === 'function' ? kb.getLayout() : null
87
+ return { tree, shell, nodeCount, keyboard }
88
+ })()`;return await t.send({type:"evaluate",code:r})??{}}function D(t){let e=t.fontSize>=18||t.fontSize>=14&&(t.fontWeight??400)>=700?3:4.5,{normal:r,background:n}=t;if(r.width<=0||r.height<=0||r.width!==n.width||r.height!==n.height)return{ratio:null,required:e,reason:"capture dimensions do not match"};let o=Math.max(0,Math.floor(t.box.x)),s=Math.max(0,Math.floor(t.box.y)),i=Math.min(r.width,Math.ceil(t.box.x+t.box.w)),d=Math.min(r.height,Math.ceil(t.box.y+t.box.h));if(i<=o||d<=s)return{ratio:null,required:e,reason:"text is outside the captured frame"};let p=l=>{let u=l/255;return u<=.04045?u/12.92:Math.pow((u+.055)/1.055,2.4)},g=(l,u)=>{let c=.2126*p(l[0])+.7152*p(l[1])+.0722*p(l[2]),v=.2126*p(u[0])+.7152*p(u[1])+.0722*p(u[2]);return(Math.max(c,v)+.05)/(Math.min(c,v)+.05)},a=l=>`#${l.slice(0,3).map(u=>Math.round(u).toString(16).padStart(2,"0")).join("")}`,h=(i-o)*(d-s),y=Math.max(1,Math.floor(Math.sqrt(h/12e3))),b=(l,u)=>(u*r.width+l)*4,x=l=>Math.max(Math.abs(r.data[l]-n.data[l]),Math.abs(r.data[l+1]-n.data[l+1]),Math.abs(r.data[l+2]-n.data[l+2])),f=0,m=null,w=null;for(let l=s;l<d;l+=y)for(let u=o;u<i;u+=y){let c=b(u,l);if(n.data[c+3]<250)continue;let v=[n.data[c],n.data[c+1],n.data[c+2]];w??=v;let E=x(c);E<=f||(f=E,m=[r.data[c],r.data[c+1],r.data[c+2]])}let S=1/0,I=null,T=null,k=(l,u)=>{let c=g(l,u);c>=S||(S=c,I=l,T=u)};if(f>=2&&m)for(let l=s;l<d;l+=y)for(let u=o;u<i;u+=y){let c=b(u,l);n.data[c+3]<250||x(c)<2||k(m,[n.data[c],n.data[c+1],n.data[c+2]])}else w&&k(w,w);return!I||!T||!Number.isFinite(S)?{ratio:null,required:e,reason:"could not isolate opaque rendered text pixels"}:{ratio:Math.round(S*100)/100,required:e,foreground:a(I),background:a(T)}}function A(t={}){let e=t.styling===!0,r=t.filter?.trim().toLowerCase()??"";return`(async () => {
89
+ const t = window.__sootsimTest
90
+ if (!t || typeof t.listInspectable !== 'function') return []
91
+ const list = await t.listInspectable({})
92
+ if (!Array.isArray(list)) return []
93
+ const includeStyle = ${JSON.stringify(e)}
94
+ const scoreContrast = ${D.toString()}
95
+ // narrows by ELEMENT, not by style field: fewer rows, full detail on each.
96
+ const filter = ${JSON.stringify(r)}
97
+ const matchesFilter = (n, text) => {
98
+ if (!filter) return true
99
+ const fields = [text, n.testID || n.testId, n.accessibilityRole || n.role, n.type]
100
+ return fields.some((f) => typeof f === 'string' && f.toLowerCase().includes(filter))
101
+ }
102
+
103
+ const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0)
104
+ const round = (v) => Math.round(num(v))
105
+
106
+ // borderRadius can be authored as a string ("12px") or split per-corner;
107
+ // prefer the uniform borderRadius, else the largest corner radius present.
108
+ const radiusOf = (style) => {
109
+ if (!style) return 0
110
+ const keys = ['borderRadius','borderTopLeftRadius','borderTopRightRadius','borderBottomLeftRadius','borderBottomRightRadius']
111
+ let max = 0
112
+ for (const k of keys) {
113
+ const raw = style[k]
114
+ const n = typeof raw === 'number' ? raw : (typeof raw === 'string' ? parseFloat(raw) : NaN)
115
+ if (Number.isFinite(n)) max = Math.max(max, n)
116
+ }
117
+ return Math.round(max)
118
+ }
119
+ const fontSizeOf = (style) => {
120
+ if (!style) return 0
121
+ const raw = style.fontSize
122
+ const n = typeof raw === 'number' ? raw : (typeof raw === 'string' ? parseFloat(raw) : NaN)
123
+ return Number.isFinite(n) ? Math.round(n) : 0
124
+ }
125
+ // styling extractors \u2014 omit boring defaults so the agent only sees notable
126
+ // styling (low opacity, struck text, clipping, a real border/color).
127
+ const colorStr = (v) => {
128
+ if (v == null) return undefined
129
+ const s = String(v).split(' ').join('')
130
+ return s && s !== 'transparent' && s !== 'rgba(0,0,0,0)' ? s : undefined
131
+ }
132
+ const opacityOf = (style) => {
133
+ const o = style && style.opacity
134
+ const n = typeof o === 'number' ? o : (typeof o === 'string' ? parseFloat(o) : NaN)
135
+ return Number.isFinite(n) && n < 1 ? Math.round(n * 100) / 100 : undefined
136
+ }
137
+ const weightOf = (style) => {
138
+ const w = style && style.fontWeight
139
+ const n = w === 'bold' ? 700 : (typeof w === 'number' ? w : (typeof w === 'string' ? parseInt(w, 10) : NaN))
140
+ return Number.isFinite(n) && n >= 600 ? n : undefined
141
+ }
142
+ const decoOf = (style) => {
143
+ const d = style && (style.textDecorationLine || style.textDecoration)
144
+ return d && d !== 'none' && d !== 'normal' ? String(d).split(' ')[0] : undefined
145
+ }
146
+ const overflowOf = (style) => (style && style.overflow === 'hidden' ? 'hidden' : undefined)
147
+ const borderWOf = (style) => {
148
+ if (!style) return undefined
149
+ const keys = ['borderWidth','borderTopWidth','borderBottomWidth','borderLeftWidth','borderRightWidth']
150
+ let max = 0
151
+ for (const k of keys) {
152
+ const r = style[k]
153
+ const n = typeof r === 'number' ? r : (typeof r === 'string' ? parseFloat(r) : NaN)
154
+ if (Number.isFinite(n)) max = Math.max(max, n)
155
+ }
156
+ return max > 0 ? Math.round(max) : undefined
157
+ }
158
+ // only meaningful alongside a real border width, so it is resolved by the
159
+ // caller below rather than on its own.
160
+ const borderColorOf = (style) => {
161
+ if (!style) return undefined
162
+ const keys = ['borderColor','borderTopColor','borderBottomColor','borderLeftColor','borderRightColor']
163
+ for (const k of keys) {
164
+ const c = colorStr(style[k])
165
+ if (c) return c
166
+ }
167
+ return undefined
168
+ }
169
+
170
+ const isVisible = (n) => {
171
+ const layout = n && n.layout
172
+ if (!layout || layout.width <= 0 || layout.height <= 0) return false
173
+ const abs = (n && (n.absolute || n.absolutePosition)) || null
174
+ if (!abs) return true
175
+ const device = (n && n.device) || {}
176
+ const screenW = Number(device.width) || window.innerWidth || 0
177
+ const screenH = Number(device.height) || window.innerHeight || 0
178
+ if (!screenW || !screenH) return true
179
+ return abs.x + layout.width > 0 && abs.y + layout.height > 0 && abs.x < screenW && abs.y < screenH
180
+ }
181
+
182
+ const elements = list.filter(isVisible).filter((n) => {
183
+ const t = typeof n.text === 'string' && n.text.trim() ? n.text.trim() : undefined
184
+ return matchesFilter(n, t)
185
+ }).map((n) => {
186
+ const layout = n.layout || { x: 0, y: 0, width: 0, height: 0 }
187
+ const abs = n.absolute || n.absolutePosition || { x: layout.x, y: layout.y }
188
+ const text = typeof n.text === 'string' && n.text.trim() ? n.text.trim() : undefined
189
+ const base = {
190
+ ...(typeof n.nodeId === 'number'
191
+ ? {
192
+ nodeId: n.nodeId,
193
+ ancestorIds: Array.isArray(n.ancestors)
194
+ ? n.ancestors.map((ancestor) => ancestor && ancestor.nodeId).filter((id) => typeof id === 'number')
195
+ : [],
196
+ }
197
+ : {}),
198
+ testID: n.testID || n.testId || undefined,
199
+ role: n.accessibilityRole || n.role || undefined,
200
+ type: typeof n.type === 'string' ? n.type : 'node',
201
+ text,
202
+ box: { x: round(abs.x), y: round(abs.y), w: round(layout.width), h: round(layout.height) },
203
+ borderRadius: 0,
204
+ padding: { t: 0, r: 0, b: 0, l: 0 },
205
+ fontSize: 0,
206
+ }
207
+ if (!includeStyle) return base
208
+ // computedStyle has the resolved values; style is the curated subset \u2014
209
+ // fall back across both so radius/fontSize survive either shape.
210
+ const style = Object.assign({}, n.style || {}, n.computedStyle || {})
211
+ const pad = (n.boxModel && n.boxModel.padding) || {}
212
+ const borderWidth = borderWOf(style)
213
+ return {
214
+ ...base,
215
+ borderRadius: radiusOf(style),
216
+ padding: { t: round(pad.top), r: round(pad.right), b: round(pad.bottom), l: round(pad.left) },
217
+ fontSize: text ? (fontSizeOf(style) || 14) : 0,
218
+ color: text ? colorStr(style.color) : undefined,
219
+ bg: colorStr(style.backgroundColor),
220
+ opacity: opacityOf(style),
221
+ fontWeight: weightOf(style),
222
+ textDecoration: decoOf(style),
223
+ overflow: overflowOf(style),
224
+ borderWidth,
225
+ borderColor: borderWidth ? borderColorOf(style) : undefined,
226
+ }
227
+ })
228
+ const textElements = elements.filter((element) => element.text && element.fontSize > 0)
229
+ if (!includeStyle || textElements.length === 0) return elements
230
+
231
+ const screenshot = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.screenshot
232
+ if (typeof screenshot !== 'function') {
233
+ throw new Error('styled native layout requires the rnx capture bridge')
234
+ }
235
+ const device = list.find((node) => node && node.device)?.device || {}
236
+ const width = Math.round(Number(device.width) || window.innerWidth || 0)
237
+ const height = Math.round(Number(device.height) || window.innerHeight || 0)
238
+ if (!width || !height) throw new Error('native layout has no capture dimensions')
239
+ const capture = async (suppressText) => {
240
+ const dataUrl = await screenshot({
241
+ format: 'png',
242
+ outputWidth: width,
243
+ outputHeight: height,
244
+ ...(suppressText ? { suppressText: true } : {}),
245
+ })
246
+ const image = await new Promise((resolve, reject) => {
247
+ const next = new Image()
248
+ next.onload = () => resolve(next)
249
+ next.onerror = () => reject(new Error('could not decode native layout pixels'))
250
+ next.src = dataUrl
251
+ })
252
+ const canvas = document.createElement('canvas')
253
+ canvas.width = image.naturalWidth
254
+ canvas.height = image.naturalHeight
255
+ const context = canvas.getContext('2d', { willReadFrequently: true })
256
+ if (!context) throw new Error('could not read native layout pixels')
257
+ context.drawImage(image, 0, 0)
258
+ return context.getImageData(0, 0, canvas.width, canvas.height)
259
+ }
260
+ const normal = await capture(false)
261
+ const background = await capture(true)
262
+ for (const element of textElements) {
263
+ element.contrast = scoreContrast({
264
+ normal,
265
+ background,
266
+ box: element.box,
267
+ fontSize: element.fontSize,
268
+ fontWeight: element.fontWeight,
269
+ })
270
+ }
271
+ return elements
272
+ })()`}var re=A();async function oe(t,e={}){let r=await t.send({type:"evaluate",code:A(e)});return Array.isArray(r)?r:[]}function se(t,e){return t.length===0?" no visible elements found":t.map(n=>{let s=[n.testID?`#${n.testID}`:n.selector?n.selector:n.role?`[${n.role}]`:`<${n.type}>`,`@(${n.box.x},${n.box.y})`,`${n.box.w}x${n.box.h}`];n.borderRadius>0&&s.push(`radius:${n.borderRadius}`);let i=n.padding;if(i.t||i.r||i.b||i.l){let d=i.t===i.r&&i.r===i.b&&i.b===i.l;s.push(d?`pad:${i.t}`:`pad:${i.t},${i.r},${i.b},${i.l}`)}if(n.fontSize>0&&s.push(`font:${n.fontSize}`),e?.styling){if(n.fontWeight&&s.push(`weight:${n.fontWeight}`),n.color&&s.push(`color:${n.color}`),n.bg&&s.push(`bg:${n.bg}`),n.contrast){let d=n.contrast.ratio==null?`?/${n.contrast.required}`:`${n.contrast.ratio}/${n.contrast.required}${n.contrast.ratio<n.contrast.required?" FAIL":""}`;s.push(`contrast:${d}`),n.contrast.background&&s.push(`on:${n.contrast.background}`)}n.opacity!=null&&s.push(`opacity:${n.opacity}`),n.textDecoration&&s.push(`deco:${n.textDecoration}`),n.overflow&&s.push(`overflow:${n.overflow}`),n.borderWidth&&s.push(n.borderColor?`border:${n.borderWidth}/${n.borderColor}`:`border:${n.borderWidth}`)}if(n.text){let d=n.text.length>40?`${n.text.slice(0,39)}\u2026`:n.text;s.push(`"${d}"`)}return` ${s.join(" ")}`}).join(`
273
+ `)}var O=`(async () => {
274
+ const t = window.__sootsimTest
275
+ if (!t) return []
276
+
277
+ const readLayout = (n) => n?.layout || null
278
+ const readAbs = (n) => n?.absolutePosition || n?.absolute || null
279
+ const readRole = (n) => n?.accessibilityRole || n?.role || null
280
+ const readLabel = (n) => n?.accessibilityLabel || n?.label || n?.text || null
281
+ const readHint = (n) => n?.accessibilityHint || n?.hint || null
282
+ const readState = (n) => n?.accessibilityState || n?.state || null
283
+ const readTestId = (n) => n?.testID || n?.testId || null
284
+ const readType = (n) => typeof n?.type === 'string' ? n.type.toLowerCase() : n?.type
285
+ const readPressable = (n) => {
286
+ if (n?.pressable) return true
287
+ const handlers = Array.isArray(n?.handlers) ? n.handlers : []
288
+ const role = readRole(n)
289
+ return handlers.length > 0 || role === 'button' || role === 'link' || role === 'tab'
290
+ }
291
+ const isTextInput = (n) => n?.isTextInput === true
292
+ const isTextNode = (n) => readType(n) === 'text'
293
+ const isVisibleTarget = (n) => {
294
+ const layout = readLayout(n)
295
+ if (!layout || layout.width <= 0 || layout.height <= 0) return false
296
+ const abs = readAbs(n)
297
+ if (!abs) return true
298
+ const device = n?.device || {}
299
+ const screenW = Number(device.width) || window.innerWidth || 0
300
+ const screenH = Number(device.height) || window.innerHeight || 0
301
+ return (
302
+ abs.x + layout.width > 0 &&
303
+ abs.y + layout.height > 0 &&
304
+ abs.x < screenW &&
305
+ abs.y < screenH
306
+ )
307
+ }
308
+ const hasAccessibleSignal = (n) => {
309
+ const role = readRole(n)
310
+ const label = readLabel(n)
311
+ const hint = readHint(n)
312
+ if (role) return true
313
+ if (hint) return true
314
+ if (isTextInput(n)) return true
315
+ if (readPressable(n)) return true
316
+ if (isTextNode(n) && n?.text) return true
317
+ if (typeof label === 'string' && label.length <= 30 && label !== n?.text) return true
318
+ return false
319
+ }
320
+ const normalize = (n) => {
321
+ const layout = readLayout(n)
322
+ const abs = readAbs(n)
323
+ const role = readRole(n) || (readPressable(n) ? 'button' : isTextInput(n) ? 'textfield' : isTextNode(n) ? 'statictext' : 'none')
324
+ return {
325
+ role,
326
+ label: readLabel(n),
327
+ hint: readHint(n),
328
+ state: readState(n),
329
+ testID: readTestId(n),
330
+ position: abs ? { x: Math.round(abs.x), y: Math.round(abs.y) } : null,
331
+ size: layout ? { w: Math.round(layout.width), h: Math.round(layout.height) } : null,
332
+ }
333
+ }
334
+
335
+ if (typeof t.listInspectable === 'function') {
336
+ const list = await t.listInspectable({})
337
+ if (Array.isArray(list)) {
338
+ return list.filter(n => isVisibleTarget(n) && hasAccessibleSignal(n)).map(normalize)
339
+ }
340
+ }
341
+
342
+ const all = await t.queryAll({ pruneHidden: true })
343
+ return all
344
+ .filter(n => isVisibleTarget(n) && hasAccessibleSignal(n))
345
+ .map(normalize)
346
+ })()`;async function ae(t){let e=await t.send({type:"evaluate",code:O});return Array.isArray(e)?e:[]}var R=`
347
+ const fromInspectable = async () => {
348
+ if (typeof t.listInspectable !== 'function') return null
349
+ const list = await t.listInspectable({})
350
+ if (!Array.isArray(list)) return null
351
+ return list.map((n) => {
352
+ const role = n.accessibilityRole ?? n.role
353
+ const label = n.accessibilityLabel ?? n.label
354
+ const layout = n.layout
355
+ const absolutePosition = n.absolutePosition ?? n.absolute
356
+ const screenW = Number(n.device?.width) || window.innerWidth || 0
357
+ const screenH = Number(n.device?.height) || window.innerHeight || 0
358
+ const visibleFrame = layout && absolutePosition
359
+ ? {
360
+ x: Math.max(0, absolutePosition.x),
361
+ y: Math.max(0, absolutePosition.y),
362
+ width: Math.max(
363
+ 0,
364
+ Math.min(screenW, absolutePosition.x + layout.width) -
365
+ Math.max(0, absolutePosition.x),
366
+ ),
367
+ height: Math.max(
368
+ 0,
369
+ Math.min(screenH, absolutePosition.y + layout.height) -
370
+ Math.max(0, absolutePosition.y),
371
+ ),
372
+ }
373
+ : null
374
+ const handlers = Array.isArray(n.handlers) ? n.handlers : []
375
+ const pressable =
376
+ handlers.length > 0 ||
377
+ role === 'button' ||
378
+ role === 'link' ||
379
+ role === 'tab'
380
+ return {
381
+ type: typeof n.type === 'string' ? n.type.toLowerCase() : n.type,
382
+ id: n.id ?? n.nodeId,
383
+ nodeId: n.nodeId,
384
+ testID: n.testID ?? n.testId,
385
+ text: n.text,
386
+ layout,
387
+ absolutePosition,
388
+ visibleFrame,
389
+ style: n.computedStyle ?? n.style ?? {},
390
+ childCount: n.childCount ?? 0,
391
+ pressed: n.pressed ?? false,
392
+ pressable,
393
+ isTextInput: n.isTextInput ?? false,
394
+ accessible: n.accessible ?? true,
395
+ accessibilityLabel: label,
396
+ accessibilityRole: role,
397
+ accessibilityHint: n.accessibilityHint,
398
+ accessibilityState: n.accessibilityState,
399
+ accessibilityValue: n.accessibilityValue,
400
+ }
401
+ })
402
+ }
403
+ const isVisibleTarget = (n) => {
404
+ if (!n?.layout) return false
405
+ const frame = n.visibleFrame
406
+ if (frame) return frame.width > 0 && frame.height > 0
407
+ const abs = n.absolutePosition
408
+ if (!abs) return n.layout.width > 0 && n.layout.height > 0
409
+ const screenW = window.innerWidth || 0
410
+ const screenH = window.innerHeight || 0
411
+ return (
412
+ abs.x + n.layout.width > 0 &&
413
+ abs.y + n.layout.height > 0 &&
414
+ abs.x < screenW &&
415
+ abs.y < screenH
416
+ )
417
+ }
418
+ `;function C(t){return t.testId?{mode:"testid",code:`(async () => {
419
+ const t = window.__sootsimTest
420
+ if (!t) return null
421
+ return (await t.findByTestId(${JSON.stringify(t.testId)})) || (await t.findById(${JSON.stringify(t.testId)}))
422
+ })()`}:t.role?{mode:"role",code:`(async () => {
423
+ const t = window.__sootsimTest
424
+ if (!t) return []
425
+ return await t.queryAll({ hasRole: ${JSON.stringify(t.role)}, pruneHidden: true })
426
+ })()`}:t.type?{mode:"type",code:`(async () => {
427
+ const t = window.__sootsimTest
428
+ if (!t) return []
429
+ return await t.queryAll({ type: ${JSON.stringify(t.type)}, pruneHidden: true })
430
+ })()`}:t.pressable?{mode:"pressable",code:`(async () => {
431
+ const t = window.__sootsimTest
432
+ if (!t) return []
433
+ ${R}
434
+ const inspectable = await fromInspectable()
435
+ if (inspectable) return inspectable.filter(n => n.pressable && isVisibleTarget(n))
436
+ const all = await t.queryAll({ pruneHidden: true })
437
+ return all.filter(n => n.pressable && isVisibleTarget(n))
438
+ })()`}:t.interactive?{mode:"interactive-targets",code:`(async () => {
439
+ const t = window.__sootsimTest
440
+ if (!t) return []
441
+ ${R}
442
+ const inspectable = await fromInspectable()
443
+ if (inspectable) {
444
+ return inspectable.filter(n => n.pressable && isVisibleTarget(n))
445
+ }
446
+ const all = await t.queryAll({ pruneHidden: true })
447
+ return all.filter(n => n.pressable && isVisibleTarget(n))
448
+ })()`}:t.visible?{mode:"visible",code:`(async () => {
449
+ const t = window.__sootsimTest
450
+ if (!t) return []
451
+ const all = await t.queryAll({ pruneHidden: true })
452
+ return all.filter(n => n.layout && n.layout.width > 0 && n.layout.height > 0)
453
+ })()`}:t.text?{mode:"text",code:`(async () => {
454
+ const t = window.__sootsimTest
455
+ if (!t) return null
456
+ return await t.findByText(${JSON.stringify(t.text)})
457
+ })()`}:null}async function ie(t,e){let r=C(e);if(!r)return null;let n=await t.send({type:"evaluate",code:r.code});return{mode:r.mode,result:n}}function le(t){return[...t].sort((e,r)=>$(r)-$(e))}function $(t){let e=0;t.testID&&(e+=100),typeof t.text=="string"&&t.text.trim().length>0&&(e+=60),typeof t.accessibilityLabel=="string"&&t.accessibilityLabel.trim().length>0&&(e+=30),t.accessibilityRole&&(e+=15);let r=t.layout?.width??0,n=t.layout?.height??0,o=r*n;return o>=400&&o<=6e4?e+=25:o>6e4&&(e-=20),(t.absolutePosition?.y??0)<0&&(e-=30),e}function ue(t){if(t.testID)return`rnxsim do tap-id ${_(t.testID)}`;let e=typeof t.text=="string"?t.text.trim():"";if(e.length>0&&e.length<=80)return`rnxsim do tap-text ${_(e)}`;let r=Math.round(((t.absolutePosition?.x??0)+(t.layout?.width??0)/2)*10)/10,n=Math.round(((t.absolutePosition?.y??0)+(t.layout?.height??0)/2)*10)/10;return`rnxsim do tap ${r} ${n}`}function _(t){return/^[A-Za-z0-9_./@:-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}var F=`(async () => {
458
+ const t = window.__sootsimTest
459
+ let nodes = 0
460
+ try { nodes = (await t?.getNodeCount?.()) || 0 } catch {}
461
+ let targets = 0
462
+ let liveFrameActive = false
463
+ let liveFrameChannels = 0
464
+ let liveFramePublishes = 0
465
+ let loadingText = ''
466
+ const cleanText = (value) =>
467
+ typeof value === 'string' ? value.replace(/\\s+/g, ' ').trim() : ''
468
+ const loadingSignal = (value) => {
469
+ const text = cleanText(value)
470
+ if (!text) return ''
471
+ return /^(opening app\\b|looking for your app\\b|building bundle\\b|preparing rnxsim runtime\\b|loading native bundle\\b|loading rnx stubs\\b|loading bundle loader\\b|loading native stubs\\b|loading compat bridge\\b|loading react-native shim\\b|loading react bridge\\b|loading reconciler\\b|loading replacement modules\\b|injecting rnx modules\\b|warming sqlite engine\\b|capturing root component\\b|reloading app\\b|loading(?:[.!\u2026]*)?$|connecting(?:[.!\u2026]*)?$)/i.test(text)
472
+ ? text
473
+ : ''
474
+ }
475
+ try {
476
+ const loading = window.__sootsimConnectRNLoading
477
+ if (loading && loading.active === true) {
478
+ loadingText = [loading.title, loading.detail].map(cleanText).filter(Boolean).join(' ')
479
+ }
480
+ } catch {}
481
+ try {
482
+ if (typeof t?.listInspectable === 'function') {
483
+ const list = await t.listInspectable({})
484
+ if (Array.isArray(list)) {
485
+ const screenW = window.innerWidth || 0
486
+ const screenH = window.innerHeight || 0
487
+ const isVisible = (n) => {
488
+ const layout = n?.layout
489
+ if (!layout || layout.width <= 0 || layout.height <= 0) return false
490
+ const abs = n?.absolutePosition || n?.absolute
491
+ if (!abs) return true
492
+ const device = n?.device || {}
493
+ const w = Number(device.width) || screenW
494
+ const h = Number(device.height) || screenH
495
+ return (
496
+ abs.x + layout.width > 0 &&
497
+ abs.y + layout.height > 0 &&
498
+ abs.x < w &&
499
+ abs.y < h
500
+ )
501
+ }
502
+ const hasContentSignal = (n) => {
503
+ const role = n?.accessibilityRole || n?.role
504
+ const label = cleanText(n?.accessibilityLabel || n?.label)
505
+ const handlers = Array.isArray(n?.handlers) ? n.handlers : []
506
+ const text = cleanText(n?.text)
507
+ const testID = cleanText(n?.testID || n?.testId)
508
+ const loading = loadingSignal(text) || loadingSignal(label) || loadingSignal(testID)
509
+ if (!loadingText && loading) {
510
+ loadingText = loading
511
+ }
512
+ if (handlers.length > 0) return true
513
+ if (role) return true
514
+ if (n?.isTextInput) return true
515
+ if (text) return true
516
+ if (label) return true
517
+ if (testID && !/^splash|loading/i.test(testID)) return true
518
+ return false
519
+ }
520
+ targets = list.filter(n => isVisible(n) && hasContentSignal(n)).length
521
+ }
522
+ }
523
+ } catch {}
524
+ try {
525
+ const stats = await t?.getImageLoaderStats?.()
526
+ const presentation = stats?.liveFramePresentation
527
+ liveFrameChannels = Number(presentation?.activeChannels) || 0
528
+ liveFramePublishes = Number(presentation?.publishes) || 0
529
+ const previous = window.__sootsimWaitReadyLiveFramePublishes
530
+ liveFrameActive =
531
+ liveFrameChannels > 0 &&
532
+ typeof previous === 'number' &&
533
+ liveFramePublishes > previous
534
+ window.__sootsimWaitReadyLiveFramePublishes = liveFramePublishes
535
+ } catch {}
536
+ let externalReady = null
537
+ let externalStatus = ''
538
+ let externalError = ''
539
+ let suppressedEntryError = ''
540
+ try {
541
+ const getExternalAppState = t?.getExternalAppState
542
+ const external = typeof getExternalAppState === 'function'
543
+ ? await Promise.race([
544
+ getExternalAppState(),
545
+ new Promise((resolve) => setTimeout(
546
+ () => resolve({
547
+ state: {
548
+ ready: false,
549
+ loading: true,
550
+ status: 'waiting for tenant worker...',
551
+ },
552
+ }),
553
+ 1000,
554
+ )),
555
+ ])
556
+ : null
557
+ const state = external?.state
558
+ if (state && typeof state === 'object') {
559
+ externalReady = state.ready === true
560
+ if (typeof state.status === 'string') externalStatus = state.status
561
+ if (typeof state.error === 'string') externalError = state.error
562
+ }
563
+ if (!externalError && Array.isArray(external?.entryErrors)) {
564
+ // suppressed-and-continued entry errors (bundle-loader's patched __r
565
+ // swallows entry throws and moves on) must NOT gate readiness \u2014 the
566
+ // app frequently runs fine after one (e.g. metro's "Unknown named
567
+ // module" probing noise). they surface separately as a diagnostic
568
+ // for the timeout path.
569
+ const isReal = (item) => item && typeof item.message === 'string' && item.message.trim()
570
+ const fatal = external.entryErrors.find((item) => isReal(item) && item.suppressed !== true)
571
+ if (fatal) externalError = fatal.message
572
+ const suppressed = external.entryErrors.find((item) => isReal(item) && item.suppressed === true)
573
+ if (suppressed) suppressedEntryError = suppressed.message
574
+ }
575
+ // once the app has errored its last status ("injecting sootsim
576
+ // modules...") is stale \u2014 reporting it makes a dead app read as one that
577
+ // is still booting.
578
+ if (externalError) loadingText = ''
579
+ else if (externalReady === false && externalStatus) loadingText = externalStatus
580
+ } catch {}
581
+ let errors = 0
582
+ try { errors = window.__sootsimConsole?.count?.()?.errors ?? 0 } catch {}
583
+ return {
584
+ flag: (window).__sootsimExternalAppReady,
585
+ at: (window).__sootsimExternalAppReadyAt || 0,
586
+ nodes,
587
+ targets,
588
+ liveFrameActive,
589
+ liveFrameChannels,
590
+ liveFramePublishes,
591
+ errors,
592
+ loadingText,
593
+ externalReady,
594
+ externalStatus,
595
+ externalError,
596
+ suppressedEntryError,
597
+ }
598
+ })()`,W=100,H=750,B=2e3,z=150;function j(t){return t.liveFrameActive||t.targets>0||t.nodes>=W}function J(t){return t.liveFrameActive||t.targets>0}function ce(t){if(t.bridgeError)return`sim unreachable: ${t.bridgeError} \u2014 the target tab is closed or no sim is connected (check \`rnxsim list\`, reopen with \`rnxsim open\`)`;let e=t.externalError?`guest app errored: ${t.externalError}`:t.loadingText?`still showing "${t.loadingText}"`:t.externalReady===!1?"guest app is still loading":t.flag!==!0&&t.targets>0?"native content is rendered but the ready signal has not settled":t.flag!==!0?"guest app has not emitted sootsim:externalAppReady":t.targets<=0?"ready flag emitted but no visible app content is inspectable yet":"node tree is still changing";return!t.externalError&&t.suppressedEntryError?`${e} (suppressed entry error: ${t.suppressedEntryError})`:e}async function de(t,e=2e4,r={}){let n=Date.now(),o=n+e,s=r.progressIntervalMs??B,i=n+s,d=-1,p=n,g="",a={flag:void 0,at:0,nodes:0,targets:0,liveFrameActive:!1,liveFrameChannels:0,liveFramePublishes:0,errors:0,loadingText:"",externalReady:null,externalStatus:"",externalError:"",suppressedEntryError:""};for(;Date.now()<o;){try{a=await t.send({type:"evaluate",code:F})??a,g=""}catch(m){if(g=m instanceof Error?m.message:String(m),g.startsWith("multiple sims are connected:")||g.startsWith("saved sim "))throw m}let y=Date.now(),b={ready:!1,elapsedMs:y-n,nodes:a.nodes,targets:a.targets,liveFrameActive:a.liveFrameActive,liveFrameChannels:a.liveFrameChannels,liveFramePublishes:a.liveFramePublishes,flag:a.flag,loadingText:a.loadingText,externalReady:a.externalReady,externalStatus:a.externalStatus,externalError:a.externalError,suppressedEntryError:a.suppressedEntryError,errors:a.errors,bridgeError:g};a.nodes!==d&&(d=a.nodes,p=y);let x=a.flag===!0&&j(a),f=a.flag!==!0&&J(a);if((x||f)&&a.externalReady!==!1&&!a.externalError&&!a.loadingText&&y-p>=H)return{...b,ready:!0};if(a.externalError)return b;if(r.onProgress&&s>0&&y>=i){r.onProgress(b);do i+=s;while(y>=i)}await new Promise(m=>setTimeout(m,z))}let h={ready:!1,elapsedMs:Date.now()-n,nodes:a.nodes,targets:a.targets,liveFrameActive:a.liveFrameActive,liveFrameChannels:a.liveFrameChannels,liveFramePublishes:a.liveFramePublishes,flag:a.flag,loadingText:a.loadingText,externalReady:a.externalReady,externalStatus:a.externalStatus,externalError:a.externalError,suppressedEntryError:a.suppressedEntryError,errors:a.errors,bridgeError:g};return r.onProgress&&s>0&&Date.now()>=i&&r.onProgress(h),h}async function pe(t,e,r=5e3,n={}){let o=n.gone===!0;return await t.send({type:"evaluate",code:`(async () => {
599
+ const start = Date.now()
600
+ const deadline = start + ${r}
601
+ const gone = ${o}
602
+ const ID = ${JSON.stringify(e)}
603
+ const present = (node) => !!(node && node.layout && node.layout.width > 0 && node.layout.height > 0)
604
+ const find = async () => {
605
+ const t = window.__sootsimTest
606
+ if (!t) return undefined // bridge not ready \u2014 indeterminate, not "gone"
607
+ try {
608
+ // gone-mode confirms a gate/screen LEFT \u2014 it only needs structural
609
+ // existence + layout, NOT the full-tree occlusion pass (pruneHidden).
610
+ // that pass (computeOccludedInspectNodeIds) walks the whole tree and
611
+ // does O(n\xB2)-ish rect-occlusion testing EVERY poll; on a large
612
+ // post-login app tree it costs seconds per poll, so --gone can never
613
+ // get two clean "absent" polls inside budget and falsely reports the
614
+ // gate as still blocked \u2014 the root cause of the 3pc PR-preview outage.
615
+ // presence-mode keeps pruneHidden so "appeared" still means
616
+ // visibly-reachable. a departed gate is unmounted or zero-sized, so the
617
+ // cheap structural+layout check is correct here and ~O(n) cheap.
618
+ const matches = await t.queryAll?.(gone ? { hasId: ID } : { hasId: ID, pruneHidden: true })
619
+ if (!Array.isArray(matches)) return undefined
620
+ return matches.find(present) || null
621
+ } catch {
622
+ return undefined
623
+ }
624
+ }
625
+ let goneStreak = 0
626
+ while (Date.now() < deadline) {
627
+ const node = await find()
628
+ if (gone) {
629
+ if (node === null) {
630
+ goneStreak += 1
631
+ if (goneStreak >= 2) return { found: true, elapsed: Date.now() - start }
632
+ } else {
633
+ goneStreak = 0
634
+ }
635
+ } else if (present(node)) {
636
+ return { found: true, node, elapsed: Date.now() - start }
637
+ }
638
+ await new Promise((r) => setTimeout(r, 80))
639
+ }
640
+ return { found: false, elapsed: Date.now() - start }
641
+ })()`},{timeoutMs:r+1e3})??{found:!1,elapsed:r}}function L(t,e){return`(() => {
642
+ const out = []
643
+ const seen = new Set()
644
+ const norm = (s) => (typeof s === 'string' ? s : (() => { try { return JSON.stringify(s) } catch { return String(s) } })())
645
+ const key = (ts, args) => Math.round((ts || 0) / 250) + '|' + (Array.isArray(args) ? args.map(norm).join(' ') : norm(args))
646
+ const push = (e) => {
647
+ if (!e) return
648
+ const ts = typeof e.timestamp === 'number' ? e.timestamp : (typeof e.ts === 'number' ? e.ts : 0)
649
+ const k = key(ts, e.args)
650
+ if (seen.has(k)) return
651
+ seen.add(k)
652
+ out.push({ timestamp: ts, args: Array.isArray(e.args) ? e.args : [e.args], stack: e.stack || undefined, source: e.source || undefined })
653
+ }
654
+ // page-realm ws-bridge buffer first (richest stacks for page-origin errors)
655
+ try { for (const e of (window.__sootsimConsole?.${t==="error"?"getErrors":"getWarnings"}(${e}) || [])) push(e) } catch {}
656
+ // engine observability store \u2014 the always-on render-worker / forwarded path
657
+ try {
658
+ const obs = window.__sootsimObservability
659
+ const snap = obs && obs.logs && typeof obs.logs.getSnapshot === 'function' ? obs.logs.getSnapshot() : []
660
+ for (const e of snap) if (e && e.level === ${JSON.stringify(t)}) push(e)
661
+ } catch {}
662
+ return out.sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0)).slice(-${e})
663
+ })()`}async function ye(t,e=20){let r=await t.send({type:"evaluate",code:L("error",e)});return Array.isArray(r)?r:[]}async function me(t,e=20){let r=await t.send({type:"evaluate",code:L("warn",e)});return Array.isArray(r)?r:[]}var ge=`(() => {
664
+ const norm = (s) => (typeof s === 'string' ? s : (() => { try { return JSON.stringify(s) } catch { return String(s) } })())
665
+ const key = (lvl, ts, args) => lvl + '|' + Math.round((ts || 0) / 250) + '|' + (Array.isArray(args) ? args.map(norm).join(' ') : norm(args))
666
+ const seen = new Set()
667
+ let errors = 0
668
+ let warnings = 0
669
+ const add = (lvl, ts, args) => {
670
+ if (lvl !== 'error' && lvl !== 'warn') return
671
+ const k = key(lvl, ts, args)
672
+ if (seen.has(k)) return
673
+ seen.add(k)
674
+ if (lvl === 'error') errors++
675
+ else warnings++
676
+ }
677
+ try {
678
+ const c = window.__sootsimConsole
679
+ for (const e of (c?.getErrors?.(200) || [])) add('error', e?.timestamp ?? e?.ts, e?.args)
680
+ for (const e of (c?.getWarnings?.(200) || [])) add('warn', e?.timestamp ?? e?.ts, e?.args)
681
+ } catch {}
682
+ try {
683
+ const obs = window.__sootsimObservability
684
+ const snap = obs && obs.logs && typeof obs.logs.getSnapshot === 'function' ? obs.logs.getSnapshot() : []
685
+ for (const e of snap) if (e) add(e.level, e.ts, e.args)
686
+ } catch {}
687
+ return { errors, warnings, total: errors + warnings }
688
+ })()`;async function be(t){await t.send({type:"evaluate",code:'window.__sootsimConsole?.clear(); window.__sootsimObservability?.logs?.clear?.(); "cleared"'})}async function fe(t,e={}){let r=e.limit??20,n=e.failed===!1?"getRequests":"getFailedRequests",o=await t.send({type:"call",path:`__sootsimTest.${n}`,args:[r]});return Array.isArray(o)?o:[]}async function he(t){await t.send({type:"call",path:"__sootsimTest.clearRequests",args:[]})}async function xe(t){let e=await t.send({type:"evaluate",code:`(() => {
689
+ const obs = window.__sootsimObservability;
690
+ if (!obs) return { ok: false };
691
+ return { ok: true, entries: obs.logs.getSnapshot() };
692
+ })()`});return!e||!e.ok?[]:e.entries??[]}async function we(t){await t.send({type:"evaluate",code:'window.__sootsimObservability?.logs.clear(); "cleared"'})}function K(t,e){if(t.source===e.source||t.level!==e.level||Math.abs(t.ts-e.ts)>1e3||t.args.length!==e.args.length)return!1;let r=new Set([t.source,e.source]);return!r.has("sootsim-worker")||!r.has("render-worker")&&!r.has("forwarded-render-worker")?!1:t.args.every((n,o)=>n===e.args[o])}function Se(t,e={}){let r=[];for(let n of t)r.some(o=>K(o,n))||r.push(n);if(e.showInternal||(r=r.filter(n=>{let o=n.args[0];return!(typeof o=="string"&&o.startsWith("[rnx]"))})),e.level&&(r=r.filter(n=>e.level.has(n.level))),e.filter){let n=e.filter.toLowerCase();r=r.filter(o=>o.args.join(" ").toLowerCase().includes(n))}return r}async function ve(t,e){return await t.send({type:"call",path:"SootSim.bridges.timeline.summary",args:[e]})}async function V(t,e){return await t.send({type:"call",path:"SootSim.bridges.timeline.recent",args:[e]})}async function Ie(t){let e;try{e=(await V(t,{kinds:["alert","actionsheet"],limit:80})).events}catch{return[]}let r=new Map;for(let s of e)r.set(s.kind,s);let n=[],o=(s,i)=>{let d=r.get(s);if(!d||!d.data||typeof d.data!="object")return;let p=d.data;p.phase==="show"&&n.push({label:i,title:typeof p.title=="string"?p.title:null})};return o("alert","Alert"),o("actionsheet","ActionSheet"),n}async function Te(t,e,r){await t.send({type:"call",path:"SootSim.bridges.timeline.cursorAdvance",args:[e,r]})}async function ke(t){return await t.send({type:"evaluate",code:`(() => {
693
+ const kb = window.__sootsimKeyboard
694
+ if (!kb || typeof kb.getLayout !== 'function') {
695
+ return { error: 'keyboard bridge getLayout() not available' }
696
+ }
697
+ return kb.getLayout()
698
+ })()`})??{error:"keyboard bridge returned no result"}}function q(t){let e=t instanceof Error?t.message:String(t);return e.includes("call target not found: SootSim.bridges.mainShell")||e.includes("test bridge unavailable before app-in-worker boot")}async function Y(t,e=0){let r=Date.now()+Math.max(0,e);for(;;)try{return await t.send({type:"call",path:"SootSim.bridges.mainShell.getState",args:[]})}catch(n){if(!q(n)||Date.now()>=r)throw n;await new Promise(o=>setTimeout(o,50))}}async function Ee(t){let e=await t.send({type:"evaluate",code:`(async () => {
699
+ const test = window.__sootsimTest
700
+ const kb = window.__sootsimKeyboard
701
+ const navSnap =
702
+ test && typeof test.getNavigationSnapshot === 'function'
703
+ ? await test.getNavigationSnapshot()
704
+ : null
705
+ const route =
706
+ test && typeof test.getRouteInfo === 'function'
707
+ ? await test.getRouteInfo()
708
+ : null
709
+ const keyboard =
710
+ kb && typeof kb.getLayout === 'function'
711
+ ? (() => {
712
+ const layout = kb.getLayout()
713
+ return layout ? {
714
+ visible: layout.visible,
715
+ mode: layout.mode,
716
+ spec: layout.spec
717
+ ? {
718
+ keyboardType: layout.spec.keyboardType,
719
+ returnKeyType: layout.spec.returnKeyType,
720
+ }
721
+ : null,
722
+ } : null
723
+ })()
724
+ : null
725
+ return { nav: navSnap, route, keyboard }
726
+ })()`});return{shell:await Y(t,500).catch(()=>null),nav:e?.nav??null,route:e?.route??null,keyboard:e?.keyboard??null}}async function Re(t){return t.send({type:"evaluate",code:"window.__sootsimDebug.status()"})}async function $e(t){return t.send({type:"evaluate",code:"window.__sootsimDebug.flags()"})}async function _e(t,e){return t.send({type:"evaluate",code:`window.__sootsimTest.debugFind(${JSON.stringify(e)})`})}async function Ae(t,e,r=50){let n=e&&e!=="all"?`window.__sootsimDebug.recent(${JSON.stringify(e)}, ${r})`:`window.__sootsimDebug.recent(undefined, ${r})`;return t.send({type:"evaluate",code:n})}async function Le(t,e,r){let n=r.length>0?r.map(o=>JSON.stringify(o)).join(", "):e==="disable"?"'all'":"";return t.send({type:"evaluate",code:`window.__sootsimDebug.${e}(${n})`})}async function Pe(t){return await t.send({type:"evaluate",code:`(async () => {
727
+ const host = window.__sootsimRenderHost
728
+ const stats = host?.queryStats ? await host.queryStats() : null
729
+ const shellRaw = window.__sootsimShellMemory
730
+ ? await window.__sootsimShellMemory()
731
+ : null
732
+ const shell = shellRaw && !shellRaw.error ? shellRaw : null
733
+ // the compositor paints home + app:one + app:two, so every app-surface
734
+ // picture and raster image is counted here and nowhere else.
735
+ let compositor = null
736
+ try {
737
+ const cs = await window.__sootsimCompositor?.getStats?.(false, true)
738
+ compositor = cs?.memory ?? null
739
+ } catch {}
740
+ const normalize = (m) =>
741
+ m
742
+ ? {
743
+ nodesRegistered: m.nodesRegistered ?? null,
744
+ nodesDetached: m.nodesDetached ?? null,
745
+ detachedTypes: m.detachedTypes ?? null,
746
+ objects: m.objects ?? null,
747
+ activeNativeAnimations: m.activeNativeAnimations ?? null,
748
+ imageLoader: m.imageLoader ?? null,
749
+ workerHeap: m.workerHeap ?? null,
750
+ wasmHeapBytes: m.wasmHeapBytes ?? null,
751
+ }
752
+ : null
753
+ const hostMem = performance.memory
754
+ ? {
755
+ usedJSHeapSize: performance.memory.usedJSHeapSize,
756
+ totalJSHeapSize: performance.memory.totalJSHeapSize,
757
+ jsHeapSizeLimit: performance.memory.jsHeapSizeLimit,
758
+ }
759
+ : null
760
+ return {
761
+ tenant: normalize(stats?.memory),
762
+ shell: normalize(shell),
763
+ compositor: normalize(compositor),
764
+ hostHeap: hostMem,
765
+ }
766
+ })()`})??{tenant:null,shell:null,compositor:null,hostHeap:null}}function Ne(t){if(t.total===0)return"nothing recorded";let e=[],r=["error","warning","console","fetch","toast","alert","actionsheet","picker","notification","screen","route","keyboard","app-launch","shell","scroll","gesture","text-input","react-commit","animation","reanimated"],n=new Set;for(let o of r){let s=t.byKind[o];s&&(e.push(`${s} ${o}${s===1?"":"s"}`),n.add(o))}for(let[o,s]of Object.entries(t.byKind))!n.has(o)&&s&&e.push(`${s} ${o}${s===1?"":"s"}`);return e.join(" \xB7 ")}var Me=new Set(["react-commit","layout","scroll"]);function U(t,e){if(e===null)return new Date(t).toLocaleTimeString();let r=(t-e)/1e3;return`${r>=0?"+":""}${r.toFixed(2)}s`}function G(t,e){switch(t){case"app-launch":return e.phase==="launch"?`launch ${e.appName??e.toAppId??""}`:`dismiss ${e.appName??e.fromAppId??""} \u2192 ${e.toAppId??""}`;case"toast":return`"${e.text??""}"${e.durationMs?` (${e.durationMs}ms)`:""}`;case"keyboard":return`${e.phase??"?"}${e.heightPx?` h=${e.heightPx}`:""}${e.mode?` ${e.mode}`:""}`;case"screen":return`${e.phase??"?"} ${e.name??e.activeName??""}`;case"flow-step":return`${e.status??"?"} ${e.stepName??"step"}${e.durationMs?` ${e.durationMs}ms`:""}`;case"route":return`${e.phase??"?"} ${e.path??e.pathname??""}`;case"alert":case"actionsheet":case"picker":return`${e.phase??"?"} ${e.title??e.message??""}`;case"notification":return`${e.title??""}${e.body?` \u2014 ${e.body}`:""}`;case"fetch":return`${e.method??"GET"} ${e.url??""}${e.status?` -> ${e.status}`:""}`;case"console":case"console-log":return`${e.level??"log"}: ${(e.message??"").toString().slice(0,120)}`;case"shell":return`${e.event??e.type??e.phase??""}`;case"scroll":return`${e.phase??"?"} ${e.target??""}`;case"gesture":return`${e.phase??"?"} ${e.type??""}`;case"text-input":return`${e.phase??"?"}${e.value!==void 0?` "${String(e.value).slice(0,40)}"`:""}`;case"layout":return`${e.kind??"?"} ${e.testID??e.type??""}${e.skipped?` skipped:${e.reason??"unknown"}`:""}`;case"react-commit":{let r=e.slowest;return`${e.fiberCount??"?"} fibers ${e.durationMs??"?"}ms${r?.displayName?` \xB7 ${r.displayName} ${r.durationMs??"?"}ms`:""}`}case"frame":return`${e.totalMs??"?"}ms${e.renderMs?` \xB7 render ${e.renderMs}ms`:""}${e.layoutMs?` \xB7 layout ${e.layoutMs}ms`:""}${e.copyMs?` \xB7 copy ${e.copyMs}ms`:""}`;case"reanimated":case"animation":return`${e.kind??""} ${e.target??""}${e.durationMs?` ${e.durationMs}ms`:""}`}return""}function De(t,e){let r=U(t.t,e).padStart(8),n=t.context.padEnd(6),o=`[${t.kind}]`.padEnd(15),s=t.data,i=s&&typeof s=="object"?G(t.kind,s):"";return` ${r} ${n} ${o} ${i}`}export{Q as a,X as b,Z as c,ee as d,te as e,ne as f,oe as g,se as h,ae as i,ie as j,le as k,ue as l,F as m,H as n,z as o,j as p,J as q,ce as r,de as s,pe as t,ye as u,me as v,ge as w,be as x,fe as y,he as z,xe as A,we as B,Se as C,ve as D,V as E,Ie as F,Te as G,ke as H,q as I,Y as J,Ee as K,Re as L,$e as M,_e as N,Ae as O,Le as P,Pe as Q,Ne as R,Me as S,De as T};