sootsim 0.1.61 → 0.1.63

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 (136) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-Y5DHXXIB.js → agent-Z7M6NMR6.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-JKTA44ZS.js → agent-wrapper-C7OMZWTX.js} +2 -2
  4. package/dist-cli/chunks/{assert-RCHJYS4V.js → assert-OB4RMGU6.js} +2 -2
  5. package/dist-cli/chunks/auto-bootstrap-JF7VEKGP.js +2 -0
  6. package/dist-cli/chunks/beta-SZGXUHPX.js +2 -0
  7. package/dist-cli/chunks/{chunk-WNOAY3OR.js → chunk-2TVSYU32.js} +2 -2
  8. package/dist-cli/chunks/{chunk-MIGHBWF3.js → chunk-4232ZQOX.js} +1 -1
  9. package/dist-cli/chunks/{chunk-RESH7AUO.js → chunk-4H3UC4KB.js} +2 -2
  10. package/dist-cli/chunks/{chunk-CJTUKYTH.js → chunk-4OW4EPBS.js} +2 -2
  11. package/dist-cli/chunks/{chunk-SDHFNWW6.js → chunk-5OZ7M24R.js} +2 -2
  12. package/dist-cli/chunks/{chunk-2PMX6E4H.js → chunk-76MTBJ24.js} +1 -1
  13. package/dist-cli/chunks/{chunk-EZDINY66.js → chunk-7RZWW5VK.js} +2 -2
  14. package/dist-cli/chunks/{chunk-OPYA7ZEE.js → chunk-A3UFHDMY.js} +1 -1
  15. package/dist-cli/chunks/{chunk-O4GFKP3K.js → chunk-AMZB6WUA.js} +2 -2
  16. package/dist-cli/chunks/{chunk-PB7AQQSR.js → chunk-AUMMYIP5.js} +2 -2
  17. package/dist-cli/chunks/{chunk-OXK76D2Y.js → chunk-AYJGGZA4.js} +2 -2
  18. package/dist-cli/chunks/{chunk-7O43QYRW.js → chunk-B3644N6L.js} +1 -1
  19. package/dist-cli/chunks/{chunk-7U5X273C.js → chunk-C6UT7L2J.js} +2 -2
  20. package/dist-cli/chunks/chunk-CAFGDFEU.js +1 -0
  21. package/dist-cli/chunks/chunk-DAO2KA4O.js +1 -0
  22. package/dist-cli/chunks/{chunk-ROBRQSBJ.js → chunk-DFRQMFUV.js} +1 -1
  23. package/dist-cli/chunks/{chunk-6I65RLOE.js → chunk-DYUOXUBI.js} +1 -1
  24. package/dist-cli/chunks/{chunk-GHPKHUMA.js → chunk-E2EPTSHO.js} +2 -2
  25. package/dist-cli/chunks/{chunk-4XUOL4AD.js → chunk-EIKREDI4.js} +2 -2
  26. package/dist-cli/chunks/{chunk-5HIFH66T.js → chunk-ENACZPKI.js} +2 -2
  27. package/dist-cli/chunks/{chunk-UZYGDMBM.js → chunk-FEZCATWN.js} +2 -2
  28. package/dist-cli/chunks/{chunk-VOIYKBUR.js → chunk-FSSJVHNV.js} +3 -3
  29. package/dist-cli/chunks/{chunk-K23PH2GT.js → chunk-GICJIXEH.js} +2 -2
  30. package/dist-cli/chunks/{chunk-FFLU7U2E.js → chunk-GW77VHPI.js} +2 -2
  31. package/dist-cli/chunks/{chunk-JH7QZNMN.js → chunk-HPVO7FJA.js} +2 -2
  32. package/dist-cli/chunks/{chunk-3NBPI3RK.js → chunk-IKFKEII6.js} +1 -1
  33. package/dist-cli/chunks/{chunk-U35XNNJY.js → chunk-INXMOS35.js} +1 -1
  34. package/dist-cli/chunks/{chunk-D7ELOJUV.js → chunk-KRRNCL56.js} +2 -2
  35. package/dist-cli/chunks/{chunk-GU4C6XUG.js → chunk-KX3FO4N4.js} +3 -3
  36. package/dist-cli/chunks/{chunk-KILM2EVT.js → chunk-LJ7SH2KY.js} +2 -2
  37. package/dist-cli/chunks/{chunk-7IFCJ2IT.js → chunk-MTTIJQ64.js} +2 -2
  38. package/dist-cli/chunks/{chunk-FULJHRZT.js → chunk-NWHQG4PG.js} +2 -2
  39. package/dist-cli/chunks/{chunk-4E765KMB.js → chunk-PDMITY2P.js} +1 -1
  40. package/dist-cli/chunks/{chunk-XZLTYOHT.js → chunk-PX7QNGSM.js} +3 -3
  41. package/dist-cli/chunks/{chunk-UXECVWRC.js → chunk-PY25FDGX.js} +1 -1
  42. package/dist-cli/chunks/{chunk-CQVJMAK7.js → chunk-QW6P2JE2.js} +1 -1
  43. package/dist-cli/chunks/chunk-SOKY5FGT.js +1 -0
  44. package/dist-cli/chunks/{chunk-SBJZMEWR.js → chunk-SSTMIACF.js} +1 -1
  45. package/dist-cli/chunks/{chunk-J45J6PUU.js → chunk-T7H7BKA7.js} +2 -2
  46. package/dist-cli/chunks/chunk-U42HSSAI.js +2 -0
  47. package/dist-cli/chunks/{chunk-FEAAP6XM.js → chunk-VV265FEE.js} +2 -2
  48. package/dist-cli/chunks/chunk-WCMYVXHS.js +2 -0
  49. package/dist-cli/chunks/{chunk-PKUBEQ7T.js → chunk-XILD5NPV.js} +1 -1
  50. package/dist-cli/chunks/cli-version-BB3PGPZA.js +2 -0
  51. package/dist-cli/chunks/{compat-PPH5L7UC.js → compat-2AFC4MFV.js} +3 -3
  52. package/dist-cli/chunks/{config-S6QN23OF.js → config-KEEXBCOM.js} +2 -2
  53. package/dist-cli/chunks/control-PI6FRLTV.js +2 -0
  54. package/dist-cli/chunks/{cpu-profile-J5KLARMT.js → cpu-profile-RPSEEWCO.js} +2 -2
  55. package/dist-cli/chunks/{daemon-6N7C25DV.js → daemon-FCQLYFNH.js} +2 -2
  56. package/dist-cli/chunks/{debug-3FBARTDW.js → debug-QSYUF4WZ.js} +3 -3
  57. package/dist-cli/chunks/demo-app-registry-SDP4RWXB.js +2 -0
  58. package/dist-cli/chunks/{detox-TXZELC5K.js → detox-6PJOIC7Z.js} +2 -2
  59. package/dist-cli/chunks/{device-NBV6IVKX.js → device-H7GVARBE.js} +2 -2
  60. package/dist-cli/chunks/{diagnose-DGRJ3BSK.js → diagnose-H47FC64H.js} +2 -2
  61. package/dist-cli/chunks/drivers-BFET7Y5U.js +2 -0
  62. package/dist-cli/chunks/{electron-HUTXPJJI.js → electron-54ZCOKJE.js} +3 -3
  63. package/dist-cli/chunks/flow-JC7BTILV.js +2 -0
  64. package/dist-cli/chunks/{hints-4473IWWZ.js → hints-V4VBWK3W.js} +2 -2
  65. package/dist-cli/chunks/{home-paths-YIFLBNJ7.js → home-paths-GUUGF76T.js} +2 -2
  66. package/dist-cli/chunks/{inspect-I3QAWTDQ.js → inspect-NDLLEBJK.js} +63 -30
  67. package/dist-cli/chunks/install-AXZ4MKSG.js +2 -0
  68. package/dist-cli/chunks/{install-desktop-WY7UJ3Z6.js → install-desktop-FBK4PRA3.js} +3 -3
  69. package/dist-cli/chunks/{keys-BSBR3RLA.js → keys-IWDHA2GT.js} +2 -2
  70. package/dist-cli/chunks/{launch-CVEJVX4U.js → launch-MQEJM5XD.js} +3 -3
  71. package/dist-cli/chunks/{login-CQD3S2ON.js → login-FFLXNWYQ.js} +4 -4
  72. package/dist-cli/chunks/{logout-KAXI55BQ.js → logout-X4NH4PZG.js} +2 -2
  73. package/dist-cli/chunks/{maestro-X5DOFIRM.js → maestro-V3GTFFX6.js} +2 -2
  74. package/dist-cli/chunks/{preview-WIYOOZUK.js → preview-YHY7IHFE.js} +2 -2
  75. package/dist-cli/chunks/{profile-OY2E3X2K.js → profile-CFYRAH3J.js} +2 -2
  76. package/dist-cli/chunks/{react-WR32MKDG.js → react-L7NP2D6J.js} +2 -2
  77. package/dist-cli/chunks/{record-RRC2AFKD.js → record-36R7J2BU.js} +8 -8
  78. package/dist-cli/chunks/runtime-L2E4XOOB.js +2 -0
  79. package/dist-cli/chunks/{runtime-delivery-NCBHWNDU.js → runtime-delivery-CWSGC6RY.js} +2 -2
  80. package/dist-cli/chunks/{screenshot-APLXYLMG.js → screenshot-FAPUEO63.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-EHIGEDTE.js → screenshot-mode-QB7FVHYI.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-2VO2ONBK.js → screenshots-XAB5UKQB.js} +2 -2
  83. package/dist-cli/chunks/{server-HYBCDWZM.js → server-NLNCGLAT.js} +2 -2
  84. package/dist-cli/chunks/setup-repo-XGSB77UN.js +2 -0
  85. package/dist-cli/chunks/{skills-NR3LGYAG.js → skills-WBR5NZHN.js} +2 -2
  86. package/dist-cli/chunks/{start-OFEUKSPM.js → start-3I5VJI3S.js} +4 -4
  87. package/dist-cli/chunks/store-3LACO57B.js +2 -0
  88. package/dist-cli/chunks/telemetry-6QW73WDZ.js +2 -0
  89. package/dist-cli/chunks/{test-TYEMATPY.js → test-LD2RIFI2.js} +3 -3
  90. package/dist-cli/chunks/{three-mode-EIKE6HNC.js → three-mode-5GPHB6BR.js} +2 -2
  91. package/dist-cli/chunks/{timeline-O6EYX7EM.js → timeline-AOVC2P3F.js} +2 -2
  92. package/dist-cli/chunks/{upgrade-HKW6G5DV.js → upgrade-CU3DMD2C.js} +2 -2
  93. package/dist-cli/chunks/upload-32RTWBK5.js +2 -0
  94. package/dist-cli/chunks/web-RNUV6WCK.js +2 -0
  95. package/dist-cli/chunks/{what-happened-YCDOVOKQ.js → what-happened-BSRVVJPQ.js} +2 -2
  96. package/dist-cli/chunks/{whoami-NQYPKVCM.js → whoami-ZAVHKQPY.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 +1 -1
  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 +1 -1
  116. package/dist-lib/vite.cjs +1 -1
  117. package/package.json +1 -1
  118. package/dist-cli/chunks/auto-bootstrap-OJZDXBR6.js +0 -2
  119. package/dist-cli/chunks/beta-RIJR4LYY.js +0 -2
  120. package/dist-cli/chunks/chunk-4ZZ2FEXT.js +0 -2
  121. package/dist-cli/chunks/chunk-6AJED4HB.js +0 -2
  122. package/dist-cli/chunks/chunk-EFPFJZQG.js +0 -1
  123. package/dist-cli/chunks/chunk-QAMASPCQ.js +0 -1
  124. package/dist-cli/chunks/chunk-RVDEV2FN.js +0 -1
  125. package/dist-cli/chunks/cli-version-YAMXXNI2.js +0 -2
  126. package/dist-cli/chunks/control-7GTHUVJB.js +0 -2
  127. package/dist-cli/chunks/demo-app-registry-BT3NTO6L.js +0 -2
  128. package/dist-cli/chunks/drivers-AJGSL6IM.js +0 -2
  129. package/dist-cli/chunks/flow-RBX5EOXV.js +0 -2
  130. package/dist-cli/chunks/install-ZI3J7HCK.js +0 -2
  131. package/dist-cli/chunks/runtime-URJZQE3L.js +0 -2
  132. package/dist-cli/chunks/setup-repo-I767FRBL.js +0 -2
  133. package/dist-cli/chunks/store-F6RPVKJL.js +0 -2
  134. package/dist-cli/chunks/telemetry-HGTHILVR.js +0 -2
  135. package/dist-cli/chunks/upload-KUD4O36E.js +0 -2
  136. package/dist-cli/chunks/web-GMKCHONH.js +0 -2
@@ -1,9 +1,9 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBRQSBJ.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-RESH7AUO.js";import{a as Be,h as ce}from"./chunk-SDHFNWW6.js";import{b as ct,c as dt,i as ut}from"./chunk-K23PH2GT.js";import"./chunk-7U5X273C.js";import{a as je}from"./chunk-UXECVWRC.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-7O43QYRW.js";import"./chunk-O4GFKP3K.js";import"./chunk-PB7AQQSR.js";import"./chunk-3NBPI3RK.js";import"./chunk-RVDEV2FN.js";import"./chunk-4XUOL4AD.js";import"./chunk-OPYA7ZEE.js";import{a as we,c as xe,d as Oe}from"./chunk-MIGHBWF3.js";import{a as Ae}from"./chunk-6AJED4HB.js";import{c as Re,e as Ee,f as De,g as Ce,h as $e}from"./chunk-CJTUKYTH.js";import{b as Pe}from"./chunk-SBJZMEWR.js";import"./chunk-4ZZ2FEXT.js";import"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.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(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as G}from"./chunk-2TVSYU32.js";import{a as Le,b as Je}from"./chunk-DFRQMFUV.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-4H3UC4KB.js";import{a as Be,h as ce}from"./chunk-5OZ7M24R.js";import{b as ct,c as dt,i as ut}from"./chunk-GICJIXEH.js";import"./chunk-C6UT7L2J.js";import{a as je}from"./chunk-PY25FDGX.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-B3644N6L.js";import"./chunk-AMZB6WUA.js";import"./chunk-AUMMYIP5.js";import"./chunk-IKFKEII6.js";import"./chunk-CAFGDFEU.js";import"./chunk-EIKREDI4.js";import"./chunk-A3UFHDMY.js";import{a as we,c as xe,d as Oe}from"./chunk-4232ZQOX.js";import{a as Ae}from"./chunk-WCMYVXHS.js";import{c as Re,e as Ee,f as De,g as Ce,h as $e}from"./chunk-4OW4EPBS.js";import{b as Pe}from"./chunk-SSTMIACF.js";import"./chunk-U42HSSAI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.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,F=Y?.keyboard;if(a){B({shell:x,tree:W??"",keyboard:F});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"),F&&F.visible){let O=F.spec,V=[O?.keyboardType?`type=${O.keyboardType}`:null,O?.returnKeyType&&O.returnKeyType!=="default"?`return=${O.returnKeyType}`:null,F.mode!=="letters"?`mode=${F.mode}`:null,F.shifted?"shift":null,F.capsLock?"caps":null,O?.autoCapitalize&&O.autoCapitalize!=="sentences"?`autoCap=${O.autoCapitalize}`:null,F.accessoryBarId?`accessory=${F.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(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(`
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 F=l.indexOf(x);return F>=0&&F+1<l.length?l[F+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 F of x.slice(0,20)){let Z=F.absolutePosition?`@(${Math.round(F.absolutePosition.x)},${Math.round(F.absolutePosition.y)})`:"",O=F.layout?`${Math.round(F.layout.width)}x${Math.round(F.layout.height)}`:"?x?",V=F.text?` "${F.text.slice(0,30)}"`:"",oe=F.testID?` #${F.testID}`:"",ee=F.accessibilityLabel?` \u24D8"${String(F.accessibilityLabel).slice(0,24)}"`:"",ye=F.accessibilityRole?`[${F.accessibilityRole}]`:F.type,he=ve(F);console.log(` ${ye}${V}${ee}${oe} ${O} ${Z}`),console.log(` \u2192 ${he}`),W&&console.log(Ie(JSON.stringify(F,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 F=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} ${F}${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 F=`@(${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} ${F}${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
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
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 () => {
@@ -39,8 +39,32 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
39
39
  const requiredStablePolls = ${Math.max(1,Math.round(l))}
40
40
  const strict = ${f?"true":"false"}
41
41
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
42
+
43
+ // route-aware settle: a tap that pushes/pops a screen is async \u2014 the
44
+ // old screen still renders for a moment, then the new one mounts and
45
+ // its content loads. a pure layout-hash check reports "idle" on the
46
+ // outgoing screen or on the incoming skeleton, so a driver re-taps
47
+ // and stacks duplicate navigations. drain any in-flight screen
48
+ // transition FIRST, bounded by the overall budget. when no
49
+ // transition is happening this returns in ~80ms (startWindowMs), so
50
+ // a plain button tap barely pays for it.
51
+ try {
52
+ const wfst = window.__sootsimTest?.waitForScreenTransitions
53
+ if (typeof wfst === 'function') {
54
+ const remaining = deadline - Date.now()
55
+ if (remaining > 120) {
56
+ await wfst({
57
+ timeoutMs: Math.min(remaining - 80, 4000),
58
+ settleMs: 64,
59
+ startWindowMs: 80,
60
+ })
61
+ }
62
+ }
63
+ } catch {}
64
+
42
65
  const readSnapshot = async () => {
43
66
  let animating = false
67
+ let pendingFetches = 0
44
68
  try {
45
69
  const stats = await window.__sootsimRenderHost?.queryStats?.()
46
70
  if (stats) {
@@ -48,6 +72,14 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
48
72
  stats.hasActiveAnims === true ||
49
73
  stats.hasActiveNativeAnimations === true ||
50
74
  stats.hasPendingAnimationFrames === true
75
+ // a freshly-pushed screen showing a skeleton is layout-stable
76
+ // but not actually settled \u2014 its data/images are still in
77
+ // flight. treat bounded image-loader fetches as not-idle so
78
+ // settle waits for real content, capped by the budget.
79
+ const pf = stats.memory && stats.memory.imageLoader
80
+ ? stats.memory.imageLoader.pendingFetches
81
+ : 0
82
+ pendingFetches = typeof pf === 'number' ? pf : 0
51
83
  }
52
84
  } catch {}
53
85
  const root = window.__sootsimRoot
@@ -61,7 +93,7 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
61
93
  }
62
94
  walk(root)
63
95
  }
64
- return { layout: nodes.join(';'), animating }
96
+ return { layout: nodes.join(';'), animating, pendingFetches }
65
97
  }
66
98
 
67
99
  let lastLayout = ''
@@ -69,7 +101,8 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
69
101
  while (Date.now() < deadline) {
70
102
  const snapshot = await readSnapshot()
71
103
  const strictOk = !strict || !snapshot.animating
72
- if (strictOk && snapshot.layout === lastLayout) {
104
+ const contentReady = snapshot.pendingFetches === 0
105
+ if (strictOk && contentReady && snapshot.layout === lastLayout) {
73
106
  stable++
74
107
  if (stable >= requiredStablePolls) {
75
108
  return { settled: true, elapsed: Date.now() - start }
@@ -85,8 +118,8 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
85
118
  const t = window.SootSim?.bridges?.timeline
86
119
  if (!t) return { ok: false, error: 'timeline bridge missing' }
87
120
  return { ok: true, result: await t.recent(${JSON.stringify(K)}) }
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 () => {
121
+ })()`});(!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 Ft(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 _t(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(`
122
+ `).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 _e(s){return s.send({type:"evaluate",code:`(async () => {
90
123
  const kb = window.__sootsimKeyboard
91
124
  const test = window.__sootsimTest
92
125
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -118,7 +151,7 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
118
151
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
119
152
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
120
153
  }
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 () => {
154
+ })()`})}async function fo(s,d=600){let i=Date.now()+d;for(;Date.now()<=i;){let l=await _e(s);if(l.visible)return l;await X(30)}return _e(s)}async function ge(s,d){let i=await _e(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 () => {
122
155
  const requested = ${JSON.stringify(i??"toggle")}
123
156
  const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
124
157
  const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
@@ -135,16 +168,16 @@ import{a as G}from"./chunk-WNOAY3OR.js";import{a as Le,b as Je}from"./chunk-ROBR
135
168
  })()`}):s.send({type:"evaluate",code:`(async () => {
136
169
  window.dispatchEvent(new CustomEvent(${JSON.stringify(d==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
137
170
  return { ok: true, action: ${JSON.stringify(d)} }
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}
171
+ })()`})}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 Fe(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
172
  `),process.exit(0))}if(k==="shell"){let n=xe("shell",t);n&&(console.log(`${n}
140
173
  `),process.exit(0))}let e=xe("inspect",t),o=["do","get","debug","wait"].map(n=>we(n,t)).filter(n=>n!=null).join(`
141
174
 
142
175
  `);console.log(`${e??""}
143
176
 
144
177
  ${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-AJGSL6IM.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:`(() => ({
178
+ `),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-BFET7Y5U.js"),e=t();console.log(` available drivers (${e.length}):
179
+ `);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()?5e3:1500;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.
180
+ `)}catch{}}async function F(){try{return await c.send({type:"evaluate",code:`(() => ({
148
181
  console: window.__sootsimConsole?.count?.() || null,
149
182
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
150
183
  }))()`})||{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(`
@@ -153,7 +186,7 @@ ${o}
153
186
  `);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
187
  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(`
155
188
  recent console errors:
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,`(() => {
189
+ `);for(let w of m){let g=new Date(w.timestamp).toLocaleTimeString(),$=Array.isArray(w.args)?w.args.map(_=>typeof _=="object"?JSON.stringify(_):String(_)).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,`(() => {
157
190
  const tl = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.timeline
158
191
  if (!tl || typeof tl.summary !== 'function') return null
159
192
  const cursorKey = ${JSON.stringify(e)}
@@ -171,7 +204,7 @@ ${o}
171
204
  return summary ? { summary, consoleSplit } : null
172
205
  })()`)}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
206
  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 () => {
207
+ `);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 _t({bridge:c,args:s});break}case"idle":{await Ft({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 () => {
175
208
  const t = window.__sootsimTest
176
209
  const q = ${JSON.stringify(t)}
177
210
  let node = null
@@ -232,12 +265,12 @@ ${o}
232
265
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
233
266
  const value = await interact.drag(${t}, ${e}, ${o}, ${n}, ${Math.max(1,Math.round(m))}, ${Math.max(0,Math.round(w))})
234
267
  return { ok: !!value, value }
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 () => {
268
+ })()`});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 _=await c.send({type:"evaluate",code:`(async () => {
236
269
  const interact = window.__sootsimInteract
237
270
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
238
271
  const value = await interact.pinch(${t}, ${e}, ${o}, ${n}, ${r}, ${u}, ${m}, ${w}, ${Math.max(1,Math.round(g))}, ${Math.max(0,Math.round($))})
239
272
  return { ok: !!value, value }
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 () => {
273
+ })()`});_?.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(_,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"),_=e("--max-y"),q=e("--min-x"),H=e("--max-x");for(let[R,A]of[["--min-y",$],["--max-y",_],["--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:_!==null?Number(_):null,near:I,nth:r,first:g}),p=await c.send({type:"evaluate",code:`(async () => {
241
274
  const t = window.__sootsimTest
242
275
  if (!t) return { error: 'bridge-not-ready' }
243
276
  const F = ${b}
@@ -357,7 +390,7 @@ ${o}
357
390
  total,
358
391
  idx,
359
392
  }
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 () => {
393
+ })()`});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=Fe(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 () => {
361
394
  const t = window.__sootsimTest
362
395
  if (!t) return { error: 'bridge-not-ready' }
363
396
  // try testID first \u2014 strongest signal of "this is the
@@ -398,7 +431,7 @@ ${o}
398
431
  }
399
432
  }
400
433
  return { strategy: 'none' }
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 () => {
434
+ })()`});"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=Fe(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 () => {
402
435
  const t = window.__sootsimTest
403
436
  if (!t) return null
404
437
  const n = (await t.findByTestId(${e})) || (await t.findById(${e}))
@@ -440,7 +473,7 @@ ${o}
440
473
  },
441
474
  strategy: (resolved && resolved.strategy) || 'matched-node',
442
475
  }
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 () => {
476
+ })()`});(!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=Fe(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 () => {
444
477
  const t = window.__sootsimTest
445
478
  if (!t) return null
446
479
  const n = await (t.findByTestId(${o}) || t.findById(${o}))
@@ -496,7 +529,7 @@ ${o}
496
529
  statusBarHeight: spec.statusBarHeight || 0,
497
530
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
498
531
  }
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 () => {
532
+ })()`}),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),_=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=_,R=Math.min(u-q,_+U);break;case"swipe-from-bottom-edge":b=g,p=u-q,R=Math.max(_,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 () => {
500
533
  const interact = window.__sootsimInteract
501
534
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
502
535
  const value = await interact.drag(${b}, ${p}, ${P}, ${R}, ${A}, ${be})
@@ -592,7 +625,7 @@ ${o}
592
625
  ${h("shell")} open-card clock 800
593
626
  ${h("shell")} appearance dark
594
627
  ${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:`;(() => {
628
+ `);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 _=$?.applied??g;console.log(` appearance: ${_}`)}}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:`;(() => {
596
629
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
597
630
  if (typeof reloadExternalApp === 'function') {
598
631
  reloadExternalApp()
@@ -603,7 +636,7 @@ ${o}
603
636
  })()`});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(`
604
637
  \u26A0 ${m.length} error(s) during mount:
605
638
  `);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 () => {
639
+ `).slice(0,2);for(let _ of $)console.log(` ${_.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 () => {
607
640
  const globals = {}
608
641
 
609
642
  // test bridge (proxy in worker mode)
@@ -834,7 +867,7 @@ ${o}
834
867
  mode: 'main-thread',
835
868
  frames: (stats.recentFrames || []).slice(-${e}),
836
869
  }
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 () => {
870
+ })()`});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,$,_,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${_.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 () => {
838
871
  if (window.__sootsimRenderHost) {
839
872
  const session = window.${Q} || {}
840
873
  if (session.active) {
@@ -876,7 +909,7 @@ ${o}
876
909
  mode: 'main-thread',
877
910
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${e}),
878
911
  }
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(`
912
+ })()`});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,$,_,q]of r)console.log(` ${m.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${g.toFixed(2).padStart(7)} ${$.toFixed(2).padStart(7)} ${_.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
913
  ${h("perf")} transition <event> \u2014 profile a shell transition
881
914
 
882
915
  events:
@@ -980,13 +1013,13 @@ ${o}
980
1013
  const obs = window.__sootsimObservability;
981
1014
  if (!obs) return { ok: false };
982
1015
  return { ok: true, entries: obs.network.getSnapshot() };
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):
1016
+ })()`});if(!I||!I.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return I.entries??[]},_=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=_(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
1017
  `:` ${b.length} request(s):
985
1018
  `);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):
1019
+ `);let q=new Set,H=!0,U=()=>{H=!1};process.on("SIGINT",U);try{for(;H;){let I=await $(),b=_(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).
1020
+ to target a specific sim, use \`--sim ${t}\` instead.`),process.exit(1));let _=()=>tt(c),q=b=>st(b,{level:w,filter:e,showInternal:m});if(!r){let b=await _(),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
1021
  `);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:
1022
+ `);let H=new Set,U=!0,I=()=>{U=!1};process.on("SIGINT",I);try{for(;U;){let b=await _(),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:
990
1023
  sootsim close --sim <id> # force-close the wedged sim
991
1024
  sootsim list # confirm it's gone
992
1025
  `);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};
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as o}from"./chunk-HPVO7FJA.js";import"./chunk-PDMITY2P.js";import"./chunk-FSSJVHNV.js";import"./chunk-VV265FEE.js";import"./chunk-GW77VHPI.js";import"./chunk-4OW4EPBS.js";import"./chunk-SSTMIACF.js";import"./chunk-U42HSSAI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";async function t(n){console.error(" note: `sootsim install` is now `sootsim setup-repo`. forwarding\u2026\n"),await o(n)}export{t as runInstall};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as b}from"./chunk-4E765KMB.js";import{a as x}from"./chunk-3NBPI3RK.js";import"./chunk-U35XNNJY.js";import{spawn as k,spawnSync as u}from"child_process";import{chmodSync as S,createWriteStream as E,existsSync as w,mkdirSync as y,renameSync as T,rmSync as g,statSync as P}from"fs";import{tmpdir as D}from"os";import{dirname as M,join as f,resolve as v}from"path";var h="https://sootbean.com/api/electron-release";function A(){let r=process.arch;if(process.platform==="darwin"){let o=r==="arm64"?"mac-arm64":"mac-x64",n=`sootsim-latest-${o}.dmg`;return{platform:o,filename:n,url:`${h}/${n}`,install:_}}if(process.platform==="linux"){let o="sootsim-latest-linux-x64.AppImage";return{platform:"linux-x64",filename:o,url:`${h}/${o}`,install:L}}if(process.platform==="win32"){let o="sootsim-latest-win-x64.exe";return{platform:"win-x64",filename:o,url:`${h}/${o}`,install:C}}return null}async function O({url:r,dest:o,onProgress:n}){let s=await fetch(r,{redirect:"follow"});if(!s.ok)throw new Error(`download failed: ${s.status} ${s.statusText} (${r})`);let t=s.headers.get("content-length"),a=t?Number(t):null;if(!s.body)throw new Error("download failed: empty response body");y(M(o),{recursive:!0});let i=E(o),d=s.body.getReader(),c=0;try{for(;;){let{done:l,value:p}=await d.read();if(l)break;i.write(Buffer.from(p)),c+=p.byteLength,n?.(c,a)}}finally{await new Promise((l,p)=>{i.end(e=>e?p(e):l())})}}function I(r,o){let n=(r/1048576).toFixed(1);if(!o)return` ${n} MB`;let s=Math.min(100,Math.round(r/o*100)),t=(o/(1024*1024)).toFixed(1),a=24,i=Math.round(s/100*a);return` ${"\u2588".repeat(i)+"\u2591".repeat(a-i)} ${s}% ${n} / ${t} MB`}async function _(r){let o=u("hdiutil",["attach","-nobrowse","-readonly",r],{encoding:"utf8"});if(o.status!==0)throw new Error(`hdiutil attach failed: ${o.stderr||o.stdout}`.trim());let n=o.stdout.trim().split(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as b}from"./chunk-PDMITY2P.js";import{a as x}from"./chunk-IKFKEII6.js";import"./chunk-INXMOS35.js";import{spawn as k,spawnSync as u}from"child_process";import{chmodSync as S,createWriteStream as E,existsSync as w,mkdirSync as y,renameSync as T,rmSync as g,statSync as P}from"fs";import{tmpdir as D}from"os";import{dirname as M,join as f,resolve as v}from"path";var h="https://sootbean.com/api/electron-release";function A(){let r=process.arch;if(process.platform==="darwin"){let o=r==="arm64"?"mac-arm64":"mac-x64",n=`sootsim-latest-${o}.dmg`;return{platform:o,filename:n,url:`${h}/${n}`,install:_}}if(process.platform==="linux"){let o="sootsim-latest-linux-x64.AppImage";return{platform:"linux-x64",filename:o,url:`${h}/${o}`,install:L}}if(process.platform==="win32"){let o="sootsim-latest-win-x64.exe";return{platform:"win-x64",filename:o,url:`${h}/${o}`,install:C}}return null}async function O({url:r,dest:o,onProgress:n}){let s=await fetch(r,{redirect:"follow"});if(!s.ok)throw new Error(`download failed: ${s.status} ${s.statusText} (${r})`);let t=s.headers.get("content-length"),a=t?Number(t):null;if(!s.body)throw new Error("download failed: empty response body");y(M(o),{recursive:!0});let i=E(o),d=s.body.getReader(),c=0;try{for(;;){let{done:l,value:p}=await d.read();if(l)break;i.write(Buffer.from(p)),c+=p.byteLength,n?.(c,a)}}finally{await new Promise((l,p)=>{i.end(e=>e?p(e):l())})}}function I(r,o){let n=(r/1048576).toFixed(1);if(!o)return` ${n} MB`;let s=Math.min(100,Math.round(r/o*100)),t=(o/(1024*1024)).toFixed(1),a=24,i=Math.round(s/100*a);return` ${"\u2588".repeat(i)+"\u2591".repeat(a-i)} ${s}% ${n} / ${t} MB`}async function _(r){let o=u("hdiutil",["attach","-nobrowse","-readonly",r],{encoding:"utf8"});if(o.status!==0)throw new Error(`hdiutil attach failed: ${o.stderr||o.stdout}`.trim());let n=o.stdout.trim().split(`
3
3
  `),t=n[n.length-1].split(" ").pop()?.trim();if(!t||!w(t))throw new Error(`could not determine dmg mount point (output: ${o.stdout})`);let a=f(t,"sootsim.app");if(!w(a))throw u("hdiutil",["detach","-force",t]),new Error(`sootsim.app not found inside ${t}`);let i="/Applications",d=v(process.env.HOME||"","Applications"),c=i;try{let m=f(i,`.sootsim-write-probe-${process.pid}`);u("touch",[m]),w(m)?g(m,{force:!0}):c=d}catch{c=d}c===d&&y(c,{recursive:!0});let l=f(c,"sootsim.app");w(l)&&g(l,{recursive:!0,force:!0});let p=u("cp",["-R",a,l]),e=u("hdiutil",["detach","-force",t]);if(p.status!==0)throw new Error(`copy to ${l} failed: ${p.stderr?.toString()||""}`.trim());return e.status!==0&&console.warn(` warning: failed to unmount ${t} (${e.stderr?.toString().trim()||"unknown error"})`),u("xattr",["-dr","com.apple.quarantine",l]),l}async function L(r){let o=v(process.env.HOME||"","Applications");y(o,{recursive:!0});let n=f(o,"sootsim.AppImage");return w(n)&&g(n,{force:!0}),T(r,n),S(n,493),n}async function C(r){return await new Promise((o,n)=>{let s=k("cmd",["/c","start",'""',"/wait",r],{stdio:"inherit"});s.once("error",n),s.once("exit",t=>{t===0?o():n(new Error(`installer exited with code ${t}`))})}),r}async function Y(r){(r.includes("--help")||r.includes("-h"))&&(console.log(`
4
4
  sootsim install-desktop \u2014 download and install the optional desktop GUI
5
5
 
@@ -20,4 +20,4 @@ examples:
20
20
  `),process.exit(0));let o=r.includes("--yes")||r.includes("-y")||process.env.SOOTSIM_NO_PROMPT==="1"||process.env.CI==="1"||!process.stdin.isTTY,n=r.includes("--force"),s=x();if(s&&!n){console.log(` sootsim desktop already installed at: ${s.path}`),console.log(" pass --force to reinstall.");return}let t=A();if(t||(console.error(` no desktop build available for ${process.platform}/${process.arch}.`),console.error(" supported: darwin-arm64, darwin-x64, linux-x64, win32-x64"),process.exit(1)),console.log(` platform: ${t.platform}`),console.log(` download: ${t.url}`),console.log(),!o){if(!await b("download and install now?",!0)){console.log(" cancelled.");return}console.log()}let a=f(D(),`sootsim-install-${Date.now()}`),i=f(a,t.filename),d=0;process.stdout.write(` downloading ${t.filename}...
21
21
  `);try{await O({url:t.url,dest:i,onProgress:(e,m)=>{let $=Date.now();$-d<100&&e<(m??1/0)||(d=$,process.stdout.isTTY&&process.stdout.write(`\r\x1B[2K${I(e,m)}`))}})}catch(e){g(a,{recursive:!0,force:!0}),console.error(`
22
22
  download failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}process.stdout.isTTY&&process.stdout.write(`
23
- `);let c=P(i).size;console.log(` downloaded ${(c/(1024*1024)).toFixed(1)} MB`),console.log(),console.log(" installing...");let{trackCliEvent:l,flushCliTelemetry:p}=await import("./telemetry-HGTHILVR.js");try{let e=await t.install(i);l({event:"cli_install_desktop_succeeded",properties:{platform:t.platform,size_bytes:c}}),console.log(` installed: ${e}`)}catch(e){l({event:"cli_install_desktop_failed",properties:{platform:t.platform,error:e instanceof Error?e.message:String(e)}}),await p(),console.error(` install failed: ${e instanceof Error?e.message:String(e)}`),console.error(` keeping download at ${i} for manual install.`),process.exit(1)}finally{g(a,{recursive:!0,force:!0})}console.log(),console.log(" next steps:"),console.log(" sootsim electron launch the desktop app"),console.log(" sootsim open <target> open a demo or bundle in it")}export{Y as runInstallDesktop};
23
+ `);let c=P(i).size;console.log(` downloaded ${(c/(1024*1024)).toFixed(1)} MB`),console.log(),console.log(" installing...");let{trackCliEvent:l,flushCliTelemetry:p}=await import("./telemetry-6QW73WDZ.js");try{let e=await t.install(i);l({event:"cli_install_desktop_succeeded",properties:{platform:t.platform,size_bytes:c}}),console.log(` installed: ${e}`)}catch(e){l({event:"cli_install_desktop_failed",properties:{platform:t.platform,error:e instanceof Error?e.message:String(e)}}),await p(),console.error(` install failed: ${e instanceof Error?e.message:String(e)}`),console.error(` keeping download at ${i} for manual install.`),process.exit(1)}finally{g(a,{recursive:!0,force:!0})}console.log(),console.log(" next steps:"),console.log(" sootsim electron launch the desktop app"),console.log(" sootsim open <target> open a demo or bundle in it")}export{Y as runInstallDesktop};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as l,b as d,c as k,d as y,e as g}from"./chunk-FULJHRZT.js";import{d as c}from"./chunk-FFLU7U2E.js";import"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.js";async function a(){let s=await c();return s?.token||(process.stderr.write(" sootsim keys ... needs you to be signed in.\n run `sootsim login` first.\n"),process.exit(1)),{origin:s.origin,token:s.token}}function f(s){if(!s)return"never";try{return new Date(s).toLocaleString()}catch{return s}}async function h(s){let i=s[0];if(!i||i==="--help"||i==="-h"){u();return}if(i==="list"){let{origin:o,token:e}=await a(),n=await fetch(`${o.replace(/\/$/,"")}/api/sootsim/billing/keys`,{headers:{authorization:`Bearer ${e}`}});n.ok||(console.error(` keys list failed (${n.status})`),process.exit(1));let{keys:r}=await n.json();if(r.length===0){console.log(" no keys. create one with `sootsim keys create <label>`.");return}for(let t of r)console.log(` ${t.keyPrefix}\u2026 ${t.label.padEnd(24)} scopes=${t.scopes.join(",")} last=${f(t.lastUsedAt)} id=${t.id}`);return}if(i==="create"){let o=s[1]?.trim();o||(console.error(" usage: sootsim keys create <label>"),process.exit(1));let{origin:e,token:n}=await a(),r=await fetch(`${e.replace(/\/$/,"")}/api/sootsim/billing/keys`,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({label:o})});r.ok||(console.error(` keys create failed (${r.status}): ${await r.text()}`),process.exit(1));let t=await r.json();console.log(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as l,b as d,c as k,d as y,e as g}from"./chunk-NWHQG4PG.js";import{d as c}from"./chunk-GW77VHPI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";async function a(){let s=await c();return s?.token||(process.stderr.write(" sootsim keys ... needs you to be signed in.\n run `sootsim login` first.\n"),process.exit(1)),{origin:s.origin,token:s.token}}function f(s){if(!s)return"never";try{return new Date(s).toLocaleString()}catch{return s}}async function h(s){let i=s[0];if(!i||i==="--help"||i==="-h"){u();return}if(i==="list"){let{origin:o,token:e}=await a(),n=await fetch(`${o.replace(/\/$/,"")}/api/sootsim/billing/keys`,{headers:{authorization:`Bearer ${e}`}});n.ok||(console.error(` keys list failed (${n.status})`),process.exit(1));let{keys:r}=await n.json();if(r.length===0){console.log(" no keys. create one with `sootsim keys create <label>`.");return}for(let t of r)console.log(` ${t.keyPrefix}\u2026 ${t.label.padEnd(24)} scopes=${t.scopes.join(",")} last=${f(t.lastUsedAt)} id=${t.id}`);return}if(i==="create"){let o=s[1]?.trim();o||(console.error(" usage: sootsim keys create <label>"),process.exit(1));let{origin:e,token:n}=await a(),r=await fetch(`${e.replace(/\/$/,"")}/api/sootsim/billing/keys`,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({label:o})});r.ok||(console.error(` keys create failed (${r.status}): ${await r.text()}`),process.exit(1));let t=await r.json();console.log(`
3
3
  created: ${t.record.label} (${t.record.keyPrefix}\u2026)`),console.log(` scopes: ${t.record.scopes.join(",")}`),console.log(`
4
4
  secret: ${t.secret}
5
5
  `),console.log(` copy this now \u2014 we can't show it again.
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-QAMASPCQ.js";import{b as m}from"./chunk-PB7AQQSR.js";import{a as u}from"./chunk-3NBPI3RK.js";import"./chunk-RVDEV2FN.js";import"./chunk-4XUOL4AD.js";import"./chunk-OPYA7ZEE.js";import{D as c,E as r,F as l,y as s,z as a}from"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.js";import{spawn as p}from"child_process";import{existsSync as h}from"fs";async function I(n){if(n.includes("--help")||n.includes("-h")){console.log(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-DAO2KA4O.js";import{b as m}from"./chunk-AUMMYIP5.js";import{a as u}from"./chunk-IKFKEII6.js";import"./chunk-CAFGDFEU.js";import"./chunk-EIKREDI4.js";import"./chunk-A3UFHDMY.js";import{D as c,E as r,F as l,y as s,z as a}from"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";import{spawn as p}from"child_process";import{existsSync as h}from"fs";async function I(n){if(n.includes("--help")||n.includes("-h")){console.log(`
3
3
  sootsim launch \u2014 one-shot: install runtime if needed, start daemon, open app
4
4
 
5
5
  usage:
@@ -13,4 +13,4 @@ options:
13
13
  examples:
14
14
  sootsim launch
15
15
  sootsim launch --version 1.2.3
16
- `);return}let e=n.includes("--no-runtime-install"),i=n.indexOf("--channel"),t=i>=0&&n[i+1]?n[i+1]:"stable",o=n.indexOf("--version"),f=o>=0&&n[o+1]?n[o+1]:void 0;s(),await v({skipAutoInstall:e,channel:t,explicitVersion:f}),await d(),await x()}async function v(n){let e=a(),i=c();if(e&&i)return;n.skipAutoInstall&&(console.error(" no sootsim runtime installed. run `sootsim runtime install` first, or drop --no-runtime-install."),process.exit(1)),console.log("sootsim: first run \u2014 installing runtime");let{runRuntime:t}=await import("./runtime-URJZQE3L.js"),o=[];n.explicitVersion&&o.push(n.explicitVersion),n.channel!=="stable"&&o.push("--channel",n.channel),await t(["install",...o],{channel:n.channel})}async function d(){let n=r();if(l(n))return;console.log("sootsim: starting daemon");let e=w();p(e,["server","--quiet"],{detached:!0,stdio:"ignore",env:process.env}).unref();let t=Date.now()+8e3;for(;Date.now()<t;){let o=r();if(l(o))return;await g(150)}console.error(" daemon didn't become ready within 8s \u2014 check ~/.sootsim/ or run `sootsim server` in a terminal to see errors"),process.exit(1)}async function x(){u()||(console.error(" no sootsim desktop companion installed. run `sootsim install-desktop` to download electron + the shell."),process.exit(1));let e=await m.launch({});e.launched||(console.error(` ${e.message}`),process.exit(1)),console.log(` ${e.message}`)}function w(){let n=process.argv[1];return n&&h(n)?n:"sootsim"}function g(n){return new Promise(e=>setTimeout(e,n))}async function R(){s(),await d()}export{R as ensureDaemonRunning,I as runLaunch};
16
+ `);return}let e=n.includes("--no-runtime-install"),i=n.indexOf("--channel"),t=i>=0&&n[i+1]?n[i+1]:"stable",o=n.indexOf("--version"),f=o>=0&&n[o+1]?n[o+1]:void 0;s(),await v({skipAutoInstall:e,channel:t,explicitVersion:f}),await d(),await x()}async function v(n){let e=a(),i=c();if(e&&i)return;n.skipAutoInstall&&(console.error(" no sootsim runtime installed. run `sootsim runtime install` first, or drop --no-runtime-install."),process.exit(1)),console.log("sootsim: first run \u2014 installing runtime");let{runRuntime:t}=await import("./runtime-L2E4XOOB.js"),o=[];n.explicitVersion&&o.push(n.explicitVersion),n.channel!=="stable"&&o.push("--channel",n.channel),await t(["install",...o],{channel:n.channel})}async function d(){let n=r();if(l(n))return;console.log("sootsim: starting daemon");let e=w();p(e,["server","--quiet"],{detached:!0,stdio:"ignore",env:process.env}).unref();let t=Date.now()+8e3;for(;Date.now()<t;){let o=r();if(l(o))return;await g(150)}console.error(" daemon didn't become ready within 8s \u2014 check ~/.sootsim/ or run `sootsim server` in a terminal to see errors"),process.exit(1)}async function x(){u()||(console.error(" no sootsim desktop companion installed. run `sootsim install-desktop` to download electron + the shell."),process.exit(1));let e=await m.launch({});e.launched||(console.error(` ${e.message}`),process.exit(1)),console.log(` ${e.message}`)}function w(){let n=process.argv[1];return n&&h(n)?n:"sootsim"}function g(n){return new Promise(e=>setTimeout(e,n))}async function R(){s(),await d()}export{R as ensureDaemonRunning,I as runLaunch};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{b as f,d as m}from"./chunk-FFLU7U2E.js";import"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.js";import{exec as S}from"node:child_process";import{randomBytes as $}from"node:crypto";import _ from"node:http";var I=process.env.SOOTSIM_AUTH_ORIGIN||"https://sootbean.com",h="http://localhost:3000";async function x(t){if(t)return t;if(process.env.SOOTSIM_AUTH_ORIGIN)return process.env.SOOTSIM_AUTH_ORIGIN;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{if((await fetch(`${h}/api/auth/me`)).ok)return h}catch{}return I}function R(){console.log(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{b as f,d as m}from"./chunk-GW77VHPI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";import{exec as S}from"node:child_process";import{randomBytes as $}from"node:crypto";import _ from"node:http";var I=process.env.SOOTSIM_AUTH_ORIGIN||"https://sootbean.com",h="http://localhost:3000";async function x(t){if(t)return t;if(process.env.SOOTSIM_AUTH_ORIGIN)return process.env.SOOTSIM_AUTH_ORIGIN;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{if((await fetch(`${h}/api/auth/me`)).ok)return h}catch{}return I}function R(){console.log(`
3
3
  sootsim login \u2014 sign in so desktop uploads can attach to your account
4
4
 
5
5
  usage:
@@ -21,6 +21,6 @@ options:
21
21
  <p style="color:#ccc">${t}</p>
22
22
  </div>
23
23
  </body>
24
- </html>`}async function P(t){try{let o=await fetch(`${t.replace(/\/$/,"")}/api/dev-login`,{method:"POST"});if(o.status===403)return{ok:!1,error:"dev-login disabled (not in dev mode)"};if(!o.ok){let c=await o.text().catch(()=>"");return{ok:!1,error:`dev-login ${o.status}: ${c}`}}let e=await o.json();return e.token?{ok:!0,token:e.token,userId:e.user?.id,email:e.email}:{ok:!1,error:"dev-login response missing token"}}catch(o){return{ok:!1,error:o instanceof Error?o.message:"dev-login fetch failed"}}}function A(t){try{let o=new URL(t).hostname;return o==="localhost"||o==="127.0.0.1"||o.endsWith(".local")}catch{return!1}}async function G(t){(t.includes("--help")||t.includes("-h"))&&(R(),process.exit(0));let o=[...t],e=await x(T(o,"--origin"));if(A(e)){console.log(` detected local origin (${e}) \u2014 signing in as dev user`);let r=await P(e);if(r.ok){f({token:r.token,user:r.userId?{id:r.userId,email:r.email}:null,origin:e,source:"cli"});let s=await m(e),l=s?.user?.email||r.email||s?.user?.id||r.userId,{trackCliEvent:n,flushCliTelemetry:a}=await import("./telemetry-HGTHILVR.js");n({event:"cli_login_succeeded",identity:{userId:r.userId??s?.user?.id??null},properties:{origin:e,mode:"dev"}}),await a(),console.log(` signed in${l?` as ${l}`:""} (dev)`);return}console.log(` dev-login not available (${r.error}); falling back to browser`)}let c=$(16).toString("hex"),i=await new Promise(r=>{let s=_.createServer((l,n)=>{try{let a=new URL(l.url||"/","http://127.0.0.1"),w=a.searchParams.get("state"),k=a.searchParams.get("token"),b=a.searchParams.get("email")||void 0,O=a.searchParams.get("userId")||void 0,g=a.searchParams.get("error");if(n.setHeader("content-type","text/html; charset=utf-8"),g){n.end(u(`sign-in failed: ${g}`)),r({ok:!1,error:g}),s.close();return}if(w!==c){n.end(u("state mismatch. close this tab and retry `sootsim login`.")),r({ok:!1,error:"state mismatch"}),s.close();return}if(!k){n.end(u("missing token. close this tab and retry `sootsim login`.")),r({ok:!1,error:"missing token"}),s.close();return}n.end(u("sign-in complete. you can return to the terminal.")),r({ok:!0,token:k,email:b,userId:O}),s.close()}catch(a){n.statusCode=500,n.end(u("sign-in callback failed. retry `sootsim login`.")),r({ok:!1,error:a instanceof Error?a.message:"callback failed"}),s.close()}});s.listen(0,"127.0.0.1",()=>{let l=s.address();if(!l||typeof l=="string"){r({ok:!1,error:"failed to bind callback server"}),s.close();return}let n=new URL(`${e.replace(/\/$/,"")}/auth/sootsim-cli`);n.searchParams.set("state",c),n.searchParams.set("port",String(l.port)),n.searchParams.set("sootbean",e),console.log(" opening browser for sootsim login..."),console.log(` waiting for callback on 127.0.0.1:${l.port}`),console.log(` if nothing opens, visit:
24
+ </html>`}async function P(t){try{let o=await fetch(`${t.replace(/\/$/,"")}/api/dev-login`,{method:"POST"});if(o.status===403)return{ok:!1,error:"dev-login disabled (not in dev mode)"};if(!o.ok){let c=await o.text().catch(()=>"");return{ok:!1,error:`dev-login ${o.status}: ${c}`}}let e=await o.json();return e.token?{ok:!0,token:e.token,userId:e.user?.id,email:e.email}:{ok:!1,error:"dev-login response missing token"}}catch(o){return{ok:!1,error:o instanceof Error?o.message:"dev-login fetch failed"}}}function A(t){try{let o=new URL(t).hostname;return o==="localhost"||o==="127.0.0.1"||o.endsWith(".local")}catch{return!1}}async function G(t){(t.includes("--help")||t.includes("-h"))&&(R(),process.exit(0));let o=[...t],e=await x(T(o,"--origin"));if(A(e)){console.log(` detected local origin (${e}) \u2014 signing in as dev user`);let r=await P(e);if(r.ok){f({token:r.token,user:r.userId?{id:r.userId,email:r.email}:null,origin:e,source:"cli"});let s=await m(e),l=s?.user?.email||r.email||s?.user?.id||r.userId,{trackCliEvent:n,flushCliTelemetry:a}=await import("./telemetry-6QW73WDZ.js");n({event:"cli_login_succeeded",identity:{userId:r.userId??s?.user?.id??null},properties:{origin:e,mode:"dev"}}),await a(),console.log(` signed in${l?` as ${l}`:""} (dev)`);return}console.log(` dev-login not available (${r.error}); falling back to browser`)}let c=$(16).toString("hex"),i=await new Promise(r=>{let s=_.createServer((l,n)=>{try{let a=new URL(l.url||"/","http://127.0.0.1"),w=a.searchParams.get("state"),k=a.searchParams.get("token"),b=a.searchParams.get("email")||void 0,O=a.searchParams.get("userId")||void 0,g=a.searchParams.get("error");if(n.setHeader("content-type","text/html; charset=utf-8"),g){n.end(u(`sign-in failed: ${g}`)),r({ok:!1,error:g}),s.close();return}if(w!==c){n.end(u("state mismatch. close this tab and retry `sootsim login`.")),r({ok:!1,error:"state mismatch"}),s.close();return}if(!k){n.end(u("missing token. close this tab and retry `sootsim login`.")),r({ok:!1,error:"missing token"}),s.close();return}n.end(u("sign-in complete. you can return to the terminal.")),r({ok:!0,token:k,email:b,userId:O}),s.close()}catch(a){n.statusCode=500,n.end(u("sign-in callback failed. retry `sootsim login`.")),r({ok:!1,error:a instanceof Error?a.message:"callback failed"}),s.close()}});s.listen(0,"127.0.0.1",()=>{let l=s.address();if(!l||typeof l=="string"){r({ok:!1,error:"failed to bind callback server"}),s.close();return}let n=new URL(`${e.replace(/\/$/,"")}/auth/sootsim-cli`);n.searchParams.set("state",c),n.searchParams.set("port",String(l.port)),n.searchParams.set("sootbean",e),console.log(" opening browser for sootsim login..."),console.log(` waiting for callback on 127.0.0.1:${l.port}`),console.log(` if nothing opens, visit:
25
25
  ${n.toString()}
26
- `),L(n.toString())})});if(!i.ok){let{trackCliEvent:r,flushCliTelemetry:s}=await import("./telemetry-HGTHILVR.js");r({event:"cli_login_failed",properties:{origin:e,error:i.error}}),await s(),console.error(` login failed: ${i.error}`),process.exit(1)}f({token:i.token,user:i.userId?{id:i.userId,email:i.email}:null,origin:e,source:"cli"});let d=await m(e),p=d?.user?.email||i.email||d?.user?.id||i.userId,{trackCliEvent:y,flushCliTelemetry:v}=await import("./telemetry-HGTHILVR.js");y({event:"cli_login_succeeded",identity:{userId:i.userId??d?.user?.id??null},properties:{origin:e}}),await v(),console.log(` signed in${p?` as ${p}`:""}`)}export{G as runLogin};
26
+ `),L(n.toString())})});if(!i.ok){let{trackCliEvent:r,flushCliTelemetry:s}=await import("./telemetry-6QW73WDZ.js");r({event:"cli_login_failed",properties:{origin:e,error:i.error}}),await s(),console.error(` login failed: ${i.error}`),process.exit(1)}f({token:i.token,user:i.userId?{id:i.userId,email:i.email}:null,origin:e,source:"cli"});let d=await m(e),p=d?.user?.email||i.email||d?.user?.id||i.userId,{trackCliEvent:y,flushCliTelemetry:v}=await import("./telemetry-6QW73WDZ.js");y({event:"cli_login_succeeded",identity:{userId:i.userId??d?.user?.id??null},properties:{origin:e}}),await v(),console.log(` signed in${p?` as ${p}`:""}`)}export{G as runLogin};
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as r,b as i}from"./chunk-FEAAP6XM.js";import{a as t,c as o}from"./chunk-FFLU7U2E.js";import"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.js";async function s(){let e=t();if(!e?.token){console.log(" not signed in");return}try{await fetch(`${e.origin.replace(/\/$/,"")}/api/auth/sign-out`,{method:"POST",headers:{authorization:`Bearer ${e.token}`}})}catch{}o(),r({event:"cli_logout",identity:{userId:e.user?.id??null},properties:{origin:e.origin}}),await i(),console.log(" signed out")}export{s as runLogout};
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as r,b as i}from"./chunk-VV265FEE.js";import{a as t,c as o}from"./chunk-GW77VHPI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";async function s(){let e=t();if(!e?.token){console.log(" not signed in");return}try{await fetch(`${e.origin.replace(/\/$/,"")}/api/auth/sign-out`,{method:"POST",headers:{authorization:`Bearer ${e.token}`}})}catch{}o(),r({event:"cli_logout",identity:{userId:e.user?.id??null},properties:{origin:e.origin}}),await i(),console.log(" signed out")}export{s as runLogout};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.61 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{b as h,c as w}from"./chunk-GU4C6XUG.js";import"./chunk-UZYGDMBM.js";import"./chunk-EFPFJZQG.js";import"./chunk-7IFCJ2IT.js";import"./chunk-EZDINY66.js";import"./chunk-FULJHRZT.js";import"./chunk-SDHFNWW6.js";import"./chunk-K23PH2GT.js";import"./chunk-7U5X273C.js";import"./chunk-UXECVWRC.js";import"./chunk-7O43QYRW.js";import"./chunk-O4GFKP3K.js";import"./chunk-PB7AQQSR.js";import"./chunk-3NBPI3RK.js";import"./chunk-RVDEV2FN.js";import"./chunk-4XUOL4AD.js";import"./chunk-OPYA7ZEE.js";import"./chunk-5HIFH66T.js";import"./chunk-6AJED4HB.js";import"./chunk-FEAAP6XM.js";import"./chunk-FFLU7U2E.js";import"./chunk-D7ELOJUV.js";import"./chunk-OXK76D2Y.js";import"./chunk-CJTUKYTH.js";import"./chunk-SBJZMEWR.js";import"./chunk-4ZZ2FEXT.js";import"./chunk-CQVJMAK7.js";import"./chunk-U35XNNJY.js";import*as i from"fs";import*as l from"path";var v=[".maestro","maestro"];function x(){console.log(`
1
+ /*! sootsim v0.1.63 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{b as h,c as w}from"./chunk-KX3FO4N4.js";import"./chunk-FEZCATWN.js";import"./chunk-SOKY5FGT.js";import"./chunk-MTTIJQ64.js";import"./chunk-7RZWW5VK.js";import"./chunk-NWHQG4PG.js";import"./chunk-5OZ7M24R.js";import"./chunk-GICJIXEH.js";import"./chunk-C6UT7L2J.js";import"./chunk-PY25FDGX.js";import"./chunk-B3644N6L.js";import"./chunk-AMZB6WUA.js";import"./chunk-AUMMYIP5.js";import"./chunk-IKFKEII6.js";import"./chunk-CAFGDFEU.js";import"./chunk-EIKREDI4.js";import"./chunk-A3UFHDMY.js";import"./chunk-ENACZPKI.js";import"./chunk-WCMYVXHS.js";import"./chunk-VV265FEE.js";import"./chunk-GW77VHPI.js";import"./chunk-KRRNCL56.js";import"./chunk-AYJGGZA4.js";import"./chunk-4OW4EPBS.js";import"./chunk-SSTMIACF.js";import"./chunk-U42HSSAI.js";import"./chunk-QW6P2JE2.js";import"./chunk-INXMOS35.js";import*as i from"fs";import*as l from"path";var v=[".maestro","maestro"];function x(){console.log(`
3
3
  sootsim maestro \u2014 run maestro YAML flows against sootsim (drop-in)
4
4
 
5
5
  usage: