sootsim 0.0.1 → 0.0.2

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 (122) hide show
  1. package/README.md +12 -0
  2. package/dist-cli/bin.js +16 -10
  3. package/dist-cli/chunks/agent-3T4BJEZM.js +61 -0
  4. package/dist-cli/chunks/agent-wrapper-WCYNLWHZ.js +15 -0
  5. package/dist-cli/chunks/assert-FPFJEFF3.js +47 -0
  6. package/dist-cli/chunks/auto-bootstrap-HDW6N77H.js +2 -0
  7. package/dist-cli/chunks/chunk-3HBBSRLE.js +2 -0
  8. package/dist-cli/chunks/chunk-4372UQHZ.js +308 -0
  9. package/dist-cli/chunks/chunk-4GWEO5CL.js +1 -0
  10. package/dist-cli/chunks/{chunk-G5MR66EB.js → chunk-5C5I5OFM.js} +2 -2
  11. package/dist-cli/chunks/chunk-6IPY24VM.js +11 -0
  12. package/dist-cli/chunks/chunk-AS4V7TZU.js +2 -0
  13. package/dist-cli/chunks/chunk-B5R4K2DG.js +5 -0
  14. package/dist-cli/chunks/chunk-CXTA5VGA.js +4 -0
  15. package/dist-cli/chunks/chunk-CZZB4DWG.js +3 -0
  16. package/dist-cli/chunks/chunk-DW54UPRZ.js +119 -0
  17. package/dist-cli/chunks/chunk-EIZCWDRE.js +1 -0
  18. package/dist-cli/chunks/{chunk-KSACMDXK.js → chunk-ET3NNZAR.js} +2 -2
  19. package/dist-cli/chunks/chunk-EWEKADK4.js +5 -0
  20. package/dist-cli/chunks/{chunk-JSF5LPNT.js → chunk-EWMYTXM2.js} +5 -5
  21. package/dist-cli/chunks/chunk-FUQ4XA6I.js +16 -0
  22. package/dist-cli/chunks/chunk-GQUOQNTP.js +27 -0
  23. package/dist-cli/chunks/chunk-HBNVKYSC.js +2 -0
  24. package/dist-cli/chunks/{chunk-64TOMNZX.js → chunk-HORCHQT7.js} +2 -2
  25. package/dist-cli/chunks/{chunk-YCETS3B3.js → chunk-ISAMAM3I.js} +2 -2
  26. package/dist-cli/chunks/{chunk-GPVPHE2B.js → chunk-K6YUSCAC.js} +2 -2
  27. package/dist-cli/chunks/{chunk-E522F5JW.js → chunk-K7LDP7JL.js} +1 -1
  28. package/dist-cli/chunks/chunk-KZ2LIDW6.js +2 -0
  29. package/dist-cli/chunks/{chunk-J2S3OCWA.js → chunk-LOV766MI.js} +1 -1
  30. package/dist-cli/chunks/{chunk-OROM7DZI.js → chunk-LXCFGKL2.js} +1 -1
  31. package/dist-cli/chunks/{chunk-PWXPA745.js → chunk-NE62JSI6.js} +1 -1
  32. package/dist-cli/chunks/chunk-NHA3G6A3.js +22 -0
  33. package/dist-cli/chunks/chunk-NXWCDGWS.js +2 -0
  34. package/dist-cli/chunks/{chunk-QOBRRY5X.js → chunk-RJUBGX5M.js} +1 -1
  35. package/dist-cli/chunks/chunk-SLCVEGTW.js +4 -0
  36. package/dist-cli/chunks/chunk-TGDP3D3V.js +34 -0
  37. package/dist-cli/chunks/chunk-TSZBQS6W.js +62 -0
  38. package/dist-cli/chunks/chunk-XKDQEYTE.js +1 -0
  39. package/dist-cli/chunks/chunk-XXUAOYYT.js +4 -0
  40. package/dist-cli/chunks/{chunk-7X6OPSRD.js → chunk-YVSZHVLU.js} +2 -2
  41. package/dist-cli/chunks/{compat-MRN2ORY5.js → compat-3HMKLGXL.js} +4 -4
  42. package/dist-cli/chunks/{config-CO5IYWUY.js → config-IJQ3KANN.js} +5 -5
  43. package/dist-cli/chunks/control-3RAFI4AW.js +2 -0
  44. package/dist-cli/chunks/{daemon-G4XVRFHM.js → daemon-BBEQJLRY.js} +2 -2
  45. package/dist-cli/chunks/{debug-ZNSZTWT6.js → debug-SGZ5ZFQI.js} +4 -4
  46. package/dist-cli/chunks/demo-app-registry-NCYP3WA6.js +2 -0
  47. package/dist-cli/chunks/{detox-JEGYNTYV.js → detox-PK74V2Y7.js} +2 -2
  48. package/dist-cli/chunks/{device-BS34FAFM.js → device-MWNFX54L.js} +2 -2
  49. package/dist-cli/chunks/drivers-EXUREU4B.js +2 -0
  50. package/dist-cli/chunks/electron-3NIHSU2K.js +15 -0
  51. package/dist-cli/chunks/flow-6Y3E6E5P.js +2 -0
  52. package/dist-cli/chunks/{hints-7Z656W4H.js → hints-XZJLBIXW.js} +2 -2
  53. package/dist-cli/chunks/home-paths-BNRMUBJA.js +2 -0
  54. package/dist-cli/chunks/{inspect-NAHXP2M5.js → inspect-FGTUAK4C.js} +153 -165
  55. package/dist-cli/chunks/install-LCXALH26.js +65 -0
  56. package/dist-cli/chunks/{install-desktop-PYIZIH67.js → install-desktop-U3RQ6XUX.js} +8 -4
  57. package/dist-cli/chunks/install-dev-desktop-BLKRFI42.js +100 -0
  58. package/dist-cli/chunks/keys-N5LBDSD5.js +19 -0
  59. package/dist-cli/chunks/launch-NIMSJH5I.js +16 -0
  60. package/dist-cli/chunks/{login-Z5Z54HUJ.js → login-CQV2XBRM.js} +5 -5
  61. package/dist-cli/chunks/{logout-T2QDYGCB.js → logout-R56NWAWQ.js} +2 -2
  62. package/dist-cli/chunks/{maestro-4AXTS7OE.js → maestro-ZYUVTM7H.js} +2 -2
  63. package/dist-cli/chunks/{preview-NMGWHWMX.js → preview-AOAWAYEQ.js} +2 -2
  64. package/dist-cli/chunks/{profile-6RGJA4FR.js → profile-DDADDPRW.js} +3 -3
  65. package/dist-cli/chunks/record-3OIOTHP6.js +37 -0
  66. package/dist-cli/chunks/runtime-JTLZYEXK.js +25 -0
  67. package/dist-cli/chunks/{screenshot-R3GCCSCI.js → screenshot-Q6N2V5LL.js} +3 -3
  68. package/dist-cli/chunks/screenshot-mode-WWLWJWQD.js +17 -0
  69. package/dist-cli/chunks/{screenshots-4UQJE4NC.js → screenshots-2JEPJGZO.js} +2 -2
  70. package/dist-cli/chunks/server-VH34RVAX.js +29 -0
  71. package/dist-cli/chunks/{skills-2PPKPL4B.js → skills-PU4627FY.js} +2 -2
  72. package/dist-cli/chunks/store-U2VDD2S4.js +2 -0
  73. package/dist-cli/chunks/{test-5LFKOQ4M.js → test-AECE56E7.js} +3 -3
  74. package/dist-cli/chunks/upload-KPP7KG6E.js +2 -0
  75. package/dist-cli/chunks/{whoami-H6FW34JS.js → whoami-NCGRRR7X.js} +2 -2
  76. package/dist-lib/agent-daemon-client.cjs +414 -0
  77. package/dist-lib/agent-events.cjs +48 -0
  78. package/dist-lib/agent-sessions.cjs +692 -0
  79. package/dist-lib/attached-projects.cjs +448 -0
  80. package/dist-lib/auth/shared-session.cjs +174 -0
  81. package/dist-lib/backend-origin.cjs +70 -0
  82. package/dist-lib/bridge-constants.cjs +32 -0
  83. package/dist-lib/cli-constants.cjs +32 -0
  84. package/dist-lib/config.cjs +88 -0
  85. package/dist-lib/dev-bundle-resolution.cjs +236 -0
  86. package/dist-lib/home-paths.cjs +234 -0
  87. package/dist-lib/host/bridge-host.cjs +3458 -0
  88. package/dist-lib/index.cjs +361 -0
  89. package/dist-lib/metro.cjs +215 -0
  90. package/dist-lib/render-mode.cjs +54 -0
  91. package/dist-lib/vite-base.cjs +4217 -0
  92. package/dist-lib/vite.cjs +178 -0
  93. package/package.json +80 -13
  94. package/scripts/postinstall.cjs +70 -0
  95. package/dist-cli/chunks/bridge-host-2EY7Z4AO.js +0 -2
  96. package/dist-cli/chunks/chunk-3C3ZH7PP.js +0 -4
  97. package/dist-cli/chunks/chunk-3R4ZZESY.js +0 -119
  98. package/dist-cli/chunks/chunk-74XPLOV4.js +0 -2
  99. package/dist-cli/chunks/chunk-7LMDCMSI.js +0 -8
  100. package/dist-cli/chunks/chunk-A2CZQIWO.js +0 -1
  101. package/dist-cli/chunks/chunk-CKZ376AY.js +0 -322
  102. package/dist-cli/chunks/chunk-E5UBZEYR.js +0 -2
  103. package/dist-cli/chunks/chunk-HOIHCO7S.js +0 -3
  104. package/dist-cli/chunks/chunk-KQWZZ56P.js +0 -2
  105. package/dist-cli/chunks/chunk-KSB6MSZ4.js +0 -34
  106. package/dist-cli/chunks/chunk-KXYKAYYB.js +0 -51
  107. package/dist-cli/chunks/chunk-MBFP2LVH.js +0 -3
  108. package/dist-cli/chunks/chunk-MPSZ5EWF.js +0 -16
  109. package/dist-cli/chunks/chunk-X2U72K7X.js +0 -1
  110. package/dist-cli/chunks/control-Y7TKKB6D.js +0 -2
  111. package/dist-cli/chunks/dev-ZUKCZQEX.js +0 -25
  112. package/dist-cli/chunks/dev-checkout-IEZVVTCN.js +0 -2
  113. package/dist-cli/chunks/drivers-46PFFIDF.js +0 -2
  114. package/dist-cli/chunks/electron-P2KOPX2S.js +0 -15
  115. package/dist-cli/chunks/flow-VVOF6UNC.js +0 -2
  116. package/dist-cli/chunks/install-EPUJX4AT.js +0 -67
  117. package/dist-cli/chunks/record-IE27Z2GA.js +0 -37
  118. package/dist-cli/chunks/screenshot-mode-SZQDNGYE.js +0 -17
  119. package/dist-cli/chunks/server-AN2G5KO4.js +0 -21
  120. package/dist-cli/chunks/store-PU5ES4YQ.js +0 -2
  121. package/dist-cli/chunks/upload-BYNPC54C.js +0 -2
  122. package/dist-cli/chunks/vite-plugin-5AEUUBKP.js +0 -9
