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