sootsim 0.1.184 → 0.1.185

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 (148) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-KSX5D27X.js → agent-VF756RZU.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-MS6TJF5Y.js → agent-wrapper-IAFL7ROV.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-HHN6X2VJ.js → app-fonts-VWLEC7ZA.js} +2 -2
  5. package/dist-cli/chunks/{assert-XHVSQZOE.js → assert-I55QVGG7.js} +2 -2
  6. package/dist-cli/chunks/beta-X6YPQVZH.js +2 -0
  7. package/dist-cli/chunks/{camera-7L7D4XUO.js → camera-CYYBJH7W.js} +2 -2
  8. package/dist-cli/chunks/{chunk-C3WRMMUM.js → chunk-2T73IGB2.js} +2 -2
  9. package/dist-cli/chunks/{chunk-AKQWG57K.js → chunk-4NUQVW5P.js} +17 -4
  10. package/dist-cli/chunks/{chunk-IG7F7DTQ.js → chunk-4OUQAR34.js} +1 -1
  11. package/dist-cli/chunks/{chunk-7C6RC3BU.js → chunk-7OAUPGLN.js} +2 -2
  12. package/dist-cli/chunks/{chunk-NBF2SXAH.js → chunk-ARNLQPMQ.js} +2 -2
  13. package/dist-cli/chunks/{chunk-53KKDNCU.js → chunk-BI56RR3G.js} +1 -1
  14. package/dist-cli/chunks/{chunk-JFCJIRX6.js → chunk-BMCBPMTC.js} +1 -1
  15. package/dist-cli/chunks/{chunk-XSWATK6S.js → chunk-C3UEINOZ.js} +2 -2
  16. package/dist-cli/chunks/{chunk-YQNX7JK6.js → chunk-C63EVPDN.js} +2 -2
  17. package/dist-cli/chunks/{chunk-U636Z2JZ.js → chunk-CYBRFHPU.js} +2 -2
  18. package/dist-cli/chunks/{chunk-3KK3YZQ3.js → chunk-DZLBZGHN.js} +2 -2
  19. package/dist-cli/chunks/{chunk-V36X7TNR.js → chunk-E5DE33BU.js} +1 -1
  20. package/dist-cli/chunks/{chunk-S5XWFD5C.js → chunk-EXFB33AZ.js} +2 -2
  21. package/dist-cli/chunks/{chunk-7DKGX746.js → chunk-FHJTTB3W.js} +2 -2
  22. package/dist-cli/chunks/{chunk-OGLOOKK6.js → chunk-FUHXL6BW.js} +1 -1
  23. package/dist-cli/chunks/{chunk-7DHLNDOA.js → chunk-FY6DJGOS.js} +1 -1
  24. package/dist-cli/chunks/{chunk-IHH3JCV5.js → chunk-GX6MKIFC.js} +1 -1
  25. package/dist-cli/chunks/{chunk-IZMNFZXZ.js → chunk-HQG4DRQ3.js} +1 -1
  26. package/dist-cli/chunks/chunk-IGJHME3T.js +1 -0
  27. package/dist-cli/chunks/{chunk-ID25RWPE.js → chunk-IJP257WP.js} +1 -1
  28. package/dist-cli/chunks/chunk-JRL7PFNZ.js +463 -0
  29. package/dist-cli/chunks/{chunk-YYS2ITHH.js → chunk-K2THZIVC.js} +1 -1
  30. package/dist-cli/chunks/chunk-KOKIECMB.js +118 -0
  31. package/dist-cli/chunks/{chunk-3S5BOWO5.js → chunk-LI4RLX6B.js} +1 -1
  32. package/dist-cli/chunks/{chunk-N5LA5G7V.js → chunk-LJ3SOZBF.js} +2 -2
  33. package/dist-cli/chunks/{chunk-QZW44BMW.js → chunk-M3P67TBN.js} +1 -1
  34. package/dist-cli/chunks/{chunk-Q6EHTP4Q.js → chunk-MADEJDFD.js} +1 -1
  35. package/dist-cli/chunks/{chunk-WSN7MF4E.js → chunk-NL5IFN4T.js} +2 -2
  36. package/dist-cli/chunks/chunk-OAHGYDJR.js +13 -0
  37. package/dist-cli/chunks/{chunk-Q2S6VBXK.js → chunk-PDLQWZN4.js} +1 -1
  38. package/dist-cli/chunks/{chunk-6MPD3QXA.js → chunk-PIUKLO3W.js} +1 -1
  39. package/dist-cli/chunks/{chunk-6GC57KRY.js → chunk-PKZNXDUJ.js} +2 -2
  40. package/dist-cli/chunks/{chunk-MXXD5U6B.js → chunk-QQ4NSPAD.js} +2 -2
  41. package/dist-cli/chunks/{chunk-FAB5CDE7.js → chunk-QTFCJYBF.js} +3 -3
  42. package/dist-cli/chunks/{chunk-WAZCQ5UO.js → chunk-R4KLD4P4.js} +2 -2
  43. package/dist-cli/chunks/chunk-SL6565MR.js +1 -0
  44. package/dist-cli/chunks/{chunk-M6RZYHFK.js → chunk-TFZO277G.js} +1 -1
  45. package/dist-cli/chunks/{chunk-WMLFWLD7.js → chunk-TNHF6BON.js} +1 -1
  46. package/dist-cli/chunks/{chunk-T4XAQ7VQ.js → chunk-TUF6EPCQ.js} +2 -2
  47. package/dist-cli/chunks/chunk-V4M2R6FZ.js +2 -0
  48. package/dist-cli/chunks/{chunk-FD4BKULK.js → chunk-V5JEPE3P.js} +2 -2
  49. package/dist-cli/chunks/{chunk-WNUF6LJX.js → chunk-WBY4JJ2K.js} +2 -2
  50. package/dist-cli/chunks/{chunk-QQ4JDVR6.js → chunk-WEJKLJ4B.js} +2 -2
  51. package/dist-cli/chunks/{chunk-NWNFGZSI.js → chunk-X4KS33ZC.js} +2 -2
  52. package/dist-cli/chunks/{chunk-T5YWTSGG.js → chunk-XU5EMZ4B.js} +2 -2
  53. package/dist-cli/chunks/cli-version-ICHQMND6.js +2 -0
  54. package/dist-cli/chunks/{compat-EGXOXW5F.js → compat-ZJA3N4ZT.js} +3 -3
  55. package/dist-cli/chunks/{control-LUH3EQQG.js → control-CZFSYSYG.js} +2 -2
  56. package/dist-cli/chunks/{cpu-profile-7LF5VVWE.js → cpu-profile-ACSQMVXY.js} +2 -2
  57. package/dist-cli/chunks/daemon-337B4P3B.js +2 -0
  58. package/dist-cli/chunks/{debug-3J74TASS.js → debug-W2ZOVTQO.js} +3 -3
  59. package/dist-cli/chunks/{detox-PHLGST7G.js → detox-ANJO6T27.js} +2 -2
  60. package/dist-cli/chunks/{device-CBGLBSS6.js → device-KPPN4KYD.js} +2 -2
  61. package/dist-cli/chunks/{diagnose-BXUHKEVI.js → diagnose-5PEJYGES.js} +2 -2
  62. package/dist-cli/chunks/drivers-MSDIFHBD.js +2 -0
  63. package/dist-cli/chunks/{electron-UYJPUPAG.js → electron-U456QLSQ.js} +3 -3
  64. package/dist-cli/chunks/flow-JL3SC6HC.js +2 -0
  65. package/dist-cli/chunks/help-PA4RTR5X.js +2 -0
  66. package/dist-cli/chunks/{hints-7A4UIZZL.js → hints-MBBQLMQU.js} +2 -2
  67. package/dist-cli/chunks/{home-paths-THYEF54Y.js → home-paths-KQKYP2SE.js} +2 -2
  68. package/dist-cli/chunks/{inspect-QULPTQ5V.js → inspect-ZP5SM4EW.js} +61 -61
  69. package/dist-cli/chunks/{install-desktop-X7G7VTBV.js → install-desktop-OR6ZJ43X.js} +3 -3
  70. package/dist-cli/chunks/{keys-JLP4YC4T.js → keys-JSQMBUE7.js} +2 -2
  71. package/dist-cli/chunks/{login-VB4HG5WR.js → login-DVMWAI3G.js} +4 -4
  72. package/dist-cli/chunks/{logout-TIVYUTTD.js → logout-RIVPFE5N.js} +2 -2
  73. package/dist-cli/chunks/{maestro-C2WVLDFM.js → maestro-TX6FPTVH.js} +8 -6
  74. package/dist-cli/chunks/optional-demo-registry-ONYG6DUI.js +2 -0
  75. package/dist-cli/chunks/{preview-YBV54B2S.js → preview-3AD7WNA6.js} +2 -2
  76. package/dist-cli/chunks/{profile-67C256LQ.js → profile-HY55VFNR.js} +2 -2
  77. package/dist-cli/chunks/{react-HJ3WPDNO.js → react-HDRCKCKV.js} +2 -2
  78. package/dist-cli/chunks/{record-FD4QYCBW.js → record-HW4C7QYN.js} +2 -2
  79. package/dist-cli/chunks/runtime-RHHPW5WO.js +2 -0
  80. package/dist-cli/chunks/{screenshot-UTVYF7F4.js → screenshot-XFR3QN5T.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-WPSK6REL.js → screenshot-mode-Y5CVO267.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-OXRAQXWN.js → screenshots-RKUL2ZZT.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-capture-KDNNRKDL.js → screenshots-capture-RVNF75ZD.js} +8 -8
  84. package/dist-cli/chunks/{serve-ZKEXM2U5.js → serve-QMRYLWL5.js} +2 -2
  85. package/dist-cli/chunks/{setup-A5RLMR3I.js → setup-ELNJS7AI.js} +3 -3
  86. package/dist-cli/chunks/{skills-FSJFEKNP.js → skills-GPSJYS4W.js} +2 -2
  87. package/dist-cli/chunks/{slides-UU3DFZDY.js → slides-OCFNPIFG.js} +2 -2
  88. package/dist-cli/chunks/store-MBKDUQEQ.js +2 -0
  89. package/dist-cli/chunks/telemetry-46XXIUEE.js +2 -0
  90. package/dist-cli/chunks/{telemetry-TOTJDY6O.js → telemetry-KFZQUFG5.js} +2 -2
  91. package/dist-cli/chunks/{test-D6T7Z4XS.js → test-Z2HZXCZM.js} +3 -3
  92. package/dist-cli/chunks/{three-mode-CAKEPRJQ.js → three-mode-NKJFCDYS.js} +2 -2
  93. package/dist-cli/chunks/{timeline-D6NKNKNS.js → timeline-PRGQMQRR.js} +2 -2
  94. package/dist-cli/chunks/{upgrade-DBT6E6DD.js → upgrade-3NW7JRRX.js} +2 -2
  95. package/dist-cli/chunks/upload-QVDVJ6ZK.js +2 -0
  96. package/dist-cli/chunks/{version-4PLJ73Q3.js → version-FDTZRIYT.js} +2 -2
  97. package/dist-cli/chunks/{web-O6QWIX3V.js → web-4N5QQEQJ.js} +2 -2
  98. package/dist-cli/chunks/{what-happened-67DBMM4S.js → what-happened-IX2RRCOS.js} +2 -2
  99. package/dist-cli/chunks/{whoami-PSQRCMUL.js → whoami-QZ42FYYF.js} +2 -2
  100. package/dist-lib/agent-daemon-client.cjs +1 -1
  101. package/dist-lib/agent-events.cjs +1 -1
  102. package/dist-lib/agent-sessions.cjs +1 -1
  103. package/dist-lib/attached-projects.cjs +1 -1
  104. package/dist-lib/auth/shared-session.cjs +1 -1
  105. package/dist-lib/backend-origin.cjs +1 -1
  106. package/dist-lib/beta.cjs +1 -1
  107. package/dist-lib/beta.mjs +1 -1
  108. package/dist-lib/bridge-constants.cjs +1 -1
  109. package/dist-lib/cli-constants.cjs +1 -1
  110. package/dist-lib/config.cjs +1 -1
  111. package/dist-lib/detox/index.cjs +1 -1
  112. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  113. package/dist-lib/home-paths.cjs +1 -1
  114. package/dist-lib/host/bridge-host.cjs +1 -1
  115. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  116. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  117. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  118. package/dist-lib/host/websocket-proxy.cjs +1 -1
  119. package/dist-lib/index.cjs +1 -1
  120. package/dist-lib/jump-to-source-babel.cjs +1 -1
  121. package/dist-lib/menu.cjs +1 -1
  122. package/dist-lib/menu.mjs +1 -1
  123. package/dist-lib/metro.cjs +1 -1
  124. package/dist-lib/profiles.cjs +1 -1
  125. package/dist-lib/render-mode.cjs +1 -1
  126. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  127. package/dist-lib/sdk.cjs +1 -1
  128. package/dist-lib/sdk.mjs +1 -1
  129. package/dist-lib/skills.cjs +218 -47
  130. package/dist-lib/vite.cjs +1 -1
  131. package/package.json +1 -1
  132. package/dist-cli/chunks/beta-JS4JTDFC.js +0 -2
  133. package/dist-cli/chunks/chunk-BB432MX4.js +0 -1
  134. package/dist-cli/chunks/chunk-MFL73VJG.js +0 -2
  135. package/dist-cli/chunks/chunk-VGTPGXKM.js +0 -1
  136. package/dist-cli/chunks/chunk-VVACMCCE.js +0 -118
  137. package/dist-cli/chunks/chunk-WDMIABUY.js +0 -463
  138. package/dist-cli/chunks/chunk-WLDAMCQK.js +0 -13
  139. package/dist-cli/chunks/cli-version-L6NDSEVW.js +0 -2
  140. package/dist-cli/chunks/daemon-NGDXMG6R.js +0 -2
  141. package/dist-cli/chunks/drivers-QX77DPCG.js +0 -2
  142. package/dist-cli/chunks/flow-KDVDRUEN.js +0 -2
  143. package/dist-cli/chunks/help-4L6UVSAZ.js +0 -2
  144. package/dist-cli/chunks/optional-demo-registry-WV2BZJ5T.js +0 -2
  145. package/dist-cli/chunks/runtime-BY3EB4G7.js +0 -2
  146. package/dist-cli/chunks/store-TZH6LKFH.js +0 -2
  147. package/dist-cli/chunks/telemetry-AHIQ3SS5.js +0 -2
  148. package/dist-cli/chunks/upload-JR2B3YT7.js +0 -2
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.184 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}from"./chunk-T5YWTSGG.js";import{b as Mt,c as It,k as Nt}from"./chunk-WLDAMCQK.js";import"./chunk-FD4BKULK.js";import{a as te,b as A,c as E,d as je,e as ae,f as Y,g as ue,h as ge,i as vt,j as kt,k as Me,l as Tt}from"./chunk-7DKGX746.js";import{A as pt,B as ft,E as gt,G as yt,I as de,J as bt,P as ht,a as ve,b as Qe,c as Ze,d as et,e as tt,f as ot,g as st,h as nt,i as rt,j as it,k as Re,l as De,q as Ce,r as at,s as lt,t as fe,u as ct,v as ke,w as Be,x as dt,y as ut,z as mt}from"./chunk-7DHLNDOA.js";import"./chunk-WMLFWLD7.js";import"./chunk-ID25RWPE.js";import"./chunk-YYS2ITHH.js";import{c as wt,e as xt,f as $t,g as St,h as Te}from"./chunk-7C6RC3BU.js";import"./chunk-AKQWG57K.js";import"./chunk-JFCJIRX6.js";import"./chunk-IZMNFZXZ.js";import"./chunk-WNUF6LJX.js";import{a as Ye}from"./chunk-M6RZYHFK.js";import{a as Ee,c as Pe}from"./chunk-VVACMCCE.js";import{a as X}from"./chunk-WAZCQ5UO.js";import{a as Xe}from"./chunk-MFL73VJG.js";import"./chunk-Q2S6VBXK.js";import{b as Ve}from"./chunk-V36X7TNR.js";import"./chunk-53KKDNCU.js";import"./chunk-IHH3JCV5.js";import{existsSync as ho,mkdirSync as wo,readFileSync as xo,rmSync as Ot,writeFileSync as $o}from"fs";import{tmpdir as So}from"os";import{dirname as vo,join as ko,resolve as To}from"path";var ye=1,Mo="SOOTSIM_INSPECT_NOTICE_PATH",Io=300*1e3,No=15e3;function At(){return To(process.env[Mo]||ko(So(),"sootsim-inspect-notice-state.json"))}function Fo(e,a){return Object.fromEntries(Object.entries(e).filter(([,r])=>typeof r?.signature=="string"&&Number.isFinite(r?.updatedAt)&&a-r.updatedAt<=Io))}function _o(e){let a=At();if(!ho(a))return{version:ye,entries:{}};try{let r=JSON.parse(xo(a,"utf8"));return r.version!==ye||!r.entries||typeof r.entries!="object"?(Ot(a,{force:!0}),{version:ye,entries:{}}):{version:ye,entries:Fo(r.entries,e)}}catch{return Ot(a,{force:!0}),{version:ye,entries:{}}}}function Oo(e){let a=At();wo(vo(a),{recursive:!0}),$o(a,JSON.stringify(e,null,2)+`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as Ft,b as _t}from"./chunk-MADEJDFD.js";import{a as Le,g as Ie,j as oe}from"./chunk-XU5EMZ4B.js";import{b as Mt,c as It,k as Nt}from"./chunk-OAHGYDJR.js";import"./chunk-V5JEPE3P.js";import{a as te,b as A,c as E,d as je,e as ae,f as Y,g as de,h as ge,i as vt,j as kt,k as Me,l as Tt}from"./chunk-FHJTTB3W.js";import{A as pt,B as ft,E as gt,G as yt,I as ue,J as bt,P as ht,a as ve,b as Qe,c as Ze,d as et,e as tt,f as ot,g as st,h as nt,i as rt,j as it,k as Re,l as De,q as Ce,r as at,s as lt,t as fe,u as ct,v as ke,w as Be,x as ut,y as dt,z as mt}from"./chunk-FY6DJGOS.js";import"./chunk-TNHF6BON.js";import"./chunk-IJP257WP.js";import"./chunk-K2THZIVC.js";import{c as wt,e as xt,f as $t,g as St,h as Te}from"./chunk-7OAUPGLN.js";import"./chunk-4NUQVW5P.js";import"./chunk-BMCBPMTC.js";import"./chunk-HQG4DRQ3.js";import"./chunk-WBY4JJ2K.js";import{a as Ye}from"./chunk-TFZO277G.js";import{a as Ee,c as Pe}from"./chunk-KOKIECMB.js";import{a as X}from"./chunk-R4KLD4P4.js";import{a as Xe}from"./chunk-V4M2R6FZ.js";import"./chunk-PDLQWZN4.js";import{b as Ve}from"./chunk-E5DE33BU.js";import"./chunk-BI56RR3G.js";import"./chunk-GX6MKIFC.js";import{existsSync as ho,mkdirSync as wo,readFileSync as xo,rmSync as Ot,writeFileSync as $o}from"fs";import{tmpdir as So}from"os";import{dirname as vo,join as ko,resolve as To}from"path";var ye=1,Mo="SOOTSIM_INSPECT_NOTICE_PATH",Io=300*1e3,No=15e3;function At(){return To(process.env[Mo]||ko(So(),"sootsim-inspect-notice-state.json"))}function Fo(e,a){return Object.fromEntries(Object.entries(e).filter(([,r])=>typeof r?.signature=="string"&&Number.isFinite(r?.updatedAt)&&a-r.updatedAt<=Io))}function _o(e){let a=At();if(!ho(a))return{version:ye,entries:{}};try{let r=JSON.parse(xo(a,"utf8"));return r.version!==ye||!r.entries||typeof r.entries!="object"?(Ot(a,{force:!0}),{version:ye,entries:{}}):{version:ye,entries:Fo(r.entries,e)}}catch{return Ot(a,{force:!0}),{version:ye,entries:{}}}}function Oo(e){let a=At();wo(vo(a),{recursive:!0}),$o(a,JSON.stringify(e,null,2)+`
3
3
  `)}function Ao(e,a){let r=a.trim()||"default";return`${e}:${r}`}function Je(e,a,r,l={}){let m=l.nowMs??Date.now(),i=l.cooldownMs??No,g=_o(m),y=Ao(e,a),M=g.entries[y];return M&&M.signature===r&&m-M.updatedAt<i?!1:(g.entries[y]={signature:r,updatedAt:m},Oo(g),!0)}var Eo={initialWaitMs:3e3,deadlineMs:5e3,retryWaitMs:700},Po={initialWaitMs:1200,deadlineMs:2500,retryWaitMs:700};function Ro(e,a={}){return{...e?Eo:Po,...a}}function me(e){return!(!e||e.hit===!1||e.ok===!1||e.pointerTapHandled===!1&&!e.keyboardOpened&&!e.isTextInput)}function Do(e,a){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??a??null,type:e.target?.type??e.match?.type??e.node?.type??null}}async function be(e,a){let r=Ro(!!a.agent,a.timing),l=0,m=null,i=null;try{await oe({bridge:e,maxMs:r.initialWaitMs,pollMs:32,stablePolls:2})}catch{}let g=Date.now()+r.deadlineMs;for(;Date.now()<=g||l===0;){l++;let y=await a.resolve();if(m=y,y?.error==="bridge-not-ready"||y?.ambiguous||y?.nthOutOfRange)return{payload:y,result:null,attempts:l,failure:"special"};if(y&&typeof y.cx=="number"&&typeof y.cy=="number"){let I=await e.send({type:"tap",x:y.cx,y:y.cy,target:Do(y,a.textFallback)});if(i=I,me(I))return{payload:y,result:I,attempts:l}}let M=g-Date.now();if(M<=0)break;try{await oe({bridge:e,maxMs:Math.min(M,r.retryWaitMs),pollMs:32,stablePolls:2})}catch{await new Promise(I=>setTimeout(I,Math.min(120,M)))}}return{payload:m,result:i,attempts:l,failure:m&&typeof m.cx=="number"?"missed":"not-found"}}async function Et(e,a,r,l){return e.send({type:"tap",x:a,y:r,...l?{target:l}:{}})}async function Pt(e,a,r={}){let l=JSON.stringify(a);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
@@ -197,14 +197,14 @@ import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}
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"?a:i.text,type:i.type}}}})}async function Ct(e,a={args:[]}){let r=await Ze(e);if(A(a.args)){E(r);return}console.log(` nodes: ${r.nodes}`)}function We(e,a){let r=e.indexOf(a);return r>=0&&r+1<e.length?e[r+1]:null}async function Bt(e){let{bridge:a,args:r,positional:l}=e,m=r.includes("--verbose")||r.includes("-v"),i=A(r),g=m&&!i,y=r.includes("--watch")||r.includes("-w"),M=1e3,I=r.includes("--compact"),b=r.includes("--no-xy"),T=r.includes("--no-clipped"),O=r.includes("--include-occluded"),N=We(r,"--testid-like"),P=We(r,"--only"),L=We(r,"--subtree"),d=l[1]&&!l[1].startsWith("-")?l[1]:void 0,G=d?/[*?]/.test(d):!1,j=!G&&!P?d:void 0,B=P??(G?d:void 0),Z=async()=>{await ue(a,{verbose:g});let v=await ot(a,{describe:!0,verbose:m,filter:j||"",testIdLike:N||void 0,onlyGlob:B||void 0,subtreeRoot:L||void 0,compact:I,hideXy:b,includeOccluded:O}),F=v?.tree,W=v?.shell,q=v?.keyboard;if(i){E({shell:W,tree:F??"",keyboard:q});return}if(W&&typeof W=="object"){let C=[W.state?`state=${W.state}`:null,W.activeApp?`app=${W.activeApp}`:null,W.showSwitcher?"switcher":null,W.switcherPhase&&W.switcherPhase!=="idle"?`phase=${W.switcherPhase}`:null].filter(Boolean);C.length>0&&console.log(` shell: ${C.join(" ")}`)}if(typeof F=="string"&&F.startsWith("__SUBTREE_NOT_FOUND__:")){let C=F.slice(22);console.log(` subtree root not found: ${C}`),X("subtree-root-not-found",C);return}if(!F){let C=v?.nodeCount??0;console.log(" no matching nodes found"),!(j||N||B||L)&&C<10&&X("app-still-loading",C);return}let Q=F,ee=0;if(T&&typeof Q=="string"){let C=Q.split(`
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"?a:i.text,type:i.type}}}})}async function Ct(e,a={args:[]}){let r=await Ze(e);if(A(a.args)){E(r);return}console.log(` nodes: ${r.nodes}`)}function We(e,a){let r=e.indexOf(a);return r>=0&&r+1<e.length?e[r+1]:null}async function Bt(e){let{bridge:a,args:r,positional:l}=e,m=r.includes("--verbose")||r.includes("-v"),i=A(r),g=m&&!i,y=r.includes("--watch")||r.includes("-w"),M=1e3,I=r.includes("--compact"),b=r.includes("--no-xy"),T=r.includes("--no-clipped"),O=r.includes("--include-occluded"),N=We(r,"--testid-like"),P=We(r,"--only"),L=We(r,"--subtree"),u=l[1]&&!l[1].startsWith("-")?l[1]:void 0,G=u?/[*?]/.test(u):!1,j=!G&&!P?u:void 0,B=P??(G?u:void 0),Z=async()=>{await de(a,{verbose:g});let v=await ot(a,{describe:!0,verbose:m,filter:j||"",testIdLike:N||void 0,onlyGlob:B||void 0,subtreeRoot:L||void 0,compact:I,hideXy:b,includeOccluded:O}),F=v?.tree,W=v?.shell,q=v?.keyboard;if(i){E({shell:W,tree:F??"",keyboard:q});return}if(W&&typeof W=="object"){let C=[W.state?`state=${W.state}`:null,W.activeApp?`app=${W.activeApp}`:null,W.showSwitcher?"switcher":null,W.switcherPhase&&W.switcherPhase!=="idle"?`phase=${W.switcherPhase}`:null].filter(Boolean);C.length>0&&console.log(` shell: ${C.join(" ")}`)}if(typeof F=="string"&&F.startsWith("__SUBTREE_NOT_FOUND__:")){let C=F.slice(22);console.log(` subtree root not found: ${C}`),X("subtree-root-not-found",C);return}if(!F){let C=v?.nodeCount??0;console.log(" no matching nodes found"),!(j||N||B||L)&&C<10&&X("app-still-loading",C);return}let Q=F,ee=0;if(T&&typeof Q=="string"){let C=Q.split(`
201
201
  `),ce=[];for(let $e of C){if($e.includes("(clipped:")){ee+=1;continue}ce.push($e)}Q=ce.join(`
202
202
  `)}console.log(Q),ee>0&&console.log(` ${ee} clipped row(s) hidden (omit --no-clipped to see)`);let ie=j||N||B||L;if((j||N||B)&&!y&&X("describe-filter-context"),!ie&&!y&&F.split(`
203
203
  `).length>=80&&X("describe-use-filters"),q&&q.visible){let C=q.spec,ce=[C?.keyboardType?`type=${C.keyboardType}`:null,C?.returnKeyType&&C.returnKeyType!=="default"?`return=${C.returnKeyType}`:null,q.mode!=="letters"?`mode=${q.mode}`:null,q.shifted?"shift":null,q.capsLock?"caps":null,C?.autoCapitalize&&C.autoCapitalize!=="sentences"?`autoCap=${C.autoCapitalize}`:null,q.accessoryBarId?`accessory=${q.accessoryBarId}`:null].filter(Boolean);console.log(`
204
204
  keyboard: ${ce.join(" ")||"visible"}`)}};if(y)for(console.log(` watching... (Ctrl+C to stop)
205
- `);;)console.clear(),await Z(),await te(M);else await Z()}var Co=["SOOTSIM_AGENT","AGENTBUS_SESSION","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function pe(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let e of Co){let a=process.env[e];if(a&&a.trim()&&a!=="0")return!0}return!1}async function jt(e){let{bridge:a,args:r,effectiveArgs:l,positional:m,inspectUsage:i}=e,g=v=>{let F=l.indexOf(v);return F>=0&&F+1<l.length?l[F+1]:null},y=v=>l.includes(v),M=g("--testid")||g("--test-id"),I=g("--role"),b=g("--type"),T=g("--text"),O=y("--pressable"),N=y("--visible"),P=y("--interactive-targets")||y("--actions"),L=!M&&!I&&!b&&!T&&!O&&!N&&!P?m[1]:null,d=T??L,G=await it(a,{testId:M,role:I,type:b,text:d,pressable:O,visible:N,interactive:P});G||(console.error(i("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:j,result:B}=G,Z=A(r),se=r.includes("--verbose")||r.includes("--dump");if(Z)j==="interactive-targets"&&Array.isArray(B)?E(Re(B).map(v=>({...v,tap:De(v)}))):E(B??null);else if(Array.isArray(B))if(B.length===0){console.log(` no ${j} nodes found`);let v=await a.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof v=="number"&&v<10&&X("app-still-loading",v)}else if(j==="interactive-targets"){let v=Re(B);console.log(` found ${v.length} interactive target${v.length===1?"":"s"} (sorted by score):`);for(let F of v.slice(0,20)){let W=F.absolutePosition?`@(${Math.round(F.absolutePosition.x)},${Math.round(F.absolutePosition.y)})`:"",q=F.layout?`${Math.round(F.layout.width)}x${Math.round(F.layout.height)}`:"?x?",Q=F.text?` "${F.text.slice(0,30)}"`:"",ee=F.testID?` #${F.testID}`:"",ie=F.accessibilityLabel?` \u24D8"${String(F.accessibilityLabel).slice(0,24)}"`:"",xe=F.accessibilityRole?`[${F.accessibilityRole}]`:F.type,C=De(F);console.log(` ${xe}${Q}${ie}${ee} ${q} ${W}`),console.log(` \u2192 ${C}`),se&&console.log(qe(JSON.stringify(F,null,2)," "))}v.length>20&&console.log(` ... and ${v.length-20} more`)}else{console.log(` found ${B.length} node${B.length===1?"":"s"} (${j}):`);for(let v of B.slice(0,20)){let F=v.absolutePosition?`@(${Math.round(v.absolutePosition.x)},${Math.round(v.absolutePosition.y)})`:"",W=v.layout?`${Math.round(v.layout.width)}x${Math.round(v.layout.height)}`:"?x?",q=v.text?` "${v.text.slice(0,30)}"`:"",Q=v.testID?` #${v.testID}`:"",ee=v.pressable?" (tap)":"",ie=v.accessibilityRole?`[${v.accessibilityRole}]`:v.type;console.log(` ${ie}${q}${Q} ${W} ${F}${ee}`),se&&console.log(qe(JSON.stringify(v,null,2)," "))}B.length>20&&console.log(` ... and ${B.length-20} more`)}else if(B==null)console.log(` not found: ${d||M||I||b||""||j}`),M&&X("wait-selector-for-missing-testid",M);else{let v=B;if(v.type&&v.absolutePosition){let F=`@(${Math.round(v.absolutePosition.x)},${Math.round(v.absolutePosition.y)})`,W=v.layout?`${Math.round(v.layout.width)}x${Math.round(v.layout.height)}`:"?x?",q=v.text?` "${v.text.slice(0,40)}"`:"",Q=v.testID?` #${v.testID}`:"",ee=v.pressable?" (tap)":"",ie=v.accessibilityRole?`[${v.accessibilityRole}]`:v.type;console.log(` ${ie}${q}${Q} ${W} ${F}${ee}`),se&&console.log(qe(JSON.stringify(v,null,2)," "))}else console.log(JSON.stringify(B,null,2))}}function qe(e,a){return e.split(`
205
+ `);;)console.clear(),await Z(),await te(M);else await Z()}var Co=["SOOTSIM_AGENT","AGENTBUS_SESSION","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function pe(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let e of Co){let a=process.env[e];if(a&&a.trim()&&a!=="0")return!0}return!1}async function jt(e){let{bridge:a,args:r,effectiveArgs:l,positional:m,inspectUsage:i}=e,g=v=>{let F=l.indexOf(v);return F>=0&&F+1<l.length?l[F+1]:null},y=v=>l.includes(v),M=g("--testid")||g("--test-id"),I=g("--role"),b=g("--type"),T=g("--text"),O=y("--pressable"),N=y("--visible"),P=y("--interactive-targets")||y("--actions"),L=!M&&!I&&!b&&!T&&!O&&!N&&!P?m[1]:null,u=T??L,G=await it(a,{testId:M,role:I,type:b,text:u,pressable:O,visible:N,interactive:P});G||(console.error(i("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:j,result:B}=G,Z=A(r),se=r.includes("--verbose")||r.includes("--dump");if(Z)j==="interactive-targets"&&Array.isArray(B)?E(Re(B).map(v=>({...v,tap:De(v)}))):E(B??null);else if(Array.isArray(B))if(B.length===0){console.log(` no ${j} nodes found`);let v=await a.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof v=="number"&&v<10&&X("app-still-loading",v)}else if(j==="interactive-targets"){let v=Re(B);console.log(` found ${v.length} interactive target${v.length===1?"":"s"} (sorted by score):`);for(let F of v.slice(0,20)){let W=F.absolutePosition?`@(${Math.round(F.absolutePosition.x)},${Math.round(F.absolutePosition.y)})`:"",q=F.layout?`${Math.round(F.layout.width)}x${Math.round(F.layout.height)}`:"?x?",Q=F.text?` "${F.text.slice(0,30)}"`:"",ee=F.testID?` #${F.testID}`:"",ie=F.accessibilityLabel?` \u24D8"${String(F.accessibilityLabel).slice(0,24)}"`:"",xe=F.accessibilityRole?`[${F.accessibilityRole}]`:F.type,C=De(F);console.log(` ${xe}${Q}${ie}${ee} ${q} ${W}`),console.log(` \u2192 ${C}`),se&&console.log(qe(JSON.stringify(F,null,2)," "))}v.length>20&&console.log(` ... and ${v.length-20} more`)}else{console.log(` found ${B.length} node${B.length===1?"":"s"} (${j}):`);for(let v of B.slice(0,20)){let F=v.absolutePosition?`@(${Math.round(v.absolutePosition.x)},${Math.round(v.absolutePosition.y)})`:"",W=v.layout?`${Math.round(v.layout.width)}x${Math.round(v.layout.height)}`:"?x?",q=v.text?` "${v.text.slice(0,30)}"`:"",Q=v.testID?` #${v.testID}`:"",ee=v.pressable?" (tap)":"",ie=v.accessibilityRole?`[${v.accessibilityRole}]`:v.type;console.log(` ${ie}${q}${Q} ${W} ${F}${ee}`),se&&console.log(qe(JSON.stringify(v,null,2)," "))}B.length>20&&console.log(` ... and ${B.length-20} more`)}else if(B==null)console.log(` not found: ${u||M||I||b||""||j}`),M&&X("wait-selector-for-missing-testid",M);else{let v=B;if(v.type&&v.absolutePosition){let F=`@(${Math.round(v.absolutePosition.x)},${Math.round(v.absolutePosition.y)})`,W=v.layout?`${Math.round(v.layout.width)}x${Math.round(v.layout.height)}`:"?x?",q=v.text?` "${v.text.slice(0,40)}"`:"",Q=v.testID?` #${v.testID}`:"",ee=v.pressable?" (tap)":"",ie=v.accessibilityRole?`[${v.accessibilityRole}]`:v.type;console.log(` ${ie}${q}${Q} ${W} ${F}${ee}`),se&&console.log(qe(JSON.stringify(v,null,2)," "))}else console.log(JSON.stringify(B,null,2))}}function qe(e,a){return e.split(`
206
206
  `).map(r=>a+r).join(`
207
- `)}async function Lt(e){let{bridge:a,args:r}=e,l=A(r);await ue(a,{verbose:!l});let m=r.includes("--styling"),i=await st(a,{styling:m});if(l){E({count:i.length,elements:i});return}console.log(` layout (${i.length} element${i.length===1?"":"s"}):
207
+ `)}async function Lt(e){let{bridge:a,args:r}=e,l=A(r);await de(a,{verbose:!l});let m=r.includes("--styling"),i=await st(a,{styling:m});if(l){E({count:i.length,elements:i});return}console.log(` layout (${i.length} element${i.length===1?"":"s"}):
208
208
  `),console.log(nt(i,{styling:m}))}async function Jt(e,a={}){let r=await yt(e);if("error"in r&&(console.error(r.error),process.exit(1)),a.json){console.log(JSON.stringify(r,null,2));return}let{visible:l,spec:m,mode:i,shifted:g,capsLock:y,accessoryBarId:M}=r,I=[];I.push(`keyboard: ${l?"visible":"hidden"}`),m?(I.push(` type: ${m.keyboardType}`),I.push(` returnKey: ${m.returnKeyType}`),I.push(` autoCap: ${m.autoCapitalize}`),I.push(` autoCorrect: ${m.autoCorrect?"on":"off"}`),I.push(` appearance: ${m.keyboardAppearance}`),m.secureTextEntry&&I.push(" secureTextEntry: true"),m.enablesReturnKeyAutomatically&&I.push(` return: ${m.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):I.push(" spec: <none> (shown via dev-tools with no TextInput)"),I.push(` mode: ${i}${g?" (shifted)":""}${y?" (caps)":""}`),M&&I.push(` accessoryBar: ${M}`),console.log(I.join(`
209
209
  `))}async function Wt(e){let a=await e.bridge.listSims(),r=e.args.includes("--all"),l=e.args.find((y,M)=>e.args[M-1]==="--bundle"),m=e.args.find((y,M)=>e.args[M-1]==="--app-port"),i=e.args.includes("--primary"),g=a.filter(y=>!(i&&!y.isPrimary||l&&!(y.url??"").includes(l)||m&&!(y.url??"").includes(`/rn/${m}`)||!r&&!l&&!m&&!i&&!(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}Nt(g,e.simId),g.length<a.length&&!A(e.args)&&console.log(` (${a.length-g.length} more hidden \u2014 pass --all to show)`)}function le(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/1024/1024).toFixed(1)}MB`}function Ne(e,a){return a<=0?"?":`${(e/a*100).toFixed(0)}%`}async function qt(e,a={args:[]}){let r=await ht(e);if(A(a.args)){E(r);return}if(console.log(" memory:"),r.imageLoader){let l=r.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${l.cacheEntries} / ${l.cacheMaxEntries} (${Ne(l.cacheEntries,l.cacheMaxEntries)})`),console.log(` pixel bytes: ${le(l.cachePixelBytes)} / ${le(l.cachePixelBudget)} (${Ne(l.cachePixelBytes,l.cachePixelBudget)})`),console.log(` pending: ${l.pendingFetches} fetches, ${l.pendingBytes} bytes`),console.log(` failed uris: ${l.failedUris}`),console.log(` snapshots: ${l.snapshots}`),console.log(` live frames: ${l.liveFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(r.workerHeap){let l=r.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${le(l.usedJSHeapSize)} / ${le(l.jsHeapSizeLimit)} (${Ne(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${le(l.totalJSHeapSize)}`)}if(r.hostHeap){let l=r.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${le(l.usedJSHeapSize)} / ${le(l.jsHeapSizeLimit)} (${Ne(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${le(l.totalJSHeapSize)}`)}}var V="<redacted secure text>";function he(e){let a=e?.layout?.spec??e?.spec??null;return!!a?.secureTextEntry&&a.keyboardType!=="visible-password"}function He(e,a){return he(a)?V:e}function Ke(e){if(!e||!he(e))return e;let a=e.focusedInput;return!a||typeof a!="object"?e:{...e,focusedInput:{...a,secureTextEntry:!0,text:typeof a.text=="string"?V:a.text}}}function we(e){let a=e.indexOf("--testid");if(a>=0&&e[a+1])return{mode:"testid",value:e[a+1]};let r=e.indexOf("--test-id");if(r>=0&&e[r+1])return{mode:"testid",value:e[r+1]};let l=e.indexOf("--text");return l>=0&&e[l+1]?{mode:"text",value:e[l+1]}:null}async function Fe(e,a){let r=JSON.stringify(a.value),l=a.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
@@ -236,7 +236,7 @@ import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}
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(G)}) }
239
- })()`});(!j||!j.ok)&&(console.error(` could not query timeline: ${j&&"error"in j?j.error:"unknown"}`),process.exit(1));let B=j.result.events??[];for(let Z of B)if(Bo(Z,{filter:M,equals:I})){let se=Date.now()-O;console.log(T?JSON.stringify({found:!0,elapsedMs:se,event:Z}):` ${i} event after ${se}ms${M?` (filter: ${M})`:""}${I?` (equals: ${I})`:""}`);return}j.result.watermark&&j.result.watermark>L&&(L=j.result.watermark),await new Promise(Z=>setTimeout(Z,P))}let d=Date.now()-O;T?console.log(JSON.stringify({found:!1,elapsedMs:d,kind:i,filter:M,equals:I})):console.error(` \u26A0 wait event ${i} timed out after ${d}ms${M?` (filter: ${M})`:""}${I?` (equals: ${I})`:""}`),process.exit(1)}async function Qt(e){let{bridge:a,args:r}=e,l=r.includes("--strict"),m=ve(r,3e3),{elapsed:i,settled:g}=await oe({bridge:a,maxMs:m,strict:l});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 Zt(e){let{bridge:a,args:r}=e,l=ve(r,2e4),{ready:m,elapsedMs:i,nodes:g,targets:y,flag:M,loadingText:I,externalReady:b,externalError:T,errors:O}=await at(a,l,{onProgress(P){console.error(` still waiting after ${P.elapsedMs}ms \u2014 ${Ce(P)} (nodes: ${P.nodes}, targets: ${P.targets}, errors: ${P.errors})`)}});if(m){let P=l-i,L=Math.max(100,Math.min(1e4,P)),d=await oe({bridge:a,maxMs:L,pollMs:32,stablePolls:2});d.settled||(console.error(` \u26A0 wait ready timed out after ${i+d.elapsed}ms \u2014 app mounted but did not settle (nodes: ${g}, targets: ${y})`),process.exit(1)),console.log(` ready in ${i+d.elapsed}ms: ${g} nodes, ${y} targets`);return}let N=Ce({externalError:T,loadingText:I,externalReady:b,flag:M,targets:y});console.error(` \u26A0 wait ready timed out after ${i}ms \u2014 ${N} (nodes: ${g}, targets: ${y}, errors: ${O})`),process.exit(1)}async function eo(e){let{bridge:a,args:r,positional:l,inspectUsage:m}=e,i=l[1];i||(console.error(m("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,M=r.includes("--gone"),{found:I,node:b,elapsed:T}=await lt(a,i,y,{gone:M});if(M){I?console.log(` #${i} gone after ${T}ms`):(console.error(` \u26A0 wait selector #${i} --gone timed out after ${T??y}ms (still present)`),process.exit(1));return}if(I&&b){let O=b.absolutePosition?`@(${Math.round(b.absolutePosition.x)},${Math.round(b.absolutePosition.y)})`:"",N=b.layout?`${Math.round(b.layout.width)}x${Math.round(b.layout.height)}`:"?x?";console.log(` found #${i} in ${T}ms ${N} ${O}`)}else console.error(` \u26A0 wait selector #${i} timed out after ${T??y}ms`),process.exit(1)}function co(e){return e==null?"\u2014":e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}K`:`${(e/1024/1024).toFixed(1)}M`}function uo(e){return e==null?" \u2026":e<1e3?`${e}ms`.padStart(5):`${(e/1e3).toFixed(2)}s`.padStart(5)}function to(){process.stderr.write(` the sim is not responding. recover it with:
239
+ })()`});(!j||!j.ok)&&(console.error(` could not query timeline: ${j&&"error"in j?j.error:"unknown"}`),process.exit(1));let B=j.result.events??[];for(let Z of B)if(Bo(Z,{filter:M,equals:I})){let se=Date.now()-O;console.log(T?JSON.stringify({found:!0,elapsedMs:se,event:Z}):` ${i} event after ${se}ms${M?` (filter: ${M})`:""}${I?` (equals: ${I})`:""}`);return}j.result.watermark&&j.result.watermark>L&&(L=j.result.watermark),await new Promise(Z=>setTimeout(Z,P))}let u=Date.now()-O;T?console.log(JSON.stringify({found:!1,elapsedMs:u,kind:i,filter:M,equals:I})):console.error(` \u26A0 wait event ${i} timed out after ${u}ms${M?` (filter: ${M})`:""}${I?` (equals: ${I})`:""}`),process.exit(1)}async function Qt(e){let{bridge:a,args:r}=e,l=r.includes("--strict"),m=ve(r,3e3),{elapsed:i,settled:g}=await oe({bridge:a,maxMs:m,strict:l});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 Zt(e){let{bridge:a,args:r}=e,l=ve(r,2e4),{ready:m,elapsedMs:i,nodes:g,targets:y,flag:M,loadingText:I,externalReady:b,externalError:T,errors:O}=await at(a,l,{onProgress(P){console.error(` still waiting after ${P.elapsedMs}ms \u2014 ${Ce(P)} (nodes: ${P.nodes}, targets: ${P.targets}, errors: ${P.errors})`)}});if(m){let P=l-i,L=Math.max(100,Math.min(1e4,P)),u=await oe({bridge:a,maxMs:L,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 N=Ce({externalError:T,loadingText:I,externalReady:b,flag:M,targets:y});console.error(` \u26A0 wait ready timed out after ${i}ms \u2014 ${N} (nodes: ${g}, targets: ${y}, errors: ${O})`),process.exit(1)}async function eo(e){let{bridge:a,args:r,positional:l,inspectUsage:m}=e,i=l[1];i||(console.error(m("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,M=r.includes("--gone"),{found:I,node:b,elapsed:T}=await lt(a,i,y,{gone:M});if(M){I?console.log(` #${i} gone after ${T}ms`):(console.error(` \u26A0 wait selector #${i} --gone timed out after ${T??y}ms (still present)`),process.exit(1));return}if(I&&b){let O=b.absolutePosition?`@(${Math.round(b.absolutePosition.x)},${Math.round(b.absolutePosition.y)})`:"",N=b.layout?`${Math.round(b.layout.width)}x${Math.round(b.layout.height)}`:"?x?";console.log(` found #${i} in ${T}ms ${N} ${O}`)}else console.error(` \u26A0 wait selector #${i} timed out after ${T??y}ms`),process.exit(1)}function co(e){return e==null?"\u2014":e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}K`:`${(e/1024/1024).toFixed(1)}M`}function uo(e){return e==null?" \u2026":e<1e3?`${e}ms`.padStart(5):`${(e/1e3).toFixed(2)}s`.padStart(5)}function to(){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
242
  `)}async function Lo(e){try{return await e.send({type:"evaluate",code:"1"},{timeoutMs:3e3}),!0}catch{return!1}}async function Jo(e,a){try{let r=await e.send({type:"evaluate",code:`(async () => {
@@ -259,7 +259,7 @@ import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}
259
259
  return []
260
260
  }
261
261
  })()`});if(!Array.isArray(r)||r.length===0)return;let l=a.toLowerCase(),m=r.map(i=>({id:i,score:Wo(l,i.toLowerCase())})).filter(i=>i.score<l.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 Wo(e,a){if(a===e)return 0;if(a.includes(e))return 1;if(e.includes(a))return 2;let r=0;for(;r<e.length&&r<a.length&&e[r]===a[r];)r+=1;return qo(e,a)-r}function qo(e,a){if(e===a)return 0;if(!e.length)return a.length;if(!a.length)return e.length;let r=new Array(a.length+1),l=new Array(a.length+1);for(let m=0;m<=a.length;m++)r[m]=m;for(let m=1;m<=e.length;m++){l[0]=m;for(let g=1;g<=a.length;g++)l[g]=Math.min(r[g]+1,l[g-1]+1,r[g-1]+(e[m-1]===a[g-1]?0:1));let i=r;r=l,l=i}return r[a.length]}function Ho(e){return e.error?"err":e.status==null?" \u2026 ":String(e.status)}function oo(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 so(e){let a=ae(e.startTs),r=Ho(e).padEnd(3),l=e.method.padEnd(5),m=co(e.size).padStart(6),i=uo(e.durationMs);console.log(` [${a}] ${r} ${l} ${m} ${i} ${e.displayUrl}`),e.error&&console.log(` error: ${e.error}`)}function Ko(e){let a=[["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",ae(e.startTs)],["duration",uo(e.durationMs).trim()],["size",co(e.size)],["content-type",e.type??"\u2014"]];for(let[r,l]of a)console.log(` ${r.padEnd(13)} ${l}`)}var Uo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},no="\x1B[0m",zo="\x1B[2m";function ro(e,a){let r=ae(e.ts),l=e.level.toUpperCase().padEnd(5),m=e.args.join(" ");if(a){let i=Uo[e.level];console.log(` ${zo}[${r}]${no} ${i}${l}${no} ${m}`)}else console.log(` [${r}] ${l} ${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 re="__sootsimCliPerf",Go=120;async function io(e,a){let r=e.find((O,N)=>e[N-1]==="--id"),l=e.find((O,N)=>e[N-1]==="--text");if(r||l){let O=await a.send({type:"evaluate",code:Ft({id:r,text:l})});if(!O)throw new Error(r?`no node with id "${r}"`:`no node matching text "${l}"`);let{x:N,y:P,w:L,h:d}=O;return{x:N,y:P,w:L,h:d}}let m=e.find((O,N)=>e[N-1]==="--area");if(m){let O=m.split(",").map(G=>Number(G.trim()));if(O.length!==4||O.some(G=>!Number.isFinite(G)))throw new Error(`--area expects x,y,w,h (got "${m}")`);let[N,P,L,d]=O;return{x:N,y:P,w:L,h:d}}let i=O=>{let N=e.find((L,d)=>e[d-1]===O);if(N==null)return null;let P=Number(N);return Number.isFinite(P)?P:null},g=i("--x"),y=i("--y"),M=i("--w"),I=i("--h");if(g!=null||y!=null||M!=null||I!=null)return{x:g??0,y:y??0,w:M??1,h:I??1};let T=e.filter((O,N)=>N>0&&!O.startsWith("-")&&e[N-1]!=="--output"&&e[N-1]!=="--area"&&e[N-1]!=="--id"&&e[N-1]!=="--text"&&e[N-1]!=="--x"&&e[N-1]!=="--y"&&e[N-1]!=="--w"&&e[N-1]!=="--h").map(Number).filter(O=>Number.isFinite(O));if(T.length>=2){let[O,N,P=1,L=1]=T;return{x:O,y:N,w:P,h:L}}return null}function Ue(e){let a={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let r of e)r<8?a["<8"]++:r<12?a["8-12"]++:r<16?a["12-16"]++:r<20?a["16-20"]++:r<33?a["20-33"]++:a[">33"]++;console.log(" histogram:");for(let[r,l]of Object.entries(a)){let m="\u2588".repeat(Math.ceil(l/e.length*40));console.log(` ${r.padEnd(6)} ${m} ${l}`)}}async function Oe(e,a,r){let l=Date.now()+a,m=await de(e,a);for(;;){if(r(m))return{settled:!0,state:m};if(Date.now()>=l)return{settled:!1,state:m};await te(16),m=await de(e)}}async function Ge(e){return e.send({type:"evaluate",code:`(async () => {
262
+ `).slice(0,5);for(let g of i)console.log(` ${g.trim()}`)}}var re="__sootsimCliPerf",Go=120;async function io(e,a){let r=e.find((O,N)=>e[N-1]==="--id"),l=e.find((O,N)=>e[N-1]==="--text");if(r||l){let O=await a.send({type:"evaluate",code:Ft({id:r,text:l})});if(!O)throw new Error(r?`no node with id "${r}"`:`no node matching text "${l}"`);let{x:N,y:P,w:L,h:u}=O;return{x:N,y:P,w:L,h:u}}let m=e.find((O,N)=>e[N-1]==="--area");if(m){let O=m.split(",").map(G=>Number(G.trim()));if(O.length!==4||O.some(G=>!Number.isFinite(G)))throw new Error(`--area expects x,y,w,h (got "${m}")`);let[N,P,L,u]=O;return{x:N,y:P,w:L,h:u}}let i=O=>{let N=e.find((L,u)=>e[u-1]===O);if(N==null)return null;let P=Number(N);return Number.isFinite(P)?P:null},g=i("--x"),y=i("--y"),M=i("--w"),I=i("--h");if(g!=null||y!=null||M!=null||I!=null)return{x:g??0,y:y??0,w:M??1,h:I??1};let T=e.filter((O,N)=>N>0&&!O.startsWith("-")&&e[N-1]!=="--output"&&e[N-1]!=="--area"&&e[N-1]!=="--id"&&e[N-1]!=="--text"&&e[N-1]!=="--x"&&e[N-1]!=="--y"&&e[N-1]!=="--w"&&e[N-1]!=="--h").map(Number).filter(O=>Number.isFinite(O));if(T.length>=2){let[O,N,P=1,L=1]=T;return{x:O,y:N,w:P,h:L}}return null}function Ue(e){let a={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let r of e)r<8?a["<8"]++:r<12?a["8-12"]++:r<16?a["12-16"]++:r<20?a["16-20"]++:r<33?a["20-33"]++:a[">33"]++;console.log(" histogram:");for(let[r,l]of Object.entries(a)){let m="\u2588".repeat(Math.ceil(l/e.length*40));console.log(` ${r.padEnd(6)} ${m} ${l}`)}}async function Oe(e,a,r){let l=Date.now()+a,m=await ue(e,a);for(;;){if(r(m))return{settled:!0,state:m};if(Date.now()>=l)return{settled:!1,state:m};await te(16),m=await ue(e)}}async function Ge(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,7 +296,7 @@ import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}
296
296
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
297
297
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
298
298
  }
299
- })()`}).then(a=>Ke(a))}function Yo(e,a,r){if(!e.visible)return!1;let l=e.focusedInput;return!(a&&l&&!(l.testID===a||l.id===a)||r!==null&&he(e)!==r)}async function Xo(e,a=600,r={}){let l=Date.now()+a;for(;Date.now()<=l;){let m=await Ge(e);if(Yo(m,r.targetId??null,r.secureTextEntry??null))return m;await te(30)}return Ge(e)}async function Ae(e,a){let r=await Ge(e);if(r.visible)return r;console.error(` ${a} 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 ao(e,a,r){return a==="appearance"?e.send({type:"evaluate",code:`(async () => {
299
+ })()`}).then(a=>Ke(a))}function Yo(e,a,r){if(!e.visible)return!1;let l=e.focusedInput;return!(a&&l&&!(l.testID===a||l.id===a)||r!==null&&he(e)!==r)}async function Xo(e,a=600,r={}){let l=Date.now()+a;for(;Date.now()<=l;){let m=await Ge(e);if(Yo(m,r.targetId??null,r.secureTextEntry??null))return m;await te(30)}return Ge(e)}async function Ae(e,a){let r=await Ge(e);if(r.visible&&r.focusedInput)return r;r.visible&&(console.error(` ${a} requires a focused TextInput. the iOS keyboard is visible, but no input owns focus.`),process.exit(1)),console.error(` ${a} 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 ao(e,a,r){return a==="appearance"?e.send({type:"evaluate",code:`(async () => {
300
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
@@ -326,19 +326,19 @@ import{a as Ft,b as _t}from"./chunk-Q6EHTP4Q.js";import{a as Le,g as Ie,j as oe}
326
326
  `);console.log(`${o??""}
327
327
 
328
328
  ${t}
329
- `),process.exit(0)}let O=m.wsPort,N=m.simId,P=m.simIdSource,L=m.commandTimeoutMs;if(g==="list"&&l.some($=>$==="--drivers"||$==="-D")){let{buildDriverListRows:$}=await import("./drivers-QX77DPCG.js"),o=$();console.log(` available drivers (${o.length}):
330
- `);let t=Math.max(...o.map(n=>n.id.length),6),s=Math.max(...o.map(n=>n.kind.length),4);for(let n of o){let c=n.available?"\u2713":"\u2717",u=n.id.padEnd(t),p=n.kind.padEnd(s);console.log(` ${c} ${u} ${p} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let d=xt(m),G=N||"default",j=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","storage-clear","list","wait","sleep"]),B=200;function Z($){let o=$.replace(/\s+/g," ").trim();if(!o)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(o)){let s=/<title[^>]*>([^<]+)<\/title>/i.exec($)?.[1]?.trim(),n=/<body[^>]*>([\s\S]*?)<\//i.exec($)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),c=s||n||"html error page";return`<html ${$.length}B> "${c}" (body elided \u2014 add --json for the full payload)`}return o.length<=B?o:`${o.slice(0,B)}\u2026 (+${o.length-B} more bytes)`}function se($){let o=$.displayUrl||$.url;return $.status!=null?`${$.method} ${o} -> ${$.status}${$.statusText?` ${$.statusText}`:""}`:$.error?`${$.method} ${o} -> ${$.error}`:`${$.method} ${o}`}async function v($){let o=pe()?5e3:1500;try{let{settled:t,elapsed:s}=await oe({bridge:$,maxMs:o,pollMs:32,stablePolls:2});t||process.stderr.write(` \u26A0 auto-wait timed out after ${s??o}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
331
- `)}catch{}}function F($,o){console.error(` tap failed: ${$} stayed visible but did not receive a hittable press after ${o.attempts} attempt${o.attempts===1?"":"s"}`),o.result&&console.error(` last result: ${JSON.stringify(o.result)}`)}async function W(){try{return await d.send({type:"evaluate",code:`(() => ({
329
+ `),process.exit(0)}let O=m.wsPort,N=m.simId,P=m.simIdSource,L=m.commandTimeoutMs;if(g==="list"&&l.some($=>$==="--drivers"||$==="-D")){let{buildDriverListRows:$}=await import("./drivers-MSDIFHBD.js"),o=$();console.log(` available drivers (${o.length}):
330
+ `);let t=Math.max(...o.map(n=>n.id.length),6),s=Math.max(...o.map(n=>n.kind.length),4);for(let n of o){let c=n.available?"\u2713":"\u2717",d=n.id.padEnd(t),p=n.kind.padEnd(s);console.log(` ${c} ${d} ${p} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let u=xt(m),G=N||"default",j=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","storage-clear","list","wait","sleep"]),B=200;function Z($){let o=$.replace(/\s+/g," ").trim();if(!o)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(o)){let s=/<title[^>]*>([^<]+)<\/title>/i.exec($)?.[1]?.trim(),n=/<body[^>]*>([\s\S]*?)<\//i.exec($)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),c=s||n||"html error page";return`<html ${$.length}B> "${c}" (body elided \u2014 add --json for the full payload)`}return o.length<=B?o:`${o.slice(0,B)}\u2026 (+${o.length-B} more bytes)`}function se($){let o=$.displayUrl||$.url;return $.status!=null?`${$.method} ${o} -> ${$.status}${$.statusText?` ${$.statusText}`:""}`:$.error?`${$.method} ${o} -> ${$.error}`:`${$.method} ${o}`}async function v($){let o=pe()?5e3:1500;try{let{settled:t,elapsed:s}=await oe({bridge:$,maxMs:o,pollMs:32,stablePolls:2});t||process.stderr.write(` \u26A0 auto-wait timed out after ${s??o}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
331
+ `)}catch{}}function F($,o){console.error(` tap failed: ${$} stayed visible but did not receive a hittable press after ${o.attempts} attempt${o.attempts===1?"":"s"}`),o.result&&console.error(` last result: ${JSON.stringify(o.result)}`)}async function W(){try{return await u.send({type:"evaluate",code:`(() => ({
332
332
  console: ${ke},
333
333
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
334
- }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function q($={}){let o=$.counts!==void 0?$.counts:await Y(d,"getRequestCounts");if(!o||typeof o!="object")return;let t=Math.max(0,Number(o.failed)||0);if(t===0||!$.includeTail&&!Je("requests",G,String(t))||(console.log(`
335
- network: ${t} failed request${t===1?"":"s"}`),console.log(` inspect: ${b("requests")} 5`),!$.includeTail))return;let s=await Y(d,"getFailedRequests",5);if(!(!Array.isArray(s)||s.length===0)){console.log(`
334
+ }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function q($={}){let o=$.counts!==void 0?$.counts:await Y(u,"getRequestCounts");if(!o||typeof o!="object")return;let t=Math.max(0,Number(o.failed)||0);if(t===0||!$.includeTail&&!Je("requests",G,String(t))||(console.log(`
335
+ network: ${t} failed request${t===1?"":"s"}`),console.log(` inspect: ${b("requests")} 5`),!$.includeTail))return;let s=await Y(u,"getFailedRequests",5);if(!(!Array.isArray(s)||s.length===0)){console.log(`
336
336
  recent failed requests:
337
337
  `);for(let n of s){let c=ae(n.timestamp);console.log(` [${c}] ${se(n)}`),n.responseBody?console.log(` ${Z(n.responseBody)}`):n.error&&console.log(` ${n.error}`)}}}function Q($){for(let o of $){let t=o.title?` (\u201C${o.title}\u201D)`:"";console.log(`
338
- note: ${o.label} is open${t} \u2014 taps/drags hit it, not the app`)}}async function ee($={}){let o=$.counts!==void 0?$.counts:await d.send({type:"evaluate",code:ke});if(!o||typeof o!="object")return;let t=o,s=Math.max(0,Number(t.errors)||0),n=Math.max(0,Number(t.warnings)||0);if(s===0&&n===0||!$.includeTail&&!Je("console",G,`${s}:${n}`))return;let c=[];if(s>0&&c.push(`${s} console error${s===1?"":"s"}`),n>0&&c.push(`${n} console warning${n===1?"":"s"}`),console.log(`
339
- console: ${c.join(", ")}`),console.log(` inspect: ${b("errors")} 5`),n>0&&console.log(` inspect: ${b("warnings")} 5`),!$.includeTail||s===0)return;let u=await fe(d,5);if(!(!Array.isArray(u)||u.length===0)){console.log(`
338
+ note: ${o.label} is open${t} \u2014 taps/drags hit it, not the app`)}}async function ee($={}){let o=$.counts!==void 0?$.counts:await u.send({type:"evaluate",code:ke});if(!o||typeof o!="object")return;let t=o,s=Math.max(0,Number(t.errors)||0),n=Math.max(0,Number(t.warnings)||0);if(s===0&&n===0||!$.includeTail&&!Je("console",G,`${s}:${n}`))return;let c=[];if(s>0&&c.push(`${s} console error${s===1?"":"s"}`),n>0&&c.push(`${n} console warning${n===1?"":"s"}`),console.log(`
339
+ console: ${c.join(", ")}`),console.log(` inspect: ${b("errors")} 5`),n>0&&console.log(` inspect: ${b("warnings")} 5`),!$.includeTail||s===0)return;let d=await fe(u,5);if(!(!Array.isArray(d)||d.length===0)){console.log(`
340
340
  recent console errors:
341
- `);for(let p of u){let h=ae(p.timestamp),f=Array.isArray(p.args)?p.args.map(x=>typeof x=="object"?JSON.stringify(x):String(x)).join(" "):String(p);console.log(` [${h}] ${f}`)}}}let ie=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function xe($){let o=Ve(),t=null;try{t=await St($,`(() => {
341
+ `);for(let p of d){let h=ae(p.timestamp),f=Array.isArray(p.args)?p.args.map(x=>typeof x=="object"?JSON.stringify(x):String(x)).join(" "):String(p);console.log(` [${h}] ${f}`)}}}let ie=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function xe($){let o=Ve(),t=null;try{t=await St($,`(() => {
342
342
  const tl = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.timeline
343
343
  if (!tl || typeof tl.summary !== 'function') return null
344
344
  const cursorKey = ${JSON.stringify(o)}
@@ -354,9 +354,9 @@ ${t}
354
354
  }
355
355
  }
356
356
  return summary ? { summary, consoleSplit } : null
357
- })()`)}catch{return}if(!t||!t.summary||!t.summary.total)return;let s=t.summary.byKind??{},n=[],c=new Set;for(let u of ie){let p=s[u];if(p)if(c.add(u),u==="console"&&t.consoleSplit){let{error:h,warn:f}=t.consoleSplit;h>0&&n.push(`${h} error${h===1?"":"s"}`),f>0&&n.push(`${f} warning${f===1?"":"s"}`)}else n.push(`${p} ${u}${p===1?"":"s"}`)}for(let[u,p]of Object.entries(s))!c.has(u)&&p&&n.push(`${p} ${u}${p===1?"":"s"}`);if(n.length!==0&&(console.log(`
358
- since last: ${n.join(" \xB7 ")} \u2014 sootsim what-happened`),t.summary.lastAt))try{await Te($,"SootSim.bridges.timeline.cursorAdvance",o,t.summary.lastAt)}catch{}}let C=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"]),ce=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"]),$e=(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)),C.has(g)&&await $t(d),ce.has(g)&&await ue(d,{verbose:$e});try{let $=C.has(g)&&!A(l)?await gt(d):[];switch(g){case"list":{await Wt({bridge:d,simId:N,args:l});break}case"tree":{await zt({bridge:d,args:l,positional:i});break}case"a11y":{let o=await rt(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):
359
- `);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 jt({bridge:d,args:e,effectiveArgs:l,positional:i,inspectUsage:T});break}case"count":{await Ct(d,{args:l});break}case"keyboard":{await Jt(d,{json:e.includes("--json")});break}case"screens":{await Ht(d,{json:e.includes("--json")});break}case"memory":{await qt(d,{args:l});break}case"wait":{await Yt({wsPort:O,commandTimeoutMs:L,simId:N,simIdSource:P,positional:i});break}case"sleep":{await Ut({positional:i,inspectUsage:T});break}case"settle":{await Kt({bridge:d,args:e,positional:i});break}case"ready":{await Zt({bridge:d,args:e});break}case"idle":{await Qt({bridge:d,args:e,positional:i});break}case"selector":{await eo({bridge:d,args:e,positional:i,inspectUsage:T});break}case"event":{await Vt({bridge:d,args:e,positional:i,inspectUsage:T});break}case"layout":{let o=i[1];if(!o){await Lt({bridge:d,args:l});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((h,f)=>e[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await io(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 io(e,d);o||(console.error(T("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:_t(o)});if(e.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:n,b:c,a:u,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}, ${n}, ${c}, ${u}) ${f} ${h} samples`)}break}case"node":{let o=i[1];o||(console.error(T("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 () => {
357
+ })()`)}catch{return}if(!t||!t.summary||!t.summary.total)return;let s=t.summary.byKind??{},n=[],c=new Set;for(let d of ie){let p=s[d];if(p)if(c.add(d),d==="console"&&t.consoleSplit){let{error:h,warn:f}=t.consoleSplit;h>0&&n.push(`${h} error${h===1?"":"s"}`),f>0&&n.push(`${f} warning${f===1?"":"s"}`)}else n.push(`${p} ${d}${p===1?"":"s"}`)}for(let[d,p]of Object.entries(s))!c.has(d)&&p&&n.push(`${p} ${d}${p===1?"":"s"}`);if(n.length!==0&&(console.log(`
358
+ since last: ${n.join(" \xB7 ")} \u2014 sootsim what-happened`),t.summary.lastAt))try{await Te($,"SootSim.bridges.timeline.cursorAdvance",o,t.summary.lastAt)}catch{}}let C=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"]),ce=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"]),$e=(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)),C.has(g)&&await $t(u),ce.has(g)&&await de(u,{verbose:$e});try{let $=C.has(g)&&!A(l)?await gt(u):[];switch(g){case"list":{await Wt({bridge:u,simId:N,args:l});break}case"tree":{await zt({bridge:u,args:l,positional:i});break}case"a11y":{let o=await rt(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):
359
+ `);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 jt({bridge:u,args:e,effectiveArgs:l,positional:i,inspectUsage:T});break}case"count":{await Ct(u,{args:l});break}case"keyboard":{await Jt(u,{json:e.includes("--json")});break}case"screens":{await Ht(u,{json:e.includes("--json")});break}case"memory":{await qt(u,{args:l});break}case"wait":{await Yt({wsPort:O,commandTimeoutMs:L,simId:N,simIdSource:P,positional:i});break}case"sleep":{await Ut({positional:i,inspectUsage:T});break}case"settle":{await Kt({bridge:u,args:e,positional:i});break}case"ready":{await Zt({bridge:u,args:e});break}case"idle":{await Qt({bridge:u,args:e,positional:i});break}case"selector":{await eo({bridge:u,args:e,positional:i,inspectUsage:T});break}case"event":{await Vt({bridge:u,args:e,positional:i,inspectUsage:T});break}case"layout":{let o=i[1];if(!o){await Lt({bridge:u,args:l});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 io(e,u),n={type:"screenshot"};s&&(n.crop=s);let d=(await u.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(d,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let o=await io(e,u);o||(console.error(T("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:_t(o)});if(e.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:n,b:c,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}, ${n}, ${c}, ${d}) ${f} ${h} samples`)}break}case"node":{let o=i[1];o||(console.error(T("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 () => {
360
360
  const t = window.__sootsimTest
361
361
  const q = ${JSON.stringify(o)}
362
362
  let node = null
@@ -412,17 +412,17 @@ ${t}
412
412
  transform,
413
413
  parentChain,
414
414
  }
415
- })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(i[1]),t=Number(i[2]),s=we(e);if(s){let u=await be(d,{agent:pe(),textFallback:s.mode==="text"?s.value:void 0,resolve:async()=>{let f=await Fe(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}}),p=u.payload;(!p||typeof p.cx!="number")&&(console.error(` not found: ${s.value}`),s.mode==="testid"&&X("wait-selector-for-missing-testid",s.value),process.exit(1)),me(u.result)||(F(`${s.mode} "${s.value}"`,u),process.exit(1));let h=lo(p.cx,p.cy,u.result);h&&await J("inspect tap",h.step,h.summary),console.log(JSON.stringify({...u.attempts>1?{attempts:u.attempts}:{},...u.result},null,2));break}(!Number.isFinite(o)||!Number.isFinite(t))&&(console.error(T("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let n=await Et(d,o,t),c=lo(o,t,n);c&&await J("inspect tap",c.step,c.summary),console.log(JSON.stringify(n,null,2));break}case"drag":case"swipe":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),n=Number(i[4]),c=g==="swipe"?10:12,u=g==="swipe"?8:16,p=i[5]?Number(i[5]):c,h=i[6]?Number(i[6]):u;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(p)||!Number.isFinite(h))&&(console.error(T(g,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await d.send({type:"evaluate",code:`(async () => {
415
+ })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(i[1]),t=Number(i[2]),s=we(e);if(s){let d=await be(u,{agent:pe(),textFallback:s.mode==="text"?s.value:void 0,resolve:async()=>{let f=await Fe(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"&&X("wait-selector-for-missing-testid",s.value),process.exit(1)),me(d.result)||(F(`${s.mode} "${s.value}"`,d),process.exit(1));let h=lo(p.cx,p.cy,d.result);h&&await J("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(T("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let n=await Et(u,o,t),c=lo(o,t,n);c&&await J("inspect tap",c.step,c.summary),console.log(JSON.stringify(n,null,2));break}case"drag":case"swipe":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),n=Number(i[4]),c=g==="swipe"?10:12,d=g==="swipe"?8:16,p=i[5]?Number(i[5]):c,h=i[6]?Number(i[6]):d;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(p)||!Number.isFinite(h))&&(console.error(T(g,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await u.send({type:"evaluate",code:`(async () => {
416
416
  const interact = window.__sootsimInteract
417
417
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
418
418
  const value = await interact.drag(${o}, ${t}, ${s}, ${n}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(h))})
419
419
  return { ok: !!value, value }
420
- })()`});if(f?.ok){let x=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,h)));await J(`inspect ${g}`,{swipe:{start:`${o}, ${t}`,end:`${s}, ${n}`,duration:x}},`${g} ${o},${t} -> ${s},${n}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),n=Number(i[4]),c=Number(i[5]),u=Number(i[6]),p=Number(i[7]),h=Number(i[8]),f=i[9]?Number(i[9]):12,x=i[10]?Number(i[10]):16;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(c)||!Number.isFinite(u)||!Number.isFinite(p)||!Number.isFinite(h)||!Number.isFinite(f)||!Number.isFinite(x))&&(console.error(T("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let R=await d.send({type:"evaluate",code:`(async () => {
420
+ })()`});if(f?.ok){let x=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,h)));await J(`inspect ${g}`,{swipe:{start:`${o}, ${t}`,end:`${s}, ${n}`,duration:x}},`${g} ${o},${t} -> ${s},${n}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),n=Number(i[4]),c=Number(i[5]),d=Number(i[6]),p=Number(i[7]),h=Number(i[8]),f=i[9]?Number(i[9]):12,x=i[10]?Number(i[10]):16;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(c)||!Number.isFinite(d)||!Number.isFinite(p)||!Number.isFinite(h)||!Number.isFinite(f)||!Number.isFinite(x))&&(console.error(T("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let R=await u.send({type:"evaluate",code:`(async () => {
421
421
  const interact = window.__sootsimInteract
422
422
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
423
- const value = await interact.pinch(${o}, ${t}, ${s}, ${n}, ${c}, ${u}, ${p}, ${h}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(x))})
423
+ const value = await interact.pinch(${o}, ${t}, ${s}, ${n}, ${c}, ${d}, ${p}, ${h}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(x))})
424
424
  return { ok: !!value, value }
425
- })()`});R?.ok&&await J("inspect pinch",{pinch:{from:[o,t,s,n],to:[c,u,p,h],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(x))}},`pinch (${o},${t}) (${s},${n}) -> (${c},${u}) (${p},${h})`),console.log(JSON.stringify(R,null,2));break}case"tap-text":{let o=i[1];o||(console.error(T("tap-text","<text>")),process.exit(1));let t=z=>{let D=e.indexOf(z);return D>=0&&D+1<e.length?e[D+1]:null},s=z=>e.includes(z),n=t("--nth")??t("--index"),c=n!==null?Number(n):null;c!==null&&!Number.isFinite(c)&&(console.error(` --nth/--index requires an integer, got: ${n}`),process.exit(1));let u=t("--within"),p=t("--role"),h=s("--exact"),f=s("--first"),x=t("--min-y"),R=t("--max-y"),H=t("--min-x"),K=t("--max-x");for(let[z,D]of[["--min-y",x],["--max-y",R],["--min-x",H],["--max-x",K]])D!==null&&!Number.isFinite(Number(D))&&(console.error(` ${z} requires a number, got: ${D}`),process.exit(1));let U=e.indexOf("--near"),_=null;if(U>=0){let z=Number(e[U+1]),D=Number(e[U+2]);(!Number.isFinite(z)||!Number.isFinite(D))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),_={x:z,y:D}}let w={exact:h,role:p,within:u,minX:H!==null?Number(H):null,maxX:K!==null?Number(K):null,minY:x!==null?Number(x):null,maxY:R!==null?Number(R):null,near:_,nth:c,first:f},S=await Rt(d,o,w,{agent:pe()}),k=S.payload;if(k?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),k?.ambiguous){let z=k.candidates;console.error(` ambiguous: ${k.total} matches for "${o}"`);for(let D of z){let Se=D.abs?`@(${Math.round(D.abs.x)},${Math.round(D.abs.y)})`:"",po=D.layout?` ${D.layout.width}x${D.layout.height}`:"",fo=D.testID?` #${D.testID}`:"",go=D.text?` "${D.text}"`:"",yo=D.ancestorTestIDs.length>0?` within ${D.ancestorTestIDs.slice(0,3).map(bo=>`#${bo}`).join(" > ")}`:"";console.error(` [${D.idx}] <${D.type}>${go}${fo} ${Se}${po}${yo}`)}k.total>z.length&&console.error(` ... and ${k.total-z.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)}k?.nthOutOfRange&&(console.error(` not found: nth ${k.nth} of ${k.total} match${k.total===1?"":"es"} for "${o}"`),process.exit(1)),(!k||typeof k.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),me(S.result)||(F(`text "${o}"`,S),process.exit(1));let ne=ze(o,{id:k.target?.id??null,testID:k.target?.testID??null,type:k.target?.type??null,cx:k.cx,cy:k.cy},"text");await J("inspect tap-text",ne.step,ne.summary),console.log(JSON.stringify({matched:k.match,tapped:{nodeId:k.target?.nodeId??null,id:k.target?.id??null,testID:k.target?.testID??null,type:k.target?.type??null,cx:k.cx,cy:k.cy},...k.strategy&&k.strategy!=="matched-node"?{strategy:k.strategy}:{},...k.total>1||c!==null?{nth:{index:k.idx,total:k.total}}:{},...S.attempts>1?{attempts:S.attempts}:{},result:S.result},null,2));break}case"tap-best":{let o=i[1];o||(console.error(T("tap-best","<query>")),process.exit(1));let t=await Dt(d,o,{agent:pe()}),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;me(t.result)||(F(`best "${o}"`,t),process.exit(1));let c=ze(o,{id:n.id,testID:n.testID,type:n.type,cx:s.cx,cy:s.cy},s.strategy==="testid"?"id":"text");await J("inspect tap-best",c.step,c.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=i[1];o||(console.error(T("tap-id","<id>")),process.exit(1));let t=await Pt(d,o,{agent:pe()}),s=t.payload;(!s||typeof s.cx!="number")&&(console.error(` not found: ${o}`),await Jo(d,o),process.exit(1)),me(t.result)||(F(`id "${o}"`,t),process.exit(1));let n=ze(o,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await J("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=i[1],t=i.slice(2).join(" ");(!o||!t)&&(console.error(T("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(o),n=await d.send({type:"evaluate",code:`(async () => {
425
+ })()`});R?.ok&&await J("inspect pinch",{pinch:{from:[o,t,s,n],to:[c,d,p,h],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(x))}},`pinch (${o},${t}) (${s},${n}) -> (${c},${d}) (${p},${h})`),console.log(JSON.stringify(R,null,2));break}case"tap-text":{let o=i[1];o||(console.error(T("tap-text","<text>")),process.exit(1));let t=z=>{let D=e.indexOf(z);return D>=0&&D+1<e.length?e[D+1]:null},s=z=>e.includes(z),n=t("--nth")??t("--index"),c=n!==null?Number(n):null;c!==null&&!Number.isFinite(c)&&(console.error(` --nth/--index requires an integer, got: ${n}`),process.exit(1));let d=t("--within"),p=t("--role"),h=s("--exact"),f=s("--first"),x=t("--min-y"),R=t("--max-y"),H=t("--min-x"),K=t("--max-x");for(let[z,D]of[["--min-y",x],["--max-y",R],["--min-x",H],["--max-x",K]])D!==null&&!Number.isFinite(Number(D))&&(console.error(` ${z} requires a number, got: ${D}`),process.exit(1));let U=e.indexOf("--near"),_=null;if(U>=0){let z=Number(e[U+1]),D=Number(e[U+2]);(!Number.isFinite(z)||!Number.isFinite(D))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),_={x:z,y:D}}let w={exact:h,role:p,within:d,minX:H!==null?Number(H):null,maxX:K!==null?Number(K):null,minY:x!==null?Number(x):null,maxY:R!==null?Number(R):null,near:_,nth:c,first:f},S=await Rt(u,o,w,{agent:pe()}),k=S.payload;if(k?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),k?.ambiguous){let z=k.candidates;console.error(` ambiguous: ${k.total} matches for "${o}"`);for(let D of z){let Se=D.abs?`@(${Math.round(D.abs.x)},${Math.round(D.abs.y)})`:"",po=D.layout?` ${D.layout.width}x${D.layout.height}`:"",fo=D.testID?` #${D.testID}`:"",go=D.text?` "${D.text}"`:"",yo=D.ancestorTestIDs.length>0?` within ${D.ancestorTestIDs.slice(0,3).map(bo=>`#${bo}`).join(" > ")}`:"";console.error(` [${D.idx}] <${D.type}>${go}${fo} ${Se}${po}${yo}`)}k.total>z.length&&console.error(` ... and ${k.total-z.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)}k?.nthOutOfRange&&(console.error(` not found: nth ${k.nth} of ${k.total} match${k.total===1?"":"es"} for "${o}"`),process.exit(1)),(!k||typeof k.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),me(S.result)||(F(`text "${o}"`,S),process.exit(1));let ne=ze(o,{id:k.target?.id??null,testID:k.target?.testID??null,type:k.target?.type??null,cx:k.cx,cy:k.cy},"text");await J("inspect tap-text",ne.step,ne.summary),console.log(JSON.stringify({matched:k.match,tapped:{nodeId:k.target?.nodeId??null,id:k.target?.id??null,testID:k.target?.testID??null,type:k.target?.type??null,cx:k.cx,cy:k.cy},...k.strategy&&k.strategy!=="matched-node"?{strategy:k.strategy}:{},...k.total>1||c!==null?{nth:{index:k.idx,total:k.total}}:{},...S.attempts>1?{attempts:S.attempts}:{},result:S.result},null,2));break}case"tap-best":{let o=i[1];o||(console.error(T("tap-best","<query>")),process.exit(1));let t=await Dt(u,o,{agent:pe()}),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;me(t.result)||(F(`best "${o}"`,t),process.exit(1));let c=ze(o,{id:n.id,testID:n.testID,type:n.type,cx:s.cx,cy:s.cy},s.strategy==="testid"?"id":"text");await J("inspect tap-best",c.step,c.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=i[1];o||(console.error(T("tap-id","<id>")),process.exit(1));let t=await Pt(u,o,{agent:pe()}),s=t.payload;(!s||typeof s.cx!="number")&&(console.error(` not found: ${o}`),await Jo(u,o),process.exit(1)),me(t.result)||(F(`id "${o}"`,t),process.exit(1));let n=ze(o,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await J("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=i[1],t=i.slice(2).join(" ");(!o||!t)&&(console.error(T("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(o),n=await u.send({type:"evaluate",code:`(async () => {
426
426
  const t = window.__sootsimTest
427
427
  if (!t) return null
428
428
  const n = await (t.findByTestId(${s}) || t.findById(${s}))
@@ -437,7 +437,7 @@ ${t}
437
437
  secureTextEntry: !!n.secureTextEntry,
438
438
  placeholder: n.placeholder || null,
439
439
  }
440
- })()`});(!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 c=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,p=await Xo(d,1e3,{targetId:o,secureTextEntry:u});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 d.send({type:"keyboard",action:"type",text:t});let f=u||he(p),x=f?V:He(t,p),R=f&&p.focusedInput?{...p.focusedInput,secureTextEntry:!0,text:typeof p.focusedInput.text=="string"?V:p.focusedInput.text}:p.focusedInput??null;await J("inspect type-into",{tapOn:{id:o},inputText:x},x===V?`type-into #${o} ${V}`:`type-into #${o} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:o,isTextInput:n.isTextInput,secureTextEntry:f,keyboardOpened:p.visible??c?.keyboardOpened??!1,focusedInput:R,typed:x},null,2));break}case"type":{let o=i.slice(1).join(" ");o||(console.error(T("type","<text>")),process.exit(1));let t=await Ae(d,"type");await d.send({type:"keyboard",action:"type",text:o});let s=He(o,t);await J("inspect type",{inputText:s},s===V?`type ${V}`:`type ${JSON.stringify(o)}`),console.log(s===V?` typed: ${V}`:` typed: ${JSON.stringify(o)}`);break}case"key":{let o=i[1];o||(console.error(T("key","<name>")),process.exit(1)),await Ae(d,"key"),await d.send({type:"keyboard",action:"press",text:o}),await J("inspect key",{pressKey:o},`key ${o}`),console.log(` pressed: ${o}`);break}case"key-sequence":{let o=i.slice(1);o.length===0&&(console.error(T("key-sequence","<key> [<key> ...]")),process.exit(1)),await Ae(d,"key-sequence");for(let t of o)await d.send({type:"keyboard",action:"press",text:t});await J("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(T("keycode","<code> [<code> ...]")),process.exit(1));let t=o.map(n=>({code:n,key:Vo(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 Ae(d,"keycode");for(let n of t)await d.send({type:"keyboard",action:"press",text:n.key});await J("inspect keycode",{pressKey:t.map(n=>n.key).join(" ")},`keycode ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"dispatch":{let o=i[1];o||(console.error(T("dispatch","<char>")),process.exit(1)),await d.send({type:"keyboard",action:"dispatchKey",text:o}),await J("inspect dispatch",{dispatchKey:o},`dispatch ${JSON.stringify(o)}`),console.log(` dispatched: ${o}`);break}case"dismiss":{await d.send({type:"keyboard",action:"dismiss"}),await J("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let o=Number(i[1]),t=Number(i[2]),s=we(e);if(s){let p=await Fe(d,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&X("wait-selector-for-missing-testid",s.value),process.exit(1)),o=p.x,t=p.y}let n=i[3]?Number(i[3]):80;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(n))&&(console.error(T("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let c=Math.max(0,Math.round(n)),u=await d.send({type:"evaluate",code:`(async () => {
440
+ })()`});(!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 c=await u.send({type:"tap",x:n.cx,y:n.cy,target:{id:n.id??o,testID:n.testID??o,text:null,type:n.type??null}}),d=n.secureTextEntry===!0,p=await Xo(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),x=f?V:He(t,p),R=f&&p.focusedInput?{...p.focusedInput,secureTextEntry:!0,text:typeof p.focusedInput.text=="string"?V:p.focusedInput.text}:p.focusedInput??null;await J("inspect type-into",{tapOn:{id:o},inputText:x},x===V?`type-into #${o} ${V}`:`type-into #${o} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:o,isTextInput:n.isTextInput,secureTextEntry:f,keyboardOpened:p.visible??c?.keyboardOpened??!1,focusedInput:R,typed:x},null,2));break}case"type":{let o=i.slice(1).join(" ");o||(console.error(T("type","<text>")),process.exit(1));let t=await Ae(u,"type");await u.send({type:"keyboard",action:"type",text:o});let s=He(o,t);await J("inspect type",{inputText:s},s===V?`type ${V}`:`type ${JSON.stringify(o)}`),console.log(s===V?` typed: ${V}`:` typed: ${JSON.stringify(o)}`);break}case"key":{let o=i[1];o||(console.error(T("key","<name>")),process.exit(1)),await Ae(u,"key"),await u.send({type:"keyboard",action:"press",text:o}),await J("inspect key",{pressKey:o},`key ${o}`),console.log(` pressed: ${o}`);break}case"key-sequence":{let o=i.slice(1);o.length===0&&(console.error(T("key-sequence","<key> [<key> ...]")),process.exit(1)),await Ae(u,"key-sequence");for(let t of o)await u.send({type:"keyboard",action:"press",text:t});await J("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(T("keycode","<code> [<code> ...]")),process.exit(1));let t=o.map(n=>({code:n,key:Vo(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 Ae(u,"keycode");for(let n of t)await u.send({type:"keyboard",action:"press",text:n.key});await J("inspect keycode",{pressKey:t.map(n=>n.key).join(" ")},`keycode ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"dispatch":{let o=i[1];o||(console.error(T("dispatch","<char>")),process.exit(1)),await u.send({type:"keyboard",action:"dispatchKey",text:o}),await J("inspect dispatch",{dispatchKey:o},`dispatch ${JSON.stringify(o)}`),console.log(` dispatched: ${o}`);break}case"dismiss":{await u.send({type:"keyboard",action:"dismiss"}),await J("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let o=Number(i[1]),t=Number(i[2]),s=we(e);if(s){let p=await Fe(u,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&X("wait-selector-for-missing-testid",s.value),process.exit(1)),o=p.x,t=p.y}let n=i[3]?Number(i[3]):80;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(n))&&(console.error(T("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let c=Math.max(0,Math.round(n)),d=await u.send({type:"evaluate",code:`(async () => {
441
441
  const interact = window.__sootsimInteract
442
442
  if (interact?.doubleTap) {
443
443
  return {
@@ -460,13 +460,13 @@ ${t}
460
460
  first,
461
461
  second,
462
462
  }
463
- })()`});u?.ok&&await J("inspect double-tap",{doubleTapAtCoords:{x:o,y:t,gapMs:c}},`double-tap @${o},${t}`),console.log(JSON.stringify(u,null,2));break}case"long-press":{let o=Number(i[1]),t=Number(i[2]),s=we(e),n=null;if(s){let f=await Fe(d,s);f||(console.error(` not found: ${s.value}`),s.mode==="testid"&&X("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 c=s?i[1]:i[3],u=c?Number(c):600;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(u))&&(console.error(T("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let p=Math.max(0,Math.round(u)),h=await d.send({type:"longPress",x:o,y:t,durationMs:p,target:n});h?.ok&&await J("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]),n=i[4]?Number(i[4]):999,c=o==="down"?"touchDown":o==="move"?"touchMove":o==="up"?"touchUp":o==="cancel"?"touchCancel":null;c||(console.error(T("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),o!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(T("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let u=o==="down"?"tap":o==="move"?"move":null,p=u&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${u}', x: ${t}, y: ${s} } }));`:"",h=await d.send({type:"evaluate",code:`(async () => {
463
+ })()`});d?.ok&&await J("inspect double-tap",{doubleTapAtCoords:{x:o,y:t,gapMs:c}},`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=we(e),n=null;if(s){let f=await Fe(u,s);f||(console.error(` not found: ${s.value}`),s.mode==="testid"&&X("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 c=s?i[1]:i[3],d=c?Number(c):600;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(d))&&(console.error(T("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:n});h?.ok&&await J("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]),n=i[4]?Number(i[4]):999,c=o==="down"?"touchDown":o==="move"?"touchMove":o==="up"?"touchUp":o==="cancel"?"touchCancel":null;c||(console.error(T("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),o!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(T("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 () => {
464
464
  ${p}
465
465
  const interact = window.__sootsimInteract
466
466
  if (!interact?.${c}) return { ok: false, reason: 'no interact.${c}' }
467
467
  const value = ${o==="cancel"?`await interact.${c}(${Math.max(1,Math.round(n))})`:`await interact.${c}(${t}, ${s}, ${Math.max(1,Math.round(n))})`}
468
468
  return { ok: !!value, value }
469
- })()`});h?.ok&&o!=="cancel"&&await J("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(T("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 () => {
469
+ })()`});h?.ok&&o!=="cancel"&&await J("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(T("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 u.send({type:"evaluate",code:`(async () => {
470
470
  const spec = globalThis.__sootsimDeviceSpec || {}
471
471
  return {
472
472
  width: spec.width || window.innerWidth || 393,
@@ -474,12 +474,12 @@ ${t}
474
474
  statusBarHeight: spec.statusBarHeight || 0,
475
475
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
476
476
  }
477
- })()`}),c=Number(n?.width)||393,u=Number(n?.height)||852,p=Number(n?.statusBarHeight)||0,h=Number(n?.homeIndicatorHeight)||0,f=Math.round(c/2),x=Math.round(u/2),R=Math.max(24,p+18),H=Math.max(24,h+18),K=18,U=Math.min(220,Math.round(u*.24)),_=Math.min(180,Math.round(c*.32)),w=f,S=x,k=f,ne=x;switch(t){case"scroll-up":S=x+Math.round(U/2),ne=x-Math.round(U/2);break;case"scroll-down":S=x-Math.round(U/2),ne=x+Math.round(U/2);break;case"scroll-left":w=f+Math.round(_/2),k=f-Math.round(_/2);break;case"scroll-right":w=f-Math.round(_/2),k=f+Math.round(_/2);break;case"swipe-from-left-edge":w=K,S=x,k=Math.min(c-K,K+_);break;case"swipe-from-right-edge":w=c-K,S=x,k=Math.max(K,c-K-_);break;case"swipe-from-top-edge":w=f,S=R,ne=Math.min(u-H,R+U);break;case"swipe-from-bottom-edge":w=f,S=u-H,ne=Math.max(R,u-H-U);break}let z=Math.max(8,Math.round(s/16)),D=Math.max(1,Math.round(s/z)),Se=await d.send({type:"evaluate",code:`(async () => {
477
+ })()`}),c=Number(n?.width)||393,d=Number(n?.height)||852,p=Number(n?.statusBarHeight)||0,h=Number(n?.homeIndicatorHeight)||0,f=Math.round(c/2),x=Math.round(d/2),R=Math.max(24,p+18),H=Math.max(24,h+18),K=18,U=Math.min(220,Math.round(d*.24)),_=Math.min(180,Math.round(c*.32)),w=f,S=x,k=f,ne=x;switch(t){case"scroll-up":S=x+Math.round(U/2),ne=x-Math.round(U/2);break;case"scroll-down":S=x-Math.round(U/2),ne=x+Math.round(U/2);break;case"scroll-left":w=f+Math.round(_/2),k=f-Math.round(_/2);break;case"scroll-right":w=f-Math.round(_/2),k=f+Math.round(_/2);break;case"swipe-from-left-edge":w=K,S=x,k=Math.min(c-K,K+_);break;case"swipe-from-right-edge":w=c-K,S=x,k=Math.max(K,c-K-_);break;case"swipe-from-top-edge":w=f,S=R,ne=Math.min(d-H,R+U);break;case"swipe-from-bottom-edge":w=f,S=d-H,ne=Math.max(R,d-H-U);break}let z=Math.max(8,Math.round(s/16)),D=Math.max(1,Math.round(s/z)),Se=await u.send({type:"evaluate",code:`(async () => {
478
478
  const interact = window.__sootsimInteract
479
479
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
480
480
  const value = await interact.drag(${w}, ${S}, ${k}, ${ne}, ${z}, ${D})
481
481
  return { ok: !!value, value }
482
- })()`});Se?.ok&&await J("inspect gesture",{swipe:{start:`${w}, ${S}`,end:`${k}, ${ne}`,duration:Math.max(1,Math.round(s))}},`gesture ${t}`),console.log(JSON.stringify({preset:t,from:{x:w,y:S},to:{x:k,y:ne},result:Se},null,2));break}case"scroll":{let o=we(e),t=Zo(e),s=o?.mode==="testid"?o.value:t==null?i[1]:null,n=o||t!=null?1:2,c=Number(i[n]),u=Number(i[n+1]);(!s&&t==null||!Number.isFinite(c)||!Number.isFinite(u))&&(console.error(T("scroll","<id> <x> <y> | --testid <id> <x> <y> | --node-id <nodeId> <x> <y>")),process.exit(1));let p=await d.send({type:"evaluate",code:`(async () => {
482
+ })()`});Se?.ok&&await J("inspect gesture",{swipe:{start:`${w}, ${S}`,end:`${k}, ${ne}`,duration:Math.max(1,Math.round(s))}},`gesture ${t}`),console.log(JSON.stringify({preset:t,from:{x:w,y:S},to:{x:k,y:ne},result:Se},null,2));break}case"scroll":{let o=we(e),t=Zo(e),s=o?.mode==="testid"?o.value:t==null?i[1]:null,n=o||t!=null?1:2,c=Number(i[n]),d=Number(i[n+1]);(!s&&t==null||!Number.isFinite(c)||!Number.isFinite(d))&&(console.error(T("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 () => {
483
483
  const t = window.__sootsimTest
484
484
  if (!t) return null
485
485
  const n = ${t!=null?`await t.inspectByNodeId(${JSON.stringify(t)})`:`await t.findByTestId(${JSON.stringify(s)})
@@ -489,7 +489,7 @@ ${t}
489
489
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
490
490
  cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
491
491
  }
492
- })()`}),h=await Y(d,"scrollTo",t!=null?{nodeId:t}:s,c,u,!1);if(h?.ok){let f=t!=null?`node ${t}`:`#${s}`;await J("inspect scroll",{scrollTo:{...t!=null?{nodeId:t}:{id:s},x:c,y:u}},`scroll ${f} -> ${c},${u}`)}console.log(JSON.stringify({...h,...p?{at:{x:p.cx,y:p.cy}}:{}},null,2));break}case"state":{let o=i[1];if(r==="get"&&!o){let s=await Y(d,"getRuntimeState"),n=await d.send({type:"evaluate",code:ke});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 c=await de(d);c&&(s.shell=c)}catch{}console.log(JSON.stringify(s,null,2));break}if(!o||o==="--help"||o==="-h"){console.log(`
492
+ })()`}),h=await Y(u,"scrollTo",t!=null?{nodeId:t}:s,c,d,!1);if(h?.ok){let f=t!=null?`node ${t}`:`#${s}`;await J("inspect scroll",{scrollTo:{...t!=null?{nodeId:t}:{id:s},x:c,y:d}},`scroll ${f} -> ${c},${d}`)}console.log(JSON.stringify({...h,...p?{at:{x:p.cx,y:p.cy}}:{}},null,2));break}case"state":{let o=i[1];if(r==="get"&&!o){let s=await Y(u,"getRuntimeState"),n=await u.send({type:"evaluate",code:ke});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 c=await ue(u);c&&(s.shell=c)}catch{}console.log(JSON.stringify(s,null,2));break}if(!o||o==="--help"||o==="-h"){console.log(`
493
493
  ${b("state")} \u2014 dump raw runtime state
494
494
 
495
495
  subcommands:
@@ -513,13 +513,13 @@ ${t}
513
513
  ${b("state")} scroll feed
514
514
  ${b("state")} scroll-hit 360 420
515
515
  ${b("state")} hit 200 720
516
- `);break}let t;switch(o){case"shell":t=await de(d,500);break;case"worker":t=await Te(d,"__sootsimRenderHost.queryStats");break;case"ownership":t=await d.send({type:"evaluate",code:`(() => {
516
+ `);break}let t;switch(o){case"shell":t=await ue(u,500);break;case"worker":t=await Te(u,"__sootsimRenderHost.queryStats");break;case"ownership":t=await u.send({type:"evaluate",code:`(() => {
517
517
  const h = window.__sootsimRenderHost
518
518
  if (!h || typeof h.getOwnershipSnapshot !== 'function') {
519
519
  return { error: 'getOwnershipSnapshot not available' }
520
520
  }
521
521
  return h.getOwnershipSnapshot()
522
- })()`});break;case"keyboard":t=await d.send({type:"evaluate",code:`(async () => {
522
+ })()`});break;case"keyboard":t=await u.send({type:"evaluate",code:`(async () => {
523
523
  const kb = window.__sootsimKeyboard
524
524
  const test = window.__sootsimTest
525
525
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -547,7 +547,7 @@ ${t}
547
547
  text: secureTextEntry ? ${JSON.stringify(V)} : (focused.text || null),
548
548
  } : null,
549
549
  }
550
- })()`}),t=Ke(t);break;case"node":{let s=i[2];s||(console.error(` usage: ${b("state")} node <id>`),process.exit(1)),t=await Y(d,"findByTestId",s)||await Y(d,"findById",s);break}case"scroll":{let s=i[2];s||(console.error(` usage: ${b("state")} scroll <id>`),process.exit(1)),t=await Y(d,"getScrollState",s);break}case"scroll-hit":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} scroll-hit <x> <y>`),process.exit(1)),t=await Y(d,"getScrollStateAt",s,n);break}case"hit":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} hit <x> <y>`),process.exit(1)),t=await Y(d,"debugHitAt",s,n);break}case"gesture":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} gesture <x> <y>`),process.exit(1)),t=await Y(d,"debugGestureAt",s,n);break}case"gesture-seam":t=await Te(d,"SootSim.bridges.mainShell.callTestBridge","getShellGestureSeamDebug");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(`
550
+ })()`}),t=Ke(t);break;case"node":{let s=i[2];s||(console.error(` usage: ${b("state")} node <id>`),process.exit(1)),t=await Y(u,"findByTestId",s)||await Y(u,"findById",s);break}case"scroll":{let s=i[2];s||(console.error(` usage: ${b("state")} scroll <id>`),process.exit(1)),t=await Y(u,"getScrollState",s);break}case"scroll-hit":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} scroll-hit <x> <y>`),process.exit(1)),t=await Y(u,"getScrollStateAt",s,n);break}case"hit":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} hit <x> <y>`),process.exit(1)),t=await Y(u,"debugHitAt",s,n);break}case"gesture":{let s=Number(i[2]),n=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} gesture <x> <y>`),process.exit(1)),t=await Y(u,"debugGestureAt",s,n);break}case"gesture-seam":t=await Te(u,"SootSim.bridges.mainShell.callTestBridge","getShellGestureSeamDebug");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(`
551
551
  ${b("shell")} \u2014 run built-in shell commands
