sootsim 0.1.150 → 0.1.152
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-LSSBQD6J.js → agent-URVJOKFR.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-HYZ3VS4M.js → agent-wrapper-73YIYNDO.js} +2 -2
- package/dist-cli/chunks/{app-fonts-XXHCZZVE.js → app-fonts-OEG4MO3O.js} +2 -2
- package/dist-cli/chunks/{assert-7I2ANKDG.js → assert-XE7724HR.js} +2 -2
- package/dist-cli/chunks/auto-bootstrap-KIVFMYKA.js +2 -0
- package/dist-cli/chunks/beta-YMZIDOZC.js +2 -0
- package/dist-cli/chunks/{camera-4D7T4PZW.js → camera-XDX3TEIA.js} +2 -2
- package/dist-cli/chunks/{chunk-7YEISEQ2.js → chunk-3M46FQ2H.js} +2 -2
- package/dist-cli/chunks/chunk-3QQ4WEDP.js +1 -0
- package/dist-cli/chunks/{chunk-DNTULI35.js → chunk-42IGHH7U.js} +1 -1
- package/dist-cli/chunks/{chunk-GXFEY4YV.js → chunk-4ZQHJ2LD.js} +1 -1
- package/dist-cli/chunks/{chunk-NK5T7NYR.js → chunk-6WD7VNN7.js} +1 -1
- package/dist-cli/chunks/{chunk-WQF5CLFD.js → chunk-A3NUKJZO.js} +3 -3
- package/dist-cli/chunks/{chunk-3RRDJNXM.js → chunk-A6AU7FG6.js} +2 -2
- package/dist-cli/chunks/{chunk-PGAGVXOZ.js → chunk-AHDSZKGA.js} +2 -2
- package/dist-cli/chunks/{chunk-3CENW2HN.js → chunk-AN6JOHDA.js} +2 -2
- package/dist-cli/chunks/{chunk-IADOI73U.js → chunk-AOCR2CD7.js} +2 -2
- package/dist-cli/chunks/{chunk-KIDONDPE.js → chunk-BBTJZTFD.js} +2 -2
- package/dist-cli/chunks/{chunk-PFFELWZN.js → chunk-BQJV36HU.js} +2 -2
- package/dist-cli/chunks/{chunk-36L4ANT2.js → chunk-BSHQ5LBD.js} +1 -1
- package/dist-cli/chunks/{chunk-6UA5JZ4E.js → chunk-FI3MX5RA.js} +2 -2
- package/dist-cli/chunks/{chunk-BFGPENAX.js → chunk-G3Q7KPV4.js} +1 -1
- package/dist-cli/chunks/{chunk-65GDTEX7.js → chunk-H2OQW4BL.js} +3 -3
- package/dist-cli/chunks/{chunk-3K237XV5.js → chunk-HJJXFBPX.js} +1 -1
- package/dist-cli/chunks/{chunk-NI2TIFUK.js → chunk-HQVHLEVY.js} +1 -1
- package/dist-cli/chunks/{chunk-6SXJQK5R.js → chunk-IFJ6JPWX.js} +3 -3
- package/dist-cli/chunks/{chunk-NISJ26VT.js → chunk-IGOGHY64.js} +2 -2
- package/dist-cli/chunks/{chunk-LBZGVNQE.js → chunk-IPKUT3NW.js} +1 -1
- package/dist-cli/chunks/{chunk-45XLWBNT.js → chunk-KQ5DX2FL.js} +1 -1
- package/dist-cli/chunks/{chunk-CDLPRRMH.js → chunk-LHSK2AQC.js} +2 -2
- package/dist-cli/chunks/{chunk-KO4VABY3.js → chunk-LOXEQ4OP.js} +1 -1
- package/dist-cli/chunks/{chunk-QIGU47UD.js → chunk-MGPNEZMT.js} +1 -1
- package/dist-cli/chunks/{chunk-3MWCUIK4.js → chunk-NJHB3U4Y.js} +2 -2
- package/dist-cli/chunks/{chunk-VJRAGYZ6.js → chunk-NNCA2HGI.js} +2 -2
- package/dist-cli/chunks/{chunk-B43JOK5N.js → chunk-NZPLKMSV.js} +2 -2
- package/dist-cli/chunks/{chunk-BUKMAGA6.js → chunk-OW3UFAND.js} +2 -2
- package/dist-cli/chunks/{chunk-NSEXBZUW.js → chunk-QEQF7ENZ.js} +2 -2
- package/dist-cli/chunks/{chunk-5Q464MLB.js → chunk-QFCV5A2F.js} +1 -1
- package/dist-cli/chunks/chunk-QKOVR72W.js +1 -0
- package/dist-cli/chunks/chunk-SARXTEIR.js +2 -0
- package/dist-cli/chunks/chunk-T2NDDQMC.js +1 -0
- package/dist-cli/chunks/{chunk-BWVKFTFM.js → chunk-TD3Z6FJN.js} +1 -1
- package/dist-cli/chunks/{chunk-NHDDW7WP.js → chunk-TW5OHRSG.js} +1 -1
- package/dist-cli/chunks/{chunk-LPVQM4H7.js → chunk-U67KLQVW.js} +2 -2
- package/dist-cli/chunks/{chunk-YLSVHL4W.js → chunk-US6SE4QV.js} +2 -2
- package/dist-cli/chunks/{chunk-IIJQQIAP.js → chunk-V5WZEFDP.js} +2 -2
- package/dist-cli/chunks/{chunk-YSN32GSR.js → chunk-V7YDKVRT.js} +2 -2
- package/dist-cli/chunks/{chunk-WNJOX4AQ.js → chunk-VIELKBJ6.js} +2 -2
- package/dist-cli/chunks/{chunk-JPWK6SFZ.js → chunk-WZXPKEQL.js} +1 -1
- package/dist-cli/chunks/{chunk-3J5I64W6.js → chunk-X4SL3FWM.js} +2 -2
- package/dist-cli/chunks/{chunk-MFPT2P6I.js → chunk-YRCAWRYU.js} +1 -1
- package/dist-cli/chunks/{chunk-WZ5JKRIA.js → chunk-YUHAC5LG.js} +2 -2
- package/dist-cli/chunks/cli-version-TWV3TFQ3.js +2 -0
- package/dist-cli/chunks/{compat-EPSPO3GI.js → compat-FE2GEVSP.js} +3 -3
- package/dist-cli/chunks/{config-7YGGAVYO.js → config-QKDBBBFW.js} +2 -2
- package/dist-cli/chunks/{control-TMFCD2NX.js → control-L3JMCHKG.js} +2 -2
- package/dist-cli/chunks/{cpu-profile-44YYVMOE.js → cpu-profile-YLKJMGUU.js} +2 -2
- package/dist-cli/chunks/{daemon-4XLAN5CC.js → daemon-BFAKPK23.js} +2 -2
- package/dist-cli/chunks/{debug-MUYM2RWK.js → debug-5XWSMAEY.js} +3 -3
- package/dist-cli/chunks/{detox-NZJVVCA3.js → detox-6YK4JUL7.js} +2 -2
- package/dist-cli/chunks/{device-7HMHAQ2Q.js → device-XAGXQWCU.js} +2 -2
- package/dist-cli/chunks/{diagnose-FXVOC7LV.js → diagnose-LSEBEQRY.js} +2 -2
- package/dist-cli/chunks/drivers-NS3LOKMD.js +2 -0
- package/dist-cli/chunks/{electron-NKK6Z2F3.js → electron-SA3SV6UY.js} +3 -3
- package/dist-cli/chunks/flow-XTVNMYAH.js +2 -0
- package/dist-cli/chunks/help-22JRBXSN.js +2 -0
- package/dist-cli/chunks/{hints-BLVNUKRX.js → hints-EHBTJHUI.js} +2 -2
- package/dist-cli/chunks/{home-paths-2QMRDV5X.js → home-paths-2N2B7LN2.js} +2 -2
- package/dist-cli/chunks/{inspect-E6Z6N3PK.js → inspect-KL7CMTWX.js} +114 -105
- package/dist-cli/chunks/install-IZDG63T5.js +2 -0
- package/dist-cli/chunks/{install-desktop-O2E7FC4R.js → install-desktop-6M27SW3X.js} +3 -3
- package/dist-cli/chunks/{keys-GWXMM5CC.js → keys-5DN6QA44.js} +2 -2
- package/dist-cli/chunks/{launch-KWMHPASG.js → launch-T2FDKJG4.js} +3 -3
- package/dist-cli/chunks/{login-AJO4L3ZI.js → login-OQV4ZCHQ.js} +4 -4
- package/dist-cli/chunks/{logout-ZVGPEGAB.js → logout-4LVSTCVR.js} +2 -2
- package/dist-cli/chunks/{maestro-4QX23OEI.js → maestro-NEFF35FI.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-BELFZOQ7.js +2 -0
- package/dist-cli/chunks/{preview-CGBGA343.js → preview-45X2RX4V.js} +2 -2
- package/dist-cli/chunks/{profile-RLKDXLSK.js → profile-CB6ROMKP.js} +2 -2
- package/dist-cli/chunks/{react-W2VGA55C.js → react-APJTHAUG.js} +2 -2
- package/dist-cli/chunks/{record-CF2HMY5Y.js → record-FHQFTXRJ.js} +2 -2
- package/dist-cli/chunks/runtime-B7K6SZWG.js +2 -0
- package/dist-cli/chunks/{runtime-delivery-DZWXR2A5.js → runtime-delivery-OVTPB7AF.js} +2 -2
- package/dist-cli/chunks/{screenshot-YV7USPJA.js → screenshot-X6PKMHZD.js} +2 -2
- package/dist-cli/chunks/{screenshot-mode-V27UKIG6.js → screenshot-mode-AFR7MPX7.js} +2 -2
- package/dist-cli/chunks/{screenshots-BUOMYKKW.js → screenshots-LPXTJRA3.js} +2 -2
- package/dist-cli/chunks/{server-6EZSHZV3.js → server-UNWWKLBD.js} +3 -3
- package/dist-cli/chunks/setup-repo-6NH6DGUZ.js +2 -0
- package/dist-cli/chunks/{skills-NXDCB76R.js → skills-NLF6QK66.js} +2 -2
- package/dist-cli/chunks/{slides-6LF76Q4J.js → slides-AV3CI3OJ.js} +2 -2
- package/dist-cli/chunks/{start-5VNJWI56.js → start-VQOSYBXB.js} +4 -4
- package/dist-cli/chunks/store-Q4QFSOED.js +2 -0
- package/dist-cli/chunks/telemetry-RQO4MFL2.js +2 -0
- package/dist-cli/chunks/{test-KPKJXRDI.js → test-XN75KVKO.js} +3 -3
- package/dist-cli/chunks/{three-mode-RWCVKNGM.js → three-mode-7WW3Q4SM.js} +2 -2
- package/dist-cli/chunks/{timeline-SRG5UM44.js → timeline-ZAVFYKLA.js} +2 -2
- package/dist-cli/chunks/{upgrade-LMUTKCI4.js → upgrade-Y2ADK7EE.js} +2 -2
- package/dist-cli/chunks/upload-WYFEDT7T.js +2 -0
- package/dist-cli/chunks/{version-P4LKM55A.js → version-RUSJ5QZA.js} +2 -2
- package/dist-cli/chunks/web-UMQ7ZOWC.js +2 -0
- package/dist-cli/chunks/{what-happened-AFWB7XTD.js → what-happened-33FFOC5R.js} +2 -2
- package/dist-cli/chunks/{whoami-YXJ6KECJ.js → whoami-FAAZEBWU.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/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 +3 -3
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/dist-cli/chunks/auto-bootstrap-YJM7QYAO.js +0 -2
- package/dist-cli/chunks/beta-EQOZMXP3.js +0 -2
- package/dist-cli/chunks/chunk-H5YQDCRA.js +0 -1
- package/dist-cli/chunks/chunk-OYWQKX2A.js +0 -2
- package/dist-cli/chunks/chunk-PHRIZLTZ.js +0 -1
- package/dist-cli/chunks/chunk-YKWGZWBE.js +0 -1
- package/dist-cli/chunks/cli-version-QHAJ7OMR.js +0 -2
- package/dist-cli/chunks/drivers-GM6GJG7Q.js +0 -2
- package/dist-cli/chunks/flow-3E4SG5M7.js +0 -2
- package/dist-cli/chunks/help-VIYWVIUB.js +0 -2
- package/dist-cli/chunks/install-U7C5NDWU.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-LKCGAST6.js +0 -2
- package/dist-cli/chunks/runtime-A7DUL4IU.js +0 -2
- package/dist-cli/chunks/setup-repo-MCAZJVL5.js +0 -2
- package/dist-cli/chunks/store-SX54DA6L.js +0 -2
- package/dist-cli/chunks/telemetry-PHXMPEY3.js +0 -2
- package/dist-cli/chunks/upload-3YJQJYAD.js +0 -2
- package/dist-cli/chunks/web-5ZYKOZJG.js +0 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{a as Y}from"./chunk-
|
|
3
|
-
`)}function
|
|
1
|
+
/*! sootsim v0.1.152 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{a as Y}from"./chunk-YUHAC5LG.js";import{a as vt,b as kt}from"./chunk-QFCV5A2F.js";import{a as Qe,g as ve,j as te}from"./chunk-IGOGHY64.js";import{b as Tt,c as Mt,j as It}from"./chunk-AN6JOHDA.js";import"./chunk-NNCA2HGI.js";import{a as ee,b as A,c as P,d as Re,e as ie,f as G,g as ue,h as fe,i as xt,j as $t,k as De,l as St}from"./chunk-V5WZEFDP.js";import{A as gt,B as yt,F as bt,H as ce,I as ht,O as wt,a as xe,b as Ze,c as et,d as tt,e as ot,f as st,g as nt,h as rt,i as it,j as at,k as Ae,l as Pe,q as Ee,r as lt,s as ct,t as $e,u as ut,v as Se,w as dt,x as mt,y as pt,z as ft}from"./chunk-MGPNEZMT.js";import"./chunk-6WD7VNN7.js";import{c as Ge,e as Ye,f as Xe,g as Ve,h as Oe}from"./chunk-FI3MX5RA.js";import"./chunk-G3Q7KPV4.js";import"./chunk-VIELKBJ6.js";import"./chunk-IPKUT3NW.js";import"./chunk-NJHB3U4Y.js";import"./chunk-3QQ4WEDP.js";import"./chunk-BSHQ5LBD.js";import{b as ze}from"./chunk-HQVHLEVY.js";import{a as Ke}from"./chunk-KQ5DX2FL.js";import{a as Fe,c as _e}from"./chunk-NZPLKMSV.js";import{a as Ue}from"./chunk-SARXTEIR.js";import"./chunk-LOXEQ4OP.js";import"./chunk-TW5OHRSG.js";import"./chunk-YRCAWRYU.js";import{existsSync as fo,mkdirSync as go,readFileSync as yo,rmSync as Nt,writeFileSync as bo}from"fs";import{tmpdir as ho}from"os";import{dirname as wo,join as xo,resolve as $o}from"path";var ge=1,So="SOOTSIM_INSPECT_NOTICE_PATH",vo=300*1e3,ko=15e3;function Ft(){return $o(process.env[So]||xo(ho(),"sootsim-inspect-notice-state.json"))}function To(e,l){return Object.fromEntries(Object.entries(e).filter(([,n])=>typeof n?.signature=="string"&&Number.isFinite(n?.updatedAt)&&l-n.updatedAt<=vo))}function Mo(e){let l=Ft();if(!fo(l))return{version:ge,entries:{}};try{let n=JSON.parse(yo(l,"utf8"));return n.version!==ge||!n.entries||typeof n.entries!="object"?(Nt(l,{force:!0}),{version:ge,entries:{}}):{version:ge,entries:To(n.entries,e)}}catch{return Nt(l,{force:!0}),{version:ge,entries:{}}}}function Io(e){let l=Ft();go(wo(l),{recursive:!0}),bo(l,JSON.stringify(e,null,2)+`
|
|
3
|
+
`)}function No(e,l){let n=l.trim()||"default";return`${e}:${n}`}function Ce(e,l,n,c={}){let m=c.nowMs??Date.now(),i=c.cooldownMs??ko,g=Mo(m),y=No(e,l),T=g.entries[y];return T&&T.signature===n&&m-T.updatedAt<i?!1:(g.entries[y]={signature:n,updatedAt:m},Io(g),!0)}var Fo={initialWaitMs:3e3,deadlineMs:5e3,retryWaitMs:700},_o={initialWaitMs:1200,deadlineMs:2500,retryWaitMs:700};function Oo(e,l={}){return{...e?Fo:_o,...l}}function de(e){return!(!e||e.hit===!1||e.ok===!1||e.pointerTapHandled===!1&&!e.keyboardOpened&&!e.isTextInput)}function Ao(e,l){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??l??null,type:e.target?.type??e.match?.type??e.node?.type??null}}async function ye(e,l){let n=Oo(!!l.agent,l.timing),c=0,m=null,i=null;try{await te({bridge:e,maxMs:n.initialWaitMs,pollMs:32,stablePolls:2})}catch{}let g=Date.now()+n.deadlineMs;for(;Date.now()<=g||c===0;){c++;let y=await l.resolve();if(m=y,y?.error==="bridge-not-ready"||y?.ambiguous||y?.nthOutOfRange)return{payload:y,result:null,attempts:c,failure:"special"};if(y&&typeof y.cx=="number"&&typeof y.cy=="number"){let M=await e.send({type:"tap",x:y.cx,y:y.cy,target:Ao(y,l.textFallback)});if(i=M,de(M))return{payload:y,result:M,attempts:c}}let T=g-Date.now();if(T<=0)break;try{await te({bridge:e,maxMs:Math.min(T,n.retryWaitMs),pollMs:32,stablePolls:2})}catch{await new Promise(M=>setTimeout(M,Math.min(120,T)))}}return{payload:m,result:i,attempts:c,failure:m&&typeof m.cx=="number"?"missed":"not-found"}}async function _t(e,l,n,c){return e.send({type:"tap",x:l,y:n,...c?{target:c}:{}})}async function Ot(e,l,n={}){let c=JSON.stringify(l);return ye(e,{agent:n.agent,timing:n.timing,resolve:()=>e.send({type:"evaluate",code:`(async () => {
|
|
4
4
|
const t = window.__sootsimTest
|
|
5
5
|
if (!t) return null
|
|
6
|
-
const n = (await t.findByTestId(${
|
|
6
|
+
const n = (await t.findByTestId(${c})) || (await t.findById(${c}))
|
|
7
7
|
if (!n || !n.absolutePosition || !n.layout) return { cx: null }
|
|
8
8
|
const resolved =
|
|
9
9
|
typeof n.nodeId === 'number' && typeof t.resolveTapTarget === 'function'
|
|
@@ -42,7 +42,7 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
42
42
|
},
|
|
43
43
|
strategy: (resolved && resolved.strategy) || 'matched-node',
|
|
44
44
|
}
|
|
45
|
-
})()`})})}async function
|
|
45
|
+
})()`})})}async function At(e,l,n={},c={}){let m=JSON.stringify({query:l,exact:!!n.exact,role:n.role??null,within:n.within??null,minX:n.minX??null,maxX:n.maxX??null,minY:n.minY??null,maxY:n.maxY??null,near:n.near??null,nth:n.nth??null,first:!!n.first});return ye(e,{agent:c.agent,timing:c.timing,textFallback:l,resolve:()=>e.send({type:"evaluate",code:`(async () => {
|
|
46
46
|
const t = window.__sootsimTest
|
|
47
47
|
if (!t) return { error: 'bridge-not-ready' }
|
|
48
48
|
const F = ${m}
|
|
@@ -162,11 +162,11 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
162
162
|
total,
|
|
163
163
|
idx,
|
|
164
164
|
}
|
|
165
|
-
})()`})})}async function
|
|
165
|
+
})()`})})}async function Pt(e,l,n={}){let c=JSON.stringify(l);return ye(e,{agent:n.agent,timing:n.timing,textFallback:l,resolve:async()=>{let m=await e.send({type:"evaluate",code:`(async () => {
|
|
166
166
|
const t = window.__sootsimTest
|
|
167
167
|
if (!t) return { error: 'bridge-not-ready' }
|
|
168
168
|
const byTestId =
|
|
169
|
-
(await t.findByTestId(${
|
|
169
|
+
(await t.findByTestId(${c})) || (await t.findById(${c}))
|
|
170
170
|
if (byTestId && byTestId.absolutePosition && byTestId.layout) {
|
|
171
171
|
return {
|
|
172
172
|
strategy: 'testid',
|
|
@@ -181,7 +181,7 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
181
181
|
},
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
-
const byText = await t.findByText(${
|
|
184
|
+
const byText = await t.findByText(${c})
|
|
185
185
|
if (byText && byText.absolutePosition && byText.layout) {
|
|
186
186
|
return {
|
|
187
187
|
strategy: 'text',
|
|
@@ -197,19 +197,19 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
return { strategy: 'none' }
|
|
200
|
-
})()`});if(!m||!("node"in m))return m;let
|
|
201
|
-
`),
|
|
202
|
-
`)}console.log(
|
|
203
|
-
`).length>=80&&Y("describe-use-filters"),W&&W.visible){let C=W.spec,
|
|
204
|
-
keyboard: ${
|
|
205
|
-
`);;)console.clear(),await
|
|
206
|
-
`).map(n=>
|
|
207
|
-
`)}async function
|
|
208
|
-
`),console.log(
|
|
209
|
-
`))}async function
|
|
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"?l:i.text,type:i.type}}}})}async function Et(e,l={args:[]}){let n=await et(e);if(A(l.args)){P(n);return}console.log(` nodes: ${n.nodes}`)}function Be(e,l){let n=e.indexOf(l);return n>=0&&n+1<e.length?e[n+1]:null}async function Rt(e){let{bridge:l,args:n,positional:c}=e,m=n.includes("--verbose")||n.includes("-v"),i=A(n),g=m&&!i,y=n.includes("--watch")||n.includes("-w"),T=1e3,M=n.includes("--compact"),h=n.includes("--no-xy"),k=n.includes("--no-clipped"),_=n.includes("--include-occluded"),I=Be(n,"--testid-like"),E=Be(n,"--only"),j=Be(n,"--subtree"),u=c[1]&&!c[1].startsWith("-")?c[1]:void 0,z=u?/[*?]/.test(u):!1,B=!z&&!E?u:void 0,D=E??(z?u:void 0),Q=async()=>{await ue(l,{verbose:g});let S=await st(l,{describe:!0,verbose:m,filter:B||"",testIdLike:I||void 0,onlyGlob:D||void 0,subtreeRoot:j||void 0,compact:M,hideXy:h,includeOccluded:_}),N=S?.tree,J=S?.shell,W=S?.keyboard;if(i){P({shell:J,tree:N??"",keyboard:W});return}if(J&&typeof J=="object"){let C=[J.state?`state=${J.state}`:null,J.activeApp?`app=${J.activeApp}`:null,J.showSwitcher?"switcher":null,J.switcherPhase&&J.switcherPhase!=="idle"?`phase=${J.switcherPhase}`:null].filter(Boolean);C.length>0&&console.log(` shell: ${C.join(" ")}`)}if(typeof N=="string"&&N.startsWith("__SUBTREE_NOT_FOUND__:")){let C=N.slice(22);console.log(` subtree root not found: ${C}`),Y("subtree-root-not-found",C);return}if(!N){let C=S?.nodeCount??0;console.log(" no matching nodes found"),!(B||I||D||j)&&C<10&&Y("app-still-loading",C);return}let V=N,Z=0;if(k&&typeof V=="string"){let C=V.split(`
|
|
201
|
+
`),le=[];for(let o of C){if(o.includes("(clipped:")){Z+=1;continue}le.push(o)}V=le.join(`
|
|
202
|
+
`)}console.log(V),Z>0&&console.log(` ${Z} clipped row(s) hidden (omit --no-clipped to see)`);let re=B||I||D||j;if((B||I||D)&&!y&&Y("describe-filter-context"),!re&&!y&&N.split(`
|
|
203
|
+
`).length>=80&&Y("describe-use-filters"),W&&W.visible){let C=W.spec,le=[C?.keyboardType?`type=${C.keyboardType}`:null,C?.returnKeyType&&C.returnKeyType!=="default"?`return=${C.returnKeyType}`:null,W.mode!=="letters"?`mode=${W.mode}`:null,W.shifted?"shift":null,W.capsLock?"caps":null,C?.autoCapitalize&&C.autoCapitalize!=="sentences"?`autoCap=${C.autoCapitalize}`:null,W.accessoryBarId?`accessory=${W.accessoryBarId}`:null].filter(Boolean);console.log(`
|
|
204
|
+
keyboard: ${le.join(" ")||"visible"}`)}};if(y)for(console.log(` watching... (Ctrl+C to stop)
|
|
205
|
+
`);;)console.clear(),await Q(),await ee(T);else await Q()}var Po=["SOOTSIM_AGENT","CLAUDECODE","CLAUDE_CODE_ENTRYPOINT","CLAUDE_CODE_SESSION_ID","CODEX_THREAD_ID","CURSOR_TRACE_ID","AIDER_MODEL"];function me(){if(process.env.SOOTSIM_AGENT==="0")return!1;for(let e of Po){let l=process.env[e];if(l&&l.trim()&&l!=="0")return!0}return!1}async function Dt(e){let{bridge:l,args:n,effectiveArgs:c,positional:m,inspectUsage:i}=e,g=S=>{let N=c.indexOf(S);return N>=0&&N+1<c.length?c[N+1]:null},y=S=>c.includes(S),T=g("--testid")||g("--test-id"),M=g("--role"),h=g("--type"),k=g("--text"),_=y("--pressable"),I=y("--visible"),E=y("--interactive-targets")||y("--actions"),j=!T&&!M&&!h&&!k&&!_&&!I&&!E?m[1]:null,u=k??j,z=await at(l,{testId:T,role:M,type:h,text:u,pressable:_,visible:I,interactive:E});z||(console.error(i("find","<text> | --text <t> | --testid <id> | --role <r> | --type <t> | --pressable | --visible | --interactive-targets")),process.exit(1));let{mode:B,result:D}=z,Q=A(n),oe=n.includes("--verbose")||n.includes("--dump");if(Q)B==="interactive-targets"&&Array.isArray(D)?P(Ae(D).map(S=>({...S,tap:Pe(S)}))):P(D??null);else if(Array.isArray(D))if(D.length===0){console.log(` no ${B} nodes found`);let S=await l.send({type:"evaluate",code:"(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()"});typeof S=="number"&&S<10&&Y("app-still-loading",S)}else if(B==="interactive-targets"){let S=Ae(D);console.log(` found ${S.length} interactive target${S.length===1?"":"s"} (sorted by score):`);for(let N of S.slice(0,20)){let J=N.absolutePosition?`@(${Math.round(N.absolutePosition.x)},${Math.round(N.absolutePosition.y)})`:"",W=N.layout?`${Math.round(N.layout.width)}x${Math.round(N.layout.height)}`:"?x?",V=N.text?` "${N.text.slice(0,30)}"`:"",Z=N.testID?` #${N.testID}`:"",re=N.accessibilityLabel?` \u24D8"${String(N.accessibilityLabel).slice(0,24)}"`:"",pe=N.accessibilityRole?`[${N.accessibilityRole}]`:N.type,C=Pe(N);console.log(` ${pe}${V}${re}${Z} ${W} ${J}`),console.log(` \u2192 ${C}`),oe&&console.log(je(JSON.stringify(N,null,2)," "))}S.length>20&&console.log(` ... and ${S.length-20} more`)}else{console.log(` found ${D.length} node${D.length===1?"":"s"} (${B}):`);for(let S of D.slice(0,20)){let N=S.absolutePosition?`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`:"",J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,30)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(je(JSON.stringify(S,null,2)," "))}D.length>20&&console.log(` ... and ${D.length-20} more`)}else if(D==null)console.log(` not found: ${u||T||M||h||""||B}`),T&&Y("wait-selector-for-missing-testid",T);else{let S=D;if(S.type&&S.absolutePosition){let N=`@(${Math.round(S.absolutePosition.x)},${Math.round(S.absolutePosition.y)})`,J=S.layout?`${Math.round(S.layout.width)}x${Math.round(S.layout.height)}`:"?x?",W=S.text?` "${S.text.slice(0,40)}"`:"",V=S.testID?` #${S.testID}`:"",Z=S.pressable?" (tap)":"",re=S.accessibilityRole?`[${S.accessibilityRole}]`:S.type;console.log(` ${re}${W}${V} ${J} ${N}${Z}`),oe&&console.log(je(JSON.stringify(S,null,2)," "))}else console.log(JSON.stringify(D,null,2))}}function je(e,l){return e.split(`
|
|
206
|
+
`).map(n=>l+n).join(`
|
|
207
|
+
`)}async function Ct(e){let{bridge:l,args:n}=e,c=A(n);await ue(l,{verbose:!c});let m=n.includes("--styling"),i=await nt(l,{styling:m});if(c){P({count:i.length,elements:i});return}console.log(` layout (${i.length} element${i.length===1?"":"s"}):
|
|
208
|
+
`),console.log(rt(i,{styling:m}))}async function Bt(e,l={}){let n=await bt(e);if("error"in n&&(console.error(n.error),process.exit(1)),l.json){console.log(JSON.stringify(n,null,2));return}let{visible:c,spec:m,mode:i,shifted:g,capsLock:y,accessoryBarId:T}=n,M=[];M.push(`keyboard: ${c?"visible":"hidden"}`),m?(M.push(` type: ${m.keyboardType}`),M.push(` returnKey: ${m.returnKeyType}`),M.push(` autoCap: ${m.autoCapitalize}`),M.push(` autoCorrect: ${m.autoCorrect?"on":"off"}`),M.push(` appearance: ${m.keyboardAppearance}`),m.secureTextEntry&&M.push(" secureTextEntry: true"),m.enablesReturnKeyAutomatically&&M.push(` return: ${m.currentTextIsEmpty?"disabled (empty)":"enabled"}`)):M.push(" spec: <none> (shown via dev-tools with no TextInput)"),M.push(` mode: ${i}${g?" (shifted)":""}${y?" (caps)":""}`),T&&M.push(` accessoryBar: ${T}`),console.log(M.join(`
|
|
209
|
+
`))}async function jt(e){let l=await e.bridge.listSims(),n=e.args.includes("--all"),c=e.args.find((y,T)=>e.args[T-1]==="--bundle"),m=e.args.find((y,T)=>e.args[T-1]==="--app-port"),i=e.args.includes("--primary"),g=l.filter(y=>!(i&&!y.isPrimary||c&&!(y.url??"").includes(c)||m&&!(y.url??"").includes(`/rn/${m}`)||!n&&!c&&!m&&!i&&!(y.url&&(y.url.includes("bundle=")||y.url.includes("/index.bundle")))&&y.id!==e.simId));if(A(e.args)){P(g.map(y=>({...y,active:y.id===e.simId})));return}It(g,e.simId),g.length<l.length&&!A(e.args)&&console.log(` (${l.length-g.length} more hidden \u2014 pass --all to show)`)}function ae(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/1024/1024).toFixed(1)}MB`}function ke(e,l){return l<=0?"?":`${(e/l*100).toFixed(0)}%`}async function Lt(e,l={args:[]}){let n=await wt(e);if(A(l.args)){P(n);return}if(console.log(" memory:"),n.imageLoader){let c=n.imageLoader;console.log(" image-loader cache"),console.log(` entries: ${c.cacheEntries} / ${c.cacheMaxEntries} (${ke(c.cacheEntries,c.cacheMaxEntries)})`),console.log(` pixel bytes: ${ae(c.cachePixelBytes)} / ${ae(c.cachePixelBudget)} (${ke(c.cachePixelBytes,c.cachePixelBudget)})`),console.log(` pending: ${c.pendingFetches} fetches, ${c.pendingBytes} bytes`),console.log(` failed uris: ${c.failedUris}`),console.log(` snapshots: ${c.snapshots}`),console.log(` live frames: ${c.liveFrames}`)}else console.log(" image-loader cache: not available (engine pre-rebuild?)");if(n.workerHeap){let c=n.workerHeap;console.log(" worker heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${ke(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}if(n.hostHeap){let c=n.hostHeap;console.log(" host heap (chrome only)"),console.log(` used: ${ae(c.usedJSHeapSize)} / ${ae(c.jsHeapSizeLimit)} (${ke(c.usedJSHeapSize,c.jsHeapSizeLimit)})`),console.log(` total: ${ae(c.totalJSHeapSize)}`)}}var X="<redacted secure text>";function be(e){let l=e?.layout?.spec??e?.spec??null;return!!l?.secureTextEntry&&l.keyboardType!=="visible-password"}function Le(e,l){return be(l)?X:e}function Je(e){if(!e||!be(e))return e;let l=e.focusedInput;return!l||typeof l!="object"?e:{...e,focusedInput:{...l,secureTextEntry:!0,text:typeof l.text=="string"?X:l.text}}}function he(e){let l=e.indexOf("--testid");if(l>=0&&e[l+1])return{mode:"testid",value:e[l+1]};let n=e.indexOf("--test-id");if(n>=0&&e[n+1])return{mode:"testid",value:e[n+1]};let c=e.indexOf("--text");return c>=0&&e[c+1]?{mode:"text",value:e[c+1]}:null}async function Te(e,l){let n=JSON.stringify(l.value),c=l.mode==="testid"?`(await t.findByTestId(${n})) || (await t.findById(${n}))`:`await t.findByText(${n})`;return await e.send({type:"evaluate",code:`(async () => {
|
|
210
210
|
const t = window.__sootsimTest
|
|
211
211
|
if (!t) return null
|
|
212
|
-
const n = ${
|
|
212
|
+
const n = ${c}
|
|
213
213
|
if (!n || !n.absolutePosition || !n.layout) return null
|
|
214
214
|
const resolved =
|
|
215
215
|
typeof n.nodeId === 'number' && typeof t.resolveTapTarget === 'function'
|
|
@@ -228,18 +228,18 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
228
228
|
y: cy,
|
|
229
229
|
id: n.id ?? null,
|
|
230
230
|
testID: n.testID ?? null,
|
|
231
|
-
text: ${JSON.stringify(
|
|
231
|
+
text: ${JSON.stringify(l.mode==="text")} ? ${n} : (n.text ?? n.accessibilityLabel ?? null),
|
|
232
232
|
type: n.type ?? null,
|
|
233
233
|
}
|
|
234
|
-
})()`})??null}async function
|
|
235
|
-
`))}async function
|
|
234
|
+
})()`})??null}async function Jt(e,l={}){let{nav:n,keyboard:c,shell:m}=await ht(e);if(l.json){console.log(JSON.stringify({shell:m??null,nav:n,keyboard:c},null,2));return}let i=[];if(m){let g=m.activeApp??m.state??"<none>",y=m.showSwitcher?" (app switcher open)":"",T=typeof m.launchProgress=="number"&&m.launchProgress<.98?` launching (${Math.round(m.launchProgress*100)}%)`:"";i.push(`shell: ${g}${y}${T}`)}else i.push("shell: <unavailable>");if(n){let g=n.transitionPhase!=="idle"?` (${n.transitionPhase}, ${n.activeTransitionCount} active)`:"";if(i.push(`nav: phase=${n.transitionPhase}${g}`),n.screens.length===0)i.push(" <no registered screens \u2014 app may not use react-native-screens>");else for(let y of n.screens){let T=y.isActive?"\u25B6":" ",M=y.routeName?` ${y.routeName}`:"",h=y.headerHeight>0?` header=${y.headerHeight}`:"",k=y.largeTitleState&&y.largeTitleState!=="expanded"?` large-title=${y.largeTitleState}`:"";i.push(` ${T} #${y.id}${M}${h}${k}`)}}else i.push("nav: <runtime not available>");if(c&&c.visible){let g=c.spec?.keyboardType??"default",y=c.spec?.returnKeyType??"default";i.push(`keyboard: visible (${g}, return=${y}, mode=${c.mode??"?"})`)}else i.push("keyboard: hidden");console.log(i.join(`
|
|
235
|
+
`))}async function Wt(e){let{bridge:l,args:n,positional:c}=e,m=c[1]?Number(c[1])*1e3:3e3,i=n.includes("--strict"),{elapsed:g,settled:y}=await te({bridge:l,maxMs:m,strict:i});console.log(y?` settled in ${g}ms`:` timed out after ${g}ms (may still be animating)`)}async function qt(e){let l=e.positional[1]?Number(e.positional[1]):.5;(!Number.isFinite(l)||l<0)&&(console.error(e.inspectUsage("sleep","[seconds]")),process.exit(1)),await ee(l*1e3),console.log(` slept ${l}s`)}async function Ht(e){let{bridge:l,args:n,positional:c}=e,m=c[1]?Number(c[1]):5,{tree:i}=await tt(l,m);if(A(n)){P({depth:m,tree:i??null});return}console.log(typeof i=="string"?i:JSON.stringify(i,null,2))}async function Kt(e,l={args:[]}){let n=await ot(e);if(A(l.args)){P(n);return}console.log(n.url)}async function Ut(e){let{wsPort:l,commandTimeoutMs:n,simId:c,simIdSource:m,positional:i}=e,g=i[1]?Number(i[1]):30,y=Math.max(1e3,(Number.isFinite(g)?g:30)*1e3),T=Math.max(1,Math.ceil(y/500));console.log(" waiting for sim reconnect...");let M=await xt(l,n,c,{attempts:T,simIdSource:m});M||(console.error(" timed out waiting for sim reconnect"),process.exit(1)),M.bridge.close(),ve({source:"inspect wait",step:{wait:y},summary:`wait ${Math.round(y/1e3)}s`}),console.log(` ready: ${M.count} nodes`)}var zt=new Set(["app-launch","toast","keyboard","screen","route","alert","actionsheet","picker","notification","fetch","console","shell","scroll","gesture","text-input","react-commit","animation","reanimated"]);function Me(e,l){let n=e.indexOf(l);if(n>=0&&n+1<e.length)return e[n+1]}function Eo(e,l){if(!l.filter&&!l.equals)return!0;let n=e.data,c=[];if(n&&typeof n=="object")for(let i of["url","displayUrl","message","name","activeName","path","pathname","title","phase","event","type","kind"]){let g=n[i];typeof g=="string"&&g.length>0&&c.push(g)}let m=c.join(" ");return l.equals?c.some(i=>i===l.equals):l.filter?m.toLowerCase().includes(l.filter.toLowerCase()):!0}async function Gt(e){let{bridge:l,args:n,positional:c,inspectUsage:m}=e,i=c[1];i||(console.error(m("wait event","<kind> [--max-ms 5000] [--filter <substring>] [--equals <exact>] [--since now|cursor]")),process.exit(1)),zt.has(i)||console.error(` warning: '${i}' is not a known timeline kind \u2014 waiting anyway. known: ${[...zt].sort().join(", ")}`);let g=Me(n,"--max-ms"),y=g&&Number.isFinite(Number(g))?Math.max(100,Number(g)):5e3,T=Me(n,"--filter"),M=Me(n,"--equals"),h=Me(n,"--since")??"now",k=n.includes("--json"),_=Date.now(),I=_+y,E=200,j=_;for(;Date.now()<I;){let z={kinds:[i],since:h==="cursor"?void 0:j,limit:50},B=await l.send({type:"evaluate",code:`(async () => {
|
|
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(z)}) }
|
|
239
|
-
})()`});(!B||!B.ok)&&(console.error(` could not query timeline: ${B&&"error"in B?B.error:"unknown"}`),process.exit(1));let D=B.result.events??[];for(let
|
|
239
|
+
})()`});(!B||!B.ok)&&(console.error(` could not query timeline: ${B&&"error"in B?B.error:"unknown"}`),process.exit(1));let D=B.result.events??[];for(let Q of D)if(Eo(Q,{filter:T,equals:M})){let oe=Date.now()-_;console.log(k?JSON.stringify({found:!0,elapsedMs:oe,event:Q}):` ${i} event after ${oe}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`);return}B.result.watermark&&B.result.watermark>j&&(j=B.result.watermark),await new Promise(Q=>setTimeout(Q,E))}let u=Date.now()-_;k?console.log(JSON.stringify({found:!1,elapsedMs:u,kind:i,filter:T,equals:M})):console.error(` \u26A0 wait event ${i} timed out after ${u}ms${T?` (filter: ${T})`:""}${M?` (equals: ${M})`:""}`),process.exit(1)}async function Yt(e){let{bridge:l,args:n}=e,c=n.includes("--strict"),m=xe(n,3e3),{elapsed:i,settled:g}=await te({bridge:l,maxMs:m,strict:c});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 Xt(e){let{bridge:l,args:n}=e,c=xe(n,2e4),{ready:m,elapsedMs:i,nodes:g,targets:y,flag:T,loadingText:M,externalReady:h,externalError:k,errors:_}=await lt(l,c,{onProgress(E){console.error(` still waiting after ${E.elapsedMs}ms \u2014 ${Ee(E)} (nodes: ${E.nodes}, targets: ${E.targets}, errors: ${E.errors})`)}});if(m){let E=c-i,j=Math.max(100,Math.min(1e4,E)),u=await te({bridge:l,maxMs:j,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 I=Ee({externalError:k,loadingText:M,externalReady:h,flag:T,targets:y});console.error(` \u26A0 wait ready timed out after ${i}ms \u2014 ${I} (nodes: ${g}, targets: ${y}, errors: ${_})`),process.exit(1)}async function Vt(e){let{bridge:l,args:n,positional:c,inspectUsage:m}=e,i=c[1];i||(console.error(m("wait selector","<testid> [--max-ms 5000] [--gone]")),process.exit(1));let g=n.indexOf("--max-ms"),y=g>=0&&n[g+1]?Math.max(100,Number(n[g+1])):5e3,T=n.includes("--gone"),{found:M,node:h,elapsed:k}=await ct(l,i,y,{gone:T});if(T){M?console.log(` #${i} gone after ${k}ms`):(console.error(` \u26A0 wait selector #${i} --gone timed out after ${k??y}ms (still present)`),process.exit(1));return}if(M&&h){let _=h.absolutePosition?`@(${Math.round(h.absolutePosition.x)},${Math.round(h.absolutePosition.y)})`:"",I=h.layout?`${Math.round(h.layout.width)}x${Math.round(h.layout.height)}`:"?x?";console.log(` found #${i} in ${k}ms ${I} ${_}`)}else console.error(` \u26A0 wait selector #${i} timed out after ${k??y}ms`),process.exit(1)}function ro(e){return e==null?"\u2014":e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}K`:`${(e/1024/1024).toFixed(1)}M`}function io(e){return e==null?" \u2026":e<1e3?`${e}ms`.padStart(5):`${(e/1e3).toFixed(2)}s`.padStart(5)}function Qt(){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
|
-
`)}async function
|
|
242
|
+
`)}async function Do(e){try{return await e.send({type:"evaluate",code:"1"},{timeoutMs:3e3}),!0}catch{return!1}}async function Co(e,l){try{let n=await e.send({type:"evaluate",code:`(async () => {
|
|
243
243
|
const t = window.__sootsimTest
|
|
244
244
|
if (!t || typeof t.queryAll !== 'function') return []
|
|
245
245
|
try {
|
|
@@ -258,11 +258,14 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
258
258
|
} catch {
|
|
259
259
|
return []
|
|
260
260
|
}
|
|
261
|
-
})()`});if(!Array.isArray(n)||n.length===0)return;let l
|
|
262
|
-
`).slice(0,5);for(let g of
|
|
261
|
+
})()`});if(!Array.isArray(n)||n.length===0)return;let c=l.toLowerCase(),m=n.map(i=>({id:i,score:Bo(c,i.toLowerCase())})).filter(i=>i.score<c.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 Bo(e,l){if(l===e)return 0;if(l.includes(e))return 1;if(e.includes(l))return 2;let n=0;for(;n<e.length&&n<l.length&&e[n]===l[n];)n+=1;return jo(e,l)-n}function jo(e,l){if(e===l)return 0;if(!e.length)return l.length;if(!l.length)return e.length;let n=new Array(l.length+1),c=new Array(l.length+1);for(let m=0;m<=l.length;m++)n[m]=m;for(let m=1;m<=e.length;m++){c[0]=m;for(let g=1;g<=l.length;g++)c[g]=Math.min(n[g]+1,c[g-1]+1,n[g-1]+(e[m-1]===l[g-1]?0:1));let i=n;n=c,c=i}return n[l.length]}function Lo(e){return e.error?"err":e.status==null?" \u2026 ":String(e.status)}function Jo(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 Zt(e){let l=ie(e.startTs),n=Lo(e).padEnd(3),c=e.method.padEnd(5),m=ro(e.size).padStart(6),i=io(e.durationMs);console.log(` [${l}] ${n} ${c} ${m} ${i} ${e.displayUrl}`),e.error&&console.log(` error: ${e.error}`)}function Wo(e){let l=[["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",ie(e.startTs)],["duration",io(e.durationMs).trim()],["size",ro(e.size)],["content-type",e.type??"\u2014"]];for(let[n,c]of l)console.log(` ${n.padEnd(13)} ${c}`)}var qo={error:"\x1B[31m",warn:"\x1B[33m",info:"\x1B[36m",debug:"\x1B[35m",log:"\x1B[37m"},eo="\x1B[0m",Ho="\x1B[2m";function to(e,l){let n=ie(e.ts),c=e.level.toUpperCase().padEnd(5),m=e.args.join(" ");if(l){let i=qo[e.level];console.log(` ${Ho}[${n}]${eo} ${i}${c}${eo} ${m}`)}else console.log(` [${n}] ${c} ${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 ne="__sootsimCliPerf",Ko=120;async function oo(e,l){let n=e.find((_,I)=>e[I-1]==="--id"),c=e.find((_,I)=>e[I-1]==="--text");if(n||c){let _=await l.send({type:"evaluate",code:vt({id:n,text:c})});if(!_)throw new Error(n?`no node with id "${n}"`:`no node matching text "${c}"`);let{x:I,y:E,w:j,h:u}=_;return{x:I,y:E,w:j,h:u}}let m=e.find((_,I)=>e[I-1]==="--area");if(m){let _=m.split(",").map(z=>Number(z.trim()));if(_.length!==4||_.some(z=>!Number.isFinite(z)))throw new Error(`--area expects x,y,w,h (got "${m}")`);let[I,E,j,u]=_;return{x:I,y:E,w:j,h:u}}let i=_=>{let I=e.find((j,u)=>e[u-1]===_);if(I==null)return null;let E=Number(I);return Number.isFinite(E)?E:null},g=i("--x"),y=i("--y"),T=i("--w"),M=i("--h");if(g!=null||y!=null||T!=null||M!=null)return{x:g??0,y:y??0,w:T??1,h:M??1};let k=e.filter((_,I)=>I>0&&!_.startsWith("-")&&e[I-1]!=="--output"&&e[I-1]!=="--area"&&e[I-1]!=="--id"&&e[I-1]!=="--text"&&e[I-1]!=="--x"&&e[I-1]!=="--y"&&e[I-1]!=="--w"&&e[I-1]!=="--h").map(Number).filter(_=>Number.isFinite(_));if(k.length>=2){let[_,I,E=1,j=1]=k;return{x:_,y:I,w:E,h:j}}return null}function We(e){let l={"<8":0,"8-12":0,"12-16":0,"16-20":0,"20-33":0,">33":0};for(let n of e)n<8?l["<8"]++:n<12?l["8-12"]++:n<16?l["12-16"]++:n<20?l["16-20"]++:n<33?l["20-33"]++:l[">33"]++;console.log(" histogram:");for(let[n,c]of Object.entries(l)){let m="\u2588".repeat(Math.ceil(c/e.length*40));console.log(` ${n.padEnd(6)} ${m} ${c}`)}}async function Ie(e,l,n){let c=Date.now()+l,m=await ce(e,l);for(;;){if(n(m))return{settled:!0,state:m};if(Date.now()>=c)return{settled:!1,state:m};await ee(16),m=await ce(e)}}async function He(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' }
|
|
266
|
+
const layout = typeof kb.getLayout === 'function' ? kb.getLayout() : null
|
|
267
|
+
const secureTextEntry =
|
|
268
|
+
!!layout?.spec?.secureTextEntry && layout?.spec?.keyboardType !== 'visible-password'
|
|
266
269
|
const visible = kb.isVisible()
|
|
267
270
|
const mode = kb.getMode()
|
|
268
271
|
let focused = null
|
|
@@ -280,18 +283,20 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
280
283
|
return {
|
|
281
284
|
visible,
|
|
282
285
|
mode,
|
|
286
|
+
layout,
|
|
283
287
|
focusedInput: focused ? {
|
|
284
288
|
nodeId: focused.nodeId ?? null,
|
|
285
289
|
testID: focused.testID || null,
|
|
286
290
|
id: focused.id || null,
|
|
287
291
|
placeholder: focused.placeholder || null,
|
|
288
|
-
|
|
292
|
+
secureTextEntry,
|
|
293
|
+
text: secureTextEntry ? ${JSON.stringify(X)} : (focused.text || null),
|
|
289
294
|
} : null,
|
|
290
295
|
phase: runtimeSnapshot?.keyboard?.phase ?? null,
|
|
291
296
|
frame: runtimeSnapshot?.keyboard?.frame ?? null,
|
|
292
297
|
focusedRect: runtimeSnapshot?.focused?.rect ?? null,
|
|
293
298
|
}
|
|
294
|
-
})()`})}async function
|
|
299
|
+
})()`}).then(l=>Je(l))}function Uo(e,l,n){if(!e.visible)return!1;let c=e.focusedInput;return!(l&&c&&!(c.testID===l||c.id===l)||n!==null&&be(e)!==n)}async function zo(e,l=600,n={}){let c=Date.now()+l;for(;Date.now()<=c;){let m=await He(e);if(Uo(m,n.targetId??null,n.secureTextEntry??null))return m;await ee(30)}return He(e)}async function Ne(e,l){let n=await He(e);if(n.visible)return n;console.error(` ${l} 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 so(e,l,n){return l==="appearance"?e.send({type:"evaluate",code:`(async () => {
|
|
295
300
|
const requested = ${JSON.stringify(n??"toggle")}
|
|
296
301
|
const rootBg = (document.documentElement?.style?.background || '').toLowerCase()
|
|
297
302
|
const inferredCurrent = rootBg.includes('33') ? 'dark' : 'light'
|
|
@@ -306,27 +311,27 @@ import{a as Y}from"./chunk-WZ5JKRIA.js";import{a as wt,b as xt}from"./chunk-5Q46
|
|
|
306
311
|
: next
|
|
307
312
|
return { ok: true, requested, value: next, applied }
|
|
308
313
|
})()`}):e.send({type:"evaluate",code:`(async () => {
|
|
309
|
-
window.dispatchEvent(new CustomEvent(${JSON.stringify(
|
|
310
|
-
return { ok: true, action: ${JSON.stringify(
|
|
311
|
-
})()`})}function
|
|
312
|
-
`),process.exit(0))}if(M==="shell"){let
|
|
313
|
-
`),process.exit(0))}let t=
|
|
314
|
+
window.dispatchEvent(new CustomEvent(${JSON.stringify(l==="lock"?"sootsim:toggleLock":"sootsim:shake")}))
|
|
315
|
+
return { ok: true, action: ${JSON.stringify(l)} }
|
|
316
|
+
})()`})}function Go(e){let l={Enter:"return",NumpadEnter:"return",Backspace:"delete",Delete:"delete",Space:"space",ShiftLeft:"shift",ShiftRight:"shift"};if(l[e])return l[e];let n=e.match(/^Digit([0-9])$/);if(n)return n[1];let c=e.match(/^Key([A-Z])$/);return c?c[1].toLowerCase():null}function Yo(e){if(typeof e!="string")return null;let l=e.replace(/\s+/g," ").trim();return l?l.slice(0,80):null}function ao(...e){for(let l of e){if(typeof l!="string")continue;let n=l.trim();if(n)return n}return null}function Xo(e){let l=e.indexOf("--node-id");if(l<0)return null;let n=e[l+1];if(!n)return null;let c=Number(n);return Number.isInteger(c)&&c>0?c:null}async function L(e,l,n){let c=ve({source:e,step:l,summary:n});c.active&&(c.replaced?console.error(` draft: replaced unkept action "${c.replaced.summary}" \u2014 \`flow keep\` commits one action at a time`):console.error(" draft: action pending \u2014 `sootsim flow keep` to commit"))}function no(e,l,n){if(!n||n.hit===!1)return null;let c=ao(n.responderTestID,n.testID);if(c)return{step:{tapOn:{id:c}},summary:`tap #${c}`};let m=Yo(n.text);return m?{step:{tapOn:m},summary:`tap "${m}"`}:{step:{tapAtCoords:{x:e,y:l}},summary:`tap @${Math.round(e)},${Math.round(l)}`}}function qe(e,l,n){let c=ao(l?.testID,l?.id);return c?{step:{tapOn:{id:c}},summary:`tap #${c}`}:n==="id"?{step:{tapOn:{id:e}},summary:`tap #${e}`}:{step:{tapOn:e},summary:`tap "${e}"`}}async function Jn(e,l){let n=e[0]==="get"||e[0]==="do"||e[0]==="debug"||e[0]==="wait"?e[0]:null,c=n?e.slice(1):e,m=Ge(c,{port:l.port,commandTimeoutMs:l.timeoutMs,stripBooleanFlags:["--verbose","-v","--help","-h","--clear-state","--json","--all","--watch","-w","--strict","--no-wait","--dump","--failed","--slow","--tail","-f","--interactive-targets","--actions","--internal","--compact","--no-xy","--no-clipped","--include-occluded"],stripValueFlags:["--output","--nth","--index","--testid","--test-id","--text","--node-id","--max-ms","--filter","--limit","--level","--threshold","--equals","--since","--testid-like","--only","--subtree"]}),i=m.positional,g=i[0],y=n==="get"||n==="do"||n==="debug"||n==="wait"?n:"inspect",T=typeof c[0]=="string"&&Ke.has(c[0]),M=T?c[0]:null,h=o=>T&&o===c[0]?`sootsim ${o}`:`sootsim ${y} ${o}`,k=(o,t)=>` usage: ${h(o)}${t?` ${t}`:""}`;if(!g||e.includes("--help")||e.includes("-h")){let o={bridgePort:7668,defaultShellUrl:Ue};if(y==="do"||y==="get"||y==="debug"||y==="wait"){let r=Fe(y,o);r&&(console.log(`${r}
|
|
317
|
+
`),process.exit(0))}if(M==="shell"){let r=_e("shell",o);r&&(console.log(`${r}
|
|
318
|
+
`),process.exit(0))}let t=_e("inspect",o),s=["do","get","debug","wait"].map(r=>Fe(r,o)).filter(r=>r!=null).join(`
|
|
314
319
|
|
|
315
320
|
`);console.log(`${t??""}
|
|
316
321
|
|
|
317
322
|
${s}
|
|
318
|
-
`),process.exit(0)}let _=m.wsPort,I=m.simId,
|
|
319
|
-
`);let s=Math.max(...t.map(a=>a.id.length),6),
|
|
320
|
-
`)}catch{}}function N(o,t){console.error(` tap failed: ${o} stayed visible but did not receive a hittable press after ${t.attempts} attempt${t.attempts===1?"":"s"}`),t.result&&console.error(` last result: ${JSON.stringify(t.result)}`)}async function
|
|
321
|
-
console: ${
|
|
323
|
+
`),process.exit(0)}let _=m.wsPort,I=m.simId,E=m.simIdSource,j=m.commandTimeoutMs;if(g==="list"&&c.some(o=>o==="--drivers"||o==="-D")){let{buildDriverListRows:o}=await import("./drivers-NS3LOKMD.js"),t=o();console.log(` available drivers (${t.length}):
|
|
324
|
+
`);let s=Math.max(...t.map(a=>a.id.length),6),r=Math.max(...t.map(a=>a.kind.length),4);for(let a of t){let d=a.available?"\u2713":"\u2717",p=a.id.padEnd(s),b=a.kind.padEnd(r);console.log(` ${d} ${p} ${b} ${a.description}`),a.available&&a.detail?console.log(` ${a.detail}`):!a.available&&a.reason&&console.log(` unavailable: ${a.reason}`)}return}let u=Ye(m),z=I||"default",B=new Set(["errors","warnings","requests","js","eval","reload","globals","perf","list","wait","sleep"]),D=200;function Q(o){let t=o.replace(/\s+/g," ").trim();if(!t)return"";if(/^<(!doctype html|html|\?xml)|<body[\s>]/i.test(t)){let r=/<title[^>]*>([^<]+)<\/title>/i.exec(o)?.[1]?.trim(),a=/<body[^>]*>([\s\S]*?)<\//i.exec(o)?.[1]?.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80),d=r||a||"html error page";return`<html ${o.length}B> "${d}" (body elided \u2014 add --json for the full payload)`}return t.length<=D?t:`${t.slice(0,D)}\u2026 (+${t.length-D} more bytes)`}function oe(o){let t=o.displayUrl||o.url;return o.status!=null?`${o.method} ${t} -> ${o.status}${o.statusText?` ${o.statusText}`:""}`:o.error?`${o.method} ${t} -> ${o.error}`:`${o.method} ${t}`}async function S(o){let t=me()?5e3:1500;try{let{settled:s,elapsed:r}=await te({bridge:o,maxMs:t,pollMs:32,stablePolls:2});s||process.stderr.write(` \u26A0 auto-wait timed out after ${r??t}ms \u2014 next command may see mid-animation state. use \`sootsim do settle\` for a longer wait.
|
|
325
|
+
`)}catch{}}function N(o,t){console.error(` tap failed: ${o} stayed visible but did not receive a hittable press after ${t.attempts} attempt${t.attempts===1?"":"s"}`),t.result&&console.error(` last result: ${JSON.stringify(t.result)}`)}async function J(){try{return await u.send({type:"evaluate",code:`(() => ({
|
|
326
|
+
console: ${Se},
|
|
322
327
|
requests: window.__sootsimTest?.getRequestCounts?.() || null,
|
|
323
|
-
}))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function W(o={}){let t=o.counts!==void 0?o.counts:await G(
|
|
324
|
-
network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${h("requests")} 5`),!o.includeTail))return;let
|
|
328
|
+
}))()`})||{console:null,requests:null}}catch{return{console:null,requests:null}}}async function W(o={}){let t=o.counts!==void 0?o.counts:await G(u,"getRequestCounts");if(!t||typeof t!="object")return;let s=Math.max(0,Number(t.failed)||0);if(s===0||!o.includeTail&&!Ce("requests",z,String(s))||(console.log(`
|
|
329
|
+
network: ${s} failed request${s===1?"":"s"}`),console.log(` inspect: ${h("requests")} 5`),!o.includeTail))return;let r=await G(u,"getFailedRequests",5);if(!(!Array.isArray(r)||r.length===0)){console.log(`
|
|
325
330
|
recent failed requests:
|
|
326
|
-
`);for(let a of
|
|
327
|
-
console: ${
|
|
331
|
+
`);for(let a of r){let d=ie(a.timestamp);console.log(` [${d}] ${oe(a)}`),a.responseBody?console.log(` ${Q(a.responseBody)}`):a.error&&console.log(` ${a.error}`)}}}async function V(o={}){let t=o.counts!==void 0?o.counts:await u.send({type:"evaluate",code:Se});if(!t||typeof t!="object")return;let s=t,r=Math.max(0,Number(s.errors)||0),a=Math.max(0,Number(s.warnings)||0);if(r===0&&a===0||!o.includeTail&&!Ce("console",z,`${r}:${a}`))return;let d=[];if(r>0&&d.push(`${r} console error${r===1?"":"s"}`),a>0&&d.push(`${a} console warning${a===1?"":"s"}`),console.log(`
|
|
332
|
+
console: ${d.join(", ")}`),console.log(` inspect: ${h("errors")} 5`),a>0&&console.log(` inspect: ${h("warnings")} 5`),!o.includeTail||r===0)return;let p=await $e(u,5);if(!(!Array.isArray(p)||p.length===0)){console.log(`
|
|
328
333
|
recent console errors:
|
|
329
|
-
`);for(let b of p){let f=
|
|
334
|
+
`);for(let b of p){let f=ie(b.timestamp),w=Array.isArray(b.args)?b.args.map(O=>typeof O=="object"?JSON.stringify(O):String(O)).join(" "):String(b);console.log(` [${f}] ${w}`)}}}let Z=["console","fetch","toast","alert","notification","screen","app-launch","keyboard","route","actionsheet","picker","shell","scroll","gesture","text-input","animation","reanimated"];async function re(o){let t=ze(),s=null;try{s=await Ve(o,`(() => {
|
|
330
335
|
const tl = window.SootSim && window.SootSim.bridges && window.SootSim.bridges.timeline
|
|
331
336
|
if (!tl || typeof tl.summary !== 'function') return null
|
|
332
337
|
const cursorKey = ${JSON.stringify(t)}
|
|
@@ -342,9 +347,9 @@ ${s}
|
|
|
342
347
|
}
|
|
343
348
|
}
|
|
344
349
|
return summary ? { summary, consoleSplit } : null
|
|
345
|
-
})()`)}catch{return}if(!s||!s.summary||!s.summary.total)return;let
|
|
346
|
-
since last: ${a.join(" \xB7 ")} \u2014 sootsim what-happened`),s.summary.lastAt))try{await
|
|
347
|
-
`);for(let t of o){let s=[];if(s.push(`[${t.role}]`),t.label){let
|
|
350
|
+
})()`)}catch{return}if(!s||!s.summary||!s.summary.total)return;let r=s.summary.byKind??{},a=[],d=new Set;for(let p of Z){let b=r[p];if(b)if(d.add(p),p==="console"&&s.consoleSplit){let{error:f,warn:w}=s.consoleSplit;f>0&&a.push(`${f} error${f===1?"":"s"}`),w>0&&a.push(`${w} warning${w===1?"":"s"}`)}else a.push(`${b} ${p}${b===1?"":"s"}`)}for(let[p,b]of Object.entries(r))!d.has(p)&&b&&a.push(`${b} ${p}${b===1?"":"s"}`);if(a.length!==0&&(console.log(`
|
|
351
|
+
since last: ${a.join(" \xB7 ")} \u2014 sootsim what-happened`),s.summary.lastAt))try{await Oe(o,"SootSim.bridges.timeline.cursorAdvance",t,s.summary.lastAt)}catch{}}let pe=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"]),C=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"]),le=(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)),pe.has(g)&&await Xe(u),C.has(g)&&await ue(u,{verbose:le});try{switch(g){case"list":{await jt({bridge:u,simId:I,args:c});break}case"tree":{await Ht({bridge:u,args:c,positional:i});break}case"a11y":{let o=await it(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):
|
|
352
|
+
`);for(let t of o){let s=[];if(s.push(`[${t.role}]`),t.label){let r=t.label.length>50?t.label.slice(0,47)+"...":t.label;s.push(`"${r}"`)}if(t.hint&&s.push(`(hint: "${t.hint}")`),t.testID&&s.push(`#${t.testID}`),t.state){let r=[];t.state.disabled&&r.push("disabled"),t.state.selected&&r.push("selected"),t.state.checked===!0&&r.push("checked"),t.state.checked==="mixed"&&r.push("mixed"),t.state.busy&&r.push("busy"),t.state.expanded===!0&&r.push("expanded"),t.state.expanded===!1&&r.push("collapsed"),r.length&&s.push(`{${r.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 Dt({bridge:u,args:e,effectiveArgs:c,positional:i,inspectUsage:k});break}case"count":{await Et(u,{args:c});break}case"keyboard":{await Bt(u,{json:e.includes("--json")});break}case"screens":{await Jt(u,{json:e.includes("--json")});break}case"memory":{await Lt(u,{args:c});break}case"wait":{await Ut({wsPort:_,commandTimeoutMs:j,simId:I,simIdSource:E,positional:i});break}case"sleep":{await qt({positional:i,inspectUsage:k});break}case"settle":{await Wt({bridge:u,args:e,positional:i});break}case"ready":{await Xt({bridge:u,args:e});break}case"idle":{await Yt({bridge:u,args:e,positional:i});break}case"selector":{await Vt({bridge:u,args:e,positional:i,inspectUsage:k});break}case"event":{await Gt({bridge:u,args:e,positional:i,inspectUsage:k});break}case"layout":{let o=i[1];if(!o){await Ct({bridge:u,args:c});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((b,f)=>e[f-1]==="--output")||"/tmp/sootsim-inspect.png",s=await oo(e,u),r={type:"screenshot"};s&&(r.crop=s);let d=(await u.send(r)).replace(/^data:image\/png;base64,/,"");s&&console.log(` area: x=${s.x} y=${s.y} w=${s.w} h=${s.h}`),(await import("fs")).writeFileSync(t,Buffer.from(d,"base64")),console.log(` saved: ${t}`);break}case"sample-color":{let o=await oo(e,u);o||(console.error(k("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:kt(o)});if(e.includes("--json"))console.log(JSON.stringify(t,null,2));else{let{r:s,g:r,b:a,a:d,hex:p,samples:b}=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}, ${r}, ${a}, ${d}) ${f} ${b} samples`)}break}case"node":{let o=i[1];o||(console.error(k("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 () => {
|
|
348
353
|
const t = window.__sootsimTest
|
|
349
354
|
const q = ${JSON.stringify(o)}
|
|
350
355
|
let node = null
|
|
@@ -400,17 +405,17 @@ ${s}
|
|
|
400
405
|
transform,
|
|
401
406
|
parentChain,
|
|
402
407
|
}
|
|
403
|
-
})()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(
|
|
408
|
+
})()`});console.log(JSON.stringify(t,null,2));break}case"tap":{let o=Number(i[1]),t=Number(i[2]),s=he(e);if(s){let d=await ye(u,{agent:me(),textFallback:s.mode==="text"?s.value:void 0,resolve:async()=>{let f=await Te(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"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),de(d.result)||(N(`${s.mode} "${s.value}"`,d),process.exit(1));let b=no(p.cx,p.cy,d.result);b&&await L("inspect tap",b.step,b.summary),console.log(JSON.stringify({...d.attempts>1?{attempts:d.attempts}:{},...d.result},null,2));break}(!Number.isFinite(o)||!Number.isFinite(t))&&(console.error(k("tap","<x> <y> | --testid <id> | --text <t>")),process.exit(1));let r=await _t(u,o,t),a=no(o,t,r);a&&await L("inspect tap",a.step,a.summary),console.log(JSON.stringify(r,null,2));break}case"drag":case"swipe":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),r=Number(i[4]),a=g==="swipe"?10:12,d=g==="swipe"?8:16,p=i[5]?Number(i[5]):a,b=i[6]?Number(i[6]):d;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(p)||!Number.isFinite(b))&&(console.error(k(g,"<x1> <y1> <x2> <y2> [steps] [stepMs]")),process.exit(1));let f=await u.send({type:"evaluate",code:`(async () => {
|
|
404
409
|
const interact = window.__sootsimInteract
|
|
405
410
|
if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
|
|
406
|
-
const value = await interact.drag(${o}, ${t}, ${s}, ${
|
|
411
|
+
const value = await interact.drag(${o}, ${t}, ${s}, ${r}, ${Math.max(1,Math.round(p))}, ${Math.max(0,Math.round(b))})
|
|
407
412
|
return { ok: !!value, value }
|
|
408
|
-
})()`});if(f?.ok){let
|
|
413
|
+
})()`});if(f?.ok){let w=Math.max(1,Math.round(Math.max(1,p)*Math.max(0,b)));await L(`inspect ${g}`,{swipe:{start:`${o}, ${t}`,end:`${s}, ${r}`,duration:w}},`${g} ${o},${t} -> ${s},${r}`)}console.log(JSON.stringify(f,null,2));break}case"pinch":{let o=Number(i[1]),t=Number(i[2]),s=Number(i[3]),r=Number(i[4]),a=Number(i[5]),d=Number(i[6]),p=Number(i[7]),b=Number(i[8]),f=i[9]?Number(i[9]):12,w=i[10]?Number(i[10]):16;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(a)||!Number.isFinite(d)||!Number.isFinite(p)||!Number.isFinite(b)||!Number.isFinite(f)||!Number.isFinite(w))&&(console.error(k("pinch","<x1> <y1> <x2> <y2> <x1'> <y1'> <x2'> <y2'> [steps] [stepMs]")),process.exit(1));let O=await u.send({type:"evaluate",code:`(async () => {
|
|
409
414
|
const interact = window.__sootsimInteract
|
|
410
415
|
if (!interact?.pinch) return { ok: false, reason: 'no interact.pinch' }
|
|
411
|
-
const value = await interact.pinch(${o}, ${t}, ${s}, ${
|
|
416
|
+
const value = await interact.pinch(${o}, ${t}, ${s}, ${r}, ${a}, ${d}, ${p}, ${b}, ${Math.max(1,Math.round(f))}, ${Math.max(0,Math.round(w))})
|
|
412
417
|
return { ok: !!value, value }
|
|
413
|
-
})()`});O?.ok&&await
|
|
418
|
+
})()`});O?.ok&&await L("inspect pinch",{pinch:{from:[o,t,s,r],to:[a,d,p,b],steps:Math.max(1,Math.round(f)),stepMs:Math.max(0,Math.round(w))}},`pinch (${o},${t}) (${s},${r}) -> (${a},${d}) (${p},${b})`),console.log(JSON.stringify(O,null,2));break}case"tap-text":{let o=i[1];o||(console.error(k("tap-text","<text>")),process.exit(1));let t=U=>{let R=e.indexOf(U);return R>=0&&R+1<e.length?e[R+1]:null},s=U=>e.includes(U),r=t("--nth")??t("--index"),a=r!==null?Number(r):null;a!==null&&!Number.isFinite(a)&&(console.error(` --nth/--index requires an integer, got: ${r}`),process.exit(1));let d=t("--within"),p=t("--role"),b=s("--exact"),f=s("--first"),w=t("--min-y"),O=t("--max-y"),q=t("--min-x"),H=t("--max-x");for(let[U,R]of[["--min-y",w],["--max-y",O],["--min-x",q],["--max-x",H]])R!==null&&!Number.isFinite(Number(R))&&(console.error(` ${U} requires a number, got: ${R}`),process.exit(1));let K=e.indexOf("--near"),F=null;if(K>=0){let U=Number(e[K+1]),R=Number(e[K+2]);(!Number.isFinite(U)||!Number.isFinite(R))&&(console.error(" --near requires two numbers: --near <x> <y>"),process.exit(1)),F={x:U,y:R}}let x={exact:b,role:p,within:d,minX:q!==null?Number(q):null,maxX:H!==null?Number(H):null,minY:w!==null?Number(w):null,maxY:O!==null?Number(O):null,near:F,nth:a,first:f},$=await At(u,o,x,{agent:me()}),v=$.payload;if(v?.error==="bridge-not-ready"&&(console.error(" sootsim test bridge not ready"),process.exit(1)),v?.ambiguous){let U=v.candidates;console.error(` ambiguous: ${v.total} matches for "${o}"`);for(let R of U){let we=R.abs?`@(${Math.round(R.abs.x)},${Math.round(R.abs.y)})`:"",lo=R.layout?` ${R.layout.width}x${R.layout.height}`:"",co=R.testID?` #${R.testID}`:"",uo=R.text?` "${R.text}"`:"",mo=R.ancestorTestIDs.length>0?` within ${R.ancestorTestIDs.slice(0,3).map(po=>`#${po}`).join(" > ")}`:"";console.error(` [${R.idx}] <${R.type}>${uo}${co} ${we}${lo}${mo}`)}v.total>U.length&&console.error(` ... and ${v.total-U.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)}v?.nthOutOfRange&&(console.error(` not found: nth ${v.nth} of ${v.total} match${v.total===1?"":"es"} for "${o}"`),process.exit(1)),(!v||typeof v.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),de($.result)||(N(`text "${o}"`,$),process.exit(1));let se=qe(o,{id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},"text");await L("inspect tap-text",se.step,se.summary),console.log(JSON.stringify({matched:v.match,tapped:{nodeId:v.target?.nodeId??null,id:v.target?.id??null,testID:v.target?.testID??null,type:v.target?.type??null,cx:v.cx,cy:v.cy},...v.strategy&&v.strategy!=="matched-node"?{strategy:v.strategy}:{},...v.total>1||a!==null?{nth:{index:v.idx,total:v.total}}:{},...$.attempts>1?{attempts:$.attempts}:{},result:$.result},null,2));break}case"tap-best":{let o=i[1];o||(console.error(k("tap-best","<query>")),process.exit(1));let t=await Pt(u,o,{agent:me()}),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 r=s.node;de(t.result)||(N(`best "${o}"`,t),process.exit(1));let a=qe(o,{id:r.id,testID:r.testID,type:r.type,cx:s.cx,cy:s.cy},s.strategy==="testid"?"id":"text");await L("inspect tap-best",a.step,a.summary),console.log(JSON.stringify({matched:{strategy:s.strategy,nodeId:r.nodeId,id:r.id,testID:r.testID,type:r.type,text:r.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(k("tap-id","<id>")),process.exit(1));let t=await Ot(u,o,{agent:me()}),s=t.payload;(!s||typeof s.cx!="number")&&(console.error(` not found: ${o}`),await Co(u,o),process.exit(1)),de(t.result)||(N(`id "${o}"`,t),process.exit(1));let r=qe(o,{id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},"id");await L("inspect tap-id",r.step,r.summary),console.log(JSON.stringify({matched:s.match,tapped:{nodeId:s.target?.nodeId??null,id:s.target?.id??null,testID:s.target?.testID??null,type:s.target?.type??null,cx:s.cx,cy:s.cy},...s.strategy&&s.strategy!=="matched-node"?{strategy:s.strategy}:{},...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(k("type-into","<id> <text>")),process.exit(1));let s=JSON.stringify(o),r=await u.send({type:"evaluate",code:`(async () => {
|
|
414
419
|
const t = window.__sootsimTest
|
|
415
420
|
if (!t) return null
|
|
416
421
|
const n = await (t.findByTestId(${s}) || t.findById(${s}))
|
|
@@ -422,9 +427,10 @@ ${s}
|
|
|
422
427
|
testID: n.testID,
|
|
423
428
|
type: n.type,
|
|
424
429
|
isTextInput: !!n.isTextInput,
|
|
430
|
+
secureTextEntry: !!n.secureTextEntry,
|
|
425
431
|
placeholder: n.placeholder || null,
|
|
426
432
|
}
|
|
427
|
-
})()`});(!
|
|
433
|
+
})()`});(!r||typeof r.cx!="number")&&(console.error(` not found: ${o}`),process.exit(1)),r.isTextInput||console.error(` warning: ${o} is not a text input (isTextInput: false)`);let a=await u.send({type:"tap",x:r.cx,y:r.cy,target:{id:r.id??o,testID:r.testID??o,text:null,type:r.type??null}}),d=r.secureTextEntry===!0,p=await zo(u,1e3,{targetId:o,secureTextEntry:d});p.visible||(console.error(` keyboard did not open after tapping ${o}`),process.exit(1));let b=p.focusedInput;b&&(b.testID===o||b.id===o||(console.error(` focus routing mismatch after tap: requested ${JSON.stringify(o)} but focus is on ${JSON.stringify(b.testID??b.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||be(p),w=f?X:Le(t,p),O=f&&p.focusedInput?{...p.focusedInput,secureTextEntry:!0,text:typeof p.focusedInput.text=="string"?X:p.focusedInput.text}:p.focusedInput??null;await L("inspect type-into",{tapOn:{id:o},inputText:w},w===X?`type-into #${o} ${X}`:`type-into #${o} ${JSON.stringify(t)}`),console.log(JSON.stringify({target:o,isTextInput:r.isTextInput,secureTextEntry:f,keyboardOpened:p.visible??a?.keyboardOpened??!1,focusedInput:O,typed:w},null,2));break}case"type":{let o=i.slice(1).join(" ");o||(console.error(k("type","<text>")),process.exit(1));let t=await Ne(u,"type");await u.send({type:"keyboard",action:"type",text:o});let s=Le(o,t);await L("inspect type",{inputText:s},s===X?`type ${X}`:`type ${JSON.stringify(o)}`),console.log(s===X?` typed: ${X}`:` typed: ${JSON.stringify(o)}`);break}case"key":{let o=i[1];o||(console.error(k("key","<name>")),process.exit(1)),await Ne(u,"key"),await u.send({type:"keyboard",action:"press",text:o}),await L("inspect key",{pressKey:o},`key ${o}`),console.log(` pressed: ${o}`);break}case"key-sequence":{let o=i.slice(1);o.length===0&&(console.error(k("key-sequence","<key> [<key> ...]")),process.exit(1)),await Ne(u,"key-sequence");for(let t of o)await u.send({type:"keyboard",action:"press",text:t});await L("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(k("keycode","<code> [<code> ...]")),process.exit(1));let t=o.map(r=>({code:r,key:Go(r)})),s=t.filter(r=>!r.key);s.length>0&&(console.error(` unsupported keycode(s): ${s.map(r=>r.code).join(", ")}`),process.exit(1)),await Ne(u,"keycode");for(let r of t)await u.send({type:"keyboard",action:"press",text:r.key});await L("inspect keycode",{pressKey:t.map(r=>r.key).join(" ")},`keycode ${o.join(" ")}`),console.log(` pressed: ${o.join(", ")}`);break}case"dispatch":{let o=i[1];o||(console.error(k("dispatch","<char>")),process.exit(1)),await u.send({type:"keyboard",action:"dispatchKey",text:o}),await L("inspect dispatch",{dispatchKey:o},`dispatch ${JSON.stringify(o)}`),console.log(` dispatched: ${o}`);break}case"dismiss":{await u.send({type:"keyboard",action:"dismiss"}),await L("inspect dismiss",{hideKeyboard:!0},"dismiss keyboard"),console.log(" keyboard dismissed");break}case"double-tap":{let o=Number(i[1]),t=Number(i[2]),s=he(e);if(s){let p=await Te(u,s);p||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=p.x,t=p.y}let r=i[3]?Number(i[3]):80;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(r))&&(console.error(k("double-tap","<x> <y> [gapMs] | --testid <id>")),process.exit(1));let a=Math.max(0,Math.round(r)),d=await u.send({type:"evaluate",code:`(async () => {
|
|
428
434
|
const interact = window.__sootsimInteract
|
|
429
435
|
if (interact?.doubleTap) {
|
|
430
436
|
return {
|
|
@@ -447,13 +453,13 @@ ${s}
|
|
|
447
453
|
first,
|
|
448
454
|
second,
|
|
449
455
|
}
|
|
450
|
-
})()`});
|
|
456
|
+
})()`});d?.ok&&await L("inspect double-tap",{doubleTapAtCoords:{x:o,y:t,gapMs:a}},`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=he(e),r=null;if(s){let f=await Te(u,s);f||(console.error(` not found: ${s.value}`),s.mode==="testid"&&Y("wait-selector-for-missing-testid",s.value),process.exit(1)),o=f.x,t=f.y,r={id:f.id??null,testID:f.testID??null,text:f.text??null,type:f.type??null}}let a=s?i[1]:i[3],d=a?Number(a):600;(!Number.isFinite(o)||!Number.isFinite(t)||!Number.isFinite(d))&&(console.error(k("long-press","<x> <y> [durationMs] | --testid <id>")),process.exit(1));let p=Math.max(0,Math.round(d)),b=await u.send({type:"longPress",x:o,y:t,durationMs:p,target:r});b?.ok&&await L("inspect long-press",{tapAtCoords:{x:o,y:t}},`long-press @${o},${t}`),console.log(JSON.stringify(b,null,2));break}case"touch":{let o=i[1],t=Number(i[2]),s=Number(i[3]),r=i[4]?Number(i[4]):999,a=o==="down"?"touchDown":o==="move"?"touchMove":o==="up"?"touchUp":o==="cancel"?"touchCancel":null;a||(console.error(k("touch","<down|move|up|cancel> <x> <y> [pointerId]")),process.exit(1)),o!=="cancel"&&(!Number.isFinite(t)||!Number.isFinite(s))&&(console.error(k("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} } }));`:"",b=await u.send({type:"evaluate",code:`(async () => {
|
|
451
457
|
${p}
|
|
452
458
|
const interact = window.__sootsimInteract
|
|
453
459
|
if (!interact?.${a}) return { ok: false, reason: 'no interact.${a}' }
|
|
454
|
-
const value = ${o==="cancel"?`await interact.${a}(${Math.max(1,Math.round(
|
|
460
|
+
const value = ${o==="cancel"?`await interact.${a}(${Math.max(1,Math.round(r))})`:`await interact.${a}(${t}, ${s}, ${Math.max(1,Math.round(r))})`}
|
|
455
461
|
return { ok: !!value, value }
|
|
456
|
-
})()`});b?.ok&&o!=="cancel"&&await
|
|
462
|
+
})()`});b?.ok&&o!=="cancel"&&await L("inspect touch",{tapAtCoords:{x:t,y:s}},`touch ${o} @${t},${s}`),console.log(JSON.stringify(b,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(k("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 r=await u.send({type:"evaluate",code:`(async () => {
|
|
457
463
|
const spec = globalThis.__sootsimDeviceSpec || {}
|
|
458
464
|
return {
|
|
459
465
|
width: spec.width || window.innerWidth || 393,
|
|
@@ -461,12 +467,12 @@ ${s}
|
|
|
461
467
|
statusBarHeight: spec.statusBarHeight || 0,
|
|
462
468
|
homeIndicatorHeight: spec.homeIndicatorHeight || 0,
|
|
463
469
|
}
|
|
464
|
-
})()`}),a=Number(
|
|
470
|
+
})()`}),a=Number(r?.width)||393,d=Number(r?.height)||852,p=Number(r?.statusBarHeight)||0,b=Number(r?.homeIndicatorHeight)||0,f=Math.round(a/2),w=Math.round(d/2),O=Math.max(24,p+18),q=Math.max(24,b+18),H=18,K=Math.min(220,Math.round(d*.24)),F=Math.min(180,Math.round(a*.32)),x=f,$=w,v=f,se=w;switch(t){case"scroll-up":$=w+Math.round(K/2),se=w-Math.round(K/2);break;case"scroll-down":$=w-Math.round(K/2),se=w+Math.round(K/2);break;case"scroll-left":x=f+Math.round(F/2),v=f-Math.round(F/2);break;case"scroll-right":x=f-Math.round(F/2),v=f+Math.round(F/2);break;case"swipe-from-left-edge":x=H,$=w,v=Math.min(a-H,H+F);break;case"swipe-from-right-edge":x=a-H,$=w,v=Math.max(H,a-H-F);break;case"swipe-from-top-edge":x=f,$=O,se=Math.min(d-q,O+K);break;case"swipe-from-bottom-edge":x=f,$=d-q,se=Math.max(O,d-q-K);break}let U=Math.max(8,Math.round(s/16)),R=Math.max(1,Math.round(s/U)),we=await u.send({type:"evaluate",code:`(async () => {
|
|
465
471
|
const interact = window.__sootsimInteract
|
|
466
472
|
if (!interact?.drag) return { ok: false, reason: 'no interact.drag' }
|
|
467
|
-
const value = await interact.drag(${
|
|
473
|
+
const value = await interact.drag(${x}, ${$}, ${v}, ${se}, ${U}, ${R})
|
|
468
474
|
return { ok: !!value, value }
|
|
469
|
-
})()`});
|
|
475
|
+
})()`});we?.ok&&await L("inspect gesture",{swipe:{start:`${x}, ${$}`,end:`${v}, ${se}`,duration:Math.max(1,Math.round(s))}},`gesture ${t}`),console.log(JSON.stringify({preset:t,from:{x,y:$},to:{x:v,y:se},result:we},null,2));break}case"scroll":{let o=he(e),t=Xo(e),s=o?.mode==="testid"?o.value:t==null?i[1]:null,r=o||t!=null?1:2,a=Number(i[r]),d=Number(i[r+1]);(!s&&t==null||!Number.isFinite(a)||!Number.isFinite(d))&&(console.error(k("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 () => {
|
|
470
476
|
const t = window.__sootsimTest
|
|
471
477
|
if (!t) return null
|
|
472
478
|
const n = ${t!=null?`await t.inspectByNodeId(${JSON.stringify(t)})`:`await t.findByTestId(${JSON.stringify(s)})
|
|
@@ -476,7 +482,7 @@ ${s}
|
|
|
476
482
|
cx: n.absolutePosition.x + (n.layout.width || 0) / 2,
|
|
477
483
|
cy: n.absolutePosition.y + (n.layout.height || 0) / 2,
|
|
478
484
|
}
|
|
479
|
-
})()`}),b=await G(
|
|
485
|
+
})()`}),b=await G(u,"scrollTo",t!=null?{nodeId:t}:s,a,d,!1);if(b?.ok){let f=t!=null?`node ${t}`:`#${s}`;await L("inspect scroll",{scrollTo:{...t!=null?{nodeId:t}:{id:s},x:a,y:d}},`scroll ${f} -> ${a},${d}`)}console.log(JSON.stringify({...b,...p?{at:{x:p.cx,y:p.cy}}:{}},null,2));break}case"state":{let o=i[1];if(n==="get"&&!o){let s=await G(u,"getRuntimeState"),r=await u.send({type:"evaluate",code:Se});if(s&&typeof s=="object"&&s.diagnostics&&(s.diagnostics.errors=r?.errors??0,s.diagnostics.warnings=r?.warnings??0),s&&typeof s=="object"&&s.shell==null)try{let a=await ce(u);a&&(s.shell=a)}catch{}console.log(JSON.stringify(s,null,2));break}if(!o||o==="--help"||o==="-h"){console.log(`
|
|
480
486
|
${h("state")} \u2014 dump raw runtime state
|
|
481
487
|
|
|
482
488
|
subcommands:
|
|
@@ -499,17 +505,19 @@ ${s}
|
|
|
499
505
|
${h("state")} scroll feed
|
|
500
506
|
${h("state")} scroll-hit 360 420
|
|
501
507
|
${h("state")} hit 200 720
|
|
502
|
-
`);break}let t;switch(o){case"shell":t=await
|
|
508
|
+
`);break}let t;switch(o){case"shell":t=await ce(u,500);break;case"worker":t=await Oe(u,"__sootsimRenderHost.queryStats");break;case"ownership":t=await u.send({type:"evaluate",code:`(() => {
|
|
503
509
|
const h = window.__sootsimRenderHost
|
|
504
510
|
if (!h || typeof h.getOwnershipSnapshot !== 'function') {
|
|
505
511
|
return { error: 'getOwnershipSnapshot not available' }
|
|
506
512
|
}
|
|
507
513
|
return h.getOwnershipSnapshot()
|
|
508
|
-
})()`});break;case"keyboard":t=await
|
|
514
|
+
})()`});break;case"keyboard":t=await u.send({type:"evaluate",code:`(async () => {
|
|
509
515
|
const kb = window.__sootsimKeyboard
|
|
510
516
|
const test = window.__sootsimTest
|
|
511
517
|
if (!kb) return { error: 'keyboard bridge not available' }
|
|
512
518
|
const layout = typeof kb.getLayout === 'function' ? kb.getLayout() : null
|
|
519
|
+
const secureTextEntry =
|
|
520
|
+
!!layout?.spec?.secureTextEntry && layout?.spec?.keyboardType !== 'visible-password'
|
|
513
521
|
const visible = kb.isVisible()
|
|
514
522
|
const mode = kb.getMode()
|
|
515
523
|
let focused = null
|
|
@@ -527,10 +535,11 @@ ${s}
|
|
|
527
535
|
testID: focused.testID || null,
|
|
528
536
|
id: focused.id || null,
|
|
529
537
|
placeholder: focused.placeholder || null,
|
|
530
|
-
|
|
538
|
+
secureTextEntry,
|
|
539
|
+
text: secureTextEntry ? ${JSON.stringify(X)} : (focused.text || null),
|
|
531
540
|
} : null,
|
|
532
541
|
}
|
|
533
|
-
})()`});break;case"node":{let s=
|
|
542
|
+
})()`}),t=Je(t);break;case"node":{let s=i[2];s||(console.error(` usage: ${h("state")} node <id>`),process.exit(1)),t=await G(u,"findByTestId",s)||await G(u,"findById",s);break}case"scroll":{let s=i[2];s||(console.error(` usage: ${h("state")} scroll <id>`),process.exit(1)),t=await G(u,"getScrollState",s);break}case"scroll-hit":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${h("state")} scroll-hit <x> <y>`),process.exit(1)),t=await G(u,"getScrollStateAt",s,r);break}case"hit":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${h("state")} hit <x> <y>`),process.exit(1)),t=await G(u,"debugHitAt",s,r);break}case"gesture":{let s=Number(i[2]),r=Number(i[3]);(!Number.isFinite(s)||!Number.isFinite(r))&&(console.error(` usage: ${h("state")} gesture <x> <y>`),process.exit(1)),t=await G(u,"debugGestureAt",s,r);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(`
|
|
534
543
|
${h("shell")} \u2014 run built-in shell commands
|
|
535
544
|
|
|
536
545
|
subcommands:
|
|
@@ -554,7 +563,7 @@ ${s}
|
|
|
554
563
|
${h("shell")} open-card clock 800
|
|
555
564
|
${h("shell")} appearance dark
|
|
556
565
|
${h("shell")} lock
|
|
557
|
-
`);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?
|
|
566
|
+
`);break}let t=o==="launch"||o==="open-card"||o==="home"||o==="switcher",s=o==="launch"||o==="open-card"?i[3]:i[2],r=s?Number(s):350;t&&(!Number.isFinite(r)||r<0)&&(console.error(k("shell",o==="launch"||o==="open-card"?"<launch|open-card> <appId> [settleMs]":"<home|switcher> [settleMs]")),process.exit(1));let a=!1,d=!1,p=null,b=e.includes("--clear-state");if(o==="launch"){let f=i[2];f||(console.error(k("shell","launch <appId> [settleMs] [--clear-state]")),process.exit(1)),b&&await u.send({type:"evaluate",code:Qe(!0)}),a=!!await fe(u,"launchApp",r,f),{settled:d,state:p}=await Ie(u,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.launchProgress=="number"&&w.launchProgress>=.98),a&&await L("inspect shell launch",b?{launchApp:{clearState:!0}}:{launchApp:{}},b?"launch app (clear state)":"launch app")}else if(o==="home")a=!!await fe(u,"goHome",r),{settled:d,state:p}=await Ie(u,Math.round(r),f=>!!f&&f.state==="home"&&f.activeApp==null&&f.showSwitcher===!1&&f.switcherPhase==="idle"&&typeof f.launchProgress=="number"&&f.launchProgress>=.98);else if(o==="switcher")a=!!await fe(u,"openSwitcher",r),{settled:d,state:p}=await Ie(u,Math.round(r),f=>!!f&&f.state==="app"&&f.showSwitcher===!0&&f.switcherPhase==="idle"&&typeof f.zoomLevel=="number"&&Math.abs(f.zoomLevel)<=.02&&typeof f.horizontalZoom=="number"&&Math.abs(f.horizontalZoom)<=.02),d&&(await ee(Ko),p=await ce(u));else if(o==="open-card"){let f=i[2];f||(console.error(k("shell","open-card <appId> [settleMs]")),process.exit(1)),a=!!await fe(u,"openSwitcherCard",r,f),{settled:d,state:p}=await Ie(u,Math.round(r),w=>!!w&&w.state==="app"&&w.activeApp===f&&w.showSwitcher===!1&&w.switcherPhase==="idle"&&typeof w.zoomLevel=="number"&&w.zoomLevel>=.98&&typeof w.horizontalZoom=="number"&&w.horizontalZoom>=.98),a&&await L("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(k("shell","appearance <light|dark|auto|toggle>")),process.exit(1));let w=await so(u,"appearance",f);if(a=!!w?.ok,p={appearance:w},a){let O=w?.applied??f;console.log(` appearance: ${O}`)}}else if(o==="lock"||o==="shake"){let f=await so(u,o);a=!!f?.ok,p={[o]:f}}else console.error(` unknown shell subcommand: ${o}`),process.exit(1);console.log(JSON.stringify({ok:a,settled:d,state:p},null,2));break}case"url":{await Kt(u,{args:c});break}case"reload":{let s=!1,r=!1;try{await u.send({type:"evaluate",code:"window.__sootsimConsole?.clear()"});let p=await u.send({type:"evaluate",code:`;(() => {
|
|
558
567
|
const reloadExternalApp = window.SootSim?.bridges?.hotRemount?.reloadExternalApp
|
|
559
568
|
if (typeof reloadExternalApp === 'function') {
|
|
560
569
|
reloadExternalApp()
|
|
@@ -562,10 +571,10 @@ ${s}
|
|
|
562
571
|
}
|
|
563
572
|
window.location.reload()
|
|
564
573
|
return { kind: 'page' }
|
|
565
|
-
})()`});
|
|
574
|
+
})()`});r=!!p&&p.kind==="external-app",s=!0}catch{}console.log(" reloading...");let a=u,d=null;if(r)d=await De(u,{timeoutMs:1e4,errorGraceMs:3e3});else{s&&await ee(300);let p=await $t(_,j,I,{timeoutMs:1e4,simIdSource:E});p?(a=p,d=await De(p,{timeoutMs:1e4,errorGraceMs:3e3})):(console.log(" \u26A0 reload: bridge never reconnected within 10000ms"),a=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=Jo(d);console.log(` \u26A0 reload timed out after ${d.elapsedMs}ms \u2014 ${p} (nodes: ${d.nodes}, targets: ${d.targets}, errors: ${d.errors})`)}if(a)try{let p=await $e(a,10);if(a!==u&&a.close(),Array.isArray(p)&&p.length>0){console.log(`
|
|
566
575
|
\u26A0 ${p.length} error(s) during mount:
|
|
567
|
-
`);for(let b of p){let f=b.args.map(
|
|
568
|
-
`).slice(0,2);for(let O of
|
|
576
|
+
`);for(let b of p){let f=b.args.map(w=>typeof w=="object"?JSON.stringify(w):w).join(" ");if(console.log(` ${f}`),b.stack){let w=b.stack.split(`
|
|
577
|
+
`).slice(0,2);for(let O of w)console.log(` ${O.trim()}`)}}}}catch{}d&&!d.ready&&(process.exitCode=1);break}case"eval":case"js":{let o=i.slice(1).join(" ");o||(console.error(k("js","<javascript>")),console.error(""),console.error(" runs the snippet in the engine realm. SootSim is the"),console.error(" canonical state surface \u2014 reach into it directly."),console.error(""),console.error(" examples:"),console.error(` ${h("js")} SootSim.bridges.test.findByText("Sign in")`),console.error(` ${h("js")} SootSim.bridges.debug.snapshot("before")`),console.error(` ${h("js")} SootSim.bridges.keyboard.type("hello")`),console.error(` ${h("js")} SootSim.state.root.children.length`),process.exit(1));let 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 r=o.toLowerCase(),a=[];(r.includes("sootsim:gohome")||r.includes("gohome"))&&a.push("sootsim shell home"),(r.includes("sootsim:appswitcher")||r.includes("appswitcher"))&&a.push("sootsim shell switcher"),(r.includes("keyboard.isvisible")||r.includes("keyboard.getmode"))&&a.push("sootsim debug state keyboard"),r.includes("interact.tap")&&a.push("sootsim do tap <x> <y>"),r.includes("keyboard.type")&&a.push("sootsim do type <text>"),(r.includes("keyboard.press")||r.includes("keyboard.dispatchkey"))&&a.push("sootsim do key <name>"),r.includes("keyboard.dismiss")&&a.push("sootsim do dismiss"),r.includes("dumptree")&&a.push("sootsim get tree"),r.includes("dumpaccessibilitytree")&&a.push("sootsim get a11y"),r.includes("getnodecount")&&a.push("sootsim get count"),r.includes("findbytext")&&a.push("sootsim find <text>"),(r.includes("findbytestid")||r.includes("findbyid"))&&a.push("sootsim find --testid <id>"),r.includes("document.hidden")&&a.push("sootsim debug state keyboard (includes tab health)"),a.length>0&&Y("prefer-cli-over-eval",a);break}case"globals":{let o=await u.send({type:"evaluate",code:`(async () => {
|
|
569
578
|
const globals = {}
|
|
570
579
|
|
|
571
580
|
// test bridge (proxy in worker mode)
|
|
@@ -603,7 +612,7 @@ ${s}
|
|
|
603
612
|
|
|
604
613
|
return globals
|
|
605
614
|
})()`});console.log(` sootsim JS API:
|
|
606
|
-
`);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let
|
|
615
|
+
`);for(let[t,s]of Object.entries(o)){console.log(` ${t}:`);for(let r of s)console.log(` .${r}`);console.log("")}console.log(` use: ${h("js")} <expression>`),console.log(` example: ${h("js")} test.findByText("Sign in")`);break}case"describe":{await Rt({bridge:u,args:e,positional:i});break}case"perf":{let o=i[1];if(!o||o==="--help"||o==="-h"){console.log(`
|
|
607
616
|
${h("perf")} \u2014 performance profiling
|
|
608
617
|
|
|
609
618
|
subcommands:
|
|
@@ -624,7 +633,7 @@ ${s}
|
|
|
624
633
|
${h("perf")} stop
|
|
625
634
|
${h("perf")} stop --json
|
|
626
635
|
${h("perf")} transition goHome
|
|
627
|
-
`);break}switch(o){case"stats":{let t=await
|
|
636
|
+
`);break}switch(o){case"stats":{let t=await u.send({type:"evaluate",code:`(async () => {
|
|
628
637
|
// worker mode (host exposes these)
|
|
629
638
|
if (window.__sootsimPerfStats) {
|
|
630
639
|
return await window.__sootsimPerfStats()
|
|
@@ -649,17 +658,17 @@ ${s}
|
|
|
649
658
|
jankFrames: frameStats.recentFrames?.filter(f => f > 16.67).length || 0,
|
|
650
659
|
recentCount: frameStats.recentFrames?.length || 0,
|
|
651
660
|
}
|
|
652
|
-
})()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(
|
|
661
|
+
})()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){P(t);break}let s=t.avgMs==="?"&&t.maxMs==="?",r=t.avgMs!=="?"?(1e3/parseFloat(t.avgMs)).toFixed(1):"?";console.log(" perf stats:"),console.log(` frames: ${t.frames}`),console.log(` avg: ${t.avgMs}ms (${r} fps)`),console.log(` max: ${t.maxMs}ms`),console.log(` layout: ${t.layoutMs}ms total`),console.log(` nodes: ${t.nodeCount}`),t.recentCount>0&&console.log(` jank: ${t.jankFrames}/${t.recentCount} frames >16.67ms`),s&&process.stderr.write(`
|
|
653
662
|
\u26A0 frame timings are zero \u2014 enable them first:
|
|
654
663
|
sootsim debug perf start # begin recording
|
|
655
664
|
# \u2026 interact / run a flow / wait for the transition \u2026
|
|
656
665
|
sootsim debug perf stop # full report
|
|
657
666
|
sootsim debug perf stats # one-shot snapshot
|
|
658
|
-
`);break}case"start":{await
|
|
667
|
+
`);break}case"start":{await u.send({type:"evaluate",code:`(async () => {
|
|
659
668
|
// worker mode
|
|
660
669
|
if (window.__sootsimPerfStart && window.__sootsimRenderHost) {
|
|
661
670
|
const result = window.__sootsimPerfStart()
|
|
662
|
-
window.${
|
|
671
|
+
window.${ne} = {
|
|
663
672
|
active: true,
|
|
664
673
|
mode: 'render-worker',
|
|
665
674
|
lastSamples: [],
|
|
@@ -670,23 +679,23 @@ ${s}
|
|
|
670
679
|
// main-thread mode
|
|
671
680
|
window.__sootsimPerf?.enableFrameStats?.(true)
|
|
672
681
|
window.__sootsimA11y?.resetProfile?.()
|
|
673
|
-
window.${
|
|
682
|
+
window.${ne} = {
|
|
674
683
|
active: true,
|
|
675
684
|
mode: 'main-thread',
|
|
676
685
|
lastSamples: [],
|
|
677
686
|
startedAt: performance.now(),
|
|
678
687
|
}
|
|
679
688
|
return { started: true }
|
|
680
|
-
})()`}),console.log(` profiling started \u2014 interact with the app, then run '${h("perf")} stop'`);break}case"stop":{let t=await
|
|
689
|
+
})()`}),console.log(` profiling started \u2014 interact with the app, then run '${h("perf")} stop'`);break}case"stop":{let t=await u.send({type:"evaluate",code:`(async () => {
|
|
681
690
|
// worker mode
|
|
682
691
|
if (window.__sootsimRenderHost) {
|
|
683
|
-
const session = window.${
|
|
692
|
+
const session = window.${ne} || {}
|
|
684
693
|
const priorSamples = session.active && Array.isArray(session.lastSamples)
|
|
685
694
|
? session.lastSamples
|
|
686
695
|
: []
|
|
687
696
|
const flushedSamples = await window.__sootsimRenderHost.flushSamples()
|
|
688
697
|
const samples = priorSamples.concat(flushedSamples)
|
|
689
|
-
window.${
|
|
698
|
+
window.${ne} = {
|
|
690
699
|
...session,
|
|
691
700
|
active: false,
|
|
692
701
|
mode: 'render-worker',
|
|
@@ -750,8 +759,8 @@ ${s}
|
|
|
750
759
|
|
|
751
760
|
// disable collection
|
|
752
761
|
perf?.disableFrameStats?.()
|
|
753
|
-
window.${
|
|
754
|
-
...(window.${
|
|
762
|
+
window.${ne} = {
|
|
763
|
+
...(window.${ne} || {}),
|
|
755
764
|
active: false,
|
|
756
765
|
mode: 'main-thread',
|
|
757
766
|
lastSamples: recent.map((ms, index) => [index, ms, 0, 0, 0, 0, 0]),
|
|
@@ -771,16 +780,16 @@ ${s}
|
|
|
771
780
|
jankFrames: recent.filter(f => f > 16.67).length,
|
|
772
781
|
sampleCount: recent.length,
|
|
773
782
|
}
|
|
774
|
-
})()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(
|
|
775
|
-
`),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 (${
|
|
783
|
+
})()`});if(t.error&&(console.error(` error: ${t.error}`),process.exit(1)),A(c)){P(t);break}let s=t.avgMs>0?(1e3/t.avgMs).toFixed(1):"?",r=t.sampleCount>0?(t.jankFrames/t.sampleCount*100).toFixed(1):"0";console.log(` profiling stopped:
|
|
784
|
+
`),console.log(` frames: ${t.frames}`),console.log(` total: ${t.totalMs.toFixed(1)}ms`),console.log(` avg: ${t.avgMs.toFixed(2)}ms (${s} fps)`),console.log(` max: ${t.maxMs.toFixed(2)}ms`),console.log(""),t.layoutAvgMs!==void 0&&(console.log(" breakdown (avg per frame):"),console.log(` layout: ${t.layoutAvgMs.toFixed(2)}ms`),console.log(` render: ${t.renderAvgMs.toFixed(2)}ms`),console.log(` copy: ${t.copyAvgMs.toFixed(2)}ms`),t.auxAvgMs!==void 0&&console.log(` aux: ${t.auxAvgMs.toFixed(2)}ms`),t.otherAvgMs!==void 0&&console.log(` other: ${t.otherAvgMs.toFixed(2)}ms`),console.log("")),console.log(` distribution (${t.sampleCount} samples):`),console.log(` p50: ${t.p50.toFixed(2)}ms`),console.log(` p95: ${t.p95.toFixed(2)}ms`),console.log(` p99: ${t.p99.toFixed(2)}ms`),console.log(` jank: ${t.jankFrames} frames (${r}%) >16.67ms`);break}case"frames":{let t=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 () => {
|
|
776
785
|
if (window.__sootsimRenderHost) {
|
|
777
|
-
const session = window.${
|
|
786
|
+
const session = window.${ne} || {}
|
|
778
787
|
if (session.active) {
|
|
779
788
|
const priorSamples = Array.isArray(session.lastSamples) ? session.lastSamples : []
|
|
780
789
|
const flushedSamples = await window.__sootsimRenderHost.flushSamples()
|
|
781
790
|
const samples = priorSamples.concat(flushedSamples)
|
|
782
791
|
window.__sootsimRenderHost.startSampling()
|
|
783
|
-
window.${
|
|
792
|
+
window.${ne} = {
|
|
784
793
|
...session,
|
|
785
794
|
active: true,
|
|
786
795
|
mode: 'render-worker',
|
|
@@ -807,15 +816,15 @@ ${s}
|
|
|
807
816
|
mode: 'main-thread',
|
|
808
817
|
frames: (stats.recentFrames || []).slice(-${t}),
|
|
809
818
|
}
|
|
810
|
-
})()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(
|
|
819
|
+
})()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){P(s);break}if(s.mode==="render-worker"){let a=Array.isArray(s.samples)?s.samples:[];if(a.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${a.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,b,f,w,O,q]of a)console.log(` ${p.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(d).padStart(5)}`);console.log(""),We(a.map(d=>d[1])),s.live&&console.log(" sampling continues");break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` last ${r.length} frame times (ms):`),console.log(` ${r.map(a=>a.toFixed(2)).join(", ")}`),We(r);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 () => {
|
|
811
820
|
if (window.__sootsimRenderHost) {
|
|
812
|
-
const session = window.${
|
|
821
|
+
const session = window.${ne} || {}
|
|
813
822
|
if (session.active) {
|
|
814
823
|
const priorSamples = Array.isArray(session.lastSamples) ? session.lastSamples : []
|
|
815
824
|
const flushedSamples = await window.__sootsimRenderHost.flushSamples()
|
|
816
825
|
const samples = priorSamples.concat(flushedSamples)
|
|
817
826
|
window.__sootsimRenderHost.startSampling()
|
|
818
|
-
window.${
|
|
827
|
+
window.${ne} = {
|
|
819
828
|
...session,
|
|
820
829
|
active: true,
|
|
821
830
|
mode: 'render-worker',
|
|
@@ -849,7 +858,7 @@ ${s}
|
|
|
849
858
|
mode: 'main-thread',
|
|
850
859
|
frames: recent.slice().sort((a, b) => b - a).slice(0, ${t}),
|
|
851
860
|
}
|
|
852
|
-
})()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(
|
|
861
|
+
})()`});if(s.error&&(console.error(` error: ${s.error}`),process.exit(1)),A(c)){P(s);break}if(s.mode==="render-worker"){let a=Array.isArray(s.samples)?s.samples:[];if(a.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${a.length} sampled frames (ms):`),console.log(" total layout render copy aux other t+");for(let[d,p,b,f,w,O,q]of a)console.log(` ${p.toFixed(2).padStart(7)} ${b.toFixed(2).padStart(7)} ${f.toFixed(2).padStart(7)} ${w.toFixed(2).padStart(7)} ${O.toFixed(2).padStart(6)} ${q.toFixed(2).padStart(7)} ${String(d).padStart(5)}`);s.live&&(console.log(""),console.log(" sampling continues"));break}let r=Array.isArray(s.frames)?s.frames:Array.isArray(s)?s:[];if(r.length===0){console.log(` no frame data \u2014 run '${h("perf")} start' first`);break}console.log(` worst ${r.length} frame times (ms):`),console.log(` ${r.map(a=>a.toFixed(2)).join(", ")}`);break}case"transition":{let t=i[2];if(!t||!["goHome","appSwitcher","lockScreen"].includes(t)){console.log(`
|
|
853
862
|
${h("perf")} transition <event> \u2014 profile a shell transition
|
|
854
863
|
|
|
855
864
|
events:
|
|
@@ -862,7 +871,7 @@ ${s}
|
|
|
862
871
|
examples:
|
|
863
872
|
${h("perf")} transition goHome --timeout 10000
|
|
864
873
|
${h("perf")} transition appSwitcher
|
|
865
|
-
`);break}let
|
|
874
|
+
`);break}let r=`sootsim:${t}`;Re(` profiling ${t} transition...`),Re(" (use --timeout 10000 if this times out)");let a=await u.send({type:"evaluate",code:`(async () => {
|
|
866
875
|
// only supported in render-worker mode
|
|
867
876
|
if (!window.__sootsimRenderHost) {
|
|
868
877
|
return { error: 'transition profiling requires render-worker mode' }
|
|
@@ -875,7 +884,7 @@ ${s}
|
|
|
875
884
|
await new Promise(r => requestAnimationFrame(() => r(undefined)))
|
|
876
885
|
|
|
877
886
|
// dispatch the shell event
|
|
878
|
-
window.dispatchEvent(new Event('${
|
|
887
|
+
window.dispatchEvent(new Event('${r}'))
|
|
879
888
|
|
|
880
889
|
// wait 600ms for transition to complete (shell animations are ~300-500ms)
|
|
881
890
|
// using fixed timing avoids complex animation-end detection
|
|
@@ -921,11 +930,11 @@ ${s}
|
|
|
921
930
|
jankFrames: frameTimes.filter(f => f > 16.67).length,
|
|
922
931
|
samples,
|
|
923
932
|
}
|
|
924
|
-
})()`});if(a.error&&(console.error(` error: ${a.error}`),process.exit(1)),A(
|
|
933
|
+
})()`});if(a.error&&(console.error(` error: ${a.error}`),process.exit(1)),A(c)){P(a);break}if(a.warning&&console.log(` warning: ${a.warning}`),a.frames===0){console.log(" no frames captured");break}let d=a.avgMs>0?(1e3/a.avgMs).toFixed(1):"?",p=a.frames>0?(a.jankFrames/a.frames*100).toFixed(1):"0";console.log(` ${t} transition profiled:
|
|
925
934
|
|
|
926
935
|
frames: ${a.frames}
|
|
927
936
|
total: ${a.totalMs.toFixed(1)}ms
|
|
928
|
-
avg: ${a.avgMs.toFixed(2)}ms (${
|
|
937
|
+
avg: ${a.avgMs.toFixed(2)}ms (${d} fps)
|
|
929
938
|
max: ${a.maxMs.toFixed(2)}ms
|
|
930
939
|
|
|
931
940
|
breakdown (avg per frame):
|
|
@@ -939,29 +948,29 @@ ${s}
|
|
|
939
948
|
p50: ${a.p50.toFixed(2)}ms
|
|
940
949
|
p95: ${a.p95.toFixed(2)}ms
|
|
941
950
|
p99: ${a.p99.toFixed(2)}ms
|
|
942
|
-
jank: ${a.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(a.samples)&&a.samples.length>0&&(console.log(""),
|
|
943
|
-
`);for(let
|
|
944
|
-
`).slice(0,3);for(let b of p)console.log(` ${b.trim()}`)}}break}case"warnings":{let o=
|
|
945
|
-
`);for(let s of t){let
|
|
946
|
-
`);for(let t of o){let s=String(t.kind).padEnd(6),
|
|
947
|
-
`);for(let
|
|
951
|
+
jank: ${a.jankFrames} frames (${p}%) >16.67ms`),Array.isArray(a.samples)&&a.samples.length>0&&(console.log(""),We(a.samples.map(b=>b[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 dt(u),A(c)?P({cleared:!0}):console.log(" error buffer cleared");break}let t=o?Number(o):20,s=await $e(u,t);if(A(c)){P(s);break}if(s.length===0){console.log(" no errors captured");break}console.log(` ${s.length} error(s):
|
|
952
|
+
`);for(let r of s){let a=ie(r.timestamp),d=r.args.map(p=>typeof p=="object"?JSON.stringify(p):p).join(" ");if(console.log(` [${a}] ${d}`),r.stack){let p=r.stack.split(`
|
|
953
|
+
`).slice(0,3);for(let b of p)console.log(` ${b.trim()}`)}}break}case"warnings":{let o=i[1]?Number(i[1]):20,t=await ut(u,o);if(A(c)){P(t);break}if(t.length===0){console.log(" no warnings captured");break}console.log(` ${t.length} warning(s):
|
|
954
|
+
`);for(let s of t){let r=ie(s.timestamp),a=s.args.map(d=>typeof d=="object"?JSON.stringify(d):d).join(" ");console.log(` [${r}] ${a}`)}break}case"animations":{let o=await G(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):
|
|
955
|
+
`);for(let t of o){let s=String(t.kind).padEnd(6),r=`${Number(t.from).toFixed(2)}\u2192${Number(t.to).toFixed(2)}`,a=Number(t.current??0).toFixed(2),d=`${Math.round((t.progress??0)*100)}%`,p=`${Math.round(t.elapsedMs??0)}ms`,b=t.loop?" loop":"",f=t.layoutBound?" layout":"";console.log(` #${t.id} ${s} ${r.padEnd(14)} cur=${a.padEnd(7)} ${d.padStart(4)} ${p}${b}${f}`)}break}case"animation":{let o=i[1];(!o||o==="--help"||o==="-h")&&(console.error(` usage: ${h("animation")} <id>`),process.exit(1));let t=Number(o);Number.isFinite(t)||(console.error(` invalid id: ${o}`),process.exit(1));let s=await G(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: ${h("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 G(u,"stopAnimation",t);console.log(` stopped ${s??0} animation(s)`);break}case"requests":{let o=i[1];if(o==="clear"){await pt(u),A(c)?P({cleared:!0}):console.log(" request buffer cleared");break}let t=o==="all",s=t?i[2]:o,r=s?Number(s):20,a=await mt(u,{failed:!t,limit:r});if(A(c)){P(a);break}if(a.length===0){console.log(t?" no requests captured":" no failed requests captured");break}console.log(` ${a.length} ${t?"request(s)":"failed request(s)"}:
|
|
956
|
+
`);for(let d of a){let p=ie(d.timestamp);console.log(` [${p}] ${oe(d)}`),d.responseBody?console.log(` ${d.responseBody}`):d.error&&console.log(` ${d.error}`)}break}case"network":{let o=i[1],t=null,s=null,r=!1,a=!1,d=1e3,p=!1,b=!1;for(let F=0;F<c.length;F++){let x=c[F];if(x==="--filter")t=c[F+1]??null,F++;else if(x==="--limit"){let $=Number(c[F+1]);Number.isFinite($)&&(s=$),F++}else if(x==="--threshold"){let $=Number(c[F+1]);Number.isFinite($)&&$>0&&(d=$),F++}else x==="--failed"?r=!0:x==="--slow"?a=!0:x==="--tail"||x==="-f"?p=!0:x==="--json"&&(b=!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 F=i[2];F||(console.error(" usage: sootsim network get <id>"),process.exit(1));let x=await u.send({type:"evaluate",code:`(() => {
|
|
948
957
|
const obs = window.__sootsimObservability;
|
|
949
958
|
if (!obs) return null;
|
|
950
959
|
return obs.network.getSnapshot().find(e => e.id === ${JSON.stringify(F)}) || null;
|
|
951
|
-
})()`});
|
|
952
|
-
to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let
|
|
960
|
+
})()`});x||(console.error(` no entry with id ${F}`),process.exit(1)),b?console.log(JSON.stringify(x,null,2)):Wo(x);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. ${h("network")} 100).
|
|
961
|
+
to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let w=async()=>{let F=await u.send({type:"evaluate",code:`(() => {
|
|
953
962
|
const obs = window.__sootsimObservability;
|
|
954
963
|
if (!obs) return { ok: false };
|
|
955
964
|
return { ok: true, entries: obs.network.getSnapshot() };
|
|
956
|
-
})()`});if(!F||!F.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return F.entries??[]},O=F=>{let
|
|
957
|
-
`:` ${
|
|
958
|
-
`);for(let $ of
|
|
959
|
-
`);let q=new Set,H=!0,
|
|
960
|
-
to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let O=()=>
|
|
961
|
-
`);for(let v of $)
|
|
962
|
-
`);let H=new Set,
|
|
965
|
+
})()`});if(!F||!F.ok)throw new Error("observability bridge not installed \u2014 is the engine running?");return F.entries??[]},O=F=>{let x=F;if(r&&(x=x.filter($=>!!$.error||$.status!=null&&$.status>=400)),a&&(x=x.filter($=>$.durationMs!=null&&$.durationMs>=d)),t){let $=t.toLowerCase();x=x.filter(v=>(v.displayUrl||v.url).toLowerCase().includes($))}return a&&!p&&(x=[...x].sort(($,v)=>(v.durationMs??0)-($.durationMs??0))),x};if(!p){let F=await w(),x=O(F).slice(-f);if(b){console.log(JSON.stringify(x,null,2));break}if(x.length===0){F.length===0?console.log(" no network requests captured"):console.log(a?` no requests slower than ${d}ms (${F.length} total \u2014 try --threshold <ms>)`:" no matching requests");break}console.log(a?` ${x.length} request(s) slower than ${d}ms (sorted by duration desc):
|
|
966
|
+
`:` ${x.length} request(s):
|
|
967
|
+
`);for(let $ of x)Zt($);break}console.log(` tailing network (ctrl-c to stop)...
|
|
968
|
+
`);let q=new Set,H=!0,K=()=>{H=!1};process.on("SIGINT",K);try{for(;H;){let F=await w(),x=O(F);for(let $ of x)$.durationMs!=null&&(q.has($.id)||(q.add($.id),b?console.log(JSON.stringify($)):Zt($)));await ee(250)}}finally{process.off("SIGINT",K)}break}case"logs":{let o=i[1],t=null,s=null,r=null,a=!1,d=!1,p=!1;for(let x=0;x<c.length;x++){let $=c[x];if($==="--filter")t=c[x+1]??null,x++;else if($==="--limit"){let v=Number(c[x+1]);Number.isFinite(v)&&(s=v),x++}else $==="--level"?(r=c[x+1]??null,x++):$==="--tail"||$==="-f"?a=!0:$==="--json"?d=!0:($==="--internal"||$==="--all")&&(p=!0)}let b=r?new Set(r.split(",").map(x=>x.trim()).filter(x=>x==="log"||x==="info"||x==="warn"||x==="error"||x==="debug")):null;if(o==="clear"){await gt(u),console.log(" log buffer cleared");break}let f=!d&&process.stdout.isTTY===!0,w=s??(a?500:o?Number(o):50);Number.isFinite(w)||(console.error(` invalid limit: ${o} \u2014 \`logs\` takes a numeric count (e.g. ${h("logs")} 100).
|
|
969
|
+
to target a specific sim, use \`--sim ${o}\` instead.`),process.exit(1));let O=()=>ft(u),q=x=>yt(x,{level:b,filter:t,showInternal:p});if(!a){let x=await O(),$=q(x).slice(-w);if(d){console.log(JSON.stringify($,null,2));break}if($.length===0){console.log(x.length===0?" no logs captured":" no matching logs");break}console.log(` ${$.length} log(s):
|
|
970
|
+
`);for(let v of $)to(v,f);break}console.log(` tailing logs (ctrl-c to stop)...
|
|
971
|
+
`);let H=new Set,K=!0,F=()=>{K=!1};process.on("SIGINT",F);try{for(;K;){let x=await O(),$=q(x);for(let v of $)H.has(v.id)||(H.add(v.id),d?console.log(JSON.stringify(v)):to(v,f));await ee(250)}}finally{process.off("SIGINT",F)}break}default:console.error(` unknown subcommand: ${g}`),process.exit(1)}if(pe.has(g)&&!e.includes("--no-wait")&&process.env.SOOTSIM_NO_AUTO_WAIT!=="1"&&!await Ze(u,g)&&await S(u),!B.has(g)&&!A(c))try{await re(u)}catch{}}catch(o){let t=o instanceof Error?o.message:String(o);console.error(` ${g??"inspect"} failed: ${t}`);let s=/^no sim connected with id (.+)$/.exec(t),r=/^command timed out after (\d+)s$/.exec(t),a=t.startsWith("sim disconnected:")||t.startsWith("bridge never reconnected")||t.startsWith("could not connect to ws://");if(s)await Mt(u,_,s[1]);else if(/^no sim connected$/.test(t))Tt(_);else if(r)if(await Do(u)){let p=g??"describe";process.stderr.write(` the sim is still responsive \u2014 '${p}' just exceeded the ${r[1]}s command budget.
|
|
963
972
|
the screen's node tree is large; narrow the query or raise the budget:
|
|
964
973
|
sootsim ${p} --testid <id> # scope to one subtree
|
|
965
974
|
sootsim find --testid <id> # targeted single-node lookup
|
|
966
975
|
sootsim ${p} --timeout 60000 # raise per-command budget (ms)
|
|
967
|
-
`)}else
|
|
976
|
+
`)}else Qt();else if(a)Qt();else{try{await St(u)}catch{}try{await V({includeTail:!0})}catch{}try{await W({includeTail:!0})}catch{}}process.exit(1)}finally{u.close()}}export{Jn as runInspect};
|