@@ -1,6 +1,6 @@
1
- /*! sootsim v0.0.1 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3OCWA.js";import{a as z,b as B,c as q,d as K,e as re,f as X,g as Q,h as Me,i as Ne,j as ue}from"./chunk-64TOMNZX.js";import{a as be,e as ne}from"./chunk-JSF5LPNT.js";import{a as ce,c as de,d as he}from"./chunk-3R4ZZESY.js";import{f as _e}from"./chunk-HOIHCO7S.js";import{a as we}from"./chunk-KSB6MSZ4.js";import"./chunk-OROM7DZI.js";import{b as ve,d as ke,e as Se,g as Te}from"./chunk-MPSZ5EWF.js";import"./chunk-3C3ZH7PP.js";import{a as ye}from"./chunk-E5UBZEYR.js";import"./chunk-X2U72K7X.js";import"./chunk-74XPLOV4.js";import"./chunk-MBFP2LVH.js";import"./chunk-E522F5JW.js";import{existsSync as it,mkdirSync as lt,readFileSync as ct,rmSync as Ie,writeFileSync as dt}from"fs";import{tmpdir as ut}from"os";import{dirname as mt,join as pt,resolve as ft}from"path";var ee=1,gt="SOOTSIM_INSPECT_NOTICE_PATH",yt=300*1e3,ht=15e3;function Fe(){return ft(process.env[gt]||pt(ut(),"sootsim-inspect-notice-state.json"))}function bt(s,c){return Object.fromEntries(Object.entries(s).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&c-i.updatedAt<=yt))}function wt(s){let c=Fe();if(!it(c))return{version:ee,entries:{}};try{let i=JSON.parse(ct(c,"utf8"));return i.version!==ee||!i.entries||typeof i.entries!="object"?(Ie(c,{force:!0}),{version:ee,entries:{}}):{version:ee,entries:bt(i.entries,s)}}catch{return Ie(c,{force:!0}),{version:ee,entries:{}}}}function xt(s){let c=Fe();lt(mt(c),{recursive:!0}),dt(c,JSON.stringify(s,null,2)+`
3
- `)}function $t(s,c){let i=c.trim()||"default";return`${s}:${i}`}function me(s,c,i,d={}){let y=d.nowMs??Date.now(),a=d.cooldownMs??ht,h=wt(y),S=$t(s,c),x=h.entries[S];return x&&x.signature===i&&y-x.updatedAt<a?!1:(h.entries[S]={signature:i,updatedAt:y},xt(h),!0)}async function Ae(s,c={args:[]}){let i=await s.send({type:"evaluate",code:"(async () => await window.__sootsimTest.getNodeCount())()"}),d=typeof i=="number"?i:0;if(B(c.args)){q({nodes:d});return}console.log(` nodes: ${d}`)}function pe(s,c){let i=s.indexOf(c);return i>=0&&i+1<s.length?s[i+1]:null}async function Pe(s){let{bridge:c,args:i,positional:d}=s,y=i.includes("--verbose")||i.includes("-v"),a=B(i),h=y&&!a,S=i.includes("--watch")||i.includes("-w"),x=1e3,T=i.includes("--compact"),f=i.includes("--no-xy"),v=pe(i,"--testid-like"),_=pe(i,"--only"),k=pe(i,"--subtree"),C=d[1],l=C?/[*?]/.test(C):!1,E=!l&&!_?C:void 0,R=_??(l?C:void 0),H=async()=>{await re(c,{verbose:h});let V=`(async () => {
1
+ /*! sootsim v0.0.2 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as U}from"./chunk-K6YUSCAC.js";import{a as Ne,b as _e}from"./chunk-LOV766MI.js";import{a as Y,b as E,c as C,d as z,e as ie,f as V,g as te,h as Ie,i as Fe,j as fe}from"./chunk-HORCHQT7.js";import{a as Te,e as ae}from"./chunk-EWMYTXM2.js";import{a as me,c as pe,d as xe}from"./chunk-DW54UPRZ.js";import{g as Ae}from"./chunk-6IPY24VM.js";import"./chunk-AS4V7TZU.js";import{a as Me}from"./chunk-TGDP3D3V.js";import"./chunk-LXCFGKL2.js";import{a as we}from"./chunk-3HBBSRLE.js";import{c as $e,e as Se,f as ke,h as ve}from"./chunk-FUQ4XA6I.js";import"./chunk-XXUAOYYT.js";import"./chunk-EIZCWDRE.js";import"./chunk-CXTA5VGA.js";import"./chunk-YVSZHVLU.js";import"./chunk-B5R4K2DG.js";import"./chunk-K7LDP7JL.js";import{existsSync as ut,mkdirSync as mt,readFileSync as pt,rmSync as Pe,writeFileSync as ft}from"fs";import{tmpdir as gt}from"os";import{dirname as yt,join as bt,resolve as ht}from"path";var oe=1,wt="SOOTSIM_INSPECT_NOTICE_PATH",xt=300*1e3,$t=15e3;function Oe(){return ht(process.env[wt]||bt(gt(),"sootsim-inspect-notice-state.json"))}function St(o,c){return Object.fromEntries(Object.entries(o).filter(([,i])=>typeof i?.signature=="string"&&Number.isFinite(i?.updatedAt)&&c-i.updatedAt<=xt))}function kt(o){let c=Oe();if(!ut(c))return{version:oe,entries:{}};try{let i=JSON.parse(pt(c,"utf8"));return i.version!==oe||!i.entries||typeof i.entries!="object"?(Pe(c,{force:!0}),{version:oe,entries:{}}):{version:oe,entries:St(i.entries,o)}}catch{return Pe(c,{force:!0}),{version:oe,entries:{}}}}function vt(o){let c=Oe();mt(yt(c),{recursive:!0}),ft(c,JSON.stringify(o,null,2)+`
3
+ `)}function Tt(o,c){let i=c.trim()||"default";return`${o}:${i}`}function ge(o,c,i,d={}){let u=d.nowMs??Date.now(),a=d.cooldownMs??$t,b=kt(u),k=Tt(o,c),$=b.entries[k];return $&&$.signature===i&&u-$.updatedAt<a?!1:(b.entries[k]={signature:i,updatedAt:u},vt(b),!0)}async function Ee(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"(async () => await window.__sootsimTest.getNodeCount())()"}),d=typeof i=="number"?i:0;if(E(c.args)){C({nodes:d});return}console.log(` nodes: ${d}`)}function ye(o,c){let i=o.indexOf(c);return i>=0&&i+1<o.length?o[i+1]:null}async function Re(o){let{bridge:c,args:i,positional:d}=o,u=i.includes("--verbose")||i.includes("-v"),a=E(i),b=u&&!a,k=i.includes("--watch")||i.includes("-w"),$=1e3,I=i.includes("--compact"),y=i.includes("--no-xy"),S=ye(i,"--testid-like"),A=ye(i,"--only"),v=ye(i,"--subtree"),j=d[1],l=j?/[*?]/.test(j):!1,R=!l&&!A?j:void 0,D=A??(l?j:void 0),q=async()=>{await ie(c,{verbose:b});let Z=`(async () => {
4
4
  const t = window.__sootsimTest
5
5
  const mainShell = window.SootSim?.bridges?.mainShell
6
6
  const kb = window.__sootsimKeyboard
@@ -11,33 +11,48 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
11
11
  shell = typeof mainShell?.getState === 'function' ? await mainShell.getState() : null
12
12
  } catch {}
13
13
 
14
- const tree = await t.dumpTree(12, ${JSON.stringify({describe:!0,verbose:y,filter:E||"",testIdLike:v||void 0,onlyGlob:R||void 0,subtreeRoot:k||void 0,compact:T,hideXy:f})})
14
+ const tree = await t.dumpTree(12, ${JSON.stringify({describe:!0,verbose:u,filter:R||"",testIdLike:S||void 0,onlyGlob:D||void 0,subtreeRoot:v||void 0,compact:I,hideXy:y})})
15
15
  const nodeCount = (await t.getNodeCount?.()) || 0
16
16
  const keyboard = kb && typeof kb.getLayout === 'function' ? kb.getLayout() : null
17
17
  return { tree, shell, nodeCount, keyboard }
18
- })()`,$=await c.send({type:"evaluate",code:V}),j=$?.tree,J=$?.shell,U=$?.keyboard;if(a){q({shell:J,tree:j??"",keyboard:U});return}if(J&&typeof J=="object"){let e=[J.state?`state=${J.state}`:null,J.activeApp?`app=${J.activeApp}`:null,J.showSwitcher?"switcher":null,J.switcherPhase&&J.switcherPhase!=="idle"?`phase=${J.switcherPhase}`:null].filter(Boolean);e.length>0&&console.log(` shell: ${e.join(" ")}`)}if(typeof j=="string"&&j.startsWith("__SUBTREE_NOT_FOUND__:")){let e=j.slice(22);console.log(` subtree root not found: ${e}`),Y("subtree-root-not-found",e);return}if(!j){let e=$?.nodeCount??0;console.log(" no matching nodes found"),!(E||v||R||k)&&e<10&&Y("app-still-loading",e);return}if(console.log(j),!(E||v||R||k)&&!S&&j.split(`
19
- `).length>=80&&Y("describe-use-filters"),U&&U.visible){let e=U.spec,t=[e?.keyboardType?`type=${e.keyboardType}`:null,e?.returnKeyType&&e.returnKeyType!=="default"?`return=${e.returnKeyType}`:null,U.mode!=="letters"?`mode=${U.mode}`:null,U.shifted?"shift":null,U.capsLock?"caps":null,e?.autoCapitalize&&e.autoCapitalize!=="sentences"?`autoCap=${e.autoCapitalize}`:null,U.accessoryBarId?`accessory=${U.accessoryBarId}`:null].filter(Boolean);console.log(`
20
- keyboard: ${t.join(" ")||"visible"}`)}};if(S)for(console.log(` watching... (Ctrl+C to stop)
21
- `);;)console.clear(),await H(),await z(x);else await H()}var vt=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function Oe(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let s of vt){let c=process.env[s];if(c&&c.trim()&&c!=="0")return!0}return!1}async function Ee(s){let{bridge:c,args:i,effectiveArgs:d,positional:y,inspectUsage:a}=s,h=$=>{let j=d.indexOf($);return j>=0&&j+1<d.length?d[j+1]:null},S=$=>d.includes($),x=h("--testid")||h("--test-id"),T=h("--role"),f=h("--type"),v=h("--text"),_=S("--pressable"),k=S("--visible"),C=!x&&!T&&!f&&!v&&!_&&!k?y[1]:null,l=v??C,E,R;x?(R="testid",E=`(async () => {
18
+ })()`,x=await c.send({type:"evaluate",code:Z}),J=x?.tree,H=x?.shell,K=x?.keyboard;if(a){C({shell:H,tree:J??"",keyboard:K});return}if(H&&typeof H=="object"){let e=[H.state?`state=${H.state}`:null,H.activeApp?`app=${H.activeApp}`:null,H.showSwitcher?"switcher":null,H.switcherPhase&&H.switcherPhase!=="idle"?`phase=${H.switcherPhase}`:null].filter(Boolean);e.length>0&&console.log(` shell: ${e.join(" ")}`)}if(typeof J=="string"&&J.startsWith("__SUBTREE_NOT_FOUND__:")){let e=J.slice(22);console.log(` subtree root not found: ${e}`),U("subtree-root-not-found",e);return}if(!J){let e=x?.nodeCount??0;console.log(" no matching nodes found"),!(R||S||D||v)&&e<10&&U("app-still-loading",e);return}if(console.log(J),!(R||S||D||v)&&!k&&J.split(`
19
+ `).length>=80&&U("describe-use-filters"),K&&K.visible){let e=K.spec,t=[e?.keyboardType?`type=${e.keyboardType}`:null,e?.returnKeyType&&e.returnKeyType!=="default"?`return=${e.returnKeyType}`:null,K.mode!=="letters"?`mode=${K.mode}`:null,K.shifted?"shift":null,K.capsLock?"caps":null,e?.autoCapitalize&&e.autoCapitalize!=="sentences"?`autoCap=${e.autoCapitalize}`:null,K.accessoryBarId?`accessory=${K.accessoryBarId}`:null].filter(Boolean);console.log(`
20
+ keyboard: ${t.join(" ")||"visible"}`)}};if(k)for(console.log(` watching... (Ctrl+C to stop)
21
+ `);;)console.clear(),await q(),await Y($);else await q()}var Mt=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function Ce(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let o of Mt){let c=process.env[o];if(c&&c.trim()&&c!=="0")return!0}return!1}async function Be(o){let{bridge:c,args:i,effectiveArgs:d,positional:u,inspectUsage:a}=o,b=x=>{let J=d.indexOf(x);return J>=0&&J+1<d.length?d[J+1]:null},k=x=>d.includes(x),$=b("--testid")||b("--test-id"),I=b("--role"),y=b("--type"),S=b("--text"),A=k("--pressable"),v=k("--visible"),j=!$&&!I&&!y&&!S&&!A&&!v?u[1]:null,l=S??j,R,D;$?(D="testid",R=`(async () => {
22
22
  const t = window.__sootsimTest
23
- return (await t.findByTestId(${JSON.stringify(x)})) || (await t.findById(${JSON.stringify(x)}))
24
- })()`):T?(R="role",E=`(async () => await window.__sootsimTest.queryAll({ hasRole: ${JSON.stringify(T)}, pruneHidden: true }))()`):f?(R="type",E=`(async () => await window.__sootsimTest.queryAll({ type: ${JSON.stringify(f)}, pruneHidden: true }))()`):_?(R="pressable",E=`(async () => {
23
+ return (await t.findByTestId(${JSON.stringify($)})) || (await t.findById(${JSON.stringify($)}))
24
+ })()`):I?(D="role",R=`(async () => await window.__sootsimTest.queryAll({ hasRole: ${JSON.stringify(I)}, pruneHidden: true }))()`):y?(D="type",R=`(async () => await window.__sootsimTest.queryAll({ type: ${JSON.stringify(y)}, pruneHidden: true }))()`):A?(D="pressable",R=`(async () => {
25
25
  const t = window.__sootsimTest
26
26
  const all = await t.queryAll({ pruneHidden: true })
27
27
  return all.filter(n => n.pressable)
28
- })()`):k?(R="visible",E=`(async () => {
28
+ })()`):v?(D="visible",R=`(async () => {
29
29
  const all = await window.__sootsimTest.queryAll({ pruneHidden: true })
30
30
  return all.filter(n => n.layout && n.layout.width > 0 && n.layout.height > 0)
31
- })()`):l?(R="text",E=`(async () => await window.__sootsimTest.findByText(${JSON.stringify(l)}))()`):(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible")),process.exit(1));let H=await c.send({type:"evaluate",code:E}),oe=B(i),V=i.includes("--verbose")||i.includes("--dump");if(oe)q(H??null);else if(Array.isArray(H))if(H.length===0){console.log(` no ${R} nodes found`);let $=await c.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof $=="number"&&$<10&&Y("app-still-loading",$)}else{console.log(` found ${H.length} node${H.length===1?"":"s"} (${R}):`);for(let $ of H.slice(0,20)){let j=$.absolutePosition?`@(${Math.round($.absolutePosition.x)},${Math.round($.absolutePosition.y)})`:"",J=$.layout?`${Math.round($.layout.width)}x${Math.round($.layout.height)}`:"?x?",U=$.text?` "${$.text.slice(0,30)}"`:"",Z=$.testID?` #${$.testID}`:"",e=$.pressable?" (tap)":"",t=$.accessibilityRole?`[${$.accessibilityRole}]`:$.type;console.log(` ${t}${U}${Z} ${J} ${j}${e}`),V&&console.log(Ce(JSON.stringify($,null,2)," "))}H.length>20&&console.log(` ... and ${H.length-20} more`)}else if(H==null)console.log(` not found: ${l||x||T||f||""||R}`),x&&Y("wait-selector-for-missing-testid",x);else{let $=H;if($.type&&$.absolutePosition){let j=`@(${Math.round($.absolutePosition.x)},${Math.round($.absolutePosition.y)})`,J=$.layout?`${Math.round($.layout.width)}x${Math.round($.layout.height)}`:"?x?",U=$.text?` "${$.text.slice(0,40)}"`:"",Z=$.testID?` #${$.testID}`:"",e=$.pressable?" (tap)":"",t=$.accessibilityRole?`[${$.accessibilityRole}]`:$.type;console.log(` ${t}${U}${Z} ${J} ${j}${e}`),V&&console.log(Ce(JSON.stringify($,null,2)," "))}else console.log(JSON.stringify(H,null,2))}}function Ce(s,c){return s.split(`
31
+ })()`):l?(D="text",R=`(async () => await window.__sootsimTest.findByText(${JSON.stringify(l)}))()`):(console.error(a("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible")),process.exit(1));let q=await c.send({type:"evaluate",code:R}),ne=E(i),Z=i.includes("--verbose")||i.includes("--dump");if(ne)C(q??null);else if(Array.isArray(q))if(q.length===0){console.log(` no ${D} nodes found`);let x=await c.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof x=="number"&&x<10&&U("app-still-loading",x)}else{console.log(` found ${q.length} node${q.length===1?"":"s"} (${D}):`);for(let x of q.slice(0,20)){let J=x.absolutePosition?`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`:"",H=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",K=x.text?` "${x.text.slice(0,30)}"`:"",Q=x.testID?` #${x.testID}`:"",e=x.pressable?" (tap)":"",t=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${t}${K}${Q} ${H} ${J}${e}`),Z&&console.log(De(JSON.stringify(x,null,2)," "))}q.length>20&&console.log(` ... and ${q.length-20} more`)}else if(q==null)console.log(` not found: ${l||$||I||y||""||D}`),$&&U("wait-selector-for-missing-testid",$);else{let x=q;if(x.type&&x.absolutePosition){let J=`@(${Math.round(x.absolutePosition.x)},${Math.round(x.absolutePosition.y)})`,H=x.layout?`${Math.round(x.layout.width)}x${Math.round(x.layout.height)}`:"?x?",K=x.text?` "${x.text.slice(0,40)}"`:"",Q=x.testID?` #${x.testID}`:"",e=x.pressable?" (tap)":"",t=x.accessibilityRole?`[${x.accessibilityRole}]`:x.type;console.log(` ${t}${K}${Q} ${H} ${J}${e}`),Z&&console.log(De(JSON.stringify(x,null,2)," "))}else console.log(JSON.stringify(q,null,2))}}function De(o,c){return o.split(`
32
32
  `).map(i=>c+i).join(`
33
- `)}async function Re(s,c={}){let i=await s.send({type:"evaluate",code:`(() => {
33
+ `)}async function Le(o,c={}){let i=await o.send({type:"evaluate",code:`(() => {
34
34
  const kb = window.__sootsimKeyboard
35
35
  if (!kb || typeof kb.getLayout !== 'function') {
36
36
  return { error: 'keyboard bridge getLayout() not available' }
37
37
  }
38
38
  return kb.getLayout()
39
- })()`});if("error"in i&&(console.error(i.error),process.exit(1)),c.json){console.log(JSON.stringify(i,null,2));return}let{visible:d,spec:y,mode:a,shifted:h,capsLock:S,accessoryBarId:x}=i,T=[];T.push(`keyboard: ${d?"visible":"hidden"}`),y?(T.push(` type: ${y.keyboardType}`),T.push(` returnKey: ${y.returnKeyType}`),T.push(` autoCap: ${y.autoCapitalize}`),T.push(` autoCorrect: ${y.autoCorrect?"on":"off"}`),T.push(` appearance: ${y.keyboardAppearance}`),y.secureTextEntry&&T.push(" secureTextEntry: true"),y.enablesReturnKeyAutomatically&&T.push(` return: ${y.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):T.push(" spec: <none> (shown via dev-tools with no TextInput)"),T.push(` mode: ${a}${h?" (shifted)":""}${S?" (caps)":""}`),x&&T.push(` accessoryBar: ${x}`),console.log(T.join(`
40
- `))}async function De(s){let c=await s.bridge.listBrowsers();if(B(s.args)){q(c.map(i=>({...i,active:i.id===s.browserId})));return}_e(c,s.browserId)}function te(s){let c=s.indexOf("--testid");if(c>=0&&s[c+1])return{mode:"testid",value:s[c+1]};let i=s.indexOf("--test-id");if(i>=0&&s[i+1])return{mode:"testid",value:s[i+1]};let d=s.indexOf("--text");return d>=0&&s[d+1]?{mode:"text",value:s[d+1]}:null}async function ae(s,c){let i=JSON.stringify(c.value),d=c.mode==="testid"?`(await t.findByTestId(${i})) || (await t.findById(${i}))`:`await t.findByText(${i})`;return await s.send({type:"evaluate",code:`(async () => {
39
+ })()`});if("error"in i&&(console.error(i.error),process.exit(1)),c.json){console.log(JSON.stringify(i,null,2));return}let{visible:d,spec:u,mode:a,shifted:b,capsLock:k,accessoryBarId:$}=i,I=[];I.push(`keyboard: ${d?"visible":"hidden"}`),u?(I.push(` type: ${u.keyboardType}`),I.push(` returnKey: ${u.returnKeyType}`),I.push(` autoCap: ${u.autoCapitalize}`),I.push(` autoCorrect: ${u.autoCorrect?"on":"off"}`),I.push(` appearance: ${u.keyboardAppearance}`),u.secureTextEntry&&I.push(" secureTextEntry: true"),u.enablesReturnKeyAutomatically&&I.push(` return: ${u.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):I.push(" spec: <none> (shown via dev-tools with no TextInput)"),I.push(` mode: ${a}${b?" (shifted)":""}${k?" (caps)":""}`),$&&I.push(` accessoryBar: ${$}`),console.log(I.join(`
40
+ `))}async function je(o){let c=await o.bridge.listBrowsers();if(E(o.args)){C(c.map(i=>({...i,active:i.id===o.browserId})));return}Ae(c,o.browserId)}function X(o){return o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}KB`:`${(o/1024/1024).toFixed(1)}MB`}function le(o,c){return c<=0?"?":`${(o/c*100).toFixed(0)}%`}async function Je(o,c={args:[]}){let d=await o.send({type:"evaluate",code:`(async () => {
41
+ const host = window.__sootsimRenderHost
42
+ const stats = host?.queryStats ? await host.queryStats() : null
43
+ const hostMem = performance.memory
44
+ ? {
45
+ usedJSHeapSize: performance.memory.usedJSHeapSize,
46
+ totalJSHeapSize: performance.memory.totalJSHeapSize,
47
+ jsHeapSizeLimit: performance.memory.jsHeapSizeLimit,
48
+ }
49
+ : null
50
+ return {
51
+ imageLoader: stats?.memory?.imageLoader ?? null,
52
+ workerHeap: stats?.memory?.workerHeap ?? null,
53
+ hostHeap: hostMem,
54
+ }
55
+ })()`})??{};if(E(c.args)){C(d);return}if(console.log(" memory:"),d.imageLoader){let u=d.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${u.cacheEntries} / ${u.cacheMaxEntries} (${le(u.cacheEntries,u.cacheMaxEntries)})`),console.log(` pixel bytes: ${X(u.cachePixelBytes)} / ${X(u.cachePixelBudget)} (${le(u.cachePixelBytes,u.cachePixelBudget)})`),console.log(` pending: ${u.pendingFetches} fetches, ${u.pendingBytes} bytes`),console.log(` failed uris: ${u.failedUris}`),console.log(` snapshots: ${u.snapshots}`),console.log(` camera frames: ${u.cameraFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(d.workerHeap){let u=d.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${X(u.usedJSHeapSize)} / ${X(u.jsHeapSizeLimit)} (${le(u.usedJSHeapSize,u.jsHeapSizeLimit)})`),console.log(` total: ${X(u.totalJSHeapSize)}`)}if(d.hostHeap){let u=d.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${X(u.usedJSHeapSize)} / ${X(u.jsHeapSizeLimit)} (${le(u.usedJSHeapSize,u.jsHeapSizeLimit)})`),console.log(` total: ${X(u.totalJSHeapSize)}`)}}function se(o){let c=o.indexOf("--testid");if(c>=0&&o[c+1])return{mode:"testid",value:o[c+1]};let i=o.indexOf("--test-id");if(i>=0&&o[i+1])return{mode:"testid",value:o[i+1]};let d=o.indexOf("--text");return d>=0&&o[d+1]?{mode:"text",value:o[d+1]}:null}async function ce(o,c){let i=JSON.stringify(c.value),d=c.mode==="testid"?`(await t.findByTestId(${i})) || (await t.findById(${i}))`:`await t.findByText(${i})`;return await o.send({type:"evaluate",code:`(async () => {
41
56
  const t = window.__sootsimTest
42
57
  if (!t) return null
43
58
  const n = ${d}
@@ -55,7 +70,7 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
55
70
  ? resolved.cy
56
71
  : n.absolutePosition.y + (n.layout.height || 0) / 2
57
72
  return { x: cx, y: cy, testID: n.testID, text: n.text }
58
- })()`})??null}async function Be(s,c={}){let i=await s.send({type:"evaluate",code:`(async () => {
73
+ })()`})??null}async function He(o,c={}){let i=await o.send({type:"evaluate",code:`(async () => {
59
74
  const test = window.__sootsimTest
60
75
  const kb = window.__sootsimKeyboard
61
76
  const navSnap =
@@ -79,8 +94,15 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
79
94
  })()
80
95
  : null
81
96
  return { nav: navSnap, keyboard }
82
- })()`}),d=i?.nav??null,y=i?.keyboard??null,a=await X(s,500).catch(()=>null);if(c.json){console.log(JSON.stringify({shell:a??null,nav:d,keyboard:y},null,2));return}let h=[];if(a){let S=a.activeApp??a.state??"<none>",x=a.showSwitcher?" (app switcher open)":"",T=typeof a.launchProgress=="number"&&a.launchProgress<.98?` launching (${Math.round(a.launchProgress*100)}%)`:"";h.push(`shell: ${S}${x}${T}`)}else h.push("shell: <unavailable>");if(d){let S=d.transitionPhase!=="idle"?` (${d.transitionPhase}, ${d.activeTransitionCount} active)`:"";if(h.push(`nav: phase=${d.transitionPhase}${S}`),d.screens.length===0)h.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let x of d.screens){let T=x.isActive?"\u25B6":" ",f=x.routeName?` ${x.routeName}`:"",v=x.headerHeight>0?` header=${x.headerHeight}`:"",_=x.largeTitleState&&x.largeTitleState!=="expanded"?` large-title=${x.largeTitleState}`:"";h.push(` ${T} #${x.id}${f}${v}${_}`)}}else h.push("nav: <runtime not available>");if(y&&y.visible){let S=y.spec?.keyboardType??"default",x=y.spec?.returnKeyType??"default";h.push(`keyboard: visible (${S}, return=${x}, mode=${y.mode??"?"})`)}else h.push("keyboard: hidden");console.log(h.join(`
83
- `))}async function Le(s){let{bridge:c,args:i,positional:d}=s,y=d[1]?Number(d[1])*1e3:3e3,a=i.includes("--strict"),h=Date.now(),S=!1,x="",T=0;for(;Date.now()-h<y;){let v=await c.send({type:"evaluate",code:`(async () => {
97
+ })()`}),d=i?.nav??null,u=i?.keyboard??null,a=await V(o,500).catch(()=>null);if(c.json){console.log(JSON.stringify({shell:a??null,nav:d,keyboard:u},null,2));return}let b=[];if(a){let k=a.activeApp??a.state??"<none>",$=a.showSwitcher?" (app switcher open)":"",I=typeof a.launchProgress=="number"&&a.launchProgress<.98?` launching (${Math.round(a.launchProgress*100)}%)`:"";b.push(`shell: ${k}${$}${I}`)}else b.push("shell: <unavailable>");if(d){let k=d.transitionPhase!=="idle"?` (${d.transitionPhase}, ${d.activeTransitionCount} active)`:"";if(b.push(`nav: phase=${d.transitionPhase}${k}`),d.screens.length===0)b.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let $ of d.screens){let I=$.isActive?"\u25B6":" ",y=$.routeName?` ${$.routeName}`:"",S=$.headerHeight>0?` header=${$.headerHeight}`:"",A=$.largeTitleState&&$.largeTitleState!=="expanded"?` large-title=${$.largeTitleState}`:"";b.push(` ${I} #${$.id}${y}${S}${A}`)}}else b.push("nav: <runtime not available>");if(u&&u.visible){let k=u.spec?.keyboardType??"default",$=u.spec?.returnKeyType??"default";b.push(`keyboard: visible (${k}, return=${$}, mode=${u.mode??"?"})`)}else b.push("keyboard: hidden");console.log(b.join(`
98
+ `))}async function ee({bridge:o,maxMs:c,pollMs:i=50,stablePolls:d=3,strict:u=!1}){let a=await o.send({type:"evaluate",code:`(async () => {
99
+ const start = Date.now()
100
+ const deadline = start + ${Math.max(0,Math.round(c))}
101
+ const pollMs = ${Math.max(1,Math.round(i))}
102
+ const requiredStablePolls = ${Math.max(1,Math.round(d))}
103
+ const strict = ${u?"true":"false"}
104
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
105
+ const readSnapshot = async () => {
84
106
  let animating = false
85
107
  try {
86
108
  const stats = await window.__sootsimRenderHost?.queryStats?.()
@@ -103,30 +125,26 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
103
125
  walk(root)
104
126
  }
105
127
  return { layout: nodes.join(';'), animating }
106
- })()`}),{layout:_,animating:k}=v;if((!a||!k)&&_===x){if(T++,T>=3){S=!0;break}}else T=0;x=_,await z(50)}let f=Date.now()-h;console.log(S?` settled in ${f}ms`:` timed out after ${f}ms (may still be animating)`)}async function je(s){let c=s.positional[1]?Number(s.positional[1]):.5;(!Number.isFinite(c)||c<0)&&(console.error(s.inspectUsage("sleep","[seconds]")),process.exit(1)),await z(c*1e3),console.log(` slept ${c}s`)}async function Je(s){let{bridge:c,args:i,positional:d}=s,y=d[1]?Number(d[1]):5,a=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.dumpTree(${y}))()`});if(B(i)){q({depth:y,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function qe(s,c={args:[]}){let i=await s.send({type:"evaluate",code:"window.location.href"}),d=typeof i=="string"?i:"";if(B(c.args)){q({url:d});return}console.log(d)}async function He(s){let{wsPort:c,commandTimeoutMs:i,browserId:d,positional:y}=s,a=y[1]?Number(y[1]):30,h=Math.max(1e3,(Number.isFinite(a)?a:30)*1e3),S=Math.max(1,Math.ceil(h/500));console.log(" waiting for browser reconnect...");let x=await Me(c,i,d,{attempts:S});x||(console.error(" timed out waiting for browser reconnect"),process.exit(1)),x.bridge.close(),ne({source:"inspect wait",step:{wait:h},summary:`wait ${Math.round(h/1e3)}s`}),console.log(` ready: ${x.count} nodes`)}async function We(s){let{bridge:c,args:i}=s,d=i.includes("--strict"),y=i.indexOf("--max-ms"),a=y>=0&&i[y+1]?Math.max(100,Number(i[y+1])):3e3,h=Date.now(),S=!1,x="",T=0;for(;Date.now()-h<a;){let v=await c.send({type:"evaluate",code:`(async () => {
107
- let animating = false
108
- try {
109
- const stats = await window.__sootsimRenderHost?.queryStats?.()
110
- if (stats) {
111
- animating =
112
- stats.hasActiveAnims === true ||
113
- stats.hasActiveNativeAnimations === true ||
114
- stats.hasPendingAnimationFrames === true
115
- }
116
- } catch {}
117
- const root = window.__sootsimRoot
118
- const nodes = []
119
- if (root) {
120
- const walk = (n) => {
121
- if (n.layout && n.layout.width > 0) {
122
- nodes.push(Math.round(n.layout.x) + ',' + Math.round(n.layout.y) + ',' + Math.round(n.layout.width))
123
- }
124
- for (const c of n.children || []) walk(c)
128
+ }
129
+
130
+ let lastLayout = ''
131
+ let stable = 0
132
+ while (Date.now() < deadline) {
133
+ const snapshot = await readSnapshot()
134
+ const strictOk = !strict || !snapshot.animating
135
+ if (strictOk && snapshot.layout === lastLayout) {
136
+ stable++
137
+ if (stable >= requiredStablePolls) {
138
+ return { settled: true, elapsed: Date.now() - start }
125
139
  }
126
- walk(root)
140
+ } else {
141
+ stable = 0
127
142
  }
128
- return { layout: nodes.join(';'), animating }
129
- })()`}),{layout:_,animating:k}=v;if((!d||!k)&&_===x){if(T++,T>=3){S=!0;break}}else T=0;x=_,await z(50)}let f=Date.now()-h;S?console.log(` idle in ${f}ms`):(console.error(` \u26A0 wait idle timed out after ${f}ms (may still be animating)`),process.exit(1))}async function Ke(s){let{bridge:c,args:i}=s,d=2e4,y=i.indexOf("--max-ms");y>=0&&i[y+1]&&(d=Math.max(100,Number(i[y+1])));let a=Date.now(),h=a+d,S=`(async () => {
143
+ lastLayout = snapshot.layout
144
+ await sleep(pollMs)
145
+ }
146
+ return { settled: false, elapsed: Date.now() - start }
147
+ })()`}),{elapsed:b,settled:k}=a??{};return{elapsed:typeof b=="number"?b:c,settled:k===!0}}async function qe(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1])*1e3:3e3,a=i.includes("--strict"),{elapsed:b,settled:k}=await ee({bridge:c,maxMs:u,strict:a});console.log(k?` settled in ${b}ms`:` timed out after ${b}ms (may still be animating)`)}async function We(o){let c=o.positional[1]?Number(o.positional[1]):.5;(!Number.isFinite(c)||c<0)&&(console.error(o.inspectUsage("sleep","[seconds]")),process.exit(1)),await Y(c*1e3),console.log(` slept ${c}s`)}async function ze(o){let{bridge:c,args:i,positional:d}=o,u=d[1]?Number(d[1]):5,a=await c.send({type:"evaluate",code:`(async () => await window.__sootsimTest.dumpTree(${u}))()`});if(E(i)){C({depth:u,tree:a??null});return}console.log(typeof a=="string"?a:JSON.stringify(a,null,2))}async function Ke(o,c={args:[]}){let i=await o.send({type:"evaluate",code:"window.location.href"}),d=typeof i=="string"?i:"";if(E(c.args)){C({url:d});return}console.log(d)}async function Ue(o){let{wsPort:c,commandTimeoutMs:i,browserId:d,positional:u}=o,a=u[1]?Number(u[1]):30,b=Math.max(1e3,(Number.isFinite(a)?a:30)*1e3),k=Math.max(1,Math.ceil(b/500));console.log(" waiting for browser reconnect...");let $=await Ie(c,i,d,{attempts:k});$||(console.error(" timed out waiting for browser reconnect"),process.exit(1)),$.bridge.close(),ae({source:"inspect wait",step:{wait:b},summary:`wait ${Math.round(b/1e3)}s`}),console.log(` ready: ${$.count} nodes`)}async function Ye(o){let{bridge:c,args:i}=o,d=i.includes("--strict"),u=i.indexOf("--max-ms"),a=u>=0&&i[u+1]?Math.max(100,Number(i[u+1])):3e3,{elapsed:b,settled:k}=await ee({bridge:c,maxMs:a,strict:d});k?console.log(` idle in ${b}ms`):(console.error(` \u26A0 wait idle timed out after ${b}ms (may still be animating)`),process.exit(1))}async function Ge(o){let{bridge:c,args:i}=o,d=2e4,u=i.indexOf("--max-ms");u>=0&&i[u+1]&&(d=Math.max(100,Number(i[u+1])));let a=Date.now(),b=a+d,k=`(async () => {
130
148
  const t = window.__sootsimTest
131
149
  let nodes = 0
132
150
  try { nodes = (await t?.getNodeCount?.()) || 0 } catch {}
@@ -135,9 +153,9 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
135
153
  at: (window).__sootsimExternalAppReadyAt || 0,
136
154
  nodes,
137
155
  }
138
- })()`,x={flag:void 0,at:0,nodes:0};for(;Date.now()<h;){try{x=await c.send({type:"evaluate",code:S})??x}catch{}if(x.flag===!0){console.log(` ready in ${Date.now()-a}ms: ${x.nodes} nodes (flag)`);return}await new Promise(T=>setTimeout(T,150))}console.error(` \u26A0 wait ready timed out after ${Date.now()-a}ms \u2014 guest app did not emit sootsim:externalAppReady (nodes: ${x.nodes})`),process.exit(1)}async function Ue(s){let{bridge:c,args:i,positional:d,inspectUsage:y}=s,a=d[1];a||(console.error(y("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let h=i.indexOf("--max-ms"),S=h>=0&&i[h+1]?Math.max(100,Number(i[h+1])):5e3,x=await c.send({type:"evaluate",code:`(async () => {
156
+ })()`,$={flag:void 0,at:0,nodes:0};for(;Date.now()<b;){try{$=await c.send({type:"evaluate",code:k})??$}catch{}if($.flag===!0){console.log(` ready in ${Date.now()-a}ms: ${$.nodes} nodes (flag)`);return}await new Promise(I=>setTimeout(I,150))}console.error(` \u26A0 wait ready timed out after ${Date.now()-a}ms \u2014 guest app did not emit sootsim:externalAppReady (nodes: ${$.nodes})`),process.exit(1)}async function Xe(o){let{bridge:c,args:i,positional:d,inspectUsage:u}=o,a=d[1];a||(console.error(u("wait selector","<testid> [--max-ms 5000]")),process.exit(1));let b=i.indexOf("--max-ms"),k=b>=0&&i[b+1]?Math.max(100,Number(i[b+1])):5e3,$=await c.send({type:"evaluate",code:`(async () => {
139
157
  const start = Date.now()
140
- const deadline = start + ${S}
158
+ const deadline = start + ${k}
141
159
  const t = window.__sootsimTest
142
160
  const find = async () => {
143
161
  try {
@@ -154,8 +172,8 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
154
172
  await new Promise((r) => setTimeout(r, 80))
155
173
  }
156
174
  return { found: false, elapsed: Date.now() - start }
157
- })()`}),{found:T,node:f,elapsed:v}=x??{};if(T&&f){let _=f.absolutePosition?`@(${Math.round(f.absolutePosition.x)},${Math.round(f.absolutePosition.y)})`:"",k=f.layout?`${Math.round(f.layout.width)}x${Math.round(f.layout.height)}`:"?x?";console.log(` found #${a} in ${v}ms ${k} ${_}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${v??S}ms`),process.exit(1)}function Qe(s){return s==null?"\u2014":s<1024?`${s}B`:s<1024*1024?`${(s/1024).toFixed(1)}K`:`${(s/1024/1024).toFixed(1)}M`}function et(s){return s==null?" \u2026":s<1e3?`${s}ms`.padStart(5):`${(s/1e3).toFixed(2)}s`.padStart(5)}function St(s){return s.error?"err":s.status==null?" \u2026 ":String(s.status)}function ze(s){let c=new Date(s.startTs).toLocaleTimeString(),i=St(s).padEnd(3),d=s.method.padEnd(5),y=Qe(s.size).padStart(6),a=et(s.durationMs);console.log(` [${c}] ${i} ${d} ${y} ${a} ${s.displayUrl}`),s.error&&console.log(` error: ${s.error}`)}function Tt(s){let c=[["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",et(s.durationMs).trim()],["size",Qe(s.size)],["content-type",s.type??"\u2014"]];for(let[i,d]of c)console.log(` ${i.padEnd(13)} ${d}`)}var Mt={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Ye="\x1B[0m",Nt="\x1B[2m";function Ge(s,c){let i=new Date(s.ts).toLocaleTimeString(),d=s.level.toUpperCase().padEnd(5),y=s.args.join(" ");if(c){let a=Mt[s.level];console.log(` ${Nt}[${i}]${Ye} ${a}${d}${Ye} ${y}`)}else console.log(` [${i}] ${d} ${y}`);if(s.stack&&s.level==="error"){let a=s.stack.split(`
158
- `).slice(0,5);for(let h of a)console.log(` ${h.trim()}`)}}var G="__sootsimCliPerf",_t=120;async function Xe(s,c){let i=s.find((_,k)=>s[k-1]==="--id"),d=s.find((_,k)=>s[k-1]==="--text");if(i||d){let _=await c.send({type:"evaluate",code:xe({id:i,text:d})});if(!_)throw new Error(i?`no node with id "${i}"`:`no node matching text "${d}"`);let{x:k,y:C,w:l,h:E}=_;return{x:k,y:C,w:l,h:E}}let y=s.find((_,k)=>s[k-1]==="--area");if(y){let _=y.split(",").map(R=>Number(R.trim()));if(_.length!==4||_.some(R=>!Number.isFinite(R)))throw new Error(`--area expects x,y,w,h (got "${y}")`);let[k,C,l,E]=_;return{x:k,y:C,w:l,h:E}}let a=_=>{let k=s.find((l,E)=>s[E-1]===_);if(k==null)return null;let C=Number(k);return Number.isFinite(C)?C:null},h=a("--x"),S=a("--y"),x=a("--w"),T=a("--h");if(h!=null||S!=null||x!=null||T!=null)return{x:h??0,y:S??0,w:x??1,h:T??1};let v=s.filter((_,k)=>k>0&&!_.startsWith("-")&&s[k-1]!=="--output"&&s[k-1]!=="--area"&&s[k-1]!=="--id"&&s[k-1]!=="--text"&&s[k-1]!=="--x"&&s[k-1]!=="--y"&&s[k-1]!=="--w"&&s[k-1]!=="--h").map(Number).filter(_=>Number.isFinite(_));if(v.length>=2){let[_,k,C=1,l=1]=v;return{x:_,y:k,w:C,h:l}}return null}function fe(s){let c={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of s)i<8?c["<8"]++:i<12?c["8-12"]++:i<16?c["12-16"]++:i<20?c["16-20"]++:i<33?c["20-33"]++:c[">33"]++;console.log(" histogram:");for(let[i,d]of Object.entries(c)){let y="\u2588".repeat(Math.ceil(d/s.length*40));console.log(` ${i.padEnd(6)} ${y} ${d}`)}}async function ie(s,c,i){let d=Date.now()+c,y=await X(s,c);for(;;){if(i(y))return{settled:!0,state:y};if(Date.now()>=d)return{settled:!1,state:y};await z(16),y=await X(s)}}async function ge(s){return s.send({type:"evaluate",code:`(async () => {
175
+ })()`}),{found:I,node:y,elapsed:S}=$??{};if(I&&y){let A=y.absolutePosition?`@(${Math.round(y.absolutePosition.x)},${Math.round(y.absolutePosition.y)})`:"",v=y.layout?`${Math.round(y.layout.width)}x${Math.round(y.layout.height)}`:"?x?";console.log(` found #${a} in ${S}ms ${v} ${A}`)}else console.error(` \u26A0 wait selector #${a} timed out after ${S??k}ms`),process.exit(1)}function st(o){return o==null?"\u2014":o<1024?`${o}B`:o<1024*1024?`${(o/1024).toFixed(1)}K`:`${(o/1024/1024).toFixed(1)}M`}function nt(o){return o==null?" \u2026":o<1e3?`${o}ms`.padStart(5):`${(o/1e3).toFixed(2)}s`.padStart(5)}function _t(o){return o.error?"err":o.status==null?" \u2026 ":String(o.status)}function Ve(o){let c=new Date(o.startTs).toLocaleTimeString(),i=_t(o).padEnd(3),d=o.method.padEnd(5),u=st(o.size).padStart(6),a=nt(o.durationMs);console.log(` [${c}] ${i} ${d} ${u} ${a} ${o.displayUrl}`),o.error&&console.log(` error: ${o.error}`)}function It(o){let c=[["id",o.id],["source",o.source],["kind",o.kind],["method",o.method],["status",o.error?`error: ${o.error}`:`${o.status??"\u2014"} ${o.statusText??""}`.trim()],["url",o.url],["started",new Date(o.startTs).toLocaleTimeString()],["duration",nt(o.durationMs).trim()],["size",st(o.size)],["content-type",o.type??"\u2014"]];for(let[i,d]of c)console.log(` ${i.padEnd(13)} ${d}`)}var Ft={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},Ze="\x1B[0m",At="\x1B[2m";function Qe(o,c){let i=new Date(o.ts).toLocaleTimeString(),d=o.level.toUpperCase().padEnd(5),u=o.args.join(" ");if(c){let a=Ft[o.level];console.log(` ${At}[${i}]${Ze} ${a}${d}${Ze} ${u}`)}else console.log(` [${i}] ${d} ${u}`);if(o.stack&&o.level==="error"){let a=o.stack.split(`
176
+ `).slice(0,5);for(let b of a)console.log(` ${b.trim()}`)}}var G="__sootsimCliPerf",Pt=120;async function et(o,c){let i=o.find((A,v)=>o[v-1]==="--id"),d=o.find((A,v)=>o[v-1]==="--text");if(i||d){let A=await c.send({type:"evaluate",code:Ne({id:i,text:d})});if(!A)throw new Error(i?`no node with id "${i}"`:`no node matching text "${d}"`);let{x:v,y:j,w:l,h:R}=A;return{x:v,y:j,w:l,h:R}}let u=o.find((A,v)=>o[v-1]==="--area");if(u){let A=u.split(",").map(D=>Number(D.trim()));if(A.length!==4||A.some(D=>!Number.isFinite(D)))throw new Error(`--area expects x,y,w,h (got "${u}")`);let[v,j,l,R]=A;return{x:v,y:j,w:l,h:R}}let a=A=>{let v=o.find((l,R)=>o[R-1]===A);if(v==null)return null;let j=Number(v);return Number.isFinite(j)?j:null},b=a("--x"),k=a("--y"),$=a("--w"),I=a("--h");if(b!=null||k!=null||$!=null||I!=null)return{x:b??0,y:k??0,w:$??1,h:I??1};let S=o.filter((A,v)=>v>0&&!A.startsWith("-")&&o[v-1]!=="--output"&&o[v-1]!=="--area"&&o[v-1]!=="--id"&&o[v-1]!=="--text"&&o[v-1]!=="--x"&&o[v-1]!=="--y"&&o[v-1]!=="--w"&&o[v-1]!=="--h").map(Number).filter(A=>Number.isFinite(A));if(S.length>=2){let[A,v,j=1,l=1]=S;return{x:A,y:v,w:j,h:l}}return null}function be(o){let c={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let i of o)i<8?c["<8"]++:i<12?c["8-12"]++:i<16?c["12-16"]++:i<20?c["16-20"]++:i<33?c["20-33"]++:c[">33"]++;console.log(" histogram:");for(let[i,d]of Object.entries(c)){let u="\u2588".repeat(Math.ceil(d/o.length*40));console.log(` ${i.padEnd(6)} ${u} ${d}`)}}async function de(o,c,i){let d=Date.now()+c,u=await V(o,c);for(;;){if(i(u))return{settled:!0,state:u};if(Date.now()>=d)return{settled:!1,state:u};await Y(16),u=await V(o)}}async function he(o){return o.send({type:"evaluate",code:`(async () => {
159
177
  const kb = window.__sootsimKeyboard
160
178
  const test = window.__sootsimTest
161
179
  if (!kb) return { error: 'keyboard bridge not available' }
@@ -187,7 +205,7 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
187
205
  frame: runtimeSnapshot?.keyboard?.frame ?? null,
188
206
  focusedRect: runtimeSnapshot?.focused?.rect ?? null,
189
207
  }
190
- })()`})}async function It(s,c=600){let i=Date.now()+c;for(;Date.now()<=i;){let d=await ge(s);if(d.visible)return d;await z(30)}return ge(s)}async function le(s,c){let i=await ge(s);if(i.visible)return i;console.error(` ${c} 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 Ve(s,c,i){return c==="appearance"?s.send({type:"evaluate",code:`(async () => {
208
+ })()`})}async function Ot(o,c=600){let i=Date.now()+c;for(;Date.now()<=i;){let d=await he(o);if(d.visible)return d;await Y(30)}return he(o)}async function ue(o,c){let i=await he(o);if(i.visible)return i;console.error(` ${c} 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 tt(o,c,i){return c==="appearance"?o.send({type:"evaluate",code:`(async () => {
191
209
  const requested = ${JSON.stringify(i??"toggle")}
192
210
  const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
193
211
  const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
@@ -199,58 +217,28 @@ import{a as Y}from"./chunk-GPVPHE2B.js";import{a as xe,b as $e}from"./chunk-J2S3
199
217
  }
200
218
  window.postMessage({ type: 'soot-action', action: 'set-appearance', value: applied }, '*')
201
219
  return { ok: true, requested, applied }
202
- })()`}):s.send({type:"evaluate",code:`(async () => {
220
+ })()`}):o.send({type:"evaluate",code:`(async () => {
203
221
  window.dispatchEvent(new CustomEvent(${JSON.stringify(c==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
204
222
  return { ok: true, action: ${JSON.stringify(c)} }
205
- })()`})}function Ft(s){let c={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(c[s])return c[s];let i=s.match(/^Digit([0-9])$/);if(i)return i[1];let d=s.match(/^Key([A-Z])$/);return d?d[1].toLowerCase():null}function At(s){if(typeof s!="string")return null;let c=s.replace(/\s+/g," ").trim();return c?c.slice(0,80):null}function tt(...s){for(let c of s){if(typeof c!="string")continue;let i=c.trim();if(i)return i}return null}async function L(s,c,i){ne({source:s,step:c,summary:i})}function Pt(s,c,i){if(!i||i.hit===!1)return null;let d=tt(i.responderTestID,i.testID);if(d)return{step:{tapOn:{id:d}},summary:`tap #${d}`};let y=At(i.text);return y?{step:{tapOn:y},summary:`tap "${y}"`}:{step:{tapAtCoords:{x:s,y:c}},summary:`tap @${Math.round(s)},${Math.round(c)}`}}function Ze(s,c,i){let d=tt(c?.testID,c?.id);return d?{step:{tapOn:{id:d}},summary:`tap #${d}`}:i==="id"?{step:{tapOn:{id:s}},summary:`tap #${s}`}:{step:{tapOn:s},summary:`tap "${s}"`}}async function Yo(s,c){let i=s[0]==="get"||s[0]==="do"||s[0]==="debug"||s[0]==="wait"?s[0]:null,d=i?s.slice(1):s,y=ve(d,{port:c.port,commandTimeoutMs:c.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--tail","-f","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--max-ms","--filter","--limit","--level"]}),a=y.positional,h=a[0],S=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",x=typeof d[0]=="string"&&he.has(d[0]),T=x?d[0]:null,f=e=>x&&e===d[0]?`sootsim ${e}`:`sootsim ${S} ${e}`,v=(e,t)=>` usage: ${f(e)}${t?` ${t}`:""}`;if(!h||s.includes("--help")||s.includes("-h")){let e={bridgePort:7668,defaultShellUrl:ye};if(S==="do"||S==="get"||S==="debug"||S==="wait"){let r=ce(S,e);r&&(console.log(`${r}
206
- `),process.exit(0))}if(T==="shell"){let r=de("shell",e);r&&(console.log(`${r}
207
- `),process.exit(0))}let t=de("inspect",e),o=["do","get","debug","wait"].map(r=>ce(r,e)).filter(r=>r!=null).join(`
223
+ })()`})}function Et(o){let c={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(c[o])return c[o];let i=o.match(/^Digit([0-9])$/);if(i)return i[1];let d=o.match(/^Key([A-Z])$/);return d?d[1].toLowerCase():null}function Rt(o){if(typeof o!="string")return null;let c=o.replace(/\s+/g," ").trim();return c?c.slice(0,80):null}function rt(...o){for(let c of o){if(typeof c!="string")continue;let i=c.trim();if(i)return i}return null}async function L(o,c,i){ae({source:o,step:c,summary:i})}function Ct(o,c,i){if(!i||i.hit===!1)return null;let d=rt(i.responderTestID,i.testID);if(d)return{step:{tapOn:{id:d}},summary:`tap #${d}`};let u=Rt(i.text);return u?{step:{tapOn:u},summary:`tap "${u}"`}:{step:{tapAtCoords:{x:o,y:c}},summary:`tap @${Math.round(o)},${Math.round(c)}`}}function ot(o,c,i){let d=rt(c?.testID,c?.id);return d?{step:{tapOn:{id:d}},summary:`tap #${d}`}:i==="id"?{step:{tapOn:{id:o}},summary:`tap #${o}`}:{step:{tapOn:o},summary:`tap "${o}"`}}async function ss(o,c){let i=o[0]==="get"||o[0]==="do"||o[0]==="debug"||o[0]==="wait"?o[0]:null,d=i?o.slice(1):o,u=$e(d,{port:c.port,commandTimeoutMs:c.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--tail","-f","--internal"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--max-ms","--filter","--limit","--level"]}),a=u.positional,b=a[0],k=i==="get"||i==="do"||i==="debug"||i==="wait"?i:"inspect",$=typeof d[0]=="string"&&xe.has(d[0]),I=$?d[0]:null,y=e=>$&&e===d[0]?`sootsim ${e}`:`sootsim ${k} ${e}`,S=(e,t)=>` usage: ${y(e)}${t?` ${t}`:""}`;if(!b||o.includes("--help")||o.includes("-h")){let e={bridgePort:7668,defaultShellUrl:we};if(k==="do"||k==="get"||k==="debug"||k==="wait"){let r=me(k,e);r&&(console.log(`${r}
224
+ `),process.exit(0))}if(I==="shell"){let r=pe("shell",e);r&&(console.log(`${r}
225
+ `),process.exit(0))}let t=pe("inspect",e),s=["do","get","debug","wait"].map(r=>me(r,e)).filter(r=>r!=null).join(`
208
226
 
209
227
  `);console.log(`${t??""}
210
228
 
211
- ${o}
212
- `),process.exit(0)}let _=y.wsPort,k=y.browserId,C=y.commandTimeoutMs;if(h==="list"&&d.some(e=>e==="--drivers"||e==="-D")){let{buildDriverListRows:e}=await import("./drivers-46PFFIDF.js"),t=e();console.log(` available drivers (${t.length}):
213
- `);let o=Math.max(...t.map(n=>n.id.length),6),r=Math.max(...t.map(n=>n.kind.length),4);for(let n of t){let u=n.available?"\u2713":"\u2717",m=n.id.padEnd(o),b=n.kind.padEnd(r);console.log(` ${u} ${m} ${b} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let l=ke(y),E=k||"default",R=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]);function H(e){let t=e.displayUrl||e.url;return e.status!=null?`${e.method} ${t} -> ${e.status}${e.statusText?` ${e.statusText}`:""}`:e.error?`${e.method} ${t} -> ${e.error}`:`${e.method} ${t}`}async function oe(e){let t=Oe()?1200:350;try{let o=await e.send({type:"evaluate",code:`(async () => {
214
- const start = Date.now()
215
- const deadline = start + ${t}
216
- const hash = () => {
217
- const root = window.__sootsimRoot
218
- if (!root) return ''
219
- const nodes = []
220
- const walk = (n) => {
221
- if (n.layout && n.layout.width > 0) {
222
- nodes.push(Math.round(n.layout.x) + ',' + Math.round(n.layout.y) + ',' + Math.round(n.layout.width))
223
- }
224
- for (const c of n.children || []) walk(c)
225
- }
226
- walk(root)
227
- return nodes.join(';')
228
- }
229
- let last = ''
230
- let stable = 0
231
- while (Date.now() < deadline) {
232
- const h = hash()
233
- if (h === last) {
234
- stable++
235
- if (stable >= 2) return { settled: true, elapsed: Date.now() - start }
236
- } else {
237
- stable = 0
238
- }
239
- last = h
240
- await new Promise((r) => setTimeout(r, 32))
241
- }
242
- return { settled: false, elapsed: Date.now() - start }
243
- })()`}),{settled:r,elapsed:n}=o??{};r===!1&&process.stderr.write(` \u26A0 auto-wait timed out after ${n??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
244
- `)}catch{}}async function V(){try{return await l.send({type:"evaluate",code:`(() => ({
229
+ ${s}
230
+ `),process.exit(0)}let A=u.wsPort,v=u.browserId,j=u.commandTimeoutMs;if(b==="list"&&d.some(e=>e==="--drivers"||e==="-D")){let{buildDriverListRows:e}=await import("./drivers-EXUREU4B.js"),t=e();console.log(` available drivers (${t.length}):
231
+ `);let s=Math.max(...t.map(n=>n.id.length),6),r=Math.max(...t.map(n=>n.kind.length),4);for(let n of t){let m=n.available?"\u2713":"\u2717",p=n.id.padEnd(s),h=n.kind.padEnd(r);console.log(` ${m} ${p} ${h} ${n.description}`),n.available&&n.detail?console.log(` ${n.detail}`):!n.available&&n.reason&&console.log(` unavailable: ${n.reason}`)}return}let l=Se(u),R=v||"default",D=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]);function q(e){let t=e.displayUrl||e.url;return e.status!=null?`${e.method} ${t} -> ${e.status}${e.statusText?` ${e.statusText}`:""}`:e.error?`${e.method} ${t} -> ${e.error}`:`${e.method} ${t}`}async function ne(e){let t=Ce()?1200:350;try{let{settled:s,elapsed:r}=await ee({bridge:e,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${r??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
232
+ `)}catch{}}async function Z(){try{return await l.send({type:"evaluate",code:`(() => ({
245
233
  console: window.__sootsimConsole?.count?.() || null,
246
234
  requests: window.__sootsimTest?.getRequestCounts?.() || null,
247
- }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function $(e={}){let t=e.counts!==void 0?e.counts:await K(l,"getRequestCounts");if(!t||typeof t!="object")return;let o=Math.max(0,Number(t.failed)||0);if(o===0||!e.includeTail&&!me("requests",E,String(o))||(console.log(`
248
- network: ${o} failed request${o===1?"":"s"}`),console.log(` inspect: ${f("requests")} 5`),!e.includeTail))return;let r=await K(l,"getFailedRequests",5);if(!(!Array.isArray(r)||r.length===0)){console.log(`
235
+ }))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function x(e={}){let t=e.counts!==void 0?e.counts:await z(l,"getRequestCounts");if(!t||typeof t!="object")return;let s=Math.max(0,Number(t.failed)||0);if(s===0||!e.includeTail&&!ge("requests",R,String(s))||(console.log(`
236
+ network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${y("requests")} 5`),!e.includeTail))return;let r=await z(l,"getFailedRequests",5);if(!(!Array.isArray(r)||r.length===0)){console.log(`
249
237
  recent failed requests:
250
- `);for(let n of r){let u=new Date(n.timestamp).toLocaleTimeString();console.log(` [${u}] ${H(n)}`),n.responseBody?console.log(` ${n.responseBody}`):n.error&&console.log(` ${n.error}`)}}}async function j(e={}){let t=e.counts!==void 0?e.counts:await l.send({type:"evaluate",code:"window.__sootsimConsole?.count?.() || { errors: 0, warnings: 0, total: 0 }"});if(!t||typeof t!="object")return;let o=Math.max(0,Number(t.errors)||0),r=Math.max(0,Number(t.warnings)||0);if(o===0&&r===0||!e.includeTail&&!me("console",E,`${o}:${r}`))return;let n=[];if(o>0&&n.push(`${o} console error${o===1?"":"s"}`),r>0&&n.push(`${r} console warning${r===1?"":"s"}`),console.log(`
251
- console: ${n.join(", ")}`),console.log(` inspect: ${f("errors")} 5`),r>0&&console.log(` inspect: ${f("warnings")} 5`),!e.includeTail||o===0)return;let u=await l.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors?.(5) || []"});if(!(!Array.isArray(u)||u.length===0)){console.log(`
238
+ `);for(let n of r){let m=new Date(n.timestamp).toLocaleTimeString();console.log(` [${m}] ${q(n)}`),n.responseBody?console.log(` ${n.responseBody}`):n.error&&console.log(` ${n.error}`)}}}async function J(e={}){let t=e.counts!==void 0?e.counts:await l.send({type:"evaluate",code:"window.__sootsimConsole?.count?.() || { errors: 0, warnings: 0, total: 0 }"});if(!t||typeof t!="object")return;let s=t,r=Math.max(0,Number(s.errors)||0),n=Math.max(0,Number(s.warnings)||0);if(r===0&&n===0||!e.includeTail&&!ge("console",R,`${r}:${n}`))return;let m=[];if(r>0&&m.push(`${r} console error${r===1?"":"s"}`),n>0&&m.push(`${n} console warning${n===1?"":"s"}`),console.log(`
239
+ console: ${m.join(", ")}`),console.log(` inspect: ${y("errors")} 5`),n>0&&console.log(` inspect: ${y("warnings")} 5`),!e.includeTail||r===0)return;let p=await l.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors?.(5) || []"});if(!(!Array.isArray(p)||p.length===0)){console.log(`
252
240
  recent console errors:
253
- `);for(let m of u){let b=new Date(m.timestamp).toLocaleTimeString(),p=Array.isArray(m.args)?m.args.map(w=>typeof w=="object"?JSON.stringify(w):String(w)).join(" "):String(m);console.log(` [${b}] ${p}`)}}}let J=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"]),U=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"]),Z=(s.includes("--verbose")||s.includes("-v"))&&!s.includes("--json");S==="do"&&h==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),J.has(h)&&await Se(l),U.has(h)&&await re(l,{verbose:Z});try{switch(h){case"list":{await De({bridge:l,browserId:k,args:d});break}case"tree":{await Je({bridge:l,args:d,positional:a});break}case"a11y":{let e=a[1]?Number(a[1]):5,t=await l.send({type:"evaluate",code:`(async () => {
241
+ `);for(let h of p){let f=new Date(h.timestamp).toLocaleTimeString(),w=Array.isArray(h.args)?h.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(h);console.log(` [${f}] ${w}`)}}}let H=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"]),K=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"]),Q=(o.includes("--verbose")||o.includes("-v"))&&!o.includes("--json");k==="do"&&b==="shell"&&(console.error(" `sootsim do shell` was removed. use `sootsim shell ...` instead."),process.exit(1)),H.has(b)&&await ke(l),K.has(b)&&await ie(l,{verbose:Q});try{switch(b){case"list":{await je({bridge:l,browserId:v,args:d});break}case"tree":{await ze({bridge:l,args:d,positional:a});break}case"a11y":{let e=a[1]?Number(a[1]):5,t=await l.send({type:"evaluate",code:`(async () => {
254
242
  const t = window.__sootsimTest
255
243
  if (!t) return []
256
244
  const all = await t.queryAll({ pruneHidden: true })
@@ -278,8 +266,8 @@ ${o}
278
266
  position: n.absolutePosition ? { x: Math.round(n.absolutePosition.x), y: Math.round(n.absolutePosition.y) } : null,
279
267
  size: n.layout ? { w: Math.round(n.layout.width), h: Math.round(n.layout.height) } : null,
280
268
  }))
281
- })()`});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):
282
- `);for(let o of t){let r=[];if(r.push(`[${o.role}]`),o.label){let n=o.label.length>50?o.label.slice(0,47)+"...":o.label;r.push(`"${n}"`)}if(o.hint&&r.push(`(hint: "${o.hint}")`),o.testID&&r.push(`#${o.testID}`),o.state){let n=[];o.state.disabled&&n.push("disabled"),o.state.selected&&n.push("selected"),o.state.checked===!0&&n.push("checked"),o.state.checked==="mixed"&&n.push("mixed"),o.state.busy&&n.push("busy"),o.state.expanded===!0&&n.push("expanded"),o.state.expanded===!1&&n.push("collapsed"),n.length&&r.push(`{${n.join(", ")}}`)}o.position&&r.push(`@(${o.position.x},${o.position.y})`),o.size&&r.push(`${o.size.w}x${o.size.h}`),console.log(" "+r.join(" "))}}break}case"find":{await Ee({bridge:l,args:s,effectiveArgs:d,positional:a,inspectUsage:v});break}case"count":{await Ae(l,{args:d});break}case"keyboard":{await Re(l,{json:s.includes("--json")});break}case"screens":{await Be(l,{json:s.includes("--json")});break}case"wait":{await He({wsPort:_,commandTimeoutMs:C,browserId:k,positional:a});break}case"sleep":{await je({positional:a,inspectUsage:v});break}case"settle":{await Le({bridge:l,args:s,positional:a});break}case"ready":{await Ke({bridge:l,args:s});break}case"idle":{await We({bridge:l,args:s,positional:a});break}case"selector":{await Ue({bridge:l,args:s,positional:a,inspectUsage:v});break}case"layout":{let e=a[1];e||(console.error(v("layout","<id>")),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(e)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=s.find((b,p)=>s[p-1]==="--output")||"/tmp/sootsim-inspect.png",o=await Xe(s,l),r={type:"screenshot"};o&&(r.crop=o);let u=(await l.send(r)).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(t,Buffer.from(u,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let e=await Xe(s,l);e||(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 t=await l.send({type:"evaluate",code:$e(e)});if(s.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:o,g:r,b:n,a:u,hex:m,samples:b}=t,p=e.w===1&&e.h===1?`@(${e.x},${e.y})`:`@(${e.x},${e.y}) ${e.w}x${e.h}`;console.log(` ${m} rgba(${o}, ${r}, ${n}, ${u}) ${p} ${b} samples`)}break}case"node":{let e=a[1];e||(console.error(v("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => {
269
+ })()`});if(!Array.isArray(t)||t.length===0){console.log(" no accessible nodes found");break}if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{console.log(` accessibility tree (${t.length} nodes):
270
+ `);for(let s of t){let r=[];if(r.push(`[${s.role}]`),s.label){let n=s.label.length>50?s.label.slice(0,47)+"...":s.label;r.push(`"${n}"`)}if(s.hint&&r.push(`(hint: "${s.hint}")`),s.testID&&r.push(`#${s.testID}`),s.state){let n=[];s.state.disabled&&n.push("disabled"),s.state.selected&&n.push("selected"),s.state.checked===!0&&n.push("checked"),s.state.checked==="mixed"&&n.push("mixed"),s.state.busy&&n.push("busy"),s.state.expanded===!0&&n.push("expanded"),s.state.expanded===!1&&n.push("collapsed"),n.length&&r.push(`{${n.join(", ")}}`)}s.position&&r.push(`@(${s.position.x},${s.position.y})`),s.size&&r.push(`${s.size.w}x${s.size.h}`),console.log(" "+r.join(" "))}}break}case"find":{await Be({bridge:l,args:o,effectiveArgs:d,positional:a,inspectUsage:S});break}case"count":{await Ee(l,{args:d});break}case"keyboard":{await Le(l,{json:o.includes("--json")});break}case"screens":{await He(l,{json:o.includes("--json")});break}case"memory":{await Je(l,{args:d});break}case"wait":{await Ue({wsPort:A,commandTimeoutMs:j,browserId:v,positional:a});break}case"sleep":{await We({positional:a,inspectUsage:S});break}case"settle":{await qe({bridge:l,args:o,positional:a});break}case"ready":{await Ge({bridge:l,args:o});break}case"idle":{await Ye({bridge:l,args:o,positional:a});break}case"selector":{await Xe({bridge:l,args:o,positional:a,inspectUsage:S});break}case"layout":{let e=a[1];e||(console.error(S("layout","<id>")),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => await window.__sootsimTest.getLayout(${JSON.stringify(e)}))()`});console.log(JSON.stringify(t,null,2));break}case"capture":case"screenshot":{let t=o.find((h,f)=>o[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await et(o,l),r={type:"screenshot"};s&&(r.crop=s);let m=(await l.send(r)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(m,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let e=await et(o,l);e||(console.error(S("sample-color","<x> <y> [w] [h] | --id <testID> | --text <text>")),console.error(" samples an averaged color from the canvas. coords are logical sootsim units."),process.exit(1));let t=await l.send({type:"evaluate",code:_e(e)});if(o.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:r,b:n,a:m,hex:p,samples:h}=t,f=e.w===1&&e.h===1?`@(${e.x},${e.y})`:`@(${e.x},${e.y}) ${e.w}x${e.h}`;console.log(` ${p} rgba(${s}, ${r}, ${n}, ${m}) ${f} ${h} samples`)}break}case"node":{let e=a[1];e||(console.error(S("node","<matcher>")),console.error(" resolves testID, id, then text \u2014 dumps full node info as JSON"),process.exit(1));let t=await l.send({type:"evaluate",code:`(async () => {
283
271
  const t = window.__sootsimTest
284
272
  const q = ${JSON.stringify(e)}
285
273
  let node = null
@@ -335,17 +323,17 @@ ${o}
335
323
  transform,
336
324
  parentChain,
337
325
  }
338
- })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let e=Number(a[1]),t=Number(a[2]),o=te(s);if(o){let u=await ae(l,o);u||(console.error(` not found: ${o.value}`),o.mode==="testid"&&Y("wait-selector-for-missing-testid",o.value),process.exit(1)),e=u.x,t=u.y}(!Number.isFinite(e)||!Number.isFinite(t))&&(console.error(v("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await l.send({type:"tap",x:e,y:t}),n=Pt(e,t,r);n&&await L("inspect tap",n.step,n.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let e=Number(a[1]),t=Number(a[2]),o=Number(a[3]),r=Number(a[4]),n=h==="swipe"?10:12,u=h==="swipe"?8:16,m=a[5]?Number(a[5]):n,b=a[6]?Number(a[6]):u;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(o)||!Number.isFinite(r)||!Number.isFinite(m)||!Number.isFinite(b))&&(console.error(v(h,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let p=await l.send({type:"evaluate",code:`(async () => {
326
+ })()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let m=await ce(l,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=m.x,t=m.y}(!Number.isFinite(e)||!Number.isFinite(t))&&(console.error(S("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await l.send({type:"tap",x:e,y:t}),n=Ct(e,t,r);n&&await L("inspect tap",n.step,n.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=b==="swipe"?10:12,m=b==="swipe"?8:16,p=a[5]?Number(a[5]):n,h=a[6]?Number(a[6]):m;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(p)||!Number.isFinite(h))&&(console.error(S(b,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await l.send({type:"evaluate",code:`(async () => {
339
327
  const interact = window.__sootsimInteract
340
328
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
341
- const value = await interact.drag(${e}, ${t}, ${o}, ${r}, ${Math.max(1,Math.round(m))}, ${Math.max(0,Math.round(b))})
329
+ const value = await interact.drag(${e}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(h))})
342
330
  return { ok: !!value, value }
343
- })()`});if(p?.ok){let w=Math.max(1,Math.round(Math.max(1,m)*Math.max(0,b)));await L(`inspect ${h}`,{swipe:{start:`${e}, ${t}`,end:`${o}, ${r}`,duration:w}},`${h} ${e},${t} -> ${o},${r}`)}console.log(JSON.stringify(p,null,2));break}case"pinch":{let e=Number(a[1]),t=Number(a[2]),o=Number(a[3]),r=Number(a[4]),n=Number(a[5]),u=Number(a[6]),m=Number(a[7]),b=Number(a[8]),p=a[9]?Number(a[9]):12,w=a[10]?Number(a[10]):16;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(o)||!Number.isFinite(r)||!Number.isFinite(n)||!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(b)||!Number.isFinite(p)||!Number.isFinite(w))&&(console.error(v("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await l.send({type:"evaluate",code:`(async () => {
331
+ })()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,h)));await L(`inspect ${b}`,{swipe:{start:`${e}, ${t}`,end:`${s}, ${r}`,duration:w}},`${b} ${e},${t} -> ${s},${r}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let e=Number(a[1]),t=Number(a[2]),s=Number(a[3]),r=Number(a[4]),n=Number(a[5]),m=Number(a[6]),p=Number(a[7]),h=Number(a[8]),f=a[9]?Number(a[9]):12,w=a[10]?Number(a[10]):16;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(n)||!Number.isFinite(m)||!Number.isFinite(p)||!Number.isFinite(h)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(S("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await l.send({type:"evaluate",code:`(async () => {
344
332
  const interact = window.__sootsimInteract
345
333
  if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
346
- const value = await interact.pinch(${e}, ${t}, ${o}, ${r}, ${n}, ${u}, ${m}, ${b}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(w))})
334
+ const value = await interact.pinch(${e}, ${t}, ${s}, ${r}, ${n}, ${m}, ${p}, ${h}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
347
335
  return { ok: !!value, value }
348
- })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[e,t,o,r],to:[n,u,m,b],steps:Math.max(1,Math.round(p)),stepMs:Math.max(0,Math.round(w))}},`pinch (${e},${t}) (${o},${r}) -> (${n},${u}) (${m},${b})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let e=a[1];e||(console.error(v("tap-text","<text>")),process.exit(1));let t=F=>{let P=s.indexOf(F);return P>=0&&P+1<s.length?s[P+1]:null},o=F=>s.includes(F),r=t("--nth")??t("--index"),n=r!==null?Number(r):null;n!==null&&!Number.isFinite(n)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let u=t("--within"),m=t("--role"),b=o("--exact"),p=o("--first"),w=t("--min-y"),O=t("--max-y"),D=t("--min-x"),I=t("--max-x");for(let[F,P]of[["--min-y",w],["--max-y",O],["--min-x",D],["--max-x",I]])P!==null&&!Number.isFinite(Number(P))&&(console.error(` ${F} requires a number, got: ${P}`),process.exit(1));let N=s.indexOf("--near"),A=null;if(N>=0){let F=Number(s[N+1]),P=Number(s[N+2]);(!Number.isFinite(F)||!Number.isFinite(P))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),A={x:F,y:P}}let W=JSON.stringify({query:e,exact:b,role:m,within:u,minX:D!==null?Number(D):null,maxX:I!==null?Number(I):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:A,nth:n,first:p}),g=await l.send({type:"evaluate",code:`(async () => {
336
+ })()`});O?.ok&&await L("inspect pinch",{pinch:{from:[e,t,s,r],to:[n,m,p,h],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${e},${t}) (${s},${r}) -> (${n},${m}) (${p},${h})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let e=a[1];e||(console.error(S("tap-text","<text>")),process.exit(1));let t=_=>{let P=o.indexOf(_);return P>=0&&P+1<o.length?o[P+1]:null},s=_=>o.includes(_),r=t("--nth")??t("--index"),n=r!==null?Number(r):null;n!==null&&!Number.isFinite(n)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let m=t("--within"),p=t("--role"),h=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),B=t("--min-x"),N=t("--max-x");for(let[_,P]of[["--min-y",w],["--max-y",O],["--min-x",B],["--max-x",N]])P!==null&&!Number.isFinite(Number(P))&&(console.error(` ${_} requires a number, got: ${P}`),process.exit(1));let M=o.indexOf("--near"),F=null;if(M>=0){let _=Number(o[M+1]),P=Number(o[M+2]);(!Number.isFinite(_)||!Number.isFinite(P))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:_,y:P}}let W=JSON.stringify({query:e,exact:h,role:p,within:m,minX:B!==null?Number(B):null,maxX:N!==null?Number(N):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:n,first:f}),g=await l.send({type:"evaluate",code:`(async () => {
349
337
  const t = window.__sootsimTest
350
338
  if (!t) return { error: 'bridge-not-ready' }
351
339
  const F = ${W}
@@ -459,7 +447,7 @@ ${o}
459
447
  total,
460
448
  idx,
461
449
  }
462
- })()`});if(g?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),g?.ambiguous){let F=g.candidates;console.error(` ambiguous: ${g.total} matches for "${e}"`);for(let P of F){let se=P.abs?`@(${Math.round(P.abs.x)},${Math.round(P.abs.y)})`:"",ot=P.layout?` ${P.layout.width}x${P.layout.height}`:"",st=P.testID?` #${P.testID}`:"",nt=P.text?` "${P.text}"`:"",rt=P.ancestorTestIDs.length>0?` within ${P.ancestorTestIDs.slice(0,3).map(at=>`#${at}`).join(" > ")}`:"";console.error(` [${P.idx}] <${P.type}>${nt}${st} ${se}${ot}${rt}`)}g.total>F.length&&console.error(` ... and ${g.total-F.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)}g?.nthOutOfRange&&(console.error(` not found: nth ${g.nth} of ${g.total} match${g.total===1?"":"es"} for "${e}"`),process.exit(1)),(!g||typeof g.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let M=await l.send({type:"tap",x:g.cx,y:g.cy});if(M?.hit!==!1&&M?.ok!==!1){let F=Ze(e,{id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},"text");await L("inspect tap-text",F.step,F.summary)}console.log(JSON.stringify({matched:g.match,tapped:{nodeId:g.target?.nodeId??null,id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},...g.strategy&&g.strategy!=="matched-node"?{strategy:g.strategy}:{},...g.total>1||n!==null?{nth:{index:g.idx,total:g.total}}:{},result:M},null,2));break}case"tap-id":{let e=a[1];e||(console.error(v("tap-id","<id>")),process.exit(1));let t=JSON.stringify(e),o=await l.send({type:"evaluate",code:`(async () => {
450
+ })()`});if(g?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),g?.ambiguous){let _=g.candidates;console.error(` ambiguous: ${g.total} matches for "${e}"`);for(let P of _){let re=P.abs?`@(${Math.round(P.abs.x)},${Math.round(P.abs.y)})`:"",at=P.layout?` ${P.layout.width}x${P.layout.height}`:"",it=P.testID?` #${P.testID}`:"",lt=P.text?` "${P.text}"`:"",ct=P.ancestorTestIDs.length>0?` within ${P.ancestorTestIDs.slice(0,3).map(dt=>`#${dt}`).join(" > ")}`:"";console.error(` [${P.idx}] <${P.type}>${lt}${it} ${re}${at}${ct}`)}g.total>_.length&&console.error(` ... and ${g.total-_.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)}g?.nthOutOfRange&&(console.error(` not found: nth ${g.nth} of ${g.total} match${g.total===1?"":"es"} for "${e}"`),process.exit(1)),(!g||typeof g.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let T=await l.send({type:"tap",x:g.cx,y:g.cy});if(T?.hit!==!1&&T?.ok!==!1){let _=ot(e,{id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},"text");await L("inspect tap-text",_.step,_.summary)}console.log(JSON.stringify({matched:g.match,tapped:{nodeId:g.target?.nodeId??null,id:g.target?.id??null,testID:g.target?.testID??null,type:g.target?.type??null,cx:g.cx,cy:g.cy},...g.strategy&&g.strategy!=="matched-node"?{strategy:g.strategy}:{},...g.total>1||n!==null?{nth:{index:g.idx,total:g.total}}:{},result:T},null,2));break}case"tap-id":{let e=a[1];e||(console.error(S("tap-id","<id>")),process.exit(1));let t=JSON.stringify(e),s=await l.send({type:"evaluate",code:`(async () => {
463
451
  const t = window.__sootsimTest
464
452
  if (!t) return null
465
453
  const n = (await t.findByTestId(${t})) || (await t.findById(${t}))
@@ -494,10 +482,10 @@ ${o}
494
482
  },
495
483
  strategy: (resolved && resolved.strategy) || 'matched-node',
496
484
  }
497
- })()`});(!o||typeof o.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let r=await l.send({type:"tap",x:o.cx,y:o.cy});if(r?.hit!==!1&&r?.ok!==!1){let n=Ze(e,{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",n.step,n.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:r},null,2));break}case"type-into":{let e=a[1],t=a.slice(2).join(" ");(!e||!t)&&(console.error(v("type-into","<id> <text>")),process.exit(1));let o=JSON.stringify(e),r=await l.send({type:"evaluate",code:`(async () => {
485
+ })()`});(!s||typeof s.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1));let r=await l.send({type:"tap",x:s.cx,y:s.cy});if(r?.hit!==!1&&r?.ok!==!1){let n=ot(e,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",n.step,n.summary)}console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},result:r},null,2));break}case"type-into":{let e=a[1],t=a.slice(2).join(" ");(!e||!t)&&(console.error(S("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(e),r=await l.send({type:"evaluate",code:`(async () => {
498
486
  const t = window.__sootsimTest
499
487
  if (!t) return null
500
- const n = await (t.findByTestId(${o}) || t.findById(${o}))
488
+ const n = await (t.findByTestId(${s}) || t.findById(${s}))
501
489
  if (!n || !n.absolutePosition || !n.layout) return null
502
490
  return {
503
491
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
@@ -506,7 +494,7 @@ ${o}
506
494
  isTextInput: !!n.isTextInput,
507
495
  placeholder: n.placeholder || null,
508
496
  }
509
- })()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1)),r.isTextInput||console.error(` warning: ${e} is not a text input (isTextInput: false)`);let n=await l.send({type:"tap",x:r.cx,y:r.cy}),u=await It(l);u.visible||(console.error(` keyboard did not open after tapping ${e}`),process.exit(1));let m=u.focusedInput;m&&(m.testID===e||m.id===e||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(e)} but focus is on ${JSON.stringify(m.testID??m.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await l.send({type:"keyboard",action:"type",text:t}),await L("inspect type-into",{tapOn:{id:e},inputText:t},`type-into #${e} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:e,isTextInput:r.isTextInput,keyboardOpened:u.visible??n?.keyboardOpened??!1,focusedInput:u.focusedInput??null,typed:t},null,2));break}case"type":{let e=a.slice(1).join(" ");e||(console.error(v("type","<text>")),process.exit(1)),await le(l,"type"),await l.send({type:"keyboard",action:"type",text:e}),await L("inspect type",{inputText:e},`type ${JSON.stringify(e)}`),console.log(` typed: ${JSON.stringify(e)}`);break}case"key":{let e=a[1];e||(console.error(v("key","<name>")),process.exit(1)),await le(l,"key"),await l.send({type:"keyboard",action:"press",text:e}),await L("inspect key",{pressKey:e},`key ${e}`),console.log(` pressed: ${e}`);break}case"key-sequence":{let e=a.slice(1);e.length===0&&(console.error(v("key-sequence","<key> [<key> ...]")),process.exit(1)),await le(l,"key-sequence");for(let t of e)await l.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:e.join(" ")},`key-sequence ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"keycode":{let e=a.slice(1);e.length===0&&(console.error(v("keycode","<code> [<code> ...]")),process.exit(1));let t=e.map(r=>({code:r,key:Ft(r)})),o=t.filter(r=>!r.key);o.length>0&&(console.error(` unsupported keycode(s): ${o.map(r=>r.code).join(", ")}`),process.exit(1)),await le(l,"keycode");for(let r of t)await l.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"dispatch":{let e=a[1];e||(console.error(v("dispatch","<char>")),process.exit(1)),await l.send({type:"keyboard",action:"dispatchKey",text:e}),await L("inspect dispatch",{dispatchKey:e},`dispatch ${JSON.stringify(e)}`),console.log(` dispatched: ${e}`);break}case"dismiss":{await l.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let e=Number(a[1]),t=Number(a[2]),o=te(s);if(o){let m=await ae(l,o);m||(console.error(` not found: ${o.value}`),o.mode==="testid"&&Y("wait-selector-for-missing-testid",o.value),process.exit(1)),e=m.x,t=m.y}let r=a[3]?Number(a[3]):80;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(v("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let n=Math.max(0,Math.round(r)),u=await l.send({type:"evaluate",code:`(async () => {
497
+ })()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${e}`),process.exit(1)),r.isTextInput||console.error(` warning: ${e} is not a text input (isTextInput: false)`);let n=await l.send({type:"tap",x:r.cx,y:r.cy}),m=await Ot(l);m.visible||(console.error(` keyboard did not open after tapping ${e}`),process.exit(1));let p=m.focusedInput;p&&(p.testID===e||p.id===e||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(e)} but focus is on ${JSON.stringify(p.testID??p.id??null)}. did the tap land on an outer Pressable wrapper?`),process.exit(1))),await l.send({type:"keyboard",action:"type",text:t}),await L("inspect type-into",{tapOn:{id:e},inputText:t},`type-into #${e} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:e,isTextInput:r.isTextInput,keyboardOpened:m.visible??n?.keyboardOpened??!1,focusedInput:m.focusedInput??null,typed:t},null,2));break}case"type":{let e=a.slice(1).join(" ");e||(console.error(S("type","<text>")),process.exit(1)),await ue(l,"type"),await l.send({type:"keyboard",action:"type",text:e}),await L("inspect type",{inputText:e},`type ${JSON.stringify(e)}`),console.log(` typed: ${JSON.stringify(e)}`);break}case"key":{let e=a[1];e||(console.error(S("key","<name>")),process.exit(1)),await ue(l,"key"),await l.send({type:"keyboard",action:"press",text:e}),await L("inspect key",{pressKey:e},`key ${e}`),console.log(` pressed: ${e}`);break}case"key-sequence":{let e=a.slice(1);e.length===0&&(console.error(S("key-sequence","<key> [<key> ...]")),process.exit(1)),await ue(l,"key-sequence");for(let t of e)await l.send({type:"keyboard",action:"press",text:t});await L("inspect key-sequence",{pressKey:e.join(" ")},`key-sequence ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"keycode":{let e=a.slice(1);e.length===0&&(console.error(S("keycode","<code> [<code> ...]")),process.exit(1));let t=e.map(r=>({code:r,key:Et(r)})),s=t.filter(r=>!r.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(r=>r.code).join(", ")}`),process.exit(1)),await ue(l,"keycode");for(let r of t)await l.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${e.join(" ")}`),console.log(` pressed: ${e.join(", ")}`);break}case"dispatch":{let e=a[1];e||(console.error(S("dispatch","<char>")),process.exit(1)),await l.send({type:"keyboard",action:"dispatchKey",text:e}),await L("inspect dispatch",{dispatchKey:e},`dispatch ${JSON.stringify(e)}`),console.log(` dispatched: ${e}`);break}case"dismiss":{await l.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let p=await ce(l,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=p.x,t=p.y}let r=a[3]?Number(a[3]):80;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(S("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let n=Math.max(0,Math.round(r)),m=await l.send({type:"evaluate",code:`(async () => {
510
498
  const interact = window.__sootsimInteract
511
499
  if (interact?.doubleTap) {
512
500
  return {
@@ -529,18 +517,18 @@ ${o}
529
517
  first,
530
518
  second,
531
519
  }
532
- })()`});u?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:e,y:t,gapMs:n}},`double-tap @${e},${t}`),console.log(JSON.stringify(u,null,2));break}case"long-press":{let e=Number(a[1]),t=Number(a[2]),o=te(s);if(o){let u=await ae(l,o);u||(console.error(` not found: ${o.value}`),o.mode==="testid"&&Y("wait-selector-for-missing-testid",o.value),process.exit(1)),e=u.x,t=u.y}let r=a[3]?Number(a[3]):600;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(v("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let n=await l.send({type:"evaluate",code:`(async () => {
520
+ })()`});m?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:e,y:t,gapMs:n}},`double-tap @${e},${t}`),console.log(JSON.stringify(m,null,2));break}case"long-press":{let e=Number(a[1]),t=Number(a[2]),s=se(o);if(s){let m=await ce(l,s);m||(console.error(` not found: ${s.value}`),s.mode==="testid"&&U("wait-selector-for-missing-testid",s.value),process.exit(1)),e=m.x,t=m.y}let r=a[3]?Number(a[3]):600;(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(S("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let n=await l.send({type:"evaluate",code:`(async () => {
533
521
  const interact = window.__sootsimInteract
534
522
  if (!interact?.longPress) return { ok: false, reason: 'no interact.longPress' }
535
523
  const value = await interact.longPress(${e}, ${t}, ${Math.max(0,Math.round(r))})
536
524
  return { ok: !!value, value }
537
- })()`});n?.ok&&await L("inspect long-press",{tapAtCoords:{x:e,y:t}},`long-press @${e},${t}`),console.log(JSON.stringify(n,null,2));break}case"touch":{let e=a[1],t=Number(a[2]),o=Number(a[3]),r=a[4]?Number(a[4]):999,n=e==="down"?"touchDown":e==="move"?"touchMove":e==="up"?"touchUp":e==="cancel"?"touchCancel":null;n||(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),e!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(o))&&(console.error(v("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let u=e==="down"?"tap":e==="move"?"move":null,m=u&&Number.isFinite(t)&&Number.isFinite(o)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${u}', x: ${t}, y: ${o} } }));`:"",b=await l.send({type:"evaluate",code:`(async () => {
538
- ${m}
525
+ })()`});n?.ok&&await L("inspect long-press",{tapAtCoords:{x:e,y:t}},`long-press @${e},${t}`),console.log(JSON.stringify(n,null,2));break}case"touch":{let e=a[1],t=Number(a[2]),s=Number(a[3]),r=a[4]?Number(a[4]):999,n=e==="down"?"touchDown":e==="move"?"touchMove":e==="up"?"touchUp":e==="cancel"?"touchCancel":null;n||(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),e!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(S("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1));let m=e==="down"?"tap":e==="move"?"move":null,p=m&&Number.isFinite(t)&&Number.isFinite(s)?`window.dispatchEvent(new CustomEvent('sootsim:agentAction', { detail: { type: '${m}', x: ${t}, y: ${s} } }));`:"",h=await l.send({type:"evaluate",code:`(async () => {
526
+ ${p}
539
527
  const interact = window.__sootsimInteract
540
528
  if (!interact?.${n}) return { ok: false, reason: 'no interact.${n}' }
541
- const value = ${e==="cancel"?`await interact.${n}(${Math.max(1,Math.round(r))})`:`await interact.${n}(${t}, ${o}, ${Math.max(1,Math.round(r))})`}
529
+ const value = ${e==="cancel"?`await interact.${n}(${Math.max(1,Math.round(r))})`:`await interact.${n}(${t}, ${s}, ${Math.max(1,Math.round(r))})`}
542
530
  return { ok: !!value, value }
543
- })()`});b?.ok&&e!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:o}},`touch ${e} @${t},${o}`),console.log(JSON.stringify(b,null,2));break}case"gesture":{let e=a[1],t=a[2]?Number(a[2]):220;(!e||!Number.isFinite(t))&&(console.error(v("gesture","<preset> [durationMs]")),process.exit(1));let o=await l.send({type:"evaluate",code:`(async () => {
531
+ })()`});h?.ok&&e!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${e} @${t},${s}`),console.log(JSON.stringify(h,null,2));break}case"gesture":{let e=a[1],t=a[2]?Number(a[2]):220;(!e||!Number.isFinite(t))&&(console.error(S("gesture","<preset> [durationMs]")),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
544
532
  const spec = globalThis.__sootsimDeviceSpec || {}
545
533
  return {
546
534
  width: spec.width || window.innerWidth || 393,
@@ -548,12 +536,12 @@ ${o}
548
536
  statusBarHeight: spec.statusBarHeight || 0,
549
537
  homeIndicatorHeight: spec.homeIndicatorHeight || 0,
550
538
  }
551
- })()`}),r=Number(o?.width)||393,n=Number(o?.height)||852,u=Number(o?.statusBarHeight)||0,m=Number(o?.homeIndicatorHeight)||0,b=Math.round(r/2),p=Math.round(n/2),w=Math.max(24,u+18),O=Math.max(24,m+18),D=18,I=Math.min(220,Math.round(n*.24)),N=Math.min(180,Math.round(r*.32)),A=b,W=p,g=b,M=p;switch(e){case"scroll-up":W=p+Math.round(I/2),M=p-Math.round(I/2);break;case"scroll-down":W=p-Math.round(I/2),M=p+Math.round(I/2);break;case"scroll-left":A=b+Math.round(N/2),g=b-Math.round(N/2);break;case"scroll-right":A=b-Math.round(N/2),g=b+Math.round(N/2);break;case"swipe-from-left-edge":A=D,W=p,g=Math.min(r-D,D+N);break;case"swipe-from-right-edge":A=r-D,W=p,g=Math.max(D,r-D-N);break;case"swipe-from-top-edge":A=b,W=w,M=Math.min(n-O,w+I);break;case"swipe-from-bottom-edge":A=b,W=n-O,M=Math.max(w,n-O-I);break;default:console.error(` unknown gesture preset: ${e}`),process.exit(1)}let F=Math.max(8,Math.round(t/16)),P=Math.max(1,Math.round(t/F)),se=await l.send({type:"evaluate",code:`(async () => {
539
+ })()`}),r=Number(s?.width)||393,n=Number(s?.height)||852,m=Number(s?.statusBarHeight)||0,p=Number(s?.homeIndicatorHeight)||0,h=Math.round(r/2),f=Math.round(n/2),w=Math.max(24,m+18),O=Math.max(24,p+18),B=18,N=Math.min(220,Math.round(n*.24)),M=Math.min(180,Math.round(r*.32)),F=h,W=f,g=h,T=f;switch(e){case"scroll-up":W=f+Math.round(N/2),T=f-Math.round(N/2);break;case"scroll-down":W=f-Math.round(N/2),T=f+Math.round(N/2);break;case"scroll-left":F=h+Math.round(M/2),g=h-Math.round(M/2);break;case"scroll-right":F=h-Math.round(M/2),g=h+Math.round(M/2);break;case"swipe-from-left-edge":F=B,W=f,g=Math.min(r-B,B+M);break;case"swipe-from-right-edge":F=r-B,W=f,g=Math.max(B,r-B-M);break;case"swipe-from-top-edge":F=h,W=w,T=Math.min(n-O,w+N);break;case"swipe-from-bottom-edge":F=h,W=n-O,T=Math.max(w,n-O-N);break;default:console.error(` unknown gesture preset: ${e}`),process.exit(1)}let _=Math.max(8,Math.round(t/16)),P=Math.max(1,Math.round(t/_)),re=await l.send({type:"evaluate",code:`(async () => {
552
540
  const interact = window.__sootsimInteract
553
541
  if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
554
- const value = await interact.drag(${A}, ${W}, ${g}, ${M}, ${F}, ${P})
542
+ const value = await interact.drag(${F}, ${W}, ${g}, ${T}, ${_}, ${P})
555
543
  return { ok: !!value, value }
556
- })()`});se?.ok&&await L("inspect gesture",{swipe:{start:`${A}, ${W}`,end:`${g}, ${M}`,duration:Math.max(1,Math.round(t))}},`gesture ${e}`),console.log(JSON.stringify({preset:e,from:{x:A,y:W},to:{x:g,y:M},result:se},null,2));break}case"scroll":{let e=te(s),t=e?.mode==="testid"?e.value:a[1],o=Number(a[e?1:2]),r=Number(a[e?2:3]);(!t||!Number.isFinite(o)||!Number.isFinite(r))&&(console.error(v("scroll","<id> <dx> <dy> | --testid <id> <dx> <dy>")),process.exit(1));let n=await l.send({type:"evaluate",code:`(async () => {
544
+ })()`});re?.ok&&await L("inspect gesture",{swipe:{start:`${F}, ${W}`,end:`${g}, ${T}`,duration:Math.max(1,Math.round(t))}},`gesture ${e}`),console.log(JSON.stringify({preset:e,from:{x:F,y:W},to:{x:g,y:T},result:re},null,2));break}case"scroll":{let e=se(o),t=e?.mode==="testid"?e.value:a[1],s=Number(a[e?1:2]),r=Number(a[e?2:3]);(!t||!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(S("scroll","<id> <dx> <dy> | --testid <id> <dx> <dy>")),process.exit(1));let n=await l.send({type:"evaluate",code:`(async () => {
557
545
  const t = window.__sootsimTest
558
546
  if (!t) return null
559
547
  const n = await t.findByTestId(${JSON.stringify(t)})
@@ -563,11 +551,11 @@ ${o}
563
551
  cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
564
552
  cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
565
553
  }
566
- })()`}),u=await K(l,"scrollTo",t,o,r,!1);u?.ok&&await L("inspect scroll",{scrollTo:{id:t,x:o,y:r}},`scroll ${t} -> ${o},${r}`),console.log(JSON.stringify({...u,...n?{at:{x:n.cx,y:n.cy}}:{}},null,2));break}case"state":{let e=a[1];if(i==="get"&&!e){let o=await K(l,"getSessionState"),r=await l.send({type:"evaluate",code:`({
554
+ })()`}),m=await z(l,"scrollTo",t,s,r,!1);m?.ok&&await L("inspect scroll",{scrollTo:{id:t,x:s,y:r}},`scroll ${t} -> ${s},${r}`),console.log(JSON.stringify({...m,...n?{at:{x:n.cx,y:n.cy}}:{}},null,2));break}case"state":{let e=a[1];if(i==="get"&&!e){let s=await z(l,"getSessionState"),r=await l.send({type:"evaluate",code:`({
567
555
  errors: window.__sootsimConsole?.getErrors?.()?.length ?? 0,
568
556
  warnings: window.__sootsimConsole?.getWarnings?.()?.length ?? 0,
569
- })`});o&&typeof o=="object"&&o.diagnostics&&(o.diagnostics.errors=r?.errors??0,o.diagnostics.warnings=r?.warnings??0),console.log(JSON.stringify(o,null,2));break}if(!e||e==="--help"||e==="-h"){console.log(`
570
- ${f("state")} \u2014 dump raw runtime state
557
+ })`});s&&typeof s=="object"&&s.diagnostics&&(s.diagnostics.errors=r?.errors??0,s.diagnostics.warnings=r?.warnings??0),console.log(JSON.stringify(s,null,2));break}if(!e||e==="--help"||e==="-h"){console.log(`
558
+ ${y("state")} \u2014 dump raw runtime state
571
559
 
572
560
  subcommands:
573
561
  shell dump shell transition/layout state
@@ -581,15 +569,15 @@ ${o}
581
569
  gesture <x> <y> dump gesture routing/debug info at coordinates
582
570
 
583
571
  examples:
584
- ${f("state")} shell
585
- ${f("state")} worker
586
- ${f("state")} keyboard
587
- ${f("state")} ownership
588
- ${f("state")} node photos
589
- ${f("state")} scroll feed
590
- ${f("state")} scroll-hit 360 420
591
- ${f("state")} hit 200 720
592
- `);break}let t;switch(e){case"shell":t=await X(l,500);break;case"worker":t=await Te(l,"__sootsimRenderHost.queryStats");break;case"ownership":t=await l.send({type:"evaluate",code:`(() => {
572
+ ${y("state")} shell
573
+ ${y("state")} worker
574
+ ${y("state")} keyboard
575
+ ${y("state")} ownership
576
+ ${y("state")} node photos
577
+ ${y("state")} scroll feed
578
+ ${y("state")} scroll-hit 360 420
579
+ ${y("state")} hit 200 720
580
+ `);break}let t;switch(e){case"shell":t=await V(l,500);break;case"worker":t=await ve(l,"__sootsimRenderHost.queryStats");break;case"ownership":t=await l.send({type:"evaluate",code:`(() => {
593
581
  const h = window.__sootsimRenderHost
594
582
  if (!h || typeof h.getOwnershipSnapshot !== 'function') {
595
583
  return { error: 'getOwnershipSnapshot not available' }
@@ -620,8 +608,8 @@ ${o}
620
608
  text: focused.text || null,
621
609
  } : null,
622
610
  }
623
- })()`});break;case"node":{let o=a[2];o||(console.error(` usage: ${f("state")} node <id>`),process.exit(1)),t=await K(l,"findByTestId",o)||await K(l,"findById",o);break}case"scroll":{let o=a[2];o||(console.error(` usage: ${f("state")} scroll <id>`),process.exit(1)),t=await K(l,"getScrollState",o);break}case"scroll-hit":{let o=Number(a[2]),r=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(r))&&(console.error(` usage: ${f("state")} scroll-hit <x> <y>`),process.exit(1)),t=await K(l,"getScrollStateAt",o,r);break}case"hit":{let o=Number(a[2]),r=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(r))&&(console.error(` usage: ${f("state")} hit <x> <y>`),process.exit(1)),t=await K(l,"debugHitAt",o,r);break}case"gesture":{let o=Number(a[2]),r=Number(a[3]);(!Number.isFinite(o)||!Number.isFinite(r))&&(console.error(` usage: ${f("state")} gesture <x> <y>`),process.exit(1)),t=await K(l,"debugGestureAt",o,r);break}default:console.error(` unknown state subcommand: ${e}`),process.exit(1)}console.log(JSON.stringify(t,null,2));break}case"shell":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
624
- ${f("shell")} \u2014 run built-in shell commands
611
+ })()`});break;case"node":{let s=a[2];s||(console.error(` usage: ${y("state")} node <id>`),process.exit(1)),t=await z(l,"findByTestId",s)||await z(l,"findById",s);break}case"scroll":{let s=a[2];s||(console.error(` usage: ${y("state")} scroll <id>`),process.exit(1)),t=await z(l,"getScrollState",s);break}case"scroll-hit":{let s=Number(a[2]),r=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${y("state")} scroll-hit <x> <y>`),process.exit(1)),t=await z(l,"getScrollStateAt",s,r);break}case"hit":{let s=Number(a[2]),r=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${y("state")} hit <x> <y>`),process.exit(1)),t=await z(l,"debugHitAt",s,r);break}case"gesture":{let s=Number(a[2]),r=Number(a[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${y("state")} gesture <x> <y>`),process.exit(1)),t=await z(l,"debugGestureAt",s,r);break}default:console.error(` unknown state subcommand: ${e}`),process.exit(1)}console.log(JSON.stringify(t,null,2));break}case"shell":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
612
+ ${y("shell")} \u2014 run built-in shell commands
625
613
 
626
614
  subcommands:
627
615
  launch <appId> [waitMs] [--clear-state]
@@ -636,15 +624,15 @@ ${o}
636
624
  shake trigger the simulator shake gesture
637
625
 
638
626
  examples:
639
- ${f("shell")} launch photos
640
- ${f("shell")} launch rn --clear-state
641
- ${f("shell")} launch photos 1500
642
- ${f("shell")} home 500
643
- ${f("shell")} switcher 800
644
- ${f("shell")} open-card clock 800
645
- ${f("shell")} appearance dark
646
- ${f("shell")} lock
647
- `);break}let t=e==="launch"||e==="open-card"||e==="home"||e==="switcher",o=e==="launch"||e==="open-card"?a[3]:a[2],r=o?Number(o):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(v("shell",e==="launch"||e==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let n=!1,u=!1,m=null,b=s.includes("--clear-state");if(e==="launch"){let p=a[2];p||(console.error(v("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),b&&await l.send({type:"evaluate",code:be}),n=!!await Q(l,"launchApp",r,p),{settled:u,state:m}=await ie(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===p&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),n&&await L("inspect shell launch",b?{launchApp:{clearState:!0}}:{launchApp:{}},b?"launch app (clear state)":"launch app")}else if(e==="home")n=!!await Q(l,"goHome",r),{settled:u,state:m}=await ie(l,Math.round(r),p=>!!p&&p.state==="home"&&p.activeApp==null&&p.showSwitcher===!1&&p.switcherPhase==="idle"&&typeof p.launchProgress=="number"&&p.launchProgress>=.98);else if(e==="switcher")n=!!await Q(l,"openSwitcher",r),{settled:u,state:m}=await ie(l,Math.round(r),p=>!!p&&p.state==="app"&&p.showSwitcher===!0&&p.switcherPhase==="idle"&&typeof p.zoomLevel=="number"&&Math.abs(p.zoomLevel)<=.02&&typeof p.horizontalZoom=="number"&&Math.abs(p.horizontalZoom)<=.02),u&&(await z(_t),m=await X(l));else if(e==="open-card"){let p=a[2];p||(console.error(v("shell","open-card <appId> [settleMs]")),process.exit(1)),n=!!await Q(l,"openSwitcherCard",r,p),{settled:u,state:m}=await ie(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===p&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),n&&await L("inspect shell open-card",{openSwitcherCard:{appId:p}},`open switcher card ${p}`)}else if(e==="appearance"){let p=a[2];(!p||!["light","dark","auto","toggle"].includes(p))&&(console.error(v("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await Ve(l,"appearance",p);n=!!w?.ok,m={appearance:w}}else if(e==="lock"||e==="shake"){let p=await Ve(l,e);n=!!p?.ok,m={[e]:p}}else console.error(` unknown shell subcommand: ${e}`),process.exit(1);console.log(JSON.stringify({ok:n,settled:u,state:m},null,2));break}case"url":{await qe(l,{args:d});break}case"reload":{let o=!1,r=!1;try{await l.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let m=await l.send({type:"evaluate",code:`;(() => {
627
+ ${y("shell")} launch photos
628
+ ${y("shell")} launch rn --clear-state
629
+ ${y("shell")} launch photos 1500
630
+ ${y("shell")} home 500
631
+ ${y("shell")} switcher 800
632
+ ${y("shell")} open-card clock 800
633
+ ${y("shell")} appearance dark
634
+ ${y("shell")} lock
635
+ `);break}let t=e==="launch"||e==="open-card"||e==="home"||e==="switcher",s=e==="launch"||e==="open-card"?a[3]:a[2],r=s?Number(s):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(S("shell",e==="launch"||e==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let n=!1,m=!1,p=null,h=o.includes("--clear-state");if(e==="launch"){let f=a[2];f||(console.error(S("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),h&&await l.send({type:"evaluate",code:Te}),n=!!await te(l,"launchApp",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),n&&await L("inspect shell launch",h?{launchApp:{clearState:!0}}:{launchApp:{}},h?"launch app (clear state)":"launch app")}else if(e==="home")n=!!await te(l,"goHome",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(e==="switcher")n=!!await te(l,"openSwitcher",r),{settled:m,state:p}=await de(l,Math.round(r),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),m&&(await Y(Pt),p=await V(l));else if(e==="open-card"){let f=a[2];f||(console.error(S("shell","open-card <appId> [settleMs]")),process.exit(1)),n=!!await te(l,"openSwitcherCard",r,f),{settled:m,state:p}=await de(l,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),n&&await L("inspect shell open-card",{openSwitcherCard:{appId:f}},`open switcher card ${f}`)}else if(e==="appearance"){let f=a[2];(!f||!["light","dark","auto","toggle"].includes(f))&&(console.error(S("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await tt(l,"appearance",f);n=!!w?.ok,p={appearance:w}}else if(e==="lock"||e==="shake"){let f=await tt(l,e);n=!!f?.ok,p={[e]:f}}else console.error(` unknown shell subcommand: ${e}`),process.exit(1);console.log(JSON.stringify({ok:n,settled:m,state:p},null,2));break}case"url":{await Ke(l,{args:d});break}case"reload":{let s=!1,r=!1;try{await l.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await l.send({type:"evaluate",code:`;(() => {
648
636
  const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
649
637
  if (typeof reloadExternalApp === 'function') {
650
638
  reloadExternalApp()
@@ -652,10 +640,10 @@ ${o}
652
640
  }
653
641
  window.location.reload()
654
642
  return { kind: 'page' }
655
- })()`});r=!!m&&m.kind==="external-app",o=!0}catch{}console.log(" reloading...");let n=l,u=null;if(r)u=await ue(l,{timeoutMs:1e4,errorGraceMs:3e3});else{o&&await z(300);let m=await Ne(_,C,k,{timeoutMs:1e4});m?(n=m,u=await ue(m,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),n=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(n)try{let m=await n.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(n!==l&&n.close(),Array.isArray(m)&&m.length>0){console.log(`
656
- \u26A0 ${m.length} error(s) during mount:
657
- `);for(let b of m){let p=b.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${p}`),b.stack){let w=b.stack.split(`
658
- `).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}u&&!u.ready&&(process.exitCode=1);break}case"eval":case"js":{let e=a.slice(1).join(" ");e||(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(` ${f("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${f("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${f("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${f("js")} SootSim.state.root.children.length`),process.exit(1));let t=e;t.startsWith("(async")||(t=`(async () => ${t})()`);let o=await l.send({type:"evaluate",code:t});console.log(JSON.stringify(o,null,2));let r=e.toLowerCase(),n=[];(r.includes("sootsim:gohome")||r.includes("gohome"))&&n.push("sootsim shell home"),(r.includes("sootsim:appswitcher")||r.includes("appswitcher"))&&n.push("sootsim shell switcher"),(r.includes("keyboard.isvisible")||r.includes("keyboard.getmode"))&&n.push("sootsim debug state keyboard"),r.includes("interact.tap")&&n.push("sootsim do tap <x> <y>"),r.includes("keyboard.type")&&n.push("sootsim do type <text>"),(r.includes("keyboard.press")||r.includes("keyboard.dispatchkey"))&&n.push("sootsim do key <name>"),r.includes("keyboard.dismiss")&&n.push("sootsim do dismiss"),r.includes("dumptree")&&n.push("sootsim get tree"),r.includes("dumpaccessibilitytree")&&n.push("sootsim get a11y"),r.includes("getnodecount")&&n.push("sootsim get count"),r.includes("findbytext")&&n.push("sootsim find <text>"),(r.includes("findbytestid")||r.includes("findbyid"))&&n.push("sootsim find --testid <id>"),r.includes("document.hidden")&&n.push("sootsim debug state keyboard (includes tab health)"),n.length>0&&Y("prefer-cli-over-eval",n);break}case"globals":{let e=await l.send({type:"evaluate",code:`(async () => {
643
+ })()`});r=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let n=l,m=null;if(r)m=await fe(l,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await Y(300);let p=await Fe(A,j,v,{timeoutMs:1e4});p?(n=p,m=await fe(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),n=null)}if(m)if(m.ready){let p=m.source==="nodes-fallback"?" (no ready signal, node-count fallback)":"";console.log(` ready in ${m.elapsedMs}ms: ${m.nodes} nodes${p}`)}else m.source==="error-bail"?console.log(` \u26A0 reload bailed after ${m.elapsedMs}ms: ${m.errors} console error(s), ready signal never fired`):console.log(` \u26A0 reload timed out after ${m.elapsedMs}ms (${m.nodes} nodes, ${m.errors} errors)`);if(n)try{let p=await n.send({type:"evaluate",code:"window.__sootsimConsole?.getErrors(10) || []"});if(n!==l&&n.close(),Array.isArray(p)&&p.length>0){console.log(`
644
+ \u26A0 ${p.length} error(s) during mount:
645
+ `);for(let h of p){let f=h.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),h.stack){let w=h.stack.split(`
646
+ `).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}m&&!m.ready&&(process.exitCode=1);break}case"eval":case"js":{let e=a.slice(1).join(" ");e||(console.error(S("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(` ${y("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${y("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${y("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${y("js")} SootSim.state.root.children.length`),process.exit(1));let t=e;t.startsWith("(async")||(t=`(async () => ${t})()`);let s=await l.send({type:"evaluate",code:t});console.log(JSON.stringify(s,null,2));let r=e.toLowerCase(),n=[];(r.includes("sootsim:gohome")||r.includes("gohome"))&&n.push("sootsim shell home"),(r.includes("sootsim:appswitcher")||r.includes("appswitcher"))&&n.push("sootsim shell switcher"),(r.includes("keyboard.isvisible")||r.includes("keyboard.getmode"))&&n.push("sootsim debug state keyboard"),r.includes("interact.tap")&&n.push("sootsim do tap <x> <y>"),r.includes("keyboard.type")&&n.push("sootsim do type <text>"),(r.includes("keyboard.press")||r.includes("keyboard.dispatchkey"))&&n.push("sootsim do key <name>"),r.includes("keyboard.dismiss")&&n.push("sootsim do dismiss"),r.includes("dumptree")&&n.push("sootsim get tree"),r.includes("dumpaccessibilitytree")&&n.push("sootsim get a11y"),r.includes("getnodecount")&&n.push("sootsim get count"),r.includes("findbytext")&&n.push("sootsim find <text>"),(r.includes("findbytestid")||r.includes("findbyid"))&&n.push("sootsim find --testid <id>"),r.includes("document.hidden")&&n.push("sootsim debug state keyboard (includes tab health)"),n.length>0&&U("prefer-cli-over-eval",n);break}case"globals":{let e=await l.send({type:"evaluate",code:`(async () => {
659
647
  const globals = {}
660
648
 
661
649
  // test bridge (proxy in worker mode)
@@ -693,8 +681,8 @@ ${o}
693
681
 
694
682
  return globals
695
683
  })()`});console.log(` sootsim JS API:
696
- `);for(let[t,o]of Object.entries(e)){console.log(` ${t}:`);for(let r of o)console.log(` .${r}`);console.log("")}console.log(` use: ${f("js")} <expression>`),console.log(` example: ${f("js")} test.findByText("Sign in")`);break}case"describe":{await Pe({bridge:l,args:s,positional:a});break}case"perf":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
697
- ${f("perf")} \u2014 performance profiling
684
+ `);for(let[t,s]of Object.entries(e)){console.log(` ${t}:`);for(let r of s)console.log(` .${r}`);console.log("")}console.log(` use: ${y("js")} <expression>`),console.log(` example: ${y("js")} test.findByText("Sign in")`);break}case"describe":{await Re({bridge:l,args:o,positional:a});break}case"perf":{let e=a[1];if(!e||e==="--help"||e==="-h"){console.log(`
685
+ ${y("perf")} \u2014 performance profiling
698
686
 
699
687
  subcommands:
700
688
  stats one-shot stats (zero overhead query)
@@ -704,11 +692,11 @@ ${o}
704
692
  transition <e> profile a shell transition (goHome, appSwitcher, lockScreen)
705
693
 
706
694
  examples:
707
- ${f("perf")} stats
708
- ${f("perf")} start
695
+ ${y("perf")} stats
696
+ ${y("perf")} start
709
697
  # ... interact with the app ...
710
- ${f("perf")} stop
711
- ${f("perf")} transition goHome
698
+ ${y("perf")} stop
699
+ ${y("perf")} transition goHome
712
700
  `);break}switch(e){case"stats":{let t=await l.send({type:"evaluate",code:`(async () => {
713
701
  // worker mode (host exposes these)
714
702
  if (window.__sootsimPerfStats) {
@@ -734,7 +722,7 @@ ${o}
734
722
  jankFrames: frameStats.recentFrames?.filter(f => f > 16.67).length || 0,
735
723
  recentCount: frameStats.recentFrames?.length || 0,
736
724
  }
737
- })()`});t.error&&(console.error(` error: ${t.error}`),process.exit(1));let o=t.avgMs!=="?"?(1e3/parseFloat(t.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${t.frames}`),console.log(` avg: ${t.avgMs}ms (${o} fps)`),console.log(` max: ${t.maxMs}ms`),console.log(` layout: ${t.layoutMs}ms total`),console.log(` nodes: ${t.nodeCount}`),t.recentCount>0&&console.log(` jank: ${t.jankFrames}/${t.recentCount} frames >16.67ms`);break}case"start":{await l.send({type:"evaluate",code:`(async () => {
725
+ })()`});t.error&&(console.error(` error: ${t.error}`),process.exit(1));let s=t.avgMs!=="?"?(1e3/parseFloat(t.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${t.frames}`),console.log(` avg: ${t.avgMs}ms (${s} fps)`),console.log(` max: ${t.maxMs}ms`),console.log(` layout: ${t.layoutMs}ms total`),console.log(` nodes: ${t.nodeCount}`),t.recentCount>0&&console.log(` jank: ${t.jankFrames}/${t.recentCount} frames >16.67ms`);break}case"start":{await l.send({type:"evaluate",code:`(async () => {
738
726
  // worker mode
739
727
  if (window.__sootsimPerfStart && window.__sootsimRenderHost) {
740
728
  const result = window.__sootsimPerfStart()
@@ -756,7 +744,7 @@ ${o}
756
744
  startedAt: performance.now(),
757
745
  }
758
746
  return { started: true }
759
- })()`}),console.log(` profiling started \u2014 interact with the app, then run '${f("perf")} stop'`);break}case"stop":{let t=await l.send({type:"evaluate",code:`(async () => {
747
+ })()`}),console.log(` profiling started \u2014 interact with the app, then run '${y("perf")} stop'`);break}case"stop":{let t=await l.send({type:"evaluate",code:`(async () => {
760
748
  // worker mode
761
749
  if (window.__sootsimRenderHost) {
762
750
  const session = window.${G} || {}
@@ -850,8 +838,8 @@ ${o}
850
838
  jankFrames: recent.filter(f => f > 16.67).length,
851
839
  sampleCount: recent.length,
852
840
  }
853
- })()`});t.error&&(console.error(` error: ${t.error}`),process.exit(1));let o=t.avgMs>0?(1e3/t.avgMs).toFixed(1):"?",r=t.sampleCount>0?(t.jankFrames/t.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
854
- `),console.log(` frames: ${t.frames}`),console.log(` total: ${t.totalMs.toFixed(1)}ms`),console.log(` avg: ${t.avgMs.toFixed(2)}ms (${o} fps)`),console.log(` max: ${t.maxMs.toFixed(2)}ms`),console.log(""),t.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${t.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${t.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${t.copyAvgMs.toFixed(2)}ms`),t.auxAvgMs!==void 0&&console.log(` aux: ${t.auxAvgMs.toFixed(2)}ms`),t.otherAvgMs!==void 0&&console.log(` other: ${t.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${t.sampleCount} samples):`),console.log(` p50: ${t.p50.toFixed(2)}ms`),console.log(` p95: ${t.p95.toFixed(2)}ms`),console.log(` p99: ${t.p99.toFixed(2)}ms`),console.log(` jank: ${t.jankFrames} frames (${r}%) >16.67ms`);break}case"frames":{let t=a[2]?Number(a[2]):50;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let o=await l.send({type:"evaluate",code:`(async () => {
841
+ })()`});t.error&&(console.error(` error: ${t.error}`),process.exit(1));let s=t.avgMs>0?(1e3/t.avgMs).toFixed(1):"?",r=t.sampleCount>0?(t.jankFrames/t.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
842
+ `),console.log(` frames: ${t.frames}`),console.log(` total: ${t.totalMs.toFixed(1)}ms`),console.log(` avg: ${t.avgMs.toFixed(2)}ms (${s} fps)`),console.log(` max: ${t.maxMs.toFixed(2)}ms`),console.log(""),t.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${t.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${t.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${t.copyAvgMs.toFixed(2)}ms`),t.auxAvgMs!==void 0&&console.log(` aux: ${t.auxAvgMs.toFixed(2)}ms`),t.otherAvgMs!==void 0&&console.log(` other: ${t.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${t.sampleCount} samples):`),console.log(` p50: ${t.p50.toFixed(2)}ms`),console.log(` p95: ${t.p95.toFixed(2)}ms`),console.log(` p99: ${t.p99.toFixed(2)}ms`),console.log(` jank: ${t.jankFrames} frames (${r}%) >16.67ms`);break}case"frames":{let t=a[2]?Number(a[2]):50;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
855
843
  if (window.__sootsimRenderHost) {
856
844
  const session = window.${G} || {}
857
845
  if (session.active) {
@@ -886,7 +874,7 @@ ${o}
886
874
  mode: 'main-thread',
887
875
  frames: (stats.recentFrames || []).slice(-${t}),
888
876
  }
889
- })()`});if(o.error&&(console.error(` error: ${o.error}`),process.exit(1)),o.mode==="render-worker"){let n=Array.isArray(o.samples)?o.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${f("perf")} start' first`);break}console.log(` last ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,b,p,w,O,D]of n)console.log(` ${m.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${p.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${D.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);console.log(""),fe(n.map(u=>u[1])),o.live&&console.log(" sampling continues");break}let r=Array.isArray(o.frames)?o.frames:Array.isArray(o)?o:[];if(r.length===0){console.log(` no frame data \u2014 run '${f("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`),fe(r);break}case"worst":{let t=a[2]?Number(a[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let o=await l.send({type:"evaluate",code:`(async () => {
877
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,h,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);console.log(""),be(n.map(m=>m[1])),s.live&&console.log(" sampling continues");break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`),be(r);break}case"worst":{let t=a[2]?Number(a[2]):20;(!Number.isFinite(t)||t<=0)&&(console.error(` error: expected a positive frame count, got "${a[2]}"`),process.exit(1));let s=await l.send({type:"evaluate",code:`(async () => {
890
878
  if (window.__sootsimRenderHost) {
891
879
  const session = window.${G} || {}
892
880
  if (session.active) {
@@ -928,8 +916,8 @@ ${o}
928
916
  mode: 'main-thread',
929
917
  frames: recent.slice().sort((a, b) => b - a).slice(0, ${t}),
930
918
  }
931
- })()`});if(o.error&&(console.error(` error: ${o.error}`),process.exit(1)),o.mode==="render-worker"){let n=Array.isArray(o.samples)?o.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${f("perf")} start' first`);break}console.log(` worst ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[u,m,b,p,w,O,D]of n)console.log(` ${m.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${p.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${D.toFixed(2).padStart(7)} ${String(u).padStart(5)}`);o.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(o.frames)?o.frames:Array.isArray(o)?o:[];if(r.length===0){console.log(` no frame data \u2014 run '${f("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`);break}case"transition":{let t=a[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
932
- ${f("perf")} transition <event> \u2014 profile a shell transition
919
+ })()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),s.mode==="render-worker"){let n=Array.isArray(s.samples)?s.samples:[];if(n.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${n.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[m,p,h,f,w,O,B]of n)console.log(` ${p.toFixed(2).padStart(7)} ${h.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${B.toFixed(2).padStart(7)} ${String(m).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${y("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(n=>n.toFixed(2)).join(", ")}`);break}case"transition":{let t=a[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
920
+ ${y("perf")} transition <event> \u2014 profile a shell transition
933
921
 
934
922
  events:
935
923
  goHome swipe-to-home animation
@@ -939,8 +927,8 @@ ${o}
939
927
  note: uses 600ms capture window \u2014 may need --timeout 10000 flag
940
928
 
941
929
  examples:
942
- ${f("perf")} transition goHome --timeout 10000
943
- ${f("perf")} transition appSwitcher
930
+ ${y("perf")} transition goHome --timeout 10000
931
+ ${y("perf")} transition appSwitcher
944
932
  `);break}let r=`sootsim:${t}`;console.log(` profiling ${t} transition...`),console.log(" (use --timeout 10000 if this times out)");let n=await l.send({type:"evaluate",code:`(async () => {
945
933
  // only supported in render-worker mode
946
934
  if (!window.__sootsimRenderHost) {
@@ -1000,11 +988,11 @@ ${o}
1000
988
  jankFrames: frameTimes.filter(f => f > 16.67).length,
1001
989
  samples,
1002
990
  }
1003
- })()`});if(n.error&&(console.error(` error: ${n.error}`),process.exit(1)),n.warning&&console.log(` warning: ${n.warning}`),n.frames===0){console.log(" no frames captured");break}let u=n.avgMs>0?(1e3/n.avgMs).toFixed(1):"?",m=n.frames>0?(n.jankFrames/n.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
991
+ })()`});if(n.error&&(console.error(` error: ${n.error}`),process.exit(1)),n.warning&&console.log(` warning: ${n.warning}`),n.frames===0){console.log(" no frames captured");break}let m=n.avgMs>0?(1e3/n.avgMs).toFixed(1):"?",p=n.frames>0?(n.jankFrames/n.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
1004
992
 
1005
993
  frames: ${n.frames}
1006
994
  total: ${n.totalMs.toFixed(1)}ms
1007
- avg: ${n.avgMs.toFixed(2)}ms (${u} fps)
995
+ avg: ${n.avgMs.toFixed(2)}ms (${m} fps)
1008
996
  max: ${n.maxMs.toFixed(2)}ms
1009
997
 
1010
998
  breakdown (avg per frame):
@@ -1018,25 +1006,25 @@ ${o}
1018
1006
  p50: ${n.p50.toFixed(2)}ms
1019
1007
  p95: ${n.p95.toFixed(2)}ms
1020
1008
  p99: ${n.p99.toFixed(2)}ms
1021
- jank: ${n.jankFrames} frames (${m}%) >16.67ms`),Array.isArray(n.samples)&&n.samples.length>0&&(console.log(""),fe(n.samples.map(b=>b[1])));break}default:console.error(` unknown perf subcommand: ${e}`),process.exit(1)}break}case"errors":{let e=a[1];if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimConsole?.clear(); "cleared"'}),B(d)?q({cleared:!0}):console.log(" error buffer cleared");break}let t=e?Number(e):20,o=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getErrors(${t}) || []`}),r=Array.isArray(o)?o:[];if(B(d)){q(r);break}if(r.length===0){console.log(" no errors captured");break}console.log(` ${r.length} error(s):
1022
- `);for(let n of r){let u=new Date(n.timestamp).toLocaleTimeString(),m=n.args.map(b=>typeof b=="object"?JSON.stringify(b):b).join(" ");if(console.log(` [${u}] ${m}`),n.stack){let b=n.stack.split(`
1023
- `).slice(0,3);for(let p of b)console.log(` ${p.trim()}`)}}break}case"warnings":{let e=a[1]?Number(a[1]):20,t=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getWarnings(${e}) || []`}),o=Array.isArray(t)?t:[];if(B(d)){q(o);break}if(o.length===0){console.log(" no warnings captured");break}console.log(` ${o.length} warning(s):
1024
- `);for(let r of o){let n=new Date(r.timestamp).toLocaleTimeString(),u=r.args.map(m=>typeof m=="object"?JSON.stringify(m):m).join(" ");console.log(` [${n}] ${u}`)}break}case"animations":{let e=await K(l,"listAnimations")??[];if(s.includes("--json")){console.log(JSON.stringify(e,null,2));break}if(e.length===0){console.log(" no active animations");break}console.log(` ${e.length} active animation(s):
1025
- `);for(let t of e){let o=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,n=Number(t.current??0).toFixed(2),u=`${Math.round((t.progress??0)*100)}%`,m=`${Math.round(t.elapsedMs??0)}ms`,b=t.loop?" loop":"",p=t.layoutBound?" layout":"";console.log(` #${t.id} ${o} ${r.padEnd(14)} cur=${n.padEnd(7)} ${u.padStart(4)} ${m}${b}${p}`)}break}case"animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${f("animation")} <id>`),process.exit(1));let t=Number(e);Number.isFinite(t)||(console.error(` invalid id: ${e}`),process.exit(1));let o=await K(l,"getAnimation",t);console.log(JSON.stringify(o,null,2));break}case"stop-animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${f("stop-animation")} <id|all>`),process.exit(1));let t=e==="all"?"all":Number(e);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${e}`),process.exit(1));let o=await K(l,"stopAnimation",t);console.log(` stopped ${o??0} animation(s)`);break}case"requests":{let e=a[1];if(e==="clear"){await K(l,"clearRequests"),B(d)?q({cleared:!0}):console.log(" request buffer cleared");break}let t=e==="all",o=t?a[2]:e,r=o?Number(o):20,n=t?await K(l,"getRequests",r):await K(l,"getFailedRequests",r),u=Array.isArray(n)?n:[];if(B(d)){q(u);break}if(u.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${u.length} ${t?"request(s)":"failed request(s)"}:
1026
- `);for(let m of u){let b=new Date(m.timestamp).toLocaleTimeString();console.log(` [${b}] ${H(m)}`),m.responseBody?console.log(` ${m.responseBody}`):m.error&&console.log(` ${m.error}`)}break}case"network":{let e=a[1],t=null,o=null,r=!1,n=!1,u=!1;for(let I=0;I<d.length;I++){let N=d[I];if(N==="--filter")t=d[I+1]??null,I++;else if(N==="--limit"){let A=Number(d[I+1]);Number.isFinite(A)&&(o=A),I++}else N==="--failed"?r=!0:N==="--tail"||N==="-f"?n=!0:N==="--json"&&(u=!0)}if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(e==="get"){let I=a[2];I||(console.error(" usage: sootsim network get <id>"),process.exit(1));let N=await l.send({type:"evaluate",code:`(() => {
1009
+ jank: ${n.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(n.samples)&&n.samples.length>0&&(console.log(""),be(n.samples.map(h=>h[1])));break}default:console.error(` unknown perf subcommand: ${e}`),process.exit(1)}break}case"errors":{let e=a[1];if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimConsole?.clear(); "cleared"'}),E(d)?C({cleared:!0}):console.log(" error buffer cleared");break}let t=e?Number(e):20,s=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getErrors(${t}) || []`}),r=Array.isArray(s)?s:[];if(E(d)){C(r);break}if(r.length===0){console.log(" no errors captured");break}console.log(` ${r.length} error(s):
1010
+ `);for(let n of r){let m=new Date(n.timestamp).toLocaleTimeString(),p=n.args.map(h=>typeof h=="object"?JSON.stringify(h):h).join(" ");if(console.log(` [${m}] ${p}`),n.stack){let h=n.stack.split(`
1011
+ `).slice(0,3);for(let f of h)console.log(` ${f.trim()}`)}}break}case"warnings":{let e=a[1]?Number(a[1]):20,t=await l.send({type:"evaluate",code:`window.__sootsimConsole?.getWarnings(${e}) || []`}),s=Array.isArray(t)?t:[];if(E(d)){C(s);break}if(s.length===0){console.log(" no warnings captured");break}console.log(` ${s.length} warning(s):
1012
+ `);for(let r of s){let n=new Date(r.timestamp).toLocaleTimeString(),m=r.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");console.log(` [${n}] ${m}`)}break}case"animations":{let e=await z(l,"listAnimations")??[];if(o.includes("--json")){console.log(JSON.stringify(e,null,2));break}if(e.length===0){console.log(" no active animations");break}console.log(` ${e.length} active animation(s):
1013
+ `);for(let t of e){let s=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,n=Number(t.current??0).toFixed(2),m=`${Math.round((t.progress??0)*100)}%`,p=`${Math.round(t.elapsedMs??0)}ms`,h=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${r.padEnd(14)} cur=${n.padEnd(7)} ${m.padStart(4)} ${p}${h}${f}`)}break}case"animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("animation")} <id>`),process.exit(1));let t=Number(e);Number.isFinite(t)||(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"getAnimation",t);console.log(JSON.stringify(s,null,2));break}case"stop-animation":{let e=a[1];(!e||e==="--help"||e==="-h")&&(console.error(` usage: ${y("stop-animation")} <id|all>`),process.exit(1));let t=e==="all"?"all":Number(e);t!=="all"&&!Number.isFinite(t)&&(console.error(` invalid id: ${e}`),process.exit(1));let s=await z(l,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let e=a[1];if(e==="clear"){await z(l,"clearRequests"),E(d)?C({cleared:!0}):console.log(" request buffer cleared");break}let t=e==="all",s=t?a[2]:e,r=s?Number(s):20,n=t?await z(l,"getRequests",r):await z(l,"getFailedRequests",r),m=Array.isArray(n)?n:[];if(E(d)){C(m);break}if(m.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${m.length} ${t?"request(s)":"failed request(s)"}:
1014
+ `);for(let p of m){let h=new Date(p.timestamp).toLocaleTimeString();console.log(` [${h}] ${q(p)}`),p.responseBody?console.log(` ${p.responseBody}`):p.error&&console.log(` ${p.error}`)}break}case"network":{let e=a[1],t=null,s=null,r=!1,n=!1,m=!1;for(let N=0;N<d.length;N++){let M=d[N];if(M==="--filter")t=d[N+1]??null,N++;else if(M==="--limit"){let F=Number(d[N+1]);Number.isFinite(F)&&(s=F),N++}else M==="--failed"?r=!0:M==="--tail"||M==="-f"?n=!0:M==="--json"&&(m=!0)}if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.network.clear(); "cleared"'}),console.log(" network buffer cleared");break}if(e==="get"){let N=a[2];N||(console.error(" usage: sootsim network get <id>"),process.exit(1));let M=await l.send({type:"evaluate",code:`(() => {
1027
1015
  const obs = window.__sootsimObservability;
1028
1016
  if (!obs) return null;
1029
- return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(I)}) || null;
1030
- })()`});N||(console.error(` no entry with id ${I}`),process.exit(1)),u?console.log(JSON.stringify(N,null,2)):Tt(N);break}let m=o??(n?200:e?Number(e):20);Number.isFinite(m)||(console.error(` invalid limit: ${e}`),process.exit(1));let b=async()=>{let I=await l.send({type:"evaluate",code:`(() => {
1017
+ return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(N)}) || null;
1018
+ })()`});M||(console.error(` no entry with id ${N}`),process.exit(1)),m?console.log(JSON.stringify(M,null,2)):It(M);break}let p=s??(n?200:e?Number(e):20);Number.isFinite(p)||(console.error(` invalid limit: ${e}`),process.exit(1));let h=async()=>{let N=await l.send({type:"evaluate",code:`(() => {
1031
1019
  const obs = window.__sootsimObservability;
1032
1020
  if (!obs) return { ok: false };
1033
1021
  return { ok: true, entries: obs.network.getSnapshot() };
1034
- })()`});if(!I||!I.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return I.entries??[]},p=I=>{let N=I;if(r&&(N=N.filter(A=>!!A.error||A.status!=null&&A.status>=400)),t){let A=t.toLowerCase();N=N.filter(W=>(W.displayUrl||W.url).toLowerCase().includes(A))}return N};if(!n){let I=await b(),N=p(I).slice(-m);if(u){console.log(JSON.stringify(N,null,2));break}if(N.length===0){console.log(I.length===0?" no network requests captured":" no matching requests");break}console.log(` ${N.length} request(s):
1035
- `);for(let A of N)ze(A);break}console.log(` tailing network (ctrl-c to stop)...
1036
- `);let w=new Set,O=!0,D=()=>{O=!1};process.on("SIGINT",D);try{for(;O;){let I=await b(),N=p(I);for(let A of N)A.durationMs!=null&&(w.has(A.id)||(w.add(A.id),u?console.log(JSON.stringify(A)):ze(A)));await z(250)}}finally{process.off("SIGINT",D)}break}case"logs":{let e=a[1],t=null,o=null,r=null,n=!1,u=!1,m=!1;for(let g=0;g<d.length;g++){let M=d[g];if(M==="--filter")t=d[g+1]??null,g++;else if(M==="--limit"){let F=Number(d[g+1]);Number.isFinite(F)&&(o=F),g++}else M==="--level"?(r=d[g+1]??null,g++):M==="--tail"||M==="-f"?n=!0:M==="--json"?u=!0:(M==="--internal"||M==="--all")&&(m=!0)}let b=r?new Set(r.split(",").map(g=>g.trim()).filter(g=>g==="log"||g==="info"||g==="warn"||g==="error"||g==="debug")):null;if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.logs.clear(); "cleared"'}),console.log(" log buffer cleared");break}let p=!u&&process.stdout.isTTY===!0,w=o??(n?500:e?Number(e):50);Number.isFinite(w)||(console.error(` invalid limit: ${e}`),process.exit(1));let O=async()=>{let g=await l.send({type:"evaluate",code:`(() => {
1022
+ })()`});if(!N||!N.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return N.entries??[]},f=N=>{let M=N;if(r&&(M=M.filter(F=>!!F.error||F.status!=null&&F.status>=400)),t){let F=t.toLowerCase();M=M.filter(W=>(W.displayUrl||W.url).toLowerCase().includes(F))}return M};if(!n){let N=await h(),M=f(N).slice(-p);if(m){console.log(JSON.stringify(M,null,2));break}if(M.length===0){console.log(N.length===0?" no network requests captured":" no matching requests");break}console.log(` ${M.length} request(s):
1023
+ `);for(let F of M)Ve(F);break}console.log(` tailing network (ctrl-c to stop)...
1024
+ `);let w=new Set,O=!0,B=()=>{O=!1};process.on("SIGINT",B);try{for(;O;){let N=await h(),M=f(N);for(let F of M)F.durationMs!=null&&(w.has(F.id)||(w.add(F.id),m?console.log(JSON.stringify(F)):Ve(F)));await Y(250)}}finally{process.off("SIGINT",B)}break}case"logs":{let e=a[1],t=null,s=null,r=null,n=!1,m=!1,p=!1;for(let g=0;g<d.length;g++){let T=d[g];if(T==="--filter")t=d[g+1]??null,g++;else if(T==="--limit"){let _=Number(d[g+1]);Number.isFinite(_)&&(s=_),g++}else T==="--level"?(r=d[g+1]??null,g++):T==="--tail"||T==="-f"?n=!0:T==="--json"?m=!0:(T==="--internal"||T==="--all")&&(p=!0)}let h=r?new Set(r.split(",").map(g=>g.trim()).filter(g=>g==="log"||g==="info"||g==="warn"||g==="error"||g==="debug")):null;if(e==="clear"){await l.send({type:"evaluate",code:'window.__sootsimObservability?.logs.clear(); "cleared"'}),console.log(" log buffer cleared");break}let f=!m&&process.stdout.isTTY===!0,w=s??(n?500:e?Number(e):50);Number.isFinite(w)||(console.error(` invalid limit: ${e}`),process.exit(1));let O=async()=>{let g=await l.send({type:"evaluate",code:`(() => {
1037
1025
  const obs = window.__sootsimObservability;
1038
1026
  if (!obs) return { ok: false };
1039
1027
  return { ok: true, entries: obs.logs.getSnapshot() };
1040
- })()`});if(!g||!g.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return g.entries??[]},D=g=>{let M=g.args[0];return typeof M!="string"?!1:M.startsWith("[sootsim]")},I=g=>{let M=g;if(m||(M=M.filter(F=>!D(F))),b&&(M=M.filter(F=>b.has(F.level))),t){let F=t.toLowerCase();M=M.filter(P=>P.args.join(" ").toLowerCase().includes(F))}return M};if(!n){let g=await O(),M=I(g).slice(-w);if(u){console.log(JSON.stringify(M,null,2));break}if(M.length===0){console.log(g.length===0?" no logs captured":" no matching logs");break}console.log(` ${M.length} log(s):
1041
- `);for(let F of M)Ge(F,p);break}console.log(` tailing logs (ctrl-c to stop)...
1042
- `);let N=new Set,A=!0,W=()=>{A=!1};process.on("SIGINT",W);try{for(;A;){let g=await O(),M=I(g);for(let F of M)N.has(F.id)||(N.add(F.id),u?console.log(JSON.stringify(F)):Ge(F,p));await z(250)}}finally{process.off("SIGINT",W)}break}default:console.error(` unknown subcommand: ${h}`),process.exit(1)}if(J.has(h)&&!s.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await oe(l),!R.has(h)&&!B(d)){let e=await V();try{await j({counts:e.console})}catch{}try{await $({counts:e.requests})}catch{}}}catch(e){console.error(` ${h??"inspect"} failed: ${e.message}`);try{await we(l)}catch{}try{await j({includeTail:!0})}catch{}try{await $({includeTail:!0})}catch{}process.exit(1)}finally{l.close()}}export{Yo as runInspect};
1028
+ })()`});if(!g||!g.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return g.entries??[]},B=g=>{let T=g.args[0];return typeof T!="string"?!1:T.startsWith("[sootsim]")},N=g=>{let T=g;if(p||(T=T.filter(_=>!B(_))),h&&(T=T.filter(_=>h.has(_.level))),t){let _=t.toLowerCase();T=T.filter(P=>P.args.join(" ").toLowerCase().includes(_))}return T};if(!n){let g=await O(),T=N(g).slice(-w);if(m){console.log(JSON.stringify(T,null,2));break}if(T.length===0){console.log(g.length===0?" no logs captured":" no matching logs");break}console.log(` ${T.length} log(s):
1029
+ `);for(let _ of T)Qe(_,f);break}console.log(` tailing logs (ctrl-c to stop)...
1030
+ `);let M=new Set,F=!0,W=()=>{F=!1};process.on("SIGINT",W);try{for(;F;){let g=await O(),T=N(g);for(let _ of T)M.has(_.id)||(M.add(_.id),m?console.log(JSON.stringify(_)):Qe(_,f));await Y(250)}}finally{process.off("SIGINT",W)}break}default:console.error(` unknown subcommand: ${b}`),process.exit(1)}if(H.has(b)&&!o.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&await ne(l),!D.has(b)&&!E(d)){let e=await Z();try{await J({counts:e.console})}catch{}try{await x({counts:e.requests})}catch{}}}catch(e){console.error(` ${b??"inspect"} failed: ${e.message}`);try{await Me(l)}catch{}try{await J({includeTail:!0})}catch{}try{await x({includeTail:!0})}catch{}process.exit(1)}finally{l.close()}}export{ss as runInspect};