552
552
 
553
553
  subcommands:
@@ -571,7 +571,7 @@ ${t}
571
571
  ${b("shell")} open-card clock 800
572
572
  ${b("shell")} appearance dark
573
573
  ${b("shell")} lock
574
- `);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?i[3]:i[2],n=s?Number(s):350;t&&(!Number.isFinite(n)||n<0)&&(console.error(T("shell",o==="launch"||o==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let c=!1,u=!1,p=null,h=e.includes("--clear-state");if(o==="launch"){let f=i[2];f||(console.error(T("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),h&&await d.send({type:"evaluate",code:Le(!0)}),c=!!await ge(d,"launchApp",n,f),{settled:u,state:p}=await Oe(d,Math.round(n),x=>!!x&&x.state==="app"&&x.activeApp===f&&x.showSwitcher===!1&&x.switcherPhase==="idle"&&typeof x.launchProgress=="number"&&x.launchProgress>=.98),c&&await J("inspect shell launch",h?{launchApp:{clearState:!0}}:{launchApp:{}},h?"launch app (clear state)":"launch app")}else if(o==="home")c=!!await ge(d,"goHome",n),{settled:u,state:p}=await Oe(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")c=!!await ge(d,"openSwitcher",n),{settled:u,state:p}=await Oe(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 te(Go),p=await de(d));else if(o==="open-card"){let f=i[2];f||(console.error(T("shell","open-card <appId> [settleMs]")),process.exit(1)),c=!!await ge(d,"openSwitcherCard",n,f),{settled:u,state:p}=await Oe(d,Math.round(n),x=>!!x&&x.state==="app"&&x.activeApp===f&&x.showSwitcher===!1&&x.switcherPhase==="idle"&&typeof x.zoomLevel=="number"&&x.zoomLevel>=.98&&typeof x.horizontalZoom=="number"&&x.horizontalZoom>=.98),c&&await J("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(T("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let x=await ao(d,"appearance",f);if(c=!!x?.ok,p={appearance:x},c){let R=x?.applied??f;console.log(` appearance: ${R}`)}}else if(o==="lock"||o==="shake"){let f=await ao(d,o);c=!!f?.ok,p={[o]:f}}else console.error(` unknown shell subcommand: ${o}`),process.exit(1);console.log(JSON.stringify({ok:c,settled:u,state:p},null,2));break}case"url":{await Gt(d,{args:l});break}case"reload":{let s=!1,n=!1;try{await d.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await d.send({type:"evaluate",code:`;(() => {
574
+ `);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?i[3]:i[2],n=s?Number(s):350;t&&(!Number.isFinite(n)||n<0)&&(console.error(T("shell",o==="launch"||o==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let c=!1,d=!1,p=null,h=e.includes("--clear-state");if(o==="launch"){let f=i[2];f||(console.error(T("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),h&&await u.send({type:"evaluate",code:Le(!0)}),c=!!await ge(u,"launchApp",n,f),{settled:d,state:p}=await Oe(u,Math.round(n),x=>!!x&&x.state==="app"&&x.activeApp===f&&x.showSwitcher===!1&&x.switcherPhase==="idle"&&typeof x.launchProgress=="number"&&x.launchProgress>=.98),c&&await J("inspect shell launch",h?{launchApp:{clearState:!0}}:{launchApp:{}},h?"launch app (clear state)":"launch app")}else if(o==="home")c=!!await ge(u,"goHome",n),{settled:d,state:p}=await Oe(u,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")c=!!await ge(u,"openSwitcher",n),{settled:d,state:p}=await Oe(u,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),d&&(await te(Go),p=await ue(u));else if(o==="open-card"){let f=i[2];f||(console.error(T("shell","open-card <appId> [settleMs]")),process.exit(1)),c=!!await ge(u,"openSwitcherCard",n,f),{settled:d,state:p}=await Oe(u,Math.round(n),x=>!!x&&x.state==="app"&&x.activeApp===f&&x.showSwitcher===!1&&x.switcherPhase==="idle"&&typeof x.zoomLevel=="number"&&x.zoomLevel>=.98&&typeof x.horizontalZoom=="number"&&x.horizontalZoom>=.98),c&&await J("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(T("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let x=await ao(u,"appearance",f);if(c=!!x?.ok,p={appearance:x},c){let R=x?.applied??f;console.log(` appearance: ${R}`)}}else if(o==="lock"||o==="shake"){let f=await ao(u,o);c=!!f?.ok,p={[o]:f}}else console.error(` unknown shell subcommand: ${o}`),process.exit(1);console.log(JSON.stringify({ok:c,settled:d,state:p},null,2));break}case"url":{await Gt(u,{args:l});break}case"reload":{let s=!1,n=!1;try{await u.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await u.send({type:"evaluate",code:`;(() => {
575
575
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
576
576
  if (typeof reloadExternalApp === 'function') {
577
577
  reloadExternalApp()
@@ -579,13 +579,13 @@ ${t}
579
579
  }
580
580
  window.location.reload()
581
581
  return { kind: 'page' }
582
- })()`});n=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let c=d,u=null;if(n)u=await Me(d,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await te(300);let p=await kt(O,L,N,{timeoutMs:1e4,simIdSource:P});p?(c=p,u=await Me(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),c=null)}if(u)if(u.ready){let p=u.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${u.elapsedMs}ms: ${u.nodes} nodes${p}`)}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 p=oo(u);console.log(` \u26A0 reload timed out after ${u.elapsedMs}ms \u2014 ${p} (nodes: ${u.nodes}, targets: ${u.targets}, errors: ${u.errors})`)}if(c)try{let p=await fe(c,10);if(c!==d&&c.close(),Array.isArray(p)&&p.length>0){console.log(`
582
+ })()`});n=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let c=u,d=null;if(n)d=await Me(u,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await te(300);let p=await kt(O,L,N,{timeoutMs:1e4,simIdSource:P});p?(c=p,d=await Me(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),c=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=oo(d);console.log(` \u26A0 reload timed out after ${d.elapsedMs}ms \u2014 ${p} (nodes: ${d.nodes}, targets: ${d.targets}, errors: ${d.errors})`)}if(c)try{let p=await fe(c,10);if(c!==u&&c.close(),Array.isArray(p)&&p.length>0){console.log(`
583
583
  \u26A0 ${p.length} error(s) during mount:
584
584
  `);for(let h of p){let f=h.args.map(x=>typeof x=="object"?JSON.stringify(x):x).join(" ");if(console.log(` ${f}`),h.stack){let x=h.stack.split(`
585
- `).slice(0,2);for(let R of x)console.log(` ${R.trim()}`)}}}}catch{}u&&!u.ready&&(process.exitCode=1);break}case"storage-clear":{if(await Be(d),await d.send({type:"evaluate",code:Le(!0)})!==!0){A(l)?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 Me(d,{timeoutMs:1e4,errorGraceMs:3e3});if(A(l)){E({cleared:!0,ready:n.ready,reload:n}),n.ready||(process.exitCode=1);break}if(n.ready){let c=n.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` cleared tenant storage; ready in ${n.elapsedMs}ms: ${n.nodes} nodes${c}`)}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 c=oo(n);console.log(` \u26A0 storage clear reloaded but timed out after ${n.elapsedMs}ms \u2014 ${c} (nodes: ${n.nodes}, targets: ${n.targets}, errors: ${n.errors})`)}try{let c=await fe(d,10);if(Array.isArray(c)&&c.length>0){console.log(`
585
+ `).slice(0,2);for(let R of x)console.log(` ${R.trim()}`)}}}}catch{}d&&!d.ready&&(process.exitCode=1);break}case"storage-clear":{if(await Be(u),await u.send({type:"evaluate",code:Le(!0)})!==!0){A(l)?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 Me(u,{timeoutMs:1e4,errorGraceMs:3e3});if(A(l)){E({cleared:!0,ready:n.ready,reload:n}),n.ready||(process.exitCode=1);break}if(n.ready){let c=n.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` cleared tenant storage; ready in ${n.elapsedMs}ms: ${n.nodes} nodes${c}`)}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 c=oo(n);console.log(` \u26A0 storage clear reloaded but timed out after ${n.elapsedMs}ms \u2014 ${c} (nodes: ${n.nodes}, targets: ${n.targets}, errors: ${n.errors})`)}try{let c=await fe(u,10);if(Array.isArray(c)&&c.length>0){console.log(`
586
586
  \u26A0 ${c.length} error(s) during mount:
587
- `);for(let u of c){let p=u.args.map(h=>typeof h=="object"?JSON.stringify(h):h).join(" ");if(console.log(` ${p}`),u.stack){let h=u.stack.split(`
588
- `).slice(0,2);for(let f of h)console.log(` ${f.trim()}`)}}}}catch{}n.ready||(process.exitCode=1);break}case"eval":case"js":{let o=i.slice(1).join(" ");o||(console.error(T("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 d.send({type:"evaluate",code:t});console.log(JSON.stringify(s,null,2));let n=o.toLowerCase(),c=[];(n.includes("sootsim:gohome")||n.includes("gohome"))&&c.push("sootsim shell home"),(n.includes("sootsim:appswitcher")||n.includes("appswitcher"))&&c.push("sootsim shell switcher"),(n.includes("keyboard.isvisible")||n.includes("keyboard.getmode"))&&c.push("sootsim debug state keyboard"),n.includes("interact.tap")&&c.push("sootsim do tap <x> <y>"),n.includes("keyboard.type")&&c.push("sootsim do type <text>"),(n.includes("keyboard.press")||n.includes("keyboard.dispatchkey"))&&c.push("sootsim do key <name>"),n.includes("keyboard.dismiss")&&c.push("sootsim do dismiss"),n.includes("dumptree")&&c.push("sootsim get tree"),n.includes("dumpaccessibilitytree")&&c.push("sootsim get a11y"),n.includes("getnodecount")&&c.push("sootsim get count"),n.includes("findbytext")&&c.push("sootsim find <text>"),(n.includes("findbytestid")||n.includes("findbyid"))&&c.push("sootsim find --testid <id>"),n.includes("document.hidden")&&c.push("sootsim debug state keyboard (includes tab health)"),c.length>0&&X("prefer-cli-over-eval",c);break}case"globals":{let o=await d.send({type:"evaluate",code:`(async () => {
587
+ `);for(let d of c){let p=d.args.map(h=>typeof h=="object"?JSON.stringify(h):h).join(" ");if(console.log(` ${p}`),d.stack){let h=d.stack.split(`
588
+ `).slice(0,2);for(let f of h)console.log(` ${f.trim()}`)}}}}catch{}n.ready||(process.exitCode=1);break}case"eval":case"js":{let o=i.slice(1).join(" ");o||(console.error(T("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 n=o.toLowerCase(),c=[];(n.includes("sootsim:gohome")||n.includes("gohome"))&&c.push("sootsim shell home"),(n.includes("sootsim:appswitcher")||n.includes("appswitcher"))&&c.push("sootsim shell switcher"),(n.includes("keyboard.isvisible")||n.includes("keyboard.getmode"))&&c.push("sootsim debug state keyboard"),n.includes("interact.tap")&&c.push("sootsim do tap <x> <y>"),n.includes("keyboard.type")&&c.push("sootsim do type <text>"),(n.includes("keyboard.press")||n.includes("keyboard.dispatchkey"))&&c.push("sootsim do key <name>"),n.includes("keyboard.dismiss")&&c.push("sootsim do dismiss"),n.includes("dumptree")&&c.push("sootsim get tree"),n.includes("dumpaccessibilitytree")&&c.push("sootsim get a11y"),n.includes("getnodecount")&&c.push("sootsim get count"),n.includes("findbytext")&&c.push("sootsim find <text>"),(n.includes("findbytestid")||n.includes("findbyid"))&&c.push("sootsim find --testid <id>"),n.includes("document.hidden")&&c.push("sootsim debug state keyboard (includes tab health)"),c.length>0&&X("prefer-cli-over-eval",c);break}case"globals":{let o=await u.send({type:"evaluate",code:`(async () => {
589
589
  const globals = {}
590
590
 
591
591
  // test bridge (proxy in worker mode)
@@ -623,7 +623,7 @@ ${t}
623
623
 
624
624
  return globals
625
625
  })()`});console.log(` sootsim JS API:
626
- `);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let n of s)console.log(` .${n}`);console.log("")}console.log(` use: ${b("js")} <expression>`),console.log(` example: ${b("js")} test.findByText("Sign in")`);break}case"describe":{await Bt({bridge:d,args:e,positional:i});break}case"perf":{let o=i[1];if(!o||o==="--help"||o==="-h"){console.log(`
626
+ `);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let n of s)console.log(` .${n}`);console.log("")}console.log(` use: ${b("js")} <expression>`),console.log(` example: ${b("js")} test.findByText("Sign in")`);break}case"describe":{await Bt({bridge:u,args:e,positional:i});break}case"perf":{let o=i[1];if(!o||o==="--help"||o==="-h"){console.log(`
627
627
  ${b("perf")} \u2014 performance profiling
628
628
 
629
629
  subcommands:
@@ -644,7 +644,7 @@ ${t}
644
644
  ${b("perf")} stop
645
645
  ${b("perf")} stop --json
646
646
  ${b("perf")} transition goHome
647
- `);break}switch(o){case"stats":{let t=await d.send({type:"evaluate",code:`(async () => {
647
+ `);break}switch(o){case"stats":{let t=await u.send({type:"evaluate",code:`(async () => {
648
648
  // worker mode (host exposes these)
649
649
  if (window.__sootsimPerfStats) {
650
650
  return await window.__sootsimPerfStats()
@@ -675,7 +675,7 @@ ${t}
675
675
  # \u2026 interact / run a flow / wait for the transition \u2026
676
676
  sootsim debug perf stop # full report
677
677
  sootsim debug perf stats # one-shot snapshot
678
- `);break}case"start":{await d.send({type:"evaluate",code:`(async () => {
678
+ `);break}case"start":{await u.send({type:"evaluate",code:`(async () => {
679
679
  // worker mode
680
680
  if (window.__sootsimPerfStart && window.__sootsimRenderHost) {
681
681
  const result = window.__sootsimPerfStart()
@@ -697,7 +697,7 @@ ${t}
697
697
  startedAt: performance.now(),
698
698
  }
699
699
  return { started: true }
700
- })()`}),console.log(` profiling started \u2014 interact with the app, then run '${b("perf")} stop'`);break}case"stop":{let t=await d.send({type:"evaluate",code:`(async () => {
700
+ })()`}),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 () => {
701
701
  // worker mode
702
702
  if (window.__sootsimRenderHost) {
703
703
  const session = window.${re} || {}
@@ -792,7 +792,7 @@ ${t}
792
792
  sampleCount: recent.length,
793
793
  }
794
794
  })()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(l)){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:
795
- `),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=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 d.send({type:"evaluate",code:`(async () => {
795
+ `),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=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 () => {
796
796
  if (window.__sootsimRenderHost) {
797
797
  const session = window.${re} || {}
798
798
  if (session.active) {
@@ -827,7 +827,7 @@ ${t}
827
827
  mode: 'main-thread',
828
828
  frames: (stats.recentFrames || []).slice(-${t}),
829
829
  }
830
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(l)){E(s);break}if(s.mode==="render-worker"){let c=Array.isArray(s.samples)?s.samples:[];if(c.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` last ${c.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,p,h,f,x,R,H]of c)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${R.toFixed(2).padStart(6)} ${H.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);console.log(""),Ue(c.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 '${b("perf")} start' first`);break}console.log(` last ${n.length} frame times (ms):`),console.log(` ${n.map(c=>c.toFixed(2)).join(", ")}`),Ue(n);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 d.send({type:"evaluate",code:`(async () => {
830
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(l)){E(s);break}if(s.mode==="render-worker"){let c=Array.isArray(s.samples)?s.samples:[];if(c.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` last ${c.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,h,f,x,R,H]of c)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${R.toFixed(2).padStart(6)} ${H.toFixed(2).padStart(7)} ${String(d).padStart(5)}`);console.log(""),Ue(c.map(d=>d[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 '${b("perf")} start' first`);break}console.log(` last ${n.length} frame times (ms):`),console.log(` ${n.map(c=>c.toFixed(2)).join(", ")}`),Ue(n);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 () => {
831
831
  if (window.__sootsimRenderHost) {
832
832
  const session = window.${re} || {}
833
833
  if (session.active) {
@@ -869,7 +869,7 @@ ${t}
869
869
  mode: 'main-thread',
870
870
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${t}),
871
871
  }
872
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(l)){E(s);break}if(s.mode==="render-worker"){let c=Array.isArray(s.samples)?s.samples:[];if(c.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${c.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,p,h,f,x,R,H]of c)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${R.toFixed(2).padStart(6)} ${H.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 '${b("perf")} start' first`);break}console.log(` worst ${n.length} frame times (ms):`),console.log(` ${n.map(c=>c.toFixed(2)).join(", ")}`);break}case"transition":{let t=i[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
872
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(l)){E(s);break}if(s.mode==="render-worker"){let c=Array.isArray(s.samples)?s.samples:[];if(c.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${c.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,h,f,x,R,H]of c)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${R.toFixed(2).padStart(6)} ${H.toFixed(2).padStart(7)} ${String(d).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 '${b("perf")} start' first`);break}console.log(` worst ${n.length} frame times (ms):`),console.log(` ${n.map(c=>c.toFixed(2)).join(", ")}`);break}case"transition":{let t=i[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
873
873
  ${b("perf")} transition <event> \u2014 profile a shell transition
874
874
 
875
875
  events:
@@ -882,7 +882,7 @@ ${t}
882
882
  examples:
883
883
  ${b("perf")} transition goHome --timeout 10000
884
884
  ${b("perf")} transition appSwitcher
885
- `);break}let n=`sootsim:${t}`;je(` profiling ${t} transition...`),je(" (use --timeout 10000 if this times out)");let c=await d.send({type:"evaluate",code:`(async () => {
885
+ `);break}let n=`sootsim:${t}`;je(` profiling ${t} transition...`),je(" (use --timeout 10000 if this times out)");let c=await u.send({type:"evaluate",code:`(async () => {
886
886
  // only supported in render-worker mode
887
887
  if (!window.__sootsimRenderHost) {
888
888
  return { error: 'transition profiling requires render-worker mode' }
@@ -941,11 +941,11 @@ ${t}
941
941
  jankFrames: frameTimes.filter(f => f > 16.67).length,
942
942
  samples,
943
943
  }
944
- })()`});if(c.error&&(console.error(` error: ${c.error}`),process.exit(1)),A(l)){E(c);break}if(c.warning&&console.log(` warning: ${c.warning}`),c.frames===0){console.log(" no frames captured");break}let u=c.avgMs>0?(1e3/c.avgMs).toFixed(1):"?",p=c.frames>0?(c.jankFrames/c.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
944
+ })()`});if(c.error&&(console.error(` error: ${c.error}`),process.exit(1)),A(l)){E(c);break}if(c.warning&&console.log(` warning: ${c.warning}`),c.frames===0){console.log(" no frames captured");break}let d=c.avgMs>0?(1e3/c.avgMs).toFixed(1):"?",p=c.frames>0?(c.jankFrames/c.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
945
945
 
946
946
  frames: ${c.frames}
947
947
  total: ${c.totalMs.toFixed(1)}ms
948
- avg: ${c.avgMs.toFixed(2)}ms (${u} fps)
948
+ avg: ${c.avgMs.toFixed(2)}ms (${d} fps)
949
949
  max: ${c.maxMs.toFixed(2)}ms
950
950
 
951
951
  breakdown (avg per frame):
@@ -959,29 +959,29 @@ ${t}
959
959
  p50: ${c.p50.toFixed(2)}ms
960
960
  p95: ${c.p95.toFixed(2)}ms
961
961
  p99: ${c.p99.toFixed(2)}ms
962
- jank: ${c.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(c.samples)&&c.samples.length>0&&(console.log(""),Ue(c.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 Be(d),A(l)?E({cleared:!0}):console.log(" error buffer cleared");break}let t=o?Number(o):20,s=await fe(d,t);if(A(l)){E(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
963
- `);for(let n of s){let c=ae(n.timestamp),u=n.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");if(console.log(` [${c}] ${u}`),n.stack){let p=n.stack.split(`
964
- `).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 ct(d,o);if(A(l)){E(t);break}if(t.length===0){console.log(" no warnings captured");break}console.log(` ${t.length} warning(s):
965
- `);for(let s of t){let n=ae(s.timestamp),c=s.args.map(u=>typeof u=="object"?JSON.stringify(u):u).join(" ");console.log(` [${n}] ${c}`)}break}case"animations":{let o=await Y(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):
966
- `);for(let t of o){let s=String(t.kind).padEnd(6),n=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,c=Number(t.current??0).toFixed(2),u=`${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} ${n.padEnd(14)} cur=${c.padEnd(7)} ${u.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 Y(d,"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 Y(d,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let o=i[1];if(o==="clear"){await ut(d),A(l)?E({cleared:!0}):console.log(" request buffer cleared");break}let t=o==="all",s=t?i[2]:o,n=s?Number(s):20,c=await dt(d,{failed:!t,limit:n});if(A(l)){E(c);break}if(c.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${c.length} ${t?"request(s)":"failed request(s)"}:
967
- `);for(let u of c){let p=ae(u.timestamp);console.log(` [${p}] ${se(u)}`),u.responseBody?console.log(` ${u.responseBody}`):u.error&&console.log(` ${u.error}`)}break}case"network":{let o=i[1],t=null,s=null,n=!1,c=!1,u=1e3,p=!1,h=!1;for(let _=0;_<l.length;_++){let w=l[_];if(w==="--filter")t=l[_+1]??null,_++;else if(w==="--limit"){let S=Number(l[_+1]);Number.isFinite(S)&&(s=S),_++}else if(w==="--threshold"){let S=Number(l[_+1]);Number.isFinite(S)&&S>0&&(u=S),_++}else w==="--failed"?n=!0:w==="--slow"?c=!0:w==="--tail"||w==="-f"?p=!0:w==="--json"&&(h=!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 _=i[2];_||(console.error(" usage: sootsim network get <id>"),process.exit(1));let w=await d.send({type:"evaluate",code:`(() => {
962
+ jank: ${c.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(c.samples)&&c.samples.length>0&&(console.log(""),Ue(c.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 Be(u),A(l)?E({cleared:!0}):console.log(" error buffer cleared");break}let t=o?Number(o):20,s=await fe(u,t);if(A(l)){E(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
963
+ `);for(let n of s){let c=ae(n.timestamp),d=n.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");if(console.log(` [${c}] ${d}`),n.stack){let p=n.stack.split(`
964
+ `).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 ct(u,o);if(A(l)){E(t);break}if(t.length===0){console.log(" no warnings captured");break}console.log(` ${t.length} warning(s):
965
+ `);for(let s of t){let n=ae(s.timestamp),c=s.args.map(d=>typeof d=="object"?JSON.stringify(d):d).join(" ");console.log(` [${n}] ${c}`)}break}case"animations":{let o=await Y(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):
966
+ `);for(let t of o){let s=String(t.kind).padEnd(6),n=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,c=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} ${n.padEnd(14)} cur=${c.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 Y(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 Y(u,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let o=i[1];if(o==="clear"){await dt(u),A(l)?E({cleared:!0}):console.log(" request buffer cleared");break}let t=o==="all",s=t?i[2]:o,n=s?Number(s):20,c=await ut(u,{failed:!t,limit:n});if(A(l)){E(c);break}if(c.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${c.length} ${t?"request(s)":"failed request(s)"}:
967
+ `);for(let d of c){let p=ae(d.timestamp);console.log(` [${p}] ${se(d)}`),d.responseBody?console.log(` ${d.responseBody}`):d.error&&console.log(` ${d.error}`)}break}case"network":{let o=i[1],t=null,s=null,n=!1,c=!1,d=1e3,p=!1,h=!1;for(let _=0;_<l.length;_++){let w=l[_];if(w==="--filter")t=l[_+1]??null,_++;else if(w==="--limit"){let S=Number(l[_+1]);Number.isFinite(S)&&(s=S),_++}else if(w==="--threshold"){let S=Number(l[_+1]);Number.isFinite(S)&&S>0&&(d=S),_++}else w==="--failed"?n=!0:w==="--slow"?c=!0:w==="--tail"||w==="-f"?p=!0:w==="--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 _=i[2];_||(console.error(" usage: sootsim network get <id>"),process.exit(1));let w=await u.send({type:"evaluate",code:`(() => {
968
968
  const obs = window.__sootsimObservability;
969
969
  if (!obs) return null;
970
970
  return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(_)}) || null;
971
971
  })()`});w||(console.error(` no entry with id ${_}`),process.exit(1)),h?console.log(JSON.stringify(w,null,2)):Ko(w);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).
972
- to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let x=async()=>{let _=await d.send({type:"evaluate",code:`(() => {
972
+ to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let x=async()=>{let _=await u.send({type:"evaluate",code:`(() => {
973
973
  const obs = window.__sootsimObservability;
974
974
  if (!obs) return { ok: false };
975
975
  return { ok: true, entries: obs.network.getSnapshot() };
976
- })()`});if(!_||!_.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return _.entries??[]},R=_=>{let w=_;if(n&&(w=w.filter(S=>!!S.error||S.status!=null&&S.status>=400)),c&&(w=w.filter(S=>S.durationMs!=null&&S.durationMs>=u)),t){let S=t.toLowerCase();w=w.filter(k=>(k.displayUrl||k.url).toLowerCase().includes(S))}return c&&!p&&(w=[...w].sort((S,k)=>(k.durationMs??0)-(S.durationMs??0))),w};if(!p){let _=await x(),w=R(_).slice(-f);if(h){console.log(JSON.stringify(w,null,2));break}if(w.length===0){_.length===0?console.log(" no network requests captured"):console.log(c?` no requests slower than ${u}ms (${_.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(c?` ${w.length} request(s) slower than ${u}ms (sorted by duration desc):
976
+ })()`});if(!_||!_.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return _.entries??[]},R=_=>{let w=_;if(n&&(w=w.filter(S=>!!S.error||S.status!=null&&S.status>=400)),c&&(w=w.filter(S=>S.durationMs!=null&&S.durationMs>=d)),t){let S=t.toLowerCase();w=w.filter(k=>(k.displayUrl||k.url).toLowerCase().includes(S))}return c&&!p&&(w=[...w].sort((S,k)=>(k.durationMs??0)-(S.durationMs??0))),w};if(!p){let _=await x(),w=R(_).slice(-f);if(h){console.log(JSON.stringify(w,null,2));break}if(w.length===0){_.length===0?console.log(" no network requests captured"):console.log(c?` no requests slower than ${d}ms (${_.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(c?` ${w.length} request(s) slower than ${d}ms (sorted by duration desc):
977
977
  `:` ${w.length} request(s):
978
978
  `);for(let S of w)so(S);break}console.log(` tailing network (ctrl-c to stop)...
979
- `);let H=new Set,K=!0,U=()=>{K=!1};process.on("SIGINT",U);try{for(;K;){let _=await x(),w=R(_);for(let S of w)S.durationMs!=null&&(H.has(S.id)||(H.add(S.id),h?console.log(JSON.stringify(S)):so(S)));await te(250)}}finally{process.off("SIGINT",U)}break}case"logs":{let o=i[1],t=null,s=null,n=null,c=!1,u=!1,p=!1;for(let w=0;w<l.length;w++){let S=l[w];if(S==="--filter")t=l[w+1]??null,w++;else if(S==="--limit"){let k=Number(l[w+1]);Number.isFinite(k)&&(s=k),w++}else S==="--level"?(n=l[w+1]??null,w++):S==="--tail"||S==="-f"?c=!0:S==="--json"?u=!0:(S==="--internal"||S==="--all")&&(p=!0)}let h=n?new Set(n.split(",").map(w=>w.trim()).filter(w=>w==="log"||w==="info"||w==="warn"||w==="error"||w==="debug")):null;if(o==="clear"){await pt(d),console.log(" log buffer cleared");break}let f=!u&&process.stdout.isTTY===!0,x=s??(c?500:o?Number(o):50);Number.isFinite(x)||(console.error(` invalid limit: ${o} \u2014 \`logs\` takes a numeric count (e.g. ${b("logs")} 100).
980
- to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let R=()=>mt(d),H=w=>ft(w,{level:h,filter:t,showInternal:p});if(!c){let w=await R(),S=H(w).slice(-x);if(u){console.log(JSON.stringify(S,null,2));break}if(S.length===0){console.log(w.length===0?" no logs captured":" no matching logs");break}console.log(` ${S.length} log(s):
979
+ `);let H=new Set,K=!0,U=()=>{K=!1};process.on("SIGINT",U);try{for(;K;){let _=await x(),w=R(_);for(let S of w)S.durationMs!=null&&(H.has(S.id)||(H.add(S.id),h?console.log(JSON.stringify(S)):so(S)));await te(250)}}finally{process.off("SIGINT",U)}break}case"logs":{let o=i[1],t=null,s=null,n=null,c=!1,d=!1,p=!1;for(let w=0;w<l.length;w++){let S=l[w];if(S==="--filter")t=l[w+1]??null,w++;else if(S==="--limit"){let k=Number(l[w+1]);Number.isFinite(k)&&(s=k),w++}else S==="--level"?(n=l[w+1]??null,w++):S==="--tail"||S==="-f"?c=!0:S==="--json"?d=!0:(S==="--internal"||S==="--all")&&(p=!0)}let h=n?new Set(n.split(",").map(w=>w.trim()).filter(w=>w==="log"||w==="info"||w==="warn"||w==="error"||w==="debug")):null;if(o==="clear"){await pt(u),console.log(" log buffer cleared");break}let f=!d&&process.stdout.isTTY===!0,x=s??(c?500:o?Number(o):50);Number.isFinite(x)||(console.error(` invalid limit: ${o} \u2014 \`logs\` takes a numeric count (e.g. ${b("logs")} 100).
980
+ to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let R=()=>mt(u),H=w=>ft(w,{level:h,filter:t,showInternal:p});if(!c){let w=await R(),S=H(w).slice(-x);if(d){console.log(JSON.stringify(S,null,2));break}if(S.length===0){console.log(w.length===0?" no logs captured":" no matching logs");break}console.log(` ${S.length} log(s):
981
981
  `);for(let k of S)ro(k,f);break}console.log(` tailing logs (ctrl-c to stop)...
982
- `);let K=new Set,U=!0,_=()=>{U=!1};process.on("SIGINT",_);try{for(;U;){let w=await R(),S=H(w);for(let k of S)K.has(k.id)||(K.add(k.id),u?console.log(JSON.stringify(k)):ro(k,f));await te(250)}}finally{process.off("SIGINT",_)}break}default:console.error(` unknown subcommand: ${g}`),process.exit(1)}if(C.has(g)&&!e.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&!await Qe(d,g)&&await v(d),$.length>0&&Q($),!j.has(g)&&!A(l))try{await xe(d)}catch{}}catch($){let o=$ instanceof Error?$.message:String($);console.error(` ${g??"inspect"} failed: ${o}`);let t=/^no sim connected with id (.+)$/.exec(o),s=/^command timed out after (\d+)s$/.exec(o),n=o.startsWith("sim disconnected:")||o.startsWith("bridge never reconnected")||o.startsWith("could not connect to ws://");if(t)await It(d,O,t[1]);else if(/^no sim connected$/.test(o))Mt(O);else if(s)if(await Lo(d)){let u=g??"describe";process.stderr.write(` the sim is still responsive \u2014 '${u}' just exceeded the ${s[1]}s command budget.
982
+ `);let K=new Set,U=!0,_=()=>{U=!1};process.on("SIGINT",_);try{for(;U;){let w=await R(),S=H(w);for(let k of S)K.has(k.id)||(K.add(k.id),d?console.log(JSON.stringify(k)):ro(k,f));await te(250)}}finally{process.off("SIGINT",_)}break}default:console.error(` unknown subcommand: ${g}`),process.exit(1)}if(C.has(g)&&!e.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&!await Qe(u,g)&&await v(u),$.length>0&&Q($),!j.has(g)&&!A(l))try{await xe(u)}catch{}}catch($){let o=$ instanceof Error?$.message:String($);console.error(` ${g??"inspect"} failed: ${o}`);let t=/^no sim connected with id (.+)$/.exec(o),s=/^command timed out after (\d+)s$/.exec(o),n=o.startsWith("sim disconnected:")||o.startsWith("bridge never reconnected")||o.startsWith("could not connect to ws://");if(t)await It(u,O,t[1]);else if(/^no sim connected$/.test(o))Mt(O);else if(s)if(await Lo(u)){let d=g??"describe";process.stderr.write(` the sim is still responsive \u2014 '${d}' just exceeded the ${s[1]}s command budget.
983
983
  the screen's node tree is large; narrow the query or raise the budget:
984
- sootsim ${u} --testid <id> # scope to one subtree
984
+ sootsim ${d} --testid <id> # scope to one subtree
985
985
  sootsim find --testid <id> # targeted single-node lookup
986
- sootsim ${u} --timeout 60000 # raise per-command budget (ms)
987
- `)}else to();else if(n)to();else{try{await Tt(d)}catch{}try{await ee({includeTail:!0})}catch{}try{await q({includeTail:!0})}catch{}}process.exit(1)}finally{d.close()}}export{Hn as runInspect};
986
+ sootsim ${d} --timeout 60000 # raise per-command budget (ms)
987
+ `)}else to();else if(n)to();else{try{await Tt(u)}catch{}try{await ee({includeTail:!0})}catch{}try{await q({includeTail:!0})}catch{}}process.exit(1)}finally{u.close()}}export{Hn as runInspect};