sootsim 0.1.59 → 0.1.60

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 (139) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-GD3Q5RPA.js → agent-3QM476OM.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-LBIAKQGM.js → agent-wrapper-ZGA3WMEQ.js} +2 -2
  4. package/dist-cli/chunks/{assert-LZUX5QVA.js → assert-7LOZ3UZU.js} +2 -2
  5. package/dist-cli/chunks/auto-bootstrap-5SEVYWHQ.js +2 -0
  6. package/dist-cli/chunks/beta-WS6QLCUE.js +2 -0
  7. package/dist-cli/chunks/{chunk-D6O2NXGB.js → chunk-2367OT3T.js} +2 -2
  8. package/dist-cli/chunks/{chunk-4VNKLERI.js → chunk-2X5KYBDL.js} +2 -2
  9. package/dist-cli/chunks/{chunk-PSPZTTCO.js → chunk-32X2Q5FN.js} +2 -2
  10. package/dist-cli/chunks/chunk-4LRESDDC.js +11 -0
  11. package/dist-cli/chunks/{chunk-D26QPCEP.js → chunk-4V7H5CSS.js} +2 -2
  12. package/dist-cli/chunks/{chunk-5RLJWEFW.js → chunk-7K3CWKDO.js} +1 -1
  13. package/dist-cli/chunks/{chunk-XDIT5SEC.js → chunk-A33UZUKE.js} +2 -2
  14. package/dist-cli/chunks/{chunk-HMPHDE5A.js → chunk-ARKBI7JL.js} +1 -1
  15. package/dist-cli/chunks/{chunk-4ENZNH7P.js → chunk-BOVJRVYZ.js} +2 -2
  16. package/dist-cli/chunks/{chunk-LLOURJ3N.js → chunk-BXZN6LGB.js} +3 -3
  17. package/dist-cli/chunks/chunk-C6YD4Y7P.js +1 -0
  18. package/dist-cli/chunks/{chunk-YT54ZKTQ.js → chunk-DMLDEQSS.js} +2 -2
  19. package/dist-cli/chunks/{chunk-NGEPSXEE.js → chunk-EJYB47BH.js} +9 -4
  20. package/dist-cli/chunks/{chunk-AMEUPM6D.js → chunk-FVH44DUL.js} +1 -1
  21. package/dist-cli/chunks/{chunk-Y65GFG22.js → chunk-GZQHWPLT.js} +3 -3
  22. package/dist-cli/chunks/chunk-HJEHZSNV.js +92 -0
  23. package/dist-cli/chunks/{chunk-KYP5XLIR.js → chunk-I7FBCRYN.js} +2 -2
  24. package/dist-cli/chunks/{chunk-F2DSLYX4.js → chunk-IDNLH47C.js} +1 -1
  25. package/dist-cli/chunks/chunk-IKICAURU.js +1 -0
  26. package/dist-cli/chunks/{chunk-V4SMVFRV.js → chunk-LKHZHA2M.js} +1 -1
  27. package/dist-cli/chunks/{chunk-XM4D43UP.js → chunk-LO7IVLWX.js} +2 -2
  28. package/dist-cli/chunks/{chunk-A3ATSCOF.js → chunk-LYEPRAQA.js} +2 -2
  29. package/dist-cli/chunks/{chunk-WQOEMVXN.js → chunk-N7VXONQG.js} +1 -1
  30. package/dist-cli/chunks/{chunk-TYRPY3SN.js → chunk-NH6WDZCD.js} +1 -1
  31. package/dist-cli/chunks/{chunk-V6NAG62D.js → chunk-NRYQ2JZJ.js} +1 -1
  32. package/dist-cli/chunks/{chunk-5S62LOV4.js → chunk-OXLLV636.js} +2 -2
  33. package/dist-cli/chunks/{chunk-4L72FYCQ.js → chunk-PDC6SIIZ.js} +1 -1
  34. package/dist-cli/chunks/{chunk-WQXLD5YU.js → chunk-PIV6WQG4.js} +2 -2
  35. package/dist-cli/chunks/{chunk-O4I44BRL.js → chunk-QJBS67HI.js} +1 -1
  36. package/dist-cli/chunks/{chunk-BL3IZLNB.js → chunk-QOWJXECZ.js} +2 -2
  37. package/dist-cli/chunks/{chunk-IY3JNNU7.js → chunk-RDCLJUAL.js} +2 -2
  38. package/dist-cli/chunks/{chunk-ZLMNBI7T.js → chunk-RFSQAGQM.js} +2 -2
  39. package/dist-cli/chunks/{chunk-WMTMNKH2.js → chunk-S4LMLA46.js} +2 -2
  40. package/dist-cli/chunks/{chunk-XRMTMRS5.js → chunk-S75CWUM2.js} +1 -1
  41. package/dist-cli/chunks/{chunk-ZX66GIXV.js → chunk-TNN7OYGT.js} +2 -2
  42. package/dist-cli/chunks/chunk-UW4IDGIR.js +2 -0
  43. package/dist-cli/chunks/{chunk-G3A23B5Q.js → chunk-VTLZR3XL.js} +1 -1
  44. package/dist-cli/chunks/chunk-W7X3YMV3.js +1 -0
  45. package/dist-cli/chunks/{chunk-5DO55JWB.js → chunk-WY7EM456.js} +27 -27
  46. package/dist-cli/chunks/{chunk-PS57ERTY.js → chunk-XNZIAKU5.js} +2 -2
  47. package/dist-cli/chunks/chunk-YKLWG4AA.js +119 -0
  48. package/dist-cli/chunks/chunk-YN2754CX.js +2 -0
  49. package/dist-cli/chunks/{chunk-24VAZEFY.js → chunk-YQT3TRJ5.js} +2 -2
  50. package/dist-cli/chunks/cli-version-ARDD24DZ.js +2 -0
  51. package/dist-cli/chunks/{compat-77WWLIGJ.js → compat-4TESUCFM.js} +3 -3
  52. package/dist-cli/chunks/{config-WGPGLVTW.js → config-GKXIKKRU.js} +2 -2
  53. package/dist-cli/chunks/control-NKGES73S.js +2 -0
  54. package/dist-cli/chunks/{cpu-profile-XMBVCI7K.js → cpu-profile-2F4C2O7S.js} +2 -2
  55. package/dist-cli/chunks/{daemon-FFHD2I32.js → daemon-FMZ7MNVI.js} +2 -2
  56. package/dist-cli/chunks/{debug-FMXTU6TB.js → debug-IJCU56E5.js} +3 -3
  57. package/dist-cli/chunks/demo-app-registry-B2GQWZAE.js +2 -0
  58. package/dist-cli/chunks/{detox-QGFGC5RT.js → detox-5UFOIOLZ.js} +2 -2
  59. package/dist-cli/chunks/{device-OL7VGMK7.js → device-AE6AZUWE.js} +2 -2
  60. package/dist-cli/chunks/{diagnose-6CSSFWBQ.js → diagnose-FE27W2WT.js} +2 -2
  61. package/dist-cli/chunks/drivers-EQGVLU5S.js +2 -0
  62. package/dist-cli/chunks/{electron-MHXT6NTC.js → electron-FFIZI3WU.js} +3 -3
  63. package/dist-cli/chunks/flow-DKRIB4D4.js +2 -0
  64. package/dist-cli/chunks/{hints-W5DK2COL.js → hints-AVO3XSF2.js} +2 -2
  65. package/dist-cli/chunks/{home-paths-RWCQ7AU2.js → home-paths-XCSL4IZG.js} +2 -2
  66. package/dist-cli/chunks/{inspect-5XMF34Y7.js → inspect-SEWOLKW2.js} +130 -108
  67. package/dist-cli/chunks/install-5SPPQPBO.js +2 -0
  68. package/dist-cli/chunks/{install-desktop-YVHWBC3T.js → install-desktop-ZVPLNWWN.js} +3 -3
  69. package/dist-cli/chunks/{keys-6HAEB4IC.js → keys-2ANCWIJR.js} +2 -2
  70. package/dist-cli/chunks/{launch-OHCK4MRM.js → launch-QBCI6F33.js} +3 -3
  71. package/dist-cli/chunks/{login-VBHIW5ZN.js → login-MPEC3IQC.js} +4 -4
  72. package/dist-cli/chunks/{logout-LHFYJFHT.js → logout-FHKV7PVB.js} +2 -2
  73. package/dist-cli/chunks/{maestro-56F3HFUH.js → maestro-HEPFHHZM.js} +2 -2
  74. package/dist-cli/chunks/{preview-ATGWKYQI.js → preview-SAM2AO6M.js} +2 -2
  75. package/dist-cli/chunks/{profile-UII6DPNJ.js → profile-CW3WET2M.js} +2 -2
  76. package/dist-cli/chunks/{react-4F2HFSY7.js → react-LFKI73YH.js} +2 -2
  77. package/dist-cli/chunks/record-CM3G44PK.js +45 -0
  78. package/dist-cli/chunks/runtime-JUMLSSWP.js +2 -0
  79. package/dist-cli/chunks/{runtime-delivery-CUCNWWQP.js → runtime-delivery-MSETJQQ6.js} +2 -2
  80. package/dist-cli/chunks/{screenshot-GKJ4ICW4.js → screenshot-D77TOEEP.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-OCP4HA3H.js → screenshot-mode-2YPUHGUB.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-RTRJF63K.js → screenshots-RKWVNLEI.js} +2 -2
  83. package/dist-cli/chunks/{server-SY6BQAVD.js → server-GDOHSZQ3.js} +3 -3
  84. package/dist-cli/chunks/setup-repo-GGNBHKN6.js +2 -0
  85. package/dist-cli/chunks/{skills-KX3LI7Y6.js → skills-2KROZMJJ.js} +2 -2
  86. package/dist-cli/chunks/{start-5IOHCWG6.js → start-RTIULO26.js} +4 -4
  87. package/dist-cli/chunks/store-XAQEN3N3.js +2 -0
  88. package/dist-cli/chunks/telemetry-GIZM7C4U.js +2 -0
  89. package/dist-cli/chunks/{test-2QTF7GWW.js → test-WIBWT3SJ.js} +3 -3
  90. package/dist-cli/chunks/{three-mode-EQSSYVHT.js → three-mode-XMBKE6NN.js} +2 -2
  91. package/dist-cli/chunks/{timeline-GZZYRE2U.js → timeline-3RHZIXQV.js} +2 -2
  92. package/dist-cli/chunks/{upgrade-KVJ2HKRH.js → upgrade-MLQ3YZEU.js} +2 -2
  93. package/dist-cli/chunks/upload-K36QDGWB.js +2 -0
  94. package/dist-cli/chunks/{web-2C5AJBCN.js → web-6SI6NZ22.js} +2 -2
  95. package/dist-cli/chunks/{what-happened-YECRPXV5.js → what-happened-FK6I5XEC.js} +2 -2
  96. package/dist-cli/chunks/{whoami-WCPVDNPA.js → whoami-ZVUQ4ICS.js} +2 -2
  97. package/dist-lib/agent-daemon-client.cjs +1 -1
  98. package/dist-lib/agent-events.cjs +1 -1
  99. package/dist-lib/agent-sessions.cjs +1 -1
  100. package/dist-lib/attached-projects.cjs +1 -1
  101. package/dist-lib/auth/shared-session.cjs +1 -1
  102. package/dist-lib/backend-origin.cjs +1 -1
  103. package/dist-lib/bridge-constants.cjs +1 -1
  104. package/dist-lib/cli-constants.cjs +1 -1
  105. package/dist-lib/config.cjs +1 -1
  106. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  107. package/dist-lib/home-paths.cjs +1 -1
  108. package/dist-lib/host/bridge-host.cjs +2 -2
  109. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  110. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  111. package/dist-lib/index.cjs +1 -1
  112. package/dist-lib/metro.cjs +1 -1
  113. package/dist-lib/profiles.cjs +1 -1
  114. package/dist-lib/render-mode.cjs +1 -1
  115. package/dist-lib/vite-base.cjs +2 -2
  116. package/dist-lib/vite.cjs +1 -1
  117. package/package.json +1 -1
  118. package/dist-cli/chunks/auto-bootstrap-RGEU3N4Y.js +0 -2
  119. package/dist-cli/chunks/beta-7YMPFJF7.js +0 -2
  120. package/dist-cli/chunks/chunk-DFXUPNYD.js +0 -119
  121. package/dist-cli/chunks/chunk-GL3JT3P7.js +0 -1
  122. package/dist-cli/chunks/chunk-L5PBH3V6.js +0 -1
  123. package/dist-cli/chunks/chunk-N7OHTYFK.js +0 -2
  124. package/dist-cli/chunks/chunk-O2W7EB7L.js +0 -11
  125. package/dist-cli/chunks/chunk-QNH7IX5F.js +0 -59
  126. package/dist-cli/chunks/chunk-UPW76NDZ.js +0 -2
  127. package/dist-cli/chunks/chunk-ZEB4DGC6.js +0 -1
  128. package/dist-cli/chunks/cli-version-CL32HHD6.js +0 -2
  129. package/dist-cli/chunks/control-KZYO5BDN.js +0 -2
  130. package/dist-cli/chunks/demo-app-registry-RSAPXLUE.js +0 -2
  131. package/dist-cli/chunks/drivers-7PFWCFVQ.js +0 -2
  132. package/dist-cli/chunks/flow-HMBOPMQV.js +0 -2
  133. package/dist-cli/chunks/install-3MNX7DSK.js +0 -2
  134. package/dist-cli/chunks/record-YHRJJJRY.js +0 -41
  135. package/dist-cli/chunks/runtime-HOPZF7H6.js +0 -2
  136. package/dist-cli/chunks/setup-repo-Z7WKSSP5.js +0 -2
  137. package/dist-cli/chunks/store-WYV5UMFH.js +0 -2
  138. package/dist-cli/chunks/telemetry-XABHSL5O.js +0 -2
  139. package/dist-cli/chunks/upload-4VWBZXY4.js +0 -2
