sootsim 0.1.167 → 0.1.168

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 (159) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-FGNA3LC6.js → agent-V5N6TSVL.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-5CRKG7K7.js → agent-wrapper-M32Q4WRZ.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-CM3ML6NV.js → app-fonts-QJCMHTWY.js} +2 -2
  5. package/dist-cli/chunks/{assert-DCO6XYDU.js → assert-FUPVKOCV.js} +2 -2
  6. package/dist-cli/chunks/auto-bootstrap-BMAKK4FR.js +2 -0
  7. package/dist-cli/chunks/beta-ERD6Z2EE.js +2 -0
  8. package/dist-cli/chunks/{camera-HWLYOMJV.js → camera-6Z3YMMEG.js} +2 -2
  9. package/dist-cli/chunks/{chunk-WXFUXFY7.js → chunk-27Q45J2N.js} +2 -2
  10. package/dist-cli/chunks/{chunk-T4UHUISG.js → chunk-2DDHS4Z3.js} +1 -1
  11. package/dist-cli/chunks/chunk-2UDB2A2Z.js +119 -0
  12. package/dist-cli/chunks/chunk-4PXQB4KC.js +2 -0
  13. package/dist-cli/chunks/{chunk-JDFPPPPS.js → chunk-4TJ2FLZX.js} +1 -1
  14. package/dist-cli/chunks/{chunk-3RHECMKV.js → chunk-5GGI6NGS.js} +3 -3
  15. package/dist-cli/chunks/chunk-5PEYA6XI.js +1 -0
  16. package/dist-cli/chunks/chunk-6MBEHPFK.js +1 -0
  17. package/dist-cli/chunks/{chunk-MI7BLMGH.js → chunk-7YQ7CJFO.js} +2 -2
  18. package/dist-cli/chunks/{chunk-3MQAPPOW.js → chunk-AFPKG2L6.js} +1 -1
  19. package/dist-cli/chunks/{chunk-UF2T46AA.js → chunk-BKYCQJKE.js} +2 -2
  20. package/dist-cli/chunks/{chunk-JL7K7EPF.js → chunk-BLRVSHCX.js} +3 -3
  21. package/dist-cli/chunks/{chunk-DWYDDN7J.js → chunk-BSKD5K5N.js} +2 -2
  22. package/dist-cli/chunks/{chunk-ACNSMZSP.js → chunk-BUCBIG2A.js} +1 -1
  23. package/dist-cli/chunks/chunk-EMWWY2MH.js +2 -0
  24. package/dist-cli/chunks/{chunk-47JNNTYQ.js → chunk-ENK2SG5R.js} +1 -1
  25. package/dist-cli/chunks/chunk-FAEIKMNH.js +1 -0
  26. package/dist-cli/chunks/{chunk-U7LLQDO4.js → chunk-FZ656TJA.js} +1 -1
  27. package/dist-cli/chunks/chunk-HIAR3KTT.js +5 -0
  28. package/dist-cli/chunks/{chunk-DAMNOIAJ.js → chunk-IHVCKNFX.js} +2 -2
  29. package/dist-cli/chunks/{chunk-EIMDQRZS.js → chunk-JJIJVKAV.js} +2 -2
  30. package/dist-cli/chunks/{chunk-2UGS25BK.js → chunk-L62FIJ3P.js} +1 -1
  31. package/dist-cli/chunks/{chunk-ZLZ3R452.js → chunk-L7F7QBGM.js} +2 -2
  32. package/dist-cli/chunks/{chunk-AB6TZFIE.js → chunk-LCHPOJOO.js} +1 -1
  33. package/dist-cli/chunks/{chunk-RTBG543W.js → chunk-MGB5W5VY.js} +2 -2
  34. package/dist-cli/chunks/{chunk-HCNW2QTI.js → chunk-MHEP6UMF.js} +3 -3
  35. package/dist-cli/chunks/{chunk-PDPBZD5O.js → chunk-MO3L5VGD.js} +1 -1
  36. package/dist-cli/chunks/{chunk-TFF3KXNC.js → chunk-MQWZBKOF.js} +1 -1
  37. package/dist-cli/chunks/{chunk-27CWE62K.js → chunk-MRPFNK2L.js} +2 -2
  38. package/dist-cli/chunks/{chunk-F5REXFAW.js → chunk-N6CHIBHJ.js} +2 -2
  39. package/dist-cli/chunks/{chunk-UC7LRLPE.js → chunk-OC4Y3UIV.js} +1 -1
  40. package/dist-cli/chunks/chunk-PPIRXSWS.js +13 -0
  41. package/dist-cli/chunks/{chunk-D6QVHHDU.js → chunk-QBYYAPTB.js} +1 -1
  42. package/dist-cli/chunks/{chunk-QIXDVNSM.js → chunk-QGL6XWHB.js} +2 -2
  43. package/dist-cli/chunks/{chunk-GNHGTWDX.js → chunk-QMQBMB4S.js} +2 -2
  44. package/dist-cli/chunks/{chunk-SIRMLK54.js → chunk-QWNLVJ4P.js} +1 -1
  45. package/dist-cli/chunks/{chunk-DM2EOTY5.js → chunk-SHCQRQJA.js} +2 -2
  46. package/dist-cli/chunks/{chunk-2QPTZHGU.js → chunk-SMBSZIDN.js} +2 -2
  47. package/dist-cli/chunks/{chunk-VCKKDUWG.js → chunk-TXZKEW6C.js} +2 -2
  48. package/dist-cli/chunks/{chunk-OKBGHUCY.js → chunk-VHVFXSXT.js} +1 -1
  49. package/dist-cli/chunks/{chunk-IV5NEIXZ.js → chunk-WUKEI6SL.js} +2 -2
  50. package/dist-cli/chunks/{chunk-MGX3HHAR.js → chunk-XUABY4IN.js} +1 -1
  51. package/dist-cli/chunks/{chunk-KCETAALD.js → chunk-XWG6NJJE.js} +2 -2
  52. package/dist-cli/chunks/{chunk-JI72D4RY.js → chunk-YNTWHWFY.js} +1 -1
  53. package/dist-cli/chunks/{chunk-OGH3OCGP.js → chunk-YR7WIUVL.js} +2 -2
  54. package/dist-cli/chunks/{chunk-ELHNXEJI.js → chunk-ZIEXUO4S.js} +2 -2
  55. package/dist-cli/chunks/cli-version-P4CDXF4L.js +2 -0
  56. package/dist-cli/chunks/{compat-WZAQMU3Y.js → compat-CH6BYJ4T.js} +3 -3
  57. package/dist-cli/chunks/{config-EMVWQLSZ.js → config-ST33XAYN.js} +2 -2
  58. package/dist-cli/chunks/control-FW6XTHQE.js +2 -0
  59. package/dist-cli/chunks/{cpu-profile-FIXB3BPM.js → cpu-profile-VMHZN3WB.js} +2 -2
  60. package/dist-cli/chunks/{daemon-VPUPR3CK.js → daemon-5DEUBHYC.js} +2 -2
  61. package/dist-cli/chunks/{debug-QW2VVENB.js → debug-WQP3TJ62.js} +3 -3
  62. package/dist-cli/chunks/{detox-RLEEW5BN.js → detox-IAWL5YVJ.js} +2 -2
  63. package/dist-cli/chunks/{device-MCFZ5J5W.js → device-GYJ6BHY7.js} +2 -2
  64. package/dist-cli/chunks/{diagnose-VSSY5XMS.js → diagnose-GFDUQYHG.js} +2 -2
  65. package/dist-cli/chunks/drivers-VTVBB4KQ.js +2 -0
  66. package/dist-cli/chunks/{electron-OD7H7UBA.js → electron-CF7HUVQL.js} +3 -3
  67. package/dist-cli/chunks/flow-GZZ7OVM3.js +2 -0
  68. package/dist-cli/chunks/help-EUSCLRLF.js +2 -0
  69. package/dist-cli/chunks/{hints-TU5HBDRY.js → hints-HF2LDTK7.js} +2 -2
  70. package/dist-cli/chunks/{home-paths-6WZQKHRA.js → home-paths-ZBDTVPMF.js} +2 -2
  71. package/dist-cli/chunks/{inspect-UNZ7Z5PF.js → inspect-P2MPMFR3.js} +136 -133
  72. package/dist-cli/chunks/install-N4QT365P.js +2 -0
  73. package/dist-cli/chunks/{install-desktop-6LB2C5H5.js → install-desktop-QYLXYZQJ.js} +3 -3
  74. package/dist-cli/chunks/{keys-5XMDDDUV.js → keys-LJ37JUG2.js} +2 -2
  75. package/dist-cli/chunks/{launch-RVQHYE5V.js → launch-3TUC2YGM.js} +3 -3
  76. package/dist-cli/chunks/{login-BGMYYUK2.js → login-RUZ7MAPC.js} +4 -4
  77. package/dist-cli/chunks/{logout-PXZVOWLU.js → logout-4RE2BP3H.js} +2 -2
  78. package/dist-cli/chunks/{maestro-RIGROEAZ.js → maestro-V62C4AQM.js} +2 -2
  79. package/dist-cli/chunks/optional-demo-registry-ZEPUCMEO.js +2 -0
  80. package/dist-cli/chunks/{preview-3XCXJMNU.js → preview-3HWBUCVM.js} +2 -2
  81. package/dist-cli/chunks/{profile-7MQEP55V.js → profile-D2CAEFO5.js} +2 -2
  82. package/dist-cli/chunks/{react-BBOQIY6V.js → react-PXYQBCAK.js} +2 -2
  83. package/dist-cli/chunks/{record-4U2X6JDH.js → record-R7IDN3T6.js} +2 -2
  84. package/dist-cli/chunks/runtime-RQOM2I2S.js +2 -0
  85. package/dist-cli/chunks/{runtime-delivery-VK2HCMQW.js → runtime-delivery-K4LFILF7.js} +2 -2
  86. package/dist-cli/chunks/{screenshot-MCFHIP2H.js → screenshot-YGGPEX7B.js} +2 -2
  87. package/dist-cli/chunks/{screenshot-mode-VJEAECKO.js → screenshot-mode-QDUWRQUF.js} +2 -2
  88. package/dist-cli/chunks/{screenshots-3NSCRA3U.js → screenshots-6PNFJNLF.js} +2 -2
  89. package/dist-cli/chunks/{server-HIPHVNKP.js → server-7Q3NW5MV.js} +3 -3
  90. package/dist-cli/chunks/setup-repo-UZMY3JFZ.js +2 -0
  91. package/dist-cli/chunks/{skills-JILZXX7E.js → skills-GDYPRMR5.js} +2 -2
  92. package/dist-cli/chunks/{slides-IWZX6TCC.js → slides-HJXHSWEF.js} +2 -2
  93. package/dist-cli/chunks/{start-4RYQMQMM.js → start-HDWGM5WJ.js} +4 -4
  94. package/dist-cli/chunks/store-5DYIIFYH.js +2 -0
  95. package/dist-cli/chunks/telemetry-TMT3DYZU.js +2 -0
  96. package/dist-cli/chunks/{test-VQ6HIPKR.js → test-4TUHEODP.js} +3 -3
  97. package/dist-cli/chunks/{three-mode-UWH72A46.js → three-mode-IL5442GI.js} +2 -2
  98. package/dist-cli/chunks/{timeline-T6LM4W3H.js → timeline-JILPOKRF.js} +2 -2
  99. package/dist-cli/chunks/{upgrade-KEJ2H2WE.js → upgrade-SL5WMHSF.js} +2 -2
  100. package/dist-cli/chunks/upload-35XW4DMZ.js +2 -0
  101. package/dist-cli/chunks/{version-PIJ2OP5O.js → version-ZEBIO5HC.js} +2 -2
  102. package/dist-cli/chunks/{web-DCGXY52J.js → web-JICQ5RN4.js} +2 -2
  103. package/dist-cli/chunks/{what-happened-CUA3N455.js → what-happened-KKAJOJWO.js} +2 -2
  104. package/dist-cli/chunks/{whoami-Z5XNGCGJ.js → whoami-QDJPYI2O.js} +2 -2
  105. package/dist-lib/agent-daemon-client.cjs +1 -1
  106. package/dist-lib/agent-events.cjs +1 -1
  107. package/dist-lib/agent-sessions.cjs +1 -1
  108. package/dist-lib/attached-projects.cjs +1 -1
  109. package/dist-lib/auth/shared-session.cjs +1 -1
  110. package/dist-lib/backend-origin.cjs +1 -1
  111. package/dist-lib/beta.cjs +1 -1
  112. package/dist-lib/beta.mjs +1 -1
  113. package/dist-lib/bridge-constants.cjs +1 -1
  114. package/dist-lib/cli-constants.cjs +1 -1
  115. package/dist-lib/config.cjs +1 -1
  116. package/dist-lib/detox/index.cjs +1 -1
  117. package/dist-lib/dev-bundle-resolution.cjs +10 -2
  118. package/dist-lib/home-paths.cjs +1 -1
  119. package/dist-lib/host/bridge-host.cjs +4 -1
  120. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  121. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  122. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  123. package/dist-lib/host/websocket-proxy.cjs +1 -1
  124. package/dist-lib/index.cjs +1 -1
  125. package/dist-lib/menu.cjs +1 -1
  126. package/dist-lib/menu.mjs +1 -1
  127. package/dist-lib/metro.cjs +1 -1
  128. package/dist-lib/profiles.cjs +1 -1
  129. package/dist-lib/render-mode.cjs +1 -1
  130. package/dist-lib/scripts/dev-server-scanner.cjs +4 -1
  131. package/dist-lib/sdk.cjs +1 -1
  132. package/dist-lib/sdk.mjs +1 -1
  133. package/dist-lib/skills.cjs +4 -1
  134. package/dist-lib/vite.cjs +1 -1
  135. package/package.json +1 -1
  136. package/src/dev-bundle-resolution.ts +6 -1
  137. package/src/native-dev-bundle-url.ts +12 -0
  138. package/dist-cli/chunks/auto-bootstrap-QJUHQLQH.js +0 -2
  139. package/dist-cli/chunks/beta-W5Y32GJR.js +0 -2
  140. package/dist-cli/chunks/chunk-7P6CUODK.js +0 -1
  141. package/dist-cli/chunks/chunk-BIG5BGMC.js +0 -5
  142. package/dist-cli/chunks/chunk-E5E7XQIN.js +0 -2
  143. package/dist-cli/chunks/chunk-F2UUNDRU.js +0 -119
  144. package/dist-cli/chunks/chunk-F5PLWUIU.js +0 -1
  145. package/dist-cli/chunks/chunk-HHOQMAVJ.js +0 -1
  146. package/dist-cli/chunks/chunk-MPUONWKJ.js +0 -13
  147. package/dist-cli/chunks/chunk-QX25ZRIQ.js +0 -2
  148. package/dist-cli/chunks/cli-version-RHOJPOQJ.js +0 -2
  149. package/dist-cli/chunks/control-P3M34LCO.js +0 -2
  150. package/dist-cli/chunks/drivers-GPZ62RP5.js +0 -2
  151. package/dist-cli/chunks/flow-JFSZHDB2.js +0 -2
  152. package/dist-cli/chunks/help-DFQRIC3T.js +0 -2
  153. package/dist-cli/chunks/install-7JTNTNNX.js +0 -2
  154. package/dist-cli/chunks/optional-demo-registry-GQL6Z6OH.js +0 -2
  155. package/dist-cli/chunks/runtime-HPZWCYML.js +0 -2
  156. package/dist-cli/chunks/setup-repo-LFSW66HX.js +0 -2
  157. package/dist-cli/chunks/store-RGD3TDGI.js +0 -2
  158. package/dist-cli/chunks/telemetry-7TRVV4JE.js +0 -2
  159. package/dist-cli/chunks/upload-BWSIC24N.js +0 -2