@@ -1,12 +1,12 @@
1
- /*! sootsim v0.1.59 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as G}from"./chunk-ZLMNBI7T.js";import{a as Je,b as Le}from"./chunk-F2DSLYX4.js";import{a as X,b as D,c as B,d as z,e as de,f as re,g as at,h as lt,i as ke}from"./chunk-XDIT5SEC.js";import{B as se,C as rt,I as it,a as We,b as qe,c as He,d as Ue,e as Ke,f as ze,g as Se,h as ve,m as Ye,n as Ge,o as Xe,p as Ve,q as Qe,r as Ze,s as et,t as tt,u as ot,v as st,z as nt}from"./chunk-NGEPSXEE.js";import{a as Be,g as ce}from"./chunk-BL3IZLNB.js";import{b as ct,c as dt,i as ut}from"./chunk-O2W7EB7L.js";import"./chunk-WMTMNKH2.js";import{a as je}from"./chunk-O4I44BRL.js";import"./chunk-ZX66GIXV.js";import"./chunk-QNH7IX5F.js";import"./chunk-5RLJWEFW.js";import"./chunk-L5PBH3V6.js";import"./chunk-D6O2NXGB.js";import"./chunk-G3A23B5Q.js";import{a as we,c as $e,d as Pe}from"./chunk-DFXUPNYD.js";import{a as Ae}from"./chunk-UPW76NDZ.js";import{c as Re,e as Ee,f as Ce,g as De,h as xe}from"./chunk-KYP5XLIR.js";import{b as Oe}from"./chunk-4L72FYCQ.js";import"./chunk-N7OHTYFK.js";import"./chunk-V6NAG62D.js";import"./chunk-AMEUPM6D.js";import{existsSync as Ht,mkdirSync as Ut,readFileSync as Kt,rmSync as mt,writeFileSync as zt}from"fs";import{tmpdir as Yt}from"os";import{dirname as Gt,join as Xt,resolve as Vt}from"path";var ie=1,Qt="SOOTSIM_INSPECT_NOTICE_PATH",Zt=300*1e3,eo=15e3;function pt(){return Vt(process.env[Qt]||Xt(Yt(),"sootsim-inspect-notice-state.json"))}function to(o,d){return Object.fromEntries(Object.entries(o).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&d-i.updatedAt<=Zt))}function oo(o){let d=pt();if(!Ht(d))return{version:ie,entries:{}};try{let i=JSON.parse(Kt(d,"utf8"));return i.version!==ie||!i.entries||typeof i.entries!="object"?(mt(d,{force:!0}),{version:ie,entries:{}}):{version:ie,entries:to(i.entries,o)}}catch{return mt(d,{force:!0}),{version:ie,entries:{}}}}function so(o){let d=pt();Ut(Gt(d),{recursive:!0}),zt(d,JSON.stringify(o,null,2)+`
3
- `)}function no(o,d){let i=d.trim()||"default";return`${o}:${i}`}function Te(o,d,i,l={}){let f=l.nowMs??Date.now(),a=l.cooldownMs??eo,y=oo(f),S=no(o,d),N=y.entries[S];return N&&N.signature===i&&f-N.updatedAt<a?!1:(y.entries[S]={signature:i,updatedAt:f},so(y),!0)}async function ft(o,d={args:[]}){let i=await We(o);if(D(d.args)){B(i);return}console.log(` nodes: ${i.nodes}`)}function Me(o,d){let i=o.indexOf(d);return i>=0&&i+1<o.length?o[i+1]:null}async function gt(o){let{bridge:d,args:i,positional:l}=o,f=i.includes("--verbose")||i.includes("-v"),a=D(i),y=f&&!a,S=i.includes("--watch")||i.includes("-w"),N=1e3,k=i.includes("--compact"),b=i.includes("--no-xy"),v=Me(i,"--testid-like"),_=Me(i,"--only"),T=Me(i,"--subtree"),E=l[1],L=E?/[*?]/.test(E):!1,c=!L&&!_?E:void 0,K=_??(L?E:void 0),j=async()=>{await de(d,{verbose:y});let Y=await Ue(d,{describe:!0,verbose:f,filter:c||"",testIdLike:v||void 0,onlyGlob:K||void 0,subtreeRoot:T||void 0,compact:k,hideXy:b}),W=Y?.tree,w=Y?.shell,I=Y?.keyboard;if(a){B({shell:w,tree:W??"",keyboard:I});return}if(w&&typeof w=="object"){let P=[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);P.length>0&&console.log(` shell: ${P.join(" ")}`)}if(typeof W=="string"&&W.startsWith("__SUBTREE_NOT_FOUND__:")){let P=W.slice(22);console.log(` subtree root not found: ${P}`),G("subtree-root-not-found",P);return}if(!W){let P=Y?.nodeCount??0;console.log(" no matching nodes found"),!(c||v||K||T)&&P<10&&G("app-still-loading",P);return}if(console.log(W),!(c||v||K||T)&&!S&&W.split(`
4
- `).length>=80&&G("describe-use-filters"),I&&I.visible){let P=I.spec,V=[P?.keyboardType?`type=${P.keyboardType}`:null,P?.returnKeyType&&P.returnKeyType!=="default"?`return=${P.returnKeyType}`:null,I.mode!=="letters"?`mode=${I.mode}`:null,I.shifted?"shift":null,I.capsLock?"caps":null,P?.autoCapitalize&&P.autoCapitalize!=="sentences"?`autoCap=${P.autoCapitalize}`:null,I.accessoryBarId?`accessory=${I.accessoryBarId}`:null].filter(Boolean);console.log(`
1
+ /*! sootsim v0.1.60 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as G}from"./chunk-RFSQAGQM.js";import{a as Le,b as Je}from"./chunk-IDNLH47C.js";import{a as X,b as C,c as B,d as z,e as de,f as re,g as at,h as lt,i as ke}from"./chunk-A33UZUKE.js";import{a as Be,g as ce}from"./chunk-QOWJXECZ.js";import{b as ct,c as dt,i as ut}from"./chunk-4LRESDDC.js";import"./chunk-S4LMLA46.js";import{a as je}from"./chunk-QJBS67HI.js";import{B as se,C as rt,I as it,a as We,b as qe,c as He,d as Ue,e as Ke,f as ze,g as Se,h as ve,m as Ye,n as Ge,o as Xe,p as Ve,q as Qe,r as Ze,s as et,t as tt,u as ot,v as st,z as nt}from"./chunk-EJYB47BH.js";import"./chunk-TNN7OYGT.js";import"./chunk-HJEHZSNV.js";import"./chunk-7K3CWKDO.js";import"./chunk-C6YD4Y7P.js";import"./chunk-2367OT3T.js";import"./chunk-VTLZR3XL.js";import{a as we,c as xe,d as Oe}from"./chunk-YKLWG4AA.js";import{a as Ae}from"./chunk-UW4IDGIR.js";import{c as Re,e as Ee,f as De,g as Ce,h as $e}from"./chunk-I7FBCRYN.js";import{b as Pe}from"./chunk-PDC6SIIZ.js";import"./chunk-YN2754CX.js";import"./chunk-NRYQ2JZJ.js";import"./chunk-FVH44DUL.js";import{existsSync as Ht,mkdirSync as Ut,readFileSync as Kt,rmSync as mt,writeFileSync as zt}from"fs";import{tmpdir as Yt}from"os";import{dirname as Gt,join as Xt,resolve as Vt}from"path";var ie=1,Qt="SOOTSIM_INSPECT_NOTICE_PATH",Zt=300*1e3,eo=15e3;function pt(){return Vt(process.env[Qt]||Xt(Yt(),"sootsim-inspect-notice-state.json"))}function to(s,d){return Object.fromEntries(Object.entries(s).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&d-i.updatedAt<=Zt))}function oo(s){let d=pt();if(!Ht(d))return{version:ie,entries:{}};try{let i=JSON.parse(Kt(d,"utf8"));return i.version!==ie||!i.entries||typeof i.entries!="object"?(mt(d,{force:!0}),{version:ie,entries:{}}):{version:ie,entries:to(i.entries,s)}}catch{return mt(d,{force:!0}),{version:ie,entries:{}}}}function so(s){let d=pt();Ut(Gt(d),{recursive:!0}),zt(d,JSON.stringify(s,null,2)+`
3
+ `)}function no(s,d){let i=d.trim()||"default";return`${s}:${i}`}function Te(s,d,i,l={}){let f=l.nowMs??Date.now(),a=l.cooldownMs??eo,y=oo(f),S=no(s,d),T=y.entries[S];return T&&T.signature===i&&f-T.updatedAt<a?!1:(y.entries[S]={signature:i,updatedAt:f},so(y),!0)}async function ft(s,d={args:[]}){let i=await We(s);if(C(d.args)){B(i);return}console.log(` nodes: ${i.nodes}`)}function Me(s,d){let i=s.indexOf(d);return i>=0&&i+1<s.length?s[i+1]:null}async function gt(s){let{bridge:d,args:i,positional:l}=s,f=i.includes("--verbose")||i.includes("-v"),a=C(i),y=f&&!a,S=i.includes("--watch")||i.includes("-w"),T=1e3,k=i.includes("--compact"),h=i.includes("--no-xy"),v=Me(i,"--testid-like"),N=Me(i,"--only"),M=Me(i,"--subtree"),E=l[1],J=E?/[*?]/.test(E):!1,c=!J&&!N?E:void 0,K=N??(J?E:void 0),j=async()=>{await de(d,{verbose:y});let Y=await Ue(d,{describe:!0,verbose:f,filter:c||"",testIdLike:v||void 0,onlyGlob:K||void 0,subtreeRoot:M||void 0,compact:k,hideXy:h}),W=Y?.tree,x=Y?.shell,_=Y?.keyboard;if(a){B({shell:x,tree:W??"",keyboard:_});return}if(x&&typeof x=="object"){let O=[x.state?`state=${x.state}`:null,x.activeApp?`app=${x.activeApp}`:null,x.showSwitcher?"switcher":null,x.switcherPhase&&x.switcherPhase!=="idle"?`phase=${x.switcherPhase}`:null].filter(Boolean);O.length>0&&console.log(` shell: ${O.join(" ")}`)}if(typeof W=="string"&&W.startsWith("__SUBTREE_NOT_FOUND__:")){let O=W.slice(22);console.log(` subtree root not found: ${O}`),G("subtree-root-not-found",O);return}if(!W){let O=Y?.nodeCount??0;console.log(" no matching nodes found"),!(c||v||K||M)&&O<10&&G("app-still-loading",O);return}if(console.log(W),!(c||v||K||M)&&!S&&W.split(`
4
+ `).length>=80&&G("describe-use-filters"),_&&_.visible){let O=_.spec,V=[O?.keyboardType?`type=${O.keyboardType}`:null,O?.returnKeyType&&O.returnKeyType!=="default"?`return=${O.returnKeyType}`:null,_.mode!=="letters"?`mode=${_.mode}`:null,_.shifted?"shift":null,_.capsLock?"caps":null,O?.autoCapitalize&&O.autoCapitalize!=="sentences"?`autoCap=${O.autoCapitalize}`:null,_.accessoryBarId?`accessory=${_.accessoryBarId}`:null].filter(Boolean);console.log(`
5
5
  keyboard: ${V.join(" ")||"visible"}`)}};if(S)for(console.log(` watching... (Ctrl+C to stop)
6
- `);;)console.clear(),await j(),await X(N);else await j()}var ro=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function yt(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let o of ro){let d=process.env[o];if(d&&d.trim()&&d!=="0")return!0}return!1}async function ht(o){let{bridge:d,args:i,effectiveArgs:l,positional:f,inspectUsage:a}=o,y=w=>{let I=l.indexOf(w);return I>=0&&I+1<l.length?l[I+1]:null},S=w=>l.includes(w),N=y("--testid")||y("--test-id"),k=y("--role"),b=y("--type"),v=y("--text"),_=S("--pressable"),T=S("--visible"),E=S("--interactive-targets")||S("--actions"),L=!N&&!k&&!b&&!v&&!_&&!T&&!E?f[1]:null,c=v??L,K=await ze(d,{testId:N,role:k,type:b,text:c,pressable:_,visible:T,interactive:E});K||(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:j,result:C}=K,Y=D(i),W=i.includes("--verbose")||i.includes("--dump");if(Y)j==="interactive-targets"&&Array.isArray(C)?B(Se(C).map(w=>({...w,tap:ve(w)}))):B(C??null);else if(Array.isArray(C))if(C.length===0){console.log(` no ${j} nodes found`);let w=await d.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof w=="number"&&w<10&&G("app-still-loading",w)}else if(j==="interactive-targets"){let w=Se(C);console.log(` found ${w.length} interactive target${w.length===1?"":"s"} (sorted by score):`);for(let I of w.slice(0,20)){let Z=I.absolutePosition?`@(${Math.round(I.absolutePosition.x)},${Math.round(I.absolutePosition.y)})`:"",P=I.layout?`${Math.round(I.layout.width)}x${Math.round(I.layout.height)}`:"?x?",V=I.text?` "${I.text.slice(0,30)}"`:"",oe=I.testID?` #${I.testID}`:"",ee=I.accessibilityLabel?` \u24D8"${String(I.accessibilityLabel).slice(0,24)}"`:"",ye=I.accessibilityRole?`[${I.accessibilityRole}]`:I.type,he=ve(I);console.log(` ${ye}${V}${ee}${oe} ${P} ${Z}`),console.log(` \u2192 ${he}`),W&&console.log(Ie(JSON.stringify(I,null,2)," "))}w.length>20&&console.log(` ... and ${w.length-20} more`)}else{console.log(` found ${C.length} node${C.length===1?"":"s"} (${j}):`);for(let w of C.slice(0,20)){let I=w.absolutePosition?`@(${Math.round(w.absolutePosition.x)},${Math.round(w.absolutePosition.y)})`:"",Z=w.layout?`${Math.round(w.layout.width)}x${Math.round(w.layout.height)}`:"?x?",P=w.text?` "${w.text.slice(0,30)}"`:"",V=w.testID?` #${w.testID}`:"",oe=w.pressable?" (tap)":"",ee=w.accessibilityRole?`[${w.accessibilityRole}]`:w.type;console.log(` ${ee}${P}${V} ${Z} ${I}${oe}`),W&&console.log(Ie(JSON.stringify(w,null,2)," "))}C.length>20&&console.log(` ... and ${C.length-20} more`)}else if(C==null)console.log(` not found: ${c||N||k||b||""||j}`),N&&G("wait-selector-for-missing-testid",N);else{let w=C;if(w.type&&w.absolutePosition){let I=`@(${Math.round(w.absolutePosition.x)},${Math.round(w.absolutePosition.y)})`,Z=w.layout?`${Math.round(w.layout.width)}x${Math.round(w.layout.height)}`:"?x?",P=w.text?` "${w.text.slice(0,40)}"`:"",V=w.testID?` #${w.testID}`:"",oe=w.pressable?" (tap)":"",ee=w.accessibilityRole?`[${w.accessibilityRole}]`:w.type;console.log(` ${ee}${P}${V} ${Z} ${I}${oe}`),W&&console.log(Ie(JSON.stringify(w,null,2)," "))}else console.log(JSON.stringify(C,null,2))}}function Ie(o,d){return o.split(`
6
+ `);;)console.clear(),await j(),await X(T);else await j()}var ro=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function yt(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let s of ro){let d=process.env[s];if(d&&d.trim()&&d!=="0")return!0}return!1}async function ht(s){let{bridge:d,args:i,effectiveArgs:l,positional:f,inspectUsage:a}=s,y=x=>{let _=l.indexOf(x);return _>=0&&_+1<l.length?l[_+1]:null},S=x=>l.includes(x),T=y("--testid")||y("--test-id"),k=y("--role"),h=y("--type"),v=y("--text"),N=S("--pressable"),M=S("--visible"),E=S("--interactive-targets")||S("--actions"),J=!T&&!k&&!h&&!v&&!N&&!M&&!E?f[1]:null,c=v??J,K=await ze(d,{testId:T,role:k,type:h,text:c,pressable:N,visible:M,interactive:E});K||(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:j,result:D}=K,Y=C(i),W=i.includes("--verbose")||i.includes("--dump");if(Y)j==="interactive-targets"&&Array.isArray(D)?B(Se(D).map(x=>({...x,tap:ve(x)}))):B(D??null);else if(Array.isArray(D))if(D.length===0){console.log(` no ${j} nodes found`);let x=await d.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof x=="number"&&x<10&&G("app-still-loading",x)}else if(j==="interactive-targets"){let x=Se(D);console.log(` found ${x.length} interactive target${x.length===1?"":"s"} (sorted by score):`);for(let _ of x.slice(0,20)){let Z=_.absolutePosition?`@(${Math.round(_.absolutePosition.x)},${Math.round(_.absolutePosition.y)})`:"",O=_.layout?`${Math.round(_.layout.width)}x${Math.round(_.layout.height)}`:"?x?",V=_.text?` "${_.text.slice(0,30)}"`:"",oe=_.testID?` #${_.testID}`:"",ee=_.accessibilityLabel?` \u24D8"${String(_.accessibilityLabel).slice(0,24)}"`:"",ye=_.accessibilityRole?`[${_.accessibilityRole}]`:_.type,he=ve(_);console.log(` ${ye}${V}${ee}${oe} ${O} ${Z}`),console.log(` \u2192 ${he}`),W&&console.log(Ie(JSON.stringify(_,null,2)," "))}x.length>20&&console.log(` ... and ${x.length-20} more`)}else{console.log(` found ${D.length} node${D.length===1?"":"s"} (${j}):`);for(let x of D.slice(0,20)){let _=x.absolutePosition?`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`:"",Z=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",O=x.text?` "${x.text.slice(0,30)}"`:"",V=x.testID?` #${x.testID}`:"",oe=x.pressable?" (tap)":"",ee=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${ee}${O}${V} ${Z} ${_}${oe}`),W&&console.log(Ie(JSON.stringify(x,null,2)," "))}D.length>20&&console.log(` ... and ${D.length-20} more`)}else if(D==null)console.log(` not found: ${c||T||k||h||""||j}`),T&&G("wait-selector-for-missing-testid",T);else{let x=D;if(x.type&&x.absolutePosition){let _=`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`,Z=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",O=x.text?` "${x.text.slice(0,40)}"`:"",V=x.testID?` #${x.testID}`:"",oe=x.pressable?" (tap)":"",ee=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${ee}${O}${V} ${Z} ${_}${oe}`),W&&console.log(Ie(JSON.stringify(x,null,2)," "))}else console.log(JSON.stringify(D,null,2))}}function Ie(s,d){return s.split(`
7
7
  `).map(i=>d+i).join(`
8
- `)}async function bt(o,d={}){let i=await nt(o);if("error"in i&&(console.error(i.error),process.exit(1)),d.json){console.log(JSON.stringify(i,null,2));return}let{visible:l,spec:f,mode:a,shifted:y,capsLock:S,accessoryBarId:N}=i,k=[];k.push(`keyboard: ${l?"visible":"hidden"}`),f?(k.push(` type: ${f.keyboardType}`),k.push(` returnKey: ${f.returnKeyType}`),k.push(` autoCap: ${f.autoCapitalize}`),k.push(` autoCorrect: ${f.autoCorrect?"on":"off"}`),k.push(` appearance: ${f.keyboardAppearance}`),f.secureTextEntry&&k.push(" secureTextEntry: true"),f.enablesReturnKeyAutomatically&&k.push(` return: ${f.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):k.push(" spec: <none> (shown via dev-tools with no TextInput)"),k.push(` mode: ${a}${y?" (shifted)":""}${S?" (caps)":""}`),N&&k.push(` accessoryBar: ${N}`),console.log(k.join(`
9
- `))}async function wt(o){let d=await o.bridge.listSims();if(D(o.args)){B(d.map(i=>({...i,active:i.id===o.simId})));return}ut(d,o.simId)}function te(o){return o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}KB`:`${(o/1024/1024).toFixed(1)}MB`}function ue(o,d){return d<=0?"?":`${(o/d*100).toFixed(0)}%`}async function $t(o,d={args:[]}){let i=await it(o);if(D(d.args)){B(i);return}if(console.log(" memory:"),i.imageLoader){let l=i.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${l.cacheEntries} / ${l.cacheMaxEntries} (${ue(l.cacheEntries,l.cacheMaxEntries)})`),console.log(` pixel bytes: ${te(l.cachePixelBytes)} / ${te(l.cachePixelBudget)} (${ue(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(` camera frames: ${l.cameraFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(i.workerHeap){let l=i.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${te(l.usedJSHeapSize)} / ${te(l.jsHeapSizeLimit)} (${ue(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${te(l.totalJSHeapSize)}`)}if(i.hostHeap){let l=i.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${te(l.usedJSHeapSize)} / ${te(l.jsHeapSizeLimit)} (${ue(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${te(l.totalJSHeapSize)}`)}}function ae(o){let d=o.indexOf("--testid");if(d>=0&&o[d+1])return{mode:"testid",value:o[d+1]};let i=o.indexOf("--test-id");if(i>=0&&o[i+1])return{mode:"testid",value:o[i+1]};let l=o.indexOf("--text");return l>=0&&o[l+1]?{mode:"text",value:o[l+1]}:null}async function me(o,d){let i=JSON.stringify(d.value),l=d.mode==="testid"?`(await t.findByTestId(${i})) || (await t.findById(${i}))`:`await t.findByText(${i})`;return await o.send({type:"evaluate",code:`(async () => {
8
+ `)}async function bt(s,d={}){let i=await nt(s);if("error"in i&&(console.error(i.error),process.exit(1)),d.json){console.log(JSON.stringify(i,null,2));return}let{visible:l,spec:f,mode:a,shifted:y,capsLock:S,accessoryBarId:T}=i,k=[];k.push(`keyboard: ${l?"visible":"hidden"}`),f?(k.push(` type: ${f.keyboardType}`),k.push(` returnKey: ${f.returnKeyType}`),k.push(` autoCap: ${f.autoCapitalize}`),k.push(` autoCorrect: ${f.autoCorrect?"on":"off"}`),k.push(` appearance: ${f.keyboardAppearance}`),f.secureTextEntry&&k.push(" secureTextEntry: true"),f.enablesReturnKeyAutomatically&&k.push(` return: ${f.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):k.push(" spec: <none> (shown via dev-tools with no TextInput)"),k.push(` mode: ${a}${y?" (shifted)":""}${S?" (caps)":""}`),T&&k.push(` accessoryBar: ${T}`),console.log(k.join(`
9
+ `))}async function wt(s){let d=await s.bridge.listSims();if(C(s.args)){B(d.map(i=>({...i,active:i.id===s.simId})));return}ut(d,s.simId)}function te(s){return s<1024?`${s}B`:s<1024*1024?`${(s/1024).toFixed(1)}KB`:`${(s/1024/1024).toFixed(1)}MB`}function ue(s,d){return d<=0?"?":`${(s/d*100).toFixed(0)}%`}async function xt(s,d={args:[]}){let i=await it(s);if(C(d.args)){B(i);return}if(console.log(" memory:"),i.imageLoader){let l=i.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${l.cacheEntries} / ${l.cacheMaxEntries} (${ue(l.cacheEntries,l.cacheMaxEntries)})`),console.log(` pixel bytes: ${te(l.cachePixelBytes)} / ${te(l.cachePixelBudget)} (${ue(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(` camera frames: ${l.cameraFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(i.workerHeap){let l=i.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${te(l.usedJSHeapSize)} / ${te(l.jsHeapSizeLimit)} (${ue(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${te(l.totalJSHeapSize)}`)}if(i.hostHeap){let l=i.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${te(l.usedJSHeapSize)} / ${te(l.jsHeapSizeLimit)} (${ue(l.usedJSHeapSize,l.jsHeapSizeLimit)})`),console.log(` total: ${te(l.totalJSHeapSize)}`)}}function ae(s){let d=s.indexOf("--testid");if(d>=0&&s[d+1])return{mode:"testid",value:s[d+1]};let i=s.indexOf("--test-id");if(i>=0&&s[i+1])return{mode:"testid",value:s[i+1]};let l=s.indexOf("--text");return l>=0&&s[l+1]?{mode:"text",value:s[l+1]}:null}async function me(s,d){let i=JSON.stringify(d.value),l=d.mode==="testid"?`(await t.findByTestId(${i})) || (await t.findById(${i}))`:`await t.findByText(${i})`;return await s.send({type:"evaluate",code:`(async () => {
10
10
  const t = window.__sootsimTest
11
11
  if (!t) return null
12
12
  const n = ${l}
@@ -23,9 +23,16 @@ import{a as G}from"./chunk-ZLMNBI7T.js";import{a as Je,b as Le}from"./chunk-F2DS
23
23
  typeof resolved?.cy === 'number'
24
24
  ? resolved.cy
25
25
  : n.absolutePosition.y + (n.layout.height || 0) / 2
26
- return { x: cx, y: cy, testID: n.testID, text: n.text }
27
- })()`})??null}async function xt(o,d={}){let{nav:i,keyboard:l,shell:f}=await rt(o);if(d.json){console.log(JSON.stringify({shell:f??null,nav:i,keyboard:l},null,2));return}let a=[];if(f){let y=f.activeApp??f.state??"<none>",S=f.showSwitcher?" (app switcher open)":"",N=typeof f.launchProgress=="number"&&f.launchProgress<.98?` launching (${Math.round(f.launchProgress*100)}%)`:"";a.push(`shell: ${y}${S}${N}`)}else a.push("shell: <unavailable>");if(i){let y=i.transitionPhase!=="idle"?` (${i.transitionPhase}, ${i.activeTransitionCount} active)`:"";if(a.push(`nav: phase=${i.transitionPhase}${y}`),i.screens.length===0)a.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let S of i.screens){let N=S.isActive?"\u25B6":" ",k=S.routeName?` ${S.routeName}`:"",b=S.headerHeight>0?` header=${S.headerHeight}`:"",v=S.largeTitleState&&S.largeTitleState!=="expanded"?` large-title=${S.largeTitleState}`:"";a.push(` ${N} #${S.id}${k}${b}${v}`)}}else a.push("nav: <runtime not available>");if(l&&l.visible){let y=l.spec?.keyboardType??"default",S=l.spec?.returnKeyType??"default";a.push(`keyboard: visible (${y}, return=${S}, mode=${l.mode??"?"})`)}else a.push("keyboard: hidden");console.log(a.join(`
28
- `))}async function ne({bridge:o,maxMs:d,pollMs:i=50,stablePolls:l=3,strict:f=!1}){let a=await o.send({type:"evaluate",code:`(async () => {
26
+ return {
27
+ x: cx,
28
+ y: cy,
29
+ id: n.id ?? null,
30
+ testID: n.testID ?? null,
31
+ text: ${JSON.stringify(d.mode==="text")} ? ${i} : (n.text ?? n.accessibilityLabel ?? null),
32
+ type: n.type ?? null,
33
+ }
34
+ })()`})??null}async function $t(s,d={}){let{nav:i,keyboard:l,shell:f}=await rt(s);if(d.json){console.log(JSON.stringify({shell:f??null,nav:i,keyboard:l},null,2));return}let a=[];if(f){let y=f.activeApp??f.state??"<none>",S=f.showSwitcher?" (app switcher open)":"",T=typeof f.launchProgress=="number"&&f.launchProgress<.98?` launching (${Math.round(f.launchProgress*100)}%)`:"";a.push(`shell: ${y}${S}${T}`)}else a.push("shell: <unavailable>");if(i){let y=i.transitionPhase!=="idle"?` (${i.transitionPhase}, ${i.activeTransitionCount} active)`:"";if(a.push(`nav: phase=${i.transitionPhase}${y}`),i.screens.length===0)a.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let S of i.screens){let T=S.isActive?"\u25B6":" ",k=S.routeName?` ${S.routeName}`:"",h=S.headerHeight>0?` header=${S.headerHeight}`:"",v=S.largeTitleState&&S.largeTitleState!=="expanded"?` large-title=${S.largeTitleState}`:"";a.push(` ${T} #${S.id}${k}${h}${v}`)}}else a.push("nav: <runtime not available>");if(l&&l.visible){let y=l.spec?.keyboardType??"default",S=l.spec?.returnKeyType??"default";a.push(`keyboard: visible (${y}, return=${S}, mode=${l.mode??"?"})`)}else a.push("keyboard: hidden");console.log(a.join(`
35
+ `))}async function ne({bridge:s,maxMs:d,pollMs:i=50,stablePolls:l=3,strict:f=!1}){let a=await s.send({type:"evaluate",code:`(async () => {
29
36
  const start = Date.now()
30
37
  const deadline = start + ${Math.max(0,Math.round(d))}
31
38
  const pollMs = ${Math.max(1,Math.round(i))}
@@ -74,12 +81,12 @@ import{a as G}from"./chunk-ZLMNBI7T.js";import{a as Je,b as Le}from"./chunk-F2DS
74
81
  await sleep(pollMs)
75
82
  }
76
83
  return { settled: false, elapsed: Date.now() - start }
77
- })()`}),{elapsed:y,settled:S}=a??{};return{elapsed:typeof y=="number"?y:d,settled:S===!0}}async function St(o){let{bridge:d,args:i,positional:l}=o,f=l[1]?Number(l[1])*1e3:3e3,a=i.includes("--strict"),{elapsed:y,settled:S}=await ne({bridge:d,maxMs:f,strict:a});console.log(S?` settled in ${y}ms`:` timed out after ${y}ms (may still be animating)`)}async function vt(o){let d=o.positional[1]?Number(o.positional[1]):.5;(!Number.isFinite(d)||d<0)&&(console.error(o.inspectUsage("sleep","[seconds]")),process.exit(1)),await X(d*1e3),console.log(` slept ${d}s`)}async function kt(o){let{bridge:d,args:i,positional:l}=o,f=l[1]?Number(l[1]):5,{tree:a}=await qe(d,f);if(D(i)){B({depth:f,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Tt(o,d={args:[]}){let i=await He(o);if(D(d.args)){B(i);return}console.log(i.url)}async function Mt(o){let{wsPort:d,commandTimeoutMs:i,simId:l,simIdSource:f,positional:a}=o,y=a[1]?Number(a[1]):30,S=Math.max(1e3,(Number.isFinite(y)?y:30)*1e3),N=Math.max(1,Math.ceil(S/500));console.log(" waiting for sim reconnect...");let k=await at(d,i,l,{attempts:N,simIdSource:f});k||(console.error(" timed out waiting for sim reconnect"),process.exit(1)),k.bridge.close(),ce({source:"inspect wait",step:{wait:S},summary:`wait ${Math.round(S/1e3)}s`}),console.log(` ready: ${k.count} nodes`)}var It=new Set(["app-launch","toast","keyboard","screen","route","alert","actionsheet","picker","notification","fetch","console","shell","scroll","gesture","text-input","react-commit","animation","reanimated"]);function pe(o,d){let i=o.indexOf(d);if(i>=0&&i+1<o.length)return o[i+1]}function io(o,d){if(!d.filter&&!d.equals)return!0;let i=o.data,l=[];if(i&&typeof i=="object")for(let a of["url","displayUrl","message","name","activeName","path","pathname","title","phase","event","type","kind"]){let y=i[a];typeof y=="string"&&y.length>0&&l.push(y)}let f=l.join(" ");return d.equals?l.some(a=>a===d.equals):d.filter?f.toLowerCase().includes(d.filter.toLowerCase()):!0}async function Nt(o){let{bridge:d,args:i,positional:l,inspectUsage:f}=o,a=l[1];a||(console.error(f("wait event","<kind> [--max-ms 5000] [--filter <substring>] [--equals <exact>] [--since now|cursor]")),process.exit(1)),It.has(a)||console.error(` warning: '${a}' is not a known timeline kind \u2014 waiting anyway. known: ${[...It].sort().join(", ")}`);let y=pe(i,"--max-ms"),S=y&&Number.isFinite(Number(y))?Math.max(100,Number(y)):5e3,N=pe(i,"--filter"),k=pe(i,"--equals"),b=pe(i,"--since")??"now",v=i.includes("--json"),_=Date.now(),T=_+S,E=200,L=_;for(;Date.now()<T;){let K={kinds:[a],since:b==="cursor"?void 0:L,limit:50},j=await d.send({type:"evaluate",code:`(async () => {
84
+ })()`}),{elapsed:y,settled:S}=a??{};return{elapsed:typeof y=="number"?y:d,settled:S===!0}}async function St(s){let{bridge:d,args:i,positional:l}=s,f=l[1]?Number(l[1])*1e3:3e3,a=i.includes("--strict"),{elapsed:y,settled:S}=await ne({bridge:d,maxMs:f,strict:a});console.log(S?` settled in ${y}ms`:` timed out after ${y}ms (may still be animating)`)}async function vt(s){let d=s.positional[1]?Number(s.positional[1]):.5;(!Number.isFinite(d)||d<0)&&(console.error(s.inspectUsage("sleep","[seconds]")),process.exit(1)),await X(d*1e3),console.log(` slept ${d}s`)}async function kt(s){let{bridge:d,args:i,positional:l}=s,f=l[1]?Number(l[1]):5,{tree:a}=await qe(d,f);if(C(i)){B({depth:f,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Tt(s,d={args:[]}){let i=await He(s);if(C(d.args)){B(i);return}console.log(i.url)}async function Mt(s){let{wsPort:d,commandTimeoutMs:i,simId:l,simIdSource:f,positional:a}=s,y=a[1]?Number(a[1]):30,S=Math.max(1e3,(Number.isFinite(y)?y:30)*1e3),T=Math.max(1,Math.ceil(S/500));console.log(" waiting for sim reconnect...");let k=await at(d,i,l,{attempts:T,simIdSource:f});k||(console.error(" timed out waiting for sim reconnect"),process.exit(1)),k.bridge.close(),ce({source:"inspect wait",step:{wait:S},summary:`wait ${Math.round(S/1e3)}s`}),console.log(` ready: ${k.count} nodes`)}var It=new Set(["app-launch","toast","keyboard","screen","route","alert","actionsheet","picker","notification","fetch","console","shell","scroll","gesture","text-input","react-commit","animation","reanimated"]);function pe(s,d){let i=s.indexOf(d);if(i>=0&&i+1<s.length)return s[i+1]}function io(s,d){if(!d.filter&&!d.equals)return!0;let i=s.data,l=[];if(i&&typeof i=="object")for(let a of["url","displayUrl","message","name","activeName","path","pathname","title","phase","event","type","kind"]){let y=i[a];typeof y=="string"&&y.length>0&&l.push(y)}let f=l.join(" ");return d.equals?l.some(a=>a===d.equals):d.filter?f.toLowerCase().includes(d.filter.toLowerCase()):!0}async function Nt(s){let{bridge:d,args:i,positional:l,inspectUsage:f}=s,a=l[1];a||(console.error(f("wait event","<kind> [--max-ms 5000] [--filter <substring>] [--equals <exact>] [--since now|cursor]")),process.exit(1)),It.has(a)||console.error(` warning: '${a}' is not a known timeline kind \u2014 waiting anyway. known: ${[...It].sort().join(", ")}`);let y=pe(i,"--max-ms"),S=y&&Number.isFinite(Number(y))?Math.max(100,Number(y)):5e3,T=pe(i,"--filter"),k=pe(i,"--equals"),h=pe(i,"--since")??"now",v=i.includes("--json"),N=Date.now(),M=N+S,E=200,J=N;for(;Date.now()<M;){let K={kinds:[a],since:h==="cursor"?void 0:J,limit:50},j=await d.send({type:"evaluate",code:`(async () => {
78
85
  const t = window.SootSim?.bridges?.timeline
79
86
  if (!t) return { ok: false, error: 'timeline bridge missing' }
80
87
  return { ok: true, result: await t.recent(${JSON.stringify(K)}) }
81
- })()`});(!j||!j.ok)&&(console.error(` could not query timeline: ${j&&"error"in j?j.error:"unknown"}`),process.exit(1));let C=j.result.events??[];for(let Y of C)if(io(Y,{filter:N,equals:k})){let W=Date.now()-_;console.log(v?JSON.stringify({found:!0,elapsedMs:W,event:Y}):` ${a} event after ${W}ms${N?` (filter: ${N})`:""}${k?` (equals: ${k})`:""}`);return}j.result.watermark&&j.result.watermark>L&&(L=j.result.watermark),await new Promise(Y=>setTimeout(Y,E))}let c=Date.now()-_;v?console.log(JSON.stringify({found:!1,elapsedMs:c,kind:a,filter:N,equals:k})):console.error(` \u26A0 wait event ${a} timed out after ${c}ms${N?` (filter: ${N})`:""}${k?` (equals: ${k})`:""}`),process.exit(1)}async function _t(o){let{bridge:d,args:i}=o,l=i.includes("--strict"),f=i.indexOf("--max-ms"),a=f>=0&&i[f+1]?Math.max(100,Number(i[f+1])):3e3,{elapsed:y,settled:S}=await ne({bridge:d,maxMs:a,strict:l});S?console.log(` idle in ${y}ms`):(console.error(` \u26A0 wait idle timed out after ${y}ms (may still be animating)`),process.exit(1))}async function Ft(o){let{bridge:d,args:i}=o,l=2e4,f=i.indexOf("--max-ms");f>=0&&i[f+1]&&(l=Math.max(100,Number(i[f+1])));let{ready:a,elapsedMs:y,nodes:S}=await Ye(d,l);if(a){console.log(` ready in ${y}ms: ${S} nodes (flag)`);return}console.error(` \u26A0 wait ready timed out after ${y}ms \u2014 guest app did not emit sootsim:externalAppReady (nodes: ${S})`),process.exit(1)}async function At(o){let{bridge:d,args:i,positional:l,inspectUsage:f}=o,a=l[1];a||(console.error(f("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let y=i.indexOf("--max-ms"),S=y>=0&&i[y+1]?Math.max(100,Number(i[y+1])):5e3,{found:N,node:k,elapsed:b}=await Ge(d,a,S);if(N&&k){let v=k.absolutePosition?`@(${Math.round(k.absolutePosition.x)},${Math.round(k.absolutePosition.y)})`:"",_=k.layout?`${Math.round(k.layout.width)}x${Math.round(k.layout.height)}`:"?x?";console.log(` found #${a} in ${b}ms ${_} ${v}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${b??S}ms`),process.exit(1)}function Dt(o){return o==null?"\u2014":o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}K`:`${(o/1024/1024).toFixed(1)}M`}function Bt(o){return o==null?" \u2026":o<1e3?`${o}ms`.padStart(5):`${(o/1e3).toFixed(2)}s`.padStart(5)}function lo(o){return o.error?"err":o.status==null?" \u2026 ":String(o.status)}function Pt(o){let d=new Date(o.startTs).toLocaleTimeString(),i=lo(o).padEnd(3),l=o.method.padEnd(5),f=Dt(o.size).padStart(6),a=Bt(o.durationMs);console.log(` [${d}] ${i} ${l} ${f} ${a} ${o.displayUrl}`),o.error&&console.log(` error: ${o.error}`)}function co(o){let d=[["id",o.id],["source",o.source],["kind",o.kind],["method",o.method],["status",o.error?`error: ${o.error}`:`${o.status??"\u2014"} ${o.statusText??""}`.trim()],["url",o.url],["started",new Date(o.startTs).toLocaleTimeString()],["duration",Bt(o.durationMs).trim()],["size",Dt(o.size)],["content-type",o.type??"\u2014"]];for(let[i,l]of d)console.log(` ${i.padEnd(13)} ${l}`)}var uo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Ot="\x1B[0m",mo="\x1B[2m";function Rt(o,d){let i=new Date(o.ts).toLocaleTimeString(),l=o.level.toUpperCase().padEnd(5),f=o.args.join(" ");if(d){let a=uo[o.level];console.log(` ${mo}[${i}]${Ot} ${a}${l}${Ot} ${f}`)}else console.log(` [${i}] ${l} ${f}`);if(o.stack&&o.level==="error"){let a=o.stack.split(`
82
- `).slice(0,5);for(let y of a)console.log(` ${y.trim()}`)}}var Q="__sootsimCliPerf",po=120;async function Et(o,d){let i=o.find((_,T)=>o[T-1]==="--id"),l=o.find((_,T)=>o[T-1]==="--text");if(i||l){let _=await d.send({type:"evaluate",code:Je({id:i,text:l})});if(!_)throw new Error(i?`no node with id "${i}"`:`no node matching text "${l}"`);let{x:T,y:E,w:L,h:c}=_;return{x:T,y:E,w:L,h:c}}let f=o.find((_,T)=>o[T-1]==="--area");if(f){let _=f.split(",").map(K=>Number(K.trim()));if(_.length!==4||_.some(K=>!Number.isFinite(K)))throw new Error(`--area expects x,y,w,h (got "${f}")`);let[T,E,L,c]=_;return{x:T,y:E,w:L,h:c}}let a=_=>{let T=o.find((L,c)=>o[c-1]===_);if(T==null)return null;let E=Number(T);return Number.isFinite(E)?E:null},y=a("--x"),S=a("--y"),N=a("--w"),k=a("--h");if(y!=null||S!=null||N!=null||k!=null)return{x:y??0,y:S??0,w:N??1,h:k??1};let v=o.filter((_,T)=>T>0&&!_.startsWith("-")&&o[T-1]!=="--output"&&o[T-1]!=="--area"&&o[T-1]!=="--id"&&o[T-1]!=="--text"&&o[T-1]!=="--x"&&o[T-1]!=="--y"&&o[T-1]!=="--w"&&o[T-1]!=="--h").map(Number).filter(_=>Number.isFinite(_));if(v.length>=2){let[_,T,E=1,L=1]=v;return{x:_,y:T,w:E,h:L}}return null}function Ne(o){let d={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of o)i<8?d["<8"]++:i<12?d["8-12"]++:i<16?d["12-16"]++:i<20?d["16-20"]++:i<33?d["20-33"]++:d[">33"]++;console.log(" histogram:");for(let[i,l]of Object.entries(d)){let f="\u2588".repeat(Math.ceil(l/o.length*40));console.log(` ${i.padEnd(6)} ${f} ${l}`)}}async function fe(o,d,i){let l=Date.now()+d,f=await se(o,d);for(;;){if(i(f))return{settled:!0,state:f};if(Date.now()>=l)return{settled:!1,state:f};await X(16),f=await se(o)}}async function Fe(o){return o.send({type:"evaluate",code:`(async () => {
88
+ })()`});(!j||!j.ok)&&(console.error(` could not query timeline: ${j&&"error"in j?j.error:"unknown"}`),process.exit(1));let D=j.result.events??[];for(let Y of D)if(io(Y,{filter:T,equals:k})){let W=Date.now()-N;console.log(v?JSON.stringify({found:!0,elapsedMs:W,event:Y}):` ${a} event after ${W}ms${T?` (filter: ${T})`:""}${k?` (equals: ${k})`:""}`);return}j.result.watermark&&j.result.watermark>J&&(J=j.result.watermark),await new Promise(Y=>setTimeout(Y,E))}let c=Date.now()-N;v?console.log(JSON.stringify({found:!1,elapsedMs:c,kind:a,filter:T,equals:k})):console.error(` \u26A0 wait event ${a} timed out after ${c}ms${T?` (filter: ${T})`:""}${k?` (equals: ${k})`:""}`),process.exit(1)}async function _t(s){let{bridge:d,args:i}=s,l=i.includes("--strict"),f=i.indexOf("--max-ms"),a=f>=0&&i[f+1]?Math.max(100,Number(i[f+1])):3e3,{elapsed:y,settled:S}=await ne({bridge:d,maxMs:a,strict:l});S?console.log(` idle in ${y}ms`):(console.error(` \u26A0 wait idle timed out after ${y}ms (may still be animating)`),process.exit(1))}async function Ft(s){let{bridge:d,args:i}=s,l=2e4,f=i.indexOf("--max-ms");f>=0&&i[f+1]&&(l=Math.max(100,Number(i[f+1])));let{ready:a,elapsedMs:y,nodes:S,targets:T,flag:k,loadingText:h,errors:v}=await Ye(d,l);if(a){console.log(` ready in ${y}ms: ${S} nodes, ${T} targets`);return}let N=h?`still showing "${h}"`:k!==!0?"guest app has not emitted sootsim:externalAppReady":T<=0?"ready flag emitted but no visible app content is inspectable yet":"node tree is still changing";console.error(` \u26A0 wait ready timed out after ${y}ms \u2014 ${N} (nodes: ${S}, targets: ${T}, errors: ${v})`),process.exit(1)}async function At(s){let{bridge:d,args:i,positional:l,inspectUsage:f}=s,a=l[1];a||(console.error(f("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let y=i.indexOf("--max-ms"),S=y>=0&&i[y+1]?Math.max(100,Number(i[y+1])):5e3,{found:T,node:k,elapsed:h}=await Ge(d,a,S);if(T&&k){let v=k.absolutePosition?`@(${Math.round(k.absolutePosition.x)},${Math.round(k.absolutePosition.y)})`:"",N=k.layout?`${Math.round(k.layout.width)}x${Math.round(k.layout.height)}`:"?x?";console.log(` found #${a} in ${h}ms ${N} ${v}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${h??S}ms`),process.exit(1)}function Ct(s){return s==null?"\u2014":s<1024?`${s}B`:s<1024*1024?`${(s/1024).toFixed(1)}K`:`${(s/1024/1024).toFixed(1)}M`}function Bt(s){return s==null?" \u2026":s<1e3?`${s}ms`.padStart(5):`${(s/1e3).toFixed(2)}s`.padStart(5)}function lo(s){return s.error?"err":s.status==null?" \u2026 ":String(s.status)}function Ot(s){let d=new Date(s.startTs).toLocaleTimeString(),i=lo(s).padEnd(3),l=s.method.padEnd(5),f=Ct(s.size).padStart(6),a=Bt(s.durationMs);console.log(` [${d}] ${i} ${l} ${f} ${a} ${s.displayUrl}`),s.error&&console.log(` error: ${s.error}`)}function co(s){let d=[["id",s.id],["source",s.source],["kind",s.kind],["method",s.method],["status",s.error?`error: ${s.error}`:`${s.status??"\u2014"} ${s.statusText??""}`.trim()],["url",s.url],["started",new Date(s.startTs).toLocaleTimeString()],["duration",Bt(s.durationMs).trim()],["size",Ct(s.size)],["content-type",s.type??"\u2014"]];for(let[i,l]of d)console.log(` ${i.padEnd(13)} ${l}`)}var uo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Pt="\x1B[0m",mo="\x1B[2m";function Rt(s,d){let i=new Date(s.ts).toLocaleTimeString(),l=s.level.toUpperCase().padEnd(5),f=s.args.join(" ");if(d){let a=uo[s.level];console.log(` ${mo}[${i}]${Pt} ${a}${l}${Pt} ${f}`)}else console.log(` [${i}] ${l} ${f}`);if(s.stack&&s.level==="error"){let a=s.stack.split(`
89
+ `).slice(0,5);for(let y of a)console.log(` ${y.trim()}`)}}var Q="__sootsimCliPerf",po=120;async function Et(s,d){let i=s.find((N,M)=>s[M-1]==="--id"),l=s.find((N,M)=>s[M-1]==="--text");if(i||l){let N=await d.send({type:"evaluate",code:Le({id:i,text:l})});if(!N)throw new Error(i?`no node with id "${i}"`:`no node matching text "${l}"`);let{x:M,y:E,w:J,h:c}=N;return{x:M,y:E,w:J,h:c}}let f=s.find((N,M)=>s[M-1]==="--area");if(f){let N=f.split(",").map(K=>Number(K.trim()));if(N.length!==4||N.some(K=>!Number.isFinite(K)))throw new Error(`--area expects x,y,w,h (got "${f}")`);let[M,E,J,c]=N;return{x:M,y:E,w:J,h:c}}let a=N=>{let M=s.find((J,c)=>s[c-1]===N);if(M==null)return null;let E=Number(M);return Number.isFinite(E)?E:null},y=a("--x"),S=a("--y"),T=a("--w"),k=a("--h");if(y!=null||S!=null||T!=null||k!=null)return{x:y??0,y:S??0,w:T??1,h:k??1};let v=s.filter((N,M)=>M>0&&!N.startsWith("-")&&s[M-1]!=="--output"&&s[M-1]!=="--area"&&s[M-1]!=="--id"&&s[M-1]!=="--text"&&s[M-1]!=="--x"&&s[M-1]!=="--y"&&s[M-1]!=="--w"&&s[M-1]!=="--h").map(Number).filter(N=>Number.isFinite(N));if(v.length>=2){let[N,M,E=1,J=1]=v;return{x:N,y:M,w:E,h:J}}return null}function Ne(s){let d={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of s)i<8?d["<8"]++:i<12?d["8-12"]++:i<16?d["12-16"]++:i<20?d["16-20"]++:i<33?d["20-33"]++:d[">33"]++;console.log(" histogram:");for(let[i,l]of Object.entries(d)){let f="\u2588".repeat(Math.ceil(l/s.length*40));console.log(` ${i.padEnd(6)} ${f} ${l}`)}}async function fe(s,d,i){let l=Date.now()+d,f=await se(s,d);for(;;){if(i(f))return{settled:!0,state:f};if(Date.now()>=l)return{settled:!1,state:f};await X(16),f=await se(s)}}async function Fe(s){return s.send({type:"evaluate",code:`(async () => {
83
90
  const kb = window.__sootsimKeyboard
84
91
  const test = window.__sootsimTest
85
92
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -111,7 +118,7 @@ import{a as G}from"./chunk-ZLMNBI7T.js";import{a as Je,b as Le}from"./chunk-F2DS
111
118
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
112
119
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
113
120
  }
114
- })()`})}async function fo(o,d=600){let i=Date.now()+d;for(;Date.now()<=i;){let l=await Fe(o);if(l.visible)return l;await X(30)}return Fe(o)}async function ge(o,d){let i=await Fe(o);if(i.visible)return i;console.error(` ${d} 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 Ct(o,d,i){return d==="appearance"?o.send({type:"evaluate",code:`(async () => {
121
+ })()`})}async function fo(s,d=600){let i=Date.now()+d;for(;Date.now()<=i;){let l=await Fe(s);if(l.visible)return l;await X(30)}return Fe(s)}async function ge(s,d){let i=await Fe(s);if(i.visible)return i;console.error(` ${d} 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 Dt(s,d,i){return d==="appearance"?s.send({type:"evaluate",code:`(async () => {
115
122
  const requested = ${JSON.stringify(i??"toggle")}
116
123
  const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
117
124
  const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
@@ -125,28 +132,28 @@ import{a as G}from"./chunk-ZLMNBI7T.js";import{a as Je,b as Le}from"./chunk-F2DS
125
132
  ? (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'dark' : 'light')
126
133
  : next
127
134
  return { ok: true, requested, value: next, applied }
128
- })()`}):o.send({type:"evaluate",code:`(async () => {
135
+ })()`}):s.send({type:"evaluate",code:`(async () => {
129
136
  window.dispatchEvent(new CustomEvent(${JSON.stringify(d==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
130
137
  return { ok: true, action: ${JSON.stringify(d)} }
131
- })()`})}function go(o){let d={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(d[o])return d[o];let i=o.match(/^Digit([0-9])$/);if(i)return i[1];let l=o.match(/^Key([A-Z])$/);return l?l[1].toLowerCase():null}function yo(o){if(typeof o!="string")return null;let d=o.replace(/\s+/g," ").trim();return d?d.slice(0,80):null}function jt(...o){for(let d of o){if(typeof d!="string")continue;let i=d.trim();if(i)return i}return null}async function J(o,d,i){let l=ce({source:o,step:d,summary:i});l.active&&(l.replaced?console.error(` draft: replaced unkept action "${l.replaced.summary}" \u2014 \`flow keep\` commits one action at a time`):console.error(" draft: action pending \u2014 `sootsim flow keep` to commit"))}function ho(o,d,i){if(!i||i.hit===!1)return null;let l=jt(i.responderTestID,i.testID);if(l)return{step:{tapOn:{id:l}},summary:`tap #${l}`};let f=yo(i.text);return f?{step:{tapOn:f},summary:`tap "${f}"`}:{step:{tapAtCoords:{x:o,y:d}},summary:`tap @${Math.round(o)},${Math.round(d)}`}}function _e(o,d,i){let l=jt(d?.testID,d?.id);return l?{step:{tapOn:{id:l}},summary:`tap #${l}`}:i==="id"?{step:{tapOn:{id:o}},summary:`tap #${o}`}:{step:{tapOn:o},summary:`tap "${o}"`}}async function Vs(o,d){let i=o[0]==="get"||o[0]==="do"||o[0]==="debug"||o[0]==="wait"?o[0]:null,l=i?o.slice(1):o,f=Re(l,{port:d.port,commandTimeoutMs:d.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--slow","--tail","-f","--interactive-targets","--actions","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--max-ms","--filter","--limit","--level","--threshold","--equals","--since"]}),a=f.positional,y=a[0],S=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",N=typeof l[0]=="string"&&Pe.has(l[0]),k=N?l[0]:null,b=t=>N&&t===l[0]?`sootsim ${t}`:`sootsim ${S} ${t}`,v=(t,e)=>` usage: ${b(t)}${e?` ${e}`:""}`;if(!y||o.includes("--help")||o.includes("-h")){let t={bridgePort:7668,defaultShellUrl:Ae};if(S==="do"||S==="get"||S==="debug"||S==="wait"){let n=we(S,t);n&&(console.log(`${n}
132
- `),process.exit(0))}if(k==="shell"){let n=$e("shell",t);n&&(console.log(`${n}
133
- `),process.exit(0))}let e=$e("inspect",t),s=["do","get","debug","wait"].map(n=>we(n,t)).filter(n=>n!=null).join(`
138
+ })()`})}function go(s){let d={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(d[s])return d[s];let i=s.match(/^Digit([0-9])$/);if(i)return i[1];let l=s.match(/^Key([A-Z])$/);return l?l[1].toLowerCase():null}function yo(s){if(typeof s!="string")return null;let d=s.replace(/\s+/g," ").trim();return d?d.slice(0,80):null}function jt(...s){for(let d of s){if(typeof d!="string")continue;let i=d.trim();if(i)return i}return null}function ho(s){let d=s.indexOf("--node-id");if(d<0)return null;let i=s[d+1];if(!i)return null;let l=Number(i);return Number.isInteger(l)&&l>0?l:null}async function L(s,d,i){let l=ce({source:s,step:d,summary:i});l.active&&(l.replaced?console.error(` draft: replaced unkept action "${l.replaced.summary}" \u2014 \`flow keep\` commits one action at a time`):console.error(" draft: action pending \u2014 `sootsim flow keep` to commit"))}function bo(s,d,i){if(!i||i.hit===!1)return null;let l=jt(i.responderTestID,i.testID);if(l)return{step:{tapOn:{id:l}},summary:`tap #${l}`};let f=yo(i.text);return f?{step:{tapOn:f},summary:`tap "${f}"`}:{step:{tapAtCoords:{x:s,y:d}},summary:`tap @${Math.round(s)},${Math.round(d)}`}}function _e(s,d,i){let l=jt(d?.testID,d?.id);return l?{step:{tapOn:{id:l}},summary:`tap #${l}`}:i==="id"?{step:{tapOn:{id:s}},summary:`tap #${s}`}:{step:{tapOn:s},summary:`tap "${s}"`}}async function Qs(s,d){let i=s[0]==="get"||s[0]==="do"||s[0]==="debug"||s[0]==="wait"?s[0]:null,l=i?s.slice(1):s,f=Re(l,{port:d.port,commandTimeoutMs:d.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--slow","--tail","-f","--interactive-targets","--actions","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--node-id","--max-ms","--filter","--limit","--level","--threshold","--equals","--since"]}),a=f.positional,y=a[0],S=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",T=typeof l[0]=="string"&&Oe.has(l[0]),k=T?l[0]:null,h=t=>T&&t===l[0]?`sootsim ${t}`:`sootsim ${S} ${t}`,v=(t,e)=>` usage: ${h(t)}${e?` ${e}`:""}`;if(!y||s.includes("--help")||s.includes("-h")){let t={bridgePort:7668,defaultShellUrl:Ae};if(S==="do"||S==="get"||S==="debug"||S==="wait"){let n=we(S,t);n&&(console.log(`${n}
139
+ `),process.exit(0))}if(k==="shell"){let n=xe("shell",t);n&&(console.log(`${n}
140
+ `),process.exit(0))}let e=xe("inspect",t),o=["do","get","debug","wait"].map(n=>we(n,t)).filter(n=>n!=null).join(`
134
141
 
135
142
  `);console.log(`${e??""}
136
143
 
137
- ${s}
138
- `),process.exit(0)}let _=f.wsPort,T=f.simId,E=f.simIdSource,L=f.commandTimeoutMs;if(y==="list"&&l.some(t=>t==="--drivers"||t==="-D")){let{buildDriverListRows:t}=await import("./drivers-7PFWCFVQ.js"),e=t();console.log(` available drivers (${e.length}):
139
- `);let s=Math.max(...e.map(r=>r.id.length),6),n=Math.max(...e.map(r=>r.kind.length),4);for(let r of e){let u=r.available?"\u2713":"\u2717",m=r.id.padEnd(s),x=r.kind.padEnd(n);console.log(` ${u} ${m} ${x} ${r.description}`),r.available&&r.detail?console.log(` ${r.detail}`):!r.available&&r.reason&&console.log(` unavailable: ${r.reason}`)}return}let c=Ee(f),K=T||"default",j=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]),C=200;function Y(t){let e=t.replace(/\s+/g," ").trim();if(!e)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(e)){let n=/<title[^>]*>([^<]+)<\/title>/i.exec(t)?.[1]?.trim(),r=/<body[^>]*>([\s\S]*?)<\//i.exec(t)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),u=n||r||"html error page";return`<html ${t.length}B> "${u}" (body elided \u2014 add --json for the full payload)`}return e.length<=C?e:`${e.slice(0,C)}\u2026 (+${e.length-C} more bytes)`}function W(t){let e=t.displayUrl||t.url;return t.status!=null?`${t.method} ${e} -> ${t.status}${t.statusText?` ${t.statusText}`:""}`:t.error?`${t.method} ${e} -> ${t.error}`:`${t.method} ${e}`}async function w(t){let e=yt()?1200:350;try{let{settled:s,elapsed:n}=await ne({bridge:t,maxMs:e,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${n??e}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
140
- `)}catch{}}async function I(){try{return await c.send({type:"evaluate",code:`(() => ({
144
+ ${o}
145
+ `),process.exit(0)}let N=f.wsPort,M=f.simId,E=f.simIdSource,J=f.commandTimeoutMs;if(y==="list"&&l.some(t=>t==="--drivers"||t==="-D")){let{buildDriverListRows:t}=await import("./drivers-EQGVLU5S.js"),e=t();console.log(` available drivers (${e.length}):
146
+ `);let o=Math.max(...e.map(r=>r.id.length),6),n=Math.max(...e.map(r=>r.kind.length),4);for(let r of e){let u=r.available?"\u2713":"\u2717",m=r.id.padEnd(o),w=r.kind.padEnd(n);console.log(` ${u} ${m} ${w} ${r.description}`),r.available&&r.detail?console.log(` ${r.detail}`):!r.available&&r.reason&&console.log(` unavailable: ${r.reason}`)}return}let c=Ee(f),K=M||"default",j=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]),D=200;function Y(t){let e=t.replace(/\s+/g," ").trim();if(!e)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(e)){let n=/<title[^>]*>([^<]+)<\/title>/i.exec(t)?.[1]?.trim(),r=/<body[^>]*>([\s\S]*?)<\//i.exec(t)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),u=n||r||"html error page";return`<html ${t.length}B> "${u}" (body elided \u2014 add --json for the full payload)`}return e.length<=D?e:`${e.slice(0,D)}\u2026 (+${e.length-D} more bytes)`}function W(t){let e=t.displayUrl||t.url;return t.status!=null?`${t.method} ${e} -> ${t.status}${t.statusText?` ${t.statusText}`:""}`:t.error?`${t.method} ${e} -> ${t.error}`:`${t.method} ${e}`}async function x(t){let e=yt()?1200:350;try{let{settled:o,elapsed:n}=await ne({bridge:t,maxMs:e,pollMs:32,stablePolls:2});o||process.stderr.write(` \u26A0 auto-wait timed out after ${n??e}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
147
+ `)}catch{}}async function _(){try{return await c.send({type:"evaluate",code:`(() => ({
141
148
  console: window.__sootsimConsole?.count?.() || null,
142
149
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
143
- }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function Z(t={}){let e=t.counts!==void 0?t.counts:await z(c,"getRequestCounts");if(!e||typeof e!="object")return;let s=Math.max(0,Number(e.failed)||0);if(s===0||!t.includeTail&&!Te("requests",K,String(s))||(console.log(`
144
- network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${b("requests")} 5`),!t.includeTail))return;let n=await z(c,"getFailedRequests",5);if(!(!Array.isArray(n)||n.length===0)){console.log(`
150
+ }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function Z(t={}){let e=t.counts!==void 0?t.counts:await z(c,"getRequestCounts");if(!e||typeof e!="object")return;let o=Math.max(0,Number(e.failed)||0);if(o===0||!t.includeTail&&!Te("requests",K,String(o))||(console.log(`
151
+ network: ${o} failed request${o===1?"":"s"}`),console.log(` inspect: ${h("requests")} 5`),!t.includeTail))return;let n=await z(c,"getFailedRequests",5);if(!(!Array.isArray(n)||n.length===0)){console.log(`
145
152
  recent failed requests:
146
- `);for(let r of n){let u=new Date(r.timestamp).toLocaleTimeString();console.log(` [${u}] ${W(r)}`),r.responseBody?console.log(` ${Y(r.responseBody)}`):r.error&&console.log(` ${r.error}`)}}}async function P(t={}){let e=t.counts!==void 0?t.counts:await c.send({type:"evaluate",code:"window.__sootsimConsole?.count?.() || { errors: 0, warnings: 0, total: 0 }"});if(!e||typeof e!="object")return;let s=e,n=Math.max(0,Number(s.errors)||0),r=Math.max(0,Number(s.warnings)||0);if(n===0&&r===0||!t.includeTail&&!Te("console",K,`${n}:${r}`))return;let u=[];if(n>0&&u.push(`${n} console error${n===1?"":"s"}`),r>0&&u.push(`${r} console warning${r===1?"":"s"}`),console.log(`
147
- console: ${u.join(", ")}`),console.log(` inspect: ${b("errors")} 5`),r>0&&console.log(` inspect: ${b("warnings")} 5`),!t.includeTail||n===0)return;let m=await c.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors?.(5) || []"});if(!(!Array.isArray(m)||m.length===0)){console.log(`
153
+ `);for(let r of n){let u=new Date(r.timestamp).toLocaleTimeString();console.log(` [${u}] ${W(r)}`),r.responseBody?console.log(` ${Y(r.responseBody)}`):r.error&&console.log(` ${r.error}`)}}}async function O(t={}){let e=t.counts!==void 0?t.counts:await c.send({type:"evaluate",code:"window.__sootsimConsole?.count?.() || { errors: 0, warnings: 0, total: 0 }"});if(!e||typeof e!="object")return;let o=e,n=Math.max(0,Number(o.errors)||0),r=Math.max(0,Number(o.warnings)||0);if(n===0&&r===0||!t.includeTail&&!Te("console",K,`${n}:${r}`))return;let u=[];if(n>0&&u.push(`${n} console error${n===1?"":"s"}`),r>0&&u.push(`${r} console warning${r===1?"":"s"}`),console.log(`
154
+ console: ${u.join(", ")}`),console.log(` inspect: ${h("errors")} 5`),r>0&&console.log(` inspect: ${h("warnings")} 5`),!t.includeTail||n===0)return;let m=await c.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors?.(5) || []"});if(!(!Array.isArray(m)||m.length===0)){console.log(`
148
155
  recent console errors:
149
- `);for(let x of m){let g=new Date(x.timestamp).toLocaleTimeString(),$=Array.isArray(x.args)?x.args.map(F=>typeof F=="object"?JSON.stringify(F):String(F)).join(" "):String(x);console.log(` [${g}] ${$}`)}}}let V=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function oe(t){let e=Oe(),s=null;try{s=await De(t,`(() => {
156
+ `);for(let w of m){let g=new Date(w.timestamp).toLocaleTimeString(),$=Array.isArray(w.args)?w.args.map(F=>typeof F=="object"?JSON.stringify(F):String(F)).join(" "):String(w);console.log(` [${g}] ${$}`)}}}let V=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function oe(t){let e=Pe(),o=null;try{o=await Ce(t,`(() => {
150
157
  const tl = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.timeline
151
158
  if (!tl || typeof tl.summary !== 'function') return null
152
159
  const cursorKey = ${JSON.stringify(e)}
@@ -162,9 +169,9 @@ ${s}
162
169
  }
163
170
  }
164
171
  return summary ? { summary, consoleSplit } : null
165
- })()`)}catch{return}if(!s||!s.summary||!s.summary.total)return;let n=s.summary.byKind??{},r=[],u=new Set;for(let m of V){let x=n[m];if(x)if(u.add(m),m==="console"&&s.consoleSplit){let{error:g,warn:$}=s.consoleSplit;g>0&&r.push(`${g} error${g===1?"":"s"}`),$>0&&r.push(`${$} warning${$===1?"":"s"}`)}else r.push(`${x} ${m}${x===1?"":"s"}`)}for(let[m,x]of Object.entries(n))!u.has(m)&&x&&r.push(`${x} ${m}${x===1?"":"s"}`);if(r.length!==0&&(console.log(`
166
- since last: ${r.join(" \xB7 ")} \u2014 sootsim what-happened`),s.summary.lastAt))try{await xe(t,"SootSim.bridges.timeline.cursorAdvance",e,s.summary.lastAt)}catch{}}let ee=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"]),ye=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"]),he=(o.includes("--verbose")||o.includes("-v"))&&!o.includes("--json");S==="do"&&y==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),ee.has(y)&&await Ce(c),ye.has(y)&&await de(c,{verbose:he});try{switch(y){case"list":{await wt({bridge:c,simId:T,args:l});break}case"tree":{await kt({bridge:c,args:l,positional:a});break}case"a11y":{let t=await Ke(c);if(!Array.isArray(t)||t.length===0){console.log(" no accessible nodes found");break}if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{console.log(` accessibility tree (${t.length} nodes):
167
- `);for(let e of t){let s=[];if(s.push(`[${e.role}]`),e.label){let n=e.label.length>50?e.label.slice(0,47)+"...":e.label;s.push(`"${n}"`)}if(e.hint&&s.push(`(hint: "${e.hint}")`),e.testID&&s.push(`#${e.testID}`),e.state){let n=[];e.state.disabled&&n.push("disabled"),e.state.selected&&n.push("selected"),e.state.checked===!0&&n.push("checked"),e.state.checked==="mixed"&&n.push("mixed"),e.state.busy&&n.push("busy"),e.state.expanded===!0&&n.push("expanded"),e.state.expanded===!1&&n.push("collapsed"),n.length&&s.push(`{${n.join(", ")}}`)}e.position&&s.push(`@(${e.position.x},${e.position.y})`),e.size&&s.push(`${e.size.w}x${e.size.h}`),console.log(" "+s.join(" "))}}break}case"find":{await ht({bridge:c,args:o,effectiveArgs:l,positional:a,inspectUsage:v});break}case"count":{await ft(c,{args:l});break}case"keyboard":{await bt(c,{json:o.includes("--json")});break}case"screens":{await xt(c,{json:o.includes("--json")});break}case"memory":{await $t(c,{args:l});break}case"wait":{await Mt({wsPort:_,commandTimeoutMs:L,simId:T,simIdSource:E,positional:a});break}case"sleep":{await vt({positional:a,inspectUsage:v});break}case"settle":{await St({bridge:c,args:o,positional:a});break}case"ready":{await Ft({bridge:c,args:o});break}case"idle":{await _t({bridge:c,args:o,positional:a});break}case"selector":{await At({bridge:c,args:o,positional:a,inspectUsage:v});break}case"event":{await Nt({bridge:c,args:o,positional:a,inspectUsage:v});break}case"layout":{let t=a[1];t||(console.error(v("layout","<id>")),process.exit(1));let e=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(t)}))()`});console.log(JSON.stringify(e,null,2));break}case"capture":case"screenshot":{let e=o.find((x,g)=>o[g-1]==="--output")||"/tmp/sootsim-inspect.png",s=await Et(o,c),n={type:"screenshot"};s&&(n.crop=s);let u=(await c.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(e,Buffer.from(u,"base64")),console.log(` saved: ${e}`);break}case"sample-color":{let t=await Et(o,c);t||(console.error(v("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 e=await c.send({type:"evaluate",code:Le(t)});if(o.includes("--json"))console.log(JSON.stringify(e,null,2));else{let{r:s,g:n,b:r,a:u,hex:m,samples:x}=e,g=t.w===1&&t.h===1?`@(${t.x},${t.y})`:`@(${t.x},${t.y}) ${t.w}x${t.h}`;console.log(` ${m} rgba(${s}, ${n}, ${r}, ${u}) ${g} ${x} samples`)}break}case"node":{let t=a[1];t||(console.error(v("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let e=await c.send({type:"evaluate",code:`(async () => {
172
+ })()`)}catch{return}if(!o||!o.summary||!o.summary.total)return;let n=o.summary.byKind??{},r=[],u=new Set;for(let m of V){let w=n[m];if(w)if(u.add(m),m==="console"&&o.consoleSplit){let{error:g,warn:$}=o.consoleSplit;g>0&&r.push(`${g} error${g===1?"":"s"}`),$>0&&r.push(`${$} warning${$===1?"":"s"}`)}else r.push(`${w} ${m}${w===1?"":"s"}`)}for(let[m,w]of Object.entries(n))!u.has(m)&&w&&r.push(`${w} ${m}${w===1?"":"s"}`);if(r.length!==0&&(console.log(`
173
+ since last: ${r.join(" \xB7 ")} \u2014 sootsim what-happened`),o.summary.lastAt))try{await $e(t,"SootSim.bridges.timeline.cursorAdvance",e,o.summary.lastAt)}catch{}}let ee=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"]),ye=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"]),he=(s.includes("--verbose")||s.includes("-v"))&&!s.includes("--json");S==="do"&&y==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),ee.has(y)&&await De(c),ye.has(y)&&await de(c,{verbose:he});try{switch(y){case"list":{await wt({bridge:c,simId:M,args:l});break}case"tree":{await kt({bridge:c,args:l,positional:a});break}case"a11y":{let t=await Ke(c);if(!Array.isArray(t)||t.length===0){console.log(" no accessible nodes found");break}if(s.includes("--json"))console.log(JSON.stringify(t,null,2));else{console.log(` accessibility tree (${t.length} nodes):
174
+ `);for(let e of t){let o=[];if(o.push(`[${e.role}]`),e.label){let n=e.label.length>50?e.label.slice(0,47)+"...":e.label;o.push(`"${n}"`)}if(e.hint&&o.push(`(hint: "${e.hint}")`),e.testID&&o.push(`#${e.testID}`),e.state){let n=[];e.state.disabled&&n.push("disabled"),e.state.selected&&n.push("selected"),e.state.checked===!0&&n.push("checked"),e.state.checked==="mixed"&&n.push("mixed"),e.state.busy&&n.push("busy"),e.state.expanded===!0&&n.push("expanded"),e.state.expanded===!1&&n.push("collapsed"),n.length&&o.push(`{${n.join(", ")}}`)}e.position&&o.push(`@(${e.position.x},${e.position.y})`),e.size&&o.push(`${e.size.w}x${e.size.h}`),console.log(" "+o.join(" "))}}break}case"find":{await ht({bridge:c,args:s,effectiveArgs:l,positional:a,inspectUsage:v});break}case"count":{await ft(c,{args:l});break}case"keyboard":{await bt(c,{json:s.includes("--json")});break}case"screens":{await $t(c,{json:s.includes("--json")});break}case"memory":{await xt(c,{args:l});break}case"wait":{await Mt({wsPort:N,commandTimeoutMs:J,simId:M,simIdSource:E,positional:a});break}case"sleep":{await vt({positional:a,inspectUsage:v});break}case"settle":{await St({bridge:c,args:s,positional:a});break}case"ready":{await Ft({bridge:c,args:s});break}case"idle":{await _t({bridge:c,args:s,positional:a});break}case"selector":{await At({bridge:c,args:s,positional:a,inspectUsage:v});break}case"event":{await Nt({bridge:c,args:s,positional:a,inspectUsage:v});break}case"layout":{let t=a[1];t||(console.error(v("layout","<id>")),process.exit(1));let e=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(t)}))()`});console.log(JSON.stringify(e,null,2));break}case"capture":case"screenshot":{let e=s.find((w,g)=>s[g-1]==="--output")||"/tmp/sootsim-inspect.png",o=await Et(s,c),n={type:"screenshot"};o&&(n.crop=o);let u=(await c.send(n)).replace(/^data:image\/png;base64,/,"");o&&console.log(` area: x=${o.x} y=${o.y} w=${o.w} h=${o.h}`),(await import("fs")).writeFileSync(e,Buffer.from(u,"base64")),console.log(` saved: ${e}`);break}case"sample-color":{let t=await Et(s,c);t||(console.error(v("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 e=await c.send({type:"evaluate",code:Je(t)});if(s.includes("--json"))console.log(JSON.stringify(e,null,2));else{let{r:o,g:n,b:r,a:u,hex:m,samples:w}=e,g=t.w===1&&t.h===1?`@(${t.x},${t.y})`:`@(${t.x},${t.y}) ${t.w}x${t.h}`;console.log(` ${m} rgba(${o}, ${n}, ${r}, ${u}) ${g} ${w} samples`)}break}case"node":{let t=a[1];t||(console.error(v("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let e=await c.send({type:"evaluate",code:`(async () => {
168
175
  const t = window.__sootsimTest
169
176
  const q = ${JSON.stringify(t)}
170
177
  let node = null
@@ -220,20 +227,20 @@ ${s}
220
227
  transform,
221
228
  parentChain,
222
229
  }
223
- })()`});console.log(JSON.stringify(e,null,2));break}case"tap":{let t=Number(a[1]),e=Number(a[2]),s=ae(o);if(s){let u=await me(c,s);u||(console.error(` not found: ${s.value}`),s.mode==="testid"&&G("wait-selector-for-missing-testid",s.value),process.exit(1)),t=u.x,e=u.y}(!Number.isFinite(t)||!Number.isFinite(e))&&(console.error(v("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let n=await c.send({type:"tap",x:t,y:e}),r=ho(t,e,n);r&&await J("inspect tap",r.step,r.summary),console.log(JSON.stringify(n,null,2));break}case"drag":case"swipe":{let t=Number(a[1]),e=Number(a[2]),s=Number(a[3]),n=Number(a[4]),r=y==="swipe"?10:12,u=y==="swipe"?8:16,m=a[5]?Number(a[5]):r,x=a[6]?Number(a[6]):u;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(x))&&(console.error(v(y,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let g=await c.send({type:"evaluate",code:`(async () => {
230
+ })()`});console.log(JSON.stringify(e,null,2));break}case"tap":{let t=Number(a[1]),e=Number(a[2]),o=ae(s),n=null;if(o){let m=await me(c,o);m||(console.error(` not found: ${o.value}`),o.mode==="testid"&&G("wait-selector-for-missing-testid",o.value),process.exit(1)),t=m.x,e=m.y,n=m}(!Number.isFinite(t)||!Number.isFinite(e))&&(console.error(v("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await c.send({type:"tap",x:t,y:e,...o?{target:{id:n?.id??(o.mode==="testid"?o.value:null),testID:n?.testID??(o.mode==="testid"?o.value:null),text:n?.text??(o.mode==="text"?o.value:null),type:n?.type??null}}:{}}),u=bo(t,e,r);u&&await L("inspect tap",u.step,u.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let t=Number(a[1]),e=Number(a[2]),o=Number(a[3]),n=Number(a[4]),r=y==="swipe"?10:12,u=y==="swipe"?8:16,m=a[5]?Number(a[5]):r,w=a[6]?Number(a[6]):u;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(o)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(w))&&(console.error(v(y,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let g=await c.send({type:"evaluate",code:`(async () => {
224
231
  const interact = window.__sootsimInteract
225
232
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
226
- const value = await interact.drag(${t}, ${e}, ${s}, ${n}, ${Math.max(1,Math.round(m))}, ${Math.max(0,Math.round(x))})
233
+ const value = await interact.drag(${t}, ${e}, ${o}, ${n}, ${Math.max(1,Math.round(m))}, ${Math.max(0,Math.round(w))})
227
234
  return { ok: !!value, value }
228
- })()`});if(g?.ok){let $=Math.max(1,Math.round(Math.max(1,m)*Math.max(0,x)));await J(`inspect ${y}`,{swipe:{start:`${t}, ${e}`,end:`${s}, ${n}`,duration:$}},`${y} ${t},${e} -> ${s},${n}`)}console.log(JSON.stringify(g,null,2));break}case"pinch":{let t=Number(a[1]),e=Number(a[2]),s=Number(a[3]),n=Number(a[4]),r=Number(a[5]),u=Number(a[6]),m=Number(a[7]),x=Number(a[8]),g=a[9]?Number(a[9]):12,$=a[10]?Number(a[10]):16;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(x)||!Number.isFinite(g)||!Number.isFinite($))&&(console.error(v("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let F=await c.send({type:"evaluate",code:`(async () => {
235
+ })()`});if(g?.ok){let $=Math.max(1,Math.round(Math.max(1,m)*Math.max(0,w)));await L(`inspect ${y}`,{swipe:{start:`${t}, ${e}`,end:`${o}, ${n}`,duration:$}},`${y} ${t},${e} -> ${o},${n}`)}console.log(JSON.stringify(g,null,2));break}case"pinch":{let t=Number(a[1]),e=Number(a[2]),o=Number(a[3]),n=Number(a[4]),r=Number(a[5]),u=Number(a[6]),m=Number(a[7]),w=Number(a[8]),g=a[9]?Number(a[9]):12,$=a[10]?Number(a[10]):16;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(o)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(w)||!Number.isFinite(g)||!Number.isFinite($))&&(console.error(v("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let F=await c.send({type:"evaluate",code:`(async () => {
229
236
  const interact = window.__sootsimInteract
230
237
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
231
- const value = await interact.pinch(${t}, ${e}, ${s}, ${n}, ${r}, ${u}, ${m}, ${x}, ${Math.max(1,Math.round(g))}, ${Math.max(0,Math.round($))})
238
+ const value = await interact.pinch(${t}, ${e}, ${o}, ${n}, ${r}, ${u}, ${m}, ${w}, ${Math.max(1,Math.round(g))}, ${Math.max(0,Math.round($))})
232
239
  return { ok: !!value, value }
233
- })()`});F?.ok&&await J("inspect pinch",{pinch:{from:[t,e,s,n],to:[r,u,m,x],steps:Math.max(1,Math.round(g)),stepMs:Math.max(0,Math.round($))}},`pinch (${t},${e}) (${s},${n}) -> (${r},${u}) (${m},${x})`),console.log(JSON.stringify(F,null,2));break}case"tap-text":{let t=a[1];t||(console.error(v("tap-text","<text>")),process.exit(1));let e=R=>{let A=o.indexOf(R);return A>=0&&A+1<o.length?o[A+1]:null},s=R=>o.includes(R),n=e("--nth")??e("--index"),r=n!==null?Number(n):null;r!==null&&!Number.isFinite(r)&&(console.error(` --nth/--index requires an integer, got: ${n}`),process.exit(1));let u=e("--within"),m=e("--role"),x=s("--exact"),g=s("--first"),$=e("--min-y"),F=e("--max-y"),q=e("--min-x"),H=e("--max-x");for(let[R,A]of[["--min-y",$],["--max-y",F],["--min-x",q],["--max-x",H]])A!==null&&!Number.isFinite(Number(A))&&(console.error(` ${R} requires a number, got: ${A}`),process.exit(1));let U=o.indexOf("--near"),M=null;if(U>=0){let R=Number(o[U+1]),A=Number(o[U+2]);(!Number.isFinite(R)||!Number.isFinite(A))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),M={x:R,y:A}}let h=JSON.stringify({query:t,exact:x,role:m,within:u,minX:q!==null?Number(q):null,maxX:H!==null?Number(H):null,minY:$!==null?Number($):null,maxY:F!==null?Number(F):null,near:M,nth:r,first:g}),p=await c.send({type:"evaluate",code:`(async () => {
240
+ })()`});F?.ok&&await L("inspect pinch",{pinch:{from:[t,e,o,n],to:[r,u,m,w],steps:Math.max(1,Math.round(g)),stepMs:Math.max(0,Math.round($))}},`pinch (${t},${e}) (${o},${n}) -> (${r},${u}) (${m},${w})`),console.log(JSON.stringify(F,null,2));break}case"tap-text":{let t=a[1];t||(console.error(v("tap-text","<text>")),process.exit(1));let e=R=>{let A=s.indexOf(R);return A>=0&&A+1<s.length?s[A+1]:null},o=R=>s.includes(R),n=e("--nth")??e("--index"),r=n!==null?Number(n):null;r!==null&&!Number.isFinite(r)&&(console.error(` --nth/--index requires an integer, got: ${n}`),process.exit(1));let u=e("--within"),m=e("--role"),w=o("--exact"),g=o("--first"),$=e("--min-y"),F=e("--max-y"),q=e("--min-x"),H=e("--max-x");for(let[R,A]of[["--min-y",$],["--max-y",F],["--min-x",q],["--max-x",H]])A!==null&&!Number.isFinite(Number(A))&&(console.error(` ${R} requires a number, got: ${A}`),process.exit(1));let U=s.indexOf("--near"),I=null;if(U>=0){let R=Number(s[U+1]),A=Number(s[U+2]);(!Number.isFinite(R)||!Number.isFinite(A))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),I={x:R,y:A}}let b=JSON.stringify({query:t,exact:w,role:m,within:u,minX:q!==null?Number(q):null,maxX:H!==null?Number(H):null,minY:$!==null?Number($):null,maxY:F!==null?Number(F):null,near:I,nth:r,first:g}),p=await c.send({type:"evaluate",code:`(async () => {
234
241
  const t = window.__sootsimTest
235
242
  if (!t) return { error: 'bridge-not-ready' }
236
- const F = ${h}
243
+ const F = ${b}
237
244
 
238
245
  const res = await t.queryTextCandidates({
239
246
  query: F.query,
@@ -338,13 +345,19 @@ ${s}
338
345
  nodeId: target.nodeId ?? null,
339
346
  id: target.id,
340
347
  testID: target.testID,
348
+ text:
349
+ target.text ??
350
+ target.accessibilityLabel ??
351
+ n.text ??
352
+ n.accessibilityLabel ??
353
+ null,
341
354
  type: target.type,
342
355
  },
343
356
  strategy: (resolved && resolved.strategy) || 'matched-node',
344
357
  total,
345
358
  idx,
346
359
  }
347
- })()`});if(p?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),p?.ambiguous){let R=p.candidates;console.error(` ambiguous: ${p.total} matches for "${t}"`);for(let A of R){let be=A.abs?`@(${Math.round(A.abs.x)},${Math.round(A.abs.y)})`:"",le=A.layout?` ${A.layout.width}x${A.layout.height}`:"",Jt=A.testID?` #${A.testID}`:"",Lt=A.text?` "${A.text}"`:"",Wt=A.ancestorTestIDs.length>0?` within ${A.ancestorTestIDs.slice(0,3).map(qt=>`#${qt}`).join(" > ")}`:"";console.error(` [${A.idx}] <${A.type}>${Lt}${Jt} ${be}${le}${Wt}`)}p.total>R.length&&console.error(` ... and ${p.total-R.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)}p?.nthOutOfRange&&(console.error(` not found: nth ${p.nth} of ${p.total} match${p.total===1?"":"es"} for "${t}"`),process.exit(1)),(!p||typeof p.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1));let O=await c.send({type:"tap",x:p.cx,y:p.cy});if(O?.hit!==!1&&O?.ok!==!1){let R=_e(t,{id:p.target?.id??null,testID:p.target?.testID??null,type:p.target?.type??null,cx:p.cx,cy:p.cy},"text");await J("inspect tap-text",R.step,R.summary)}console.log(JSON.stringify({matched:p.match,tapped:{nodeId:p.target?.nodeId??null,id:p.target?.id??null,testID:p.target?.testID??null,type:p.target?.type??null,cx:p.cx,cy:p.cy},...p.strategy&&p.strategy!=="matched-node"?{strategy:p.strategy}:{},...p.total>1||r!==null?{nth:{index:p.idx,total:p.total}}:{},result:O},null,2));break}case"tap-best":{let t=a[1];t||(console.error(v("tap-best","<query>")),process.exit(1));let e=JSON.stringify(t),s=await c.send({type:"evaluate",code:`(async () => {
360
+ })()`});if(p?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),p?.ambiguous){let R=p.candidates;console.error(` ambiguous: ${p.total} matches for "${t}"`);for(let A of R){let be=A.abs?`@(${Math.round(A.abs.x)},${Math.round(A.abs.y)})`:"",le=A.layout?` ${A.layout.width}x${A.layout.height}`:"",Lt=A.testID?` #${A.testID}`:"",Jt=A.text?` "${A.text}"`:"",Wt=A.ancestorTestIDs.length>0?` within ${A.ancestorTestIDs.slice(0,3).map(qt=>`#${qt}`).join(" > ")}`:"";console.error(` [${A.idx}] <${A.type}>${Jt}${Lt} ${be}${le}${Wt}`)}p.total>R.length&&console.error(` ... and ${p.total-R.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)}p?.nthOutOfRange&&(console.error(` not found: nth ${p.nth} of ${p.total} match${p.total===1?"":"es"} for "${t}"`),process.exit(1)),(!p||typeof p.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1));let P=await c.send({type:"tap",x:p.cx,y:p.cy,target:{id:p.target?.id??null,testID:p.target?.testID??null,text:t,type:p.target?.type??null}});if(P?.hit!==!1&&P?.ok!==!1){let R=_e(t,{id:p.target?.id??null,testID:p.target?.testID??null,type:p.target?.type??null,cx:p.cx,cy:p.cy},"text");await L("inspect tap-text",R.step,R.summary)}console.log(JSON.stringify({matched:p.match,tapped:{nodeId:p.target?.nodeId??null,id:p.target?.id??null,testID:p.target?.testID??null,type:p.target?.type??null,cx:p.cx,cy:p.cy},...p.strategy&&p.strategy!=="matched-node"?{strategy:p.strategy}:{},...p.total>1||r!==null?{nth:{index:p.idx,total:p.total}}:{},result:P},null,2));break}case"tap-best":{let t=a[1];t||(console.error(v("tap-best","<query>")),process.exit(1));let e=JSON.stringify(t),o=await c.send({type:"evaluate",code:`(async () => {
348
361
  const t = window.__sootsimTest
349
362
  if (!t) return { error: 'bridge-not-ready' }
350
363
  // try testID first \u2014 strongest signal of "this is the
@@ -385,7 +398,7 @@ ${s}
385
398
  }
386
399
  }
387
400
  return { strategy: 'none' }
388
- })()`});"error"in s&&(console.error(` ${s.error}`),process.exit(1)),s.strategy==="none"&&(console.error(` tap-best: no testID or visible text matched "${t}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1));let n=s.node,r=n.absolutePosition.x+n.layout.width/2,u=n.absolutePosition.y+n.layout.height/2,m=await c.send({type:"tap",x:r,y:u});if(m?.hit!==!1&&m?.ok!==!1){let x=_e(t,{id:n.id,testID:n.testID,type:n.type,cx:r,cy:u},s.strategy==="testid"?"id":"text");await J("inspect tap-best",x.step,x.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:r,cy:u},result:m},null,2));break}case"tap-id":{let t=a[1];t||(console.error(v("tap-id","<id>")),process.exit(1));let e=JSON.stringify(t),s=await c.send({type:"evaluate",code:`(async () => {
401
+ })()`});"error"in o&&(console.error(` ${o.error}`),process.exit(1)),o.strategy==="none"&&(console.error(` tap-best: no testID or visible text matched "${t}". try \`sootsim find --interactive-targets\` to list candidates.`),process.exit(1));let n=o.node,r=n.absolutePosition.x+n.layout.width/2,u=n.absolutePosition.y+n.layout.height/2,m=await c.send({type:"tap",x:r,y:u,target:{id:n.id,testID:n.testID,text:o.strategy==="text"?t:null,type:n.type}});if(m?.hit!==!1&&m?.ok!==!1){let w=_e(t,{id:n.id,testID:n.testID,type:n.type,cx:r,cy:u},o.strategy==="testid"?"id":"text");await L("inspect tap-best",w.step,w.summary)}console.log(JSON.stringify({matched:{strategy:o.strategy,nodeId:n.nodeId,id:n.id,testID:n.testID,type:n.type,text:n.text},tapped:{cx:r,cy:u},result:m},null,2));break}case"tap-id":{let t=a[1];t||(console.error(v("tap-id","<id>")),process.exit(1));let e=JSON.stringify(t),o=await c.send({type:"evaluate",code:`(async () => {
389
402
  const t = window.__sootsimTest
390
403
  if (!t) return null
391
404
  const n = (await t.findByTestId(${e})) || (await t.findById(${e}))
@@ -410,29 +423,38 @@ ${s}
410
423
  nodeId: n.nodeId ?? null,
411
424
  id: n.id,
412
425
  testID: n.testID,
426
+ text: n.text ?? n.accessibilityLabel ?? null,
413
427
  type: n.type,
414
428
  },
415
429
  target: {
416
430
  nodeId: target.nodeId ?? null,
417
431
  id: target.id,
418
432
  testID: target.testID,
433
+ text:
434
+ target.text ??
435
+ target.accessibilityLabel ??
436
+ n.text ??
437
+ n.accessibilityLabel ??
438
+ null,
419
439
  type: target.type,
420
440
  },
421
441
  strategy: (resolved && resolved.strategy) || 'matched-node',
422
442
  }
423
- })()`});(!s||typeof s.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1));let n=await c.send({type:"tap",x:s.cx,y:s.cy});if(n?.hit!==!1&&n?.ok!==!1){let r=_e(t,{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",r.step,r.summary)}console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},result:n},null,2));break}case"type-into":{let t=a[1],e=a.slice(2).join(" ");(!t||!e)&&(console.error(v("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(t),n=await c.send({type:"evaluate",code:`(async () => {
443
+ })()`});(!o||typeof o.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1));let n=await c.send({type:"tap",x:o.cx,y:o.cy,target:{id:o.target?.id??o.match?.id??null,testID:o.target?.testID??o.match?.testID??null,text:o.target?.text??o.target?.accessibilityLabel??o.match?.text??o.match?.accessibilityLabel??null,type:o.target?.type??o.match?.type??null}});if(n?.hit!==!1&&n?.ok!==!1){let r=_e(t,{id:o.target?.id??null,testID:o.target?.testID??null,type:o.target?.type??null,cx:o.cx,cy:o.cy},"id");await L("inspect tap-id",r.step,r.summary)}console.log(JSON.stringify({matched:o.match,tapped:{nodeId:o.target?.nodeId??null,id:o.target?.id??null,testID:o.target?.testID??null,type:o.target?.type??null,cx:o.cx,cy:o.cy},...o.strategy&&o.strategy!=="matched-node"?{strategy:o.strategy}:{},result:n},null,2));break}case"type-into":{let t=a[1],e=a.slice(2).join(" ");(!t||!e)&&(console.error(v("type-into","<id> <text>")),process.exit(1));let o=JSON.stringify(t),n=await c.send({type:"evaluate",code:`(async () => {
424
444
  const t = window.__sootsimTest
425
445
  if (!t) return null
426
- const n = await (t.findByTestId(${s}) || t.findById(${s}))
446
+ const n = await (t.findByTestId(${o}) || t.findById(${o}))
427
447
  if (!n || !n.absolutePosition || !n.layout) return null
428
448
  return {
429
449
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
430
450
  cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
451
+ id: n.id,
431
452
  testID: n.testID,
453
+ type: n.type,
432
454
  isTextInput: !!n.isTextInput,
433
455
  placeholder: n.placeholder || null,
434
456
  }
435
- })()`});(!n||typeof n.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1)),n.isTextInput||console.error(` warning: ${t} is not a text input (isTextInput: false)`);let r=await c.send({type:"tap",x:n.cx,y:n.cy}),u=await fo(c);u.visible||(console.error(` keyboard did not open after tapping ${t}`),process.exit(1));let m=u.focusedInput;m&&(m.testID===t||m.id===t||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(t)} but focus is on ${JSON.stringify(m.testID??m.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await c.send({type:"keyboard",action:"type",text:e}),await J("inspect type-into",{tapOn:{id:t},inputText:e},`type-into #${t} ${JSON.stringify(e)}`),console.log(JSON.stringify({target:t,isTextInput:n.isTextInput,keyboardOpened:u.visible??r?.keyboardOpened??!1,focusedInput:u.focusedInput??null,typed:e},null,2));break}case"type":{let t=a.slice(1).join(" ");t||(console.error(v("type","<text>")),process.exit(1)),await ge(c,"type"),await c.send({type:"keyboard",action:"type",text:t}),await J("inspect type",{inputText:t},`type ${JSON.stringify(t)}`),console.log(` typed: ${JSON.stringify(t)}`);break}case"key":{let t=a[1];t||(console.error(v("key","<name>")),process.exit(1)),await ge(c,"key"),await c.send({type:"keyboard",action:"press",text:t}),await J("inspect key",{pressKey:t},`key ${t}`),console.log(` pressed: ${t}`);break}case"key-sequence":{let t=a.slice(1);t.length===0&&(console.error(v("key-sequence","<key> [<key> ...]")),process.exit(1)),await ge(c,"key-sequence");for(let e of t)await c.send({type:"keyboard",action:"press",text:e});await J("inspect key-sequence",{pressKey:t.join(" ")},`key-sequence ${t.join(" ")}`),console.log(` pressed: ${t.join(", ")}`);break}case"keycode":{let t=a.slice(1);t.length===0&&(console.error(v("keycode","<code> [<code> ...]")),process.exit(1));let e=t.map(n=>({code:n,key:go(n)})),s=e.filter(n=>!n.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(n=>n.code).join(", ")}`),process.exit(1)),await ge(c,"keycode");for(let n of e)await c.send({type:"keyboard",action:"press",text:n.key});await J("inspect keycode",{pressKey:e.map(n=>n.key).join(" ")},`keycode ${t.join(" ")}`),console.log(` pressed: ${t.join(", ")}`);break}case"dispatch":{let t=a[1];t||(console.error(v("dispatch","<char>")),process.exit(1)),await c.send({type:"keyboard",action:"dispatchKey",text:t}),await J("inspect dispatch",{dispatchKey:t},`dispatch ${JSON.stringify(t)}`),console.log(` dispatched: ${t}`);break}case"dismiss":{await c.send({type:"keyboard",action:"dismiss"}),await J("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let t=Number(a[1]),e=Number(a[2]),s=ae(o);if(s){let m=await me(c,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&G("wait-selector-for-missing-testid",s.value),process.exit(1)),t=m.x,e=m.y}let n=a[3]?Number(a[3]):80;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(n))&&(console.error(v("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let r=Math.max(0,Math.round(n)),u=await c.send({type:"evaluate",code:`(async () => {
457
+ })()`});(!n||typeof n.cx!="number")&&(console.error(` not found: ${t}`),process.exit(1)),n.isTextInput||console.error(` warning: ${t} is not a text input (isTextInput: false)`);let r=await c.send({type:"tap",x:n.cx,y:n.cy,target:{id:n.id??t,testID:n.testID??t,text:null,type:n.type??null}}),u=await fo(c);u.visible||(console.error(` keyboard did not open after tapping ${t}`),process.exit(1));let m=u.focusedInput;m&&(m.testID===t||m.id===t||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(t)} but focus is on ${JSON.stringify(m.testID??m.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await c.send({type:"keyboard",action:"type",text:e}),await L("inspect type-into",{tapOn:{id:t},inputText:e},`type-into #${t} ${JSON.stringify(e)}`),console.log(JSON.stringify({target:t,isTextInput:n.isTextInput,keyboardOpened:u.visible??r?.keyboardOpened??!1,focusedInput:u.focusedInput??null,typed:e},null,2));break}case"type":{let t=a.slice(1).join(" ");t||(console.error(v("type","<text>")),process.exit(1)),await ge(c,"type"),await c.send({type:"keyboard",action:"type",text:t}),await L("inspect type",{inputText:t},`type ${JSON.stringify(t)}`),console.log(` typed: ${JSON.stringify(t)}`);break}case"key":{let t=a[1];t||(console.error(v("key","<name>")),process.exit(1)),await ge(c,"key"),await c.send({type:"keyboard",action:"press",text:t}),await L("inspect key",{pressKey:t},`key ${t}`),console.log(` pressed: ${t}`);break}case"key-sequence":{let t=a.slice(1);t.length===0&&(console.error(v("key-sequence","<key> [<key> ...]")),process.exit(1)),await ge(c,"key-sequence");for(let e of t)await c.send({type:"keyboard",action:"press",text:e});await L("inspect key-sequence",{pressKey:t.join(" ")},`key-sequence ${t.join(" ")}`),console.log(` pressed: ${t.join(", ")}`);break}case"keycode":{let t=a.slice(1);t.length===0&&(console.error(v("keycode","<code> [<code> ...]")),process.exit(1));let e=t.map(n=>({code:n,key:go(n)})),o=e.filter(n=>!n.key);o.length>0&&(console.error(` unsupported keycode(s): ${o.map(n=>n.code).join(", ")}`),process.exit(1)),await ge(c,"keycode");for(let n of e)await c.send({type:"keyboard",action:"press",text:n.key});await L("inspect keycode",{pressKey:e.map(n=>n.key).join(" ")},`keycode ${t.join(" ")}`),console.log(` pressed: ${t.join(", ")}`);break}case"dispatch":{let t=a[1];t||(console.error(v("dispatch","<char>")),process.exit(1)),await c.send({type:"keyboard",action:"dispatchKey",text:t}),await L("inspect dispatch",{dispatchKey:t},`dispatch ${JSON.stringify(t)}`),console.log(` dispatched: ${t}`);break}case"dismiss":{await c.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let t=Number(a[1]),e=Number(a[2]),o=ae(s);if(o){let m=await me(c,o);m||(console.error(` not found: ${o.value}`),o.mode==="testid"&&G("wait-selector-for-missing-testid",o.value),process.exit(1)),t=m.x,e=m.y}let n=a[3]?Number(a[3]):80;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(n))&&(console.error(v("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let r=Math.max(0,Math.round(n)),u=await c.send({type:"evaluate",code:`(async () => {
436
458
  const interact = window.__sootsimInteract
437
459
  if (interact?.doubleTap) {
438
460
  return {
@@ -455,18 +477,18 @@ ${s}
455
477
  first,
456
478
  second,
457
479
  }
458
- })()`});u?.ok&&await J("inspect double-tap",{doubleTapAtCoords:{x:t,y:e,gapMs:r}},`double-tap @${t},${e}`),console.log(JSON.stringify(u,null,2));break}case"long-press":{let t=Number(a[1]),e=Number(a[2]),s=ae(o);if(s){let u=await me(c,s);u||(console.error(` not found: ${s.value}`),s.mode==="testid"&&G("wait-selector-for-missing-testid",s.value),process.exit(1)),t=u.x,e=u.y}let n=a[3]?Number(a[3]):600;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(n))&&(console.error(v("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let r=await c.send({type:"evaluate",code:`(async () => {
480
+ })()`});u?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:t,y:e,gapMs:r}},`double-tap @${t},${e}`),console.log(JSON.stringify(u,null,2));break}case"long-press":{let t=Number(a[1]),e=Number(a[2]),o=ae(s);if(o){let u=await me(c,o);u||(console.error(` not found: ${o.value}`),o.mode==="testid"&&G("wait-selector-for-missing-testid",o.value),process.exit(1)),t=u.x,e=u.y}let n=a[3]?Number(a[3]):600;(!Number.isFinite(t)||!Number.isFinite(e)||!Number.isFinite(n))&&(console.error(v("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let r=await c.send({type:"evaluate",code:`(async () => {
459
481
  const interact = window.__sootsimInteract
460
482
  if (!interact?.longPress) return { ok: false, reason: 'no interact.longPress' }
461
483
  const value = await interact.longPress(${t}, ${e}, ${Math.max(0,Math.round(n))})
462
484
  return { ok: !!value, value }
463
- })()`});r?.ok&&await J("inspect long-press",{tapAtCoords:{x:t,y:e}},`long-press @${t},${e}`),console.log(JSON.stringify(r,null,2));break}case"touch":{let t=a[1],e=Number(a[2]),s=Number(a[3]),n=a[4]?Number(a[4]):999,r=t==="down"?"touchDown":t==="move"?"touchMove":t==="up"?"touchUp":t==="cancel"?"touchCancel":null;r||(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),t!=="cancel"&&(!Number.isFinite(e)||!Number.isFinite(s))&&(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let u=t==="down"?"tap":t==="move"?"move":null,m=u&&Number.isFinite(e)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${u}', x: ${e}, y: ${s} } }));`:"",x=await c.send({type:"evaluate",code:`(async () => {
485
+ })()`});r?.ok&&await L("inspect long-press",{tapAtCoords:{x:t,y:e}},`long-press @${t},${e}`),console.log(JSON.stringify(r,null,2));break}case"touch":{let t=a[1],e=Number(a[2]),o=Number(a[3]),n=a[4]?Number(a[4]):999,r=t==="down"?"touchDown":t==="move"?"touchMove":t==="up"?"touchUp":t==="cancel"?"touchCancel":null;r||(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),t!=="cancel"&&(!Number.isFinite(e)||!Number.isFinite(o))&&(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let u=t==="down"?"tap":t==="move"?"move":null,m=u&&Number.isFinite(e)&&Number.isFinite(o)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${u}', x: ${e}, y: ${o} } }));`:"",w=await c.send({type:"evaluate",code:`(async () => {
464
486
  ${m}
465
487
  const interact = window.__sootsimInteract
466
488
  if (!interact?.${r}) return { ok: false, reason: 'no interact.${r}' }
467
- const value = ${t==="cancel"?`await interact.${r}(${Math.max(1,Math.round(n))})`:`await interact.${r}(${e}, ${s}, ${Math.max(1,Math.round(n))})`}
489
+ const value = ${t==="cancel"?`await interact.${r}(${Math.max(1,Math.round(n))})`:`await interact.${r}(${e}, ${o}, ${Math.max(1,Math.round(n))})`}
468
490
  return { ok: !!value, value }
469
- })()`});x?.ok&&t!=="cancel"&&await J("inspect touch",{tapAtCoords:{x:e,y:s}},`touch ${t} @${e},${s}`),console.log(JSON.stringify(x,null,2));break}case"gesture":{let t=["scroll-up","scroll-down","scroll-left","scroll-right","swipe-from-left-edge","swipe-from-right-edge","swipe-from-top-edge","swipe-from-bottom-edge"],e=a[1],s=a[2]?Number(a[2]):220;(!e||!Number.isFinite(s))&&(console.error(v("gesture","<preset> [durationMs]")),console.error(` presets: ${t.join(", ")}`),process.exit(1)),t.includes(e)||(console.error(` unknown gesture preset: ${e}`),console.error(` presets: ${t.join(", ")}`),process.exit(1));let n=await c.send({type:"evaluate",code:`(async () => {
491
+ })()`});w?.ok&&t!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:e,y:o}},`touch ${t} @${e},${o}`),console.log(JSON.stringify(w,null,2));break}case"gesture":{let t=["scroll-up","scroll-down","scroll-left","scroll-right","swipe-from-left-edge","swipe-from-right-edge","swipe-from-top-edge","swipe-from-bottom-edge"],e=a[1],o=a[2]?Number(a[2]):220;(!e||!Number.isFinite(o))&&(console.error(v("gesture","<preset> [durationMs]")),console.error(` presets: ${t.join(", ")}`),process.exit(1)),t.includes(e)||(console.error(` unknown gesture preset: ${e}`),console.error(` presets: ${t.join(", ")}`),process.exit(1));let n=await c.send({type:"evaluate",code:`(async () => {
470
492
  const spec = globalThis.__sootsimDeviceSpec || {}
471
493
  return {
472
494
  width: spec.width || window.innerWidth || 393,
@@ -474,26 +496,26 @@ ${s}
474
496
  statusBarHeight: spec.statusBarHeight || 0,
475
497
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
476
498
  }
477
- })()`}),r=Number(n?.width)||393,u=Number(n?.height)||852,m=Number(n?.statusBarHeight)||0,x=Number(n?.homeIndicatorHeight)||0,g=Math.round(r/2),$=Math.round(u/2),F=Math.max(24,m+18),q=Math.max(24,x+18),H=18,U=Math.min(220,Math.round(u*.24)),M=Math.min(180,Math.round(r*.32)),h=g,p=$,O=g,R=$;switch(e){case"scroll-up":p=$+Math.round(U/2),R=$-Math.round(U/2);break;case"scroll-down":p=$-Math.round(U/2),R=$+Math.round(U/2);break;case"scroll-left":h=g+Math.round(M/2),O=g-Math.round(M/2);break;case"scroll-right":h=g-Math.round(M/2),O=g+Math.round(M/2);break;case"swipe-from-left-edge":h=H,p=$,O=Math.min(r-H,H+M);break;case"swipe-from-right-edge":h=r-H,p=$,O=Math.max(H,r-H-M);break;case"swipe-from-top-edge":h=g,p=F,R=Math.min(u-q,F+U);break;case"swipe-from-bottom-edge":h=g,p=u-q,R=Math.max(F,u-q-U);break}let A=Math.max(8,Math.round(s/16)),be=Math.max(1,Math.round(s/A)),le=await c.send({type:"evaluate",code:`(async () => {
499
+ })()`}),r=Number(n?.width)||393,u=Number(n?.height)||852,m=Number(n?.statusBarHeight)||0,w=Number(n?.homeIndicatorHeight)||0,g=Math.round(r/2),$=Math.round(u/2),F=Math.max(24,m+18),q=Math.max(24,w+18),H=18,U=Math.min(220,Math.round(u*.24)),I=Math.min(180,Math.round(r*.32)),b=g,p=$,P=g,R=$;switch(e){case"scroll-up":p=$+Math.round(U/2),R=$-Math.round(U/2);break;case"scroll-down":p=$-Math.round(U/2),R=$+Math.round(U/2);break;case"scroll-left":b=g+Math.round(I/2),P=g-Math.round(I/2);break;case"scroll-right":b=g-Math.round(I/2),P=g+Math.round(I/2);break;case"swipe-from-left-edge":b=H,p=$,P=Math.min(r-H,H+I);break;case"swipe-from-right-edge":b=r-H,p=$,P=Math.max(H,r-H-I);break;case"swipe-from-top-edge":b=g,p=F,R=Math.min(u-q,F+U);break;case"swipe-from-bottom-edge":b=g,p=u-q,R=Math.max(F,u-q-U);break}let A=Math.max(8,Math.round(o/16)),be=Math.max(1,Math.round(o/A)),le=await c.send({type:"evaluate",code:`(async () => {
478
500
  const interact = window.__sootsimInteract
479
501
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
480
- const value = await interact.drag(${h}, ${p}, ${O}, ${R}, ${A}, ${be})
502
+ const value = await interact.drag(${b}, ${p}, ${P}, ${R}, ${A}, ${be})
481
503
  return { ok: !!value, value }
482
- })()`});le?.ok&&await J("inspect gesture",{swipe:{start:`${h}, ${p}`,end:`${O}, ${R}`,duration:Math.max(1,Math.round(s))}},`gesture ${e}`),console.log(JSON.stringify({preset:e,from:{x:h,y:p},to:{x:O,y:R},result:le},null,2));break}case"scroll":{let t=ae(o),e=t?.mode==="testid"?t.value:a[1],s=Number(a[t?1:2]),n=Number(a[t?2:3]);(!e||!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(v("scroll","<id> <dx> <dy> | --testid <id> <dx> <dy>")),process.exit(1));let r=await c.send({type:"evaluate",code:`(async () => {
504
+ })()`});le?.ok&&await L("inspect gesture",{swipe:{start:`${b}, ${p}`,end:`${P}, ${R}`,duration:Math.max(1,Math.round(o))}},`gesture ${e}`),console.log(JSON.stringify({preset:e,from:{x:b,y:p},to:{x:P,y:R},result:le},null,2));break}case"scroll":{let t=ae(s),e=ho(s),o=t?.mode==="testid"?t.value:e==null?a[1]:null,n=t||e!=null?1:2,r=Number(a[n]),u=Number(a[n+1]);(!o&&e==null||!Number.isFinite(r)||!Number.isFinite(u))&&(console.error(v("scroll","<id> <x> <y> | --testid <id> <x> <y> | --node-id <nodeId> <x> <y>")),process.exit(1));let m=await c.send({type:"evaluate",code:`(async () => {
483
505
  const t = window.__sootsimTest
484
506
  if (!t) return null
485
- const n = await t.findByTestId(${JSON.stringify(e)})
486
- || await t.findById(${JSON.stringify(e)})
507
+ const n = ${e!=null?`await t.inspectByNodeId(${JSON.stringify(e)})`:`await t.findByTestId(${JSON.stringify(o)})
508
+ || await t.findById(${JSON.stringify(o)})`}
487
509
  if (!n || !n.absolutePosition || !n.layout) return null
488
510
  return {
489
511
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
490
512
  cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
491
513
  }
492
- })()`}),u=await z(c,"scrollTo",e,s,n,!1);u?.ok&&await J("inspect scroll",{scrollTo:{id:e,x:s,y:n}},`scroll ${e} -> ${s},${n}`),console.log(JSON.stringify({...u,...r?{at:{x:r.cx,y:r.cy}}:{}},null,2));break}case"state":{let t=a[1];if(i==="get"&&!t){let s=await z(c,"getRuntimeState"),n=await c.send({type:"evaluate",code:`({
514
+ })()`}),w=await z(c,"scrollTo",e!=null?{nodeId:e}:o,r,u,!1);if(w?.ok){let g=e!=null?`node ${e}`:`#${o}`;await L("inspect scroll",{scrollTo:{...e!=null?{nodeId:e}:{id:o},x:r,y:u}},`scroll ${g} -> ${r},${u}`)}console.log(JSON.stringify({...w,...m?{at:{x:m.cx,y:m.cy}}:{}},null,2));break}case"state":{let t=a[1];if(i==="get"&&!t){let o=await z(c,"getRuntimeState"),n=await c.send({type:"evaluate",code:`({
493
515
  errors: window.__sootsimConsole?.getErrors?.()?.length ?? 0,
494
516
  warnings: window.__sootsimConsole?.getWarnings?.()?.length ?? 0,
495
- })`});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 r=await se(c);r&&(s.shell=r)}catch{}console.log(JSON.stringify(s,null,2));break}if(!t||t==="--help"||t==="-h"){console.log(`
496
- ${b("state")} \u2014 dump raw runtime state
517
+ })`});if(o&&typeof o=="object"&&o.diagnostics&&(o.diagnostics.errors=n?.errors??0,o.diagnostics.warnings=n?.warnings??0),o&&typeof o=="object"&&o.shell==null)try{let r=await se(c);r&&(o.shell=r)}catch{}console.log(JSON.stringify(o,null,2));break}if(!t||t==="--help"||t==="-h"){console.log(`
518
+ ${h("state")} \u2014 dump raw runtime state
497
519
 
498
520
  subcommands:
499
521
  shell dump shell transition/layout state
@@ -507,15 +529,15 @@ ${s}
507
529
  gesture <x> <y> dump gesture routing/debug info at coordinates
508
530
 
509
531
  examples:
510
- ${b("state")} shell
511
- ${b("state")} worker
512
- ${b("state")} keyboard
513
- ${b("state")} ownership
514
- ${b("state")} node photos
515
- ${b("state")} scroll feed
516
- ${b("state")} scroll-hit 360 420
517
- ${b("state")} hit 200 720
518
- `);break}let e;switch(t){case"shell":e=await se(c,500);break;case"worker":e=await xe(c,"__sootsimRenderHost.queryStats");break;case"ownership":e=await c.send({type:"evaluate",code:`(() => {
532
+ ${h("state")} shell
533
+ ${h("state")} worker
534
+ ${h("state")} keyboard
535
+ ${h("state")} ownership
536
+ ${h("state")} node photos
537
+ ${h("state")} scroll feed
538
+ ${h("state")} scroll-hit 360 420
539
+ ${h("state")} hit 200 720
540
+ `);break}let e;switch(t){case"shell":e=await se(c,500);break;case"worker":e=await $e(c,"__sootsimRenderHost.queryStats");break;case"ownership":e=await c.send({type:"evaluate",code:`(() => {
519
541
  const h = window.__sootsimRenderHost
520
542
  if (!h || typeof h.getOwnershipSnapshot !== 'function') {
521
543
  return { error: 'getOwnershipSnapshot not available' }
@@ -546,8 +568,8 @@ ${s}
546
568
  text: focused.text || null,
547
569
  } : null,
548
570
  }
549
- })()`});break;case"node":{let s=a[2];s||(console.error(` usage: ${b("state")} node <id>`),process.exit(1)),e=await z(c,"findByTestId",s)||await z(c,"findById",s);break}case"scroll":{let s=a[2];s||(console.error(` usage: ${b("state")} scroll <id>`),process.exit(1)),e=await z(c,"getScrollState",s);break}case"scroll-hit":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} scroll-hit <x> <y>`),process.exit(1)),e=await z(c,"getScrollStateAt",s,n);break}case"hit":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} hit <x> <y>`),process.exit(1)),e=await z(c,"debugHitAt",s,n);break}case"gesture":{let s=Number(a[2]),n=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(n))&&(console.error(` usage: ${b("state")} gesture <x> <y>`),process.exit(1)),e=await z(c,"debugGestureAt",s,n);break}default:console.error(` unknown state subcommand: ${t}`),process.exit(1)}console.log(JSON.stringify(e,null,2));break}case"shell":{let t=a[1];if(!t||t==="--help"||t==="-h"){console.log(`
550
- ${b("shell")} \u2014 run built-in shell commands
571
+ })()`});break;case"node":{let o=a[2];o||(console.error(` usage: ${h("state")} node <id>`),process.exit(1)),e=await z(c,"findByTestId",o)||await z(c,"findById",o);break}case"scroll":{let o=a[2];o||(console.error(` usage: ${h("state")} scroll <id>`),process.exit(1)),e=await z(c,"getScrollState",o);break}case"scroll-hit":{let o=Number(a[2]),n=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} scroll-hit <x> <y>`),process.exit(1)),e=await z(c,"getScrollStateAt",o,n);break}case"hit":{let o=Number(a[2]),n=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} hit <x> <y>`),process.exit(1)),e=await z(c,"debugHitAt",o,n);break}case"gesture":{let o=Number(a[2]),n=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(n))&&(console.error(` usage: ${h("state")} gesture <x> <y>`),process.exit(1)),e=await z(c,"debugGestureAt",o,n);break}default:console.error(` unknown state subcommand: ${t}`),process.exit(1)}console.log(JSON.stringify(e,null,2));break}case"shell":{let t=a[1];if(!t||t==="--help"||t==="-h"){console.log(`
572
+ ${h("shell")} \u2014 run built-in shell commands
551
573
 
552
574
  subcommands:
553
575
  launch <appId> [waitMs] [--clear-state]
@@ -562,15 +584,15 @@ ${s}
562
584
  shake trigger the simulator shake gesture
563
585
 
564
586
  examples:
565
- ${b("shell")} launch photos
566
- ${b("shell")} launch rn --clear-state
567
- ${b("shell")} launch photos 1500
568
- ${b("shell")} home 500
569
- ${b("shell")} switcher 800
570
- ${b("shell")} open-card clock 800
571
- ${b("shell")} appearance dark
572
- ${b("shell")} lock
573
- `);break}let e=t==="launch"||t==="open-card"||t==="home"||t==="switcher",s=t==="launch"||t==="open-card"?a[3]:a[2],n=s?Number(s):350;e&&(!Number.isFinite(n)||n<0)&&(console.error(v("shell",t==="launch"||t==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let r=!1,u=!1,m=null,x=o.includes("--clear-state");if(t==="launch"){let g=a[2];g||(console.error(v("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),x&&await c.send({type:"evaluate",code:Be}),r=!!await re(c,"launchApp",n,g),{settled:u,state:m}=await fe(c,Math.round(n),$=>!!$&&$.state==="app"&&$.activeApp===g&&$.showSwitcher===!1&&$.switcherPhase==="idle"&&typeof $.launchProgress=="number"&&$.launchProgress>=.98),r&&await J("inspect shell launch",x?{launchApp:{clearState:!0}}:{launchApp:{}},x?"launch app (clear state)":"launch app")}else if(t==="home")r=!!await re(c,"goHome",n),{settled:u,state:m}=await fe(c,Math.round(n),g=>!!g&&g.state==="home"&&g.activeApp==null&&g.showSwitcher===!1&&g.switcherPhase==="idle"&&typeof g.launchProgress=="number"&&g.launchProgress>=.98);else if(t==="switcher")r=!!await re(c,"openSwitcher",n),{settled:u,state:m}=await fe(c,Math.round(n),g=>!!g&&g.state==="app"&&g.showSwitcher===!0&&g.switcherPhase==="idle"&&typeof g.zoomLevel=="number"&&Math.abs(g.zoomLevel)<=.02&&typeof g.horizontalZoom=="number"&&Math.abs(g.horizontalZoom)<=.02),u&&(await X(po),m=await se(c));else if(t==="open-card"){let g=a[2];g||(console.error(v("shell","open-card <appId> [settleMs]")),process.exit(1)),r=!!await re(c,"openSwitcherCard",n,g),{settled:u,state:m}=await fe(c,Math.round(n),$=>!!$&&$.state==="app"&&$.activeApp===g&&$.showSwitcher===!1&&$.switcherPhase==="idle"&&typeof $.zoomLevel=="number"&&$.zoomLevel>=.98&&typeof $.horizontalZoom=="number"&&$.horizontalZoom>=.98),r&&await J("inspect shell open-card",{openSwitcherCard:{appId:g}},`open switcher card ${g}`)}else if(t==="appearance"){let g=a[2];(!g||!["light","dark","auto","toggle"].includes(g))&&(console.error(v("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let $=await Ct(c,"appearance",g);if(r=!!$?.ok,m={appearance:$},r){let F=$?.applied??g;console.log(` appearance: ${F}`)}}else if(t==="lock"||t==="shake"){let g=await Ct(c,t);r=!!g?.ok,m={[t]:g}}else console.error(` unknown shell subcommand: ${t}`),process.exit(1);console.log(JSON.stringify({ok:r,settled:u,state:m},null,2));break}case"url":{await Tt(c,{args:l});break}case"reload":{let s=!1,n=!1;try{await c.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let m=await c.send({type:"evaluate",code:`;(() => {
587
+ ${h("shell")} launch photos
588
+ ${h("shell")} launch rn --clear-state
589
+ ${h("shell")} launch photos 1500
590
+ ${h("shell")} home 500
591
+ ${h("shell")} switcher 800
592
+ ${h("shell")} open-card clock 800
593
+ ${h("shell")} appearance dark
594
+ ${h("shell")} lock
595
+ `);break}let e=t==="launch"||t==="open-card"||t==="home"||t==="switcher",o=t==="launch"||t==="open-card"?a[3]:a[2],n=o?Number(o):350;e&&(!Number.isFinite(n)||n<0)&&(console.error(v("shell",t==="launch"||t==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let r=!1,u=!1,m=null,w=s.includes("--clear-state");if(t==="launch"){let g=a[2];g||(console.error(v("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),w&&await c.send({type:"evaluate",code:Be}),r=!!await re(c,"launchApp",n,g),{settled:u,state:m}=await fe(c,Math.round(n),$=>!!$&&$.state==="app"&&$.activeApp===g&&$.showSwitcher===!1&&$.switcherPhase==="idle"&&typeof $.launchProgress=="number"&&$.launchProgress>=.98),r&&await L("inspect shell launch",w?{launchApp:{clearState:!0}}:{launchApp:{}},w?"launch app (clear state)":"launch app")}else if(t==="home")r=!!await re(c,"goHome",n),{settled:u,state:m}=await fe(c,Math.round(n),g=>!!g&&g.state==="home"&&g.activeApp==null&&g.showSwitcher===!1&&g.switcherPhase==="idle"&&typeof g.launchProgress=="number"&&g.launchProgress>=.98);else if(t==="switcher")r=!!await re(c,"openSwitcher",n),{settled:u,state:m}=await fe(c,Math.round(n),g=>!!g&&g.state==="app"&&g.showSwitcher===!0&&g.switcherPhase==="idle"&&typeof g.zoomLevel=="number"&&Math.abs(g.zoomLevel)<=.02&&typeof g.horizontalZoom=="number"&&Math.abs(g.horizontalZoom)<=.02),u&&(await X(po),m=await se(c));else if(t==="open-card"){let g=a[2];g||(console.error(v("shell","open-card <appId> [settleMs]")),process.exit(1)),r=!!await re(c,"openSwitcherCard",n,g),{settled:u,state:m}=await fe(c,Math.round(n),$=>!!$&&$.state==="app"&&$.activeApp===g&&$.showSwitcher===!1&&$.switcherPhase==="idle"&&typeof $.zoomLevel=="number"&&$.zoomLevel>=.98&&typeof $.horizontalZoom=="number"&&$.horizontalZoom>=.98),r&&await L("inspect shell open-card",{openSwitcherCard:{appId:g}},`open switcher card ${g}`)}else if(t==="appearance"){let g=a[2];(!g||!["light","dark","auto","toggle"].includes(g))&&(console.error(v("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let $=await Dt(c,"appearance",g);if(r=!!$?.ok,m={appearance:$},r){let F=$?.applied??g;console.log(` appearance: ${F}`)}}else if(t==="lock"||t==="shake"){let g=await Dt(c,t);r=!!g?.ok,m={[t]:g}}else console.error(` unknown shell subcommand: ${t}`),process.exit(1);console.log(JSON.stringify({ok:r,settled:u,state:m},null,2));break}case"url":{await Tt(c,{args:l});break}case"reload":{let o=!1,n=!1;try{await c.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let m=await c.send({type:"evaluate",code:`;(() => {
574
596
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
575
597
  if (typeof reloadExternalApp === 'function') {
576
598
  reloadExternalApp()
@@ -578,10 +600,10 @@ ${s}
578
600
  }
579
601
  window.location.reload()
580
602
  return { kind: 'page' }
581
- })()`});n=!!m&&m.kind==="external-app",s=!0}catch{}console.log(" reloading...");let r=c,u=null;if(n)u=await ke(c,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await X(300);let m=await lt(_,L,T,{timeoutMs:1e4,simIdSource:E});m?(r=m,u=await ke(m,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),r=null)}if(u)if(u.ready){let m=u.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${u.elapsedMs}ms: ${u.nodes} nodes${m}`)}else u.source==="error-bail"?console.log(` \u26A0 reload bailed after ${u.elapsedMs}ms: ${u.errors} console error(s), ready signal never fired`):console.log(` \u26A0 reload timed out after ${u.elapsedMs}ms (${u.nodes} nodes, ${u.errors} errors)`);if(r)try{let m=await r.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(r!==c&&r.close(),Array.isArray(m)&&m.length>0){console.log(`
603
+ })()`});n=!!m&&m.kind==="external-app",o=!0}catch{}console.log(" reloading...");let r=c,u=null;if(n)u=await ke(c,{timeoutMs:1e4,errorGraceMs:3e3});else{o&&await X(300);let m=await lt(N,J,M,{timeoutMs:1e4,simIdSource:E});m?(r=m,u=await ke(m,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),r=null)}if(u)if(u.ready){let m=u.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${u.elapsedMs}ms: ${u.nodes} nodes${m}`)}else u.source==="error-bail"?console.log(` \u26A0 reload bailed after ${u.elapsedMs}ms: ${u.errors} console error(s), ready signal never fired`):console.log(` \u26A0 reload timed out after ${u.elapsedMs}ms (${u.nodes} nodes, ${u.errors} errors)`);if(r)try{let m=await r.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(r!==c&&r.close(),Array.isArray(m)&&m.length>0){console.log(`
582
604
  \u26A0 ${m.length} error(s) during mount:
583
- `);for(let x of m){let g=x.args.map($=>typeof $=="object"?JSON.stringify($):$).join(" ");if(console.log(` ${g}`),x.stack){let $=x.stack.split(`
584
- `).slice(0,2);for(let F of $)console.log(` ${F.trim()}`)}}}}catch{}u&&!u.ready&&(process.exitCode=1);break}case"eval":case"js":{let t=a.slice(1).join(" ");t||(console.error(v("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 e=t;e.startsWith("(async")||(e=`(async () => ${e})()`);let s=await c.send({type:"evaluate",code:e});console.log(JSON.stringify(s,null,2));let n=t.toLowerCase(),r=[];(n.includes("sootsim:gohome")||n.includes("gohome"))&&r.push("sootsim shell home"),(n.includes("sootsim:appswitcher")||n.includes("appswitcher"))&&r.push("sootsim shell switcher"),(n.includes("keyboard.isvisible")||n.includes("keyboard.getmode"))&&r.push("sootsim debug state keyboard"),n.includes("interact.tap")&&r.push("sootsim do tap <x> <y>"),n.includes("keyboard.type")&&r.push("sootsim do type <text>"),(n.includes("keyboard.press")||n.includes("keyboard.dispatchkey"))&&r.push("sootsim do key <name>"),n.includes("keyboard.dismiss")&&r.push("sootsim do dismiss"),n.includes("dumptree")&&r.push("sootsim get tree"),n.includes("dumpaccessibilitytree")&&r.push("sootsim get a11y"),n.includes("getnodecount")&&r.push("sootsim get count"),n.includes("findbytext")&&r.push("sootsim find <text>"),(n.includes("findbytestid")||n.includes("findbyid"))&&r.push("sootsim find --testid <id>"),n.includes("document.hidden")&&r.push("sootsim debug state keyboard (includes tab health)"),r.length>0&&G("prefer-cli-over-eval",r);break}case"globals":{let t=await c.send({type:"evaluate",code:`(async () => {
605
+ `);for(let w of m){let g=w.args.map($=>typeof $=="object"?JSON.stringify($):$).join(" ");if(console.log(` ${g}`),w.stack){let $=w.stack.split(`
606
+ `).slice(0,2);for(let F of $)console.log(` ${F.trim()}`)}}}}catch{}u&&!u.ready&&(process.exitCode=1);break}case"eval":case"js":{let t=a.slice(1).join(" ");t||(console.error(v("js","<javascript>")),console.error(""),console.error(" runs the snippet in the engine realm. SootSim is the"),console.error(" canonical state surface \u2014 reach into it directly."),console.error(""),console.error(" examples:"),console.error(` ${h("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${h("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${h("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${h("js")} SootSim.state.root.children.length`),process.exit(1));let e=t;e.startsWith("(async")||(e=`(async () => ${e})()`);let o=await c.send({type:"evaluate",code:e});console.log(JSON.stringify(o,null,2));let n=t.toLowerCase(),r=[];(n.includes("sootsim:gohome")||n.includes("gohome"))&&r.push("sootsim shell home"),(n.includes("sootsim:appswitcher")||n.includes("appswitcher"))&&r.push("sootsim shell switcher"),(n.includes("keyboard.isvisible")||n.includes("keyboard.getmode"))&&r.push("sootsim debug state keyboard"),n.includes("interact.tap")&&r.push("sootsim do tap <x> <y>"),n.includes("keyboard.type")&&r.push("sootsim do type <text>"),(n.includes("keyboard.press")||n.includes("keyboard.dispatchkey"))&&r.push("sootsim do key <name>"),n.includes("keyboard.dismiss")&&r.push("sootsim do dismiss"),n.includes("dumptree")&&r.push("sootsim get tree"),n.includes("dumpaccessibilitytree")&&r.push("sootsim get a11y"),n.includes("getnodecount")&&r.push("sootsim get count"),n.includes("findbytext")&&r.push("sootsim find <text>"),(n.includes("findbytestid")||n.includes("findbyid"))&&r.push("sootsim find --testid <id>"),n.includes("document.hidden")&&r.push("sootsim debug state keyboard (includes tab health)"),r.length>0&&G("prefer-cli-over-eval",r);break}case"globals":{let t=await c.send({type:"evaluate",code:`(async () => {
585
607
  const globals = {}
586
608
 
587
609
  // test bridge (proxy in worker mode)
@@ -619,8 +641,8 @@ ${s}
619
641
 
620
642
  return globals
621
643
  })()`});console.log(` sootsim JS API:
622
- `);for(let[e,s]of Object.entries(t)){console.log(` ${e}:`);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 gt({bridge:c,args:o,positional:a});break}case"perf":{let t=a[1];if(!t||t==="--help"||t==="-h"){console.log(`
623
- ${b("perf")} \u2014 performance profiling
644
+ `);for(let[e,o]of Object.entries(t)){console.log(` ${e}:`);for(let n of o)console.log(` .${n}`);console.log("")}console.log(` use: ${h("js")} <expression>`),console.log(` example: ${h("js")} test.findByText("Sign in")`);break}case"describe":{await gt({bridge:c,args:s,positional:a});break}case"perf":{let t=a[1];if(!t||t==="--help"||t==="-h"){console.log(`
645
+ ${h("perf")} \u2014 performance profiling
624
646
 
625
647
  subcommands:
626
648
  stats one-shot stats (zero overhead query)
@@ -630,11 +652,11 @@ ${s}
630
652
  transition <e> profile a shell transition (goHome, appSwitcher, lockScreen)
631
653
 
632
654
  examples:
633
- ${b("perf")} stats
634
- ${b("perf")} start
655
+ ${h("perf")} stats
656
+ ${h("perf")} start
635
657
  # ... interact with the app ...
636
- ${b("perf")} stop
637
- ${b("perf")} transition goHome
658
+ ${h("perf")} stop
659
+ ${h("perf")} transition goHome
638
660
  `);break}switch(t){case"stats":{let e=await c.send({type:"evaluate",code:`(async () => {
639
661
  // worker mode (host exposes these)
640
662
  if (window.__sootsimPerfStats) {
@@ -660,7 +682,7 @@ ${s}
660
682
  jankFrames: frameStats.recentFrames?.filter(f => f > 16.67).length || 0,
661
683
  recentCount: frameStats.recentFrames?.length || 0,
662
684
  }
663
- })()`});e.error&&(console.error(` error: ${e.error}`),process.exit(1));let s=e.avgMs!=="?"?(1e3/parseFloat(e.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${e.frames}`),console.log(` avg: ${e.avgMs}ms (${s} fps)`),console.log(` max: ${e.maxMs}ms`),console.log(` layout: ${e.layoutMs}ms total`),console.log(` nodes: ${e.nodeCount}`),e.recentCount>0&&console.log(` jank: ${e.jankFrames}/${e.recentCount} frames >16.67ms`);break}case"start":{await c.send({type:"evaluate",code:`(async () => {
685
+ })()`});e.error&&(console.error(` error: ${e.error}`),process.exit(1));let o=e.avgMs!=="?"?(1e3/parseFloat(e.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${e.frames}`),console.log(` avg: ${e.avgMs}ms (${o} fps)`),console.log(` max: ${e.maxMs}ms`),console.log(` layout: ${e.layoutMs}ms total`),console.log(` nodes: ${e.nodeCount}`),e.recentCount>0&&console.log(` jank: ${e.jankFrames}/${e.recentCount} frames >16.67ms`);break}case"start":{await c.send({type:"evaluate",code:`(async () => {
664
686
  // worker mode
665
687
  if (window.__sootsimPerfStart && window.__sootsimRenderHost) {
666
688
  const result = window.__sootsimPerfStart()
@@ -682,7 +704,7 @@ ${s}
682
704
  startedAt: performance.now(),
683
705
  }
684
706
  return { started: true }
685
- })()`}),console.log(` profiling started \u2014 interact with the app, then run '${b("perf")} stop'`);break}case"stop":{let e=await c.send({type:"evaluate",code:`(async () => {
707
+ })()`}),console.log(` profiling started \u2014 interact with the app, then run '${h("perf")} stop'`);break}case"stop":{let e=await c.send({type:"evaluate",code:`(async () => {
686
708
  // worker mode
687
709
  if (window.__sootsimRenderHost) {
688
710
  const session = window.${Q} || {}
@@ -776,8 +798,8 @@ ${s}
776
798
  jankFrames: recent.filter(f => f > 16.67).length,
777
799
  sampleCount: recent.length,
778
800
  }
779
- })()`});e.error&&(console.error(` error: ${e.error}`),process.exit(1));let s=e.avgMs>0?(1e3/e.avgMs).toFixed(1):"?",n=e.sampleCount>0?(e.jankFrames/e.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
780
- `),console.log(` frames: ${e.frames}`),console.log(` total: ${e.totalMs.toFixed(1)}ms`),console.log(` avg: ${e.avgMs.toFixed(2)}ms (${s} fps)`),console.log(` max: ${e.maxMs.toFixed(2)}ms`),console.log(""),e.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${e.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${e.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${e.copyAvgMs.toFixed(2)}ms`),e.auxAvgMs!==void 0&&console.log(` aux: ${e.auxAvgMs.toFixed(2)}ms`),e.otherAvgMs!==void 0&&console.log(` other: ${e.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${e.sampleCount} samples):`),console.log(` p50: ${e.p50.toFixed(2)}ms`),console.log(` p95: ${e.p95.toFixed(2)}ms`),console.log(` p99: ${e.p99.toFixed(2)}ms`),console.log(` jank: ${e.jankFrames} frames (${n}%) >16.67ms`);break}case"frames":{let e=a[2]?Number(a[2]):50;(!Number.isFinite(e)||e<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await c.send({type:"evaluate",code:`(async () => {
801
+ })()`});e.error&&(console.error(` error: ${e.error}`),process.exit(1));let o=e.avgMs>0?(1e3/e.avgMs).toFixed(1):"?",n=e.sampleCount>0?(e.jankFrames/e.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
802
+ `),console.log(` frames: ${e.frames}`),console.log(` total: ${e.totalMs.toFixed(1)}ms`),console.log(` avg: ${e.avgMs.toFixed(2)}ms (${o} fps)`),console.log(` max: ${e.maxMs.toFixed(2)}ms`),console.log(""),e.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${e.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${e.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${e.copyAvgMs.toFixed(2)}ms`),e.auxAvgMs!==void 0&&console.log(` aux: ${e.auxAvgMs.toFixed(2)}ms`),e.otherAvgMs!==void 0&&console.log(` other: ${e.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${e.sampleCount} samples):`),console.log(` p50: ${e.p50.toFixed(2)}ms`),console.log(` p95: ${e.p95.toFixed(2)}ms`),console.log(` p99: ${e.p99.toFixed(2)}ms`),console.log(` jank: ${e.jankFrames} frames (${n}%) >16.67ms`);break}case"frames":{let e=a[2]?Number(a[2]):50;(!Number.isFinite(e)||e<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let o=await c.send({type:"evaluate",code:`(async () => {
781
803
  if (window.__sootsimRenderHost) {
782
804
  const session = window.${Q} || {}
783
805
  if (session.active) {
@@ -812,7 +834,7 @@ ${s}
812
834
  mode: 'main-thread',
813
835
  frames: (stats.recentFrames || []).slice(-${e}),
814
836
  }
815
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let r=Array.isArray(s.samples)?s.samples:[];if(r.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` last ${r.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,x,g,$,F,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${F.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);console.log(""),Ne(r.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(r=>r.toFixed(2)).join(", ")}`),Ne(n);break}case"worst":{let e=a[2]?Number(a[2]):20;(!Number.isFinite(e)||e<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await c.send({type:"evaluate",code:`(async () => {
837
+ })()`});if(o.error&&(console.error(` error: ${o.error}`),process.exit(1)),o.mode==="render-worker"){let r=Array.isArray(o.samples)?o.samples:[];if(r.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${r.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,w,g,$,F,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${F.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);console.log(""),Ne(r.map(u=>u[1])),o.live&&console.log(" sampling continues");break}let n=Array.isArray(o.frames)?o.frames:Array.isArray(o)?o:[];if(n.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${n.length} frame times (ms):`),console.log(` ${n.map(r=>r.toFixed(2)).join(", ")}`),Ne(n);break}case"worst":{let e=a[2]?Number(a[2]):20;(!Number.isFinite(e)||e<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let o=await c.send({type:"evaluate",code:`(async () => {
816
838
  if (window.__sootsimRenderHost) {
817
839
  const session = window.${Q} || {}
818
840
  if (session.active) {
@@ -854,8 +876,8 @@ ${s}
854
876
  mode: 'main-thread',
855
877
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${e}),
856
878
  }
857
- })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let r=Array.isArray(s.samples)?s.samples:[];if(r.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${r.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,x,g,$,F,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${x.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${F.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let n=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(n.length===0){console.log(` no frame data \u2014 run '${b("perf")} start' first`);break}console.log(` worst ${n.length} frame times (ms):`),console.log(` ${n.map(r=>r.toFixed(2)).join(", ")}`);break}case"transition":{let e=a[2];if(!e||!["goHome","appSwitcher","lockScreen"].includes(e)){console.log(`
858
- ${b("perf")} transition <event> \u2014 profile a shell transition
879
+ })()`});if(o.error&&(console.error(` error: ${o.error}`),process.exit(1)),o.mode==="render-worker"){let r=Array.isArray(o.samples)?o.samples:[];if(r.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${r.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,w,g,$,F,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${F.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);o.live&&(console.log(""),console.log(" sampling continues"));break}let n=Array.isArray(o.frames)?o.frames:Array.isArray(o)?o:[];if(n.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${n.length} frame times (ms):`),console.log(` ${n.map(r=>r.toFixed(2)).join(", ")}`);break}case"transition":{let e=a[2];if(!e||!["goHome","appSwitcher","lockScreen"].includes(e)){console.log(`
880
+ ${h("perf")} transition <event> \u2014 profile a shell transition
859
881
 
860
882
  events:
861
883
  goHome swipe-to-home animation
@@ -865,8 +887,8 @@ ${s}
865
887
  note: uses 600ms capture window \u2014 may need --timeout 10000 flag
866
888
 
867
889
  examples:
868
- ${b("perf")} transition goHome --timeout 10000
869
- ${b("perf")} transition appSwitcher
890
+ ${h("perf")} transition goHome --timeout 10000
891
+ ${h("perf")} transition appSwitcher
870
892
  `);break}let n=`sootsim:${e}`;console.log(` profiling ${e} transition...`),console.log(" (use --timeout 10000 if this times out)");let r=await c.send({type:"evaluate",code:`(async () => {
871
893
  // only supported in render-worker mode
872
894
  if (!window.__sootsimRenderHost) {
@@ -944,27 +966,27 @@ ${s}
944
966
  p50: ${r.p50.toFixed(2)}ms
945
967
  p95: ${r.p95.toFixed(2)}ms
946
968
  p99: ${r.p99.toFixed(2)}ms
947
- jank: ${r.jankFrames} frames (${m}%) >16.67ms`),Array.isArray(r.samples)&&r.samples.length>0&&(console.log(""),Ne(r.samples.map(x=>x[1])));break}default:console.error(` unknown perf subcommand: ${t}`),process.exit(1)}break}case"errors":{let t=a[1];if(t==="clear"){await Qe(c),D(l)?B({cleared:!0}):console.log(" error buffer cleared");break}let e=t?Number(t):20,s=await Xe(c,e);if(D(l)){B(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
948
- `);for(let n of s){let r=new Date(n.timestamp).toLocaleTimeString(),u=n.args.map(m=>typeof m=="object"?JSON.stringify(m):m).join(" ");if(console.log(` [${r}] ${u}`),n.stack){let m=n.stack.split(`
949
- `).slice(0,3);for(let x of m)console.log(` ${x.trim()}`)}}break}case"warnings":{let t=a[1]?Number(a[1]):20,e=await Ve(c,t);if(D(l)){B(e);break}if(e.length===0){console.log(" no warnings captured");break}console.log(` ${e.length} warning(s):
950
- `);for(let s of e){let n=new Date(s.timestamp).toLocaleTimeString(),r=s.args.map(u=>typeof u=="object"?JSON.stringify(u):u).join(" ");console.log(` [${n}] ${r}`)}break}case"animations":{let t=await z(c,"listAnimations")??[];if(o.includes("--json")){console.log(JSON.stringify(t,null,2));break}if(t.length===0){console.log(" no active animations");break}console.log(` ${t.length} active animation(s):
951
- `);for(let e of t){let s=String(e.kind).padEnd(6),n=`${Number(e.from).toFixed(2)}\u2192${Number(e.to).toFixed(2)}`,r=Number(e.current??0).toFixed(2),u=`${Math.round((e.progress??0)*100)}%`,m=`${Math.round(e.elapsedMs??0)}ms`,x=e.loop?" loop":"",g=e.layoutBound?" layout":"";console.log(` #${e.id} ${s} ${n.padEnd(14)} cur=${r.padEnd(7)} ${u.padStart(4)} ${m}${x}${g}`)}break}case"animation":{let t=a[1];(!t||t==="--help"||t==="-h")&&(console.error(` usage: ${b("animation")} <id>`),process.exit(1));let e=Number(t);Number.isFinite(e)||(console.error(` invalid id: ${t}`),process.exit(1));let s=await z(c,"getAnimation",e);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let t=a[1];(!t||t==="--help"||t==="-h")&&(console.error(` usage: ${b("stop-animation")} <id|all>`),process.exit(1));let e=t==="all"?"all":Number(t);e!=="all"&&!Number.isFinite(e)&&(console.error(` invalid id: ${t}`),process.exit(1));let s=await z(c,"stopAnimation",e);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let t=a[1];if(t==="clear"){await et(c),D(l)?B({cleared:!0}):console.log(" request buffer cleared");break}let e=t==="all",s=e?a[2]:t,n=s?Number(s):20,r=await Ze(c,{failed:!e,limit:n});if(D(l)){B(r);break}if(r.length===0){console.log(e?" no requests captured":" no failed requests captured");break}console.log(` ${r.length} ${e?"request(s)":"failed request(s)"}:
952
- `);for(let u of r){let m=new Date(u.timestamp).toLocaleTimeString();console.log(` [${m}] ${W(u)}`),u.responseBody?console.log(` ${u.responseBody}`):u.error&&console.log(` ${u.error}`)}break}case"network":{let t=a[1],e=null,s=null,n=!1,r=!1,u=1e3,m=!1,x=!1;for(let M=0;M<l.length;M++){let h=l[M];if(h==="--filter")e=l[M+1]??null,M++;else if(h==="--limit"){let p=Number(l[M+1]);Number.isFinite(p)&&(s=p),M++}else if(h==="--threshold"){let p=Number(l[M+1]);Number.isFinite(p)&&p>0&&(u=p),M++}else h==="--failed"?n=!0:h==="--slow"?r=!0:h==="--tail"||h==="-f"?m=!0:h==="--json"&&(x=!0)}if(t==="clear"){await c.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(t==="get"){let M=a[2];M||(console.error(" usage: sootsim network get <id>"),process.exit(1));let h=await c.send({type:"evaluate",code:`(() => {
969
+ jank: ${r.jankFrames} frames (${m}%) >16.67ms`),Array.isArray(r.samples)&&r.samples.length>0&&(console.log(""),Ne(r.samples.map(w=>w[1])));break}default:console.error(` unknown perf subcommand: ${t}`),process.exit(1)}break}case"errors":{let t=a[1];if(t==="clear"){await Qe(c),C(l)?B({cleared:!0}):console.log(" error buffer cleared");break}let e=t?Number(t):20,o=await Xe(c,e);if(C(l)){B(o);break}if(o.length===0){console.log(" no errors captured");break}console.log(` ${o.length} error(s):
970
+ `);for(let n of o){let r=new Date(n.timestamp).toLocaleTimeString(),u=n.args.map(m=>typeof m=="object"?JSON.stringify(m):m).join(" ");if(console.log(` [${r}] ${u}`),n.stack){let m=n.stack.split(`
971
+ `).slice(0,3);for(let w of m)console.log(` ${w.trim()}`)}}break}case"warnings":{let t=a[1]?Number(a[1]):20,e=await Ve(c,t);if(C(l)){B(e);break}if(e.length===0){console.log(" no warnings captured");break}console.log(` ${e.length} warning(s):
972
+ `);for(let o of e){let n=new Date(o.timestamp).toLocaleTimeString(),r=o.args.map(u=>typeof u=="object"?JSON.stringify(u):u).join(" ");console.log(` [${n}] ${r}`)}break}case"animations":{let t=await z(c,"listAnimations")??[];if(s.includes("--json")){console.log(JSON.stringify(t,null,2));break}if(t.length===0){console.log(" no active animations");break}console.log(` ${t.length} active animation(s):
973
+ `);for(let e of t){let o=String(e.kind).padEnd(6),n=`${Number(e.from).toFixed(2)}\u2192${Number(e.to).toFixed(2)}`,r=Number(e.current??0).toFixed(2),u=`${Math.round((e.progress??0)*100)}%`,m=`${Math.round(e.elapsedMs??0)}ms`,w=e.loop?" loop":"",g=e.layoutBound?" layout":"";console.log(` #${e.id} ${o} ${n.padEnd(14)} cur=${r.padEnd(7)} ${u.padStart(4)} ${m}${w}${g}`)}break}case"animation":{let t=a[1];(!t||t==="--help"||t==="-h")&&(console.error(` usage: ${h("animation")} <id>`),process.exit(1));let e=Number(t);Number.isFinite(e)||(console.error(` invalid id: ${t}`),process.exit(1));let o=await z(c,"getAnimation",e);console.log(JSON.stringify(o,null,2));break}case"stop-animation":{let t=a[1];(!t||t==="--help"||t==="-h")&&(console.error(` usage: ${h("stop-animation")} <id|all>`),process.exit(1));let e=t==="all"?"all":Number(t);e!=="all"&&!Number.isFinite(e)&&(console.error(` invalid id: ${t}`),process.exit(1));let o=await z(c,"stopAnimation",e);console.log(` stopped ${o??0} animation(s)`);break}case"requests":{let t=a[1];if(t==="clear"){await et(c),C(l)?B({cleared:!0}):console.log(" request buffer cleared");break}let e=t==="all",o=e?a[2]:t,n=o?Number(o):20,r=await Ze(c,{failed:!e,limit:n});if(C(l)){B(r);break}if(r.length===0){console.log(e?" no requests captured":" no failed requests captured");break}console.log(` ${r.length} ${e?"request(s)":"failed request(s)"}:
974
+ `);for(let u of r){let m=new Date(u.timestamp).toLocaleTimeString();console.log(` [${m}] ${W(u)}`),u.responseBody?console.log(` ${u.responseBody}`):u.error&&console.log(` ${u.error}`)}break}case"network":{let t=a[1],e=null,o=null,n=!1,r=!1,u=1e3,m=!1,w=!1;for(let I=0;I<l.length;I++){let b=l[I];if(b==="--filter")e=l[I+1]??null,I++;else if(b==="--limit"){let p=Number(l[I+1]);Number.isFinite(p)&&(o=p),I++}else if(b==="--threshold"){let p=Number(l[I+1]);Number.isFinite(p)&&p>0&&(u=p),I++}else b==="--failed"?n=!0:b==="--slow"?r=!0:b==="--tail"||b==="-f"?m=!0:b==="--json"&&(w=!0)}if(t==="clear"){await c.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(t==="get"){let I=a[2];I||(console.error(" usage: sootsim network get <id>"),process.exit(1));let b=await c.send({type:"evaluate",code:`(() => {
953
975
  const obs = window.__sootsimObservability;
954
976
  if (!obs) return null;
955
- return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(M)}) || null;
956
- })()`});h||(console.error(` no entry with id ${M}`),process.exit(1)),x?console.log(JSON.stringify(h,null,2)):co(h);break}let g=s??(m?200:t?Number(t):20);Number.isFinite(g)||(console.error(` invalid limit: ${t} \u2014 \`network\` takes a numeric count (e.g. ${b("network")} 100).
957
- to target a specific sim, use \`--sim ${t}\` instead.`),process.exit(1));let $=async()=>{let M=await c.send({type:"evaluate",code:`(() => {
977
+ return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(I)}) || null;
978
+ })()`});b||(console.error(` no entry with id ${I}`),process.exit(1)),w?console.log(JSON.stringify(b,null,2)):co(b);break}let g=o??(m?200:t?Number(t):20);Number.isFinite(g)||(console.error(` invalid limit: ${t} \u2014 \`network\` takes a numeric count (e.g. ${h("network")} 100).
979
+ to target a specific sim, use \`--sim ${t}\` instead.`),process.exit(1));let $=async()=>{let I=await c.send({type:"evaluate",code:`(() => {
958
980
  const obs = window.__sootsimObservability;
959
981
  if (!obs) return { ok: false };
960
982
  return { ok: true, entries: obs.network.getSnapshot() };
961
- })()`});if(!M||!M.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return M.entries??[]},F=M=>{let h=M;if(n&&(h=h.filter(p=>!!p.error||p.status!=null&&p.status>=400)),r&&(h=h.filter(p=>p.durationMs!=null&&p.durationMs>=u)),e){let p=e.toLowerCase();h=h.filter(O=>(O.displayUrl||O.url).toLowerCase().includes(p))}return r&&!m&&(h=[...h].sort((p,O)=>(O.durationMs??0)-(p.durationMs??0))),h};if(!m){let M=await $(),h=F(M).slice(-g);if(x){console.log(JSON.stringify(h,null,2));break}if(h.length===0){M.length===0?console.log(" no network requests captured"):console.log(r?` no requests slower than ${u}ms (${M.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(r?` ${h.length} request(s) slower than ${u}ms (sorted by duration desc):
962
- `:` ${h.length} request(s):
963
- `);for(let p of h)Pt(p);break}console.log(` tailing network (ctrl-c to stop)...
964
- `);let q=new Set,H=!0,U=()=>{H=!1};process.on("SIGINT",U);try{for(;H;){let M=await $(),h=F(M);for(let p of h)p.durationMs!=null&&(q.has(p.id)||(q.add(p.id),x?console.log(JSON.stringify(p)):Pt(p)));await X(250)}}finally{process.off("SIGINT",U)}break}case"logs":{let t=a[1],e=null,s=null,n=null,r=!1,u=!1,m=!1;for(let h=0;h<l.length;h++){let p=l[h];if(p==="--filter")e=l[h+1]??null,h++;else if(p==="--limit"){let O=Number(l[h+1]);Number.isFinite(O)&&(s=O),h++}else p==="--level"?(n=l[h+1]??null,h++):p==="--tail"||p==="-f"?r=!0:p==="--json"?u=!0:(p==="--internal"||p==="--all")&&(m=!0)}let x=n?new Set(n.split(",").map(h=>h.trim()).filter(h=>h==="log"||h==="info"||h==="warn"||h==="error"||h==="debug")):null;if(t==="clear"){await ot(c),console.log(" log buffer cleared");break}let g=!u&&process.stdout.isTTY===!0,$=s??(r?500:t?Number(t):50);Number.isFinite($)||(console.error(` invalid limit: ${t} \u2014 \`logs\` takes a numeric count (e.g. ${b("logs")} 100).
965
- to target a specific sim, use \`--sim ${t}\` instead.`),process.exit(1));let F=()=>tt(c),q=h=>st(h,{level:x,filter:e,showInternal:m});if(!r){let h=await F(),p=q(h).slice(-$);if(u){console.log(JSON.stringify(p,null,2));break}if(p.length===0){console.log(h.length===0?" no logs captured":" no matching logs");break}console.log(` ${p.length} log(s):
966
- `);for(let O of p)Rt(O,g);break}console.log(` tailing logs (ctrl-c to stop)...
967
- `);let H=new Set,U=!0,M=()=>{U=!1};process.on("SIGINT",M);try{for(;U;){let h=await F(),p=q(h);for(let O of p)H.has(O.id)||(H.add(O.id),u?console.log(JSON.stringify(O)):Rt(O,g));await X(250)}}finally{process.off("SIGINT",M)}break}default:console.error(` unknown subcommand: ${y}`),process.exit(1)}if(ee.has(y)&&!o.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await w(c),!j.has(y)&&!D(l))try{await oe(c)}catch{}}catch(t){let e=t instanceof Error?t.message:String(t);console.error(` ${y??"inspect"} failed: ${e}`);let s=/^no sim connected with id (.+)$/.exec(e),n=/^command timed out after \d+s$/.test(e)||e.startsWith("sim disconnected:")||e.startsWith("bridge never reconnected")||e.startsWith("could not connect to ws://");if(s)await dt(c,_,s[1]);else if(/^no sim connected$/.test(e))ct(_);else if(n)process.stderr.write(` the sim is not responding. recover it with:
983
+ })()`});if(!I||!I.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return I.entries??[]},F=I=>{let b=I;if(n&&(b=b.filter(p=>!!p.error||p.status!=null&&p.status>=400)),r&&(b=b.filter(p=>p.durationMs!=null&&p.durationMs>=u)),e){let p=e.toLowerCase();b=b.filter(P=>(P.displayUrl||P.url).toLowerCase().includes(p))}return r&&!m&&(b=[...b].sort((p,P)=>(P.durationMs??0)-(p.durationMs??0))),b};if(!m){let I=await $(),b=F(I).slice(-g);if(w){console.log(JSON.stringify(b,null,2));break}if(b.length===0){I.length===0?console.log(" no network requests captured"):console.log(r?` no requests slower than ${u}ms (${I.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(r?` ${b.length} request(s) slower than ${u}ms (sorted by duration desc):
984
+ `:` ${b.length} request(s):
985
+ `);for(let p of b)Ot(p);break}console.log(` tailing network (ctrl-c to stop)...
986
+ `);let q=new Set,H=!0,U=()=>{H=!1};process.on("SIGINT",U);try{for(;H;){let I=await $(),b=F(I);for(let p of b)p.durationMs!=null&&(q.has(p.id)||(q.add(p.id),w?console.log(JSON.stringify(p)):Ot(p)));await X(250)}}finally{process.off("SIGINT",U)}break}case"logs":{let t=a[1],e=null,o=null,n=null,r=!1,u=!1,m=!1;for(let b=0;b<l.length;b++){let p=l[b];if(p==="--filter")e=l[b+1]??null,b++;else if(p==="--limit"){let P=Number(l[b+1]);Number.isFinite(P)&&(o=P),b++}else p==="--level"?(n=l[b+1]??null,b++):p==="--tail"||p==="-f"?r=!0:p==="--json"?u=!0:(p==="--internal"||p==="--all")&&(m=!0)}let w=n?new Set(n.split(",").map(b=>b.trim()).filter(b=>b==="log"||b==="info"||b==="warn"||b==="error"||b==="debug")):null;if(t==="clear"){await ot(c),console.log(" log buffer cleared");break}let g=!u&&process.stdout.isTTY===!0,$=o??(r?500:t?Number(t):50);Number.isFinite($)||(console.error(` invalid limit: ${t} \u2014 \`logs\` takes a numeric count (e.g. ${h("logs")} 100).
987
+ to target a specific sim, use \`--sim ${t}\` instead.`),process.exit(1));let F=()=>tt(c),q=b=>st(b,{level:w,filter:e,showInternal:m});if(!r){let b=await F(),p=q(b).slice(-$);if(u){console.log(JSON.stringify(p,null,2));break}if(p.length===0){console.log(b.length===0?" no logs captured":" no matching logs");break}console.log(` ${p.length} log(s):
988
+ `);for(let P of p)Rt(P,g);break}console.log(` tailing logs (ctrl-c to stop)...
989
+ `);let H=new Set,U=!0,I=()=>{U=!1};process.on("SIGINT",I);try{for(;U;){let b=await F(),p=q(b);for(let P of p)H.has(P.id)||(H.add(P.id),u?console.log(JSON.stringify(P)):Rt(P,g));await X(250)}}finally{process.off("SIGINT",I)}break}default:console.error(` unknown subcommand: ${y}`),process.exit(1)}if(ee.has(y)&&!s.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await x(c),!j.has(y)&&!C(l))try{await oe(c)}catch{}}catch(t){let e=t instanceof Error?t.message:String(t);console.error(` ${y??"inspect"} failed: ${e}`);let o=/^no sim connected with id (.+)$/.exec(e),n=/^command timed out after \d+s$/.test(e)||e.startsWith("sim disconnected:")||e.startsWith("bridge never reconnected")||e.startsWith("could not connect to ws://");if(o)await dt(c,N,o[1]);else if(/^no sim connected$/.test(e))ct(N);else if(n)process.stderr.write(` the sim is not responding. recover it with:
968
990
  sootsim close --sim <id> # force-close the wedged sim
969
991
  sootsim list # confirm it's gone
970
- `);else{try{await je(c)}catch{}try{await P({includeTail:!0})}catch{}try{await Z({includeTail:!0})}catch{}}process.exit(1)}finally{c.close()}}export{Vs as runInspect};
992
+ `);else{try{await je(c)}catch{}try{await O({includeTail:!0})}catch{}try{await Z({includeTail:!0})}catch{}}process.exit(1)}finally{c.close()}}export{Qs as runInspect};