@@ -1,6 +1,6 @@
1
- /*! sootsim v0.1.167 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}from"./chunk-GNHGTWDX.js";import{b as Tt,c as Mt,j as It}from"./chunk-MPUONWKJ.js";import"./chunk-BIG5BGMC.js";import{a as ee,b as A,c as P,d as Re,e as ie,f as G,g as ue,h as fe,i as xt,j as $t,k as De,l as St}from"./chunk-2QPTZHGU.js";import{A as gt,B as yt,F as ht,H as ce,I as bt,O as wt,a as xe,b as Ze,c as et,d as tt,e as ot,f as st,g as nt,h as rt,i as it,j as at,k as Ae,l as Pe,q as Ee,r as lt,s as ct,t as $e,u as ut,v as Se,w as dt,x as mt,y as pt,z as ft}from"./chunk-AB6TZFIE.js";import"./chunk-JDFPPPPS.js";import"./chunk-47JNNTYQ.js";import{c as Ge,e as Ye,f as Xe,g as Ve,h as Oe}from"./chunk-ZLZ3R452.js";import"./chunk-3MQAPPOW.js";import"./chunk-DAMNOIAJ.js";import"./chunk-MGX3HHAR.js";import"./chunk-MI7BLMGH.js";import"./chunk-7P6CUODK.js";import"./chunk-PDPBZD5O.js";import{a as Ke}from"./chunk-QX25ZRIQ.js";import{a as Fe,c as _e}from"./chunk-F2UUNDRU.js";import{a as Y}from"./chunk-UF2T46AA.js";import{a as Ue}from"./chunk-E5E7XQIN.js";import"./chunk-U7LLQDO4.js";import{b as ze}from"./chunk-D6QVHHDU.js";import"./chunk-TFF3KXNC.js";import"./chunk-ACNSMZSP.js";import{existsSync as fo,mkdirSync as go,readFileSync as yo,rmSync as Nt,writeFileSync as ho}from"fs";import{tmpdir as bo}from"os";import{dirname as wo,join as xo,resolve as $o}from"path";var ge=1,So="SOOTSIM_INSPECT_NOTICE_PATH",vo=300*1e3,ko=15e3;function Ft(){return $o(process.env[So]||xo(bo(),"sootsim-inspect-notice-state.json"))}function To(e,l){return Object.fromEntries(Object.entries(e).filter(([,n])=>typeof n?.signature=="string"&&Number.isFinite(n?.updatedAt)&&l-n.updatedAt<=vo))}function Mo(e){let l=Ft();if(!fo(l))return{version:ge,entries:{}};try{let n=JSON.parse(yo(l,"utf8"));return n.version!==ge||!n.entries||typeof n.entries!="object"?(Nt(l,{force:!0}),{version:ge,entries:{}}):{version:ge,entries:To(n.entries,e)}}catch{return Nt(l,{force:!0}),{version:ge,entries:{}}}}function Io(e){let l=Ft();go(wo(l),{recursive:!0}),ho(l,JSON.stringify(e,null,2)+`
3
- `)}function No(e,l){let n=l.trim()||"default";return`${e}:${n}`}function Ce(e,l,n,c={}){let m=c.nowMs??Date.now(),i=c.cooldownMs??ko,g=Mo(m),y=No(e,l),T=g.entries[y];return T&&T.signature===n&&m-T.updatedAt<i?!1:(g.entries[y]={signature:n,updatedAt:m},Io(g),!0)}var Fo={initialWaitMs:3e3,deadlineMs:5e3,retryWaitMs:700},_o={initialWaitMs:1200,deadlineMs:2500,retryWaitMs:700};function Oo(e,l={}){return{...e?Fo:_o,...l}}function de(e){return!(!e||e.hit===!1||e.ok===!1||e.pointerTapHandled===!1&&!e.keyboardOpened&&!e.isTextInput)}function Ao(e,l){return{id:e.target?.id??e.match?.id??e.node?.id??null,testID:e.target?.testID??e.match?.testID??e.node?.testID??null,text:e.target?.text??e.target?.accessibilityLabel??e.match?.text??e.match?.accessibilityLabel??e.node?.text??l??null,type:e.target?.type??e.match?.type??e.node?.type??null}}async function ye(e,l){let n=Oo(!!l.agent,l.timing),c=0,m=null,i=null;try{await te({bridge:e,maxMs:n.initialWaitMs,pollMs:32,stablePolls:2})}catch{}let g=Date.now()+n.deadlineMs;for(;Date.now()<=g||c===0;){c++;let y=await l.resolve();if(m=y,y?.error==="bridge-not-ready"||y?.ambiguous||y?.nthOutOfRange)return{payload:y,result:null,attempts:c,failure:"special"};if(y&&typeof y.cx=="number"&&typeof y.cy=="number"){let M=await e.send({type:"tap",x:y.cx,y:y.cy,target:Ao(y,l.textFallback)});if(i=M,de(M))return{payload:y,result:M,attempts:c}}let T=g-Date.now();if(T<=0)break;try{await te({bridge:e,maxMs:Math.min(T,n.retryWaitMs),pollMs:32,stablePolls:2})}catch{await new Promise(M=>setTimeout(M,Math.min(120,T)))}}return{payload:m,result:i,attempts:c,failure:m&&typeof m.cx=="number"?"missed":"not-found"}}async function _t(e,l,n,c){return e.send({type:"tap",x:l,y:n,...c?{target:c}:{}})}async function Ot(e,l,n={}){let c=JSON.stringify(l);return ye(e,{agent:n.agent,timing:n.timing,resolve:()=>e.send({type:"evaluate",code:`(async () => {
1
+ /*! sootsim v0.1.168 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as vt,b as kt}from"./chunk-OC4Y3UIV.js";import{a as Ee,g as ke,j as te}from"./chunk-QMQBMB4S.js";import{b as Tt,c as Mt,j as It}from"./chunk-PPIRXSWS.js";import"./chunk-HIAR3KTT.js";import{a as ee,b as A,c as E,d as Be,e as ie,f as G,g as de,h as ge,i as xt,j as $t,k as ve,l as St}from"./chunk-SMBSZIDN.js";import{A as gt,B as yt,F as bt,H as ce,I as ht,O as wt,a as $e,b as et,c as tt,d as ot,e as st,f as nt,g as rt,h as it,i as at,j as lt,k as Pe,l as Re,q as De,r as ct,s as dt,t as fe,u as ut,v as Se,w as Ce,x as mt,y as pt,z as ft}from"./chunk-LCHPOJOO.js";import"./chunk-4TJ2FLZX.js";import"./chunk-ENK2SG5R.js";import{c as Xe,e as Ve,f as Qe,g as Ze,h as Ae}from"./chunk-L7F7QBGM.js";import"./chunk-AFPKG2L6.js";import"./chunk-IHVCKNFX.js";import"./chunk-XUABY4IN.js";import"./chunk-7YQ7CJFO.js";import"./chunk-6MBEHPFK.js";import"./chunk-MO3L5VGD.js";import{a as ze}from"./chunk-4PXQB4KC.js";import{a as _e,c as Oe}from"./chunk-2UDB2A2Z.js";import{a as Y}from"./chunk-BKYCQJKE.js";import{a as Ge}from"./chunk-EMWWY2MH.js";import"./chunk-FZ656TJA.js";import{b as Ye}from"./chunk-QBYYAPTB.js";import"./chunk-MQWZBKOF.js";import"./chunk-BUCBIG2A.js";import{existsSync as go,mkdirSync as yo,readFileSync as bo,rmSync as Nt,writeFileSync as ho}from"fs";import{tmpdir as wo}from"os";import{dirname as xo,join as $o,resolve as So}from"path";var ye=1,vo="SOOTSIM_INSPECT_NOTICE_PATH",ko=300*1e3,To=15e3;function Ft(){return So(process.env[vo]||$o(wo(),"sootsim-inspect-notice-state.json"))}function Mo(e,l){return Object.fromEntries(Object.entries(e).filter(([,r])=>typeof r?.signature=="string"&&Number.isFinite(r?.updatedAt)&&l-r.updatedAt<=ko))}function Io(e){let l=Ft();if(!go(l))return{version:ye,entries:{}};try{let r=JSON.parse(bo(l,"utf8"));return r.version!==ye||!r.entries||typeof r.entries!="object"?(Nt(l,{force:!0}),{version:ye,entries:{}}):{version:ye,entries:Mo(r.entries,e)}}catch{return Nt(l,{force:!0}),{version:ye,entries:{}}}}function No(e){let l=Ft();yo(xo(l),{recursive:!0}),ho(l,JSON.stringify(e,null,2)+`
3
+ `)}function Fo(e,l){let r=l.trim()||"default";return`${e}:${r}`}function je(e,l,r,c={}){let p=c.nowMs??Date.now(),a=c.cooldownMs??To,g=Io(p),y=Fo(e,l),T=g.entries[y];return T&&T.signature===r&&p-T.updatedAt<a?!1:(g.entries[y]={signature:r,updatedAt:p},No(g),!0)}var _o={initialWaitMs:3e3,deadlineMs:5e3,retryWaitMs:700},Oo={initialWaitMs:1200,deadlineMs:2500,retryWaitMs:700};function Ao(e,l={}){return{...e?_o:Oo,...l}}function ue(e){return!(!e||e.hit===!1||e.ok===!1||e.pointerTapHandled===!1&&!e.keyboardOpened&&!e.isTextInput)}function Eo(e,l){return{id:e.target?.id??e.match?.id??e.node?.id??null,testID:e.target?.testID??e.match?.testID??e.node?.testID??null,text:e.target?.text??e.target?.accessibilityLabel??e.match?.text??e.match?.accessibilityLabel??e.node?.text??l??null,type:e.target?.type??e.match?.type??e.node?.type??null}}async function be(e,l){let r=Ao(!!l.agent,l.timing),c=0,p=null,a=null;try{await te({bridge:e,maxMs:r.initialWaitMs,pollMs:32,stablePolls:2})}catch{}let g=Date.now()+r.deadlineMs;for(;Date.now()<=g||c===0;){c++;let y=await l.resolve();if(p=y,y?.error==="bridge-not-ready"||y?.ambiguous||y?.nthOutOfRange)return{payload:y,result:null,attempts:c,failure:"special"};if(y&&typeof y.cx=="number"&&typeof y.cy=="number"){let M=await e.send({type:"tap",x:y.cx,y:y.cy,target:Eo(y,l.textFallback)});if(a=M,ue(M))return{payload:y,result:M,attempts:c}}let T=g-Date.now();if(T<=0)break;try{await te({bridge:e,maxMs:Math.min(T,r.retryWaitMs),pollMs:32,stablePolls:2})}catch{await new Promise(M=>setTimeout(M,Math.min(120,T)))}}return{payload:p,result:a,attempts:c,failure:p&&typeof p.cx=="number"?"missed":"not-found"}}async function _t(e,l,r,c){return e.send({type:"tap",x:l,y:r,...c?{target:c}:{}})}async function Ot(e,l,r={}){let c=JSON.stringify(l);return be(e,{agent:r.agent,timing:r.timing,resolve:()=>e.send({type:"evaluate",code:`(async () => {
4
4
  const t = window.__sootsimTest
5
5
  if (!t) return null
6
6
  const n = (await t.findByTestId(${c})) || (await t.findById(${c}))
@@ -42,10 +42,10 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
42
42
  },
43
43
  strategy: (resolved && resolved.strategy) || 'matched-node',
44
44
  }
45
- })()`})})}async function At(e,l,n={},c={}){let m=JSON.stringify({query:l,exact:!!n.exact,role:n.role??null,within:n.within??null,minX:n.minX??null,maxX:n.maxX??null,minY:n.minY??null,maxY:n.maxY??null,near:n.near??null,nth:n.nth??null,first:!!n.first});return ye(e,{agent:c.agent,timing:c.timing,textFallback:l,resolve:()=>e.send({type:"evaluate",code:`(async () => {
45
+ })()`})})}async function At(e,l,r={},c={}){let p=JSON.stringify({query:l,exact:!!r.exact,role:r.role??null,within:r.within??null,minX:r.minX??null,maxX:r.maxX??null,minY:r.minY??null,maxY:r.maxY??null,near:r.near??null,nth:r.nth??null,first:!!r.first});return be(e,{agent:c.agent,timing:c.timing,textFallback:l,resolve:()=>e.send({type:"evaluate",code:`(async () => {
46
46
  const t = window.__sootsimTest
47
47
  if (!t) return { error: 'bridge-not-ready' }
48
- const F = ${m}
48
+ const F = ${p}
49
49
 
50
50
  const res = await t.queryTextCandidates({
51
51
  query: F.query,
@@ -162,7 +162,7 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
162
162
  total,
163
163
  idx,
164
164
  }
165
- })()`})})}async function Pt(e,l,n={}){let c=JSON.stringify(l);return ye(e,{agent:n.agent,timing:n.timing,textFallback:l,resolve:async()=>{let m=await e.send({type:"evaluate",code:`(async () => {
165
+ })()`})})}async function Et(e,l,r={}){let c=JSON.stringify(l);return be(e,{agent:r.agent,timing:r.timing,textFallback:l,resolve:async()=>{let p=await e.send({type:"evaluate",code:`(async () => {
166
166
  const t = window.__sootsimTest
167
167
  if (!t) return { error: 'bridge-not-ready' }
168
168
  const byTestId =
@@ -197,16 +197,16 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
197
197
  }
198
198
  }
199
199
  return { strategy: 'none' }
200
- })()`});if(!m||!("node"in m))return m;let i=m.node,g=i.absolutePosition.x+i.layout.width/2,y=i.absolutePosition.y+i.layout.height/2;return{...m,cx:g,cy:y,target:{id:i.id,testID:i.testID,text:m.strategy==="text"?l:i.text,type:i.type}}}})}async function Et(e,l={args:[]}){let n=await et(e);if(A(l.args)){P(n);return}console.log(` nodes: ${n.nodes}`)}function Be(e,l){let n=e.indexOf(l);return n>=0&&n+1<e.length?e[n+1]:null}async function Rt(e){let{bridge:l,args:n,positional:c}=e,m=n.includes("--verbose")||n.includes("-v"),i=A(n),g=m&&!i,y=n.includes("--watch")||n.includes("-w"),T=1e3,M=n.includes("--compact"),b=n.includes("--no-xy"),k=n.includes("--no-clipped"),_=n.includes("--include-occluded"),I=Be(n,"--testid-like"),E=Be(n,"--only"),j=Be(n,"--subtree"),u=c[1]&&!c[1].startsWith("-")?c[1]:void 0,z=u?/[*?]/.test(u):!1,B=!z&&!E?u:void 0,D=E??(z?u:void 0),Q=async()=>{await ue(l,{verbose:g});let S=await st(l,{describe:!0,verbose:m,filter:B||"",testIdLike:I||void 0,onlyGlob:D||void 0,subtreeRoot:j||void 0,compact:M,hideXy:b,includeOccluded:_}),N=S?.tree,J=S?.shell,W=S?.keyboard;if(i){P({shell:J,tree:N??"",keyboard:W});return}if(J&&typeof J=="object"){let C=[J.state?`state=${J.state}`:null,J.activeApp?`app=${J.activeApp}`:null,J.showSwitcher?"switcher":null,J.switcherPhase&&J.switcherPhase!=="idle"?`phase=${J.switcherPhase}`:null].filter(Boolean);C.length>0&&console.log(` shell: ${C.join(" ")}`)}if(typeof N=="string"&&N.startsWith("__SUBTREE_NOT_FOUND__:")){let C=N.slice(22);console.log(` subtree root not found: ${C}`),Y("subtree-root-not-found",C);return}if(!N){let C=S?.nodeCount??0;console.log(" no matching nodes found"),!(B||I||D||j)&&C<10&&Y("app-still-loading",C);return}let V=N,Z=0;if(k&&typeof V=="string"){let C=V.split(`
200
+ })()`});if(!p||!("node"in p))return p;let a=p.node,g=a.absolutePosition.x+a.layout.width/2,y=a.absolutePosition.y+a.layout.height/2;return{...p,cx:g,cy:y,target:{id:a.id,testID:a.testID,text:p.strategy==="text"?l:a.text,type:a.type}}}})}async function Pt(e,l={args:[]}){let r=await tt(e);if(A(l.args)){E(r);return}console.log(` nodes: ${r.nodes}`)}function Le(e,l){let r=e.indexOf(l);return r>=0&&r+1<e.length?e[r+1]:null}async function Rt(e){let{bridge:l,args:r,positional:c}=e,p=r.includes("--verbose")||r.includes("-v"),a=A(r),g=p&&!a,y=r.includes("--watch")||r.includes("-w"),T=1e3,M=r.includes("--compact"),h=r.includes("--no-xy"),k=r.includes("--no-clipped"),_=r.includes("--include-occluded"),I=Le(r,"--testid-like"),P=Le(r,"--only"),j=Le(r,"--subtree"),d=c[1]&&!c[1].startsWith("-")?c[1]:void 0,z=d?/[*?]/.test(d):!1,B=!z&&!P?d:void 0,D=P??(z?d:void 0),Q=async()=>{await de(l,{verbose:g});let S=await nt(l,{describe:!0,verbose:p,filter:B||"",testIdLike:I||void 0,onlyGlob:D||void 0,subtreeRoot:j||void 0,compact:M,hideXy:h,includeOccluded:_}),N=S?.tree,J=S?.shell,W=S?.keyboard;if(a){E({shell:J,tree:N??"",keyboard:W});return}if(J&&typeof J=="object"){let C=[J.state?`state=${J.state}`:null,J.activeApp?`app=${J.activeApp}`:null,J.showSwitcher?"switcher":null,J.switcherPhase&&J.switcherPhase!=="idle"?`phase=${J.switcherPhase}`:null].filter(Boolean);C.length>0&&console.log(` shell: ${C.join(" ")}`)}if(typeof N=="string"&&N.startsWith("__SUBTREE_NOT_FOUND__:")){let C=N.slice(22);console.log(` subtree root not found: ${C}`),Y("subtree-root-not-found",C);return}if(!N){let C=S?.nodeCount??0;console.log(" no matching nodes found"),!(B||I||D||j)&&C<10&&Y("app-still-loading",C);return}let V=N,Z=0;if(k&&typeof V=="string"){let C=V.split(`
201
201
  `),le=[];for(let o of C){if(o.includes("(clipped:")){Z+=1;continue}le.push(o)}V=le.join(`
202
202
  `)}console.log(V),Z>0&&console.log(` ${Z} clipped row(s) hidden (omit --no-clipped to see)`);let re=B||I||D||j;if((B||I||D)&&!y&&Y("describe-filter-context"),!re&&!y&&N.split(`
203
203
  `).length>=80&&Y("describe-use-filters"),W&&W.visible){let C=W.spec,le=[C?.keyboardType?`type=${C.keyboardType}`:null,C?.returnKeyType&&C.returnKeyType!=="default"?`return=${C.returnKeyType}`:null,W.mode!=="letters"?`mode=${W.mode}`:null,W.shifted?"shift":null,W.capsLock?"caps":null,C?.autoCapitalize&&C.autoCapitalize!=="sentences"?`autoCap=${C.autoCapitalize}`:null,W.accessoryBarId?`accessory=${W.accessoryBarId}`:null].filter(Boolean);console.log(`
204
204
  keyboard: ${le.join(" ")||"visible"}`)}};if(y)for(console.log(` watching... (Ctrl+C to stop)
205
- `);;)console.clear(),await Q(),await ee(T);else await Q()}var Po=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function me(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let e of Po){let l=process.env[e];if(l&&l.trim()&&l!=="0")return!0}return!1}async function Dt(e){let{bridge:l,args:n,effectiveArgs:c,positional:m,inspectUsage:i}=e,g=S=>{let N=c.indexOf(S);return N>=0&&N+1<c.length?c[N+1]:null},y=S=>c.includes(S),T=g("--testid")||g("--test-id"),M=g("--role"),b=g("--type"),k=g("--text"),_=y("--pressable"),I=y("--visible"),E=y("--interactive-targets")||y("--actions"),j=!T&&!M&&!b&&!k&&!_&&!I&&!E?m[1]:null,u=k??j,z=await at(l,{testId:T,role:M,type:b,text:u,pressable:_,visible:I,interactive:E});z||(console.error(i("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:B,result:D}=z,Q=A(n),oe=n.includes("--verbose")||n.includes("--dump");if(Q)B==="interactive-targets"&&Array.isArray(D)?P(Ae(D).map(S=>({...S,tap:Pe(S)}))):P(D??null);else if(Array.isArray(D))if(D.length===0){console.log(` no ${B} nodes found`);let S=await l.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof S=="number"&&S<10&&Y("app-still-loading",S)}else if(B==="interactive-targets"){let S=Ae(D);console.log(` found ${S.length} interactive target${S.length===1?"":"s"} (sorted by score):`);for(let N of S.slice(0,20)){let J=N.absolutePosition?`@(${Math.round(N.absolutePosition.x)},${Math.round(N.absolutePosition.y)})`:"",W=N.layout?`${Math.round(N.layout.width)}x${Math.round(N.layout.height)}`:"?x?",V=N.text?` "${N.text.slice(0,30)}"`:"",Z=N.testID?` #${N.testID}`:"",re=N.accessibilityLabel?` \u24D8"${String(N.accessibilityLabel).slice(0,24)}"`:"",pe=N.accessibilityRole?`[${N.accessibilityRole}]`:N.type,C=Pe(N);console.log(` ${pe}${V}${re}${Z} ${W} ${J}`),console.log(` \u2192 ${C}`),oe&&console.log(je(JSON.stringify(N,null,2)," "))}S.length>20&&console.log(` ... and ${S.length-20} more`)}else{console.log(` found ${D.length} node${D.length===1?"":"s"} (${B}):`);for(let S of D.slice(0,20)){let N=S.absolutePosition?`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`:"",J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,30)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(je(JSON.stringify(S,null,2)," "))}D.length>20&&console.log(` ... and ${D.length-20} more`)}else if(D==null)console.log(` not found: ${u||T||M||b||""||B}`),T&&Y("wait-selector-for-missing-testid",T);else{let S=D;if(S.type&&S.absolutePosition){let N=`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`,J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,40)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(je(JSON.stringify(S,null,2)," "))}else console.log(JSON.stringify(D,null,2))}}function je(e,l){return e.split(`
206
- `).map(n=>l+n).join(`
207
- `)}async function Ct(e){let{bridge:l,args:n}=e,c=A(n);await ue(l,{verbose:!c});let m=n.includes("--styling"),i=await nt(l,{styling:m});if(c){P({count:i.length,elements:i});return}console.log(` layout (${i.length} element${i.length===1?"":"s"}):
208
- `),console.log(rt(i,{styling:m}))}async function Bt(e,l={}){let n=await ht(e);if("error"in n&&(console.error(n.error),process.exit(1)),l.json){console.log(JSON.stringify(n,null,2));return}let{visible:c,spec:m,mode:i,shifted:g,capsLock:y,accessoryBarId:T}=n,M=[];M.push(`keyboard: ${c?"visible":"hidden"}`),m?(M.push(` type: ${m.keyboardType}`),M.push(` returnKey: ${m.returnKeyType}`),M.push(` autoCap: ${m.autoCapitalize}`),M.push(` autoCorrect: ${m.autoCorrect?"on":"off"}`),M.push(` appearance: ${m.keyboardAppearance}`),m.secureTextEntry&&M.push(" secureTextEntry: true"),m.enablesReturnKeyAutomatically&&M.push(` return: ${m.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):M.push(" spec: <none> (shown via dev-tools with no TextInput)"),M.push(` mode: ${i}${g?" (shifted)":""}${y?" (caps)":""}`),T&&M.push(` accessoryBar: ${T}`),console.log(M.join(`
209
- `))}async function jt(e){let l=await e.bridge.listSims(),n=e.args.includes("--all"),c=e.args.find((y,T)=>e.args[T-1]==="--bundle"),m=e.args.find((y,T)=>e.args[T-1]==="--app-port"),i=e.args.includes("--primary"),g=l.filter(y=>!(i&&!y.isPrimary||c&&!(y.url??"").includes(c)||m&&!(y.url??"").includes(`/rn/${m}`)||!n&&!c&&!m&&!i&&!(y.url&&(y.url.includes("bundle=")||y.url.includes("/index.bundle")))&&y.id!==e.simId));if(A(e.args)){P(g.map(y=>({...y,active:y.id===e.simId})));return}It(g,e.simId),g.length<l.length&&!A(e.args)&&console.log(` (${l.length-g.length} more hidden \u2014 pass --all to show)`)}function ae(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/1024/1024).toFixed(1)}MB`}function ke(e,l){return l<=0?"?":`${(e/l*100).toFixed(0)}%`}async function Lt(e,l={args:[]}){let n=await wt(e);if(A(l.args)){P(n);return}if(console.log(" memory:"),n.imageLoader){let c=n.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${c.cacheEntries} / ${c.cacheMaxEntries} (${ke(c.cacheEntries,c.cacheMaxEntries)})`),console.log(` pixel bytes: ${ae(c.cachePixelBytes)} / ${ae(c.cachePixelBudget)} (${ke(c.cachePixelBytes,c.cachePixelBudget)})`),console.log(` pending: ${c.pendingFetches} fetches, ${c.pendingBytes} bytes`),console.log(` failed uris: ${c.failedUris}`),console.log(` snapshots: ${c.snapshots}`),console.log(` live frames: ${c.liveFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(n.workerHeap){let c=n.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${ke(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}if(n.hostHeap){let c=n.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${ke(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}}var X="<redacted secure text>";function he(e){let l=e?.layout?.spec??e?.spec??null;return!!l?.secureTextEntry&&l.keyboardType!=="visible-password"}function Le(e,l){return he(l)?X:e}function Je(e){if(!e||!he(e))return e;let l=e.focusedInput;return!l||typeof l!="object"?e:{...e,focusedInput:{...l,secureTextEntry:!0,text:typeof l.text=="string"?X:l.text}}}function be(e){let l=e.indexOf("--testid");if(l>=0&&e[l+1])return{mode:"testid",value:e[l+1]};let n=e.indexOf("--test-id");if(n>=0&&e[n+1])return{mode:"testid",value:e[n+1]};let c=e.indexOf("--text");return c>=0&&e[c+1]?{mode:"text",value:e[c+1]}:null}async function Te(e,l){let n=JSON.stringify(l.value),c=l.mode==="testid"?`(await t.findByTestId(${n})) || (await t.findById(${n}))`:`await t.findByText(${n})`;return await e.send({type:"evaluate",code:`(async () => {
205
+ `);;)console.clear(),await Q(),await ee(T);else await Q()}var Po=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function me(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let e of Po){let l=process.env[e];if(l&&l.trim()&&l!=="0")return!0}return!1}async function Dt(e){let{bridge:l,args:r,effectiveArgs:c,positional:p,inspectUsage:a}=e,g=S=>{let N=c.indexOf(S);return N>=0&&N+1<c.length?c[N+1]:null},y=S=>c.includes(S),T=g("--testid")||g("--test-id"),M=g("--role"),h=g("--type"),k=g("--text"),_=y("--pressable"),I=y("--visible"),P=y("--interactive-targets")||y("--actions"),j=!T&&!M&&!h&&!k&&!_&&!I&&!P?p[1]:null,d=k??j,z=await lt(l,{testId:T,role:M,type:h,text:d,pressable:_,visible:I,interactive:P});z||(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:B,result:D}=z,Q=A(r),oe=r.includes("--verbose")||r.includes("--dump");if(Q)B==="interactive-targets"&&Array.isArray(D)?E(Pe(D).map(S=>({...S,tap:Re(S)}))):E(D??null);else if(Array.isArray(D))if(D.length===0){console.log(` no ${B} nodes found`);let S=await l.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof S=="number"&&S<10&&Y("app-still-loading",S)}else if(B==="interactive-targets"){let S=Pe(D);console.log(` found ${S.length} interactive target${S.length===1?"":"s"} (sorted by score):`);for(let N of S.slice(0,20)){let J=N.absolutePosition?`@(${Math.round(N.absolutePosition.x)},${Math.round(N.absolutePosition.y)})`:"",W=N.layout?`${Math.round(N.layout.width)}x${Math.round(N.layout.height)}`:"?x?",V=N.text?` "${N.text.slice(0,30)}"`:"",Z=N.testID?` #${N.testID}`:"",re=N.accessibilityLabel?` \u24D8"${String(N.accessibilityLabel).slice(0,24)}"`:"",pe=N.accessibilityRole?`[${N.accessibilityRole}]`:N.type,C=Re(N);console.log(` ${pe}${V}${re}${Z} ${W} ${J}`),console.log(` \u2192 ${C}`),oe&&console.log(Je(JSON.stringify(N,null,2)," "))}S.length>20&&console.log(` ... and ${S.length-20} more`)}else{console.log(` found ${D.length} node${D.length===1?"":"s"} (${B}):`);for(let S of D.slice(0,20)){let N=S.absolutePosition?`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`:"",J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,30)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(Je(JSON.stringify(S,null,2)," "))}D.length>20&&console.log(` ... and ${D.length-20} more`)}else if(D==null)console.log(` not found: ${d||T||M||h||""||B}`),T&&Y("wait-selector-for-missing-testid",T);else{let S=D;if(S.type&&S.absolutePosition){let N=`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`,J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,40)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(Je(JSON.stringify(S,null,2)," "))}else console.log(JSON.stringify(D,null,2))}}function Je(e,l){return e.split(`
206
+ `).map(r=>l+r).join(`
207
+ `)}async function Ct(e){let{bridge:l,args:r}=e,c=A(r);await de(l,{verbose:!c});let p=r.includes("--styling"),a=await rt(l,{styling:p});if(c){E({count:a.length,elements:a});return}console.log(` layout (${a.length} element${a.length===1?"":"s"}):
208
+ `),console.log(it(a,{styling:p}))}async function Bt(e,l={}){let r=await bt(e);if("error"in r&&(console.error(r.error),process.exit(1)),l.json){console.log(JSON.stringify(r,null,2));return}let{visible:c,spec:p,mode:a,shifted:g,capsLock:y,accessoryBarId:T}=r,M=[];M.push(`keyboard: ${c?"visible":"hidden"}`),p?(M.push(` type: ${p.keyboardType}`),M.push(` returnKey: ${p.returnKeyType}`),M.push(` autoCap: ${p.autoCapitalize}`),M.push(` autoCorrect: ${p.autoCorrect?"on":"off"}`),M.push(` appearance: ${p.keyboardAppearance}`),p.secureTextEntry&&M.push(" secureTextEntry: true"),p.enablesReturnKeyAutomatically&&M.push(` return: ${p.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):M.push(" spec: <none> (shown via dev-tools with no TextInput)"),M.push(` mode: ${a}${g?" (shifted)":""}${y?" (caps)":""}`),T&&M.push(` accessoryBar: ${T}`),console.log(M.join(`
209
+ `))}async function jt(e){let l=await e.bridge.listSims(),r=e.args.includes("--all"),c=e.args.find((y,T)=>e.args[T-1]==="--bundle"),p=e.args.find((y,T)=>e.args[T-1]==="--app-port"),a=e.args.includes("--primary"),g=l.filter(y=>!(a&&!y.isPrimary||c&&!(y.url??"").includes(c)||p&&!(y.url??"").includes(`/rn/${p}`)||!r&&!c&&!p&&!a&&!(y.url&&(y.url.includes("bundle=")||y.url.includes("/index.bundle")))&&y.id!==e.simId));if(A(e.args)){E(g.map(y=>({...y,active:y.id===e.simId})));return}It(g,e.simId),g.length<l.length&&!A(e.args)&&console.log(` (${l.length-g.length} more hidden \u2014 pass --all to show)`)}function ae(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/1024/1024).toFixed(1)}MB`}function Te(e,l){return l<=0?"?":`${(e/l*100).toFixed(0)}%`}async function Lt(e,l={args:[]}){let r=await wt(e);if(A(l.args)){E(r);return}if(console.log(" memory:"),r.imageLoader){let c=r.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${c.cacheEntries} / ${c.cacheMaxEntries} (${Te(c.cacheEntries,c.cacheMaxEntries)})`),console.log(` pixel bytes: ${ae(c.cachePixelBytes)} / ${ae(c.cachePixelBudget)} (${Te(c.cachePixelBytes,c.cachePixelBudget)})`),console.log(` pending: ${c.pendingFetches} fetches, ${c.pendingBytes} bytes`),console.log(` failed uris: ${c.failedUris}`),console.log(` snapshots: ${c.snapshots}`),console.log(` live frames: ${c.liveFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(r.workerHeap){let c=r.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${Te(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}if(r.hostHeap){let c=r.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${Te(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}}var X="<redacted secure text>";function he(e){let l=e?.layout?.spec??e?.spec??null;return!!l?.secureTextEntry&&l.keyboardType!=="visible-password"}function We(e,l){return he(l)?X:e}function qe(e){if(!e||!he(e))return e;let l=e.focusedInput;return!l||typeof l!="object"?e:{...e,focusedInput:{...l,secureTextEntry:!0,text:typeof l.text=="string"?X:l.text}}}function we(e){let l=e.indexOf("--testid");if(l>=0&&e[l+1])return{mode:"testid",value:e[l+1]};let r=e.indexOf("--test-id");if(r>=0&&e[r+1])return{mode:"testid",value:e[r+1]};let c=e.indexOf("--text");return c>=0&&e[c+1]?{mode:"text",value:e[c+1]}:null}async function Me(e,l){let r=JSON.stringify(l.value),c=l.mode==="testid"?`(await t.findByTestId(${r})) || (await t.findById(${r}))`:`await t.findByText(${r})`;return await e.send({type:"evaluate",code:`(async () => {
210
210
  const t = window.__sootsimTest
211
211
  if (!t) return null
212
212
  const n = ${c}
@@ -228,18 +228,18 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
228
228
  y: cy,
229
229
  id: n.id ?? null,
230
230
  testID: n.testID ?? null,
231
- text: ${JSON.stringify(l.mode==="text")} ? ${n} : (n.text ?? n.accessibilityLabel ?? null),
231
+ text: ${JSON.stringify(l.mode==="text")} ? ${r} : (n.text ?? n.accessibilityLabel ?? null),
232
232
  type: n.type ?? null,
233
233
  }
234
- })()`})??null}async function Jt(e,l={}){let{nav:n,keyboard:c,shell:m}=await bt(e);if(l.json){console.log(JSON.stringify({shell:m??null,nav:n,keyboard:c},null,2));return}let i=[];if(m){let g=m.activeApp??m.state??"<none>",y=m.showSwitcher?" (app switcher open)":"",T=typeof m.launchProgress=="number"&&m.launchProgress<.98?` launching (${Math.round(m.launchProgress*100)}%)`:"";i.push(`shell: ${g}${y}${T}`)}else i.push("shell: <unavailable>");if(n){let g=n.transitionPhase!=="idle"?` (${n.transitionPhase}, ${n.activeTransitionCount} active)`:"";if(i.push(`nav: phase=${n.transitionPhase}${g}`),n.screens.length===0)i.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let y of n.screens){let T=y.isActive?"\u25B6":" ",M=y.routeName?` ${y.routeName}`:"",b=y.headerHeight>0?` header=${y.headerHeight}`:"",k=y.largeTitleState&&y.largeTitleState!=="expanded"?` large-title=${y.largeTitleState}`:"";i.push(` ${T} #${y.id}${M}${b}${k}`)}}else i.push("nav: <runtime not available>");if(c&&c.visible){let g=c.spec?.keyboardType??"default",y=c.spec?.returnKeyType??"default";i.push(`keyboard: visible (${g}, return=${y}, mode=${c.mode??"?"})`)}else i.push("keyboard: hidden");console.log(i.join(`
235
- `))}async function Wt(e){let{bridge:l,args:n,positional:c}=e,m=c[1]?Number(c[1])*1e3:3e3,i=n.includes("--strict"),{elapsed:g,settled:y}=await te({bridge:l,maxMs:m,strict:i});console.log(y?` settled in ${g}ms`:` timed out after ${g}ms (may still be animating)`)}async function qt(e){let l=e.positional[1]?Number(e.positional[1]):.5;(!Number.isFinite(l)||l<0)&&(console.error(e.inspectUsage("sleep","[seconds]")),process.exit(1)),await ee(l*1e3),console.log(` slept ${l}s`)}async function Ht(e){let{bridge:l,args:n,positional:c}=e,m=c[1]?Number(c[1]):5,{tree:i}=await tt(l,m);if(A(n)){P({depth:m,tree:i??null});return}console.log(typeof i=="string"?i:JSON.stringify(i,null,2))}async function Kt(e,l={args:[]}){let n=await ot(e);if(A(l.args)){P(n);return}console.log(n.url)}async function Ut(e){let{wsPort:l,commandTimeoutMs:n,simId:c,simIdSource:m,positional:i}=e,g=i[1]?Number(i[1]):30,y=Math.max(1e3,(Number.isFinite(g)?g:30)*1e3),T=Math.max(1,Math.ceil(y/500));console.log(" waiting for sim reconnect...");let M=await xt(l,n,c,{attempts:T,simIdSource:m});M||(console.error(" timed out waiting for sim reconnect"),process.exit(1)),M.bridge.close(),ve({source:"inspect wait",step:{wait:y},summary:`wait ${Math.round(y/1e3)}s`}),console.log(` ready: ${M.count} nodes`)}var zt=new Set(["app-launch","toast","keyboard","screen","route","alert","actionsheet","picker","notification","fetch","console","shell","scroll","gesture","text-input","react-commit","animation","reanimated"]);function Me(e,l){let n=e.indexOf(l);if(n>=0&&n+1<e.length)return e[n+1]}function Eo(e,l){if(!l.filter&&!l.equals)return!0;let n=e.data,c=[];if(n&&typeof n=="object")for(let i of["url","displayUrl","message","name","activeName","path","pathname","title","phase","event","type","kind"]){let g=n[i];typeof g=="string"&&g.length>0&&c.push(g)}let m=c.join(" ");return l.equals?c.some(i=>i===l.equals):l.filter?m.toLowerCase().includes(l.filter.toLowerCase()):!0}async function Gt(e){let{bridge:l,args:n,positional:c,inspectUsage:m}=e,i=c[1];i||(console.error(m("wait event","<kind> [--max-ms 5000] [--filter <substring>] [--equals <exact>] [--since now|cursor]")),process.exit(1)),zt.has(i)||console.error(` warning: '${i}' is not a known timeline kind \u2014 waiting anyway. known: ${[...zt].sort().join(", ")}`);let g=Me(n,"--max-ms"),y=g&&Number.isFinite(Number(g))?Math.max(100,Number(g)):5e3,T=Me(n,"--filter"),M=Me(n,"--equals"),b=Me(n,"--since")??"now",k=n.includes("--json"),_=Date.now(),I=_+y,E=200,j=_;for(;Date.now()<I;){let z={kinds:[i],since:b==="cursor"?void 0:j,limit:50},B=await l.send({type:"evaluate",code:`(async () => {
234
+ })()`})??null}async function Jt(e,l={}){let{nav:r,keyboard:c,shell:p}=await ht(e);if(l.json){console.log(JSON.stringify({shell:p??null,nav:r,keyboard:c},null,2));return}let a=[];if(p){let g=p.activeApp??p.state??"<none>",y=p.showSwitcher?" (app switcher open)":"",T=typeof p.launchProgress=="number"&&p.launchProgress<.98?` launching (${Math.round(p.launchProgress*100)}%)`:"";a.push(`shell: ${g}${y}${T}`)}else a.push("shell: <unavailable>");if(r){let g=r.transitionPhase!=="idle"?` (${r.transitionPhase}, ${r.activeTransitionCount} active)`:"";if(a.push(`nav: phase=${r.transitionPhase}${g}`),r.screens.length===0)a.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let y of r.screens){let T=y.isActive?"\u25B6":" ",M=y.routeName?` ${y.routeName}`:"",h=y.headerHeight>0?` header=${y.headerHeight}`:"",k=y.largeTitleState&&y.largeTitleState!=="expanded"?` large-title=${y.largeTitleState}`:"";a.push(` ${T} #${y.id}${M}${h}${k}`)}}else a.push("nav: <runtime not available>");if(c&&c.visible){let g=c.spec?.keyboardType??"default",y=c.spec?.returnKeyType??"default";a.push(`keyboard: visible (${g}, return=${y}, mode=${c.mode??"?"})`)}else a.push("keyboard: hidden");console.log(a.join(`
235
+ `))}async function Wt(e){let{bridge:l,args:r,positional:c}=e,p=c[1]?Number(c[1])*1e3:3e3,a=r.includes("--strict"),{elapsed:g,settled:y}=await te({bridge:l,maxMs:p,strict:a});console.log(y?` settled in ${g}ms`:` timed out after ${g}ms (may still be animating)`)}async function qt(e){let l=e.positional[1]?Number(e.positional[1]):.5;(!Number.isFinite(l)||l<0)&&(console.error(e.inspectUsage("sleep","[seconds]")),process.exit(1)),await ee(l*1e3),console.log(` slept ${l}s`)}async function Ht(e){let{bridge:l,args:r,positional:c}=e,p=c[1]?Number(c[1]):5,{tree:a}=await ot(l,p);if(A(r)){E({depth:p,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Kt(e,l={args:[]}){let r=await st(e);if(A(l.args)){E(r);return}console.log(r.url)}async function Ut(e){let{wsPort:l,commandTimeoutMs:r,simId:c,simIdSource:p,positional:a}=e,g=a[1]?Number(a[1]):30,y=Math.max(1e3,(Number.isFinite(g)?g:30)*1e3),T=Math.max(1,Math.ceil(y/500));console.log(" waiting for sim reconnect...");let M=await xt(l,r,c,{attempts:T,simIdSource:p});M||(console.error(" timed out waiting for sim reconnect"),process.exit(1)),M.bridge.close(),ke({source:"inspect wait",step:{wait:y},summary:`wait ${Math.round(y/1e3)}s`}),console.log(` ready: ${M.count} nodes`)}var zt=new Set(["app-launch","toast","keyboard","screen","route","alert","actionsheet","picker","notification","fetch","console","shell","scroll","gesture","text-input","react-commit","animation","reanimated"]);function Ie(e,l){let r=e.indexOf(l);if(r>=0&&r+1<e.length)return e[r+1]}function Ro(e,l){if(!l.filter&&!l.equals)return!0;let r=e.data,c=[];if(r&&typeof r=="object")for(let a of["url","displayUrl","message","name","activeName","path","pathname","title","phase","event","type","kind"]){let g=r[a];typeof g=="string"&&g.length>0&&c.push(g)}let p=c.join(" ");return l.equals?c.some(a=>a===l.equals):l.filter?p.toLowerCase().includes(l.filter.toLowerCase()):!0}async function Gt(e){let{bridge:l,args:r,positional:c,inspectUsage:p}=e,a=c[1];a||(console.error(p("wait event","<kind> [--max-ms 5000] [--filter <substring>] [--equals <exact>] [--since now|cursor]")),process.exit(1)),zt.has(a)||console.error(` warning: '${a}' is not a known timeline kind \u2014 waiting anyway. known: ${[...zt].sort().join(", ")}`);let g=Ie(r,"--max-ms"),y=g&&Number.isFinite(Number(g))?Math.max(100,Number(g)):5e3,T=Ie(r,"--filter"),M=Ie(r,"--equals"),h=Ie(r,"--since")??"now",k=r.includes("--json"),_=Date.now(),I=_+y,P=200,j=_;for(;Date.now()<I;){let z={kinds:[a],since:h==="cursor"?void 0:j,limit:50},B=await l.send({type:"evaluate",code:`(async () => {
236
236
  const t = window.SootSim?.bridges?.timeline
237
237
  if (!t) return { ok: false, error: 'timeline bridge missing' }
238
238
  return { ok: true, result: await t.recent(${JSON.stringify(z)}) }
239
- })()`});(!B||!B.ok)&&(console.error(` could not query timeline: ${B&&"error"in B?B.error:"unknown"}`),process.exit(1));let D=B.result.events??[];for(let Q of D)if(Eo(Q,{filter:T,equals:M})){let oe=Date.now()-_;console.log(k?JSON.stringify({found:!0,elapsedMs:oe,event:Q}):` ${i} event after ${oe}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`);return}B.result.watermark&&B.result.watermark>j&&(j=B.result.watermark),await new Promise(Q=>setTimeout(Q,E))}let u=Date.now()-_;k?console.log(JSON.stringify({found:!1,elapsedMs:u,kind:i,filter:T,equals:M})):console.error(` \u26A0 wait event ${i} timed out after ${u}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`),process.exit(1)}async function Yt(e){let{bridge:l,args:n}=e,c=n.includes("--strict"),m=xe(n,3e3),{elapsed:i,settled:g}=await te({bridge:l,maxMs:m,strict:c});g?console.log(` idle in ${i}ms`):(console.error(` \u26A0 wait idle timed out after ${i}ms (may still be animating)`),process.exit(1))}async function Xt(e){let{bridge:l,args:n}=e,c=xe(n,2e4),{ready:m,elapsedMs:i,nodes:g,targets:y,flag:T,loadingText:M,externalReady:b,externalError:k,errors:_}=await lt(l,c,{onProgress(E){console.error(` still waiting after ${E.elapsedMs}ms \u2014 ${Ee(E)} (nodes: ${E.nodes}, targets: ${E.targets}, errors: ${E.errors})`)}});if(m){let E=c-i,j=Math.max(100,Math.min(1e4,E)),u=await te({bridge:l,maxMs:j,pollMs:32,stablePolls:2});u.settled||(console.error(` \u26A0 wait ready timed out after ${i+u.elapsed}ms \u2014 app mounted but did not settle (nodes: ${g}, targets: ${y})`),process.exit(1)),console.log(` ready in ${i+u.elapsed}ms: ${g} nodes, ${y} targets`);return}let I=Ee({externalError:k,loadingText:M,externalReady:b,flag:T,targets:y});console.error(` \u26A0 wait ready timed out after ${i}ms \u2014 ${I} (nodes: ${g}, targets: ${y}, errors: ${_})`),process.exit(1)}async function Vt(e){let{bridge:l,args:n,positional:c,inspectUsage:m}=e,i=c[1];i||(console.error(m("wait selector","<testid> [--max-ms 5000] [--gone]")),process.exit(1));let g=n.indexOf("--max-ms"),y=g>=0&&n[g+1]?Math.max(100,Number(n[g+1])):5e3,T=n.includes("--gone"),{found:M,node:b,elapsed:k}=await ct(l,i,y,{gone:T});if(T){M?console.log(` #${i} gone after ${k}ms`):(console.error(` \u26A0 wait selector #${i} --gone timed out after ${k??y}ms (still present)`),process.exit(1));return}if(M&&b){let _=b.absolutePosition?`@(${Math.round(b.absolutePosition.x)},${Math.round(b.absolutePosition.y)})`:"",I=b.layout?`${Math.round(b.layout.width)}x${Math.round(b.layout.height)}`:"?x?";console.log(` found #${i} in ${k}ms ${I} ${_}`)}else console.error(` \u26A0 wait selector #${i} timed out after ${k??y}ms`),process.exit(1)}function ro(e){return e==null?"\u2014":e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}K`:`${(e/1024/1024).toFixed(1)}M`}function io(e){return e==null?" \u2026":e<1e3?`${e}ms`.padStart(5):`${(e/1e3).toFixed(2)}s`.padStart(5)}function Qt(){process.stderr.write(` the sim is not responding. recover it with:
239
+ })()`});(!B||!B.ok)&&(console.error(` could not query timeline: ${B&&"error"in B?B.error:"unknown"}`),process.exit(1));let D=B.result.events??[];for(let Q of D)if(Ro(Q,{filter:T,equals:M})){let oe=Date.now()-_;console.log(k?JSON.stringify({found:!0,elapsedMs:oe,event:Q}):` ${a} event after ${oe}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`);return}B.result.watermark&&B.result.watermark>j&&(j=B.result.watermark),await new Promise(Q=>setTimeout(Q,P))}let d=Date.now()-_;k?console.log(JSON.stringify({found:!1,elapsedMs:d,kind:a,filter:T,equals:M})):console.error(` \u26A0 wait event ${a} timed out after ${d}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`),process.exit(1)}async function Yt(e){let{bridge:l,args:r}=e,c=r.includes("--strict"),p=$e(r,3e3),{elapsed:a,settled:g}=await te({bridge:l,maxMs:p,strict:c});g?console.log(` idle in ${a}ms`):(console.error(` \u26A0 wait idle timed out after ${a}ms (may still be animating)`),process.exit(1))}async function Xt(e){let{bridge:l,args:r}=e,c=$e(r,2e4),{ready:p,elapsedMs:a,nodes:g,targets:y,flag:T,loadingText:M,externalReady:h,externalError:k,errors:_}=await ct(l,c,{onProgress(P){console.error(` still waiting after ${P.elapsedMs}ms \u2014 ${De(P)} (nodes: ${P.nodes}, targets: ${P.targets}, errors: ${P.errors})`)}});if(p){let P=c-a,j=Math.max(100,Math.min(1e4,P)),d=await te({bridge:l,maxMs:j,pollMs:32,stablePolls:2});d.settled||(console.error(` \u26A0 wait ready timed out after ${a+d.elapsed}ms \u2014 app mounted but did not settle (nodes: ${g}, targets: ${y})`),process.exit(1)),console.log(` ready in ${a+d.elapsed}ms: ${g} nodes, ${y} targets`);return}let I=De({externalError:k,loadingText:M,externalReady:h,flag:T,targets:y});console.error(` \u26A0 wait ready timed out after ${a}ms \u2014 ${I} (nodes: ${g}, targets: ${y}, errors: ${_})`),process.exit(1)}async function Vt(e){let{bridge:l,args:r,positional:c,inspectUsage:p}=e,a=c[1];a||(console.error(p("wait selector","<testid> [--max-ms 5000] [--gone]")),process.exit(1));let g=r.indexOf("--max-ms"),y=g>=0&&r[g+1]?Math.max(100,Number(r[g+1])):5e3,T=r.includes("--gone"),{found:M,node:h,elapsed:k}=await dt(l,a,y,{gone:T});if(T){M?console.log(` #${a} gone after ${k}ms`):(console.error(` \u26A0 wait selector #${a} --gone timed out after ${k??y}ms (still present)`),process.exit(1));return}if(M&&h){let _=h.absolutePosition?`@(${Math.round(h.absolutePosition.x)},${Math.round(h.absolutePosition.y)})`:"",I=h.layout?`${Math.round(h.layout.width)}x${Math.round(h.layout.height)}`:"?x?";console.log(` found #${a} in ${k}ms ${I} ${_}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${k??y}ms`),process.exit(1)}function io(e){return e==null?"\u2014":e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}K`:`${(e/1024/1024).toFixed(1)}M`}function ao(e){return e==null?" \u2026":e<1e3?`${e}ms`.padStart(5):`${(e/1e3).toFixed(2)}s`.padStart(5)}function Qt(){process.stderr.write(` the sim is not responding. recover it with:
240
240
  sootsim close --sim <id> # force-close the wedged sim
241
241
  sootsim list # confirm it's gone
242
- `)}async function Do(e){try{return await e.send({type:"evaluate",code:"1"},{timeoutMs:3e3}),!0}catch{return!1}}async function Co(e,l){try{let n=await e.send({type:"evaluate",code:`(async () => {
242
+ `)}async function Co(e){try{return await e.send({type:"evaluate",code:"1"},{timeoutMs:3e3}),!0}catch{return!1}}async function Bo(e,l){try{let r=await e.send({type:"evaluate",code:`(async () => {
243
243
  const t = window.__sootsimTest
244
244
  if (!t || typeof t.queryAll !== 'function') return []
245
245
  try {
@@ -258,8 +258,8 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
258
258
  } catch {
259
259
  return []
260
260
  }
261
- })()`});if(!Array.isArray(n)||n.length===0)return;let c=l.toLowerCase(),m=n.map(i=>({id:i,score:Bo(c,i.toLowerCase())})).filter(i=>i.score<c.length+4).sort((i,g)=>i.score-g.score).slice(0,5);if(m.length===0)return;console.error(" similar testIDs:");for(let i of m)console.error(` ${i.id}`)}catch{}}function Bo(e,l){if(l===e)return 0;if(l.includes(e))return 1;if(e.includes(l))return 2;let n=0;for(;n<e.length&&n<l.length&&e[n]===l[n];)n+=1;return jo(e,l)-n}function jo(e,l){if(e===l)return 0;if(!e.length)return l.length;if(!l.length)return e.length;let n=new Array(l.length+1),c=new Array(l.length+1);for(let m=0;m<=l.length;m++)n[m]=m;for(let m=1;m<=e.length;m++){c[0]=m;for(let g=1;g<=l.length;g++)c[g]=Math.min(n[g]+1,c[g-1]+1,n[g-1]+(e[m-1]===l[g-1]?0:1));let i=n;n=c,c=i}return n[l.length]}function Lo(e){return e.error?"err":e.status==null?" \u2026 ":String(e.status)}function Jo(e){return e.externalError?`guest app errored: ${e.externalError}`:e.loadingText?`still showing "${e.loadingText}"`:e.externalReady===!1?"guest app is still loading":e.flag!==!0?"guest app has not emitted sootsim:externalAppReady":e.targets<=0?"ready flag emitted but no visible app content is inspectable yet":"node tree is still changing"}function Zt(e){let l=ie(e.startTs),n=Lo(e).padEnd(3),c=e.method.padEnd(5),m=ro(e.size).padStart(6),i=io(e.durationMs);console.log(` [${l}] ${n} ${c} ${m} ${i} ${e.displayUrl}`),e.error&&console.log(` error: ${e.error}`)}function Wo(e){let l=[["id",e.id],["source",e.source],["kind",e.kind],["method",e.method],["status",e.error?`error: ${e.error}`:`${e.status??"\u2014"} ${e.statusText??""}`.trim()],["url",e.url],["started",ie(e.startTs)],["duration",io(e.durationMs).trim()],["size",ro(e.size)],["content-type",e.type??"\u2014"]];for(let[n,c]of l)console.log(` ${n.padEnd(13)} ${c}`)}var qo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},eo="\x1B[0m",Ho="\x1B[2m";function to(e,l){let n=ie(e.ts),c=e.level.toUpperCase().padEnd(5),m=e.args.join(" ");if(l){let i=qo[e.level];console.log(` ${Ho}[${n}]${eo} ${i}${c}${eo} ${m}`)}else console.log(` [${n}] ${c} ${m}`);if(e.stack&&e.level==="error"){let i=e.stack.split(`
262
- `).slice(0,5);for(let g of i)console.log(` ${g.trim()}`)}}var ne="__sootsimCliPerf",Ko=120;async function oo(e,l){let n=e.find((_,I)=>e[I-1]==="--id"),c=e.find((_,I)=>e[I-1]==="--text");if(n||c){let _=await l.send({type:"evaluate",code:vt({id:n,text:c})});if(!_)throw new Error(n?`no node with id "${n}"`:`no node matching text "${c}"`);let{x:I,y:E,w:j,h:u}=_;return{x:I,y:E,w:j,h:u}}let m=e.find((_,I)=>e[I-1]==="--area");if(m){let _=m.split(",").map(z=>Number(z.trim()));if(_.length!==4||_.some(z=>!Number.isFinite(z)))throw new Error(`--area expects x,y,w,h (got "${m}")`);let[I,E,j,u]=_;return{x:I,y:E,w:j,h:u}}let i=_=>{let I=e.find((j,u)=>e[u-1]===_);if(I==null)return null;let E=Number(I);return Number.isFinite(E)?E:null},g=i("--x"),y=i("--y"),T=i("--w"),M=i("--h");if(g!=null||y!=null||T!=null||M!=null)return{x:g??0,y:y??0,w:T??1,h:M??1};let k=e.filter((_,I)=>I>0&&!_.startsWith("-")&&e[I-1]!=="--output"&&e[I-1]!=="--area"&&e[I-1]!=="--id"&&e[I-1]!=="--text"&&e[I-1]!=="--x"&&e[I-1]!=="--y"&&e[I-1]!=="--w"&&e[I-1]!=="--h").map(Number).filter(_=>Number.isFinite(_));if(k.length>=2){let[_,I,E=1,j=1]=k;return{x:_,y:I,w:E,h:j}}return null}function We(e){let l={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let n of e)n<8?l["<8"]++:n<12?l["8-12"]++:n<16?l["12-16"]++:n<20?l["16-20"]++:n<33?l["20-33"]++:l[">33"]++;console.log(" histogram:");for(let[n,c]of Object.entries(l)){let m="\u2588".repeat(Math.ceil(c/e.length*40));console.log(` ${n.padEnd(6)} ${m} ${c}`)}}async function Ie(e,l,n){let c=Date.now()+l,m=await ce(e,l);for(;;){if(n(m))return{settled:!0,state:m};if(Date.now()>=c)return{settled:!1,state:m};await ee(16),m=await ce(e)}}async function He(e){return e.send({type:"evaluate",code:`(async () => {
261
+ })()`});if(!Array.isArray(r)||r.length===0)return;let c=l.toLowerCase(),p=r.map(a=>({id:a,score:jo(c,a.toLowerCase())})).filter(a=>a.score<c.length+4).sort((a,g)=>a.score-g.score).slice(0,5);if(p.length===0)return;console.error(" similar testIDs:");for(let a of p)console.error(` ${a.id}`)}catch{}}function jo(e,l){if(l===e)return 0;if(l.includes(e))return 1;if(e.includes(l))return 2;let r=0;for(;r<e.length&&r<l.length&&e[r]===l[r];)r+=1;return Lo(e,l)-r}function Lo(e,l){if(e===l)return 0;if(!e.length)return l.length;if(!l.length)return e.length;let r=new Array(l.length+1),c=new Array(l.length+1);for(let p=0;p<=l.length;p++)r[p]=p;for(let p=1;p<=e.length;p++){c[0]=p;for(let g=1;g<=l.length;g++)c[g]=Math.min(r[g]+1,c[g-1]+1,r[g-1]+(e[p-1]===l[g-1]?0:1));let a=r;r=c,c=a}return r[l.length]}function Jo(e){return e.error?"err":e.status==null?" \u2026 ":String(e.status)}function Zt(e){return e.externalError?`guest app errored: ${e.externalError}`:e.loadingText?`still showing "${e.loadingText}"`:e.externalReady===!1?"guest app is still loading":e.flag!==!0?"guest app has not emitted sootsim:externalAppReady":e.targets<=0?"ready flag emitted but no visible app content is inspectable yet":"node tree is still changing"}function eo(e){let l=ie(e.startTs),r=Jo(e).padEnd(3),c=e.method.padEnd(5),p=io(e.size).padStart(6),a=ao(e.durationMs);console.log(` [${l}] ${r} ${c} ${p} ${a} ${e.displayUrl}`),e.error&&console.log(` error: ${e.error}`)}function Wo(e){let l=[["id",e.id],["source",e.source],["kind",e.kind],["method",e.method],["status",e.error?`error: ${e.error}`:`${e.status??"\u2014"} ${e.statusText??""}`.trim()],["url",e.url],["started",ie(e.startTs)],["duration",ao(e.durationMs).trim()],["size",io(e.size)],["content-type",e.type??"\u2014"]];for(let[r,c]of l)console.log(` ${r.padEnd(13)} ${c}`)}var qo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},to="\x1B[0m",Ho="\x1B[2m";function oo(e,l){let r=ie(e.ts),c=e.level.toUpperCase().padEnd(5),p=e.args.join(" ");if(l){let a=qo[e.level];console.log(` ${Ho}[${r}]${to} ${a}${c}${to} ${p}`)}else console.log(` [${r}] ${c} ${p}`);if(e.stack&&e.level==="error"){let a=e.stack.split(`
262
+ `).slice(0,5);for(let g of a)console.log(` ${g.trim()}`)}}var ne="__sootsimCliPerf",Ko=120;async function so(e,l){let r=e.find((_,I)=>e[I-1]==="--id"),c=e.find((_,I)=>e[I-1]==="--text");if(r||c){let _=await l.send({type:"evaluate",code:vt({id:r,text:c})});if(!_)throw new Error(r?`no node with id "${r}"`:`no node matching text "${c}"`);let{x:I,y:P,w:j,h:d}=_;return{x:I,y:P,w:j,h:d}}let p=e.find((_,I)=>e[I-1]==="--area");if(p){let _=p.split(",").map(z=>Number(z.trim()));if(_.length!==4||_.some(z=>!Number.isFinite(z)))throw new Error(`--area expects x,y,w,h (got "${p}")`);let[I,P,j,d]=_;return{x:I,y:P,w:j,h:d}}let a=_=>{let I=e.find((j,d)=>e[d-1]===_);if(I==null)return null;let P=Number(I);return Number.isFinite(P)?P:null},g=a("--x"),y=a("--y"),T=a("--w"),M=a("--h");if(g!=null||y!=null||T!=null||M!=null)return{x:g??0,y:y??0,w:T??1,h:M??1};let k=e.filter((_,I)=>I>0&&!_.startsWith("-")&&e[I-1]!=="--output"&&e[I-1]!=="--area"&&e[I-1]!=="--id"&&e[I-1]!=="--text"&&e[I-1]!=="--x"&&e[I-1]!=="--y"&&e[I-1]!=="--w"&&e[I-1]!=="--h").map(Number).filter(_=>Number.isFinite(_));if(k.length>=2){let[_,I,P=1,j=1]=k;return{x:_,y:I,w:P,h:j}}return null}function He(e){let l={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let r of e)r<8?l["<8"]++:r<12?l["8-12"]++:r<16?l["12-16"]++:r<20?l["16-20"]++:r<33?l["20-33"]++:l[">33"]++;console.log(" histogram:");for(let[r,c]of Object.entries(l)){let p="\u2588".repeat(Math.ceil(c/e.length*40));console.log(` ${r.padEnd(6)} ${p} ${c}`)}}async function Ne(e,l,r){let c=Date.now()+l,p=await ce(e,l);for(;;){if(r(p))return{settled:!0,state:p};if(Date.now()>=c)return{settled:!1,state:p};await ee(16),p=await ce(e)}}async function Ue(e){return e.send({type:"evaluate",code:`(async () => {
263
263
  const kb = window.__sootsimKeyboard
264
264
  const test = window.__sootsimTest
265
265
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -296,8 +296,8 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
296
296
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
297
297
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
298
298
  }
299
- })()`}).then(l=>Je(l))}function Uo(e,l,n){if(!e.visible)return!1;let c=e.focusedInput;return!(l&&c&&!(c.testID===l||c.id===l)||n!==null&&he(e)!==n)}async function zo(e,l=600,n={}){let c=Date.now()+l;for(;Date.now()<=c;){let m=await He(e);if(Uo(m,n.targetId??null,n.secureTextEntry??null))return m;await ee(30)}return He(e)}async function Ne(e,l){let n=await He(e);if(n.visible)return n;console.error(` ${l} requires the iOS keyboard to be visible. focus an input first with sootsim do tap-id/tap-text or sootsim do type-into.`),process.exit(1)}async function so(e,l,n){return l==="appearance"?e.send({type:"evaluate",code:`(async () => {
300
- const requested = ${JSON.stringify(n??"toggle")}
299
+ })()`}).then(l=>qe(l))}function Uo(e,l,r){if(!e.visible)return!1;let c=e.focusedInput;return!(l&&c&&!(c.testID===l||c.id===l)||r!==null&&he(e)!==r)}async function zo(e,l=600,r={}){let c=Date.now()+l;for(;Date.now()<=c;){let p=await Ue(e);if(Uo(p,r.targetId??null,r.secureTextEntry??null))return p;await ee(30)}return Ue(e)}async function Fe(e,l){let r=await Ue(e);if(r.visible)return r;console.error(` ${l} requires the iOS keyboard to be visible. focus an input first with sootsim do tap-id/tap-text or sootsim do type-into.`),process.exit(1)}async function no(e,l,r){return l==="appearance"?e.send({type:"evaluate",code:`(async () => {
300
+ const requested = ${JSON.stringify(r??"toggle")}
301
301
  // the engine owns toggle + auto resolution (settingsStore is the single
302
302
  // source of truth). never infer the current scheme client-side \u2014 the old
303
303
  // documentElement '#333333' sniff is never set in embedded / shell-chrome
@@ -312,25 +312,25 @@ import{a as vt,b as kt}from"./chunk-UC7LRLPE.js";import{a as Qe,g as ve,j as te}
312
312
  })()`}):e.send({type:"evaluate",code:`(async () => {
313
313
  window.dispatchEvent(new CustomEvent(${JSON.stringify(l==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
314
314
  return { ok: true, action: ${JSON.stringify(l)} }
315
- })()`})}function Go(e){let l={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(l[e])return l[e];let n=e.match(/^Digit([0-9])$/);if(n)return n[1];let c=e.match(/^Key([A-Z])$/);return c?c[1].toLowerCase():null}function Yo(e){if(typeof e!="string")return null;let l=e.replace(/\s+/g," ").trim();return l?l.slice(0,80):null}function ao(...e){for(let l of e){if(typeof l!="string")continue;let n=l.trim();if(n)return n}return null}function Xo(e){let l=e.indexOf("--node-id");if(l<0)return null;let n=e[l+1];if(!n)return null;let c=Number(n);return Number.isInteger(c)&&c>0?c:null}async function L(e,l,n){let c=ve({source:e,step:l,summary:n});c.active&&(c.replaced?console.error(` draft: replaced unkept action "${c.replaced.summary}" \u2014 \`flow keep\` commits one action at a time`):console.error(" draft: action pending \u2014 `sootsim flow keep` to commit"))}function no(e,l,n){if(!n||n.hit===!1)return null;let c=ao(n.responderTestID,n.testID);if(c)return{step:{tapOn:{id:c}},summary:`tap #${c}`};let m=Yo(n.text);return m?{step:{tapOn:m},summary:`tap "${m}"`}:{step:{tapAtCoords:{x:e,y:l}},summary:`tap @${Math.round(e)},${Math.round(l)}`}}function qe(e,l,n){let c=ao(l?.testID,l?.id);return c?{step:{tapOn:{id:c}},summary:`tap #${c}`}:n==="id"?{step:{tapOn:{id:e}},summary:`tap #${e}`}:{step:{tapOn:e},summary:`tap "${e}"`}}async function Jn(e,l){let n=e[0]==="get"||e[0]==="do"||e[0]==="debug"||e[0]==="wait"?e[0]:null,c=n?e.slice(1):e,m=Ge(c,{port:l.port,commandTimeoutMs:l.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--slow","--tail","-f","--interactive-targets","--actions","--internal","--compact","--no-xy","--no-clipped","--include-occluded"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--node-id","--max-ms","--filter","--limit","--level","--threshold","--equals","--since","--testid-like","--only","--subtree"]}),i=m.positional,g=i[0],y=n==="get"||n==="do"||n==="debug"||n==="wait"?n:"inspect",T=typeof c[0]=="string"&&Ke.has(c[0]),M=T?c[0]:null,b=o=>T&&o===c[0]?`sootsim ${o}`:`sootsim ${y} ${o}`,k=(o,t)=>` usage: ${b(o)}${t?` ${t}`:""}`;if(!g||e.includes("--help")||e.includes("-h")){let o={bridgePort:7668,defaultShellUrl:Ue};if(y==="do"||y==="get"||y==="debug"||y==="wait"){let r=Fe(y,o);r&&(console.log(`${r}
316
- `),process.exit(0))}if(M==="shell"){let r=_e("shell",o);r&&(console.log(`${r}
317
- `),process.exit(0))}let t=_e("inspect",o),s=["do","get","debug","wait"].map(r=>Fe(r,o)).filter(r=>r!=null).join(`
315
+ })()`})}function Go(e){let l={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(l[e])return l[e];let r=e.match(/^Digit([0-9])$/);if(r)return r[1];let c=e.match(/^Key([A-Z])$/);return c?c[1].toLowerCase():null}function Yo(e){if(typeof e!="string")return null;let l=e.replace(/\s+/g," ").trim();return l?l.slice(0,80):null}function lo(...e){for(let l of e){if(typeof l!="string")continue;let r=l.trim();if(r)return r}return null}function Xo(e){let l=e.indexOf("--node-id");if(l<0)return null;let r=e[l+1];if(!r)return null;let c=Number(r);return Number.isInteger(c)&&c>0?c:null}async function L(e,l,r){let c=ke({source:e,step:l,summary:r});c.active&&(c.replaced?console.error(` draft: replaced unkept action "${c.replaced.summary}" \u2014 \`flow keep\` commits one action at a time`):console.error(" draft: action pending \u2014 `sootsim flow keep` to commit"))}function ro(e,l,r){if(!r||r.hit===!1)return null;let c=lo(r.responderTestID,r.testID);if(c)return{step:{tapOn:{id:c}},summary:`tap #${c}`};let p=Yo(r.text);return p?{step:{tapOn:p},summary:`tap "${p}"`}:{step:{tapAtCoords:{x:e,y:l}},summary:`tap @${Math.round(e)},${Math.round(l)}`}}function Ke(e,l,r){let c=lo(l?.testID,l?.id);return c?{step:{tapOn:{id:c}},summary:`tap #${c}`}:r==="id"?{step:{tapOn:{id:e}},summary:`tap #${e}`}:{step:{tapOn:e},summary:`tap "${e}"`}}async function Jn(e,l){let r=e[0]==="get"||e[0]==="do"||e[0]==="debug"||e[0]==="wait"?e[0]:null,c=r?e.slice(1):e,p=Xe(c,{port:l.port,commandTimeoutMs:l.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--slow","--tail","-f","--interactive-targets","--actions","--internal","--compact","--no-xy","--no-clipped","--include-occluded"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--node-id","--max-ms","--filter","--limit","--level","--threshold","--equals","--since","--testid-like","--only","--subtree"]}),a=p.positional,g=a[0],y=r==="get"||r==="do"||r==="debug"||r==="wait"?r:"inspect",T=typeof c[0]=="string"&&ze.has(c[0]),M=T?c[0]:null,h=o=>T&&o===c[0]?`sootsim ${o}`:`sootsim ${y} ${o}`,k=(o,t)=>` usage: ${h(o)}${t?` ${t}`:""}`;if(!g||e.includes("--help")||e.includes("-h")){let o={bridgePort:7668,defaultShellUrl:Ge};if(y==="do"||y==="get"||y==="debug"||y==="wait"){let n=_e(y,o);n&&(console.log(`${n}
316
+ `),process.exit(0))}if(M==="shell"){let n=Oe("shell",o);n&&(console.log(`${n}
317
+ `),process.exit(0))}let t=Oe("inspect",o),s=["do","get","debug","wait"].map(n=>_e(n,o)).filter(n=>n!=null).join(`
318
318
 
319
319
  `);console.log(`${t??""}
320
320
 
321
321
  ${s}
322
- `),process.exit(0)}let _=m.wsPort,I=m.simId,E=m.simIdSource,j=m.commandTimeoutMs;if(g==="list"&&c.some(o=>o==="--drivers"||o==="-D")){let{buildDriverListRows:o}=await import("./drivers-GPZ62RP5.js"),t=o();console.log(` available drivers (${t.length}):
323
- `);let s=Math.max(...t.map(a=>a.id.length),6),r=Math.max(...t.map(a=>a.kind.length),4);for(let a of t){let d=a.available?"\u2713":"\u2717",p=a.id.padEnd(s),h=a.kind.padEnd(r);console.log(` ${d} ${p} ${h} ${a.description}`),a.available&&a.detail?console.log(` ${a.detail}`):!a.available&&a.reason&&console.log(` unavailable: ${a.reason}`)}return}let u=Ye(m),z=I||"default",B=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]),D=200;function Q(o){let t=o.replace(/\s+/g," ").trim();if(!t)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(t)){let r=/<title[^>]*>([^<]+)<\/title>/i.exec(o)?.[1]?.trim(),a=/<body[^>]*>([\s\S]*?)<\//i.exec(o)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),d=r||a||"html error page";return`<html ${o.length}B> "${d}" (body elided \u2014 add --json for the full payload)`}return t.length<=D?t:`${t.slice(0,D)}\u2026 (+${t.length-D} more bytes)`}function oe(o){let t=o.displayUrl||o.url;return o.status!=null?`${o.method} ${t} -> ${o.status}${o.statusText?` ${o.statusText}`:""}`:o.error?`${o.method} ${t} -> ${o.error}`:`${o.method} ${t}`}async function S(o){let t=me()?5e3:1500;try{let{settled:s,elapsed:r}=await te({bridge:o,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${r??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
324
- `)}catch{}}function N(o,t){console.error(` tap failed: ${o} stayed visible but did not receive a hittable press after ${t.attempts} attempt${t.attempts===1?"":"s"}`),t.result&&console.error(` last result: ${JSON.stringify(t.result)}`)}async function J(){try{return await u.send({type:"evaluate",code:`(() => ({
322
+ `),process.exit(0)}let _=p.wsPort,I=p.simId,P=p.simIdSource,j=p.commandTimeoutMs;if(g==="list"&&c.some(o=>o==="--drivers"||o==="-D")){let{buildDriverListRows:o}=await import("./drivers-VTVBB4KQ.js"),t=o();console.log(` available drivers (${t.length}):
323
+ `);let s=Math.max(...t.map(i=>i.id.length),6),n=Math.max(...t.map(i=>i.kind.length),4);for(let i of t){let u=i.available?"\u2713":"\u2717",m=i.id.padEnd(s),b=i.kind.padEnd(n);console.log(` ${u} ${m} ${b} ${i.description}`),i.available&&i.detail?console.log(` ${i.detail}`):!i.available&&i.reason&&console.log(` unavailable: ${i.reason}`)}return}let d=Ve(p),z=I||"default",B=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","storage-clear","list","wait","sleep"]),D=200;function Q(o){let t=o.replace(/\s+/g," ").trim();if(!t)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(t)){let n=/<title[^>]*>([^<]+)<\/title>/i.exec(o)?.[1]?.trim(),i=/<body[^>]*>([\s\S]*?)<\//i.exec(o)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),u=n||i||"html error page";return`<html ${o.length}B> "${u}" (body elided \u2014 add --json for the full payload)`}return t.length<=D?t:`${t.slice(0,D)}\u2026 (+${t.length-D} more bytes)`}function oe(o){let t=o.displayUrl||o.url;return o.status!=null?`${o.method} ${t} -> ${o.status}${o.statusText?` ${o.statusText}`:""}`:o.error?`${o.method} ${t} -> ${o.error}`:`${o.method} ${t}`}async function S(o){let t=me()?5e3:1500;try{let{settled:s,elapsed:n}=await te({bridge:o,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${n??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
324
+ `)}catch{}}function N(o,t){console.error(` tap failed: ${o} stayed visible but did not receive a hittable press after ${t.attempts} attempt${t.attempts===1?"":"s"}`),t.result&&console.error(` last result: ${JSON.stringify(t.result)}`)}async function J(){try{return await d.send({type:"evaluate",code:`(() => ({
325
325
  console: ${Se},
326
326
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
327
- }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function W(o={}){let t=o.counts!==void 0?o.counts:await G(u,"getRequestCounts");if(!t||typeof t!="object")return;let s=Math.max(0,Number(t.failed)||0);if(s===0||!o.includeTail&&!Ce("requests",z,String(s))||(console.log(`
328
- network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${b("requests")} 5`),!o.includeTail))return;let r=await G(u,"getFailedRequests",5);if(!(!Array.isArray(r)||r.length===0)){console.log(`
327
+ }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function W(o={}){let t=o.counts!==void 0?o.counts:await G(d,"getRequestCounts");if(!t||typeof t!="object")return;let s=Math.max(0,Number(t.failed)||0);if(s===0||!o.includeTail&&!je("requests",z,String(s))||(console.log(`
328
+ network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${h("requests")} 5`),!o.includeTail))return;let n=await G(d,"getFailedRequests",5);if(!(!Array.isArray(n)||n.length===0)){console.log(`
329
329
  recent failed requests:
330
- `);for(let a of r){let d=ie(a.timestamp);console.log(` [${d}] ${oe(a)}`),a.responseBody?console.log(` ${Q(a.responseBody)}`):a.error&&console.log(` ${a.error}`)}}}async function V(o={}){let t=o.counts!==void 0?o.counts:await u.send({type:"evaluate",code:Se});if(!t||typeof t!="object")return;let s=t,r=Math.max(0,Number(s.errors)||0),a=Math.max(0,Number(s.warnings)||0);if(r===0&&a===0||!o.includeTail&&!Ce("console",z,`${r}:${a}`))return;let d=[];if(r>0&&d.push(`${r} console error${r===1?"":"s"}`),a>0&&d.push(`${a} console warning${a===1?"":"s"}`),console.log(`
331
- console: ${d.join(", ")}`),console.log(` inspect: ${b("errors")} 5`),a>0&&console.log(` inspect: ${b("warnings")} 5`),!o.includeTail||r===0)return;let p=await $e(u,5);if(!(!Array.isArray(p)||p.length===0)){console.log(`
330
+ `);for(let i of n){let u=ie(i.timestamp);console.log(` [${u}] ${oe(i)}`),i.responseBody?console.log(` ${Q(i.responseBody)}`):i.error&&console.log(` ${i.error}`)}}}async function V(o={}){let t=o.counts!==void 0?o.counts:await d.send({type:"evaluate",code:Se});if(!t||typeof t!="object")return;let s=t,n=Math.max(0,Number(s.errors)||0),i=Math.max(0,Number(s.warnings)||0);if(n===0&&i===0||!o.includeTail&&!je("console",z,`${n}:${i}`))return;let u=[];if(n>0&&u.push(`${n} console error${n===1?"":"s"}`),i>0&&u.push(`${i} console warning${i===1?"":"s"}`),console.log(`
331
+ console: ${u.join(", ")}`),console.log(` inspect: ${h("errors")} 5`),i>0&&console.log(` inspect: ${h("warnings")} 5`),!o.includeTail||n===0)return;let m=await fe(d,5);if(!(!Array.isArray(m)||m.length===0)){console.log(`
332
332
  recent console errors:
333
- `);for(let h of p){let f=ie(h.timestamp),w=Array.isArray(h.args)?h.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(h);console.log(` [${f}] ${w}`)}}}let Z=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function re(o){let t=ze(),s=null;try{s=await Ve(o,`(() => {
333
+ `);for(let b of m){let f=ie(b.timestamp),w=Array.isArray(b.args)?b.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(b);console.log(` [${f}] ${w}`)}}}let Z=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function re(o){let t=Ye(),s=null;try{s=await Ze(o,`(() => {
334
334
  const tl = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.timeline
335
335
  if (!tl || typeof tl.summary !== 'function') return null
336
336
  const cursorKey = ${JSON.stringify(t)}
@@ -346,9 +346,9 @@ ${s}
346
346
  }
347
347
  }
348
348
  return summary ? { summary, consoleSplit } : null
349
- })()`)}catch{return}if(!s||!s.summary||!s.summary.total)return;let r=s.summary.byKind??{},a=[],d=new Set;for(let p of Z){let h=r[p];if(h)if(d.add(p),p==="console"&&s.consoleSplit){let{error:f,warn:w}=s.consoleSplit;f>0&&a.push(`${f} error${f===1?"":"s"}`),w>0&&a.push(`${w} warning${w===1?"":"s"}`)}else a.push(`${h} ${p}${h===1?"":"s"}`)}for(let[p,h]of Object.entries(r))!d.has(p)&&h&&a.push(`${h} ${p}${h===1?"":"s"}`);if(a.length!==0&&(console.log(`
350
- since last: ${a.join(" \xB7 ")} \u2014 sootsim what-happened`),s.summary.lastAt))try{await Oe(o,"SootSim.bridges.timeline.cursorAdvance",t,s.summary.lastAt)}catch{}}let pe=new Set(["tap","double-tap","tap-text","tap-id","type","type-into","key","key-sequence","keycode","drag","swipe","long-press","touch","gesture","pinch","scroll","shell"]),C=new Set(["a11y","capture","count","double-tap","drag","find","gesture","layout","long-press","node","pinch","sample-color","scroll","screenshot","swipe","tap","tap-id","tap-text","touch","tree","type-into"]),le=(e.includes("--verbose")||e.includes("-v"))&&!e.includes("--json");y==="do"&&g==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),pe.has(g)&&await Xe(u),C.has(g)&&await ue(u,{verbose:le});try{switch(g){case"list":{await jt({bridge:u,simId:I,args:c});break}case"tree":{await Ht({bridge:u,args:c,positional:i});break}case"a11y":{let o=await it(u);if(!Array.isArray(o)||o.length===0){console.log(" no accessible nodes found");break}if(e.includes("--json"))console.log(JSON.stringify(o,null,2));else{console.log(` accessibility tree (${o.length} nodes):
351
- `);for(let t of o){let s=[];if(s.push(`[${t.role}]`),t.label){let r=t.label.length>50?t.label.slice(0,47)+"...":t.label;s.push(`"${r}"`)}if(t.hint&&s.push(`(hint: "${t.hint}")`),t.testID&&s.push(`#${t.testID}`),t.state){let r=[];t.state.disabled&&r.push("disabled"),t.state.selected&&r.push("selected"),t.state.checked===!0&&r.push("checked"),t.state.checked==="mixed"&&r.push("mixed"),t.state.busy&&r.push("busy"),t.state.expanded===!0&&r.push("expanded"),t.state.expanded===!1&&r.push("collapsed"),r.length&&s.push(`{${r.join(", ")}}`)}t.position&&s.push(`@(${t.position.x},${t.position.y})`),t.size&&s.push(`${t.size.w}x${t.size.h}`),console.log(" "+s.join(" "))}}break}case"find":{await Dt({bridge:u,args:e,effectiveArgs:c,positional:i,inspectUsage:k});break}case"count":{await Et(u,{args:c});break}case"keyboard":{await Bt(u,{json:e.includes("--json")});break}case"screens":{await Jt(u,{json:e.includes("--json")});break}case"memory":{await Lt(u,{args:c});break}case"wait":{await Ut({wsPort:_,commandTimeoutMs:j,simId:I,simIdSource:E,positional:i});break}case"sleep":{await qt({positional:i,inspectUsage:k});break}case"settle":{await Wt({bridge:u,args:e,positional:i});break}case"ready":{await Xt({bridge:u,args:e});break}case"idle":{await Yt({bridge:u,args:e,positional:i});break}case"selector":{await Vt({bridge:u,args:e,positional:i,inspectUsage:k});break}case"event":{await Gt({bridge:u,args:e,positional:i,inspectUsage:k});break}case"layout":{let o=i[1];if(!o){await Ct({bridge:u,args:c});break}let t=await u.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(o)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=e.find((h,f)=>e[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await oo(e,u),r={type:"screenshot"};s&&(r.crop=s);let d=(await u.send(r)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(d,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let o=await oo(e,u);o||(console.error(k("sample-color","<x> <y> [w] [h] | --id <testID> | --text <text>")),console.error(" samples an averaged color from the canvas. coords are logical sootsim units."),process.exit(1));let t=await u.send({type:"evaluate",code:kt(o)});if(e.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:r,b:a,a:d,hex:p,samples:h}=t,f=o.w===1&&o.h===1?`@(${o.x},${o.y})`:`@(${o.x},${o.y}) ${o.w}x${o.h}`;console.log(` ${p} rgba(${s}, ${r}, ${a}, ${d}) ${f} ${h} samples`)}break}case"node":{let o=i[1];o||(console.error(k("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await u.send({type:"evaluate",code:`(async () => {
349
+ })()`)}catch{return}if(!s||!s.summary||!s.summary.total)return;let n=s.summary.byKind??{},i=[],u=new Set;for(let m of Z){let b=n[m];if(b)if(u.add(m),m==="console"&&s.consoleSplit){let{error:f,warn:w}=s.consoleSplit;f>0&&i.push(`${f} error${f===1?"":"s"}`),w>0&&i.push(`${w} warning${w===1?"":"s"}`)}else i.push(`${b} ${m}${b===1?"":"s"}`)}for(let[m,b]of Object.entries(n))!u.has(m)&&b&&i.push(`${b} ${m}${b===1?"":"s"}`);if(i.length!==0&&(console.log(`
350
+ since last: ${i.join(" \xB7 ")} \u2014 sootsim what-happened`),s.summary.lastAt))try{await Ae(o,"SootSim.bridges.timeline.cursorAdvance",t,s.summary.lastAt)}catch{}}let pe=new Set(["tap","double-tap","tap-text","tap-id","type","type-into","key","key-sequence","keycode","drag","swipe","long-press","touch","gesture","pinch","scroll","shell","storage-clear"]),C=new Set(["a11y","capture","count","double-tap","drag","find","gesture","layout","long-press","node","pinch","sample-color","scroll","screenshot","swipe","tap","tap-id","tap-text","touch","tree","type-into"]),le=(e.includes("--verbose")||e.includes("-v"))&&!e.includes("--json");y==="do"&&g==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),pe.has(g)&&await Qe(d),C.has(g)&&await de(d,{verbose:le});try{switch(g){case"list":{await jt({bridge:d,simId:I,args:c});break}case"tree":{await Ht({bridge:d,args:c,positional:a});break}case"a11y":{let o=await at(d);if(!Array.isArray(o)||o.length===0){console.log(" no accessible nodes found");break}if(e.includes("--json"))console.log(JSON.stringify(o,null,2));else{console.log(` accessibility tree (${o.length} nodes):
351
+ `);for(let t of o){let s=[];if(s.push(`[${t.role}]`),t.label){let n=t.label.length>50?t.label.slice(0,47)+"...":t.label;s.push(`"${n}"`)}if(t.hint&&s.push(`(hint: "${t.hint}")`),t.testID&&s.push(`#${t.testID}`),t.state){let n=[];t.state.disabled&&n.push("disabled"),t.state.selected&&n.push("selected"),t.state.checked===!0&&n.push("checked"),t.state.checked==="mixed"&&n.push("mixed"),t.state.busy&&n.push("busy"),t.state.expanded===!0&&n.push("expanded"),t.state.expanded===!1&&n.push("collapsed"),n.length&&s.push(`{${n.join(", ")}}`)}t.position&&s.push(`@(${t.position.x},${t.position.y})`),t.size&&s.push(`${t.size.w}x${t.size.h}`),console.log(" "+s.join(" "))}}break}case"find":{await Dt({bridge:d,args:e,effectiveArgs:c,positional:a,inspectUsage:k});break}case"count":{await Pt(d,{args:c});break}case"keyboard":{await Bt(d,{json:e.includes("--json")});break}case"screens":{await Jt(d,{json:e.includes("--json")});break}case"memory":{await Lt(d,{args:c});break}case"wait":{await Ut({wsPort:_,commandTimeoutMs:j,simId:I,simIdSource:P,positional:a});break}case"sleep":{await qt({positional:a,inspectUsage:k});break}case"settle":{await Wt({bridge:d,args:e,positional:a});break}case"ready":{await Xt({bridge:d,args:e});break}case"idle":{await Yt({bridge:d,args:e,positional:a});break}case"selector":{await Vt({bridge:d,args:e,positional:a,inspectUsage:k});break}case"event":{await Gt({bridge:d,args:e,positional:a,inspectUsage:k});break}case"layout":{let o=a[1];if(!o){await Ct({bridge:d,args:c});break}let t=await d.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(o)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=e.find((b,f)=>e[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await so(e,d),n={type:"screenshot"};s&&(n.crop=s);let u=(await d.send(n)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(u,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let o=await so(e,d);o||(console.error(k("sample-color","<x> <y> [w] [h] | --id <testID> | --text <text>")),console.error(" samples an averaged color from the canvas. coords are logical sootsim units."),process.exit(1));let t=await d.send({type:"evaluate",code:kt(o)});if(e.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:n,b:i,a:u,hex:m,samples:b}=t,f=o.w===1&&o.h===1?`@(${o.x},${o.y})`:`@(${o.x},${o.y}) ${o.w}x${o.h}`;console.log(` ${m} rgba(${s}, ${n}, ${i}, ${u}) ${f} ${b} samples`)}break}case"node":{let o=a[1];o||(console.error(k("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await d.send({type:"evaluate",code:`(async () => {
352
352
  const t = window.__sootsimTest
353
353
  const q = ${JSON.stringify(o)}
354
354
  let node = null
@@ -404,17 +404,17 @@ ${s}
404
404
  transform,
405
405
  parentChain,
406
406
  }
407
- })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(i[1]),t=Number(i[2]),s=be(e);if(s){let d=await ye(u,{agent:me(),textFallback:s.mode==="text"?s.value:void 0,resolve:async()=>{let f=await Te(u,s);return f?{cx:f.x,cy:f.y,match:{id:s.mode==="testid"?s.value:f.id??null,testID:s.mode==="testid"?s.value:f.testID??null,text:s.mode==="text"?s.value:f.text??null,type:f.type??null},target:{id:f.id??null,testID:f.testID??null,text:f.text??null,type:f.type??null}}:null}}),p=d.payload;(!p||typeof p.cx!="number")&&(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),de(d.result)||(N(`${s.mode} "${s.value}"`,d),process.exit(1));let h=no(p.cx,p.cy,d.result);h&&await L("inspect tap",h.step,h.summary),console.log(JSON.stringify({...d.attempts>1?{attempts:d.attempts}:{},...d.result},null,2));break}(!Number.isFinite(o)||!Number.isFinite(t))&&(console.error(k("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await _t(u,o,t),a=no(o,t,r);a&&await L("inspect tap",a.step,a.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),r=Number(i[4]),a=g==="swipe"?10:12,d=g==="swipe"?8:16,p=i[5]?Number(i[5]):a,h=i[6]?Number(i[6]):d;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(p)||!Number.isFinite(h))&&(console.error(k(g,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await u.send({type:"evaluate",code:`(async () => {
407
+ })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(a[1]),t=Number(a[2]),s=we(e);if(s){let u=await be(d,{agent:me(),textFallback:s.mode==="text"?s.value:void 0,resolve:async()=>{let f=await Me(d,s);return f?{cx:f.x,cy:f.y,match:{id:s.mode==="testid"?s.value:f.id??null,testID:s.mode==="testid"?s.value:f.testID??null,text:s.mode==="text"?s.value:f.text??null,type:f.type??null},target:{id:f.id??null,testID:f.testID??null,text:f.text??null,type:f.type??null}}:null}}),m=u.payload;(!m||typeof m.cx!="number")&&(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),ue(u.result)||(N(`${s.mode} "${s.value}"`,u),process.exit(1));let b=ro(m.cx,m.cy,u.result);b&&await L("inspect tap",b.step,b.summary),console.log(JSON.stringify({...u.attempts>1?{attempts:u.attempts}:{},...u.result},null,2));break}(!Number.isFinite(o)||!Number.isFinite(t))&&(console.error(k("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let n=await _t(d,o,t),i=ro(o,t,n);i&&await L("inspect tap",i.step,i.summary),console.log(JSON.stringify(n,null,2));break}case"drag":case"swipe":{let o=Number(a[1]),t=Number(a[2]),s=Number(a[3]),n=Number(a[4]),i=g==="swipe"?10:12,u=g==="swipe"?8:16,m=a[5]?Number(a[5]):i,b=a[6]?Number(a[6]):u;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(b))&&(console.error(k(g,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await d.send({type:"evaluate",code:`(async () => {
408
408
  const interact = window.__sootsimInteract
409
409
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
410
- const value = await interact.drag(${o}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(h))})
410
+ const value = await interact.drag(${o}, ${t}, ${s}, ${n}, ${Math.max(1,Math.round(m))}, ${Math.max(0,Math.round(b))})
411
411
  return { ok: !!value, value }
412
- })()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,h)));await L(`inspect ${g}`,{swipe:{start:`${o}, ${t}`,end:`${s}, ${r}`,duration:w}},`${g} ${o},${t} -> ${s},${r}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),r=Number(i[4]),a=Number(i[5]),d=Number(i[6]),p=Number(i[7]),h=Number(i[8]),f=i[9]?Number(i[9]):12,w=i[10]?Number(i[10]):16;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(a)||!Number.isFinite(d)||!Number.isFinite(p)||!Number.isFinite(h)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(k("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await u.send({type:"evaluate",code:`(async () => {
412
+ })()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,m)*Math.max(0,b)));await L(`inspect ${g}`,{swipe:{start:`${o}, ${t}`,end:`${s}, ${n}`,duration:w}},`${g} ${o},${t} -> ${s},${n}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let o=Number(a[1]),t=Number(a[2]),s=Number(a[3]),n=Number(a[4]),i=Number(a[5]),u=Number(a[6]),m=Number(a[7]),b=Number(a[8]),f=a[9]?Number(a[9]):12,w=a[10]?Number(a[10]):16;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(b)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(k("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await d.send({type:"evaluate",code:`(async () => {
413
413
  const interact = window.__sootsimInteract
414
414
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
415
- const value = await interact.pinch(${o}, ${t}, ${s}, ${r}, ${a}, ${d}, ${p}, ${h}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
415
+ const value = await interact.pinch(${o}, ${t}, ${s}, ${n}, ${i}, ${u}, ${m}, ${b}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
416
416
  return { ok: !!value, value }
417
- })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[o,t,s,r],to:[a,d,p,h],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${o},${t}) (${s},${r}) -> (${a},${d}) (${p},${h})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let o=i[1];o||(console.error(k("tap-text","<text>")),process.exit(1));let t=U=>{let R=e.indexOf(U);return R>=0&&R+1<e.length?e[R+1]:null},s=U=>e.includes(U),r=t("--nth")??t("--index"),a=r!==null?Number(r):null;a!==null&&!Number.isFinite(a)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let d=t("--within"),p=t("--role"),h=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),q=t("--min-x"),H=t("--max-x");for(let[U,R]of[["--min-y",w],["--max-y",O],["--min-x",q],["--max-x",H]])R!==null&&!Number.isFinite(Number(R))&&(console.error(` ${U} requires a number, got: ${R}`),process.exit(1));let K=e.indexOf("--near"),F=null;if(K>=0){let U=Number(e[K+1]),R=Number(e[K+2]);(!Number.isFinite(U)||!Number.isFinite(R))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:U,y:R}}let x={exact:h,role:p,within:d,minX:q!==null?Number(q):null,maxX:H!==null?Number(H):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:a,first:f},$=await At(u,o,x,{agent:me()}),v=$.payload;if(v?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),v?.ambiguous){let U=v.candidates;console.error(` ambiguous: ${v.total} matches for "${o}"`);for(let R of U){let we=R.abs?`@(${Math.round(R.abs.x)},${Math.round(R.abs.y)})`:"",lo=R.layout?` ${R.layout.width}x${R.layout.height}`:"",co=R.testID?` #${R.testID}`:"",uo=R.text?` "${R.text}"`:"",mo=R.ancestorTestIDs.length>0?` within ${R.ancestorTestIDs.slice(0,3).map(po=>`#${po}`).join(" > ")}`:"";console.error(` [${R.idx}] <${R.type}>${uo}${co} ${we}${lo}${mo}`)}v.total>U.length&&console.error(` ... and ${v.total-U.length} more`),console.error(" pick one:"),console.error(" --nth <index> pick the nth match (top-to-bottom, left-to-right; negatives from end)"),console.error(" --within <testID> narrow to descendants of a node"),console.error(" --min-y / --max-y geometric filter (pixels, absolute)"),console.error(" --min-x / --max-x geometric filter (pixels, absolute)"),console.error(" --near <x> <y> pick the closest match to a point"),console.error(" --exact exact text match (default is substring)"),console.error(" --role <role> narrow to accessibilityRole"),console.error(" --first keep the old pick-first-silently behavior"),process.exit(2)}v?.nthOutOfRange&&(console.error(` not found: nth ${v.nth} of ${v.total} match${v.total===1?"":"es"} for "${o}"`),process.exit(1)),(!v||typeof v.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),de($.result)||(N(`text "${o}"`,$),process.exit(1));let se=qe(o,{id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},"text");await L("inspect tap-text",se.step,se.summary),console.log(JSON.stringify({matched:v.match,tapped:{nodeId:v.target?.nodeId??null,id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},...v.strategy&&v.strategy!=="matched-node"?{strategy:v.strategy}:{},...v.total>1||a!==null?{nth:{index:v.idx,total:v.total}}:{},...$.attempts>1?{attempts:$.attempts}:{},result:$.result},null,2));break}case"tap-best":{let o=i[1];o||(console.error(k("tap-best","<query>")),process.exit(1));let t=await Pt(u,o,{agent:me()}),s=t.payload;s||(console.error(` tap-best: no testID or visible text matched "${o}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1)),"error"in s&&(console.error(` ${s.error}`),process.exit(1)),s.strategy==="none"&&(console.error(` tap-best: no testID or visible text matched "${o}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1));let r=s.node;de(t.result)||(N(`best "${o}"`,t),process.exit(1));let a=qe(o,{id:r.id,testID:r.testID,type:r.type,cx:s.cx,cy:s.cy},s.strategy==="testid"?"id":"text");await L("inspect tap-best",a.step,a.summary),console.log(JSON.stringify({matched:{strategy:s.strategy,nodeId:r.nodeId,id:r.id,testID:r.testID,type:r.type,text:r.text},tapped:{cx:s.cx,cy:s.cy},...t.attempts>1?{attempts:t.attempts}:{},result:t.result},null,2));break}case"tap-id":{let o=i[1];o||(console.error(k("tap-id","<id>")),process.exit(1));let t=await Ot(u,o,{agent:me()}),s=t.payload;(!s||typeof s.cx!="number")&&(console.error(` not found: ${o}`),await Co(u,o),process.exit(1)),de(t.result)||(N(`id "${o}"`,t),process.exit(1));let r=qe(o,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",r.step,r.summary),console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},...t.attempts>1?{attempts:t.attempts}:{},result:t.result},null,2));break}case"type-into":{let o=i[1],t=i.slice(2).join(" ");(!o||!t)&&(console.error(k("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(o),r=await u.send({type:"evaluate",code:`(async () => {
417
+ })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[o,t,s,n],to:[i,u,m,b],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${o},${t}) (${s},${n}) -> (${i},${u}) (${m},${b})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let o=a[1];o||(console.error(k("tap-text","<text>")),process.exit(1));let t=U=>{let R=e.indexOf(U);return R>=0&&R+1<e.length?e[R+1]:null},s=U=>e.includes(U),n=t("--nth")??t("--index"),i=n!==null?Number(n):null;i!==null&&!Number.isFinite(i)&&(console.error(` --nth/--index requires an integer, got: ${n}`),process.exit(1));let u=t("--within"),m=t("--role"),b=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),q=t("--min-x"),H=t("--max-x");for(let[U,R]of[["--min-y",w],["--max-y",O],["--min-x",q],["--max-x",H]])R!==null&&!Number.isFinite(Number(R))&&(console.error(` ${U} requires a number, got: ${R}`),process.exit(1));let K=e.indexOf("--near"),F=null;if(K>=0){let U=Number(e[K+1]),R=Number(e[K+2]);(!Number.isFinite(U)||!Number.isFinite(R))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:U,y:R}}let x={exact:b,role:m,within:u,minX:q!==null?Number(q):null,maxX:H!==null?Number(H):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:i,first:f},$=await At(d,o,x,{agent:me()}),v=$.payload;if(v?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),v?.ambiguous){let U=v.candidates;console.error(` ambiguous: ${v.total} matches for "${o}"`);for(let R of U){let xe=R.abs?`@(${Math.round(R.abs.x)},${Math.round(R.abs.y)})`:"",co=R.layout?` ${R.layout.width}x${R.layout.height}`:"",uo=R.testID?` #${R.testID}`:"",mo=R.text?` "${R.text}"`:"",po=R.ancestorTestIDs.length>0?` within ${R.ancestorTestIDs.slice(0,3).map(fo=>`#${fo}`).join(" > ")}`:"";console.error(` [${R.idx}] <${R.type}>${mo}${uo} ${xe}${co}${po}`)}v.total>U.length&&console.error(` ... and ${v.total-U.length} more`),console.error(" pick one:"),console.error(" --nth <index> pick the nth match (top-to-bottom, left-to-right; negatives from end)"),console.error(" --within <testID> narrow to descendants of a node"),console.error(" --min-y / --max-y geometric filter (pixels, absolute)"),console.error(" --min-x / --max-x geometric filter (pixels, absolute)"),console.error(" --near <x> <y> pick the closest match to a point"),console.error(" --exact exact text match (default is substring)"),console.error(" --role <role> narrow to accessibilityRole"),console.error(" --first keep the old pick-first-silently behavior"),process.exit(2)}v?.nthOutOfRange&&(console.error(` not found: nth ${v.nth} of ${v.total} match${v.total===1?"":"es"} for "${o}"`),process.exit(1)),(!v||typeof v.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),ue($.result)||(N(`text "${o}"`,$),process.exit(1));let se=Ke(o,{id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},"text");await L("inspect tap-text",se.step,se.summary),console.log(JSON.stringify({matched:v.match,tapped:{nodeId:v.target?.nodeId??null,id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},...v.strategy&&v.strategy!=="matched-node"?{strategy:v.strategy}:{},...v.total>1||i!==null?{nth:{index:v.idx,total:v.total}}:{},...$.attempts>1?{attempts:$.attempts}:{},result:$.result},null,2));break}case"tap-best":{let o=a[1];o||(console.error(k("tap-best","<query>")),process.exit(1));let t=await Et(d,o,{agent:me()}),s=t.payload;s||(console.error(` tap-best: no testID or visible text matched "${o}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1)),"error"in s&&(console.error(` ${s.error}`),process.exit(1)),s.strategy==="none"&&(console.error(` tap-best: no testID or visible text matched "${o}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1));let n=s.node;ue(t.result)||(N(`best "${o}"`,t),process.exit(1));let i=Ke(o,{id:n.id,testID:n.testID,type:n.type,cx:s.cx,cy:s.cy},s.strategy==="testid"?"id":"text");await L("inspect tap-best",i.step,i.summary),console.log(JSON.stringify({matched:{strategy:s.strategy,nodeId:n.nodeId,id:n.id,testID:n.testID,type:n.type,text:n.text},tapped:{cx:s.cx,cy:s.cy},...t.attempts>1?{attempts:t.attempts}:{},result:t.result},null,2));break}case"tap-id":{let o=a[1];o||(console.error(k("tap-id","<id>")),process.exit(1));let t=await Ot(d,o,{agent:me()}),s=t.payload;(!s||typeof s.cx!="number")&&(console.error(` not found: ${o}`),await Bo(d,o),process.exit(1)),ue(t.result)||(N(`id "${o}"`,t),process.exit(1));let n=Ke(o,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",n.step,n.summary),console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},...t.attempts>1?{attempts:t.attempts}:{},result:t.result},null,2));break}case"type-into":{let o=a[1],t=a.slice(2).join(" ");(!o||!t)&&(console.error(k("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(o),n=await d.send({type:"evaluate",code:`(async () => {
418
418
  const t = window.__sootsimTest
419
419
  if (!t) return null
420
420
  const n = await (t.findByTestId(${s}) || t.findById(${s}))
@@ -429,36 +429,36 @@ ${s}
429
429
  secureTextEntry: !!n.secureTextEntry,
430
430
  placeholder: n.placeholder || null,
431
431
  }
432
- })()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),r.isTextInput||console.error(` warning: ${o} is not a text input (isTextInput: false)`);let a=await u.send({type:"tap",x:r.cx,y:r.cy,target:{id:r.id??o,testID:r.testID??o,text:null,type:r.type??null}}),d=r.secureTextEntry===!0,p=await zo(u,1e3,{targetId:o,secureTextEntry:d});p.visible||(console.error(` keyboard did not open after tapping ${o}`),process.exit(1));let h=p.focusedInput;h&&(h.testID===o||h.id===o||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(o)} but focus is on ${JSON.stringify(h.testID??h.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await u.send({type:"keyboard",action:"type",text:t});let f=d||he(p),w=f?X:Le(t,p),O=f&&p.focusedInput?{...p.focusedInput,secureTextEntry:!0,text:typeof p.focusedInput.text=="string"?X:p.focusedInput.text}:p.focusedInput??null;await L("inspect type-into",{tapOn:{id:o},inputText:w},w===X?`type-into #${o} ${X}`:`type-into #${o} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:o,isTextInput:r.isTextInput,secureTextEntry:f,keyboardOpened:p.visible??a?.keyboardOpened??!1,focusedInput:O,typed:w},null,2));break}case"type":{let o=i.slice(1).join(" ");o||(console.error(k("type","<text>")),process.exit(1));let t=await Ne(u,"type");await u.send({type:"keyboard",action:"type",text:o});let s=Le(o,t);await L("inspect type",{inputText:s},s===X?`type ${X}`:`type ${JSON.stringify(o)}`),console.log(s===X?` typed: ${X}`:` typed: ${JSON.stringify(o)}`);break}case"key":{let o=i[1];o||(console.error(k("key","<name>")),process.exit(1)),await Ne(u,"key"),await u.send({type:"keyboard",action:"press",text:o}),await L("inspect key",{pressKey:o},`key ${o}`),console.log(` pressed: ${o}`);break}case"key-sequence":{let o=i.slice(1);o.length===0&&(console.error(k("key-sequence","<key> [<key> ...]")),process.exit(1)),await Ne(u,"key-sequence");for(let t of o)await u.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:o.join(" ")},`key-sequence ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"keycode":{let o=i.slice(1);o.length===0&&(console.error(k("keycode","<code> [<code> ...]")),process.exit(1));let t=o.map(r=>({code:r,key:Go(r)})),s=t.filter(r=>!r.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(r=>r.code).join(", ")}`),process.exit(1)),await Ne(u,"keycode");for(let r of t)await u.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"dispatch":{let o=i[1];o||(console.error(k("dispatch","<char>")),process.exit(1)),await u.send({type:"keyboard",action:"dispatchKey",text:o}),await L("inspect dispatch",{dispatchKey:o},`dispatch ${JSON.stringify(o)}`),console.log(` dispatched: ${o}`);break}case"dismiss":{await u.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let o=Number(i[1]),t=Number(i[2]),s=be(e);if(s){let p=await Te(u,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=p.x,t=p.y}let r=i[3]?Number(i[3]):80;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(k("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let a=Math.max(0,Math.round(r)),d=await u.send({type:"evaluate",code:`(async () => {
432
+ })()`});(!n||typeof n.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),n.isTextInput||console.error(` warning: ${o} is not a text input (isTextInput: false)`);let i=await d.send({type:"tap",x:n.cx,y:n.cy,target:{id:n.id??o,testID:n.testID??o,text:null,type:n.type??null}}),u=n.secureTextEntry===!0,m=await zo(d,1e3,{targetId:o,secureTextEntry:u});m.visible||(console.error(` keyboard did not open after tapping ${o}`),process.exit(1));let b=m.focusedInput;b&&(b.testID===o||b.id===o||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(o)} but focus is on ${JSON.stringify(b.testID??b.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await d.send({type:"keyboard",action:"type",text:t});let f=u||he(m),w=f?X:We(t,m),O=f&&m.focusedInput?{...m.focusedInput,secureTextEntry:!0,text:typeof m.focusedInput.text=="string"?X:m.focusedInput.text}:m.focusedInput??null;await L("inspect type-into",{tapOn:{id:o},inputText:w},w===X?`type-into #${o} ${X}`:`type-into #${o} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:o,isTextInput:n.isTextInput,secureTextEntry:f,keyboardOpened:m.visible??i?.keyboardOpened??!1,focusedInput:O,typed:w},null,2));break}case"type":{let o=a.slice(1).join(" ");o||(console.error(k("type","<text>")),process.exit(1));let t=await Fe(d,"type");await d.send({type:"keyboard",action:"type",text:o});let s=We(o,t);await L("inspect type",{inputText:s},s===X?`type ${X}`:`type ${JSON.stringify(o)}`),console.log(s===X?` typed: ${X}`:` typed: ${JSON.stringify(o)}`);break}case"key":{let o=a[1];o||(console.error(k("key","<name>")),process.exit(1)),await Fe(d,"key"),await d.send({type:"keyboard",action:"press",text:o}),await L("inspect key",{pressKey:o},`key ${o}`),console.log(` pressed: ${o}`);break}case"key-sequence":{let o=a.slice(1);o.length===0&&(console.error(k("key-sequence","<key> [<key> ...]")),process.exit(1)),await Fe(d,"key-sequence");for(let t of o)await d.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:o.join(" ")},`key-sequence ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"keycode":{let o=a.slice(1);o.length===0&&(console.error(k("keycode","<code> [<code> ...]")),process.exit(1));let t=o.map(n=>({code:n,key:Go(n)})),s=t.filter(n=>!n.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(n=>n.code).join(", ")}`),process.exit(1)),await Fe(d,"keycode");for(let n of t)await d.send({type:"keyboard",action:"press",text:n.key});await L("inspect keycode",{pressKey:t.map(n=>n.key).join(" ")},`keycode ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"dispatch":{let o=a[1];o||(console.error(k("dispatch","<char>")),process.exit(1)),await d.send({type:"keyboard",action:"dispatchKey",text:o}),await L("inspect dispatch",{dispatchKey:o},`dispatch ${JSON.stringify(o)}`),console.log(` dispatched: ${o}`);break}case"dismiss":{await d.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let o=Number(a[1]),t=Number(a[2]),s=we(e);if(s){let m=await Me(d,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=m.x,t=m.y}let n=a[3]?Number(a[3]):80;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(n))&&(console.error(k("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let i=Math.max(0,Math.round(n)),u=await d.send({type:"evaluate",code:`(async () => {
433
433
  const interact = window.__sootsimInteract
434
434
  if (interact?.doubleTap) {
435
435
  return {
436
- ok: !!(await interact.doubleTap(${o}, ${t}, ${a})),
437
- gapMs: ${a},
436
+ ok: !!(await interact.doubleTap(${o}, ${t}, ${i})),
437
+ gapMs: ${i},
438
438
  }
439
439
  }
440
440
  if (!interact?.tap) {
441
- return { ok: false, reason: 'no interact.tap', gapMs: ${a} }
441
+ return { ok: false, reason: 'no interact.tap', gapMs: ${i} }
442
442
  }
443
443
  const first = await interact.tap(${o}, ${t})
444
444
  if (!first || first.hit === false) {
445
- return { ok: false, reason: 'first tap missed', gapMs: ${a}, first }
445
+ return { ok: false, reason: 'first tap missed', gapMs: ${i}, first }
446
446
  }
447
- await new Promise((resolve) => setTimeout(resolve, ${a}))
447
+ await new Promise((resolve) => setTimeout(resolve, ${i}))
448
448
  const second = await interact.tap(${o}, ${t})
449
449
  return {
450
450
  ok: !!second && second.hit !== false,
451
- gapMs: ${a},
451
+ gapMs: ${i},
452
452
  first,
453
453
  second,
454
454
  }
455
- })()`});d?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:o,y:t,gapMs:a}},`double-tap @${o},${t}`),console.log(JSON.stringify(d,null,2));break}case"long-press":{let o=Number(i[1]),t=Number(i[2]),s=be(e),r=null;if(s){let f=await Te(u,s);f||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=f.x,t=f.y,r={id:f.id??null,testID:f.testID??null,text:f.text??null,type:f.type??null}}let a=s?i[1]:i[3],d=a?Number(a):600;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(d))&&(console.error(k("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let p=Math.max(0,Math.round(d)),h=await u.send({type:"longPress",x:o,y:t,durationMs:p,target:r});h?.ok&&await L("inspect long-press",{tapAtCoords:{x:o,y:t}},`long-press @${o},${t}`),console.log(JSON.stringify(h,null,2));break}case"touch":{let o=i[1],t=Number(i[2]),s=Number(i[3]),r=i[4]?Number(i[4]):999,a=o==="down"?"touchDown":o==="move"?"touchMove":o==="up"?"touchUp":o==="cancel"?"touchCancel":null;a||(console.error(k("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),o!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(k("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let d=o==="down"?"tap":o==="move"?"move":null,p=d&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${d}', x: ${t}, y: ${s} } }));`:"",h=await u.send({type:"evaluate",code:`(async () => {
456
- ${p}
455
+ })()`});u?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:o,y:t,gapMs:i}},`double-tap @${o},${t}`),console.log(JSON.stringify(u,null,2));break}case"long-press":{let o=Number(a[1]),t=Number(a[2]),s=we(e),n=null;if(s){let f=await Me(d,s);f||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=f.x,t=f.y,n={id:f.id??null,testID:f.testID??null,text:f.text??null,type:f.type??null}}let i=s?a[1]:a[3],u=i?Number(i):600;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(u))&&(console.error(k("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let m=Math.max(0,Math.round(u)),b=await d.send({type:"longPress",x:o,y:t,durationMs:m,target:n});b?.ok&&await L("inspect long-press",{tapAtCoords:{x:o,y:t}},`long-press @${o},${t}`),console.log(JSON.stringify(b,null,2));break}case"touch":{let o=a[1],t=Number(a[2]),s=Number(a[3]),n=a[4]?Number(a[4]):999,i=o==="down"?"touchDown":o==="move"?"touchMove":o==="up"?"touchUp":o==="cancel"?"touchCancel":null;i||(console.error(k("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),o!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(k("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let u=o==="down"?"tap":o==="move"?"move":null,m=u&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${u}', x: ${t}, y: ${s} } }));`:"",b=await d.send({type:"evaluate",code:`(async () => {
456
+ ${m}
457
457
  const interact = window.__sootsimInteract
458
- if (!interact?.${a}) return { ok: false, reason: 'no interact.${a}' }
459
- const value = ${o==="cancel"?`await interact.${a}(${Math.max(1,Math.round(r))})`:`await interact.${a}(${t}, ${s}, ${Math.max(1,Math.round(r))})`}
458
+ if (!interact?.${i}) return { ok: false, reason: 'no interact.${i}' }
459
+ const value = ${o==="cancel"?`await interact.${i}(${Math.max(1,Math.round(n))})`:`await interact.${i}(${t}, ${s}, ${Math.max(1,Math.round(n))})`}
460
460
  return { ok: !!value, value }
461
- })()`});h?.ok&&o!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${o} @${t},${s}`),console.log(JSON.stringify(h,null,2));break}case"gesture":{let o=["scroll-up","scroll-down","scroll-left","scroll-right","swipe-from-left-edge","swipe-from-right-edge","swipe-from-top-edge","swipe-from-bottom-edge"],t=i[1],s=i[2]?Number(i[2]):220;(!t||!Number.isFinite(s))&&(console.error(k("gesture","<preset> [durationMs]")),console.error(` presets: ${o.join(", ")}`),process.exit(1)),o.includes(t)||(console.error(` unknown gesture preset: ${t}`),console.error(` presets: ${o.join(", ")}`),process.exit(1));let r=await u.send({type:"evaluate",code:`(async () => {
461
+ })()`});b?.ok&&o!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${o} @${t},${s}`),console.log(JSON.stringify(b,null,2));break}case"gesture":{let o=["scroll-up","scroll-down","scroll-left","scroll-right","swipe-from-left-edge","swipe-from-right-edge","swipe-from-top-edge","swipe-from-bottom-edge"],t=a[1],s=a[2]?Number(a[2]):220;(!t||!Number.isFinite(s))&&(console.error(k("gesture","<preset> [durationMs]")),console.error(` presets: ${o.join(", ")}`),process.exit(1)),o.includes(t)||(console.error(` unknown gesture preset: ${t}`),console.error(` presets: ${o.join(", ")}`),process.exit(1));let n=await d.send({type:"evaluate",code:`(async () => {
462
462
  const spec = globalThis.__sootsimDeviceSpec || {}
463
463
  return {
464
464
  width: spec.width || window.innerWidth || 393,
@@ -466,12 +466,12 @@ ${s}
466
466
  statusBarHeight: spec.statusBarHeight || 0,
467
467
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
468
468
  }
469
- })()`}),a=Number(r?.width)||393,d=Number(r?.height)||852,p=Number(r?.statusBarHeight)||0,h=Number(r?.homeIndicatorHeight)||0,f=Math.round(a/2),w=Math.round(d/2),O=Math.max(24,p+18),q=Math.max(24,h+18),H=18,K=Math.min(220,Math.round(d*.24)),F=Math.min(180,Math.round(a*.32)),x=f,$=w,v=f,se=w;switch(t){case"scroll-up":$=w+Math.round(K/2),se=w-Math.round(K/2);break;case"scroll-down":$=w-Math.round(K/2),se=w+Math.round(K/2);break;case"scroll-left":x=f+Math.round(F/2),v=f-Math.round(F/2);break;case"scroll-right":x=f-Math.round(F/2),v=f+Math.round(F/2);break;case"swipe-from-left-edge":x=H,$=w,v=Math.min(a-H,H+F);break;case"swipe-from-right-edge":x=a-H,$=w,v=Math.max(H,a-H-F);break;case"swipe-from-top-edge":x=f,$=O,se=Math.min(d-q,O+K);break;case"swipe-from-bottom-edge":x=f,$=d-q,se=Math.max(O,d-q-K);break}let U=Math.max(8,Math.round(s/16)),R=Math.max(1,Math.round(s/U)),we=await u.send({type:"evaluate",code:`(async () => {
469
+ })()`}),i=Number(n?.width)||393,u=Number(n?.height)||852,m=Number(n?.statusBarHeight)||0,b=Number(n?.homeIndicatorHeight)||0,f=Math.round(i/2),w=Math.round(u/2),O=Math.max(24,m+18),q=Math.max(24,b+18),H=18,K=Math.min(220,Math.round(u*.24)),F=Math.min(180,Math.round(i*.32)),x=f,$=w,v=f,se=w;switch(t){case"scroll-up":$=w+Math.round(K/2),se=w-Math.round(K/2);break;case"scroll-down":$=w-Math.round(K/2),se=w+Math.round(K/2);break;case"scroll-left":x=f+Math.round(F/2),v=f-Math.round(F/2);break;case"scroll-right":x=f-Math.round(F/2),v=f+Math.round(F/2);break;case"swipe-from-left-edge":x=H,$=w,v=Math.min(i-H,H+F);break;case"swipe-from-right-edge":x=i-H,$=w,v=Math.max(H,i-H-F);break;case"swipe-from-top-edge":x=f,$=O,se=Math.min(u-q,O+K);break;case"swipe-from-bottom-edge":x=f,$=u-q,se=Math.max(O,u-q-K);break}let U=Math.max(8,Math.round(s/16)),R=Math.max(1,Math.round(s/U)),xe=await d.send({type:"evaluate",code:`(async () => {
470
470
  const interact = window.__sootsimInteract
471
471
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
472
472
  const value = await interact.drag(${x}, ${$}, ${v}, ${se}, ${U}, ${R})
473
473
  return { ok: !!value, value }
474
- })()`});we?.ok&&await L("inspect gesture",{swipe:{start:`${x}, ${$}`,end:`${v}, ${se}`,duration:Math.max(1,Math.round(s))}},`gesture ${t}`),console.log(JSON.stringify({preset:t,from:{x,y:$},to:{x:v,y:se},result:we},null,2));break}case"scroll":{let o=be(e),t=Xo(e),s=o?.mode==="testid"?o.value:t==null?i[1]:null,r=o||t!=null?1:2,a=Number(i[r]),d=Number(i[r+1]);(!s&&t==null||!Number.isFinite(a)||!Number.isFinite(d))&&(console.error(k("scroll","<id> <x> <y> | --testid <id> <x> <y> | --node-id <nodeId> <x> <y>")),process.exit(1));let p=await u.send({type:"evaluate",code:`(async () => {
474
+ })()`});xe?.ok&&await L("inspect gesture",{swipe:{start:`${x}, ${$}`,end:`${v}, ${se}`,duration:Math.max(1,Math.round(s))}},`gesture ${t}`),console.log(JSON.stringify({preset:t,from:{x,y:$},to:{x:v,y:se},result:xe},null,2));break}case"scroll":{let o=we(e),t=Xo(e),s=o?.mode==="testid"?o.value:t==null?a[1]:null,n=o||t!=null?1:2,i=Number(a[n]),u=Number(a[n+1]);(!s&&t==null||!Number.isFinite(i)||!Number.isFinite(u))&&(console.error(k("scroll","<id> <x> <y> | --testid <id> <x> <y> | --node-id <nodeId> <x> <y>")),process.exit(1));let m=await d.send({type:"evaluate",code:`(async () => {
475
475
  const t = window.__sootsimTest
476
476
  if (!t) return null
477
477
  const n = ${t!=null?`await t.inspectByNodeId(${JSON.stringify(t)})`:`await t.findByTestId(${JSON.stringify(s)})
@@ -481,8 +481,8 @@ ${s}
481
481
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
482
482
  cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
483
483
  }
484
- })()`}),h=await G(u,"scrollTo",t!=null?{nodeId:t}:s,a,d,!1);if(h?.ok){let f=t!=null?`node ${t}`:`#${s}`;await L("inspect scroll",{scrollTo:{...t!=null?{nodeId:t}:{id:s},x:a,y:d}},`scroll ${f} -> ${a},${d}`)}console.log(JSON.stringify({...h,...p?{at:{x:p.cx,y:p.cy}}:{}},null,2));break}case"state":{let o=i[1];if(n==="get"&&!o){let s=await G(u,"getRuntimeState"),r=await u.send({type:"evaluate",code:Se});if(s&&typeof s=="object"&&s.diagnostics&&(s.diagnostics.errors=r?.errors??0,s.diagnostics.warnings=r?.warnings??0),s&&typeof s=="object"&&s.shell==null)try{let a=await ce(u);a&&(s.shell=a)}catch{}console.log(JSON.stringify(s,null,2));break}if(!o||o==="--help"||o==="-h"){console.log(`
485
- ${b("state")} \u2014 dump raw runtime state
484
+ })()`}),b=await G(d,"scrollTo",t!=null?{nodeId:t}:s,i,u,!1);if(b?.ok){let f=t!=null?`node ${t}`:`#${s}`;await L("inspect scroll",{scrollTo:{...t!=null?{nodeId:t}:{id:s},x:i,y:u}},`scroll ${f} -> ${i},${u}`)}console.log(JSON.stringify({...b,...m?{at:{x:m.cx,y:m.cy}}:{}},null,2));break}case"state":{let o=a[1];if(r==="get"&&!o){let s=await G(d,"getRuntimeState"),n=await d.send({type:"evaluate",code:Se});if(s&&typeof s=="object"&&s.diagnostics&&(s.diagnostics.errors=n?.errors??0,s.diagnostics.warnings=n?.warnings??0),s&&typeof s=="object"&&s.shell==null)try{let i=await ce(d);i&&(s.shell=i)}catch{}console.log(JSON.stringify(s,null,2));break}if(!o||o==="--help"||o==="-h"){console.log(`
485
+ ${h("state")} \u2014 dump raw runtime state
486
486
 
487
487
  subcommands:
488
488
  shell dump shell transition/layout state
@@ -496,21 +496,21 @@ ${s}
496
496
  gesture <x> <y> dump gesture routing/debug info at coordinates
497
497
 
498
498
  examples:
499
- ${b("state")} shell
500
- ${b("state")} worker
501
- ${b("state")} keyboard
502
- ${b("state")} ownership
503
- ${b("state")} node photos
504
- ${b("state")} scroll feed
505
- ${b("state")} scroll-hit 360 420
506
- ${b("state")} hit 200 720
507
- `);break}let t;switch(o){case"shell":t=await ce(u,500);break;case"worker":t=await Oe(u,"__sootsimRenderHost.queryStats");break;case"ownership":t=await u.send({type:"evaluate",code:`(() => {
499
+ ${h("state")} shell
500
+ ${h("state")} worker
501
+ ${h("state")} keyboard
502
+ ${h("state")} ownership
503
+ ${h("state")} node photos
504
+ ${h("state")} scroll feed
505
+ ${h("state")} scroll-hit 360 420
506
+ ${h("state")} hit 200 720
507
+ `);break}let t;switch(o){case"shell":t=await ce(d,500);break;case"worker":t=await Ae(d,"__sootsimRenderHost.queryStats");break;case"ownership":t=await d.send({type:"evaluate",code:`(() => {
508
508
  const h = window.__sootsimRenderHost
509
509
  if (!h || typeof h.getOwnershipSnapshot !== 'function') {
510
510
  return { error: 'getOwnershipSnapshot not available' }
511
511
  }
512
512
  return h.getOwnershipSnapshot()
513
- })()`});break;case"keyboard":t=await u.send({type:"evaluate",code:`(async () => {
513
+ })()`});break;case"keyboard":t=await d.send({type:"evaluate",code:`(async () => {
514
514
  const kb = window.__sootsimKeyboard
515
515
  const test = window.__sootsimTest
516
516
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -538,8 +538,8 @@ ${s}
538
538
  text: secureTextEntry ? ${JSON.stringify(X)} : (focused.text || null),
539
539
  } : null,
540
540
  }
541
- })()`}),t=Je(t);break;case"node":{let s=i[2];s||(console.error(` usage: ${b("state")} node <id>`),process.exit(1)),t=await G(u,"findByTestId",s)||await G(u,"findById",s);break}case"scroll":{let s=i[2];s||(console.error(` usage: ${b("state")} scroll <id>`),process.exit(1)),t=await G(u,"getScrollState",s);break}case"scroll-hit":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${b("state")} scroll-hit <x> <y>`),process.exit(1)),t=await G(u,"getScrollStateAt",s,r);break}case"hit":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${b("state")} hit <x> <y>`),process.exit(1)),t=await G(u,"debugHitAt",s,r);break}case"gesture":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${b("state")} gesture <x> <y>`),process.exit(1)),t=await G(u,"debugGestureAt",s,r);break}default:console.error(` unknown state subcommand: ${o}`),process.exit(1)}console.log(JSON.stringify(t,null,2));break}case"shell":{let o=i[1];if(!o||o==="--help"||o==="-h"){console.log(`
542
- ${b("shell")} \u2014 run built-in shell commands
541
+ })()`}),t=qe(t);break;case"node":{let s=a[2];s||(console.error(` usage: ${h("state")} node <id>`),process.exit(1)),t=await G(d,"findByTestId",s)||await G(d,"findById",s);break}case"scroll":{let s=a[2];s||(console.error(` usage: ${h("state")} scroll <id>`),process.exit(1)),t=await G(d,"getScrollState",s);break}case"scroll-hit":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} scroll-hit <x> <y>`),process.exit(1)),t=await G(d,"getScrollStateAt",s,n);break}case"hit":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} hit <x> <y>`),process.exit(1)),t=await G(d,"debugHitAt",s,n);break}case"gesture":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} gesture <x> <y>`),process.exit(1)),t=await G(d,"debugGestureAt",s,n);break}default:console.error(` unknown state subcommand: ${o}`),process.exit(1)}console.log(JSON.stringify(t,null,2));break}case"shell":{let o=a[1];if(!o||o==="--help"||o==="-h"){console.log(`
542
+ ${h("shell")} \u2014 run built-in shell commands
543
543
 
544
544
  subcommands:
545
545
  launch <appId> [waitMs] [--clear-state]
@@ -554,15 +554,15 @@ ${s}
554
554
  shake trigger the simulator shake gesture
555
555
 
556
556
  examples:
557
- ${b("shell")} launch photos
558
- ${b("shell")} launch rn --clear-state
559
- ${b("shell")} launch photos 1500
560
- ${b("shell")} home 500
561
- ${b("shell")} switcher 800
562
- ${b("shell")} open-card clock 800
563
- ${b("shell")} appearance dark
564
- ${b("shell")} lock
565
- `);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?i[3]:i[2],r=s?Number(s):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(k("shell",o==="launch"||o==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let a=!1,d=!1,p=null,h=e.includes("--clear-state");if(o==="launch"){let f=i[2];f||(console.error(k("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),h&&await u.send({type:"evaluate",code:Qe(!0)}),a=!!await fe(u,"launchApp",r,f),{settled:d,state:p}=await Ie(u,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),a&&await L("inspect shell launch",h?{launchApp:{clearState:!0}}:{launchApp:{}},h?"launch app (clear state)":"launch app")}else if(o==="home")a=!!await fe(u,"goHome",r),{settled:d,state:p}=await Ie(u,Math.round(r),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(o==="switcher")a=!!await fe(u,"openSwitcher",r),{settled:d,state:p}=await Ie(u,Math.round(r),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),d&&(await ee(Ko),p=await ce(u));else if(o==="open-card"){let f=i[2];f||(console.error(k("shell","open-card <appId> [settleMs]")),process.exit(1)),a=!!await fe(u,"openSwitcherCard",r,f),{settled:d,state:p}=await Ie(u,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),a&&await L("inspect shell open-card",{openSwitcherCard:{appId:f}},`open switcher card ${f}`)}else if(o==="appearance"){let f=i[2];(!f||!["light","dark","auto","toggle"].includes(f))&&(console.error(k("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await so(u,"appearance",f);if(a=!!w?.ok,p={appearance:w},a){let O=w?.applied??f;console.log(` appearance: ${O}`)}}else if(o==="lock"||o==="shake"){let f=await so(u,o);a=!!f?.ok,p={[o]:f}}else console.error(` unknown shell subcommand: ${o}`),process.exit(1);console.log(JSON.stringify({ok:a,settled:d,state:p},null,2));break}case"url":{await Kt(u,{args:c});break}case"reload":{let s=!1,r=!1;try{await u.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await u.send({type:"evaluate",code:`;(() => {
557
+ ${h("shell")} launch photos
558
+ ${h("shell")} launch rn --clear-state
559
+ ${h("shell")} launch photos 1500
560
+ ${h("shell")} home 500
561
+ ${h("shell")} switcher 800
562
+ ${h("shell")} open-card clock 800
563
+ ${h("shell")} appearance dark
564
+ ${h("shell")} lock
565
+ `);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?a[3]:a[2],n=s?Number(s):350;t&&(!Number.isFinite(n)||n<0)&&(console.error(k("shell",o==="launch"||o==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let i=!1,u=!1,m=null,b=e.includes("--clear-state");if(o==="launch"){let f=a[2];f||(console.error(k("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),b&&await d.send({type:"evaluate",code:Ee(!0)}),i=!!await ge(d,"launchApp",n,f),{settled:u,state:m}=await Ne(d,Math.round(n),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),i&&await L("inspect shell launch",b?{launchApp:{clearState:!0}}:{launchApp:{}},b?"launch app (clear state)":"launch app")}else if(o==="home")i=!!await ge(d,"goHome",n),{settled:u,state:m}=await Ne(d,Math.round(n),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(o==="switcher")i=!!await ge(d,"openSwitcher",n),{settled:u,state:m}=await Ne(d,Math.round(n),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),u&&(await ee(Ko),m=await ce(d));else if(o==="open-card"){let f=a[2];f||(console.error(k("shell","open-card <appId> [settleMs]")),process.exit(1)),i=!!await ge(d,"openSwitcherCard",n,f),{settled:u,state:m}=await Ne(d,Math.round(n),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),i&&await L("inspect shell open-card",{openSwitcherCard:{appId:f}},`open switcher card ${f}`)}else if(o==="appearance"){let f=a[2];(!f||!["light","dark","auto","toggle"].includes(f))&&(console.error(k("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await no(d,"appearance",f);if(i=!!w?.ok,m={appearance:w},i){let O=w?.applied??f;console.log(` appearance: ${O}`)}}else if(o==="lock"||o==="shake"){let f=await no(d,o);i=!!f?.ok,m={[o]:f}}else console.error(` unknown shell subcommand: ${o}`),process.exit(1);console.log(JSON.stringify({ok:i,settled:u,state:m},null,2));break}case"url":{await Kt(d,{args:c});break}case"reload":{let s=!1,n=!1;try{await d.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let m=await d.send({type:"evaluate",code:`;(() => {
566
566
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
567
567
  if (typeof reloadExternalApp === 'function') {
568
568
  reloadExternalApp()
@@ -570,10 +570,13 @@ ${s}
570
570
  }
571
571
  window.location.reload()
572
572
  return { kind: 'page' }
573
- })()`});r=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let a=u,d=null;if(r)d=await De(u,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await ee(300);let p=await $t(_,j,I,{timeoutMs:1e4,simIdSource:E});p?(a=p,d=await De(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),a=null)}if(d)if(d.ready){let p=d.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${d.elapsedMs}ms: ${d.nodes} nodes${p}`)}else if(d.source==="error-bail")console.log(` \u26A0 reload bailed after ${d.elapsedMs}ms: ${d.errors} console error(s), ready signal never fired`);else{let p=Jo(d);console.log(` \u26A0 reload timed out after ${d.elapsedMs}ms \u2014 ${p} (nodes: ${d.nodes}, targets: ${d.targets}, errors: ${d.errors})`)}if(a)try{let p=await $e(a,10);if(a!==u&&a.close(),Array.isArray(p)&&p.length>0){console.log(`
574
- \u26A0 ${p.length} error(s) during mount:
575
- `);for(let h of p){let f=h.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),h.stack){let w=h.stack.split(`
576
- `).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}d&&!d.ready&&(process.exitCode=1);break}case"eval":case"js":{let o=i.slice(1).join(" ");o||(console.error(k("js","<javascript>")),console.error(""),console.error(" runs the snippet in the engine realm. SootSim is the"),console.error(" canonical state surface \u2014 reach into it directly."),console.error(""),console.error(" examples:"),console.error(` ${b("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${b("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${b("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${b("js")} SootSim.state.root.children.length`),process.exit(1));let t=o;t.startsWith("(async")||(t=`(async () => ${t})()`);let s=await u.send({type:"evaluate",code:t});console.log(JSON.stringify(s,null,2));let r=o.toLowerCase(),a=[];(r.includes("sootsim:gohome")||r.includes("gohome"))&&a.push("sootsim shell home"),(r.includes("sootsim:appswitcher")||r.includes("appswitcher"))&&a.push("sootsim shell switcher"),(r.includes("keyboard.isvisible")||r.includes("keyboard.getmode"))&&a.push("sootsim debug state keyboard"),r.includes("interact.tap")&&a.push("sootsim do tap <x> <y>"),r.includes("keyboard.type")&&a.push("sootsim do type <text>"),(r.includes("keyboard.press")||r.includes("keyboard.dispatchkey"))&&a.push("sootsim do key <name>"),r.includes("keyboard.dismiss")&&a.push("sootsim do dismiss"),r.includes("dumptree")&&a.push("sootsim get tree"),r.includes("dumpaccessibilitytree")&&a.push("sootsim get a11y"),r.includes("getnodecount")&&a.push("sootsim get count"),r.includes("findbytext")&&a.push("sootsim find <text>"),(r.includes("findbytestid")||r.includes("findbyid"))&&a.push("sootsim find --testid <id>"),r.includes("document.hidden")&&a.push("sootsim debug state keyboard (includes tab health)"),a.length>0&&Y("prefer-cli-over-eval",a);break}case"globals":{let o=await u.send({type:"evaluate",code:`(async () => {
573
+ })()`});n=!!m&&m.kind==="external-app",s=!0}catch{}console.log(" reloading...");let i=d,u=null;if(n)u=await ve(d,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await ee(300);let m=await $t(_,j,I,{timeoutMs:1e4,simIdSource:P});m?(i=m,u=await ve(m,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),i=null)}if(u)if(u.ready){let m=u.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${u.elapsedMs}ms: ${u.nodes} nodes${m}`)}else if(u.source==="error-bail")console.log(` \u26A0 reload bailed after ${u.elapsedMs}ms: ${u.errors} console error(s), ready signal never fired`);else{let m=Zt(u);console.log(` \u26A0 reload timed out after ${u.elapsedMs}ms \u2014 ${m} (nodes: ${u.nodes}, targets: ${u.targets}, errors: ${u.errors})`)}if(i)try{let m=await fe(i,10);if(i!==d&&i.close(),Array.isArray(m)&&m.length>0){console.log(`
574
+ \u26A0 ${m.length} error(s) during mount:
575
+ `);for(let b of m){let f=b.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),b.stack){let w=b.stack.split(`
576
+ `).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}u&&!u.ready&&(process.exitCode=1);break}case"storage-clear":{if(await Ce(d),await d.send({type:"evaluate",code:Ee(!0)})!==!0){A(c)?E({cleared:!1,ready:!1,error:"external app reload bridge is unavailable"}):console.error(" storage clear failed: external app reload bridge is unavailable"),process.exitCode=1;break}let n=await ve(d,{timeoutMs:1e4,errorGraceMs:3e3});if(A(c)){E({cleared:!0,ready:n.ready,reload:n}),n.ready||(process.exitCode=1);break}if(n.ready){let i=n.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` cleared tenant storage; ready in ${n.elapsedMs}ms: ${n.nodes} nodes${i}`)}else if(n.source==="error-bail")console.log(` \u26A0 storage clear reloaded but bailed after ${n.elapsedMs}ms: ${n.errors} console error(s), ready signal never fired`);else{let i=Zt(n);console.log(` \u26A0 storage clear reloaded but timed out after ${n.elapsedMs}ms \u2014 ${i} (nodes: ${n.nodes}, targets: ${n.targets}, errors: ${n.errors})`)}try{let i=await fe(d,10);if(Array.isArray(i)&&i.length>0){console.log(`
577
+ \u26A0 ${i.length} error(s) during mount:
578
+ `);for(let u of i){let m=u.args.map(b=>typeof b=="object"?JSON.stringify(b):b).join(" ");if(console.log(` ${m}`),u.stack){let b=u.stack.split(`
579
+ `).slice(0,2);for(let f of b)console.log(` ${f.trim()}`)}}}}catch{}n.ready||(process.exitCode=1);break}case"eval":case"js":{let o=a.slice(1).join(" ");o||(console.error(k("js","<javascript>")),console.error(""),console.error(" runs the snippet in the engine realm. SootSim is the"),console.error(" canonical state surface \u2014 reach into it directly."),console.error(""),console.error(" examples:"),console.error(` ${h("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${h("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${h("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${h("js")} SootSim.state.root.children.length`),process.exit(1));let t=o;t.startsWith("(async")||(t=`(async () => ${t})()`);let s=await d.send({type:"evaluate",code:t});console.log(JSON.stringify(s,null,2));let n=o.toLowerCase(),i=[];(n.includes("sootsim:gohome")||n.includes("gohome"))&&i.push("sootsim shell home"),(n.includes("sootsim:appswitcher")||n.includes("appswitcher"))&&i.push("sootsim shell switcher"),(n.includes("keyboard.isvisible")||n.includes("keyboard.getmode"))&&i.push("sootsim debug state keyboard"),n.includes("interact.tap")&&i.push("sootsim do tap <x> <y>"),n.includes("keyboard.type")&&i.push("sootsim do type <text>"),(n.includes("keyboard.press")||n.includes("keyboard.dispatchkey"))&&i.push("sootsim do key <name>"),n.includes("keyboard.dismiss")&&i.push("sootsim do dismiss"),n.includes("dumptree")&&i.push("sootsim get tree"),n.includes("dumpaccessibilitytree")&&i.push("sootsim get a11y"),n.includes("getnodecount")&&i.push("sootsim get count"),n.includes("findbytext")&&i.push("sootsim find <text>"),(n.includes("findbytestid")||n.includes("findbyid"))&&i.push("sootsim find --testid <id>"),n.includes("document.hidden")&&i.push("sootsim debug state keyboard (includes tab health)"),i.length>0&&Y("prefer-cli-over-eval",i);break}case"globals":{let o=await d.send({type:"evaluate",code:`(async () => {
577
580
  const globals = {}
578
581
 
579
582
  // test bridge (proxy in worker mode)
@@ -611,8 +614,8 @@ ${s}
611
614
 
612
615
  return globals
613
616
  })()`});console.log(` sootsim JS API:
614
- `);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let r of s)console.log(` .${r}`);console.log("")}console.log(` use: ${b("js")} <expression>`),console.log(` example: ${b("js")} test.findByText("Sign in")`);break}case"describe":{await Rt({bridge:u,args:e,positional:i});break}case"perf":{let o=i[1];if(!o||o==="--help"||o==="-h"){console.log(`
615
- ${b("perf")} \u2014 performance profiling
617
+ `);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let n of s)console.log(` .${n}`);console.log("")}console.log(` use: ${h("js")} <expression>`),console.log(` example: ${h("js")} test.findByText("Sign in")`);break}case"describe":{await Rt({bridge:d,args:e,positional:a});break}case"perf":{let o=a[1];if(!o||o==="--help"||o==="-h"){console.log(`
618
+ ${h("perf")} \u2014 performance profiling
616
619
 
617
620
  subcommands:
618
621
  stats one-shot stats (zero overhead query)
@@ -626,13 +629,13 @@ ${s}
626
629
  --json for a machine-readable payload on stdout.
627
630
 
628
631
  examples:
629
- ${b("perf")} stats
630
- ${b("perf")} start
632
+ ${h("perf")} stats
633
+ ${h("perf")} start
631
634
  # ... interact with the app ...
632
- ${b("perf")} stop
633
- ${b("perf")} stop --json
634
- ${b("perf")} transition goHome
635
- `);break}switch(o){case"stats":{let t=await u.send({type:"evaluate",code:`(async () => {
635
+ ${h("perf")} stop
636
+ ${h("perf")} stop --json
637
+ ${h("perf")} transition goHome
638
+ `);break}switch(o){case"stats":{let t=await d.send({type:"evaluate",code:`(async () => {
636
639
  // worker mode (host exposes these)
637
640
  if (window.__sootsimPerfStats) {
638
641
  return await window.__sootsimPerfStats()
@@ -657,13 +660,13 @@ ${s}
657
660
  jankFrames: frameStats.recentFrames?.filter(f => f > 16.67).length || 0,
658
661
  recentCount: frameStats.recentFrames?.length || 0,
659
662
  }
660
- })()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){P(t);break}let s=t.avgMs==="?"&&t.maxMs==="?",r=t.avgMs!=="?"?(1e3/parseFloat(t.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${t.frames}`),console.log(` avg: ${t.avgMs}ms (${r} fps)`),console.log(` max: ${t.maxMs}ms`),console.log(` layout: ${t.layoutMs}ms total`),console.log(` nodes: ${t.nodeCount}`),t.recentCount>0&&console.log(` jank: ${t.jankFrames}/${t.recentCount} frames >16.67ms`),s&&process.stderr.write(`
663
+ })()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){E(t);break}let s=t.avgMs==="?"&&t.maxMs==="?",n=t.avgMs!=="?"?(1e3/parseFloat(t.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${t.frames}`),console.log(` avg: ${t.avgMs}ms (${n} fps)`),console.log(` max: ${t.maxMs}ms`),console.log(` layout: ${t.layoutMs}ms total`),console.log(` nodes: ${t.nodeCount}`),t.recentCount>0&&console.log(` jank: ${t.jankFrames}/${t.recentCount} frames >16.67ms`),s&&process.stderr.write(`
661
664
  \u26A0 frame timings are zero \u2014 enable them first:
662
665
  sootsim debug perf start # begin recording
663
666
  # \u2026 interact / run a flow / wait for the transition \u2026
664
667
  sootsim debug perf stop # full report
665
668
  sootsim debug perf stats # one-shot snapshot
666
- `);break}case"start":{await u.send({type:"evaluate",code:`(async () => {
669
+ `);break}case"start":{await d.send({type:"evaluate",code:`(async () => {
667
670
  // worker mode
668
671
  if (window.__sootsimPerfStart && window.__sootsimRenderHost) {
669
672
  const result = window.__sootsimPerfStart()
@@ -685,7 +688,7 @@ ${s}
685
688
  startedAt: performance.now(),
686
689
  }
687
690
  return { started: true }
688
- })()`}),console.log(` profiling started \u2014 interact with the app, then run '${b("perf")} stop'`);break}case"stop":{let t=await u.send({type:"evaluate",code:`(async () => {
691
+ })()`}),console.log(` profiling started \u2014 interact with the app, then run '${h("perf")} stop'`);break}case"stop":{let t=await d.send({type:"evaluate",code:`(async () => {
689
692
  // worker mode
690
693
  if (window.__sootsimRenderHost) {
691
694
  const session = window.${ne} || {}
@@ -779,8 +782,8 @@ ${s}
779
782
  jankFrames: recent.filter(f => f > 16.67).length,
780
783
  sampleCount: recent.length,
781
784
  }
782
- })()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){P(t);break}let s=t.avgMs>0?(1e3/t.avgMs).toFixed(1):"?",r=t.sampleCount>0?(t.jankFrames/t.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
783
- `),console.log(` frames: ${t.frames}`),console.log(` total: ${t.totalMs.toFixed(1)}ms`),console.log(` avg: ${t.avgMs.toFixed(2)}ms (${s} fps)`),console.log(` max: ${t.maxMs.toFixed(2)}ms`),console.log(""),t.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${t.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${t.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${t.copyAvgMs.toFixed(2)}ms`),t.auxAvgMs!==void 0&&console.log(` aux: ${t.auxAvgMs.toFixed(2)}ms`),t.otherAvgMs!==void 0&&console.log(` other: ${t.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${t.sampleCount} samples):`),console.log(` p50: ${t.p50.toFixed(2)}ms`),console.log(` p95: ${t.p95.toFixed(2)}ms`),console.log(` p99: ${t.p99.toFixed(2)}ms`),console.log(` jank: ${t.jankFrames} frames (${r}%) >16.67ms`);break}case"frames":{let t=i[2]?Number(i[2]):50;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${i[2]}"`),process.exit(1));let s=await u.send({type:"evaluate",code:`(async () => {
785
+ })()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){E(t);break}let s=t.avgMs>0?(1e3/t.avgMs).toFixed(1):"?",n=t.sampleCount>0?(t.jankFrames/t.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
786
+ `),console.log(` frames: ${t.frames}`),console.log(` total: ${t.totalMs.toFixed(1)}ms`),console.log(` avg: ${t.avgMs.toFixed(2)}ms (${s} fps)`),console.log(` max: ${t.maxMs.toFixed(2)}ms`),console.log(""),t.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${t.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${t.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${t.copyAvgMs.toFixed(2)}ms`),t.auxAvgMs!==void 0&&console.log(` aux: ${t.auxAvgMs.toFixed(2)}ms`),t.otherAvgMs!==void 0&&console.log(` other: ${t.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${t.sampleCount} samples):`),console.log(` p50: ${t.p50.toFixed(2)}ms`),console.log(` p95: ${t.p95.toFixed(2)}ms`),console.log(` p99: ${t.p99.toFixed(2)}ms`),console.log(` jank: ${t.jankFrames} frames (${n}%) >16.67ms`);break}case"frames":{let t=a[2]?Number(a[2]):50;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await d.send({type:"evaluate",code:`(async () => {
784
787
  if (window.__sootsimRenderHost) {
785
788
  const session = window.${ne} || {}
786
789
  if (session.active) {
@@ -815,7 +818,7 @@ ${s}
815
818
  mode: 'main-thread',
816
819
  frames: (stats.recentFrames || []).slice(-${t}),
817
820
  }
818
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){P(s);break}if(s.mode==="render-worker"){let a=Array.isArray(s.samples)?s.samples:[];if(a.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` last ${a.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,h,f,w,O,q]of a)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(d).padStart(5)}`);console.log(""),We(a.map(d=>d[1])),s.live&&console.log(" sampling continues");break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(a=>a.toFixed(2)).join(", ")}`),We(r);break}case"worst":{let t=i[2]?Number(i[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${i[2]}"`),process.exit(1));let s=await u.send({type:"evaluate",code:`(async () => {
821
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){E(s);break}if(s.mode==="render-worker"){let i=Array.isArray(s.samples)?s.samples:[];if(i.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${i.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,b,f,w,O,q]of i)console.log(` ${m.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);console.log(""),He(i.map(u=>u[1])),s.live&&console.log(" sampling continues");break}let n=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(n.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${n.length} frame times (ms):`),console.log(` ${n.map(i=>i.toFixed(2)).join(", ")}`),He(n);break}case"worst":{let t=a[2]?Number(a[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await d.send({type:"evaluate",code:`(async () => {
819
822
  if (window.__sootsimRenderHost) {
820
823
  const session = window.${ne} || {}
821
824
  if (session.active) {
@@ -857,8 +860,8 @@ ${s}
857
860
  mode: 'main-thread',
858
861
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${t}),
859
862
  }
860
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){P(s);break}if(s.mode==="render-worker"){let a=Array.isArray(s.samples)?s.samples:[];if(a.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${a.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,h,f,w,O,q]of a)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(d).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(a=>a.toFixed(2)).join(", ")}`);break}case"transition":{let t=i[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
861
- ${b("perf")} transition <event> \u2014 profile a shell transition
863
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){E(s);break}if(s.mode==="render-worker"){let i=Array.isArray(s.samples)?s.samples:[];if(i.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${i.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,b,f,w,O,q]of i)console.log(` ${m.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let n=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(n.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${n.length} frame times (ms):`),console.log(` ${n.map(i=>i.toFixed(2)).join(", ")}`);break}case"transition":{let t=a[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
864
+ ${h("perf")} transition <event> \u2014 profile a shell transition
862
865
 
863
866
  events:
864
867
  goHome swipe-to-home animation
@@ -868,9 +871,9 @@ ${s}
868
871
  note: uses 600ms capture window \u2014 may need --timeout 10000 flag
869
872
 
870
873
  examples:
871
- ${b("perf")} transition goHome --timeout 10000
872
- ${b("perf")} transition appSwitcher
873
- `);break}let r=`sootsim:${t}`;Re(` profiling ${t} transition...`),Re(" (use --timeout 10000 if this times out)");let a=await u.send({type:"evaluate",code:`(async () => {
874
+ ${h("perf")} transition goHome --timeout 10000
875
+ ${h("perf")} transition appSwitcher
876
+ `);break}let n=`sootsim:${t}`;Be(` profiling ${t} transition...`),Be(" (use --timeout 10000 if this times out)");let i=await d.send({type:"evaluate",code:`(async () => {
874
877
  // only supported in render-worker mode
875
878
  if (!window.__sootsimRenderHost) {
876
879
  return { error: 'transition profiling requires render-worker mode' }
@@ -883,7 +886,7 @@ ${s}
883
886
  await new Promise(r => requestAnimationFrame(() => r(undefined)))
884
887
 
885
888
  // dispatch the shell event
886
- window.dispatchEvent(new Event('${r}'))
889
+ window.dispatchEvent(new Event('${n}'))
887
890
 
888
891
  // wait 600ms for transition to complete (shell animations are ~300-500ms)
889
892
  // using fixed timing avoids complex animation-end detection
@@ -929,47 +932,47 @@ ${s}
929
932
  jankFrames: frameTimes.filter(f => f > 16.67).length,
930
933
  samples,
931
934
  }
932
- })()`});if(a.error&&(console.error(` error: ${a.error}`),process.exit(1)),A(c)){P(a);break}if(a.warning&&console.log(` warning: ${a.warning}`),a.frames===0){console.log(" no frames captured");break}let d=a.avgMs>0?(1e3/a.avgMs).toFixed(1):"?",p=a.frames>0?(a.jankFrames/a.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
935
+ })()`});if(i.error&&(console.error(` error: ${i.error}`),process.exit(1)),A(c)){E(i);break}if(i.warning&&console.log(` warning: ${i.warning}`),i.frames===0){console.log(" no frames captured");break}let u=i.avgMs>0?(1e3/i.avgMs).toFixed(1):"?",m=i.frames>0?(i.jankFrames/i.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
933
936
 
934
- frames: ${a.frames}
935
- total: ${a.totalMs.toFixed(1)}ms
936
- avg: ${a.avgMs.toFixed(2)}ms (${d} fps)
937
- max: ${a.maxMs.toFixed(2)}ms
937
+ frames: ${i.frames}
938
+ total: ${i.totalMs.toFixed(1)}ms
939
+ avg: ${i.avgMs.toFixed(2)}ms (${u} fps)
940
+ max: ${i.maxMs.toFixed(2)}ms
938
941
 
939
942
  breakdown (avg per frame):
940
- layout: ${a.layoutAvgMs?.toFixed(2)||"?"}ms
941
- render: ${a.renderAvgMs?.toFixed(2)||"?"}ms
942
- copy: ${a.copyAvgMs?.toFixed(2)||"?"}ms
943
- aux: ${a.auxAvgMs?.toFixed(2)||"?"}ms
944
- other: ${a.otherAvgMs?.toFixed(2)||"?"}ms
945
-
946
- distribution (${a.frames} samples):
947
- p50: ${a.p50.toFixed(2)}ms
948
- p95: ${a.p95.toFixed(2)}ms
949
- p99: ${a.p99.toFixed(2)}ms
950
- jank: ${a.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(a.samples)&&a.samples.length>0&&(console.log(""),We(a.samples.map(h=>h[1])));break}default:console.error(` unknown perf subcommand: ${o}`),console.error(" valid: stats, start, stop, frames, worst, transition"),/^--?reset$/.test(o)&&console.error(" note: 'perf start' already clears prior frames \u2014 no reset needed"),process.exit(1)}break}case"errors":{let o=i[1];if(o==="clear"){await dt(u),A(c)?P({cleared:!0}):console.log(" error buffer cleared");break}let t=o?Number(o):20,s=await $e(u,t);if(A(c)){P(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
951
- `);for(let r of s){let a=ie(r.timestamp),d=r.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");if(console.log(` [${a}] ${d}`),r.stack){let p=r.stack.split(`
952
- `).slice(0,3);for(let h of p)console.log(` ${h.trim()}`)}}break}case"warnings":{let o=i[1]?Number(i[1]):20,t=await ut(u,o);if(A(c)){P(t);break}if(t.length===0){console.log(" no warnings captured");break}console.log(` ${t.length} warning(s):
953
- `);for(let s of t){let r=ie(s.timestamp),a=s.args.map(d=>typeof d=="object"?JSON.stringify(d):d).join(" ");console.log(` [${r}] ${a}`)}break}case"animations":{let o=await G(u,"listAnimations")??[];if(e.includes("--json")){console.log(JSON.stringify(o,null,2));break}if(o.length===0){console.log(" no active animations");break}console.log(` ${o.length} active animation(s):
954
- `);for(let t of o){let s=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,a=Number(t.current??0).toFixed(2),d=`${Math.round((t.progress??0)*100)}%`,p=`${Math.round(t.elapsedMs??0)}ms`,h=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${r.padEnd(14)} cur=${a.padEnd(7)} ${d.padStart(4)} ${p}${h}${f}`)}break}case"animation":{let o=i[1];(!o||o==="--help"||o==="-h")&&(console.error(` usage: ${b("animation")} <id>`),process.exit(1));let t=Number(o);Number.isFinite(t)||(console.error(` invalid id: ${o}`),process.exit(1));let s=await G(u,"getAnimation",t);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let o=i[1];(!o||o==="--help"||o==="-h")&&(console.error(` usage: ${b("stop-animation")} <id|all>`),process.exit(1));let t=o==="all"?"all":Number(o);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${o}`),process.exit(1));let s=await G(u,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let o=i[1];if(o==="clear"){await pt(u),A(c)?P({cleared:!0}):console.log(" request buffer cleared");break}let t=o==="all",s=t?i[2]:o,r=s?Number(s):20,a=await mt(u,{failed:!t,limit:r});if(A(c)){P(a);break}if(a.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${a.length} ${t?"request(s)":"failed request(s)"}:
955
- `);for(let d of a){let p=ie(d.timestamp);console.log(` [${p}] ${oe(d)}`),d.responseBody?console.log(` ${d.responseBody}`):d.error&&console.log(` ${d.error}`)}break}case"network":{let o=i[1],t=null,s=null,r=!1,a=!1,d=1e3,p=!1,h=!1;for(let F=0;F<c.length;F++){let x=c[F];if(x==="--filter")t=c[F+1]??null,F++;else if(x==="--limit"){let $=Number(c[F+1]);Number.isFinite($)&&(s=$),F++}else if(x==="--threshold"){let $=Number(c[F+1]);Number.isFinite($)&&$>0&&(d=$),F++}else x==="--failed"?r=!0:x==="--slow"?a=!0:x==="--tail"||x==="-f"?p=!0:x==="--json"&&(h=!0)}if(o==="clear"){await u.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(o==="get"){let F=i[2];F||(console.error(" usage: sootsim network get <id>"),process.exit(1));let x=await u.send({type:"evaluate",code:`(() => {
943
+ layout: ${i.layoutAvgMs?.toFixed(2)||"?"}ms
944
+ render: ${i.renderAvgMs?.toFixed(2)||"?"}ms
945
+ copy: ${i.copyAvgMs?.toFixed(2)||"?"}ms
946
+ aux: ${i.auxAvgMs?.toFixed(2)||"?"}ms
947
+ other: ${i.otherAvgMs?.toFixed(2)||"?"}ms
948
+
949
+ distribution (${i.frames} samples):
950
+ p50: ${i.p50.toFixed(2)}ms
951
+ p95: ${i.p95.toFixed(2)}ms
952
+ p99: ${i.p99.toFixed(2)}ms
953
+ jank: ${i.jankFrames} frames (${m}%) >16.67ms`),Array.isArray(i.samples)&&i.samples.length>0&&(console.log(""),He(i.samples.map(b=>b[1])));break}default:console.error(` unknown perf subcommand: ${o}`),console.error(" valid: stats, start, stop, frames, worst, transition"),/^--?reset$/.test(o)&&console.error(" note: 'perf start' already clears prior frames \u2014 no reset needed"),process.exit(1)}break}case"errors":{let o=a[1];if(o==="clear"){await Ce(d),A(c)?E({cleared:!0}):console.log(" error buffer cleared");break}let t=o?Number(o):20,s=await fe(d,t);if(A(c)){E(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
954
+ `);for(let n of s){let i=ie(n.timestamp),u=n.args.map(m=>typeof m=="object"?JSON.stringify(m):m).join(" ");if(console.log(` [${i}] ${u}`),n.stack){let m=n.stack.split(`
955
+ `).slice(0,3);for(let b of m)console.log(` ${b.trim()}`)}}break}case"warnings":{let o=a[1]?Number(a[1]):20,t=await ut(d,o);if(A(c)){E(t);break}if(t.length===0){console.log(" no warnings captured");break}console.log(` ${t.length} warning(s):
956
+ `);for(let s of t){let n=ie(s.timestamp),i=s.args.map(u=>typeof u=="object"?JSON.stringify(u):u).join(" ");console.log(` [${n}] ${i}`)}break}case"animations":{let o=await G(d,"listAnimations")??[];if(e.includes("--json")){console.log(JSON.stringify(o,null,2));break}if(o.length===0){console.log(" no active animations");break}console.log(` ${o.length} active animation(s):
957
+ `);for(let t of o){let s=String(t.kind).padEnd(6),n=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,i=Number(t.current??0).toFixed(2),u=`${Math.round((t.progress??0)*100)}%`,m=`${Math.round(t.elapsedMs??0)}ms`,b=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${n.padEnd(14)} cur=${i.padEnd(7)} ${u.padStart(4)} ${m}${b}${f}`)}break}case"animation":{let o=a[1];(!o||o==="--help"||o==="-h")&&(console.error(` usage: ${h("animation")} <id>`),process.exit(1));let t=Number(o);Number.isFinite(t)||(console.error(` invalid id: ${o}`),process.exit(1));let s=await G(d,"getAnimation",t);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let o=a[1];(!o||o==="--help"||o==="-h")&&(console.error(` usage: ${h("stop-animation")} <id|all>`),process.exit(1));let t=o==="all"?"all":Number(o);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${o}`),process.exit(1));let s=await G(d,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let o=a[1];if(o==="clear"){await pt(d),A(c)?E({cleared:!0}):console.log(" request buffer cleared");break}let t=o==="all",s=t?a[2]:o,n=s?Number(s):20,i=await mt(d,{failed:!t,limit:n});if(A(c)){E(i);break}if(i.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${i.length} ${t?"request(s)":"failed request(s)"}:
958
+ `);for(let u of i){let m=ie(u.timestamp);console.log(` [${m}] ${oe(u)}`),u.responseBody?console.log(` ${u.responseBody}`):u.error&&console.log(` ${u.error}`)}break}case"network":{let o=a[1],t=null,s=null,n=!1,i=!1,u=1e3,m=!1,b=!1;for(let F=0;F<c.length;F++){let x=c[F];if(x==="--filter")t=c[F+1]??null,F++;else if(x==="--limit"){let $=Number(c[F+1]);Number.isFinite($)&&(s=$),F++}else if(x==="--threshold"){let $=Number(c[F+1]);Number.isFinite($)&&$>0&&(u=$),F++}else x==="--failed"?n=!0:x==="--slow"?i=!0:x==="--tail"||x==="-f"?m=!0:x==="--json"&&(b=!0)}if(o==="clear"){await d.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(o==="get"){let F=a[2];F||(console.error(" usage: sootsim network get <id>"),process.exit(1));let x=await d.send({type:"evaluate",code:`(() => {
956
959
  const obs = window.__sootsimObservability;
957
960
  if (!obs) return null;
958
961
  return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(F)}) || null;
959
- })()`});x||(console.error(` no entry with id ${F}`),process.exit(1)),h?console.log(JSON.stringify(x,null,2)):Wo(x);break}let f=s??(p?200:o?Number(o):20);Number.isFinite(f)||(console.error(` invalid limit: ${o} \u2014 \`network\` takes a numeric count (e.g. ${b("network")} 100).
960
- to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let w=async()=>{let F=await u.send({type:"evaluate",code:`(() => {
962
+ })()`});x||(console.error(` no entry with id ${F}`),process.exit(1)),b?console.log(JSON.stringify(x,null,2)):Wo(x);break}let f=s??(m?200:o?Number(o):20);Number.isFinite(f)||(console.error(` invalid limit: ${o} \u2014 \`network\` takes a numeric count (e.g. ${h("network")} 100).
963
+ to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let w=async()=>{let F=await d.send({type:"evaluate",code:`(() => {
961
964
  const obs = window.__sootsimObservability;
962
965
  if (!obs) return { ok: false };
963
966
  return { ok: true, entries: obs.network.getSnapshot() };
964
- })()`});if(!F||!F.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return F.entries??[]},O=F=>{let x=F;if(r&&(x=x.filter($=>!!$.error||$.status!=null&&$.status>=400)),a&&(x=x.filter($=>$.durationMs!=null&&$.durationMs>=d)),t){let $=t.toLowerCase();x=x.filter(v=>(v.displayUrl||v.url).toLowerCase().includes($))}return a&&!p&&(x=[...x].sort(($,v)=>(v.durationMs??0)-($.durationMs??0))),x};if(!p){let F=await w(),x=O(F).slice(-f);if(h){console.log(JSON.stringify(x,null,2));break}if(x.length===0){F.length===0?console.log(" no network requests captured"):console.log(a?` no requests slower than ${d}ms (${F.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(a?` ${x.length} request(s) slower than ${d}ms (sorted by duration desc):
967
+ })()`});if(!F||!F.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return F.entries??[]},O=F=>{let x=F;if(n&&(x=x.filter($=>!!$.error||$.status!=null&&$.status>=400)),i&&(x=x.filter($=>$.durationMs!=null&&$.durationMs>=u)),t){let $=t.toLowerCase();x=x.filter(v=>(v.displayUrl||v.url).toLowerCase().includes($))}return i&&!m&&(x=[...x].sort(($,v)=>(v.durationMs??0)-($.durationMs??0))),x};if(!m){let F=await w(),x=O(F).slice(-f);if(b){console.log(JSON.stringify(x,null,2));break}if(x.length===0){F.length===0?console.log(" no network requests captured"):console.log(i?` no requests slower than ${u}ms (${F.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(i?` ${x.length} request(s) slower than ${u}ms (sorted by duration desc):
965
968
  `:` ${x.length} request(s):
966
- `);for(let $ of x)Zt($);break}console.log(` tailing network (ctrl-c to stop)...
967
- `);let q=new Set,H=!0,K=()=>{H=!1};process.on("SIGINT",K);try{for(;H;){let F=await w(),x=O(F);for(let $ of x)$.durationMs!=null&&(q.has($.id)||(q.add($.id),h?console.log(JSON.stringify($)):Zt($)));await ee(250)}}finally{process.off("SIGINT",K)}break}case"logs":{let o=i[1],t=null,s=null,r=null,a=!1,d=!1,p=!1;for(let x=0;x<c.length;x++){let $=c[x];if($==="--filter")t=c[x+1]??null,x++;else if($==="--limit"){let v=Number(c[x+1]);Number.isFinite(v)&&(s=v),x++}else $==="--level"?(r=c[x+1]??null,x++):$==="--tail"||$==="-f"?a=!0:$==="--json"?d=!0:($==="--internal"||$==="--all")&&(p=!0)}let h=r?new Set(r.split(",").map(x=>x.trim()).filter(x=>x==="log"||x==="info"||x==="warn"||x==="error"||x==="debug")):null;if(o==="clear"){await gt(u),console.log(" log buffer cleared");break}let f=!d&&process.stdout.isTTY===!0,w=s??(a?500:o?Number(o):50);Number.isFinite(w)||(console.error(` invalid limit: ${o} \u2014 \`logs\` takes a numeric count (e.g. ${b("logs")} 100).
968
- to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let O=()=>ft(u),q=x=>yt(x,{level:h,filter:t,showInternal:p});if(!a){let x=await O(),$=q(x).slice(-w);if(d){console.log(JSON.stringify($,null,2));break}if($.length===0){console.log(x.length===0?" no logs captured":" no matching logs");break}console.log(` ${$.length} log(s):
969
- `);for(let v of $)to(v,f);break}console.log(` tailing logs (ctrl-c to stop)...
970
- `);let H=new Set,K=!0,F=()=>{K=!1};process.on("SIGINT",F);try{for(;K;){let x=await O(),$=q(x);for(let v of $)H.has(v.id)||(H.add(v.id),d?console.log(JSON.stringify(v)):to(v,f));await ee(250)}}finally{process.off("SIGINT",F)}break}default:console.error(` unknown subcommand: ${g}`),process.exit(1)}if(pe.has(g)&&!e.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&!await Ze(u,g)&&await S(u),!B.has(g)&&!A(c))try{await re(u)}catch{}}catch(o){let t=o instanceof Error?o.message:String(o);console.error(` ${g??"inspect"} failed: ${t}`);let s=/^no sim connected with id (.+)$/.exec(t),r=/^command timed out after (\d+)s$/.exec(t),a=t.startsWith("sim disconnected:")||t.startsWith("bridge never reconnected")||t.startsWith("could not connect to ws://");if(s)await Mt(u,_,s[1]);else if(/^no sim connected$/.test(t))Tt(_);else if(r)if(await Do(u)){let p=g??"describe";process.stderr.write(` the sim is still responsive \u2014 '${p}' just exceeded the ${r[1]}s command budget.
969
+ `);for(let $ of x)eo($);break}console.log(` tailing network (ctrl-c to stop)...
970
+ `);let q=new Set,H=!0,K=()=>{H=!1};process.on("SIGINT",K);try{for(;H;){let F=await w(),x=O(F);for(let $ of x)$.durationMs!=null&&(q.has($.id)||(q.add($.id),b?console.log(JSON.stringify($)):eo($)));await ee(250)}}finally{process.off("SIGINT",K)}break}case"logs":{let o=a[1],t=null,s=null,n=null,i=!1,u=!1,m=!1;for(let x=0;x<c.length;x++){let $=c[x];if($==="--filter")t=c[x+1]??null,x++;else if($==="--limit"){let v=Number(c[x+1]);Number.isFinite(v)&&(s=v),x++}else $==="--level"?(n=c[x+1]??null,x++):$==="--tail"||$==="-f"?i=!0:$==="--json"?u=!0:($==="--internal"||$==="--all")&&(m=!0)}let b=n?new Set(n.split(",").map(x=>x.trim()).filter(x=>x==="log"||x==="info"||x==="warn"||x==="error"||x==="debug")):null;if(o==="clear"){await gt(d),console.log(" log buffer cleared");break}let f=!u&&process.stdout.isTTY===!0,w=s??(i?500:o?Number(o):50);Number.isFinite(w)||(console.error(` invalid limit: ${o} \u2014 \`logs\` takes a numeric count (e.g. ${h("logs")} 100).
971
+ to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let O=()=>ft(d),q=x=>yt(x,{level:b,filter:t,showInternal:m});if(!i){let x=await O(),$=q(x).slice(-w);if(u){console.log(JSON.stringify($,null,2));break}if($.length===0){console.log(x.length===0?" no logs captured":" no matching logs");break}console.log(` ${$.length} log(s):
972
+ `);for(let v of $)oo(v,f);break}console.log(` tailing logs (ctrl-c to stop)...
973
+ `);let H=new Set,K=!0,F=()=>{K=!1};process.on("SIGINT",F);try{for(;K;){let x=await O(),$=q(x);for(let v of $)H.has(v.id)||(H.add(v.id),u?console.log(JSON.stringify(v)):oo(v,f));await ee(250)}}finally{process.off("SIGINT",F)}break}default:console.error(` unknown subcommand: ${g}`),process.exit(1)}if(pe.has(g)&&!e.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&!await et(d,g)&&await S(d),!B.has(g)&&!A(c))try{await re(d)}catch{}}catch(o){let t=o instanceof Error?o.message:String(o);console.error(` ${g??"inspect"} failed: ${t}`);let s=/^no sim connected with id (.+)$/.exec(t),n=/^command timed out after (\d+)s$/.exec(t),i=t.startsWith("sim disconnected:")||t.startsWith("bridge never reconnected")||t.startsWith("could not connect to ws://");if(s)await Mt(d,_,s[1]);else if(/^no sim connected$/.test(t))Tt(_);else if(n)if(await Co(d)){let m=g??"describe";process.stderr.write(` the sim is still responsive \u2014 '${m}' just exceeded the ${n[1]}s command budget.
971
974
  the screen's node tree is large; narrow the query or raise the budget:
972
- sootsim ${p} --testid <id> # scope to one subtree
975
+ sootsim ${m} --testid <id> # scope to one subtree
973
976
  sootsim find --testid <id> # targeted single-node lookup
974
- sootsim ${p} --timeout 60000 # raise per-command budget (ms)
975
- `)}else Qt();else if(a)Qt();else{try{await St(u)}catch{}try{await V({includeTail:!0})}catch{}try{await W({includeTail:!0})}catch{}}process.exit(1)}finally{u.close()}}export{Jn as runInspect};
977
+ sootsim ${m} --timeout 60000 # raise per-command budget (ms)
978
+ `)}else Qt();else if(i)Qt();else{try{await St(d)}catch{}try{await V({includeTail:!0})}catch{}try{await W({includeTail:!0})}catch{}}process.exit(1)}finally{d.close()}}export{Jn as runInspect};