@kaeawc/auto-mobile 0.0.93 → 0.0.94
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/build-info.json +12 -12
- package/dist/src/ble-peripheral.py +153 -0
- package/dist/src/{chunk-r6z1eztj.js → chunk-026y62r9.js} +11 -11
- package/dist/src/chunk-0jyfg947.js +4 -0
- package/dist/src/{chunk-8g1922rp.js → chunk-0zfpp1wh.js} +4 -4
- package/dist/src/{chunk-qf6nynk6.js → chunk-13qxf7ym.js} +5 -5
- package/dist/src/chunk-1scenrk7.js +4 -0
- package/dist/src/chunk-1vb5ph1k.js +4 -0
- package/dist/src/{chunk-710rxz9y.js → chunk-20g565q7.js} +3 -3
- package/dist/src/chunk-21h6dhdm.js +5 -0
- package/dist/src/chunk-25mfpthk.js +78 -0
- package/dist/src/{chunk-rbpdk7m0.js → chunk-2b39zyxc.js} +3 -3
- package/dist/src/chunk-2gzd6wbd.js +4 -0
- package/dist/src/{chunk-xgan0qqp.js → chunk-3dntffy9.js} +1 -1
- package/dist/src/chunk-3gfczcsn.js +4 -0
- package/dist/src/{chunk-dgrbdpb7.js → chunk-3h5jz1vb.js} +6 -6
- package/dist/src/{chunk-t6c8akcm.js → chunk-41zcy6b3.js} +3 -3
- package/dist/src/chunk-47n9m2de.js +4 -0
- package/dist/src/chunk-4vxeq0vd.js +58 -0
- package/dist/src/chunk-59dx6qaf.js +4 -0
- package/dist/src/chunk-5sdf9y92.js +4 -0
- package/dist/src/{chunk-58wzr3mt.js → chunk-5wk1t46v.js} +3 -3
- package/dist/src/{chunk-vy3bwm1d.js → chunk-661c50hh.js} +5 -5
- package/dist/src/chunk-68n6bjjd.js +21 -0
- package/dist/src/{chunk-v6pya0dm.js → chunk-69pmjdf2.js} +3 -3
- package/dist/src/{chunk-e98dqnc9.js → chunk-6hrj3jt6.js} +20 -20
- package/dist/src/{chunk-wbh8spm5.js → chunk-6myr26wx.js} +8 -8
- package/dist/src/chunk-6n96k09n.js +4 -0
- package/dist/src/chunk-6vwrbkre.js +4 -0
- package/dist/src/chunk-6wk0yrab.js +4 -0
- package/dist/src/chunk-6yhm9een.js +4 -0
- package/dist/src/{chunk-mjrps0ac.js → chunk-7k7gjg2t.js} +5 -5
- package/dist/src/chunk-7n5fz68h.js +4 -0
- package/dist/src/chunk-8cvnpnbp.js +4 -0
- package/dist/src/chunk-8kzv7rk7.js +4 -0
- package/dist/src/chunk-8nj68t1v.js +167 -0
- package/dist/src/{chunk-g7tmjbkt.js → chunk-96r3bpg7.js} +3 -3
- package/dist/src/chunk-97x887te.js +4 -0
- package/dist/src/{chunk-8ph29g99.js → chunk-99a6tbvd.js} +1 -1
- package/dist/src/chunk-9p5d2994.js +5 -0
- package/dist/src/{chunk-aabchzxk.js → chunk-9q265er0.js} +4 -4
- package/dist/src/{chunk-jh6vhqzx.js → chunk-9xgnrv5w.js} +3 -3
- package/dist/src/chunk-9xgsmshb.js +5 -0
- package/dist/src/chunk-a02d1wgv.js +4 -0
- package/dist/src/{chunk-ndt1ccxm.js → chunk-a9ps00a1.js} +10 -10
- package/dist/src/{chunk-5d2hft6c.js → chunk-aewdveet.js} +3 -3
- package/dist/src/{chunk-ycaj2sgf.js → chunk-b3tdtq7r.js} +6 -6
- package/dist/src/chunk-bn7jx7a2.js +4 -0
- package/dist/src/{chunk-3y6eykz9.js → chunk-bnyw27ja.js} +2 -2
- package/dist/src/{chunk-rqc9ap3x.js → chunk-bpwsg76p.js} +2 -2
- package/dist/src/chunk-bvranw3g.js +4 -0
- package/dist/src/chunk-c25a84zb.js +4 -0
- package/dist/src/chunk-c27yv1dx.js +5 -0
- package/dist/src/chunk-c3ewxm4x.js +5 -0
- package/dist/src/{chunk-rvvy1bte.js → chunk-cb1ga9rd.js} +5 -5
- package/dist/src/chunk-cn7fwy7k.js +4 -0
- package/dist/src/chunk-cnvy4a64.js +4 -0
- package/dist/src/{chunk-7rz9898k.js → chunk-cqhw4yr6.js} +3 -3
- package/dist/src/{chunk-g04bwyj3.js → chunk-ctmfshjc.js} +2 -2
- package/dist/src/chunk-ctwmhz13.js +4 -0
- package/dist/src/{chunk-waqwcjyn.js → chunk-d3jx9bz5.js} +2 -2
- package/dist/src/{chunk-ayp07wbb.js → chunk-d6rb08ga.js} +1 -1
- package/dist/src/chunk-ddqhj4eg.js +5 -0
- package/dist/src/{chunk-r7bpkgff.js → chunk-ddrhs1c3.js} +2 -2
- package/dist/src/chunk-dnjnh9p6.js +4 -0
- package/dist/src/{chunk-wyrkw6hw.js → chunk-dw5rwgya.js} +3 -3
- package/dist/src/{chunk-3xkpk44w.js → chunk-e0870khr.js} +3 -3
- package/dist/src/chunk-ea3k10kj.js +4 -0
- package/dist/src/chunk-emv82m1w.js +7 -0
- package/dist/src/chunk-f3m6pdnx.js +4 -0
- package/dist/src/chunk-f84z32cb.js +4 -0
- package/dist/src/chunk-fpczgf0z.js +4 -0
- package/dist/src/{chunk-2tqzq5qh.js → chunk-g2js4c2v.js} +18 -18
- package/dist/src/chunk-g3af2qbk.js +5 -0
- package/dist/src/{chunk-3qwrzxh0.js → chunk-gadtna7s.js} +6 -6
- package/dist/src/{chunk-ybbtagbt.js → chunk-gcyx407v.js} +3 -3
- package/dist/src/{chunk-bfw6125s.js → chunk-gfpntwc1.js} +3 -3
- package/dist/src/chunk-gmnm5e3e.js +4 -0
- package/dist/src/chunk-gp6vb5gf.js +4 -0
- package/dist/src/chunk-gppgy7pa.js +4 -0
- package/dist/src/chunk-hegfz0ae.js +5 -0
- package/dist/src/chunk-hpzxdp1k.js +17 -0
- package/dist/src/{chunk-qcxzr2my.js → chunk-j69g8b50.js} +3 -3
- package/dist/src/chunk-jvstjnqm.js +19 -0
- package/dist/src/chunk-jzqrv78s.js +4 -0
- package/dist/src/chunk-k2948b8d.js +4 -0
- package/dist/src/chunk-k4ftd40d.js +4 -0
- package/dist/src/{chunk-bxmsax22.js → chunk-kd9vfaxh.js} +3 -3
- package/dist/src/{chunk-s3jc6cwp.js → chunk-kdczmgwk.js} +3 -3
- package/dist/src/{chunk-t6bfvfkg.js → chunk-ke3wn14v.js} +1 -1
- package/dist/src/chunk-kh5n7m6w.js +4 -0
- package/dist/src/{chunk-6wt9rgjf.js → chunk-khejfph4.js} +3 -3
- package/dist/src/chunk-kny2xemh.js +4 -0
- package/dist/src/chunk-knyzw9md.js +4 -0
- package/dist/src/chunk-mbzpt2hp.js +4 -0
- package/dist/src/chunk-mm8rcxad.js +4 -0
- package/dist/src/chunk-nc4516tx.js +4 -0
- package/dist/src/{chunk-6bznss4t.js → chunk-ntfrqrqn.js} +5 -5
- package/dist/src/chunk-nz5h2j52.js +4 -0
- package/dist/src/chunk-p22s97qy.js +4 -0
- package/dist/src/chunk-p9kt1sgr.js +6 -0
- package/dist/src/{chunk-yb97j25b.js → chunk-pf282r5g.js} +4 -4
- package/dist/src/chunk-pnd4mrxy.js +4 -0
- package/dist/src/chunk-pqqteyj6.js +4 -0
- package/dist/src/{chunk-6xmss8er.js → chunk-qj1tbnv2.js} +6 -6
- package/dist/src/chunk-qnh9egwr.js +4 -0
- package/dist/src/chunk-qy3khhf8.js +8 -0
- package/dist/src/{chunk-z637nqg8.js → chunk-r0vp315h.js} +6 -6
- package/dist/src/chunk-r4j43b9s.js +237 -0
- package/dist/src/{chunk-1p7xf5kb.js → chunk-r54cxxze.js} +3 -3
- package/dist/src/{chunk-yf7ympyz.js → chunk-r6pvhj33.js} +92 -92
- package/dist/src/chunk-rb7aa5gr.js +54 -0
- package/dist/src/chunk-rdj50kb4.js +4 -0
- package/dist/src/chunk-rnd4vcas.js +4 -0
- package/dist/src/{chunk-w5b2jwk3.js → chunk-s3y3zfcx.js} +8 -8
- package/dist/src/chunk-s4g43k75.js +5 -0
- package/dist/src/chunk-sfqe223f.js +311 -0
- package/dist/src/{chunk-284ptqa4.js → chunk-sqdrxjw5.js} +5 -5
- package/dist/src/{chunk-zgja5f3p.js → chunk-t54k47em.js} +4 -4
- package/dist/src/{chunk-3sy6ahhz.js → chunk-tek4pnvv.js} +10 -10
- package/dist/src/chunk-tn74y7af.js +4 -0
- package/dist/src/{chunk-thbh3jew.js → chunk-tvq0nzam.js} +3 -3
- package/dist/src/{chunk-0jrrsnc9.js → chunk-tx4f0h9c.js} +4 -4
- package/dist/src/chunk-vdqag3fj.js +5 -0
- package/dist/src/chunk-vz5zzs57.js +4 -0
- package/dist/src/chunk-w4s2vfpj.js +4 -0
- package/dist/src/{chunk-4hw3665t.js → chunk-w5yypt53.js} +11 -11
- package/dist/src/{chunk-8037tzzj.js → chunk-w68v64vh.js} +3 -3
- package/dist/src/chunk-whwj0pdk.js +5 -0
- package/dist/src/chunk-wnmqt1dc.js +4 -0
- package/dist/src/{chunk-cyy71ggq.js → chunk-wpe46vsa.js} +3 -3
- package/dist/src/{chunk-w3vs79ex.js → chunk-wxdjeb4k.js} +19 -19
- package/dist/src/chunk-xcqzwf9j.js +247 -0
- package/dist/src/chunk-xezekwwn.js +5 -0
- package/dist/src/chunk-xf19m15s.js +4 -0
- package/dist/src/chunk-xghbxha4.js +4 -0
- package/dist/src/{chunk-00167wan.js → chunk-xn9m3xc2.js} +5 -5
- package/dist/src/{chunk-26k317v5.js → chunk-yqfz4vts.js} +3 -3
- package/dist/src/chunk-z8tvs8nk.js +5 -0
- package/dist/src/chunk-zm2rehqb.js +5 -0
- package/dist/src/chunk-zs6dqm35.js +4 -0
- package/dist/src/daemon/processEntry.js +2 -2
- package/dist/src/index.js +4 -4
- package/dist/src/runtime/bunRuntimeGuard.js +2 -2
- package/dist/src/utils/workers/iosBundleExtractWorker.js +2 -2
- package/package.json +2 -2
- package/dist/src/chunk-0n6swkwg.js +0 -5
- package/dist/src/chunk-0qsy1qsx.js +0 -57
- package/dist/src/chunk-11m8wj8j.js +0 -237
- package/dist/src/chunk-23p5f095.js +0 -4
- package/dist/src/chunk-28re4xrg.js +0 -4
- package/dist/src/chunk-2f9rkmhx.js +0 -5
- package/dist/src/chunk-2fxdh48t.js +0 -4
- package/dist/src/chunk-2tbdrbt6.js +0 -4
- package/dist/src/chunk-32gvv9b4.js +0 -21
- package/dist/src/chunk-3f3t1x97.js +0 -8
- package/dist/src/chunk-3fspkbc7.js +0 -4
- package/dist/src/chunk-3vg455e6.js +0 -4
- package/dist/src/chunk-49bsqdx3.js +0 -4
- package/dist/src/chunk-5snsn9cf.js +0 -4
- package/dist/src/chunk-5tm9mn47.js +0 -54
- package/dist/src/chunk-5zc77a5t.js +0 -4
- package/dist/src/chunk-64j0majr.js +0 -19
- package/dist/src/chunk-65y8v4td.js +0 -17
- package/dist/src/chunk-6awz7vhq.js +0 -5
- package/dist/src/chunk-6ep7f5ge.js +0 -4
- package/dist/src/chunk-7cs2da62.js +0 -5
- package/dist/src/chunk-7g103b54.js +0 -4
- package/dist/src/chunk-7j5vj4pa.js +0 -4
- package/dist/src/chunk-7tw8x05v.js +0 -4
- package/dist/src/chunk-7zy586cb.js +0 -4
- package/dist/src/chunk-84nanf8s.js +0 -5
- package/dist/src/chunk-8gvwcv2p.js +0 -4
- package/dist/src/chunk-8thrmfat.js +0 -4
- package/dist/src/chunk-8zgzzs7k.js +0 -78
- package/dist/src/chunk-97b1zmaq.js +0 -4
- package/dist/src/chunk-9fth9ayh.js +0 -4
- package/dist/src/chunk-9j6anhjr.js +0 -4
- package/dist/src/chunk-bfjwqk8q.js +0 -4
- package/dist/src/chunk-bnhscm2n.js +0 -4
- package/dist/src/chunk-c1vs4g1n.js +0 -4
- package/dist/src/chunk-ct3e7yng.js +0 -4
- package/dist/src/chunk-ddzkz92z.js +0 -4
- package/dist/src/chunk-drdz8hee.js +0 -5
- package/dist/src/chunk-eersndy7.js +0 -5
- package/dist/src/chunk-eggq53ks.js +0 -4
- package/dist/src/chunk-f2dya7cs.js +0 -4
- package/dist/src/chunk-fbakd6cw.js +0 -4
- package/dist/src/chunk-fgb98zjj.js +0 -5
- package/dist/src/chunk-fmpad823.js +0 -5
- package/dist/src/chunk-g0xr8zw0.js +0 -4
- package/dist/src/chunk-g3rjs80x.js +0 -4
- package/dist/src/chunk-g78rtrfv.js +0 -4
- package/dist/src/chunk-gabgv3y5.js +0 -4
- package/dist/src/chunk-gmr45m8f.js +0 -4
- package/dist/src/chunk-gsyfebqj.js +0 -4
- package/dist/src/chunk-h5rpn9wr.js +0 -247
- package/dist/src/chunk-hb1x7v55.js +0 -4
- package/dist/src/chunk-hrfytkxh.js +0 -168
- package/dist/src/chunk-j4yjzbak.js +0 -4
- package/dist/src/chunk-jd6a5v6p.js +0 -5
- package/dist/src/chunk-kn5spq15.js +0 -4
- package/dist/src/chunk-m94qs0f0.js +0 -4
- package/dist/src/chunk-n03dmn5q.js +0 -5
- package/dist/src/chunk-n72qhwd9.js +0 -4
- package/dist/src/chunk-nr6y0n4y.js +0 -5
- package/dist/src/chunk-pcsen2vs.js +0 -4
- package/dist/src/chunk-ppfr0b8h.js +0 -4
- package/dist/src/chunk-q10bdnat.js +0 -4
- package/dist/src/chunk-q9xmq595.js +0 -4
- package/dist/src/chunk-qyqypn28.js +0 -5
- package/dist/src/chunk-r2epb56s.js +0 -4
- package/dist/src/chunk-r5bxavdx.js +0 -311
- package/dist/src/chunk-r8jf3d92.js +0 -4
- package/dist/src/chunk-rc0dbypm.js +0 -4
- package/dist/src/chunk-rhcty4ms.js +0 -4
- package/dist/src/chunk-rpvckv3p.js +0 -4
- package/dist/src/chunk-ry0mz41y.js +0 -4
- package/dist/src/chunk-sfv61xjb.js +0 -6
- package/dist/src/chunk-t7w8rctc.js +0 -4
- package/dist/src/chunk-v2wd4n3e.js +0 -5
- package/dist/src/chunk-w4zga19f.js +0 -4
- package/dist/src/chunk-w7hkv422.js +0 -5
- package/dist/src/chunk-xa73x2cx.js +0 -5
- package/dist/src/chunk-y2vs6jwg.js +0 -4
- package/dist/src/chunk-yattm52s.js +0 -4
- package/dist/src/chunk-yjawdzk8.js +0 -4
- package/dist/src/chunk-zs1sghs9.js +0 -4
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{Af,i,Tf,kf,Rr,Se,Qe,di,fn,li,Q,Fl,yE,ht,Cd,cr,te,yJ,WO,we,Ra,qt,l,e}from"./chunk-z637nqg8.js";import{KL,nr,no,ZL,R,ko,Dr,mg,je,H,Je,me,on,U,fB,YT,Fre,Pc,Ac,Xt,wn,yz,rt,ie,jr,jw,Ye,v,z,Wn,L,Do,ke,tR,_z,hl,b,vt,De,rY,dne,lne,ni,ji,Jm,so,le,wu,ak,Ru,fe,Eg,Oo,o,P,Tp,pd,ib,wl,hR,pr,dt,kn,bY,Zz,ob,vR,N,ft,Tt,$t,co,Us,K,nj,Bn,ve,AR,Dg,cj,DD,OY,Pe,Og,Zne,Pk,ER,Zo,JB,jn,QB,pb,ye,mj,_k,Qo,Wa,Tl,Kn,m$,LR,Ai,VD,xu,Nk,Ee,df,Cu,lo,pie,WD,v$,zR,Rj,pf,hr,C$,xie,Cie,Fj,rO,Cc,Ps,O,wr,Il,Uie,qj,cO,Vj,Vg,dO,m9,un,Hie,vd,qie,Wj,Wg,Ib,h9,zg,Gj,H$,hO,yf,Cp,Kie,uo,Gie,rP,tE,Jr,Yie,$n,_b,Mo,x,Ce,E,SO,noe,Xi}from"./chunk-r5bxavdx.js";import{f,I,lt,Be,Hu}from"./chunk-58wzr3mt.js";import{B,m,_e,TO,Vr}from"./chunk-yf7ympyz.js";import{mo,y,gr,j,Ct,n,a,S,s,p}from"./chunk-4hw3665t.js";import{r,t,u}from"./chunk-rbpdk7m0.js";import{Nt}from"./chunk-qcxzr2my.js";var Te=250,An=Q({initialDelayMs:Te,multiplier:2,maxDelayMs:4000}),Cn=3,Pn=90000,Yt=3,Tn=8000,In=3,xn=5000,ze=2000,Jt=1000,Dn=5000,On=2,Qt="17.0";class Ro extends t{get code(){return this.deadlineExhausted?"timeout":void 0}get retryable(){return this.deadlineExhausted?!0:void 0}attempts;diagnosticCause;failureKind;retryableAndroidFrameworkFailure;deadlineExhausted;phase;constructor(c,{retryableAndroidFrameworkFailure:d=!1,deadlineExhausted:h=!1,phase:g,...w}={}){super(c);this.retryableAndroidFrameworkFailure=d,this.deadlineExhausted=h,this.phase=g,this.attempts=w.attempts,this.diagnosticCause=w.diagnosticCause,this.failureKind=w.failureKind}}var En=4000;function Mn(c){switch(c){case"package-compatibility":return"packageCompatibilityElapsedMs";case"runner-setup":return"runnerSetupElapsedMs";case"runner-connect":return"connectElapsedMs";case"runner-health":return"healthElapsedMs";default:return`${c}ElapsedMs`}}function re(c){let d=r(c),h=Wa(d);if(h.length<=En)return h;let g=Math.floor((En-32)/2);return`${h.slice(0,g)}
|
|
3
|
-
...[diagnostic truncated]...
|
|
4
|
-
${h.slice(-g)}`}async function Fn(c,d,h,g){let w=Number.isNaN(g)?1:Math.floor(g??Yt),A=Math.max(1,Math.min(Yt,w)),C=[];for(let T=1;T<=A;T+=1){h.throwIfCallerCancelled(c),d.resetSetupState();let k=await h.runPhase(c,"runner-setup",T,{operation:(M)=>d.setup(!1,c.perf,M,h.remainingForPhase(c,"runner-setup"))}).catch((M)=>{if(M instanceof Ro&&C.length>0)h.fail(c,"runner-setup",T,{detail:M.diagnosticCause,deadlineExhausted:M.deadlineExhausted,failureKind:M.failureKind,previousAttemptDetails:C});throw M});if(c.onRunnerSetup?.(),h.throwIfCallerCancelled(c),k.success)break;let D=k.retryableStartupFailure===!0&&h.remainingForPhase(c,"runner-setup")<=0;if(!k.retryableStartupFailure||D||T===A)h.fail(c,"runner-setup",T,{detail:k.error??k.message,deadlineExhausted:D,previousAttemptDetails:C});C.push(`attempt ${T}/${A}: ${re(k.error??k.message).slice(0,500)}`)}}class Zt{options;consecutiveTimeouts=0;backoffAttempt=0;processRestarted=!1;overloadedSinceRestartMs=null;constructor(c){this.options=c}get overloaded(){return this.consecutiveTimeouts>=this.options.minConsecutiveTimeouts}recordProbe({ready:c,connected:d,timedOut:h,nowMs:g}){if(c||!d||!h){this.clearOverload();return}if(this.consecutiveTimeouts++,!this.overloaded)return;if(this.backoffAttempt++,this.processRestarted)this.overloadedSinceRestartMs??=g}recordDisconnect(){this.clearOverload()}recordProcessRestart(){this.processRestarted=!0,this.clearOverload()}retryDelayMs(){return this.overloaded?this.options.backoff.delayForAttempt(this.backoffAttempt):this.options.baseDelayMs}shouldFailFast(c){return this.overloadedSinceRestartMs!==null&&c-this.overloadedSinceRestartMs>=this.options.failAfterRestartMs}clearOverload(){this.consecutiveTimeouts=0,this.backoffAttempt=0,this.overloadedSinceRestartMs=null}}var tr=2000,_n=1000;class Ne{timer;constructor(c){this.timer=c}throwIfCallerCancelled(c,d){if(c.signal?.aborted){if(c.deadlineFailure)throw c.deadlineFailure;throw c.signal.reason??d??Error("System UI ANR recovery cancelled")}}async runPhase(c,d,h,{operation:g,operationDeadlineMs:w}){let A=Math.min(this.remainingForPhase(c,d),w===void 0?Number.POSITIVE_INFINITY:Math.max(0,w-this.timer.now()));if(A<=0)this.fail(c,d,h,{detail:"readiness budget exhausted before phase started",deadlineExhausted:!0});let C=!1,T,k=!1,D=()=>{k=this.timer.now()>=this.totalDeadlineMs(c)};if(c.signal?.addEventListener("abort",D,{once:!0}),c.signal?.aborted)D();let M=()=>{let G=d==="runner-connect"?"CtrlProxy WebSocket connect":d==="runner-health"?"CtrlProxy readiness wait":c.device.platform==="ios"?"iOS CtrlProxy setup":"CtrlProxy package/setup";return new t(`${G} timed out: readiness phase exceeded the remaining deadline. Retry device acquisition.`)},F=(G)=>k?T===void 0?M():u(T,`Runner readiness ${d} failed`):G,_=this.timer.now(),V=!1,W=()=>{if(V)return;V=!0;let G=Math.max(0,this.timer.now()-_);c.phaseElapsedMs[d]=(c.phaseElapsedMs[d]??0)+G};try{return await Jm({timer:this.timer,timeoutMs:A,deadline:Ne.movableDeadline(c,d,w),signal:c.signal,graceMs:_n,label:`Runner readiness ${d}`,preferOperationFailureOnTimeout:!0,explicitAbortError:F,defaultAbortError:()=>F(c.signal?.reason),timeoutError:()=>(C=!0,M()),onRaceSettled:W},async(G)=>{try{return await Xt(`readiness:${d}`,()=>H(G,()=>g(G)))}catch(q){throw T=q,q}})}catch(G){if(W(),!k)this.throwIfCallerCancelled(c,G);return this.fail(c,d,h,{detail:G,deadlineExhausted:C||k})}finally{c.signal?.removeEventListener("abort",D),W()}}async awaitAbortSettlement(c){let d=Error("Abort settlement grace expired");try{await l(c.then(()=>{return},()=>{return}),{timer:this.timer,timeoutMs:_n,label:"Abort settlement grace",timeoutError:()=>d})}catch(h){if(h!==d)throw h}}probeTimeout(c){return Math.max(1,Math.min(tr,this.remainingForPhase(c,"runner-health")))}static isSetupPhase(c){return c==="runner-setup"||c==="package-compatibility"}static movableDeadline(c,d,h){return h===void 0&&Ne.isSetupPhase(d)?c.deadline:void 0}totalDeadlineMs(c){return c.deadline?.deadlineMs??c.totalDeadlineMs}phaseDeadlineMs(c,d){if(Ne.isSetupPhase(d))return this.totalDeadlineMs(c);return c.healthDeadlineMs??this.totalDeadlineMs(c)}remainingForPhase(c,d){return Math.max(0,this.phaseDeadlineMs(c,d)-this.timer.now())}startHealthWindow(c){if(c.healthDeadlineMs!==null)return;c.healthDeadlineMs=Math.min(this.totalDeadlineMs(c),this.timer.now()+c.readinessTimeoutMs)}fail(c,d,h,{detail:g,...w}){let{device:A}=c,C=`platform=${A.platform} requested=[${c.requestedIdentity}] resolved=[${A.name} (${A.deviceId})]`,T=this.remainingForPhase(c,d),k=Object.entries(c.phaseElapsedMs).map(([_,V])=>`${Mn(_)}=${V}`).join(" "),D=`${c.operationName??"startDevice"} automation runner readiness failed: ${C} phase=${d} attempts=${h} remainingBudgetMs=${T}${k?` ${k}`:""}`,M=[re(g),...w.previousAttemptDetails??[]].join("; "),F=new Ro(w.failureKind?`${M}; ${D}`:`${D}: ${M}`,{retryableAndroidFrameworkFailure:A.platform==="android"&&Ne.isSetupPhase(d)&&(hl(g)||_z(g)||yz(g)),deadlineExhausted:w.deadlineExhausted??!1,phase:d,attempts:h,diagnosticCause:g,failureKind:w.failureKind});if(w.deadlineExhausted)c.deadlineFailure=F;throw F}}class gt{dependencies;phases;constructor(c,d){this.dependencies=c;this.phases=d}async isResponsive(c,d,h){let g=c.deadlineFailure;try{return await this.probeUntilEvidence(c,d,h)}catch(w){if(!this.isHealthWindowExhaustion(c,w))throw w;return c.deadlineFailure=g,e.info(`[RunnerReadiness] iOS post-setup health window exhausted; restarting runner: ${w.message}`),!1}}isHealthWindowExhaustion(c,d){return d instanceof Ro&&d.deadlineExhausted&&(d.phase==="runner-health"||d.phase==="runner-connect")&&!c.signal?.aborted&&this.phases.remainingForPhase(c,"runner-setup")>0}async probeUntilEvidence(c,d,h){let g=Math.max(1,this.dependencies.iosPostSetupRestartMinFailedProbes??In);for(let w=1;w<=g;w++){let A=d.runnerSnapshot?.().xcTestProcess;if(await this.isResponsiveOnce(c,h,w))return!0;if(A&>.exitedRunnerIsCurrent(d,A))return!1;let C=await this.phases.runPhase(c,"runner-health",w,{operation:()=>d.checkRunningWithReason?.()??Promise.resolve(void 0)});if(C?.ok===!1&&C.reason==="refused")return!1;if(w<g)await this.dependencies.timer.sleep(Math.min(Te,this.phases.remainingForPhase(c,"runner-health"))),this.phases.throwIfCallerCancelled(c)}return!1}static exitedRunnerIsCurrent(c,d){if(d.exitCode===null&&d.signalCode===null)return!1;let h=c.runnerSnapshot?.().xcTestProcess??null;return h===null||h===d}async isResponsiveOnce(c,d,h){if(!(d.isConnected()||await this.phases.runPhase(c,"runner-connect",h,{operation:(A)=>d.connectWithoutSetup(A)})))return!1;let w=h===1?Math.min(Tn,this.phases.remainingForPhase(c,"runner-health")):this.phases.probeTimeout(c);return await this.phases.runPhase(c,"runner-health",h,{operation:()=>d.verifyServiceReady(1,0,w)})}}var rr="com.android.systemui",Vc="System UI isn't responding",Uc="Wait",ir="android:id/alertTitle",or="android:id/button2",ar="android:id/button1",Wc=3;function lr(c,d=new Us){let h=d.extractWindowRootGroups(c,"topmost-first")[0]??d.extractRootNodes(c);if(h.length===0)return;let g={systemUi:Kc(c)||zc(c),systemWindow:jc(c),titleFound:!1,alertTitleFound:!1,closeAppResourceFound:!1};for(let C of h)d.traverseNode(C,(T)=>qc(T,d,g));let w=$c(g)?g.waitBounds:void 0;if(w)return{waitBounds:w};let A=Gc(g)?g.waitBoundsByResourceId:void 0;if(A)return{waitBounds:A};return}function $c(c){return c.titleFound&&c.waitBounds!==void 0&&c.systemUi}function Gc(c){return c.systemUi&&c.systemWindow&&c.alertTitleFound&&c.closeAppResourceFound&&c.waitBoundsByResourceId!==void 0}function qc(c,d,h){let g=d.extractNodeProperties(c),w=bt(g.text,g["content-desc"]),A=bt(g.packageName,bt(g.package,g["package-name"])),C=bt(g["resource-id"],g.resourceId);if(h.systemUi||=A===rr,h.titleFound||=w===Vc,h.alertTitleFound||=C===ir,h.closeAppResourceFound||=C===ar,w===Uc)h.waitBounds??=Nn(d,c);if(C===or)h.waitBoundsByResourceId??=Nn(d,c)}function bt(c,d){return String(c??d??"")}function Nn(c,d){return c.parseBounds(qt(d))??void 0}function zc(c){return Hn(c)?.packageName===rr}function Kc(c){return c.packageName===rr}function jc(c){return Hn(c)?.type===Wc}function Hn(c){let d=c.windows;if(!d||d.length===0)return;return d.reduce((h,g)=>(g.windowLayer??0)>(h.windowLayer??0)?g:h)}function Ln(c){return{x:Math.floor((c.left+c.right)/2),y:Math.floor((c.top+c.bottom)/2)}}class PT extends Ro{}var ur=1000,Xc=2,Yc=5000;class mr{timer;phases;constructor(c,d){this.timer=c;this.phases=d}async recoverIfPresent(c,d){let h=this.systemUiAnrClient(c,d);if(!h)return;let g=Math.min(c.healthDeadlineMs??c.totalDeadlineMs,this.timer.now()+Yc),w=await this.readSystemUiAnrHierarchy(c,h,g),A=lr(w??{hierarchy:{}});if(!A)return;await this.selectSystemUiAnrWait(c,h,A.waitBounds,g),await this.waitForSystemUiAnrRecovery(c,h,g,w?.updatedAt)}systemUiAnrClient(c,d){if(c.device.platform!=="android"||!d.getAccessibilityHierarchy||!d.requestTapCoordinates)return;return{getAccessibilityHierarchy:(...h)=>d.getAccessibilityHierarchy(...h),requestTapCoordinates:(...h)=>d.requestTapCoordinates(...h)}}async readSystemUiAnrHierarchy(c,d,h,{minTimestamp:g=0,required:w=!1}={}){let A=Math.min(this.phases.probeTimeout(c),this.remainingSystemUiAnrRecoveryBudget(h));if(A<=0){if(this.phases.throwIfCallerCancelled(c),!w)return null;throw this.systemUiAnrRecoveryRequired(c,"recovery budget expired before the dialog state could be confirmed")}try{let C=await this.phases.runPhase(c,"runner-health",1,{operation:async(k)=>await d.getAccessibilityHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:g,disableAllFiltering:!0,signal:k,timeoutMs:A})}),T=this.isSystemUiAnrHierarchyUnavailable(C,g);if(T&&w)throw this.systemUiAnrRecoveryRequired(c,"could not confirm dialog recovery: hierarchy unavailable");return T?null:C}catch(C){if(C instanceof PT)throw C;if(this.phases.throwIfCallerCancelled(c,C),!w)return null;throw this.systemUiAnrRecoveryRequired(c,`could not confirm dialog recovery: ${re(C)}`)}}isSystemUiAnrHierarchyUnavailable(c,d){if(c===null||c.fresh===!1)return!0;return c.updatedAt!==void 0&&c.updatedAt<d}async selectSystemUiAnrWait(c,d,h,g){let{x:w,y:A}=Ln(h);try{let C=await this.phases.runPhase(c,"runner-health",1,{operation:async()=>await d.requestTapCoordinates({x:w,y:A,duration:10,timeoutMs:Math.min(this.phases.probeTimeout(c),this.remainingSystemUiAnrRecoveryBudget(g))})});if(!C.success)throw Error(C.error??"unknown tap failure")}catch(C){throw this.phases.throwIfCallerCancelled(c,C),this.systemUiAnrRecoveryRequired(c,`could not select Wait: ${re(C)}`)}}async waitForSystemUiAnrRecovery(c,d,h,g){let w=0,A=(g??0)+1;while(this.remainingSystemUiAnrRecoveryBudget(h)>0){await this.timer.sleep(Math.min(ur,this.remainingSystemUiAnrRecoveryBudget(h)));let C=await this.readSystemUiAnrHierarchy(c,d,h,{minTimestamp:A,required:!0});if(A=Math.max(A,(C?.updatedAt??0)+1),lr(C??{hierarchy:{}})){w=0;continue}if(w++,w>=Xc)return}throw this.systemUiAnrRecoveryRequired(c,"dialog persisted after selecting Wait")}remainingSystemUiAnrRecoveryBudget(c){return Math.max(0,c-this.timer.now())}systemUiAnrRecoveryRequired(c,d){return new PT(this.systemUiAnrDiagnostic(c,d))}systemUiAnrDiagnostic(c,d){return`System UI ANR recovery required: platform=android requested=[${c.requestedIdentity}] resolved=[${c.device.name} (${c.device.deviceId})]: ${d}`}}function Vn(c){return(c.isLastConnectionFailureForwardingLeaseConflict?.()??!1)&&!(c.isLastConnectionFailureTransientLeaseConflict?.()??!1)}var Jc=10;class wL{dependencies;phases;anrRecovery;iosPostSetupProbe;constructor(c){this.dependencies=c;this.phases=new Ne(c.timer),this.iosPostSetupProbe=new gt(c,this.phases),this.anrRecovery=new mr(c.timer,this.phases)}async ensureReady(c){let d={...c,healthDeadlineMs:null,phaseElapsedMs:{},lastCtrlProxyRebindMs:Number.NEGATIVE_INFINITY,ctrlProxyAccessibilityRebindAttempted:!1,lastConnectedRecoveryMs:Number.NEGATIVE_INFINITY,ctrlProxyProcessRestartAttempted:!1,androidProbeOverload:new Zt({backoff:this.dependencies.androidHealthProbeBackoff??An,baseDelayMs:Te,minConsecutiveTimeouts:Cn,failAfterRestartMs:this.dependencies.ctrlProxyUnresponsiveAfterRestartFailMs??Pn}),lastSuccessfulRebindMs:Number.NEGATIVE_INFINITY,failedHealthProbesSinceRecovery:0},h=lo(c.device.platform,c.device.deviceId),g=await this.acquireReadinessTurn(d,h);try{c.signal?.throwIfAborted(),c.assertCanSetup?.(),await this.ensureReadyUncoordinated(d)}finally{g()}}async ensureReadyUncoordinated(c){let d=c.perf,h=async()=>{if(c.device.platform==="android"){await this.ensureAndroidReady(c);return}await this.ensureIosReady(c)};if(!d)return h();return Pc(Ac(d),h)}async acquireReadinessTurn(c,d){if(this.phases.remainingForPhase(c,"runner-setup")<=0)this.phases.fail(c,"runner-setup",1,{detail:"readiness budget exhausted before setup lock",deadlineExhausted:!0});try{return await WD(d,{timer:this.dependencies.timer,signal:c.signal,timeoutMs:this.phases.remainingForPhase(c,"runner-setup"),timeoutError:()=>Error("readiness setup lock exceeded this request's deadline")})}catch(h){this.phases.throwIfCallerCancelled(c,h),this.phases.fail(c,"runner-setup",1,{detail:re(h),deadlineExhausted:!0})}}async ensureAndroidReady(c){this.phases.throwIfCallerCancelled(c);let d=this.inspectAndroidFrameworkBestEffort(c);try{let h="Android framework readiness budget exhausted";await new wn(this.dependencies.timer).executeOrThrow(async(g)=>{if(this.phases.throwIfCallerCancelled(c),this.phases.remainingForPhase(c,"runner-setup")<=0)this.phases.fail(c,"runner-setup",g,{detail:h,deadlineExhausted:!0});if(g>1)this.dependencies.getAndroidManager(c.device).resetSetupState();await this.ensureAndroidReadyAttempt(c),this.phases.throwIfCallerCancelled(c)},{maxAttempts:Math.ceil(this.phases.remainingForPhase(c,"runner-setup")/Te)+1,signal:c.signal,delays:()=>Math.min(Te,this.phases.remainingForPhase(c,"runner-setup")),shouldRetry:(g)=>g instanceof Ro&&g.retryableAndroidFrameworkFailure&&this.phases.remainingForPhase(c,"runner-setup")>0,onRetry:(g)=>{h=re(g),e.debug(`Retrying Android framework setup: ${h}`)}})}catch(h){throw this.phases.throwIfCallerCancelled(c,h),h}finally{await d?.(),this.phases.throwIfCallerCancelled(c)}}async ensureAndroidReadyAttempt(c){let d=this.dependencies.getAndroidManager(c.device),h=this.dependencies.getAndroidClient(c.device);if(c.skipCtrlProxyDownload){await this.ensureAndroidReadyWithoutDownloads(c,d,h);return}let g=await this.phases.runPhase(c,"package-compatibility",1,{operation:(C)=>d.ensureCompatibleVersion({allowDownloadWhenInstalled:!0,bypassVersionCheckCache:!1},C)});this.assertAndroidCompatibility(c,g);let[w,A]=await this.phases.runPhase(c,"runner-setup",1,{operation:async(C)=>[await d.isInstalled(C),await d.isEnabled(C)]});if(await this.isResponsiveFastPath(c,h,w&&A)){await this.anrRecovery.recoverIfPresent(c,h);return}d.reopenSetupGate(),await this.setupAndroidRunner(c,d),await this.waitForResponsiveClient(c,h,d),await this.anrRecovery.recoverIfPresent(c,h)}inspectAndroidFrameworkBestEffort(c){let d=this.dependencies.getAndroidFrameworkReadiness;if(!d)return;let h=Math.max(0,c.totalDeadlineMs-this.dependencies.timer.now());if(h<=0)return;let g=new AbortController,w=c.signal?AbortSignal.any([c.signal,g.signal]):g.signal,A=Math.min(tr,h),C=this.dependencies.timer.setTimeout(()=>g.abort(Error("Android framework inspection timed out")),A),T=Promise.resolve().then(()=>(w.throwIfAborted(),d(c.device,w,A))).then((k)=>{if(!k.ready)e.debug(`Android framework inspection is not ready yet: ${k.unavailableResources?.join(", ")??"unknown resources"}${k.diagnostic?`; ${re(k.diagnostic)}`:""}`)},(k)=>{e.debug(`Android framework inspection failed: ${re(k)}`)}).finally(()=>this.dependencies.timer.clearTimeout(C));return async()=>{g.abort(Error("Android readiness inspection finished")),this.dependencies.timer.clearTimeout(C),await this.phases.awaitAbortSettlement(T)}}async ensureAndroidReadyWithoutDownloads(c,d,h){let[g,w]=await this.phases.runPhase(c,"runner-setup",1,{operation:async(C)=>[await d.isInstalled(C),await d.isEnabled(C)]});if(!g)this.phases.fail(c,"runner-setup",1,{detail:"CtrlProxy is not installed and runner downloads are disabled"});if(!await this.phases.runPhase(c,"package-compatibility",1,{operation:()=>d.isVersionCompatible()}))this.phases.fail(c,"package-compatibility",1,{detail:"CtrlProxy version mismatch; run without skipCtrlProxyDownload to install a compatible version"});if(await this.isResponsiveFastPath(c,h,w)){await this.anrRecovery.recoverIfPresent(c,h);return}if(!w)await this.phases.runPhase(c,"runner-setup",1,{operation:()=>d.enable()});await this.waitForResponsiveClient(c,h,d),await this.anrRecovery.recoverIfPresent(c,h)}assertAndroidCompatibility(c,d){if(!(d.status==="failed"||d.status==="skipped"||d.acceptedPreinstalled===!0))return;let g=[d.error,d.upgradeError,d.reinstallError,d.acceptedPreinstalled?"installed package compatibility was not verified":void 0,d.status==="skipped"?"package compatibility check was skipped":void 0].filter((w)=>Boolean(w));this.phases.fail(c,"package-compatibility",1,{detail:d.cause??g.join("; ")})}async isResponsiveFastPath(c,d,h){if(!h||!d.isConnected())return!1;return this.phases.runPhase(c,"runner-health",1,{operation:()=>d.verifyServiceReady(1,0,this.phases.probeTimeout(c))})}async setupAndroidRunner(c,d){let h=await this.phases.runPhase(c,"runner-setup",1,{operation:(T)=>d.setup(!1,c.perf,T)});if(!h.success)this.phases.fail(c,"runner-setup",1,{detail:h.cause??h.error??h.message});let g=Math.min(c.totalDeadlineMs,this.dependencies.timer.now()+xn),w=0,A=!1,C=!1;for(;;){if(w++,[A,C]=await this.phases.runPhase(c,"runner-setup",w,{operation:async(T)=>[await d.isInstalled(T),await d.isEnabled(T,{bypassCache:w>1})],operationDeadlineMs:g}),A&&C)return;if(!A||this.dependencies.timer.now()>=g)break;if(this.phases.throwIfCallerCancelled(c),await this.dependencies.timer.sleep(Math.min(Te,g-this.dependencies.timer.now())),this.phases.throwIfCallerCancelled(c),this.dependencies.timer.now()>=g)break;await this.phases.runPhase(c,"runner-setup",w,{operation:()=>d.enable(),operationDeadlineMs:g})}if(!A||!C)this.phases.fail(c,"runner-setup",w,{detail:`CtrlProxy state after setup: installed=${A}, enabled=${C}`})}async ensureIosReady(c){this.assertIosRuntimeCompatible(c);let d=await this.phases.runPhase(c,"runner-setup",1,{operation:()=>this.dependencies.checkIosOverride()});if(d.present&&!d.usable)this.phases.fail(c,"runner-setup",1,{detail:`AUTOMOBILE_CTRL_PROXY_IOS_BUNDLE_PATH / _IPA_PATH is set but unusable: ${d.reason??"unknown reason"}`});await this.phases.runPhase(c,"runner-setup",1,{operation:()=>this.dependencies.awaitIosStartupMaintenance()});let h=this.dependencies.getIosManager(c.device),g=this.dependencies.getIosClient(c.device,h.getServicePort());if(g.isConnected()){if(this.phases.startHealthWindow(c),await this.phases.runPhase(c,"runner-health",1,{operation:()=>g.verifyServiceReady(1,0,this.phases.probeTimeout(c))}))return;h.resetSetupState(),await this.phases.runPhase(c,"runner-setup",1,{operation:(A)=>h.forceRestart({signal:A,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-health")})}),c.healthDeadlineMs=null,g=this.dependencies.getIosClient(c.device,h.getServicePort()),await this.waitForResponsiveClient(c,g);return}if(c.skipCtrlProxyDownload){await this.ensureIosReadyWithoutDownloads(c,h);return}await Fn(c,h,this.phases,this.dependencies.iosSetupMaxAttempts),g=this.dependencies.getIosClient(c.device,h.getServicePort()),await this.ensureIosClientReadyAfterStart(c,h,g)}assertIosRuntimeCompatible(c){let d=c.device.iosVersion??c.device.osVersion,h=KL(d,Qt);if(h!==null&&h<0)this.phases.fail(c,"runner-setup",1,{detail:`iOS runtime ${d} is below the CtrlProxy minimum ${Qt}; select a compatible simulator or device.`})}async ensureIosReadyWithoutDownloads(c,d){if(!await this.phases.runPhase(c,"runner-setup",1,{operation:()=>d.isInstalled()}))this.phases.fail(c,"runner-setup",1,{detail:"CtrlProxy iOS runner is not installed and runner downloads are disabled"});await this.phases.runPhase(c,"runner-setup",1,{operation:(w)=>d.start({signal:w,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-setup")})});let g=this.dependencies.getIosClient(c.device,d.getServicePort());await this.ensureIosClientReadyAfterStart(c,d,g)}async ensureIosClientReadyAfterStart(c,d,h){if(this.phases.startHealthWindow(c),await this.iosPostSetupProbe.isResponsive(c,d,h))return;d.resetSetupState(),await this.phases.runPhase(c,"runner-setup",1,{operation:(w)=>d.forceRestart({signal:w,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-setup")})}),c.healthDeadlineMs=null;let g=this.dependencies.getIosClient(c.device,d.getServicePort());await this.waitForResponsiveClient(c,g)}async waitForResponsiveClient(c,d,h){let g={release:c.device.platform==="android"?d.beginReadinessHold?.():void 0};try{await this.pollResponsiveClient(c,d,g,h)}finally{g.release?.()}}async pollResponsiveClient(c,d,h,g){this.phases.startHealthWindow(c);let w=0,A=d.isConnected(),C=A?"runner-health":"runner-connect",T=Number.NEGATIVE_INFINITY;while(this.phases.remainingForPhase(c,"runner-health")>0){if(this.phases.throwIfCallerCancelled(c),c.device.platform==="android")d=await this.replaceClosedAndroidClient(c,d,h,w);if(w++,A=d.isConnected(),!A){if(c.androidProbeOverload.recordDisconnect(),C="runner-connect",await this.rebindUnhealthyAndroidAccessibilityService(c,g,w,d),A=await this.phases.runPhase(c,C,w,{operation:()=>d.waitForConnection(1,0)}),!A&&Vn(d))await this.failUnresponsiveClient(c,d,C,{attempts:w})}if(A){if(C="runner-health",await this.probeResponsiveClient(c,d,w,g))return}if(c.device.platform==="android"&&this.dependencies.timer.now()-T>=ur)T=this.dependencies.timer.now(),await this.anrRecovery.recoverIfPresent(c,d);let k=this.phases.remainingForPhase(c,"runner-health");if(k>0)await this.dependencies.timer.sleep(Math.min(this.healthProbeRetryDelay(c,A),k))}await this.failUnresponsiveClient(c,d,C,{attempts:w})}healthProbeRetryDelay(c,d){if(c.device.platform!=="android"||!d)return Te;return c.androidProbeOverload.retryDelayMs()}async probeResponsiveClient(c,d,h,g){let w=this.phases.probeTimeout(c),A=this.dependencies.timer.now(),C=await this.phases.runPhase(c,"runner-health",h,{operation:()=>d.verifyServiceReady(1,0,w)});if(c.device.platform!=="android")return C;let T=this.dependencies.timer.now();if(c.androidProbeOverload.recordProbe({ready:C,connected:d.isConnected(),timedOut:T-A>=w-Jc,nowMs:T}),C)return!0;return await this.recoverConnectedButUnresponsiveAndroid(c,g,d,h),await this.failPersistentlyUnresponsiveAndroid(c,d,h),!1}async replaceClosedAndroidClient(c,d,h,g){if(!d.isClosed?.())return d;h.release?.(),h.release=void 0;let w=this.dependencies.getAndroidClient(c.device);if(e.info(`[RunnerReadiness] Re-resolved closed CtrlProxy client for ${c.device.deviceId}`),h.release=w.beginReadinessHold?.(),w.isClosed?.())await this.failUnresponsiveClient(c,w,"runner-connect",{attempts:g,deadlineExhausted:!1});return w}async rebindUnhealthyAndroidAccessibilityService(c,d,h,g){if(c.device.platform!=="android"||!d?.rebindIfUnhealthy||c.ctrlProxyAccessibilityRebindAttempted||this.dependencies.timer.now()-c.lastCtrlProxyRebindMs<Jt)return;let w=await this.phases.runPhase(c,"runner-connect",h,{operation:async()=>{try{return await d.rebindIfUnhealthy()}catch(A){if(!(A instanceof tR))throw A;return e.warn(`[CTRL_PROXY] Accessibility rebind inspection unavailable: ${A}`,A),!1}}});if(c.lastCtrlProxyRebindMs=this.dependencies.timer.now(),c.ctrlProxyAccessibilityRebindAttempted||=w,w)g.resetConnectionBudget?.()}async recoverConnectedButUnresponsiveAndroid(c,d,h,g){if(c.device.platform!=="android"||!d)return;if(c.failedHealthProbesSinceRecovery++,this.dependencies.timer.now()-c.lastConnectedRecoveryMs<Jt)return;let w=c.failedHealthProbesSinceRecovery;if(c.lastConnectedRecoveryMs=this.dependencies.timer.now(),d.rebindIfUnhealthy&&!c.ctrlProxyAccessibilityRebindAttempted){let C=await this.phases.runPhase(c,"runner-health",g,{operation:()=>d.rebindIfUnhealthy()});if(c.ctrlProxyAccessibilityRebindAttempted||=C,C){c.failedHealthProbesSinceRecovery=0,c.lastSuccessfulRebindMs=this.dependencies.timer.now(),h.resetConnectionBudget?.();return}}if(!this.canEscalateToProcessRestart(c,d,w))return;if(c.ctrlProxyProcessRestartAttempted=!0,await this.phases.runPhase(c,"runner-health",g,{operation:()=>d.forceRestartProcess()}))c.androidProbeOverload.recordProcessRestart(),h.resetConnectionBudget?.()}async failPersistentlyUnresponsiveAndroid(c,d,h){if(d.isConnected()&&c.androidProbeOverload.shouldFailFast(this.dependencies.timer.now()))await this.failUnresponsiveClient(c,d,"runner-health",{attempts:h,detail:"CtrlProxy accessibility service is connected but not answering hierarchy requests after a process restart. On Android XR, a window such as the XR home environment may not answer accessibility interaction. Retry device acquisition, or kill and restart the device."})}canEscalateToProcessRestart(c,d,h){if(c.ctrlProxyProcessRestartAttempted||!d.forceRestartProcess)return!1;if(h<On)return!1;return this.dependencies.timer.now()-c.lastSuccessfulRebindMs>=Dn}async failUnresponsiveClient(c,d,h,{attempts:g,deadlineExhausted:w=!0,detail:A}){if(h==="runner-connect"&&(d.isLastConnectionFailureForwardingLeaseConflict?.()??!1)){let k=d.getLastConnectionFailureMessage?.();if(k)this.phases.fail(c,h,g,{detail:k})}if(h==="runner-connect")this.failForwardUnavailableClient(c,d,g,w);let T=h==="runner-connect"?await this.runnerConnectFailureDiagnostic(c):await this.runnerHealthFailureDiagnostic(c,h);this.phases.fail(c,h,g,{detail:`${A??this.unresponsiveClientRecoveryNote(c,h)}${T}`,deadlineExhausted:w})}failForwardUnavailableClient(c,d,h,g){let w=d.getForwardFailureCause?.()??(d.isClosed?.()?`CtrlProxy client for ${c.device.deviceId} is closed; adb forward unavailable`:void 0);if(w)this.phases.fail(c,"runner-connect",h,{detail:w,deadlineExhausted:g,failureKind:"ctrlproxy_forward_unavailable"})}unresponsiveClientRecoveryNote(c,d){if(d==="runner-connect"&&c.ctrlProxyAccessibilityRebindAttempted)return"CtrlProxy accessibility service was crashed or unbound; rebind attempted, but the runner did not become responsive before the readiness deadline";if(c.ctrlProxyProcessRestartAttempted)return"CtrlProxy accessibility service was bound but unresponsive; process restart attempted, but the runner did not become responsive before the readiness deadline";return"runner did not become responsive before the readiness deadline"}async runnerConnectFailureDiagnostic(c){let d=this.dependencies.getAndroidRunnerConnectDiagnostic;if(c.device.platform!=="android"||!d)return"";let h=await this.collectBoundedAndroidDiagnostic(c,d,"runner-connect");if(!h)return"";let g=[h.primaryUserStartState?`primaryUserStartState=${h.primaryUserStartState}`:void 0,h.deviceLock?`deviceLock=${h.deviceLock.locked?"locked":"unlocked"}`:void 0].filter((w)=>Boolean(w));return g.length>0?`; ${g.join(" ")}`:""}async runnerHealthFailureDiagnostic(c,d){let h=this.dependencies.getAndroidRunnerHealthDiagnostic;if(c.device.platform!=="android"||d!=="runner-health"||!h)return"";let g=await this.collectBoundedAndroidDiagnostic(c,h,"runner-health");if(!g)return"";return`; sys.boot_completed=${g.sysBootCompleted} adbDevices=${g.adbDevices} emulatorQemuHealth=${g.emulatorQemuHealth}`}async collectBoundedAndroidDiagnostic(c,d,h){try{let g=new AbortController,w=c.signal?AbortSignal.any([c.signal,g.signal]):g.signal,A=d(c.device,w);A.catch((k)=>{e.debug(`Android readiness diagnostic rejection observed: ${r(k)}`)});let C=Error(`${h} diagnostic timed out`),T;try{T=await l(A,{timer:this.dependencies.timer,timeoutMs:ze,label:`${h} diagnostic`,timeoutError:()=>C,onTimeout:()=>g.abort(C)})}catch(k){if(k!==C)throw k}if(!T)return;return T}catch(g){e.debug(`Failed to collect Android ${h} diagnostic: ${r(g)}`);return}}}var Qc="android.hardware.touchscreen",Zc=["android.software.leanback","android.hardware.type.television"],rd=300000,id=3000;function Un(c){let d=c.trim();if(d==="true")return!0;return d==="false"?!1:null}function nd(c){let d=new Set(c.split(/\r?\n/).map((h)=>h.trim()).filter((h)=>h.length>0));return d.size===1?Un([...d][0]):null}class Gn{timer;ttlMs;cache=new Map;constructor(c=i,d=rd){this.timer=c;this.ttlMs=d}async hasTouchscreen(c,d,h){let g=this.cache.get(d);if(g&&this.timer.now()-g.readAt<this.ttlMs)return g.value;let w=await St(c,d,Qc,{signal:h});if(w===null)return this.cache.delete(d),null;if(w===!1)return this.remember(d,!1);for(let A of Zc){let C=await St(c,d,A,{signal:h});if(C===null)return this.cache.delete(d),!0;if(C)return this.remember(d,!1)}return this.remember(d,!0)}remember(c,d){return this.cache.set(c,{readAt:this.timer.now(),value:d}),d}}async function St(c,d,h,{signal:g,logTag:w="TouchscreenFeature"}={}){let A;try{let C=await c.executeCommand(`shell pm has-feature ${h}`,{noRetry:!0,timeoutMs:id,...g?{signal:g}:{}});A=Un(C.stdout)}catch(C){if(g?.throwIfAborted(),A=nd(jr(C).stdout),A===null)return e.warn(`[${w}] ${h} probe failed for ${d}: ${r(C)}`,C),null}if(A===null)e.warn(`[${w}] unrecognized pm has-feature ${h} output for ${d}`);return A}var Ste=new Gn;var od="android.software.xr.api.spatial",sd=300000,wt=(c)=>!!c&&(c.startsWith("com.android.systemui.xr")||c.startsWith("com.android.systemui/.xr"));function ad(c){return!!c&&(c.activities.some((d)=>wt(d.name))||c.tasks.some((d)=>wt(d.packageName)||wt(d.rootActivity)||wt(d.topActivity)))}function zn({device:c,backStack:d}){return c.formFactor==="xr-headset"||c.formFactor==="xr-glasses"||ad(d)}class Xn{timer;ttlMs;cache=new Map;constructor(c=i,d=sd){this.timer=c;this.ttlMs=d}async isAndroidXr(c){let{device:d,adb:h,signal:g}=c;if(d.platform!=="android")return!1;let w=this.cache.get(d.deviceId);if(w&&this.timer.now()-w.readAt<this.ttlMs)return w.value;if(!h)return zn(c);let A=await St(h,d.deviceId,od,{signal:g,logTag:"AndroidXrDetector"});if(A===null)return this.cache.delete(d.deviceId),zn(c);return this.cache.set(d.deviceId,{readAt:this.timer.now(),value:A}),A}}var Sw=new Xn;function ra(c,d=Sw){return d.isAndroidXr(c)}function cd(c){return c===void 0||c==="unknown"||c==="xr-headset"||c==="xr-glasses"}class Ke{deps;displaySizes=new Map;xrDevices=new Map;constructor(c){this.deps=c}isXrCached(){let c=this.deps.device();return c.platform==="android"&&this.xrDevices.get(c.deviceId)===!0}key(c){return`${this.deps.device().deviceId}:${Number(c.rotation===1||c.rotation===3)}`}async prime(c,d,h,g=d.displayId??0){let w=this.deps.device();if(w.platform!=="android"||g!==0||!this.deps.readDisplaySize)return;let A=this.key(d);if(this.displaySizes.has(A))return;let C=await this.isXr(c,h);if(this.xrDevices.set(w.deviceId,C),!C)return;try{let T=await this.deps.readDisplaySize(),k=d.rotation===1||d.rotation===3;this.displaySizes.set(A,k?{width:T.height,height:T.width}:T)}catch(T){(this.deps.logger??e).warn(`[OBSERVE] XR display size read failed; using hierarchy size: ${r(T)}`,T)}}isXr(c,d){let h=this.deps.device();return ra({device:h,adb:cd(h.formFactor)?this.deps.adb?.():void 0,backStack:c.backStack,signal:d},this.deps.xrDetector)}applyCached(c,d,h=d.displayId??0){if(this.deps.device().platform!=="android"||h!==0)return;let g=this.displaySizes.get(this.key(d));if(g)c.screenSize={...g},this.deps.hierarchyCollector().reconcileScreenDimensions(d,g),d.pixelWidth=g.width,d.pixelHeight=g.height}}function wte(c){let d=(w,A)=>Math.min(Math.max(w,0),Math.max(A-1,0)),h=(w,A)=>d(Math.round((A?c.xMax-w:w-c.xMin)/(c.xMax-c.xMin+1)*c.displayWidth),c.displayWidth),g=(w,A)=>d(Math.round((A?c.yMax-w:w-c.yMin)/(c.yMax-c.yMin+1)*c.displayHeight),c.displayHeight);return{toScreenPoint(w,A){switch(c.rotation){case 1:return{x:g(A,!1),y:h(w,!0)};case 2:return{x:h(w,!0),y:g(A,!0)};case 3:return{x:g(A,!0),y:h(w,!1)};default:return{x:h(w,!1),y:g(A,!1)}}}}}async function MC(c,d={}){let{stdout:h}=d.timeoutMs===void 0?await c.executeCommand("shell wm size"):await c.executeCommand("shell wm size",{timeoutMs:d.timeoutMs,noRetry:!0}),g=h.match(/Override size:\s*(\d+)x(\d+)/)??h.match(/Physical size:\s*(\d+)x(\d+)/);if(!g)throw Error(`Could not parse display size from wm size output: ${h}`);return{width:parseInt(g[1],10),height:parseInt(g[2],10)}}async function Rte(c){try{let{stdout:d}=await c.executeCommand("shell wm density"),h=d.match(/Physical density:\s*(\d+)/);if(h)return parseInt(h[1],10)/160}catch(d){e.warn(`[AxisRanges] Failed to query density; using 440 dpi: ${r(d)}`,d)}return 2.75}class fr{d;constructor(c){this.d=c}async execute(c){let d=c?.deviceReadScreenshot;m$(te(this.d.device().platform,"Observing all displays")),LR(this.d.device(),"all");let h=this.d.timer().now()+(c?.timeoutMs??15000),g=await this.readAggregatePanel("active",{options:c,deadline:h,deviceReadScreenshot:d}),w=this.d.device().displays?.panels.filter(Cd);if(!w?.length)return g;let A=this.activePanelKey(w,g.display.key),C=[];for(let k of w){let D=k.key===A?g:await this.readAggregatePanel(k.key,{options:{...c,skipScreenshot:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,skipRecompositionTracking:!0},deadline:h}),{display:M,screenSize:F,viewHierarchy:_,elements:V,screenshotPath:W,screenshotExpiresAt:G,systemInsets:q,insets:X,activeWindow:Y}=D;C.push({display:{...M,key:k.key,role:k.role},screenSize:F,viewHierarchy:_,elements:V,screenshotPath:W,screenshotExpiresAt:G,systemInsets:q,insets:X,activeWindow:Y,freshness:D.freshness??vR({now:this.d.timer().now(),unavailable:!0})})}let T={...g,displays:C};return await _b(T,this.d.pathProtection()),T}activePanelKey(c,d){let h=this.d.device();if(h.displays?.panels.some((g)=>g.key===d&&!Cd(g)))return;if(c.some((g)=>g.key===d))return d;return Ai(h,"active",{focusedPanelKey:Ce.observedPanel(h.deviceId)?.key}).key}async readAggregatePanel(c,d){let{options:h,deadline:g,deviceReadScreenshot:w}=d,A=Math.max(0,g-this.d.timer().now()),C=new AbortController,T=h?.signal,k=T?AbortSignal.any([T,C.signal]):C.signal,D=A===0;try{if(T?.throwIfAborted(),D)throw new Kn("Observe deadline reached; retry this panel separately.");return await l(async()=>{let M=await this.d.executeSingleDisplay({...h,display:c,signal:k,timeoutMs:A,skipCache:!0,preserveDisplayState:!0});if(w!==void 0)await this.d.captureDeviceReadScreenshot(M,k,w,{display:c});return M},{timer:this.d.timer(),timeoutMs:A,signal:T,label:`Observe display ${c}`,onTimeout:()=>{D=!0,C.abort()}})}catch(M){if(T?.throwIfAborted(),e.warn(`[ObserveScreen] Display ${c} unavailable: ${r(M)}`,M),c==="active"&&!D)return this.d.createCriticalFallback(M);let F=this.d.createBaseResult(),_=Ai(this.d.device(),c,{focusedPanelKey:Ce.observedPanel(this.d.device().deviceId)?.key});return F.display={...F.display,key:_.key,role:_.role,generation:Ce.identityRevision(this.d.device().deviceId)},F.screenSize={..._.sizePx,units:"physical-pixels"},F.freshness=vR({now:this.d.timer().now(),unavailable:!0,unavailableReason:D?"request_timed_out":"unknown",unavailableDetail:r(M)}),F}}}var Yn="com.apple.springboard.lockstate",dd=2000;function uW(c){return c.kind==="known"?c.lock:void 0}function Rt(c,d){if(delete c.deviceLock,delete c.deviceLockUnknown,d.kind==="known")c.deviceLock=d.lock;else c.deviceLockUnknown={reason:d.reason,...d.message===void 0?{}:{message:d.message}}}class AT{executor;options;constructor(c=new L,d={}){this.executor=c;this.options=d}async read(c,d){try{let h=await this.executor.executeCommand(Rj(c,Yn),this.options.timeoutMs??dd,d);if(h.stderr?.trim())return e.warn(`[iOS] Lock-state probe failed: ${h.stderr.trim()}`),{kind:"unknown",reason:"error",message:h.stderr.trim()};let g=h.stdout.split(`
|
|
5
|
-
`).find((A)=>A.trim().startsWith(`${Yn} `)),w=zR(g??"");if(w===null)return e.warn("[iOS] Lock-state probe returned unparseable output"),{kind:"unknown",reason:"unparseable"};return{kind:"known",lock:{locked:w,keyguardShowing:w}}}catch(h){return e.warn(`[iOS] Lock-state probe failed: ${r(h)}`,h),{kind:"unknown",reason:h instanceof ko?"timeout":"error",message:r(h)}}}}var Jn=new Set(["debug","tool-results-no-structured-content"]),ww=[{key:"debug",label:"Debug mode",description:"Enable debug tools and include extra debug data in responses.",defaultValue:!1},{key:"debug-perf",label:"Debug perf (--debug-perf)",description:"Collect performance timing data in tool responses.",defaultValue:!1},{key:"ui-perf-mode",label:"UI performance audit",description:"Run UI performance audits during observe.",defaultValue:!1},{key:"mem-perf-audit",label:"Memory audit",description:"Run memory audits during tool execution.",defaultValue:!1},{key:"accessibility-audit",label:"Accessibility audit",description:"Run accessibility audits during observe.",defaultValue:!1,defaultConfig:{level:"AA",failureMode:"report",minSeverity:"warning",useBaseline:!1,contrast:{useMultiPointSampling:!0,detectGradients:!0,compositeOverlays:!1,detectTextShadows:!1,samplingPoints:9}}},{key:"predictive-ui",label:"Predictive UI",description:"Enable predictive UI state generation during observe.",defaultValue:!1},{key:"raw-element-search",label:"Raw element search",description:"Use raw view hierarchies for element search while returning filtered observations.",defaultValue:!1},{key:"force-accessibility-mode",label:"Force accessibility mode",description:"Force-enable accessibility mode for testing (overrides auto-detection).",defaultValue:!1},{key:"accessibility-auto-detect",label:"Accessibility auto-detect",description:"Automatically detect and adapt to TalkBack/VoiceOver when enabled.",defaultValue:!0},{key:"screen-reader-navigation",label:"Screen-reader navigation (fidelity mode)",description:"Opt-in: when a screen reader is active, move the accessibility cursor onto the target with an accessibility-focus action and confirm it landed before activating (instead of activating the node directly). A failure after the focus request fails the call without a coordinate tap. For accessibility validation \u2014 reachability and what the cursor lands on.",defaultValue:!1},{key:"ai-recovery",label:"AI recovery",description:"AI-assisted recovery for failed test steps.",defaultValue:!0,defaultConfig:{maxToolCalls:5}},{key:"tool-call-recording",label:"Tool call recording",description:"Allow recordToolCalls begin/end to capture MCP tool calls as replayable YAML test plans. On by default; the tool itself is still opt-in via setToolEnabled.",defaultValue:!0},{key:"navigation-screenshots",label:"Navigation screenshots",description:"Capture screenshots on navigation events to enrich the navigation graph. Disable to reduce device resource usage.",defaultValue:!0},{key:"observe-settled-screenshot",label:"Settled observation screenshots",description:"Wait for a validated, settled screenshot instead of capturing one in the background.",defaultValue:!1},{key:"observe-result-include-elements",label:"Observe result: include elements",description:"Include the flattened elements array in observe results. It is dropped by default to reduce output size; enable this to restore it.",defaultValue:!1},{key:"tool-results-no-structured-content",label:"Tool results: no structured content",description:"Omit the structuredContent field from tool results to reduce output size.",defaultValue:!1},{key:"actions-diff-observe",label:"Actions: diff observe",description:"Return action-aware observation diffs after non-observe tools, falling back to full observations for navigation-prone or uncertain screen changes.",defaultValue:!1},{key:"actions-no-observe",label:"Actions: no observe",description:"Skip returning the post-action observation entirely to reduce output size.",defaultValue:!1},{key:"actions-compact-metadata",label:"Actions: compact metadata",description:"Omit unchanged device metadata after its first inline action response in a session and omit identical duplicate matched elements.",defaultValue:!0},{key:"device-condition",label:"Device condition fixtures",description:"Opt-in: expose the session-scoped deviceCondition surface on setDeviceState for root/integrity/fault test fixtures (epic #14047). Off by default while the individual injectors land; conditions always restore to a clean state on release.",defaultValue:!1},{key:"ios-sdk-observation-bridge",label:"iOS SDK observation bridge",description:"On iOS, merge the app's registered AutoMobile SDK observation bridge into observe and route tapOn on its nodes through it, falling back to XCTest only when the bridge is unavailable or the action is unsupported. Disable to use XCTest alone.",defaultValue:!0},{key:"observe-app-interactive",label:"Interactive observe App",description:"Spike (#17767): MCP Apps hosts get an observe view with an element picker that shows the tapped element's selector and can ask the host to run tapOn. Off by default; clients that do not render MCP Apps are unaffected.",defaultValue:!1}];var ud=Ct(y(),gr());function md(c,d,h=e){if(!d)return null;try{return ud.parse(JSON.parse(d))}catch(g){return h.warn(`[FeatureFlagRepository] Ignoring invalid config_json for flag "${c}": ${r(g)}`),null}}class yr{injectedDb;logger;timer;constructor({db:c,timer:d=i,log:h}={}){this.timer=d,this.injectedDb=c??null,this.logger=h??e}async ensureReady(){if(!this.injectedDb)await TO()}getDb(){return this.injectedDb??_e()}async ensureFlags(c){if(await this.ensureReady(),c.length===0)return;let d=this.getDb(),h=Vr(this.timer);await d.insertInto("feature_flags").values(c.map((g)=>({key:g.key,enabled:g.defaultValue?1:0,config_json:g.defaultConfig?JSON.stringify(g.defaultConfig):null,updated_at:h}))).onConflict((g)=>g.column("key").doNothing()).execute()}async listFlags(){return await this.ensureReady(),(await this.getDb().selectFrom("feature_flags").select(["key","enabled","config_json","updated_at"]).execute()).map((h)=>({key:h.key,enabled:h.enabled===1,config:md(h.key,h.config_json,this.logger),updatedAt:h.updated_at}))}async upsertFlag(c,d,h){await this.ensureReady();let g=this.getDb(),w=Vr(this.timer),A=h?JSON.stringify(h):null;await g.insertInto("feature_flags").values({key:c,enabled:d?1:0,config_json:A,updated_at:w}).onConflict((C)=>C.column("key").doUpdateSet((T)=>({enabled:d?1:0,config_json:h===void 0?T.ref("feature_flags.config_json"):A,updated_at:w}))).execute()}}var Zn=!1;function eo(c){Zn=c}function fu(){return Zn}var ge={level:"AA",failureMode:"report",useBaseline:!1,minSeverity:"warning",contrast:{useMultiPointSampling:!0,detectGradients:!0,compositeOverlays:!1,detectTextShadows:!1,samplingPoints:9}};class vr{apply(c,d,h){switch(c){case"debug":eo(d);break;case"debug-perf":fB(d);break;case"ui-perf-mode":N.setUiPerfMode(d);break;case"mem-perf-audit":N.setMemPerfAuditMode(d);break;case"accessibility-audit":N.setAccessibilityAuditConfig(d?hd(h):null);break;case"predictive-ui":N.setPredictiveUiEnabled(d);break;case"raw-element-search":N.setRawElementSearchEnabled(d);break;case"tool-call-recording":N.setToolCallRecordingEnabled(d);break;case"navigation-screenshots":N.setNavigationScreenshotsEnabled(d);break;case"ios-sdk-observation-bridge":N.setIosSdkObservationBridgeEnabled(d);break;default:this.applyOutputReduction(c,d);break}}applyOutputReduction(c,d){switch(c){case"observe-result-include-elements":N.setObserveResultIncludeElementsEnabled(d);break;case"tool-results-no-structured-content":N.setToolResultsNoStructuredContentEnabled(d);break;case"actions-diff-observe":N.setActionsDiffObserveEnabled(d);break;case"actions-compact-metadata":N.setActionsCompactMetadataEnabled(d);break;case"actions-no-observe":N.setActionsNoObserveEnabled(d);break}}}var hd=(c)=>{if(!c)return ge;let d=c.level==="A"||c.level==="AA"||c.level==="AAA"?c.level:ge.level,h=c.failureMode==="report"||c.failureMode==="threshold"||c.failureMode==="strict"?c.failureMode:ge.failureMode,g=c.minSeverity==="error"||c.minSeverity==="warning"||c.minSeverity==="info"?c.minSeverity:ge.minSeverity,w=typeof c.useBaseline==="boolean"?c.useBaseline:ge.useBaseline,A=fd(c.contrast);return{level:d,failureMode:h,minSeverity:g,useBaseline:w,contrast:A}},fd=(c)=>{if(!c||typeof c!=="object")return ge.contrast;let d=c,h=yd(d);return{useMultiPointSampling:typeof d.useMultiPointSampling==="boolean"?d.useMultiPointSampling:ge.contrast?.useMultiPointSampling,detectGradients:typeof d.detectGradients==="boolean"?d.detectGradients:ge.contrast?.detectGradients,compositeOverlays:typeof d.compositeOverlays==="boolean"?d.compositeOverlays:ge.contrast?.compositeOverlays,detectTextShadows:typeof d.detectTextShadows==="boolean"?d.detectTextShadows:ge.contrast?.detectTextShadows,samplingPoints:h}},yd=(c)=>c.samplingPoints===5||c.samplingPoints===9||c.samplingPoints===13?c.samplingPoints:ge.contrast?.samplingPoints;class br{notifyToolListChanged(){}}var NC="notifications/resources/updated";class to{listeners=new Set;subscribe(c){return this.listeners.add(c),()=>{this.listeners.delete(c)}}emit(c){for(let d of this.listeners)try{d(c)}catch(h){e.warn("[ResourceUpdatedBroadcaster] resource update listener failed",h)}}clearForTesting(){this.listeners.clear()}}var Rw=new to;var p3={tools:"notifications/tools/list_changed",resources:"notifications/resources/list_changed"};function Pte(c){for(let[d,h]of Object.entries(p3))if(h===c)return d;return}class io{listeners=new Set;generations={tools:0,resources:0};generation(c){return this.generations[c]}subscribe(c){return this.listeners.add(c),()=>{this.listeners.delete(c)}}invalidate(c){this.generations[c]++}emit(c){this.invalidate(c);for(let d of this.listeners)try{d(c)}catch(h){e.warn(`[ListChangedBroadcaster] listener failed for ${c} list_changed: ${h}`)}}clearForTesting(){this.listeners.clear()}}var Er=new io;class sr{repository;applier;definitions;notifier;static instance=null;definitionByKey;initialized=!1;flagsByKey=new Map;configsByKey=new Map;static getInstance(){if(!sr.instance)sr.instance=new sr(new yr,new vr);return sr.instance}static peekInstanceForTesting(){return sr.instance}static setInstanceForTesting(c){sr.instance=c}constructor(c,d,h=ww,g=new br){this.repository=c;this.applier=d;this.definitions=h;this.notifier=g;this.definitionByKey=new Map(h.map((w)=>[w.key,w]))}setToolListChangedNotifier(c){this.notifier=c}toolListChangedNotifierForTesting(){return this.notifier}async initialize(){if(this.initialized)return;await this.repository.ensureFlags(this.definitions);let c=await this.repository.listFlags(),d=new Map(c.map((h)=>[h.key,h]));for(let h of this.definitions){let g=d.get(h.key),w=g?g.enabled:h.defaultValue,A=g?.config??h.defaultConfig??null;this.flagsByKey.set(h.key,w),this.configsByKey.set(h.key,A),this.applier.apply(h.key,w,A)}this.initialized=!0,Er.invalidate("tools")}async listFlags(){return await this.initialize(),this.definitions.map((c)=>({key:c.key,label:c.label,description:c.description,enabled:this.flagsByKey.get(c.key)??c.defaultValue,config:this.configsByKey.get(c.key)??c.defaultConfig??null}))}async setFlag(c,d,h){await this.initialize();let g=this.definitionByKey.get(c);if(!g)throw Error(`Unknown feature flag: ${c}`);let w=h!==void 0?h:this.configsByKey.get(c)??g.defaultConfig??null,A=this.flagsByKey.get(c)??g.defaultValue;if(await this.repository.upsertFlag(c,d,h),this.flagsByKey.set(c,d),h!==void 0)this.configsByKey.set(c,w);if(this.applier.apply(c,d,w),d!==A&&Jn.has(c))this.notifier.notifyToolListChanged();return{key:g.key,label:g.label,description:g.description,enabled:d,config:w}}async setFlagConfig(c,d){await this.initialize();let h=this.definitionByKey.get(c);if(!h)throw Error(`Unknown feature flag: ${c}`);let g=this.flagsByKey.get(c)??h.defaultValue;return await this.repository.upsertFlag(c,g,d),this.configsByKey.set(c,d),this.applier.apply(c,g,d),{key:h.key,label:h.label,description:h.description,enabled:g,config:d}}isEnabled(c){let d=this.definitionByKey.get(c);if(!d)return!1;return this.flagsByKey.get(c)??d.defaultValue}}var tg=f.ACTION_OBSERVATION_SKIP_SCREENSHOT.name,rg=f.OBSERVE_WAIT_FOR_SKIP_SCREENSHOT.name;function oo(c){return c?.trim().toLowerCase()!=="false"&&c?.trim()!=="0"}function RL(c=process.env){return oo(I(f.ACTION_OBSERVATION_SKIP_SCREENSHOT,c))}function Ate(c=process.env){return oo(I(f.OBSERVE_WAIT_FOR_SKIP_SCREENSHOT,c))}var og=f.OBSERVE_SETTLED_SCREENSHOT.name;function Im(c,d=process.env,h=sr.getInstance()){if(c!==void 0)return c;let g=I(f.OBSERVE_SETTLED_SCREENSHOT,d);if(g!==void 0)return["true","1"].includes(g.trim().toLowerCase())?"settled":"async";return h.isEnabled("observe-settled-screenshot")?"settled":"async"}function gd(c){return c?.freshness?c.freshness==="cached-ok":c?.skipWaitForFresh??!0}function ao(c,d){return(c.result.backStack?.displayCount??0)<2&&(d.displayCount??0)>1&&(c.requestedDisplayId??c.observedAndroid?.logicalId)===0}function po(c){return{preserveDisplayState:c?.preserveDisplayState===!0,observerMode:c?.observerMode===!0,queryOptions:c?.queryOptions,skipWaitForFresh:gd(c),minTimestamp:c?.minTimestamp??0,signal:c?.signal,skipBackStack:c?.skipBackStack??!1,screenshotMode:c?.skipScreenshot?"none":Im(c?.screenshot)}}function ho(c){let{options:d}=c;return!c.observerMode&&!c.preserveDisplayState&&!d?.skipCache&&!d?.skipRecompositionTracking}function bd(c,d){let h=c.viewHierarchy?.hierarchy;return d&&h?.unavailableReason!==void 0||h===void 0||h.error!==void 0||c.viewHierarchy?.ctrlProxyIncomplete===!0&&!h.node}function fo(c,d){let{result:h,requestedDisplayId:g}=c,w=c.routedAggregateSecondary&&d.sampledForeground===null,A=h.viewHierarchy?.hierarchy;return{unavailable:w||!d.hierarchyPlatformValid||bd(h,c.preserveDisplayState),unavailableReason:A?.unavailableReason??(w?"unknown":void 0),unavailableDetail:A?.unavailableDetail??(w?`The foreground app of display ${g} could not be determined.`:void 0)}}function yo(c,d){let h=Fre(d.getTimings());if(!h)return;if(c.perfTiming=h.data,h.truncated)c.perfTimingTruncated=!0}var go=s({className:n(),bounds:s({left:a().finite(),top:a().finite(),right:a().finite(),bottom:a().finite()}),text:n().optional(),value:n().optional(),"resource-id":n().optional(),enabled:p(["true","false"]).optional(),focused:p(["true","false"]).optional(),selected:p(["true","false"]).optional(),get node(){return S(go).optional()}}),wd=s({hierarchy:go,updatedAt:a().finite(),packageName:n(),screenWidth:a().positive().finite(),screenHeight:a().positive().finite()});function Sr(c){return wd.safeParse(c).success}function TT(c){if(!Sr(c))throw new t("Invalid visionOS hierarchy; reconnect the runner.");let d=c.hierarchy,h=d.bounds,g=h.right-h.left,w=h.bottom-h.top;if(g<=0||w<=0)throw new t("Invalid visionOS window bounds; reconnect the runner.");return ER({...c,hierarchy:Ad(d),screenWidth:g,screenHeight:w})}function Ar(c){return Array.isArray(c.node)?c.node:c.node?[c.node]:[]}function At(c){return[c,...Ar(c).flatMap(At)]}function bo(c){return{...c,space:"ornament",...c.node&&{node:Ar(c).map(bo)}}}function vo(c){let h=("resource-id"in c?c["resource-id"]:c.resourceId)||c.text;return h?JSON.stringify([c.className,h]):void 0}function Rd(c,d){let h=c.bounds;return c.className==="4"&&h.left===0&&h.top===0&&h.right>0&&h.bottom>0&&h.right<d.right-d.left&&h.bottom<d.bottom-d.top}function Ad(c){let d=Ar(c),h=c.bounds,g=new Set;for(let w=0;w<d.length;w++){let A=d[w],C=A.bounds;if(!Rd(A,h))continue;let T=d.findIndex((F,_)=>_>w&&F.className==="4"),k=A.node?At(A):d.slice(w,T<0?d.length:T).flatMap(At),D=new Set(k),M=new Set(d.flatMap(At).filter((F)=>!D.has(F)).map(vo).filter(Boolean));if(k.some((F)=>{let _=F.bounds,V=vo(F);return _.left<0||_.top<0||_.right>C.right||_.bottom>C.bottom||V!==void 0&&M.has(V)}))continue;for(let F of k)g.add(F)}return{...c,node:d.map((w)=>g.has(w)?bo(w):w)}}import{AsyncLocalStorage as Pd}from"async_hooks";var He=new Pd;function Td(c,d){return c.labelSessionUuids??d?.labelSessionUuids}function Id(c,d){return c.routingBaseSessionUuid??d?.routingBaseSessionUuid}function kd(c,d){return c.callerMcpSessionId??d?.callerMcpSessionId}function xd(c,d){return c.deviceConnectionKey??d?.deviceConnectionKey}function Dd(c,d){return Object.hasOwn(c,"requestDeadline")?c.requestDeadline:d?.requestDeadline}var ol=async(c,d)=>{let h=He.getStore();return He.run({...h,...c,planRequest:c.planRequest??h?.planRequest,routingSessionUuid:c.routingSessionUuid??h?.routingSessionUuid,callerMcpSessionId:kd(c,h),deviceConnectionKey:xd(c,h),execution:c.execution??h?.execution,requestDeadline:Dd(c,h),toolSelectionProfileUuid:c.toolSelectionProfileUuid??h?.toolSelectionProfileUuid,labelSessionUuids:Td(c,h),routingBaseSessionUuid:Id(c,h),sessionToolSelectionService:c.sessionToolSelectionService??h?.sessionToolSelectionService},()=>mg((c.execution??h?.execution)?.deviceBinding,d))},Ue=()=>He.getStore(),dr=()=>He.getStore()?.autolockMcpSessionId,na=()=>He.getStore()?.oneShotCli===!0,Tte=()=>He.getStore()?.acceptanceDiscoveryOrder,zh=()=>{let c=He.getStore();return c?.autolockMcpSessionId??c?.callerMcpSessionId};function jh(){return Ue()?.execution}function Ms(){return Ue()?.requestDeadline}function pW(){return Ue()?.planLockNamespace}function Kh(){return Ue()?.explicitObserveDeviceRead===!0}import{access as So}from"fs/promises";import{join as Od}from"path";var Cr="AutoMobileVisionTest";class Pr{dependencies;builds=new rt;constructor(c){this.dependencies=c}async resolve(c){c?.throwIfAborted();let d=(this.dependencies.override??(()=>lt(f.VISIONOS_RUNNER_XCTESTRUN)))();if(d){let A=Se(d);return await(this.dependencies.access??So)(A),A}let h=this.dependencies.builder,g=await h.getXctestrunPath("visionSimulator",{scheme:Cr});if(g)return g;let w=h.getConfig();return await this.builds.run(w.derivedDataPath,async(A)=>await H(A,async()=>{let C=async()=>{A?.throwIfAborted();let T=Od(Se(w.projectRoot),"ios","control-proxy","CtrlProxy.xcodeproj");try{await(this.dependencies.access??So)(T)}catch(D){throw new t(`Visionos runner project is unavailable; set ${f.VISIONOS_RUNNER_XCTESTRUN.name} to a prebuilt visionos runner xctestrun. The published package does not include the visionos project.`,{cause:D})}await(this.dependencies.xcodebuild??new jn).executeCommand(["build-for-testing","-project",T,"-scheme",Cr,"-destination","generic/platform=visionOS Simulator","-derivedDataPath",w.derivedDataPath,"CODE_SIGNING_ALLOWED=NO"],{signal:A,timeoutMs:120000});let k=await h.getXctestrunPath("visionSimulator",{scheme:Cr});if(!k)throw new t(`No xrsimulator xctestrun found in ${w.derivedDataPath}/Build/Products after building AutoMobileVisionTest; set ${f.VISIONOS_RUNNER_XCTESTRUN.name} to a prebuilt visionos runner.`);return k};return h.runExclusiveOnDerivedData?await h.runExclusiveOnDerivedData(C):await C()}),c,{cancelWhenAllWaitersAbort:!0})}}class Ie extends t{errorCode;constructor(c,d,h){super(c,h);this.errorCode=d}}import Ed from"ws";var wo=5000,Md=20000,Fd=(c)=>{let d=new Ed(c);return{send:(h)=>d.send(h),close:()=>d.close(),onMessage:(h)=>{d.on("message",(g)=>h(g.toString()))},onFailure:(h)=>{d.on("error",h),d.on("close",()=>h(Error("Visionos runner disconnected; reconnect it.")))}}};function _d(c){return c==="request_hierarchy"?"hierarchy_update":`${c.slice(8)}_result`}function Nd(c){if(c==="request_hierarchy")return"The visionOS runner could not read this app's accessibility window even after relaunching the app. Other apps on the simulator may still work. Use a screenshot (simctl/screenshot) to see the app instead.";return`The visionOS runner could not read this app's accessibility window, so ${c} failed; the app was not relaunched. Observe the app first (observing relaunches it once to recover), then retry this step. Other apps on the simulator may still work. Use a screenshot (simctl/screenshot) to see the app instead.`}function Bd(c){return c.type==="request_hierarchy"?Md:wo}class Tr{options;socket;pending=new Map;sequence=0;supported=new Set;ready;resolveReady;rejectReady;failure;constructor(c,d={}){this.options=d;this.ready=new Promise((h,g)=>{this.resolveReady=h,this.rejectReady=g}),this.ready.then(void 0,()=>{}),this.socket=(d.factory??Fd)(c),this.socket.onMessage((h)=>this.receive(h)),this.socket.onFailure((h)=>this.fail(u(h,"Visionos runner connection failed")))}isUsable(){return this.failure===void 0}async waitUntilConnected(c,d){await l(async()=>{if(await this.ready,this.failure)throw this.failure},{timer:this.options.timer??i,timeoutMs:d?.timeoutMs??this.options.timeoutMs??wo,signal:c,label:"Visionos runner connected handshake"})}fail(c){this.failure=c,this.rejectReady(c);for(let d of this.pending.values())d.reject(c);this.pending.clear()}receive(c){try{let d=JSON.parse(c);if(!d||typeof d!=="object"||!("type"in d))throw new t("Invalid visionos runner response; reconnect it.");let h=d;if(h.type==="connected")this.connected(h);else this.reply(h)}catch(d){this.fail(u(d,"Invalid visionos runner response")),this.socket.close()}}connected(c){if(c.platform!=="visionos"){this.fail(new Ie("Refusing runner: connected platform must be visionos.","invalid_runner_platform")),this.socket.close();return}this.supported=new Set(Array.isArray(c.supportedCommands)?c.supportedCommands.filter((d)=>typeof d==="string"):[]),this.resolveReady();return}reply(c){let d=typeof c.requestId==="string"?this.pending.get(c.requestId):void 0;if(!d)return;if(c.type==="error"||c.success===!1){let h=String(c.error??"Visionos command failed");if(h.includes("kAXErrorAPIDisabled")){d.reject(new Ie(Nd(d.type),"accessibility_api_disabled",{cause:h}));return}d.reject(new Ie(h,String(c.errorCode??"command_failed")))}else if(c.type===_d(d.type)&&(c.success===!0||d.type==="request_hierarchy"&&c.success===void 0))d.resolve(c.data)}async request(c,d,h){let g=this.options.timer??i,w=h?.timeoutMs??this.options.timeoutMs??Bd(c),A=String(++this.sequence),C=new AbortController,T=c.type!=="request_hierarchy",k=!1,D=!1,M=d?AbortSignal.any([d,C.signal]):C.signal;try{return await l(async()=>{if(await this.ready,M.throwIfAborted(),this.failure)throw this.failure;if(!this.supported.has(c.type))throw new Ie(`The visionos runner does not support ${c.type}.`,"unsupported_on_visionos");return new Promise((F,_)=>{this.pending.set(A,{type:c.type,resolve:(V)=>{D=!0,F(V)},reject:(V)=>{D=!0,_(V)}}),this.socket.send(JSON.stringify({...c,requestId:A})),k=!0})},{timer:g,timeoutMs:w,signal:M,label:`Visionos runner ${c.type}`})}catch(F){if(k&&!D&&T&&!d?.aborted)throw new Ie(`Visionos runner ${c.type} got no reply within ${w}ms and may still be applied; observe before retrying.`,"input_outcome_unknown",{cause:F});throw F}finally{C.abort(),this.pending.delete(A)}}async hierarchy(c,d){let h=await this.request({type:"request_hierarchy"},c,d);if(!Sr(h))throw new t("Invalid visionos hierarchy; reconnect the runner.");return h}close(){this.fail(new t("Visionos runner closed; reconnect it.")),this.socket.close()}}class Co{runners=new Map;get(c){return this.runners.get(c)?.client}require(c){let d=this.get(c);if(!d)throw new t(`Start and connect the visionos XCUITest runner for ${c} before acting.`);return d}targetBundleId(c,d){let h=this.runners.get(c);return h?.client===d?h.targetBundleId:void 0}register(c,d,h){if(this.runners.has(c))throw new t(`A visionos runner is already registered for ${c}.`);return this.runners.set(c,{client:d,targetBundleId:h}),()=>{if(this.runners.get(c)?.client===d)this.runners.delete(c)}}}var Gh=new Co;import{rm as Hd}from"fs/promises";function Ld(c){for(let[d,h]of[["stdout",c.stdout],["stderr",c.stderr]])h?.on("data",(g)=>{e.debug(`Visionos runner ${d}: ${String(g).trimEnd()}`)})}class Ir{dependencies;constructor(c){this.dependencies=c}async launch(c){if(!Number.isInteger(c.port)||c.port<1||c.port>65535)throw new t("Visionos runner port must be an integer from 1 to 65535.");if(Gh.get(c.deviceId))throw new t("Visionos runner is already connected.");c.signal?.throwIfAborted();let d=c.bundleId?.trim()||void 0,h=await this.dependencies.writeRunnerEnvironment(c.xctestrun,{AM_PORT:String(c.port),...d?{AM_BUNDLE_ID:d}:{}},`visionos-${c.deviceId}`),g=!1,w=()=>{if(!g&&h!==c.xctestrun)g=!0,Hd(h,{force:!0}).catch((A)=>{e.warn("Failed to remove visionos runner xctestrun copy",A)})};try{return await this.launchPrepared({...c,bundleId:d,xctestrun:h},w)}catch(A){throw w(),u(A,"Failed to launch visionos runner")}}async launchPrepared(c,d){let h=this.dependencies.timer??i;c.signal?.throwIfAborted();let g=await(this.dependencies.xcodebuild??new jn).startStreaming(["test-without-building","-xctestrun",c.xctestrun,"-destination",`platform=visionOS Simulator,id=${c.deviceId}`,"-only-testing:CtrlProxyVisionUITests/CtrlProxyVisionUITests/testRunService"],{env:{...globalThis.process.env,TEST_RUNNER_AM_PORT:String(c.port),...c.bundleId?{TEST_RUNNER_AM_BUNDLE_ID:c.bundleId}:{}},stdio:["ignore","pipe","pipe"],startupSignal:c.signal}),w={exited:!1,unregister:()=>{}},A=()=>{w.exited=!0,w.unregister(),w.client?.close(),d()},C=()=>{let T=!w.exited;if(A(),T)g.kill("SIGTERM")};Ld(g),g.once("exit",A),g.once("error",A);try{return await l(()=>this.waitForRunner(c,w),{timer:h,timeoutMs:60000,label:"Visionos runner startup",onTimeout:C,signal:c.signal}),{stop:C}}catch(T){throw C(),u(T,"Failed to launch visionos runner")}}async waitForRunner(c,d){let h=this.dependencies.timer??i;while(!d.exited){let g=(this.dependencies.connect??((w)=>new Tr(w,{timer:h})))(`ws://127.0.0.1:${c.port}/ws`);d.client=g;try{await g.waitUntilConnected(c.signal)}catch(w){if(g.close(),d.exited||c.signal?.aborted||w instanceof Ie)throw u(w,"Visionos runner exited during startup");e.debug("Visionos runner not ready during startup",w),await h.sleep(100);continue}if(d.exited)break;c.signal?.throwIfAborted(),d.unregister=Gh.register(c.deviceId,g,c.bundleId);return}throw new t("Visionos runner exited before becoming ready; check the prebuilt test bundle.")}}class Pt{apps=new Map;uninstallListeners=[];get(c){return this.apps.get(c)}launched(c,d){this.apps.set(c,d)}terminated(c,d){if(this.apps.get(c)===d)this.apps.delete(c)}uninstalled(c,d){this.terminated(c,d);for(let h of this.uninstallListeners)h(c,d)}onUninstalled(c){this.uninstallListeners.push(c)}}var PL=new Pt;var FC="dev.jasonpearson.automobile.ctrlproxy.vision";class Io{dependencies;starts=new rt;runners=new Map;observedSessions=new WeakSet;constructor(c){this.dependencies=c;c.appUninstalls?.onUninstalled((d,h)=>this.appUninstalled(d,h))}appUninstalled(c,d){let h=this.runners.get(c);if(h&&(h.bundleId??FC)===d)return h.appRemoved=!0,!0;return!1}async ensure(c){let d=await this.start(c);return this.attach(c)??d.runnerUnavailable}async start(c){return this.starts.run(c.deviceId,(d)=>this.startOwned({...c,signal:d}),c.signal,{cancelWhenAllWaitersAbort:!0})}async startOwned(c){let{deviceId:d,sessions:h}=c;if(h)this.observeSessions(h);if(Gh.get(d)?.isUsable()&&!this.needsRestart(d))return{};this.stop(d);let g=this.dependencies.targetBundleId?.(d),w={controller:new AbortController,bundleId:g},A=je(c.signal,w.controller.signal);this.runners.set(d,w);try{let C=await this.dependencies.artifacts.resolve(A);A.throwIfAborted(),w.port=this.dependencies.ports.allocate(d);let T=await this.dependencies.launcher.launch({deviceId:d,xctestrun:C,port:w.port,bundleId:g,signal:A});if(w.stop=T.stop,A.aborted||this.runners.get(d)!==w){if(this.runners.get(d)!==w)T.stop();throw new t("the visionos session ended during runner startup")}return{stop:()=>{if(this.runners.get(d)===w)this.stop(d)}}}catch(C){if(this.runners.get(d)===w)this.stop(d);let T=r(C);return e.warn(`[VisionosRunner] Runner unavailable for ${d}: ${T}`,C),{runnerUnavailable:T}}}needsRestart(c){let d=this.runners.get(c);return d!==void 0&&(d.appRemoved===!0||d.bundleId!==this.dependencies.targetBundleId?.(c))}attach({deviceId:c,ownerSession:d,sessions:h}){this.observeSessions(h);let g=this.runners.get(c);if(!h.hasSession(d)){if(!g?.ownerSession)this.stop(c);return"the visionos session ended before runner startup"}if(g)g.ownerSession=d;return}stop(c){let d=this.runners.get(c);if(!d)return;this.runners.delete(c),d.controller.abort(new t("Visionos runner lifecycle ended"));try{d.stop?.()}catch(h){e.warn(`[VisionosRunner] Failed to stop runner for ${c}`,h)}finally{if(d.port!==void 0)this.dependencies.ports.release(c,d.port)}}stopSession(c){for(let[d,h]of this.runners)if(h.ownerSession===c)this.stop(d)}stopAll(){for(let c of this.runners.keys())this.stop(c)}observeSessions(c){if(this.observedSessions.has(c))return;this.observedSessions.add(c),c.onSessionRelease((d)=>this.stopSession(d)),c.onSessionDeviceUnbound((d,h)=>{if(this.runners.get(h)?.ownerSession===d)this.stop(h)})}}var kr;function kte(c){kr=c}function To(){if(!kr)throw new t("Visionos runner builder has not been registered by the server.");return kr()}function Vd(c){return{getXctestrunPath:(d,h)=>c().getXctestrunPath(d,h),getConfig:()=>c().getConfig(),runExclusiveOnDerivedData:(d)=>{let h=c();return h.runExclusiveOnDerivedData?h.runExclusiveOnDerivedData(d):d()}}}var Re;function Ud(){if(!Re)Re=new Io({artifacts:new Pr({builder:Vd(To)}),launcher:new Ir({writeRunnerEnvironment:(c,d,h)=>To().writeRunnerEnvironment(c,d,`${h}-${B.next()}`)}),targetBundleId:(c)=>PL.get(c)??globalThis.process.env.CTRL_PROXY_IOS_BUNDLE_ID,appUninstalls:PL,ports:{allocate:(c)=>ke.allocate(`visionos:${c}`,{reservedPorts:Do}),release:(c,d)=>ke.releaseIfAllocated(`visionos:${c}`,d)}}),process.once("exit",()=>Re?.stopAll());return Re}function Ete(){Re?.stopAll()}async function Rv(c,d,h){if(d?.throwIfAborted(),!Gh.get(c)?.isUsable()||(h??Re)?.needsRestart?.(c)){h??=Ud();let g=await h.start({deviceId:c,signal:d});if(d?.throwIfAborted(),g.runnerUnavailable)throw new t(`visionOS window-app runner unavailable: ${g.runnerUnavailable}`)}return $d(c,h),Gh.require(c)}function Wd(c){let d=r(c);return d.includes(FC)&&/is not running|not installed/i.test(d)}async function kT(c,d,h,g){try{return await h()}catch(w){let A=g??Re;if(d?.aborted||!Wd(w)||!A?.appUninstalled)throw w;if(A.appUninstalled(c,FC),!A.needsRestart?.(c))throw w;return e.warn(`[VisionosRunner] Host app of the runner for ${c} is gone; restarting the runner: ${r(w)}`,w),h()}}async function Ite(c,d,h){let g=h??Re;if(d?.aborted||!g?.appUninstalled(c,FC))return!1;return e.warn(`[VisionosRunner] launchApp found the host app of the runner for ${c} missing; restarting the runner`),await Rv(c,d,g),!0}function $d(c,d){let h=Ue()?.routingSessionUuid,g=R.sessionManager();if(h&&g){let w=(d??Re)?.attach({deviceId:c,ownerSession:h,sessions:g});if(w)throw new t(w)}}function ET(c){Re?.stop(c)}class We extends pf{displayId;detail;constructor(c,d={}){let h=d.ownerPackage?` owned by ${d.ownerPackage}`:"",g=d.uniqueId?` (${d.uniqueId})`:"";super(`Display ${c}${g} is a private virtual display${h}. Android's accessibility service does not track private virtual displays, so this display has no view hierarchy and cannot be observed. Input injected with "input -d ${c}" still reaches it. On an emulator, create the display public (the last -multidisplay field set to 1).`);this.displayId=c;this.detail=d}}var xo=s({className:n(),bounds:s({left:a().finite(),top:a().finite(),right:a().finite(),bottom:a().finite()}),text:n().optional(),"resource-id":n().optional(),enabled:p(["true","false"]).optional(),focused:p(["true","false"]).optional(),checkable:p(["true","false"]).optional(),checked:p(["true","false"]).optional(),focusable:p(["true","false"]).optional(),selected:p(["true","false"]).optional(),get node(){return S(xo).optional()}}),Gd=s({hierarchy:xo,updatedAt:a().finite(),packageName:n(),screenWidth:a().positive().finite(),screenHeight:a().positive().finite()});function AL(c){return Gd.safeParse(c).success}function _m(c){if(!AL(c))throw new t("Invalid tvOS hierarchy; reconnect the runner.");return ER({...c,hierarchy:Fo(c.hierarchy)})}function Eo(c,d){let h=c.bounds;if(c.checkable==="true"&&(c.checked==="true"||c.checked==="false")&&h&&h.left>=d.left&&h.top>=d.top&&h.right<=d.right&&h.bottom<=d.bottom)return c.checked;let g=[c.node??[]].flat();for(let w of g){let A=Eo(w,d);if(A!==void 0)return A}return}function Fo(c){let d=[c.node??[]].flat(),h=c.focused==="true"&&c.bounds?Eo(c,c.bounds):void 0;return{...c,...h!==void 0?{checkable:"true",checked:h}:{},...c.node?{node:d.map(Fo)}:{}}}class _o{clients=new Map;get(c){return this.clients.get(c)}require(c){let d=this.get(c);if(!d)throw new t(`Start and connect the tvos XCUITest runner for ${c} before acting.`);return d}register(c,d){if(this.clients.has(c))throw new t(`A tvos runner is already registered for ${c}.`);return this.clients.set(c,d),()=>{if(this.clients.get(c)===d)this.clients.delete(c)}}}var ia=new _o;import*as de from"fs/promises";import be from"path";var No="tvos-runner",qd="automobile-runner-",zd="tvos-runner.json";class xr{deps;cache;cacheDir;env;timer;fileSystem;flights=new rt;constructor(c={}){this.deps=c;this.timer=c.timer??i,this.cache=new so({downloader:c.downloader,checksumCalculator:c.checksumCalculator,timer:this.timer}),this.cacheDir=be.resolve(c.cacheDir??Qe(No)),this.env=c.env??process.env,this.fileSystem=c.fileSystem??de}async ensure(c){if(c?.throwIfAborted(),(this.deps.platform??process.platform)!=="darwin")return null;return this.flights.run("runner",async()=>{try{return await this.doEnsure()}catch(d){throw u(d,"Unable to resolve the released tvOS runner")}},c)}async doEnsure(){let c=this.deps.expectedChecksum??lne(this.env);if(!c)return e.info("[TVOS_RUNNER] This release has no pinned tvOS runner; no archive can be trusted."),null;if(!/^[a-f0-9]{64}$/i.test(c))throw new t("Invalid pinned tvOS runner SHA-256 checksum.");let d=be.join(this.cacheDir,c.toLowerCase()),h=be.join(d,zd),g=null;if(await this.cache.isCached({label:"[TVOS_RUNNER]",subject:"runner",expectedSha256:c,metadataPath:h,parseMetadata:(w)=>typeof w==="object"&&w!==null&&("sha256"in w)&&typeof w.sha256==="string"?{sha256:w.sha256}:null,verifyArtifact:async()=>(g=await this.findXctestrun(d),g!==null)}))return g;return this.download(c,d,h)}async findXctestrun(c){let d=be.join(c,"Build","Products");try{let h=(await this.fileSystem.readdir(d)).filter((w)=>w.includes("appletvsimulator")&&w.endsWith(".xctestrun")&&!w.startsWith(qd)&&be.basename(w)===w),g=[];for(let w of h){let A=be.join(d,w);if((await this.fileSystem.stat(A)).isFile())g.push(A)}return g.length===1?g[0]:null}catch(h){if(h instanceof Error&&"code"in h&&h.code==="ENOENT")e.debug("[TVOS_RUNNER] No cached runner products");else e.warn("[TVOS_RUNNER] Unable to inspect runner products",h);return null}}async download(c,d,h){if(this.deps.cacheDir===void 0)di(No);else await de.mkdir(this.cacheDir,{recursive:!0,mode:448}),await de.chmod(this.cacheDir,448);let g=await de.mkdtemp(be.join(this.cacheDir,".staging-")),w=be.join(g,rY),A=be.join(g,"extracted"),C,T=!1;try{await this.fetch({expected:c,archivePath:w,metadataPath:h,destination:d,extracted:A,staging:g,onDownloaded:()=>{T=!0},onPublished:(k)=>{C=k}})}catch(k){if(T)throw k;return e.warn(`[TVOS_RUNNER] Unable to download the released tvOS runner; falling back to a local build: ${r(k)}`,k),null}if(!C)throw new t("tvOS runner extraction did not publish an xctestrun.");return be.join(d,C)}async fetch(c){let{expected:d,archivePath:h,metadataPath:g,destination:w,extracted:A,staging:C}=c;await this.cache.fetch({label:"[TVOS_RUNNER]",expectedSha256:d,url:this.deps.releaseUrl??dne(this.env),archivePath:h,metadataPath:g,metadataMode:384,downloadTimeoutMs:this.deps.downloadTimeoutMs??120000,afterDownload:async(T)=>{c.onDownloaded(),await de.chmod(T,384)},mismatchError:(T,k)=>new t(`tvOS runner checksum verification failed. Expected: ${T}, Got: ${k}. The release archive is corrupted or tampered.`),timeoutError:()=>new t("Timed out downloading the tvOS runner. Check release asset availability."),publish:async(T,k)=>{await(this.deps.extract??((F,_)=>new QB().extractBundle(F,_)))(T,A);let M=await this.findXctestrun(A);if(!M)throw new t("tvOS runner archive must contain exactly one appletvsimulator xctestrun in Build/Products.");return c.onPublished(be.relative(A,M)),await de.chmod(A,448),await de.rm(w,{recursive:!0,force:!0}),await de.rename(A,w),{version:De(this.env),sha256:k,downloadedAt:this.timer.now()}},settle:()=>de.rm(C,{recursive:!0,force:!0})})}}import{access as Bo}from"fs/promises";import{join as Kd}from"path";class Or{dependencies;builds=new rt;constructor(c){this.dependencies=c}async resolve(c){c?.throwIfAborted();let d=(this.dependencies.override??(()=>lt(f.TVOS_RUNNER_XCTESTRUN)))();if(d){let C=Se(d);return await(this.dependencies.access??Bo)(C),C}let h=this.dependencies.builder,g=await h.getXctestrunPath("tvSimulator");if(g)return g;let w=await this.dependencies.release?.ensure(c);if(c?.throwIfAborted(),w)return w;let A=h.getConfig();return await this.builds.run(A.derivedDataPath,async(C)=>await H(C,async()=>{let T=async()=>{C?.throwIfAborted();let k=Kd(A.projectRoot,"ios","control-proxy","CtrlProxy.xcodeproj");try{await(this.dependencies.access??Bo)(k)}catch(M){throw new t(`Tvos runner project is unavailable; set ${f.TVOS_RUNNER_XCTESTRUN.name} to a prebuilt tvos runner xctestrun. This release has no published tvOS runner, and the published package does not include the tvos project.`,{cause:M})}await(this.dependencies.xcodebuild??new jn).executeCommand(["build-for-testing","-project",k,"-scheme","AutoMobileTVTest","-destination","generic/platform=tvOS Simulator","-derivedDataPath",A.derivedDataPath,"CODE_SIGNING_ALLOWED=NO"],{signal:C,timeoutMs:120000});let D=await h.getXctestrunPath("tvSimulator");if(!D)throw new t(`No appletvsimulator xctestrun found in ${A.derivedDataPath}/Build/Products after building AutoMobileTVTest; set ${f.TVOS_RUNNER_XCTESTRUN.name} to a prebuilt tvos runner.`);return D};return h.runExclusiveOnDerivedData?await h.runExclusiveOnDerivedData(T):await T()}),c,{cancelWhenAllWaitersAbort:!0})}}class Oe extends t{errorCode;constructor(c,d){super(c);this.errorCode=d}}class Mr extends t{cause;constructor(c,d){super(`The tvOS runner was already disconnected, so ${c} was not sent. Call startDevice to restart the runner, then retry.`);this.cause=d}}class Fr extends t{constructor(c,d){super(`The tvOS runner did not answer ${c} within ${d}ms and was disconnected; it can stick while XCTest waits for an app that is not in front. Call startDevice to restart the runner, then retry.`)}}import jd from"ws";var TL=["up","down","left","right","select","menu","home","playPause"],Xd="press_button_hold",m3=5000,Yd=(c)=>{let d=new jd(c);return{send:(h)=>d.send(h),close:()=>d.close(),onMessage:(h)=>{d.on("message",(g)=>h(g.toString()))},onFailure:(h)=>{d.on("error",h),d.on("close",()=>h(Error("Tvos runner disconnected; reconnect it.")))}}};function Jd(c){return c==="request_hierarchy"?"hierarchy_update":c==="request_screenshot"?"screenshot":`${c.slice(8)}_result`}class _r{options;socket;pending=new Map;sequence=0;supported=new Set;features=new Set;ready;resolveReady;rejectReady;failure;connectionLost=!1;holdEndsAt=0;constructor(c,d={}){this.options=d;this.ready=new Promise((h,g)=>{this.resolveReady=h,this.rejectReady=g}),this.ready.then(void 0,()=>{}),this.socket=(d.factory??Yd)(c),this.socket.onMessage((h)=>this.receive(h)),this.socket.onFailure((h)=>{if(!this.failure)this.connectionLost=!0;this.fail(u(h,"Tvos runner connection failed"))})}isUsable(){return this.failure===void 0}fail(c){this.failure??=c,this.rejectReady(this.failure);for(let d of this.pending.values())d.reject(this.failure);this.pending.clear()}receive(c){try{let d=JSON.parse(c);if(!d||typeof d!=="object"||!("type"in d))throw new t("Invalid tvos runner response; reconnect it.");let h=d;if(h.type==="connected")this.connected(h);else this.reply(h)}catch(d){this.fail(u(d,"Invalid tvos runner response")),this.socket.close()}}connected(c){if(c.platform!=="tvos"){this.fail(new Oe("Refusing runner: connected platform must be tvos.","invalid_runner_platform")),this.socket.close();return}this.supported=new Set(Array.isArray(c.supportedCommands)?c.supportedCommands.filter((d)=>typeof d==="string"):[]),this.features=new Set(Array.isArray(c.supportedFeatures)?c.supportedFeatures.filter((d)=>typeof d==="string"):[]),this.resolveReady();return}reply(c){let d=typeof c.requestId==="string"?this.pending.get(c.requestId):void 0;if(!d)return;if(c.type==="error"||c.success===!1)d.reject(new Oe(String(c.error??"Tvos command failed"),String(c.errorCode??"command_failed")));else if(c.type===Jd(d.type)&&(c.success===!0||["request_hierarchy","request_screenshot"].includes(d.type)&&c.success===void 0))d.resolve(c.data)}async request(c,d,h){let g=this.options.timer??i,w=(h?.timeoutMs??this.options.timeoutMs??m3)+Math.max(0,this.holdEndsAt-g.now()),A=String(++this.sequence),C=new AbortController,T=d?AbortSignal.any([d,C.signal]):C.signal,k=this.withForegroundHint(c),D=g.now(),M=JSON.stringify({...k,requestId:A}),F=!1,_,V=()=>_??=new Fr(c.type,w);try{return await l(async()=>{if(await this.ready,T.throwIfAborted(),this.failure)throw new Mr(c.type,this.failure);if(!this.supported.has(c.type))throw new Oe(`The tvos runner does not support ${c.type}.`,"unsupported_on_tvos");if(c.type==="request_press_button"&&c.durationMs!==void 0&&!this.features.has(Xd))throw new Oe("The tvos runner predates remote long presses (durationMs); rebuild or update the tvOS runner.","unsupported_on_tvos");return new Promise((W,G)=>{if(this.pending.set(A,{type:c.type,resolve:W,reject:G}),F=!0,c.type==="request_press_button"&&c.durationMs!==void 0)this.holdEndsAt=Math.max(this.holdEndsAt,g.now()+c.durationMs);this.socket.send(M)})},{timer:g,timeoutMs:w,signal:T,label:`Tvos runner ${c.type}`,timeoutError:()=>F?V():void 0,onTimeout:()=>{if(F)this.connectionLost=!0,this.fail(V()),this.socket.close()}})}catch(W){throw await this.requestError(W,k,{dispatched:F,startedAt:D,signal:d})}finally{C.abort(),this.pending.delete(A)}}async requestError(c,d,h){h.signal?.throwIfAborted();let g="bundleId"in d?d.bundleId:void 0;if(h.dispatched&&g&&this.connectionLost&&c===this.failure){let w=await this.options.appExit?.diagnose(g,d.type,h.startedAt,h.signal);if(w)return w}return u(c,"tvOS runner request failed")}withForegroundHint(c){if(c.type!=="request_hierarchy"&&c.type!=="request_append_text"&&c.type!=="request_press_button"||c.bundleId?.trim())return c;let d=this.options.foregroundApp?.();return d?{...c,bundleId:d}:c}async hierarchy(c){let d=await this.request({type:"request_hierarchy"},c);if(!AL(d))throw new t("Invalid tvos hierarchy; reconnect the runner.");return d}runnerExited(){if(!this.failure)this.connectionLost=!0;this.fail(new t("Tvos runner process exited; reconnect it.")),this.socket.close()}close(){this.fail(new t("Tvos runner closed; reconnect it.")),this.socket.close()}}var mW=new Pt;import{rm as Rl}from"fs/promises";class Xe extends t{bundleId;commandType;crashReport;constructor(c,d,h){let g=h?` (${[h.exceptionType,h.exceptionMessage,h.terminationReason,`crash report ${h.reportPath}`].filter(Boolean).join("; ")})`:"";super(`App ${c} exited during ${d}${g}; relaunch it with launchApp.`);this.bundleId=c;this.commandType=d;this.crashReport=h}}var Nr="crashApp is not supported on physical iOS devices; AutoMobile will not fall back to normal termination";class kt{kind="physical";listProcesses(c){return Promise.reject(new t(Nr))}killProcess(c){return Promise.reject(new t(Nr))}readCrashLog(c){return Promise.reject(new t(Nr))}}class LC{deviceId;simctl;launchctlDomain;kind="simulator";constructor(c,d,h="user"){this.deviceId=c;this.simctl=d;this.launchctlDomain=h}listProcesses(c){return this.simctl.executeCommandArgs(["spawn",this.deviceId,"launchctl","list"],c.timeoutMs,c.signal)}killProcess(c){return this.simctl.executeCommandArgs(["spawn",this.deviceId,"launchctl","kill",c.signalName??"SIGABRT",this.launchctlDomain==="system"?`system/${c.serviceLabel}`:`user/${c.uid}/${c.serviceLabel}`],c.timeoutMs,c.signal)}readCrashLog(c){return this.simctl.executeCommandArgs(["spawn",this.deviceId,"log","show","--last","1m","--style","compact","--timezone","UTC","--predicate",'eventMessage CONTAINS[c] "SIGABRT"'],c.timeoutMs,c.signal)}}function _te(c,d){return z({deviceId:c})==="simulator"?new LC(c,d.simctl,d.platform==="tvos"||d.platform==="watchos"?"system":"user"):new kt}function sl(c,d){for(let h of c.split(`
|
|
6
|
-
`)){let g=h.trim().match(/^(\d+)\s+\S+\s+(UIKitApplication:(.+?)\[[^\]]+\]\[[^\]]+\])$/);if(g?.[3]===d)return{pid:Number(g[1]),serviceLabel:g[2]}}return null}function BC(c,d){return sl(c,d)?.pid??null}import{homedir as fl}from"os";import{join as Vo}from"path";var fW=16;function xm(c){if(c===void 0)return;let d=c.trim();if(d.length===0)return;return d.length>500?`${d.slice(0,499)}\u2026`:d}function xte(c){let d=[c.className,c.fileName&&`${c.fileName}:${c.lineNumber??"?"}`].filter(Boolean).join(" ");return d?`${c.methodName} (${d})`:c.methodName}var Br=1000;function hW(c,d){return c.timestampMs===void 0||c.timestampMs>=d-Br}function gW(c,d){return c.appId===d.appId&&(d.processId===void 0||c.processId===d.processId)}var Qd="309",Zd=7;function Ho(c){try{let d=JSON.parse(c);return d!==null&&typeof d==="object"?d:void 0}catch(d){e.debug(`[CrashReports] .ips section is not JSON: ${d}`);return}}function el(c){let d=c?.match(/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})(?:\.(\d+))? ([+-])(\d{2})(\d{2})$/);if(!d)return;let h=(d[3]??"").padEnd(3,"0").slice(0,3),g=Date.parse(`${d[1]}T${d[2]}.${h}${d[4]}${d[5]}:${d[6]}`);return Number.isNaN(g)?void 0:g}function tl(c){let d=c.procPath?.match(/\/CoreSimulator\/Devices\/([0-9A-Fa-f-]{36})\//)?.[1],h=c.coalitionName?.match(/^com\.apple\.CoreSimulator\.SimDevice\.([0-9A-Fa-f-]{36})$/)?.[1];return(d??h)?.toUpperCase()}function rl(c){let d=c?.indexOf(".app/")??-1;return d>=0?c.slice(0,d+5):void 0}function il(c){let d=c.threads??[],h=(c.faultingThread!==void 0?d[c.faultingThread]:void 0)??d.find((w)=>w.triggered),g=rl(c.procPath);return(h?.frames??[]).slice(0,fW).map((w)=>cl(w,c,g))}function nl(c){let d=xm(c.symbol);if(d)return d;return c.imageOffset!==void 0?`0x${c.imageOffset.toString(16)}`:"???"}function cl(c,d,h){let g=c.imageIndex!==void 0?d.usedImages?.[c.imageIndex]:void 0,w=g?.path??"";return{className:g?.name??"",methodName:nl(c),fileName:c.sourceFile??null,lineNumber:c.sourceLine??null,isAppCode:h!==void 0&&w.startsWith(h)}}function dl(c){let d=Object.values(c.asi??{}).flatMap((h)=>Array.isArray(h)?h.filter((g)=>typeof g==="string"):[]);return xm(d.join(`
|
|
7
|
-
`))}function ll(c){let d=c.termination;if(!d)return;let g=[[d.namespace,d.code].filter((w)=>w!==void 0).join(" "),d.indicator].filter(Boolean).join(": ");return xm(d.byProc?`${g} (by ${d.byProc})`:g)}function ul(c){let d=c.exception??{},h=[d.type,d.signal&&`(${d.signal})`].filter(Boolean).join(" ");return{exceptionType:xm(h)??"unknown",exceptionCode:xm([d.codes,d.subtype].filter(Boolean).join(" ")),exceptionMessage:dl(c),terminationReason:ll(c)}}function pl(c){let d=c.indexOf(`
|
|
8
|
-
`);if(d<0)return;let h=Ho(c.slice(0,d));if(h?.bug_type!==Qd)return;let g=Ho(c.slice(d+1));return g?{header:h,body:g}:void 0}function Lo(c,d){let h=pl(c),g=h?.body.bundleInfo?.CFBundleIdentifier??h?.header.bundleID;if(!h||!g)return;let{header:w,body:A}=h,C=tl(A);return{report:{id:A.incident??w.incident_id??d,platform:"ios",source:"ios_ips",appId:g,appVersion:A.bundleInfo?.CFBundleShortVersionString??w.app_version,processId:A.pid,timestampMs:el(A.captureTime),...ul(A),frames:il(A),reportPath:d,...ml(w,A,C)},...C?{simulatorDeviceId:C}:{}}}function ml(c,d,h){return{deviceModel:c.platform===Zd||h!==void 0?"iOS Simulator":d.modelCode,osVersion:xm(c.os_version)}}var yl=32,vl=4194304,Pw={readdir:async(c)=>Rr(c),stat:async(c)=>kf(c),readFileBuffer:async(c)=>Tf(c)};class $C{deviceId;fileSystem;reportsDirectory;constructor(c,d,h=Vo(fl(),"Library","Logs","DiagnosticReports")){this.deviceId=c;this.fileSystem=d;this.reportsDirectory=h}async find(c){let d=this.deviceId.toUpperCase();for(let h of await this.freshCandidates(c.notBeforeTimestampMs)){c.signal?.throwIfAborted();let g=(await this.readReport(h))?.parsed;if(g?.simulatorDeviceId===d&&gW(g.report,c)&&hW(g.report,c.notBeforeTimestampMs))return{status:"found",report:g.report}}return{status:"notFound"}}async read(c,d){let h=this.deviceId.toUpperCase();for(let g of await this.freshCandidates(0)){d?.throwIfAborted();let w=await this.readReport(g);if(w?.parsed?.simulatorDeviceId===h&&w.parsed.report.id===c)return{report:w.parsed.report,text:w.text}}return}async freshCandidates(c){let d;try{d=(await this.fileSystem.readdir(this.reportsDirectory)).map((g)=>g.name)}catch(g){return e.debug(`[CrashReports] cannot list ${this.reportsDirectory}: ${g}`),[]}let h=[];for(let g of d.filter((w)=>w.endsWith(".ips"))){let w=Vo(this.reportsDirectory,g);try{let A=await this.fileSystem.stat(w),C=A.mtime.getTime();if(A.isFile()&&A.size<=vl&&C>=c-Br)h.push({path:w,mtimeMs:C})}catch(A){e.debug(`[CrashReports] cannot stat ${w}: ${A}`)}}return h.sort((g,w)=>w.mtimeMs-g.mtimeMs).slice(0,yl).map((g)=>g.path)}async readReport(c){try{let d=(await this.fileSystem.readFileBuffer(c)).toString("utf8");return{text:d,parsed:Lo(d,c)}}catch(d){e.warn(`[CrashReports] failed to read ${c}: ${r(d)}`,d);return}}}var gl=4000,bl=6000;function Sl(c,d=new L){let h=new LC(c,d,"system");return{async isRunning(g,w){let A=await h.listProcesses({timeoutMs:gl,signal:w});return sl(A.stdout,g)!==null}}}class Uo{dependencies;constructor(c){this.dependencies=c}async diagnose(c,d,h,g){let w=new AbortController,A=g?AbortSignal.any([g,w.signal]):w.signal,C=!1;try{return await l(async()=>{let T;try{T=await this.dependencies.liveness.isRunning(c,A)}catch(D){if(!(D instanceof ko))throw D;A.throwIfAborted(),e.warn(`[TvosRunner] App liveness probe timed out for ${c}; retrying`,D),T=await this.dependencies.liveness.isRunning(c,A)}if(T)return;A.throwIfAborted(),C=!0;let k=await this.dependencies.finder.find({appId:c,notBeforeTimestampMs:h,signal:A});return new Xe(c,d,k.status==="found"?k.report:void 0)},{timer:this.dependencies.timer??i,timeoutMs:bl,signal:A,label:"tvOS app-exit diagnosis",onTimeout:()=>w.abort()})}catch(T){return g?.throwIfAborted(),e.warn(`[TvosRunner] App-exit diagnosis failed for ${c}`,T),C?new Xe(c,d):void 0}finally{w.abort()}}}function Wo(c,d){return new Uo({timer:d,liveness:Sl(c),finder:new $C(c,Pw)})}function Al(c,d,h={}){let g=h.targetApps??mW;return new _r(c,{timer:h.timer,factory:h.factory,foregroundApp:()=>g.get(d),appExit:h.appExit??Wo(d,h.timer)})}class Hr{dependencies;constructor(c){this.dependencies=c}async launch(c){if(!Number.isInteger(c.port)||c.port<1||c.port>65535)throw new t("Tvos runner port must be an integer from 1 to 65535.");if(ia.get(c.deviceId))throw new t("Tvos runner is already connected.");c.signal?.throwIfAborted();let d=await this.dependencies.writeRunnerEnvironment(c.xctestrun,{AM_PORT:String(c.port)},`tvos-${c.deviceId}`),h=!1,g=()=>{if(!h&&d!==c.xctestrun)h=!0,Rl(d,{force:!0}).catch((w)=>{e.warn("Failed to remove tvos runner xctestrun copy",w)})};try{return await this.launchPrepared({...c,xctestrun:d},g)}catch(w){throw g(),u(w,"Failed to launch tvos runner")}}async launchPrepared(c,d){let h=this.dependencies.timer??i;c.signal?.throwIfAborted();let g=await(this.dependencies.xcodebuild??new jn).startStreaming(["test-without-building","-xctestrun",c.xctestrun,"-destination",`platform=tvOS Simulator,id=${c.deviceId}`,"-only-testing:CtrlProxyTVUITests/CtrlProxyTVUITests/testRunService"],{env:{...globalThis.process.env,TEST_RUNNER_AM_PORT:String(c.port)},stdio:"ignore",startupSignal:c.signal}),w={exited:!1,unregister:()=>{}},A=()=>{if(!w.exited)w.client?.runnerExited();else w.client?.close();w.exited=!0,w.unregister(),d()},C=()=>{let T=!w.exited;if(w.exited=!0,A(),T)g.kill("SIGTERM")};g.once("exit",A),g.once("error",A);try{return await l(()=>this.waitForRunner(c,w),{timer:h,timeoutMs:60000,label:"Tvos runner startup",onTimeout:C,signal:c.signal}),{stop:C}}catch(T){throw C(),u(T,"Failed to launch tvos runner")}}async waitForRunner(c,d){let h=this.dependencies.timer??i;while(!d.exited){let g=(this.dependencies.connect??((w)=>Al(w,c.deviceId,{timer:h})))(`ws://127.0.0.1:${c.port}/ws`);d.client=g;try{await g.hierarchy(c.signal)}catch(w){if(g.close(),d.exited||c.signal?.aborted||w instanceof Oe)throw u(w,"Tvos runner exited during startup");e.debug("Tvos runner not ready during startup",w),await h.sleep(100);continue}if(d.exited)break;c.signal?.throwIfAborted(),d.unregister=ia.register(c.deviceId,g);return}throw new t("Tvos runner exited before becoming ready; check the prebuilt test bundle.")}}class $o{dependencies;runners=new Map;observedSessions=new WeakSet;restarts=new rt;constructor(c){this.dependencies=c}async ensure(c){let d=await this.start(c);return this.attach(c)??d.runnerUnavailable}async start(c){return this.startOwned(c)}ownsRunner(c){return this.runners.has(c)}async restartOwned(c,d){return this.restarts.run(c,async(h)=>{if(ia.get(c)?.isUsable())return{};let g=this.runners.get(c);if(!g){let A=ia.get(c);if(A)return{unownedRunner:A};return{runnerUnavailable:"the runner is not owned by this lifecycle"}}let w=new AbortController;try{let A=this.startOwned({deviceId:c,signal:je(h,w.signal)},g.ownerSession);return await l(A,{timer:this.dependencies.timer??i,timeoutMs:65000,signal:je(h,this.runners.get(c)?.controller.signal),label:"tvOS runner recovery",onTimeout:()=>w.abort()})}catch(A){throw new t(`tvOS runner recovery failed: ${r(A)}. Call startDevice to restart the runner.`,{cause:A})}finally{w.abort()}},d,{cancelWhenAllWaitersAbort:!0})}async startOwned(c,d){let{deviceId:h,sessions:g}=c;if(g)this.observeSessions(g);if(ia.get(h)?.isUsable())return{};this.stop(h);let w={controller:new AbortController,ownerSession:d},A=je(c.signal,w.controller.signal);this.runners.set(h,w);let C=()=>{if(this.runners.get(h)===w)this.stop(h)};A.addEventListener("abort",C,{once:!0});try{A.throwIfAborted();let T=await this.dependencies.artifacts.resolve(A);A.throwIfAborted(),w.port=this.dependencies.ports.allocate(h);let k=await this.dependencies.launcher.launch({deviceId:h,xctestrun:T,port:w.port,signal:A});if(w.stop=k.stop,A.aborted||this.runners.get(h)!==w){if(this.runners.get(h)!==w)k.stop();throw new t("the tvos session ended during runner startup")}return{stop:()=>{if(this.runners.get(h)===w)this.stop(h)}}}catch(T){if(this.runners.get(h)===w)this.stop(h,T);let k=r(T);return e.warn(`[TvosRunner] Runner unavailable for ${h}: ${k}`,T),{runnerUnavailable:k}}finally{A.removeEventListener("abort",C)}}attach({deviceId:c,ownerSession:d,sessions:h}){if(this.observeSessions(h),!h.hasSession(d))return this.stop(c),"the tvos session ended before runner startup";let g=this.runners.get(c);if(g)g.ownerSession=d;return}stop(c,d=new t("Tvos runner lifecycle ended")){let h=this.runners.get(c);if(!h)return;this.runners.delete(c),h.controller.abort(d);try{h.stop?.()}catch(g){e.warn(`[TvosRunner] Failed to stop runner for ${c}`,g)}finally{if(h.port!==void 0)this.dependencies.ports.release(c,h.port)}}stopSession(c){for(let[d,h]of this.runners)if(h.ownerSession===c)this.stop(d)}stopAll(){for(let c of this.runners.keys())this.stop(c)}observeSessions(c){if(this.observedSessions.has(c))return;this.observedSessions.add(c),c.onSessionRelease((d)=>this.stopSession(d)),c.onSessionDeviceUnbound((d,h)=>{if(this.runners.get(h)?.ownerSession===d)this.stop(h)})}}var Lr;function Cte(c){Lr=c}function xt(){if(!Lr)throw new t("Tvos runner builder has not been registered by the server.");return Lr()}var Ze;function sp(){if(!Ze)Ze=new $o({artifacts:new Or({release:new xr,builder:{getXctestrunPath:(c)=>xt().getXctestrunPath(c),getConfig:()=>xt().getConfig(),runExclusiveOnDerivedData:(c)=>{let d=xt();return d.runExclusiveOnDerivedData?d.runExclusiveOnDerivedData(c):c()}}}),launcher:new Hr({writeRunnerEnvironment:(c,d,h)=>xt().writeRunnerEnvironment(c,d,`${h}-${B.next()}`)}),ports:{allocate:(c)=>ke.allocate(`tvos:${c}`,{reservedPorts:Do}),release:(c,d)=>ke.releaseIfAllocated(`tvos:${c}`,d)}}),process.once("exit",()=>Ze?.stopAll());return Ze}function Dte(){Ze?.stopAll()}async function oa(c,d,h){if(d?.throwIfAborted(),!ia.get(c)?.isUsable()){let g=await(h??sp()).restartOwned(c,d);if(d?.throwIfAborted(),g.unownedRunner)return g.unownedRunner;if(g.runnerUnavailable||!ia.get(c)?.isUsable())throw new t(`tvOS runner unavailable for ${c}: ${g.runnerUnavailable??"recovery did not connect a usable runner"}. Call startDevice to restart the runner, then retry.`)}return ia.require(c)}function f3(c){if(!c||typeof c!=="object")return!1;let d=c;return typeof d.timestamp==="number"&&Number.isFinite(d.timestamp)&&[d.screenWidth,d.screenHeight,d.screenScale].every((h)=>typeof h==="number"&&Number.isFinite(h)&&h>0)&&(d.bundleId===void 0||d.bundleId===null||typeof d.bundleId==="string")&&Go(d.root)}function Go(c){if(!c||typeof c!=="object")return!1;let d=c;return typeof d.className==="string"&&Cl(d.bounds)&&Pl(d)&&(d.children===void 0||d.children===null||Array.isArray(d.children)&&d.children.every(Go))}function Cl(c){if(!c||typeof c!=="object")return!1;let d=c;return["left","top","right","bottom"].every((h)=>typeof d[h]==="number"&&Number.isFinite(d[h]))}function Pl(c){let d=c.accessibilityTraits??[];return[c.accessibilityIdentifier,c.accessibilityLabel,c.role].every((h)=>h===void 0||h===null||typeof h==="string")&&[c.isHidden,c.isOccluded,c.isAccessibilityElement,c.isAccessibilityFocused,c.hasTapTarget,c.isUserInteractionEnabled].every((h)=>h===void 0||h===null||typeof h==="boolean")&&Number.isFinite(c.alpha??1)&&Array.isArray(d)&&d.every((h)=>typeof h==="string")}function qo(c){return!c.isHidden&&!c.isOccluded&&(c.alpha??1)>0}var kl=new Set([9,10,12,14,15,16,17,20,27,30,40,41,42,45,49,50,52,54,56,59,60,75,80]),xl=new Set([45,49,50,52]),Dl=new Set([26,32,46]);function Ol(c){let d=/^XCUIElementType\((\d+)\)$/.exec(c);return d?Number(d[1]):void 0}function Ur(c,d){let h=Ol(c.className);return h!==void 0&&d.has(h)}function El(c,d){let h=d&&Ur(c,kl),g=d&&Ur(c,xl);return{clickable:String((c.hasTapTarget??!1)||h),scrollable:Ur(c,Dl)?"true":void 0,actions:g?["set_text"]:void 0}}function zo(c){let d=c.isUserInteractionEnabled??!0;return{text:c.accessibilityLabel??void 0,resourceId:c.accessibilityIdentifier??void 0,role:c.role??void 0,className:c.className,bounds:c.bounds,enabled:String(d),...El(c,d),focusable:String(c.isAccessibilityElement??!1),accessibilityFocused:String(c.isAccessibilityFocused??!1),extras:c.accessibilityTraits?.length?{"sdk.accessibilityTraits":c.accessibilityTraits.join(",")}:void 0,node:(c.children??[]).filter(qo).map(zo)}}function Pv(c){if(!f3(c))throw new t("The watch runner returned an invalid hierarchy; reconnect the runner.");return ER({updatedAt:c.timestamp,hierarchy:qo(c.root)?zo(c.root):{},packageName:c.bundleId??"",screenWidth:c.screenWidth,screenHeight:c.screenHeight,screenScale:c.screenScale})}class Ko{clients=new Map;get(c){return this.clients.get(c)}require(c){let d=this.get(c);if(!d)throw new t(`Start and connect the watch XCUITest runner for ${c} before acting.`);return d}register(c,d){if(this.clients.has(c))throw new t(`A watch runner is already registered for ${c}.`);return this.clients.set(c,d),()=>{if(this.clients.get(c)===d)this.clients.delete(c)}}}var Po=new Ko;var $r=Nt(Tp());var jo=new Map;function UC(c){let d=jo.get(c);if(!d)d=new Wn,jo.set(c,d);return d}var Ml=1500;async function Xo(c,{deadline:d,signal:h},g){if(c.deviceId===void 0)return g();o(h);let w=d-c.timer.now();if(w<=0)throw Error("Hierarchy fallback deadline exhausted before the dump lock was free");let A=UC(c.deviceId).acquire(),C;try{C=await l(A,{timer:c.timer,timeoutMs:w,signal:h,label:"Hierarchy fallback dump lock wait"})}catch(T){throw A.then((k)=>k()),T}try{return await g()}finally{C()}}function Yo(c,d){let h=Tt(d??c.bounds);return JSON.stringify([c.package,c.class,wl(c,"resource-id")??"",wl(c,"text")??"",wl(c,"content-desc")??"",h?[h.left,h.top,h.right,h.bottom]:null])}function Gr(c,d,h){return c.flatMap((g)=>{let w=Gr(g.node??[],d,h),A=g.$,C=Tt(A?.bounds);if(!A||h!==void 0&&A.package!==h||!C||C.right<=C.left||C.bottom<=C.top)return w;let T={...A,"hierarchy-source":"uiautomator"},k={$:T,bounds:C,...w.length?{node:w}:{}};if(delete T["view-id"],delete T["unique-id"],delete T.actions,d.has(Yo(T,k.bounds)))return w;return[k]})}function _l(c,d,h){let g=new K,w=new Set(g.flattenViewHierarchy(c,{includeWindows:!0}).map((T)=>Yo(T.element,T.element.bounds))),A=Gr(d,w,h);if(!A.length)return c;let C={...c,packageName:h,hierarchy:{node:{$:{},node:[...g.extractRootNodes(c),...A]}},sources:[...new Set([...c.sources??["control-proxy"],"uiautomator"])],fresh:!1};return delete C.frameContext,delete C.receivedAt,delete C.updatedAt,C}async function yW(c,d,h,g){if(o(g),d.timer.now()>=h)return c;let w=es(d.idGenerator),A=ts(d,{deadline:h,signal:g});try{let C=await d.adb.getForegroundApp(g,h-d.timer.now());if(!C)return c;if(c.packageName!==void 0&&c.packageName!==C.packageName)return c;e.warn(`[HierarchyFallback] Supplementing incomplete CtrlProxy hierarchy (ctrlProxyIncompleteReason=${c.ctrlProxyIncompleteReason??"unknown"})`);let T=await Xo(d,{deadline:h,signal:g},async()=>(await A(["shell","uiautomator","dump",w]),A(["shell","cat",w])));return o(g),await Nl(c,T.stdout,C,{deps:d,bound:{deadline:h,signal:g}})}catch(C){return o(g),e.debug("[HierarchyFallback] Could not supplement incomplete CtrlProxy hierarchy",C),c}finally{await Jo(d,w,h,g)}}async function Jo(c,d,h,g){let w=c.adb.execute(["shell","rm","-f",d],{timeoutMs:Ml,signal:new AbortController().signal,noRetry:!0}).catch((C)=>{e.debug("[HierarchyFallback] Could not remove temporary dump",C)}),A=h-c.timer.now();if(g?.aborted||A<=0){o(g);return}try{await l(w,{timer:c.timer,timeoutMs:A,signal:g,label:"Hierarchy fallback cleanup wait"})}catch(C){e.debug("[HierarchyFallback] Stopped waiting for temporary dump cleanup",C)}o(g)}function es(c=B){return`/data/local/tmp/automobile-hierarchy-${c.next()}.xml`}async function Nl(c,d,h,{deps:g,bound:w}){let{deadline:A,signal:C}=w,k=(await $r.parseStringPromise(d,{explicitArray:!0})).hierarchy?.node;if(!Array.isArray(k)||g.timer.now()>=A)return c;let D=await g.adb.getForegroundApp(C,A-g.timer.now());if(o(C),D?.packageName!==h.packageName||D?.userId!==h.userId||g.timer.now()>=A)return c;return _l(c,k,h.packageName)}function ts(c,{deadline:d,signal:h}){return async(g)=>{o(h);let w=d-c.timer.now();if(w<=0)throw Error("Hierarchy fallback deadline exhausted");return c.adb.execute(g,{timeoutMs:w,signal:h,noRetry:!0,maxBuffer:4194304})}}function Bl(c){let d=new Set,h=(g)=>{let w=g.$?.package;if(typeof w==="string"&&w)d.add(w);(g.node??[]).forEach(h)};return c.forEach(h),d.size===1?[...d][0]:void 0}function rs(c,d){return c.every((h)=>{let g=h.bounds;return(!g||g.left>=0&&g.top>=0&&g.right<=d.width&&g.bottom<=d.height)&&rs(h.node??[],d)})}function Hl(c){let d=Pk(c,{current:!0});return d.length?d:Og(c)}async function Ll(c,d){let h=Hl((await d(["shell","dumpsys","display"])).stdout),g=h.find((A)=>A.logicalId===String(c));if(g&&Zne(g))throw new We(c,{uniqueId:g.uniqueId,ownerPackage:g.ownerPackage});let w=g?.sizePx;if(!w||w.width<=0||w.height<=0)throw new t(`Display ${c} has no readable size in dumpsys display`);return{size:w,defaultSize:h.find((A)=>A.logicalId==="0")?.sizePx}}function Vl(c,d,{size:h,defaultSize:g}){let w=`${h.width}x${h.height}`;if(!rs(c,h))return`UIAutomator dump does not fit display ${d} (${w}); this Android release likely ignores --display`;if(!c.some(({bounds:C})=>C?.left===0&&C.top===0&&C.right===h.width&&C.bottom===h.height))return`UIAutomator dump has no window spanning display ${d} (${w}), so it cannot be shown to come from that display`;if(!g||g.width===h.width&&g.height===h.height)return`Display ${d} (${w}) cannot be told apart from the default display by size, so a UIAutomator dump cannot be shown to come from it`;return}async function is(c,d,h,g){let w=es(d.idGenerator),A=ts(d,{deadline:h,signal:g});try{let C=await Ll(c,A),{size:T}=C,k=await Xo(d,{deadline:h,signal:g},async()=>(await A(["shell","uiautomator","dump","--display",String(c),w]),A(["shell","cat",w]))),D=await $r.parseStringPromise(k.stdout,{explicitArray:!0});o(g);let M=Gr(D.hierarchy?.node??[],new Set);if(!M.length||d.timer.now()>=h)throw new t(`UIAutomator returned no hierarchy for display ${c}`);let F=Vl(M,c,C);if(F)throw new t(F);let _=Bl(M);return{hierarchy:{node:M.length===1?M[0]:{$:{},node:M}},displayId:c,screenWidth:T.width,screenHeight:T.height,..._?{packageName:_}:{},sources:["uiautomator"],fresh:!1}}catch(C){if(o(g),C instanceof We)throw C;throw u(C,`Failed to read display ${c} with UIAutomator`)}finally{await Jo(d,w,h,g)}}class qr{hierarchy;sync;visible;settle;constructor(c,d,h,g){this.hierarchy=c;this.sync=d;this.visible=h;this.settle=g}readCached(c){return this.hierarchy.getViewHierarchy({},{skipWaitForFresh:!0,minTimestamp:c.minTimestamp??0,signal:c.signal,timeoutMs:c.timeoutMs})}readFresh(c){return this.sync(c)}async readSettled(c){if(!this.settle)throw new t("Settled hierarchy capture requires a settlement adapter");let d=await this.settle.execute({timeoutMs:c.timeoutMs,initialMinTimestampMs:c.minTimestamp,signal:c.signal,skipPerformanceAudit:!0,skipRecompositionTracking:!0});if(!d.settled||!d.observation.viewHierarchy)throw new t(`Hierarchy did not settle: ${d.terminalReason}`);return d.observation.viewHierarchy}projectVisible(c){return this.visible(c)}}class tt extends t{}class zr{clock;current;listeners=new Set;constructor(c,d){this.clock=c;this.current=d}get deadlineMs(){return this.current}remainingMs(){return Math.max(0,this.current-this.clock.now())}set(c){if(c===this.current)return;this.current=c;for(let d of[...this.listeners])d()}onChange(c){return this.listeners.add(c),()=>{this.listeners.delete(c)}}whenExpired(c,d,h){let g,w=!1,A=()=>{if(g!==void 0)c.clearTimeout(g),g=void 0},C=()=>{if(w)return;A(),g=c.setTimeout(()=>{if(g=void 0,this.remainingMs()>0){C();return}w=!0,T(),d()},this.remainingMs()),h?.(g)},T=this.onChange(C);return C(),()=>{w=!0,T(),A()}}}async function Ul(c,d,h){let g=v.create(c),[w,A]=await Promise.allSettled([g.execute(["shell","cmd","package","path","android"],{timeoutMs:h,noRetry:!0,signal:d}),g.execute(["shell","settings","get","secure","accessibility_enabled"],{timeoutMs:h,noRetry:!0,signal:d})]);d.throwIfAborted();let C=[],T=[];if(w.status==="rejected"||!w.value.stdout.includes("package:"))C.push("package"),T.push(w.status==="rejected"?`package: ${re(w.reason)}`:`package: ${re(w.value.stdout||w.value.stderr)}`);if(A.status==="rejected"||hl(`${A.value.stdout}
|
|
9
|
-
${A.value.stderr}`))C.push("settings"),T.push(A.status==="rejected"?`settings: ${re(A.reason)}`:`settings: ${re(A.value.stdout||A.value.stderr)}`);return{ready:C.length===0,...C.length>0?{unavailableResources:C}:{},...T.length>0?{diagnostic:T.join("; ")}:{}}}function ns(c){return re(c).replace(/\s+/g," ").trim()||"empty"}async function Wl(c,d){let h=v.create(c),g=v.create(),w={timeoutMs:ze,noRetry:!0,signal:d},[A,C,T]=await Promise.allSettled([h.execute(["shell","getprop","sys.boot_completed"],w),g.execute(["devices","-l"],w),g.execute(["-s",c.deviceId,"get-state"],w)]),k=(D)=>D.status==="fulfilled"?ns(D.value.stdout||D.value.stderr):`unavailable (${ns(r(D.reason))})`;return{sysBootCompleted:k(A),adbDevices:k(C),emulatorQemuHealth:k(T)}}function vW(c=i){return new wL({timer:c,getAndroidFrameworkReadiness:Ul,getAndroidManager:(d)=>le.getInstance(d),getAndroidClient:(d)=>E.getInstance(d),getIosManager:(d)=>ye.getInstance(d),getIosClient:(d,h)=>x.getInstance(d,h),checkIosOverride:pb,awaitIosStartupMaintenance:()=>ye.awaitStartupOrphanRunnerReap(),getAndroidRunnerConnectDiagnostic:async(d,h)=>{let g=v.create(d),[w,A]=await Promise.all([g.getDeviceLock(h),g.listUsers(h)]),C=A.find((T)=>T.profileType==="primary"||T.userId===0);return{deviceLock:w,primaryUserStartState:C?.startState}},getAndroidRunnerHealthDiagnostic:Wl})}function Kr(c){return c.platform==="ios"?x.getExistingInstance(c.deviceId):E.getExistingInstance(c.deviceId)}var $l={async awaitTransition(c,d){return R.devicePool()?.waitForAssignmentTransition(c.deviceId,d)??!1},canStart(c){let d=R.devicePool();if(!d)return!1;let h=d.getDevice(c.deviceId);return!v$(lo(c.platform,c.deviceId))&&h?.platform===c.platform&&h.name===c.name&&wr(h)&&!O(h)&&d.isSafeForObservationServiceStart(c.deviceId)}},Gl={available:()=>R.devicePoolWrites()!==void 0,isPooled:(c)=>Boolean(R.devicePool()?.getDevice(c.deviceId)),ensurePooled:async(c)=>{await R.devicePoolWrites()?.pickUpRunningDevice(c)}},ql=1e4,os=8,zl=60000,Kl=300000;class as{options;queueSnapshots=new Map;flights=new rt;pickupFlights=new rt;unpooledPickupAt=new Map;poolPickup;timer;guard;constructor(c={}){this.options=c;this.timer=c.timer??i,this.guard=c.ownershipGuard??$l,this.poolPickup=c.poolPickup??Gl}async start(c){if(c.signal?.throwIfAborted(),!this.guard.canStart(c.device)){if(this.poolPickup.available()&&!this.poolPickup.isPooled(c.device))await this.pickupIfUnpooled(c);await this.admit(c)}let d=lo(c.device.platform,c.device.deviceId),h=this.queueSnapshotFor(d),g=!1;try{return await l(()=>this.flights.run(d,(w)=>this.setup({request:c,flightSignal:w,snapshot:h}),c.signal,{cancelWhenAllWaitersAbort:!0}),{timer:this.timer,timeoutMs:Math.max(0,c.deadlineMs-this.timer.now()),signal:c.signal,label:"Observer hierarchy service start",onTimeout:()=>{g=!0}})}catch(w){c.signal?.throwIfAborted(),e.warn(`[observe] Hierarchy service start failed: ${r(w)}`,w);let A=g&&c.device.platform==="ios"&&this.flights.has(d);return this.rethrowStartupFailure(w,c,h,A)}finally{if(!this.flights.has(d))this.clearQueueSnapshot(d,h)}}async admit(c){let d=0;while(!this.guard.canStart(c.device)){let h=c.deadlineMs-this.timer.now();if(!this.guard.awaitTransition||h<=0||d>=os)break;if(d++,!await this.awaitTransition(c.device,c.deadlineMs,c.signal))break}if(!this.guard.canStart(c.device))throw new t("service start declined: ownership or pool transition cannot be excluded")}async awaitTransition(c,d,h){return l(()=>this.guard.awaitTransition(c,h),{timer:this.timer,timeoutMs:Math.max(0,d-this.timer.now()),signal:h,label:"Observer pool assignment transition"})}queueSnapshotFor(c){let d=this.flights.has(c)?this.queueSnapshots.get(c)??{}:{};return this.queueSnapshots.set(c,d),d}clearQueueSnapshot(c,d){if(this.queueSnapshots.get(c)===d)this.queueSnapshots.delete(c)}rethrowStartupFailure(c,d,h,g){if(!(c instanceof Ro&&c.deadlineExhausted||c instanceof Error&&c.message.startsWith("Observer hierarchy service start timed out"))||d.device.platform!=="ios")throw c;let A=h.status??this.launchQueueStatus(d.device);throw new SO(d.device.deviceId,A,{cause:c,startWindowExpired:!A&&!g})}launchQueueStatus(c){return c.platform==="ios"?(this.options.launchQueue??JB()).queueStatus(c.deviceId):void 0}async pickupIfUnpooled(c){let{device:d}=c;if(this.poolPickup.isPooled(d))return;let h=c.deadlineMs-this.timer.now();if(h<=0)throw new t("Observer device pool pickup timed out before pickup");let g=lo(d.platform,d.deviceId),w=await l(()=>this.pickupFlights.run(g,async()=>{let A=this.unpooledPickupAt.get(g);if(this.poolPickup.isPooled(d)||A!==void 0&&this.timer.now()-A<ql)return;let C;try{await this.poolPickup.ensurePooled(d)}catch(T){C=r(T),e.warn(`[observe] Device pool pickup failed: ${C}`,T)}if(!this.poolPickup.isPooled(d))this.unpooledPickupAt.set(g,this.timer.now());else this.unpooledPickupAt.delete(g);return C},c.signal),{timer:this.timer,timeoutMs:h,signal:c.signal,label:"Observer device pool pickup"});if(!this.poolPickup.isPooled(d)){if(w!==void 0)throw new t(`Device ${d.deviceId} is running but could not be added to this daemon's device pool: ${w}; call startDevice for it.`);throw new t(`Device ${d.deviceId} is running but not known to this daemon's device pool; call startDevice for it (or retry once the daemon has discovered it).`)}}async setup(c){let{request:d,flightSignal:h,snapshot:g}=c;if(g.status=void 0,(this.options.isServiceConnected??((D)=>Kr(D)?.isConnected()===!0))(d.device))return!1;let w=lo(d.device.platform,d.device.deviceId);if(pie(w))throw new t("service start declined: device readiness is in progress");let A=d.deadlineMs-this.timer.now();if(A<=0)throw new t("Observer hierarchy service start timed out before setup");let C=d.device.platform==="ios"?Math.max(A,this.options.iosFlightCeilingMs??zl):A,T=this.startFlightDeadline(d,g,C),k=h?AbortSignal.any([h,T.signal]):T.signal;try{let D=this.options.readiness??vW(this.timer);return await this.ensureReadyWithTransitions(D,{device:d.device,requestedIdentity:d.device.deviceId,operationName:"observe deviceId",totalDeadlineMs:T.totalDeadlineMs,deadline:T.deadline,readinessTimeoutMs:C,signal:k,skipCtrlProxyDownload:(this.options.skipCtrlProxyDownload??(()=>N.isSkipCtrlProxyDownloadEnabled()))(),assertCanSetup:()=>{if(k.throwIfAborted(),!this.guard.canStart(d.device))throw new tt("service start declined: ownership or pool transition changed while waiting for readiness")}}),!0}finally{T.stop(),this.clearQueueSnapshot(w,g)}}startFlightDeadline(c,d,h){let g=new AbortController,w=()=>{d.status=this.launchQueueStatus(c.device),g.abort(new t("Observer hierarchy service start timed out"))};if(c.device.platform!=="ios"){let k=this.timer.setTimeout(w,h);return{signal:g.signal,totalDeadlineMs:c.deadlineMs,deadline:void 0,stop:()=>this.timer.clearTimeout(k)}}let A=new zr(this.timer,this.timer.now()+h),C=this.followLaunchQueue(c.device,A,h),T=A.whenExpired(this.timer,w);return{signal:g.signal,totalDeadlineMs:A.deadlineMs,deadline:A,stop:()=>{T(),C()}}}followLaunchQueue(c,d,h){let g=Math.max(h,this.options.iosQueueCeilingMs??Kl),A=this.timer.now()+g+h,C=(M)=>d.set(Math.min(M,A)),T=()=>C(Math.max(d.deadlineMs,this.timer.now()+g)),k=this.options.launchQueue??JB(),D=k.watchQueue(c.deviceId,{queued:T,admitted:()=>C(this.timer.now()+h),left:()=>C(this.timer.now()+h)});if(k.queueStatus(c.deviceId))T();return D}async ensureReadyWithTransitions(c,d){let h=0;while(!0){let g=Math.max(0,Dt(d)-this.timer.now());try{await l(()=>c.ensureReady({...d,readinessTimeoutMs:Math.min(g,d.readinessTimeoutMs)}),{timer:this.timer,signal:d.signal,...d.deadline?{deadline:d.deadline}:{timeoutMs:g},label:"Observer hierarchy service start"});return}catch(w){await this.awaitSetupTransition(w,d,h),h++}}}async awaitSetupTransition(c,d,h){if(!(c instanceof tt)||!this.guard.awaitTransition||h>=os||d.signal?.aborted||this.timer.now()>=Dt(d))throw c;let g;try{g=await this.awaitTransition(d.device,Dt(d),d.signal)}catch(w){throw e.debug("[observe] Assignment transition wait ended before setup retry",w),c}if(!g||d.signal?.aborted||this.timer.now()>=Dt(d))throw c}}function Dt(c){return c.deadline?.deadlineMs??c.totalDeadlineMs}var ss=new WeakMap;function cs(c){let d=ss.get(c);if(!d)d=new as({timer:c}),ss.set(c,d);return d}var zi=15000,jl=li(100);function Xl(c,d,h){let g=d[Zo];return{...Vj(c.convertToViewHierarchyResult(d.hierarchy)),...g==="device"||g==="client-cache"?{[Zo]:g}:{},receivedAt:h.now(),fresh:!0,...d.frameContext!==void 0?{frameContext:d.frameContext}:{}}}async function ps(c,d,h){let g={},w=[new U,d.searchRaw===!0,d.signal],{timeoutMs:A}=h,C;if(d.observerMode){if(!c.requestHierarchySyncForObserver)throw new t("Observer hierarchy read is unavailable for this client");C=await c.requestHierarchySyncForObserver(...w,{timeoutMs:A,...d.displayId!==void 0&&d.displayId!==0?{diagnostics:g}:{},display:d.preserveDisplayState?{displayId:d.displayId,preserveDisplayState:!0}:d.displayId})}else C=await c.requestHierarchySync(...w,{timeoutMs:A,diagnostics:g,displayId:d.displayId});if(!C)Yl(d,h,g);return C}function Yl(c,d,h){if(c.displayId!==void 0&&c.displayId!==0&&h.runnerError?.includes("exposes no accessibility windows"))throw new pf(h.runnerError);let g=h.failureReason??(h.runnerError?`runner error: ${h.runnerError}`:void 0),w=!c.observerMode||d.owned?`Device ${d.deviceId} hierarchy service did not answer`:`Device ${d.deviceId} has no reachable hierarchy service`;throw new t(g?`${w}: ${g}`:w)}function ds(c,d,h=!1,g){let{adbFactory:w}=d,A=d.androidClients??E;if(c.platform==="ios")return h?x.createForObservationRead(c):x.getInstance(c);return h?A.createForObservationRead(c,w,g instanceof E?g:void 0):A.getInstance(c,w)}function Jl(c,d,h){if(d.syncClientFactory)return{syncClient:d.syncClientFactory(c),transient:!1,owned:!1};let g=Kr(c);if(!h)return{syncClient:g??ds(c,d),transient:!1,owned:!1};let w=R.devicePool(),A=w?!!O(w.getDevice(c.deviceId)):!1;if(A&&!g?.isConnected())throw new t(`Device ${c.deviceId} is session-owned and has no connected hierarchy service: the owning session's hierarchy client is disconnected. Run a session observe as the owner to reconnect it; a deviceId read only connects to an already-running service.`);if(g?.isConnected())return{syncClient:g,transient:!1,owned:A};return{syncClient:ds(c,d,!0,g),transient:!0,owned:!1}}function ms(c){let{device:d,dependencies:h,observerMode:g}=c;if(g&&h.observationClientResolver)return h.observationClientResolver(d);return Jl(d,h,g)}async function ls(c){let{connection:d,request:h,timer:g,deadline:w,device:A}=c;return await l(()=>d.syncClient.connectForObservationRead?.()??Promise.resolve(!1),{timer:g,timeoutMs:Math.max(0,w-g.now()),signal:h.signal,label:`Observer hierarchy connection for ${A.deviceId}`})}async function Ql(c){let{connection:d,request:h,timer:g,deadline:w,device:A,dependencies:C}=c;if(!d.transient||await ls(c))return!1;await d.syncClient.close?.(),d.transient=!1;let T;try{T=await(C.observationServiceStart??cs(g)).start({device:A,deadlineMs:w,signal:h.signal})}catch(k){throw h.signal?.throwIfAborted(),new t(`Device ${A.deviceId} has no reachable hierarchy service; read tried to start the service: ${r(k)}`,{cause:k})}if(Object.assign(d,ms({device:A,dependencies:C,observerMode:!0})),d.transient&&!await ls(c))throw new t(`Device ${A.deviceId} has no reachable hierarchy service; read started the service but could not connect`);return T}function us(c,d,h){let g=c.convertToViewHierarchyResult(d.hierarchy),w=d.hierarchy?.updatedAt;if(typeof w==="number"&&Number.isFinite(w))g.updatedAt=w;if(g.receivedAt=h.now(),g.fresh=!0,d.frameContext!==void 0)g.frameContext=d.frameContext;return g}async function Zl(c){let{device:d,dependencies:h,syncClient:g,deadline:w,request:A,timer:C,owned:T}=c,k=c.synced;if(d.platform==="ios")return Xl(g,k,C);let D=us(g,k,C);if(A.observerMode||!WO(D)||C.now()>=w)return D;let M=jl.delayForAttempt(1);if(w-C.now()>M)try{k=await l(async()=>{await C.sleep(M),A.signal?.throwIfAborted();let _=w-C.now();if(_<=0)throw new t(`Device ${d.deviceId} hierarchy retry deadline exhausted`);return ps(g,A,{timeoutMs:_,deviceId:d.deviceId,owned:T})},{timer:C,timeoutMs:w-C.now(),signal:A.signal,label:`Device ${d.deviceId} incomplete hierarchy retry`}),D=us(g,k,C)}catch(_){A.signal?.throwIfAborted(),e.warn("[HierarchyCapture] Incomplete CtrlProxy hierarchy retry failed",_)}if(!WO(D)||C.now()>=w)return D;let F=await yW(D,{adb:(h.adbFactory??v).create(d),timer:C,idGenerator:h.ids,deviceId:d.deviceId},w,A.signal);return Hie(F,D.updatedAt),F}function eu(c,{device:d,request:h,owned:g}){let w=h.displayId;return!(h.observerMode&&g)&&d.platform==="android"&&w!==void 0&&w!==0&&c instanceof pf&&c.message.includes(`Display ${w} exposes no accessibility windows`)?w:void 0}async function tu(c,d){try{return await Zl({...d,synced:await c()})}catch(h){let{device:g,dependencies:w,request:A,timer:C,deadline:T}=d;A.signal?.throwIfAborted();let k=eu(h,d);if(k===void 0)throw h;try{return await is(k,{adb:(w.adbFactory??v).create(g),timer:C,idGenerator:w.ids,deviceId:g.deviceId},T,A.signal)}catch(D){if(A.signal?.throwIfAborted(),D instanceof We)throw D;throw e.warn("[HierarchyCapture] Untracked-display UIAutomator fallback failed",D),h}}}function vn(c,d={}){if(c.platform==="watchos"||c.platform==="tvos"||c.platform==="visionos"){let w=async(A)=>c.platform==="visionos"?TT(await kT(c.deviceId,A.signal,async()=>(await Rv(c.deviceId,A.signal)).hierarchy(A.signal,A.timeoutMs===void 0?void 0:{timeoutMs:A.timeoutMs}))):c.platform==="tvos"?_m(await(await oa(c.deviceId,A.signal)).hierarchy(A.signal)):Pv(await Po.require(c.deviceId).hierarchy(A.signal));return new Wg("ios",{readCached:w,readFresh:w,projectVisible:(A)=>A},d.timer,d.ids)}let h=te(c.platform,"Observing the view hierarchy"),g=new qr({getViewHierarchy:(w,A)=>(d.viewHierarchy??new Xi(c,d.adbFactory,null,{timer:d.timer})).getViewHierarchy(w,A),filterOffscreenNodes:dO},async(w)=>{let A=d.timer??i,C=w.timeoutMs??zi,T=A.now()+C;w.signal?.throwIfAborted();let k=ms({device:c,dependencies:d,observerMode:w.observerMode===!0});try{let D=await Ql({device:c,dependencies:d,connection:k,request:w,timer:A,deadline:T}),{syncClient:M,owned:F}=k,_=T-A.now();if(_<=0)throw new t(`Device ${c.deviceId} hierarchy read timed out`);let V=()=>ps(M,w,{timeoutMs:_,deviceId:c.deviceId,owned:F}),W=await tu(()=>w.observerMode?l(V,{timer:A,timeoutMs:_,signal:w.signal,label:`Device ${c.deviceId} hierarchy read`}):V(),{device:c,dependencies:d,syncClient:M,deadline:T,timer:A,request:w,owned:F});if(!w.observerMode)return W;let G={...W};if(delete G.hierarchyServiceStarted,D)G.hierarchyServiceStarted=!0;return G}finally{if(k.transient)await k.syncClient.close?.()}},(w)=>Vg(h,w,h==="ios"&&(c.displays?.panels.length??0)>1),d.settle);return new Wg(h,g,d.timer,d.ids)}var ru=[{kind:"runner-error",transient:!1,pattern:/runner error:/},{kind:"screen-off",transient:!1,pattern:/Screen is off while waiting for hierarchy response/},{kind:"capture-error",transient:!1,pattern:/Unable to capture hierarchy/},{kind:"timestamp-floor",transient:!1,pattern:/Hierarchy capture did not satisfy the device timestamp floor/},{kind:"connect-failed",transient:!0,pattern:/Failed to establish CtrlProxy WebSocket connection/},{kind:"socket-unavailable",transient:!0,pattern:/Unable to request hierarchy for Android display \d+: CtrlProxy WebSocket is unavailable/},{kind:"send-failed",transient:!0,pattern:/Unable to request hierarchy for Android display \d+: /},{kind:"socket-closed-before-wait",transient:!0,pattern:/CtrlProxy WebSocket closed or changed before hierarchy wait/},{kind:"socket-changed",transient:!0,pattern:/CtrlProxy WebSocket changed while waiting for hierarchy response/},{kind:"socket-disconnected",transient:!0,pattern:/CtrlProxy WebSocket disconnected while waiting for hierarchy response/},{kind:"timeout",transient:!0,pattern:/Timed out waiting for hierarchy response after \d+ms/},{kind:"timeout",transient:!0,pattern:/Device .+ hierarchy read timed out$/},{kind:"no-answer",transient:!0,pattern:/Hierarchy service did not answer the sync request$/},{kind:"no-answer",transient:!0,pattern:/[Hh]ierarchy service did not answer$/}];function hs(c,d){if(d.signal?.aborted)return{kind:"aborted",transient:!1};let h=r(c),g=ru.find(({pattern:w})=>w.test(h));return g?{kind:g.kind,transient:g.transient}:{kind:"unknown",transient:!1}}class Xr extends Kn{kind;attempts;transient=!0;constructor(c,d){super(`${c} (after ${d.attempts} attempts)`,{cause:d.cause});this.name="SelectedDisplayReadError",this.kind=d.kind,this.attempts=d.attempts}}var iu=Q({initialDelayMs:200,multiplier:2,maxDelayMs:1000});function nu(c,d){return c.transient&&!d?.aborted}async function fs(c){let{timer:d,signal:h}=c,g=c.backoff??iu,w=c.maxAttempts??4,A=d.now()+c.budgetMs,C=0;while(!0){h?.throwIfAborted(),C++;try{return await c.read({number:C,timeoutMs:C===1?c.timeoutMs:A-d.now()})}catch(T){let k=c.classify(T),D={...k,attempts:C,exhausted:!1};if(!nu(k,h))throw c.wrap(T,D);let M=g.delayForAttempt(C),F=()=>c.wrap(T,{...D,exhausted:!0});if(C>=w||A-d.now()<=M)throw F();if(e.warn(`[SelectedDisplayRead] Retrying ${k.kind}; attempt ${C+1}`,T),await l(()=>d.sleep(M),{timer:d,signal:h,label:"Selected display read backoff"}),h?.throwIfAborted(),c.assertFenceCurrent(),A-d.now()<=0)throw F()}}}class it extends t{constructor(c,d){super(u(c,`Failed to capture screenshot for device ${d}`).message,{cause:c})}}async function ys(c,d){let{request:h,panelKey:g,captureStart:w}=d;return(await fs({...c.selectedDisplayRead,timer:c.timer,budgetMs:h.timeoutMs??zi,timeoutMs:h.timeoutMs,signal:h.signal,read:(C)=>c.hierarchyCapture.capture(C.number===1?h:{...h,timeoutMs:C.timeoutMs}),classify:(C)=>hs(C,{signal:h.signal}),assertFenceCurrent:()=>{let C=c.deviceId;if(Ce.revision(C)!==w.revision)throw df(w.identityRevision,Ce.identityRevision(C),Ce.currentObservedPanel(C)?.key)},wrap:(C,T)=>{let k=`Unable to read selected display "${g}": ${String(C)}`;return T.exhausted?new Xr(k,{cause:C,kind:T.kind,attempts:T.attempts}):new Kn(k,{cause:C})}})).hierarchy}function vs(c,d,h){if(d instanceof it||d instanceof Tl||d instanceof Kn)return!0;if(!(c==="android"&&h.display!==void 0&&h.display!=="active"))return!1;return d instanceof pf||d instanceof Ee||h.signal?.aborted===!0&&d===h.signal.reason}async function gs(c,d){try{return(await c.capture(d)).hierarchy}catch(h){if(d.signal?.aborted||h instanceof pf)throw h;let g=noe(h),w=g?.message??r(h);return e.warn(`[ObserveScreen] Observer hierarchy unavailable: ${w}`,h),{hierarchy:{error:"Hierarchy service unavailable",unavailableReason:g?"runner_launch_queued":h instanceof Eg?"request_timed_out":"connection_lost",unavailableDetail:w},fresh:!1}}}class Yr{d;constructor(c){this.d=c}captureSingleDisplayData(c){let{result:d,options:h,queryOptions:g,perf:w,skipWaitForFresh:A,minTimestamp:C,signal:T,skipBackStack:k,observerMode:D,preserveDisplayState:M,capturedHierarchy:F,requestedDisplayId:_,observedAndroid:V}=c;return this.d.collectAllData(d,{queryOptions:g,perf:w,skipWaitForFresh:A,minTimestamp:C,signal:T,skipBackStack:k,readOnly:D||M||h?.skipRecompositionTracking===!0,capturedHierarchy:F,readOptions:this.d.device().platform==="android"&&h?.requireFreshExtraction?{timeoutMs:h.timeoutMs,requireFreshExtraction:h.requireFreshExtraction}:h?.timeoutMs,displayId:_??V?.logicalId??0})}resolveSingleDisplayIntent(c){let d=po(c);return{...d,options:c,androidDisplayCache:this.selectAndroidDisplayCache(d.observerMode||d.preserveDisplayState),displayRequest:c?.display??this.defaultDisplayRequest(),perf:c?.perf??new U,iosLockState:this.startIosLockStateProbe(d.signal)}}selectAndroidDisplayCache(c){return c?new hr(this.d.timer(),!0):this.d.observedAndroidDisplayCache()}defaultDisplayRequest(){return this.d.requestedDisplay()==="all"?void 0:this.d.requestedDisplay()}startIosLockStateProbe(c){return this.d.device().platform==="ios"&&z({deviceId:this.d.device().deviceId})==="simulator"?this.d.iosLockStateProbe().read(this.d.device().deviceId,c):void 0}async beginSingleDisplay(c){let{perf:d,skipWaitForFresh:h,minTimestamp:g,signal:w,preserveDisplayState:A}=c;e.debug(`Executing observe command (skipWaitForFresh=${h}, minTimestamp=${g})`);let C=this.d.timer().now();o(w);let T=this.d.createBaseResult(),k={revision:Ce.revision(this.d.device().deviceId),identityRevision:Ce.identityRevision(this.d.device().deviceId)},D=this.d.displayBinding().resolveTarget({result:T,displayRequest:c.displayRequest,androidDisplayCache:c.androidDisplayCache,signal:w}),M=D instanceof Promise?await D:D,{explicitlyRouted:F,requestedDisplayId:_}=M,V=A&&F&&_!==void 0&&_!==0,W=uo().currentGeneration(this.d.device().deviceId);return d.serial("observe"),{...c,...M,result:T,startTime:C,captureStart:k,routedAggregateSecondary:V,cacheGeneration:W}}async failSingleDisplay(c,d){let{preserveDisplayState:h,observerMode:g,displayRequest:w,signal:A,iosLockState:C}=d;if(h){if(A?.throwIfAborted(),!g&&(w===void 0||w==="active"))return e.error("Critical error in aggregate active observation:",c),this.d.createCriticalFallback(c)}if(g||h)throw u(c,`Unable to observe device ${this.d.device().deviceId}`);if(vs(this.d.device().platform,c,{display:w,signal:A}))throw Nk(c);let T=c instanceof Error?c.stack||c.message:String(c);e.error(`Critical error in observe command: ${T}`),Pe.cancelJob(this.d.device().deviceId),Jr().update(this.d.device().deviceId,void 0,`Observation failed: ${T}`);let k=this.d.createBaseResult();if(C)Rt(k,await C);return this.d.createCriticalFallback(c,{fallback:k})}async captureSingleDisplay(c){let{options:d,result:h,perf:g,queryOptions:w,skipWaitForFresh:A,minTimestamp:C,signal:T}=c,k=this.startForegroundProbe(c),D=k.then((F)=>F?.packageName),M=await this.captureRequestedHierarchy(c);if(d?.hierarchyOnly)return await this.d.hierarchyCollector().collect(h,{queryOptions:w,perf:g,skipWaitForFresh:A,minTimestamp:C,signal:T,readOnly:!0,capturedHierarchy:M,readOptions:d.timeoutMs}),o(T),g.end(),{earlyResult:h,foregroundSnapshot:k,foregroundIdentity:D};return await this.captureSingleDisplayData({result:h,options:d,queryOptions:w,perf:g,skipWaitForFresh:A,minTimestamp:C,signal:T,skipBackStack:c.skipBackStack,observerMode:c.observerMode,preserveDisplayState:c.preserveDisplayState,capturedHierarchy:M,requestedDisplayId:c.requestedDisplayId,observedAndroid:c.observedAndroid}),{earlyResult:void 0,foregroundSnapshot:k,foregroundIdentity:D}}startForegroundProbe(c){let{options:d,signal:h,observerMode:g,routedAggregateSecondary:w,requestedDisplayId:A}=c;return!d?.hierarchyOnly&&this.d.device().platform==="android"&&(!g||w)?this.d.deviceStateCollector().collectForegroundSnapshot(h,{displayId:A}):Promise.resolve(null)}buildHierarchyCaptureRequest(c){let{options:d,observerMode:h,preserveDisplayState:g,minTimestamp:w,signal:A}=c;return{freshness:c.requestedDisplayId!==void 0&&d?.freshness==="cached-ok"?"fresh":d?.freshness??"fresh",observerMode:h,...g?{preserveDisplayState:!0}:{},minTimestamp:w>0?w:void 0,signal:A,timeoutMs:d?.timeoutMs,displayId:c.requestedDisplayId}}async captureRequestedHierarchy(c){let{options:d,observerMode:h,requestedDisplayId:g,requestedPanel:w,captureStart:A}=c,C=this.buildHierarchyCaptureRequest(c);if(h)return await gs(this.d.hierarchyCapture(),C);if(g!==void 0)return await ys({selectedDisplayRead:this.d.selectedDisplayRead(),timer:this.d.timer(),hierarchyCapture:this.d.hierarchyCapture(),deviceId:this.d.device().deviceId},{request:C,panelKey:w?.key,captureStart:A});if((d?.freshness||d?.hierarchyOnly)&&!(this.d.device().platform==="android"&&d.requireFreshExtraction))try{return(await this.d.hierarchyCapture().capture(C)).hierarchy}catch(T){e.warn(`[ObserveScreen] Freshness capture failed; collecting hierarchy: ${T}`)}return}}function ou(c){if(c.screenScale!==void 0)return!0;let d=c.hierarchy;if(d.type==="XCUIElementTypeApplication")return!0;if(d.elementType==="application")return!0;if(typeof d.bundleId==="string"&&!c.hierarchy.node)return!0;return!1}function su(c){if(c.density!==void 0)return!0;if(c.sdkInt!==void 0)return!0;if(c.foregroundActivity!==void 0)return!0;let d=c.hierarchy.node,h=d&&we(d).class;if(typeof h==="string"&&h.startsWith("android."))return!0;return!1}class Qr{validate(c,d){let h=ou(d),g=su(d);if(c==="android"&&h&&!g)return{valid:!1,error:"Platform mismatch detected: received iOS hierarchy for Android device. This may indicate a stale connection. Try calling observe again."};if(c==="ios"&&g&&!h)return{valid:!1,error:"Platform mismatch detected: received Android hierarchy for iOS device. This may indicate a stale connection. Try calling observe again."};return{valid:!0}}}function au(c){c.updatedAt=0,c.viewHierarchy=void 0,c.elements=void 0,c.selectedElements=void 0,c.focusedElement=void 0,c.accessibilityFocusedElement=void 0,c.intentChooserDetected=void 0,c.notificationPermissionDetected=void 0,c.predictions=void 0,c.activeWindow=void 0,c.screenIdentity=void 0,c.screenSize={width:0,height:0},c.systemInsets={top:0,right:0,bottom:0,left:0},c.insets={available:!1,source:"unavailable",units:"unknown"},c.layoutWarnings=void 0,c.rotation=void 0,c.wakefulness=void 0}function bs(c,d,h,g){if(!c.viewHierarchy?.hierarchy)return!0;let w=g.validate(d,c.viewHierarchy);if(w.valid)return!0;return e.error(`[observe] Platform mismatch: device ${h} is ${d} but received hierarchy from other platform. Discarding stale data to prevent cross-platform contamination.`),au(c),c.error=w.error,!1}var cu="androidx.car.app.activity.CarAppActivity",Ss="com.google.android.apps.automotive.templates.host",kL=`${Ss}:id/`;function du(c){return c["resource-id"]??c.$?.["resource-id"]}function lu(c){let d=[...zg(c)];for(let h=d.pop();h;h=d.pop()){let g=du(h);if(typeof g==="string"&&g.startsWith(kL))return!0;d.push(...Ra(h))}return!1}function EL(c){if(lu(c.viewHierarchy?.hierarchy?.node))return{kind:"carAppLibrary",hostPackage:Ss};return c.activeWindow?.activityName===cu?{kind:"carAppLibrary"}:void 0}function ws(c){let d=c.automotive;if(!d)return;let h=EL(c);if(h)d.hostRenderedUi=h;else delete d.hostRenderedUi}class Zr{d;constructor(c){this.d=c}async reconcileSingleDisplay(c,d){let{result:h,signal:g}=c,w=Rs(h),A=await d.foregroundSnapshot,C,T=()=>(C??=this.d.isConfirmedFrameworkErrorDialog(h.viewHierarchy,g),C);if(await this.recoverInitialWindowMismatch(c,d,T))C=void 0;this.adoptSampledPrimaryActivity(c,A),this.attributeRoutedAggregateSecondary(c,A);let D=bs(h,te(this.d.device().platform,"Observing the view hierarchy"),this.d.device().deviceId,this.d.platformValidator()),M=await this.resolvePostCaptureForeground(c);if(await this.verifyCachedHierarchyIfRequested(c,M),h.automotive&&Rs(h)!==w)await this.d.deviceStateCollector().refreshAutomotiveForegroundActivity(h,g);else ws(h);let F=await this.bindFinalSingleDisplay(c);return this.attachOtherDisplays(h),{sampledForeground:A,postCaptureForeground:M,hierarchyPlatformValid:D,getConfirmedFrameworkErrorDialog:T,recordProvenance:F}}async recoverInitialWindowMismatch(c,d,h){let{options:g,result:w,startTime:A,minTimestamp:C,signal:T,skipBackStack:k}=c;if(!this.shouldRecoverWrongWindow(c))return!1;let D=await this.d.windowIdentity().resolveWindowIdentityMismatch(w,d.foregroundIdentity,{postCaptureForeground:{sampled:!1,identity:void 0,activityAttributionMismatch:!1},getConfirmedFrameworkErrorDialog:h,minTimestamp:C,signal:T}),M=Math.min(500,(g?.timeoutMs??zi)-(this.d.timer().now()-A));if(!D||M<=0)return!1;return await this.d.staleRecovery().refreshKnownStaleHierarchy(w,D.foreground,g,{remainingMs:M,sideSamples:{skipBackStack:k,displayId:c.requestedDisplayId??c.observedAndroid?.logicalId??0}}),!0}shouldRecoverWrongWindow(c){let{options:d,observerMode:h,preserveDisplayState:g,explicitlyRouted:w}=c;return this.d.device().platform==="android"&&!h&&!g&&!w&&!d?.skipRecompositionTracking&&!d?.requireFreshExtraction&&!d?.skipStaleWindowRecovery}adoptSampledPrimaryActivity(c,d){let{result:h}=c;if(d===null||!ao(c,d))return;if(d.packageName===h.viewHierarchy?.packageName&&d.activityName&&h.activeWindow)h.activeWindow={...h.activeWindow,appId:d.packageName,activityName:d.activityName}}attributeRoutedAggregateSecondary(c,d){if(!c.routedAggregateSecondary)return;let{result:h}=c,g=d?.packageName??h.viewHierarchy?.packageName;h.activeWindow=g?{appId:g,activityName:d?.activityName??"",layoutSeqSum:0}:void 0}async resolvePostCaptureForeground(c){let{result:d,signal:h,observerMode:g,preserveDisplayState:w,explicitlyRouted:A}=c;if(A)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1,displayId:c.requestedDisplayId};if(g)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};return await this.d.reconcileActiveWindowAttribution(d,{signal:h,readOnly:w})}async verifyCachedHierarchyIfRequested(c,d){let{options:h,result:g,signal:w,startTime:A,skipBackStack:C}=c;if(!h?.verifyCachedHierarchy||d.activityAttributionMismatch)return;await this.d.staleRecovery().verifyCachedAndroidHierarchy(g,{signal:w,remainingMs:Math.min(500,(h.timeoutMs??zi)-(this.d.timer().now()-A)),eligible:!c.observerMode&&!c.preserveDisplayState&&!c.explicitlyRouted,sideSamples:{skipBackStack:C,displayId:c.requestedDisplayId??c.observedAndroid?.logicalId??0}})}async bindFinalSingleDisplay(c){let d=this.d.displayBinding().bindFinalDisplay({result:c.result,displayRequest:c.displayRequest,androidDisplayCache:c.androidDisplayCache,observedAndroid:c.observedAndroid,requestedPanel:c.requestedPanel,requestedDisplayId:c.requestedDisplayId,explicitlyRouted:c.explicitlyRouted,preserveDisplayState:c.preserveDisplayState,observerMode:c.observerMode,recordProvenance:c.captureStart,signal:c.signal});return(d instanceof Promise?await d:d).recordProvenance}attachOtherDisplays(c){let d=this.d.device().displays?.panels;if(d&&d.length>1)c.otherDisplays=d.filter((h)=>h.key!==c.display.key).map((h)=>uu(h))}}function uu(c){if(c.scale&&c.scale>0)return{key:c.key,role:c.role,size:{width:Math.round(c.sizePx.width/c.scale),height:Math.round(c.sizePx.height/c.scale)},units:"points"};return{key:c.key,role:c.role,size:c.sizePx,units:"physical-pixels"}}function Rs(c){return`${c.activeWindow?.appId??""}/${c.activeWindow?.activityName??""}`}import{AsyncLocalStorage as pu}from"async_hooks";var ti=new pu;function Cm(c){return ti.run(new WeakSet,c)}function As(c){if(c.viewHierarchy)ti.getStore()?.add(c.viewHierarchy);return c}function Dm(c){return ti.getStore()?.has(c)??!1}function Cs(c){return c?.[Zo]==="device"}var mu=5000,yu=1000,vu=30000;function Ts(){return Be(f.OBSERVE_PERF_SNAPSHOT)}function Is(){let c=Hu(f.OBSERVE_PERF_WINDOW_MS);if(c===void 0)return mu;return Math.min(vu,Math.max(yu,Math.round(c)))}async function ks(c,d,h){if(!Ts())return;let g=c.activeWindow?.appId;if(!g){e.debug("[PerfSnapshot] Skipping snapshot, no active app");return}let w=d.platform;if(!cr(w)){e.debug(`[PerfSnapshot] Skipping snapshot, no perf sampling on ${w}`);return}try{let{getPerformanceMonitor:A,getLastStartupTimingMs:C}=await import("./chunk-q9xmq595.js");A().requestPerfWindow(d.deviceId,g,w);let k=nj().snapshot(d.deviceId,h.now(),Is());k.startup=C(d.deviceId,g),c.perfSnapshot=k}catch(A){e.warn(`[PerfSnapshot] Failed to attach performance snapshot: ${A}`)}}var Ot="androidx.wear.tiles.action.BIND_TILE_PROVIDER";class ri extends t{component;available;reason="providerNotFound";constructor(c,d){super(`'${c}' is not a Wear tile provider on this device. `+(d.length>0?`Use one of: ${d.join(", ")}.`:`No tile providers are installed; install an app that declares a service for ${Ot}.`));this.component=c;this.available=d}}var bu=1e4,Su=/^([A-Za-z0-9_.]+)\/([\p{L}\p{N}\p{M}\p{Pc}\p{Sc}.]+)$/u;function xs(c){let d=new Set;return c.split(/\r?\n/).map((h)=>Su.exec(h.trim())).filter((h)=>h!==null).map(([,h,g])=>{let w=g.startsWith(".")?`${h}${g}`:g;return{component:`${h}/${w}`,packageName:h,className:w}}).filter((h)=>{if(d.has(h.component))return!1;return d.add(h.component),!0})}function Au(c){let d=xs(c);return d.length===1?d[0].component:c.trim()}class h3{adb;constructor(c){this.adb=c}async list(c){try{c?.throwIfAborted();let d=await this.adb.executeCommand(`shell cmd package query-services --components -a ${Ot}`,{timeoutMs:bu,signal:c});return xs(d.stdout)}catch(d){throw u(d,"Failed to list Wear tile providers")}}}async function Ds(c,d,h){let g=Au(d),w=await c.list(h),A=w.find((C)=>C.component===g);if(!A)throw new ri(d,w.map((C)=>C.component));return A}var bW="com.google.android.wearable.app.DEBUG_SURFACE",Pu="com.google.android.wearable.app.DEBUG_SYSUI",Me="com.google.android.clockwork.sysui",Tu=3000,Iu=1e4,Ote=["addTile","showTile","removeTile","listTileProviders"],g3=/^[A-Za-z][\w.]*\/\.?[A-Za-z_][\w.]*$/,Mte=["added","removed","showRequested","providerNotFound","missingComponent","indexRequired","unrecognizedOperation","unknown"],ku=/^Broadcast completed: result=(-?\d+)(?:, data="(.*)")?\s*$/m,Du=/^Index=\[(\d+)\]$/,Ou=/^Unrecognized operation (.+)$/;function y3(c){let d=ku.exec(c.replace(/\r\n/g,`
|
|
10
|
-
`));if(!d)return{code:null};return{code:Number(d[1]),...d[2]!==void 0?{data:d[2]}:{}}}function ii(c,d){let{data:h}=d,g=h===void 0?null:Ou.exec(h);if(g)return{...d,outcome:"unrecognizedOperation",operation:g[1]};let w=Mu.find((A)=>h!==void 0&&A.matches(h));if(w)return{...d,outcome:w.outcome};return d.code===1?{...d,...Fu[c](h)}:Eu(d)}function Eu(c){return{...c,outcome:"unknown"}}var Mu=[{outcome:"missingComponent",matches:(c)=>c==="A component name is required."},{outcome:"indexRequired",matches:(c)=>c==="An index is required."},{outcome:"providerNotFound",matches:(c)=>c.includes("Requested tile provider does not exist")}],Fu={"add-tile":(c)=>{let d=c===void 0?null:Du.exec(c);return d?{outcome:"added",index:Number(d[1])}:{outcome:"unknown"}},"remove-tile":(c)=>({outcome:c==="Tile(s) removed."?"removed":"unknown"}),"show-tile":(c)=>({outcome:c===void 0?"showRequested":"unknown"})},_u={providerNotFound:"The tile provider does not exist on this watch. Check the component (package/service of a service handling androidx.wear.tiles.action.BIND_TILE_PROVIDER).",missingComponent:"The broadcast was sent without a component name.",indexRequired:"The broadcast was sent without a tile index.",unrecognizedOperation:"This Wear OS build does not recognize the operation; its debug surface broadcasts may differ from the verified Wear OS 7 emulator."};function Et(c){return _u[c.outcome]??(c.code===null?"The broadcast printed no result; the debug receiver may be missing on this build.":`Unexpected broadcast reply result=${c.code}${c.data!==void 0?`, data="${c.data}"`:""}.`)}class v3{deps;constructor(c){this.deps=c}async listTileProviders(c){let d=await this.deps.tileProviders.list(c);return{success:!0,action:"listTileProviders",requested:{},providers:d,verified:!1,message:d.length>0?`${d.length} tile provider(s); pass one as component to addTile, showTile or removeTile.`:"No tile providers are installed on this watch."}}async addTile(c,d){let h=await this.addTileBroadcast(c,d),g=h.outcome==="added";return{success:g,action:"addTile",requested:{component:c},broadcastResult:h,...h.index!==void 0?{index:h.index}:{},verified:!1,message:g?`The tile is in the carousel at index ${h.index} (add-tile is idempotent: it may already have been there). Not observed; use showTile to confirm it renders.`:"The tile was not added.",...g?{}:{reason:Et(h)}}}async removeTile(c,d){let h=ii("remove-tile",await this.broadcast(bW,"remove-tile",`--ecn component ${c}`,d)),g=h.outcome==="removed";return{success:g,action:"removeTile",requested:{component:c},broadcastResult:h,verified:!1,message:g?"The tile was removed or was not present; the broadcast does not say which. Not observed.":"The tile was not removed.",...g?{}:{reason:Et(h)}}}async showTile(c,d){let h="component"in c?{component:c.component}:{index:c.index},g,w;if("component"in c){if(g=await this.addTileBroadcast(c.component,d),g.outcome!=="added"||g.index===void 0)return{success:!1,action:"showTile",requested:h,broadcastResult:g,indexResolution:g,verified:!1,message:"The tile index could not be resolved, so nothing was shown.",reason:Et(g)};w=g.index}else w=c.index;let A=ii("show-tile",await this.broadcast(Pu,"show-tile",`--ei index ${w}`,d)),C={action:"showTile",requested:h,broadcastResult:A,...g?{indexResolution:g}:{},index:w};if(A.outcome!=="showRequested")return{...C,success:!1,verified:!1,message:"The tile was not shown.",reason:Et(A)};await this.deps.timer.sleep(Tu),d?.throwIfAborted();let T=await this.deps.observe(d),k=Nu(T);return{...C,success:k===void 0,verified:k===void 0,message:k===void 0?`The show-tile broadcast was accepted for index ${w}; an observe confirmed a tile container in the foreground Wear system UI (tile identity is not verified).`:`The show-tile broadcast was accepted for index ${w}, but the observe did not confirm a tile.`,...k!==void 0?{reason:k}:{}}}async addTileBroadcast(c,d){return await Ds(this.deps.tileProviders,c,d),ii("add-tile",await this.broadcast(bW,"add-tile",`--ecn component ${c}`,d))}async broadcast(c,d,h,g){let w=`shell am broadcast -a ${c} --es operation ${d} ${h}`;try{g?.throwIfAborted();let A=await this.deps.adb.executeCommand(w,{timeoutMs:Iu,noRetry:!0,signal:g});return y3(A.stdout)}catch(A){throw u(A,`Failed to run adb ${w}`)}}}function Nu(c){if(c.appId!==Me)return`The foreground after the broadcast is ${c.appId??"unknown"}, not the Wear system UI (${Me}).`;if(c.tileShowing!==!0)return"The observed hierarchy did not contain the tile container: the index may be out of range or the hierarchy could not be read (is CtrlProxy enabled?).";return}function Os(c){let{activeWindow:d,viewHierarchy:h}=c;if(!d?.appId||!h)return;if(d.appId!==Me)return"app";if(d.activityName?.startsWith(`${Me}.experiences.globallauncher.`))return"launcher";if(d.activityName!==`${Me}.mainui.activity.SysUiActivity`)return;let g=new Us,w=!1,A=!1;for(let C of g.extractRootNodes(h))g.traverseNode(C,(T)=>{let k=we(T)["resource-id"];w||=k===`${Me}:id/carousel_tile_container`,A||=k==="watch_face_fallthrough"||k===`${Me}:id/watchface_overlay`});return w?"tile":A?"watchface":void 0}class oi{d;constructor(c){this.d=c}enrichSingleDisplayElements(c){let{result:d}=c;if(this.d.stampScreenSizeUnits(d),d.layoutWarnings={scope:"full",warnings:this.d.safeAreaAuditor().inspect(d)},d.viewHierarchy){let h=this.d.device(),g=h.platform==="android"&&(this.d.isAndroidXr?.()??!1);d.elements=this.d.elementsBuilder().build(d.viewHierarchy,te(h.platform,"Observing the view hierarchy"),g,d)}}async enrichSingleDisplay(c){if(this.enrichSingleDisplayElements({result:c.result}),this.d.device().formFactor==="watch"){let d=Os(c.result);if(d!==void 0)c.result.surface=d}await this.attachScreenRound(c),await this.startSingleDisplayScreenshot(c),await this.runSingleDisplayAudits(c)}async attachScreenRound(c){if(this.d.device().formFactor!=="watch")return;let d=await this.d.screenRound().isScreenRound(c.signal);if(d!==void 0)c.result.isScreenRound=d}async startSingleDisplayScreenshot(c){let{options:d,result:h,perf:g,signal:w,screenshotMode:A,requestedDisplayId:C}=c;if(A==="none"){h.screenshotCaptureAttempted=!1;return}let T=C,k=si(d?.screenshotOptions);if(h.screenshotCaptureAttempted=!0,ai(h,k),A==="settled")h.screenshotOrientation=this.d.platformTraits().settledScreenshotOrientation(),await this.d.captureSettledScreenshot(h,g,w,{strict:d?.screenshot==="settled",displayId:T,screenshotOptions:d?.screenshotOptions});else if(N.getAccessibilityAuditConfig())await this.d.screenshotRecorder().capture(h.observationId,{perf:g,signal:w,displayId:T,capture:k});else this.d.screenshotRecorder().start(h.observationId,{perf:g,signal:w,displayId:T,capture:k})}async runSingleDisplayAudits(c){let{options:d,result:h,perf:g,signal:w,observerMode:A}=c;if(!d?.skipRecompositionTracking&&!A)await this.d.processRecomposition(h,g);if(!d?.skipPerformanceAudit&&!A)await this.d.performanceAuditor().run(h,g);if(!d?.skipAccessibilityAudit&&!A)await this.d.accessibilityAuditor().run(h,g);if(!A)await this.d.accessibilityStateDetector().run(h,g,w);if(!A)await this.attachPredictionsIfEnabled(h)}async attachPredictionsIfEnabled(c){if(!N.isPredictiveUiEnabled())return;try{let d=await this.d.predictiveUIState().generate(c,this.d.device());this.attachPredictions(c,d)}catch(d){e.warn(`[PredictiveUIState] Failed to generate predictions: ${d}`)}}async publishSingleDisplay(c){let{result:d,perf:h,startTime:g,skipBackStack:w,observerMode:A}=c;if(h.end(),!A)await ks(d,this.d.device(),this.d.timer());if(yo(d,h),d.screenshotPath)d.screenshotExpiresAt=await this.d.pathProtection().protect(d.screenshotPath);if(this.d.device().platform==="android"&&!A&&w)this.d.deferredBackStackDisplays().set(d,c.requestedDisplayId??c.observedAndroid?.logicalId??0);return e.debug("Observe command completed"),e.debug(`Total observe command execution took ${this.d.timer().now()-g}ms`),this.d.platformTraits().grantsObservationRead(d)?As(d):d}attachPredictions(c,d){if(d)c.predictions=d}}function si(c){return c?.hidePrototypes===!0?{hidePrototypes:!0}:void 0}function ai(c,d){if(d)c.screenshotIncludesPrototype=!1;else delete c.screenshotIncludesPrototype}function ne(c,d){if(!c.errors){if(c.errors=[],c.error)c.errors.push({phase:"critical",message:c.error})}c.errors.push(d),c.error=c.errors.map((h)=>h.message).join("; ")}function bc(c,d){let h=Number.isInteger(c)&&c>=0&&c<=3;if(!d)return h?c:void 0;let g=[d.width,d.height].every((C)=>Number.isFinite(C)&&C>0),w=d.width<d.height;if(h&&!(g&&w&&(c===1||c===3)))return c;return g?w?0:1:void 0}var ue=new Set(["com.android.systemui"]),_s="com.android.systemui",Bu=3;function Es(c){return c.packageName===_s||c.type===Bu}function Lu(c,d){let h=c.bounds;if(!h)return!1;let g=h.bottom-h.top;if(d&&d>0)return g>d/2;return g>400}function Fs(c){let d=c?.windows;if(!d||d.length===0)return"none";let h=d.find((w)=>w.isFocused===!0);if(h)return Es(h)?"focused":"none";let g=d.reduce((w,A)=>(A.windowLayer??0)>(w.windowLayer??0)?A:w);return Es(g)&&Lu(g,c?.screenHeight)?"topmost-suspect":"none"}function ci(c){let d=c.split("/")[1]??"";return d.startsWith("android.widget.")||d.startsWith("android.view.")||d.endsWith("DecorView")}function nt(c){let d=c?.foregroundActivity;return typeof d==="string"&&!ci(d)}function Ns(c,d){if(d===void 0)return!0;if(!nt(c))return!1;let[h,g=""]=(c.foregroundActivity??"").split("/"),w=g.startsWith(".")?h+g:g;return d.appId===h&&d.activityName===w}function Vu(c,d){return c===d||c.startsWith(`${d}.`)}function $e(c){let d=c.viewHierarchy?.packageName,h=c.backStack;if(!d||h?.source!=="adb")return;let g=h.currentActivity?.name;if(!g)return;if(Vu(g,d))return{packageName:d,activityName:g};let w=h.currentActivity?.taskId;return h.tasks.some((C)=>C.id===w&&C.packageName===d)===!0?{packageName:d,activityName:g}:void 0}function ui(c,d,h){return!nt(c.viewHierarchy)||d.activityName!==h.activityName}function Sc(c){return c?.hierarchy!==void 0&&typeof c.hierarchy==="object"&&c.hierarchy!==null&&!("error"in c.hierarchy)}class pi{dependencies;constructor(c){this.dependencies=c}get viewHierarchy(){return this.dependencies.viewHierarchy()}get deviceStateCollector(){return this.dependencies.deviceStateCollector()}get device(){return this.dependencies.device()}get platformValidator(){return this.dependencies.platformValidator()}get hierarchyPlatform(){return te(this.device.platform,"Observing the view hierarchy")}get resolveObservationTimestampMs(){return this.dependencies.resolveObservationTimestampMs}get extractScreenSizeFromHierarchy(){return this.dependencies.extractScreenSizeFromHierarchy}async reconcileActiveWindowAttribution(c,d={}){let{signal:h,readOnly:g=!1}=d;if(await this.applyFocusedSystemUiOverlay(c,h))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let w=c.activeWindow,A=c.viewHierarchy?.packageName;if(A===void 0||w===void 0||ue.has(A))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let C=$e(c);if(C){let k=await this.reconcileAgainstBackStack(c,w,C,{signal:h,readOnly:g});if(k)return k}if(w.appId===A)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let T=await this.deviceStateCollector.collectForegroundIdentity(h);if(T===A)c.activeWindow={...w,appId:A,activityName:""};return{sampled:!0,identity:T,activityAttributionMismatch:!1}}async reconcileAgainstBackStack(c,d,h,g={}){let{signal:w,readOnly:A=!1}=g,C=!nt(c.viewHierarchy);if(!ui(c,d,h))return;if(!await this.recaptureHierarchyForBackStackAttribution(c,h,w)){if(C&&d.activityName!=="")c.activeWindow={...d,activityName:""};return{sampled:!1,identity:void 0,activityAttributionMismatch:!0}}let k=await this.refreshRecaptureSideSamples(c,d,h,{bootstrapAttribution:C,signal:w,readOnly:A});if(c.activeWindow=k,await this.applyFocusedSystemUiOverlay(c,w,!0))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let D={...k,appId:h.packageName,activityName:h.activityName};if(c.notificationPermissionDetected)D.type="notification_permission_dialog";else delete D.type;return c.activeWindow=D,{sampled:!1,identity:void 0,activityAttributionMismatch:!1}}async applyFocusedSystemUiOverlay(c,d,h=!1){if(this.device.platform!=="android")return!1;let g=c.activeWindow;if(g===void 0)return!1;let w=Fs(c.viewHierarchy);if(w==="none")return!1;if(w==="focused")return this.mirrorFocusedSystemUiOverlay(c,g),!0;return this.applyFallbackSystemUiOverlay(c,g,h,d)}async applyFallbackSystemUiOverlay(c,d,h,g){if(h)return this.confirmFallbackOverlayFocus(c,d,g);return this.resolveFallbackOverlayWithRecapture(c,d,g)}async confirmFallbackOverlayFocus(c,d,h){if(!await this.deviceStateCollector.collectFocusedSystemUiSurface(h))return!1;return this.mirrorFocusedSystemUiOverlay(c,d),!0}async resolveFallbackOverlayWithRecapture(c,d,h,g=1){if(!await this.recaptureHierarchyForSystemUiOverlay(c,h))return this.confirmFallbackOverlayFocus(c,d,h);let w=c.activeWindow??d,A=Fs(c.viewHierarchy);if(A==="none")return!1;if(A==="focused")return this.mirrorFocusedSystemUiOverlay(c,w),!0;if(await this.deviceStateCollector.collectFocusedSystemUiSurface(h))return this.mirrorFocusedSystemUiOverlay(c,w),!0;if(g>0)return this.resolveFallbackOverlayWithRecapture(c,w,h,g-1);return!1}mirrorFocusedSystemUiOverlay(c,d){let h={...d,appId:_s,activityName:"",systemOverlay:!0};delete h.type,c.activeWindow=h}async recaptureHierarchyForSystemUiOverlay(c,d){let h=this.resolveObservationTimestampMs(c);if(h===void 0)return e.debug("[OBSERVE] Skipping SystemUI-overlay recapture without a device capture timestamp"),!1;let g=h+1,w;try{w=await this.viewHierarchy.getViewHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:g,signal:d})}catch(A){return e.debug(`[OBSERVE] SystemUI-overlay recapture failed; preserving original hierarchy: ${A}`),!1}if(!w||!Sc(w)||w.fresh!==!0||!this.platformValidator.validate(this.hierarchyPlatform,w).valid)return!1;return await this.primeRecapturedHierarchy(c,w,d),this.applyRecapturedHierarchy(c,w),delete c.deviceLock,delete c.deviceLockUnknown,await this.deviceStateCollector.collectDeviceLock(c,d),delete c.backStack,this.recorrelateActiveWindowToRecapture(c,w),!0}recorrelateActiveWindowToRecapture(c,d){if(c.activeWindow===void 0)return;let h=this.deriveActiveWindowFromHierarchy(d);if(h===void 0)return;if(c.notificationPermissionDetected)h.type="notification_permission_dialog";c.activeWindow=h}deriveActiveWindowFromHierarchy(c){let d=c.packageName??c.foregroundActivity?.split("/")[0];if(!d)return;return{appId:d,activityName:"",layoutSeqSum:0}}async recaptureHierarchyForBackStackAttribution(c,d,h){let g=this.resolveObservationTimestampMs(c);if(g===void 0)return e.debug("[OBSERVE] Skipping back-stack recapture without a device capture timestamp"),!1;let w=g+1,A;try{A=await this.viewHierarchy.getViewHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:w,signal:h})}catch(k){return e.debug(`[OBSERVE] Attribution recapture failed; preserving original hierarchy: ${k}`),!1}if(!this.isUsableAttributionRecapture(A,d))return!1;let C={...c,backStack:void 0,errors:void 0};await this.deviceStateCollector.collectBackStack(C,new U,h);let T=$e(C);if(!this.matchesExpectedBackStackAttribution(T,d)){for(let k of C.errors??[])ne(c,k);return!1}return await this.primeRecapturedHierarchy(c,A,h),this.applyRecapturedHierarchy(c,A),c.backStack=C.backStack,!0}async refreshRecaptureSideSamples(c,d,h,{bootstrapAttribution:g,...w}){let{signal:A,readOnly:C=!1}=w;delete c.deviceLock,delete c.deviceLockUnknown;let[T]=await Promise.all([g?this.refreshBootstrapLayoutSeqSum(c,d,h,{readOnly:C}):Promise.resolve(d),this.deviceStateCollector.collectDeviceLock(c,A)]);return T}async refreshBootstrapLayoutSeqSum(c,d,h,g={}){let{readOnly:w=!1}=g,A={...c,activeWindow:void 0,errors:void 0};await this.deviceStateCollector.collectActiveWindow(A,w);for(let D of A.errors??[])ne(c,D);let C=A.activeWindow;if(!C?.layoutSeqSum)return d;let T=C.activityName.startsWith(".")?C.appId+C.activityName:C.activityName;return C.appId===h.packageName&&T===h.activityName?{...d,layoutSeqSum:C.layoutSeqSum}:d}isUsableAttributionRecapture(c,d){if(!c)return!1;return Sc(c)&&c.fresh===!0&&c.packageName===d.packageName&&this.platformValidator.validate(this.hierarchyPlatform,c).valid}matchesExpectedBackStackAttribution(c,d){return c?.packageName===d.packageName&&c.activityName===d.activityName}async primeRecapturedHierarchy(c,d,h){await this.dependencies.xrDisplaySize?.prime(c,d,h)}applyRecapturedGeometry(c,d){if(d.screenWidth&&d.screenHeight)c.screenSize={width:d.screenWidth,height:d.screenHeight};if(this.device.platform==="ios")c.screenSize=this.extractScreenSizeFromHierarchy(d)??c.screenSize,c.rotation=bc(d.rotation,c.screenSize);else this.dependencies.xrDisplaySize?.applyCached(c,d),c.rotation=d.rotation}applyRecapturedHierarchy(c,d){if(c.viewHierarchy=d,c.updatedAt=d.updatedAt??c.updatedAt,this.applyRecapturedGeometry(c,d),c.systemInsets=d.systemInsets??{top:0,right:0,bottom:0,left:0},c.insets=d.insets??{available:!1,source:"unavailable",units:"unknown"},c.wakefulness=d.wakefulness??c.wakefulness,d.wakefulness)c.wakefulnessSource="hierarchy";c.intentChooserDetected=d.intentChooserDetected,c.notificationPermissionDetected=d.notificationPermissionDetected,c.focusedElement=this.viewHierarchy.findFocusedElement(d)??void 0,c.accessibilityFocusedElement=this.viewHierarchy.findAccessibilityFocusedElement(d)??void 0}}function Uu(c,d){let h=c?.packageName;return d!==void 0&&!ue.has(d)&&(h===void 0?c?.ctrlProxyIncomplete===!0:ue.has(h))}function Wu(c,d,h,g){return ue.has(d)||ue.has(h)||g&&DD(c)}function Mt(c){let d=c.systemInsets.top,h=c.viewHierarchy?.hierarchy.node;if(d<=0||!h)return!1;let g=!1,w=Array.isArray(h)?[...h]:[h];while(w.length>0){let A=w.pop();if(!A)continue;if(A.bounds){if(g=!0,A.bounds.bottom>d)return!1}let C=A.node;if(C)w.push(...Array.isArray(C)?C:[C])}return g}function $u(c,d){return{foreground:d,ctrlProxyIncomplete:c?.ctrlProxyIncomplete===!0,sdkInt:c?.sdkInt,accessibilityTool:c?.accessibilityTool}}class mi{dependencies;constructor(c){this.dependencies=c}get deviceStateCollector(){return this.dependencies.deviceStateCollector()}get timer(){return this.dependencies.timer()}get resolveObservationTimestampMs(){return this.dependencies.resolveObservationTimestampMs}async resolveWindowIdentityMismatch(c,d,{postCaptureForeground:h,getConfirmedFrameworkErrorDialog:g,minTimestamp:w,signal:A}){let C=await d,T=c.viewHierarchy?.packageName??c.activeWindow?.appId;if(!C||!T)return;if(Wu(c.viewHierarchy,T,C,this.isOwnWindowEvidenceCurrent(c,w)))return;let k=await this.resolvePostCaptureForegroundIdentity(C,T,h,A);if(!k||k!==C||k===T)return;if(await g())return;return{observed:T,foreground:C}}isOwnWindowEvidenceCurrent(c,d){let h=this.resolveObservationTimestampMs(c);if(h===void 0||d>0&&h<d)return!1;let g=this.resolveHostReceivedAtMs(c)??h;return this.timer.now()-g<=ob()}async attributeFocusedOwnWindowToForeground(c,d,h){let g=c.activeWindow;if(g?.appId!==vt||!DD(c.viewHierarchy)||!this.isOwnWindowEvidenceCurrent(c,h))return;let w=await d;if(!w||w===vt||ue.has(w))return;c.activeWindow={...g,appId:w,type:g.type??cj}}async resolveStatusBarOnlyHierarchy(c,d,h,g){let w=await d,A=c.viewHierarchy,C=Mt(c);if(!Uu(A,w)&&!C)return;if(w===void 0||ue.has(w))return;let T=C?await this.confirmForegroundIdentity(h,g):await this.resolvePostCaptureForegroundIdentity(w,A?.packageName??"",h,g);if(!T||ue.has(T)||!Mt(c))return;return $u(A,T)}async confirmForegroundIdentity(c,d){if(c.sampled)return c.identity;return this.deviceStateCollector.collectForegroundIdentity(d,{displayId:c.displayId})}async resolvePostCaptureForegroundIdentity(c,d,h,g){if(h.sampled)return h.identity;if(c===d)return;return this.deviceStateCollector.collectForegroundIdentity(g,{displayId:h.displayId})}resolveHostReceivedAtMs(c){let d=c.viewHierarchy?.receivedAt;if(typeof d==="number"&&!Number.isNaN(d))return d;return}}function hi(c,d={}){let h,g=new Map;for(let A of c.split(`
|
|
11
|
-
`)){let C=A.match(/^\s*Display:\s*mDisplayId=(\d+)/);if(C){h=parseInt(C[1],10);continue}let T=A.trim(),D=T.match(/^mRotation=(\d+)/)??(T.startsWith("mDisplayFrozen=")?T.match(/\bmRotation=(\d+)\b/):null);if(!D)continue;let M=parseInt(D[1],10);if(!g.has(h))g.set(h,M)}let w=h===void 0?void 0:d.displayId??0;return g.get(w)??null}function Bs(c,d={}){let h,g=new Map,w=new Set;for(let A of c.split(`
|
|
12
|
-
`)){let C=A.match(/^\s*Display:\s*mDisplayId=(\d+)/);if(C){h=Number(C[1]);continue}if(h===void 0||w.has(h))continue;let T=A.match(/\bmDisplayRotation=(?:ROTATION_(0|90|180|270)\b|\S+)/);if(T){if(T[1]!==void 0)g.set(h,Number(T[1])/90);w.add(h)}}return g.get(d.displayId??0)??null}var Gu="shell dumpsys window displays",qu='shell dumpsys window | grep -i "mRotation="',zu=5000,Hs=ie;function Ku(c,d){return Bs(c,d)??hi(c,d)}async function al(c,d={}){let h=d.timeoutMs??zu,g=(d.displayId??0)===0,w="display 0 rotation is missing",A;try{let{stdout:T}=await c.executeCommand(Gu,{timeoutMs:h,maxBuffer:Hs,signal:d.signal}),k=Ku(T,d);if(k!==null||!g)return k}catch(T){if(d.signal?.aborted||T instanceof Error&&T.name==="AbortError"||!g)throw T;w="the displays subcommand failed",A=T}o(d.signal),e.debug(`[readWindowManagerRotation] Falling back to legacy WindowManager rotation: ${w}`,A);let{stdout:C}=await c.executeCommand(qu,{timeoutMs:h,maxBuffer:Hs,signal:d.signal});return hi(C)}var HC="sdk-capture-identity",qC="web-snapshot-id";function ju(c,d){if(c===HC||c===qC)return;if(c!==""&&typeof d==="object"&&d!==null&&"resource-id"in d){let h=d["resource-id"];if(typeof h==="string"&&qj.has(h))return}return d}function Xu(c){let d=new WeakMap;return(h)=>{if(!h?.hierarchy)return null;let g=d.get(h);if(g!==void 0)return g;let w=null;try{w=c(JSON.stringify(h.hierarchy,ju))}catch(A){e.warn(`[hierarchyFingerprint] Failed to fingerprint view hierarchy: ${r(A)}`)}return d.set(h,w),w}}var bn=Xu((c)=>Cc.generateCacheKey(c)),IL=(c,d)=>{let h=bn(c),g=bn(d);if(h===null||g===null)return null;return h!==g};function ot(c){let d=0;for(let h of c?.windows??[]){let g=h.prototypeMotion?.active;if(typeof g==="number"&&Number.isFinite(g)&&g>0)d+=g}return d}var IT=["com.google.android.apps.nexuslauncher","com.android.launcher3","com.sec.android.app.launcher","com.huawei.android.launcher","com.miui.home","com.android.launcher","com.samsung.android.app.launcher","com.oneplus.launcher"];var Yu="shell cmd package resolve-activity --brief -c android.intent.category.HOME -a android.intent.action.MAIN",Ls=5000,Ju=new Set(IT),Qu=30000,Zu=2000,Ft=new Map;function ep(c){let d=c.split(`
|
|
13
|
-
`).map((w)=>w.trim()).filter((w)=>w.length>0),h=d[d.length-1];if(!h)return null;let g=h.match(/^([^\s/]+)\//);return g?g[1]:null}function tp(c,d,h){if(c===void 0||c.incarnationToken!==h)return;let g=h===void 0?Zu:Qu;return d-c.resolvedAtMs<g?c.packageName:void 0}async function b3(c,d,h=i,{incarnationToken:g,signal:w,timeoutMs:A}={}){let C=me(w);o(C);let T=h.now(),k=Ft.get(d),D=tp(k,T,g);if(D!==void 0)return D;let M=A===void 0?Ls:Math.max(1,Math.min(Ls,A));try{let F=await c.executeCommand(Yu,{timeoutMs:M,noRetry:!0,signal:C}),_=ep(F.stdout);if(_)Ft.set(d,{packageName:_,resolvedAtMs:h.now(),incarnationToken:g});return _}catch(F){if(C?.aborted)throw F;return e.warn(`[androidLauncherPackages] Failed to resolve configured HOME launcher package: ${r(F)}`,F),null}}function Nte(c){if(c===void 0)Ft.clear();else Ft.delete(c)}function rp(c){if(!c)return!1;return Ju.has(c)}async function Av(c,d,h,{timer:g=i,...w}={}){if(!c)return!1;let{incarnationToken:A,signal:C,timeoutMs:T}=w,k=await b3(d,h,g,{incarnationToken:A,signal:C,timeoutMs:T});if(w.formFactor==="automotive"&&c==="com.android.car.mapsplaceholder")return!0;if(k)return c===k;return rp(c)}class fi{device;adbFactory;timer;reader;lastUpdatedAt;constructor(c,d,h,g){this.device=c;this.adbFactory=d;this.timer=h;this.reader=g}async wait(c,d){let h=this.timer.now()+Math.max(0,c),g=null;while(this.timer.now()<h&&!d?.aborted){let w=h-this.timer.now();try{let A=await this.readFingerprint(w,d);if(A!==null&&A===g)return;g=A}catch(A){if(g=null,d?.aborted||this.timer.now()>=h){e.debug(`Quiet-tree stability read ended: ${r(A)}`);return}e.warn(`Quiet-tree stability read failed: ${r(A)}`)}if(d?.aborted)return;await this.timer.sleep(Math.min(17,Math.max(0,h-this.timer.now())))}}async readFingerprint(c,d){let h=new AbortController,g=d?AbortSignal.any([d,h.signal]):h.signal,w=this.reader??=new Xi(this.device,this.adbFactory,null,{timer:this.timer}),A=await l(()=>w.getViewHierarchy(void 0,{timeoutMs:c,requireFreshExtraction:!0,skipWaitForFresh:!0,...this.lastUpdatedAt===void 0?{}:{minTimestamp:this.lastUpdatedAt+1},signal:g}),{timer:this.timer,timeoutMs:c,signal:d,label:"Quiet-tree stability read",onTimeout:()=>h.abort()});if(!A.hierarchy.error)this.lastUpdatedAt=un(A)??this.lastUpdatedAt;if(ot(A)>0)return null;return A.fresh===!0&&!A.hierarchy.error?bn(A):null}async metrics(c,d,h,g){return await this.wait(d+h-this.timer.now(),g),{packageName:c,percentile50thMs:null,percentile90thMs:null,percentile95thMs:null,percentile99thMs:null,missedVsyncCount:null,slowUiThreadCount:null,frameDeadlineMissedCount:null,pollCount:0,stabilityWaitMs:this.timer.now()-d,isStable:!0}}}var _L=1000,Fte=5000;class _T{adb;timer;quietTree;testHooks={isSystemLauncher:(c)=>this.isSystemLauncher(c)};constructor(c,d=v,h=i,g){this.adb=d.create(c),this.timer=h,this.quietTree=new fi(c,d,h,g)}isSystemLauncher(c){if(!c)return!1;let d=["com.android.systemui",...IT];return c==="android"||d.some((h)=>c===h||c.startsWith(`${h}.`))}async waitForQuietTreeStability(c,d,h,g){if(!this.isSystemLauncher(c))return null;return this.quietTree.metrics(c,d,h,g)}getTouchStatus(c,d,h,g){let w=this.timer.now()-c,A=this.timer.now()-d,C=A>=h,T=!C&&w<g;return{isIdle:C,shouldContinue:T,currentElapsed:w,idleTime:A}}async getRotationStatus(c,d,h,{perf:g=new U,signal:w}={}){try{let A=await g.track("adbDumpsysWindowRotation",()=>{w?.throwIfAborted();let C=d+h-this.timer.now();return al(this.adb,{signal:w,timeoutMs:Math.max(C,_L)})});if(A!==null){if(e.debug(`Current rotation: ${A}, target: ${c}`),A===c)return e.debug(`Rotation to ${c} complete, took ${this.timer.now()-d}ms`),{rotationComplete:!0,currentRotation:A,shouldContinue:!1};return{rotationComplete:!1,currentRotation:A,shouldContinue:this.timer.now()-d<h}}return{rotationComplete:!1,currentRotation:null,shouldContinue:this.timer.now()-d<h}}catch(A){return w?.throwIfAborted(),e.debug(`Rotation idle check failed, treating as not-yet-idle: ${A}`),{rotationComplete:!1,currentRotation:null,shouldContinue:this.timer.now()-d<h}}}async getUiStabilitySnapshot(c,d=200,h=new U){e.info(`[AwaitIdle] Measuring UI idle for ${c} with ${d}ms delay`);try{return await h.track("adbGfxinfoReset",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)} reset`,{maxBuffer:ie})),await this.timer.sleep(d),await this.getUiStability(c,{missedVsync:null,slowUiThread:null,frameDeadlineMissed:null,totalFrames:null},!1,{perf:h})}catch(g){return e.info(`[Idle] Error measuring UI idle: ${g}`),{isStable:!1,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:null,updatedPrevSlowUiThread:null,updatedPrevFrameDeadlineMissed:null,updatedPrevTotalFrames:null,updatedFirstGfxInfoLog:!1}}}async getFrameStats(c,d,h=new U,g={}){try{let{stdout:w}=await h.track("adbGfxinfo",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{timeoutMs:g.timeoutMs,maxBuffer:ie,signal:g.signal}));if(d)e.info(`[AwaitIdle] Initial gfxinfo stdout for ${c}:
|
|
14
|
-
${w}`);return w}catch(w){return g.signal?.throwIfAborted(),e.info(`[AwaitIdle] Failed to get gfxinfo for ${c}: ${w}`),null}}parseMetrics(c){let d=this.extractMetric(c,/50th percentile:\s+(\d+(?:\.\d+)?)ms/),h=this.extractMetric(c,/90th percentile:\s+(\d+(?:\.\d+)?)ms/),g=this.extractMetric(c,/95th percentile:\s+(\d+(?:\.\d+)?)ms/),w=this.extractMetric(c,/99th percentile:\s+(\d+(?:\.\d+)?)ms/),A=this.extractMetric(c,/Total frames rendered:\s+(\d+)/),C=this.extractMetric(c,/Number Missed Vsync:\s+(\d+)/),T=this.extractMetric(c,/Number Slow UI thread:\s+(\d+)/),k=this.extractMetric(c,/Number Frame deadline missed:\s+(\d+)/);return e.debug(`Metrics: 50th=${d}ms 90th=${h}ms 95th=${g}ms 99th=${w}ms TotalFrames=${A} MissedVsync=${C} SlowUI=${T} DeadlineMissed=${k}`),{percentile50th:d,percentile90th:h,percentile95th:g,percentile99th:w,totalFrames:A,missedVsync:C,slowUiThread:T,frameDeadlineMissed:k}}validateFrameData(c){return c.percentile50th!==null&&c.missedVsync!==null&&c.slowUiThread!==null}updateStabilityState(c,d){let{missedVsync:h,slowUiThread:g,frameDeadlineMissed:w,totalFrames:A}=c,C=this.calculateDeltas(c,d);return{updatedPrevMissedVsync:h,updatedPrevSlowUiThread:g,updatedPrevFrameDeadlineMissed:w,updatedPrevTotalFrames:A,deltas:C}}processFrameStatsForStability(c,d,h,{prevFrameDeadlineMissed:g,prevTotalFrames:w}){let A=this.parseMetrics(c);if(!this.validateFrameData(A))return e.info(`[AwaitIdle] No valid frame data yet: percentile50th ${A.percentile50th} && missedVsync ${A.missedVsync} && slowUiThread ${A.slowUiThread}`),{isStable:!1,noFrameData:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:d,updatedPrevSlowUiThread:h,updatedPrevFrameDeadlineMissed:g,updatedPrevTotalFrames:w};let C=this.updateStabilityState({missedVsync:A.missedVsync,slowUiThread:A.slowUiThread,frameDeadlineMissed:A.frameDeadlineMissed,totalFrames:A.totalFrames},{missedVsync:d,slowUiThread:h,frameDeadlineMissed:g,totalFrames:w}),T=this.checkStabilityCriteria(C.deltas,{percentile50th:A.percentile50th,percentile90th:A.percentile90th,percentile95th:A.percentile95th},A.totalFrames);return{isStable:T,shouldUpdateLastNonIdleTime:!T,updatedPrevMissedVsync:C.updatedPrevMissedVsync,updatedPrevSlowUiThread:C.updatedPrevSlowUiThread,updatedPrevFrameDeadlineMissed:C.updatedPrevFrameDeadlineMissed,updatedPrevTotalFrames:C.updatedPrevTotalFrames}}calculateDeltas(c,d){let h=d.missedVsync!==null&&c.missedVsync!==null?c.missedVsync-d.missedVsync:0,g=d.slowUiThread!==null&&c.slowUiThread!==null?c.slowUiThread-d.slowUiThread:0,w=d.frameDeadlineMissed!==null&&c.frameDeadlineMissed!==null?c.frameDeadlineMissed-d.frameDeadlineMissed:0,A=d.totalFrames!==null&&c.totalFrames!==null?c.totalFrames>=d.totalFrames?c.totalFrames-d.totalFrames:null:null;return e.debug(`Deltas: MissedVsync=${h} SlowUI=${g} DeadlineMissed=${w} TotalFrames=${A}`),{missedVsyncDelta:h,slowUiThreadDelta:g,frameDeadlineMissedDelta:w,totalFramesDelta:A}}checkStabilityCriteria(c,d,h){let{p50Int:g,p90Int:w,p95Int:A,shouldCheckPercentiles:C,percentilesOk:T}=this.assessPercentiles(c.totalFramesDelta,d,h),k=c.missedVsyncDelta===0&&c.slowUiThreadDelta===0&&c.frameDeadlineMissedDelta===0&&T;if(k)e.info("[AwaitIdle] UI appears stable (criteria met)");else{let D=C?`percentiles (50th=${g}, 90th=${w}, 95th=${A})`:`percentiles skipped (frames=${h??"n/a"}, delta=${c.totalFramesDelta??"n/a"})`;e.info(`[AwaitIdle] UI not stable: deltas (Vsync=${c.missedVsyncDelta}, UI=${c.slowUiThreadDelta}, Deadline=${c.frameDeadlineMissedDelta}, Frames=${c.totalFramesDelta??"n/a"}), ${D}`)}return k}assessPercentiles(c,d,h){let g=d.percentile50th!==null?Math.floor(d.percentile50th):0,w=d.percentile90th!==null?Math.floor(d.percentile90th):0,A=d.percentile95th!==null?Math.floor(d.percentile95th):0,C=5,T=c!==null&&c>0,k=h!==null&&h>=5,D=c===null||T&&k,M=!D||g<100&&w<100&&A<200;return{p50Int:g,p90Int:w,p95Int:A,shouldCheckPercentiles:D,percentilesOk:M}}async getUiStability(c,d,h,{perf:g=new U,...w}={}){let{missedVsync:A,slowUiThread:C,frameDeadlineMissed:T,totalFrames:k}=d;try{if(this.isSystemLauncher(c))return await this.quietTree.wait(w.timeoutMs??1000,w.signal),{isStable:!0,shouldUpdateLastNonIdleTime:!1,updatedPrevMissedVsync:null,updatedPrevSlowUiThread:null,updatedPrevFrameDeadlineMissed:null,updatedPrevTotalFrames:null,updatedFirstGfxInfoLog:!1};let D=await this.getFrameStats(c,h,g,w);if(D===null)return{isStable:!1,frameStatsUnavailable:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:A,updatedPrevSlowUiThread:C,updatedPrevFrameDeadlineMissed:T,updatedPrevTotalFrames:k,updatedFirstGfxInfoLog:!1};if(D.trim()==="")return e.info(`[AwaitIdle] No gfxinfo data for ${c}, treating as stable`),{isStable:!0,shouldUpdateLastNonIdleTime:!1,updatedPrevMissedVsync:null,updatedPrevSlowUiThread:null,updatedPrevFrameDeadlineMissed:null,updatedPrevTotalFrames:null,updatedFirstGfxInfoLog:!1};let M=this.processFrameStatsForStability(D,A,C,{prevFrameDeadlineMissed:T,prevTotalFrames:k});return{isStable:M.isStable,...M.noFrameData?{noFrameData:!0}:{},shouldUpdateLastNonIdleTime:M.shouldUpdateLastNonIdleTime,updatedPrevMissedVsync:M.updatedPrevMissedVsync,updatedPrevSlowUiThread:M.updatedPrevSlowUiThread,updatedPrevFrameDeadlineMissed:M.updatedPrevFrameDeadlineMissed,updatedPrevTotalFrames:M.updatedPrevTotalFrames,updatedFirstGfxInfoLog:!1}}catch(D){return w.signal?.throwIfAborted(),e.info(`[AwaitIdle] Error checking frame stats: ${D}`),{isStable:!1,frameStatsUnavailable:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:A,updatedPrevSlowUiThread:C,updatedPrevFrameDeadlineMissed:T,updatedPrevTotalFrames:k,updatedFirstGfxInfoLog:!1}}}extractMetric(c,d){let h=c.match(d);if(h&&h[1]){let g=parseFloat(h[1]);return isNaN(g)?null:g}return null}}var ip=750,np=2000,_t=new Map;class Le{timer;adb;deviceId;constructor(c,d=v,h=i){this.timer=h;this.adb=d.create(c),this.deviceId=c.deviceId}async detectRefreshRate(){let c=no(this.deviceId)??"unknown",d=`${this.deviceId}\x00${c}`,h=_t.get(d);if(h!==void 0)return h;let g=this.timer.now();try{let{stdout:w}=await this.probe("shell dumpsys display | grep mRefreshRate",g),A=w.match(/mRefreshRate[=:]\s*(\d+\.?\d*)/i);if(A&&A[1]){let F=Math.round(parseFloat(A[1]));return e.info(`Detected refresh rate: ${F}Hz`),_t.set(d,F),F}let{stdout:C}=await this.probe("shell dumpsys SurfaceFlinger | grep 'refresh-rate'",g),T=C.match(/refresh-rate[=:]\s*(\d+\.?\d*)/i);if(T&&T[1]){let F=Math.round(parseFloat(T[1]));return e.info(`Detected refresh rate from SurfaceFlinger: ${F}Hz`),_t.set(d,F),F}let{stdout:k}=await this.probe("shell dumpsys display | grep -A 5 'mBaseDisplayInfo'",g),D=k.match(/fps\s*[=:]\s*(\d+\.?\d*)|(\d+\.?\d*)\s*fps/i),M=D?.[1]??D?.[2];if(M){let F=Math.round(parseFloat(M));return e.info(`Detected refresh rate from display modes: ${F}Hz`),_t.set(d,F),F}return e.warn("Could not detect refresh rate, defaulting to 60Hz"),60}catch(w){return e.warn(`Error detecting refresh rate: ${w}; defaulting to 60Hz`,w),60}}async probe(c,d){let h=this.timer.now()-d,g=np-h;if(g<=0)return{stdout:""};return this.adb.executeCommand(c,{timeoutMs:Math.min(ip,g),maxBuffer:ie,noRetry:!0})}async getCapabilities(){let c=await this.detectRefreshRate(),d=1000/c;return{refreshRate:c,frameTimeMs:d}}static calculateDefaultThresholds(c){let{frameTimeMs:d,refreshRate:h}=c;return{frameTimeThresholdMs:d,p50ThresholdMs:d*0.9,p90ThresholdMs:d*1,p95ThresholdMs:d*1.2,p99ThresholdMs:d*1.5,jankCountThreshold:Math.ceil(h/12),cpuUsageThresholdPercent:80,touchLatencyThresholdMs:d*2}}}var yi={min:0.1,max:2,successMultiplier:1.1,failureMultiplier:0.9};function Vs(c,d,h){if(c.length===0)return null;let g=c.reduce((A,C)=>A+h(C),0);if(g===0)return null;return c.reduce((A,C)=>A+d(C)*h(C),0)/g}function Ws(c){if(c.length===0)return;let d=new Map,h=0,g=c[0];for(let w of c){let A=(d.get(w)??0)+1;if(d.set(w,A),A>h)h=A,g=w}return g}function $s(c){if(c.length===0)return;let d=[...c].sort((g,w)=>g-w),h=Math.floor(d.length/2);return d.length%2===0?(d[h-1]+d[h])/2:d[h]}function VC(c,d){if(d===0)return c>0?1/0:1;return c/d}function SW(c,d=Date.now()){let h=new Date(d);return h.setDate(h.getDate()-c),h.toISOString()}var WC={thresholdHours:24,baselineDays:30},Lte=0.3;var op=10,ap=100,Gs=125;function Bt(c,d){return c!==null&&d!==null&&d>c}function qs(c,d){return Bt(c.totalFrames,d.totalFrames)||Bt(c.missedVsync,d.missedVsync)||Bt(c.slowUiThread,d.slowUiThread)||Bt(c.frameDeadlineMissed,d.frameDeadlineMissed)}class vi{adb;device;idle;timer;inertTouchPointResolver;constructor(c,d=v,h=i,g){this.device=c,this.adb=d.create(c),this.idle=new _T(c,d),this.timer=h,this.inertTouchPointResolver=g}selectSafeTouchLocation(c,d,h){if(d)return e.debug(`[TouchLatency] Using caller-provided touch location: (${d.x}, ${d.y})`),d;if(h&&h.right>h.left&&h.bottom>h.top){let A=Math.floor((h.left+h.right)/2),C=Math.floor((h.top+h.bottom)/2);return e.debug(`[TouchLatency] Selected touch location from app window bounds ${JSON.stringify(h)}: (${A}, ${C})`),{x:A,y:C}}let g=Math.floor(c.width*0.5),w=Math.floor(c.height*0.12);return e.debug(`[TouchLatency] Selected safe touch location (no window bounds): (${g}, ${w})`),{x:g,y:w}}async injectTouch(c,d,h){await h.track("adbInputTap",()=>this.adb.executeCommand(`shell input tap ${c} ${d}`))}async measureFrameResponse(c,d,h,g){let w=this.timer.now();while(this.timer.now()-w<h){await this.timer.sleep(op);try{let{stdout:A}=await g.track("adbGfxinfoCheck",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),C=this.idle.parseMetrics(A);if(qs(d,C)){let T=this.timer.now()-w;return e.debug(`[TouchLatency] Frame activity detected after ${T}ms`),T}}catch(A){e.warn(`[TouchLatency] Error checking frame stats: ${A}`)}}return e.warn(`[TouchLatency] No frame activity detected within ${h}ms`),null}async takeSample(c,d,h,{perf:g,sampleIndex:w}){await g.track("adbGfxinfoReset",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)} reset`,{maxBuffer:ie})),await this.timer.sleep(Gs);let{stdout:A}=await g.track("adbGfxinfoBaselineFirst",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),C=this.idle.parseMetrics(A);await this.timer.sleep(Gs);let{stdout:T}=await g.track("adbGfxinfoBaselineSecond",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),k=this.idle.parseMetrics(T);if(qs(C,k))return e.warn(`[TouchLatency] Sample ${w+1}: frame activity detected across two consecutive no-input snapshots - app is animating, skipping this sample`),{latencyMs:null,animating:!0,obstructed:!1,tapPoint:d};let D=d,M=k;if(this.inertTouchPointResolver){let _=await g.track("touchLatencyRevalidatePoint",()=>this.inertTouchPointResolver.resolveInertTouchPoint());if(!_)return e.warn(`[TouchLatency] Sample ${w+1}: no verified-inert touch point on a freshly captured hierarchy - aborting this sample instead of tapping a possibly-live control (issue #6228)`),{latencyMs:null,animating:!1,obstructed:!0,tapPoint:d};D=_;let{stdout:V}=await g.track("adbGfxinfoBaselinePostRevalidate",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie}));M=this.idle.parseMetrics(V)}return await this.injectTouch(D.x,D.y,g),{latencyMs:await this.measureFrameResponse(c,M,h,g),animating:!1,obstructed:!1,tapPoint:D}}buildResult(c,d,h,{otherFailureCount:g,obstructedCount:w}){let A=h>0;if(d.length===0){let T=A&&g===0&&w===0,k=w>0&&g===0&&!A,D;if(T)D="App renders continuously (animating); touch latency cannot be isolated";else if(k)D="Touch point was no longer inert on a freshly captured hierarchy; aborted touch-latency measurement rather than tapping a possibly-live control";else D="No successful measurements - UI may be frozen or gfxinfo unavailable";return{latencyMs:0,touchCoordinates:c,success:!1,error:D,sampleCount:0,animating:T}}let C=$s(d)??0;return e.info(`[TouchLatency] Measured latency: ${C}ms (from ${d.length} samples)`),{latencyMs:C,touchCoordinates:c,success:!0,sampleCount:d.length,...A?{animating:!0}:{}}}async measureLatency(c,d,h={},g=new U){let w=h.sampleCount||3,A=h.maxWaitMs||200;e.info(`[TouchLatency] Measuring touch latency for ${c} (${w} samples)`);let C=this.selectSafeTouchLocation(d,h.touchPoint,h.windowBounds),T=[],k=0,D=0,M=0,F=C;try{for(let _=0;_<w;_++){e.debug(`[TouchLatency] Taking sample ${_+1}/${w}`);let V=await this.takeSample(c,C,A,{perf:g,sampleIndex:_});if(V.animating)k++;else if(V.obstructed)M++;else if(V.latencyMs!==null)F=V.tapPoint,T.push(V.latencyMs),e.debug(`[TouchLatency] Sample ${_+1}: ${V.latencyMs}ms`);else D++,e.warn(`[TouchLatency] Sample ${_+1} timeout - no response within ${A}ms`);if(_<w-1)await this.timer.sleep(ap)}return this.buildResult(F,T,k,{otherFailureCount:D,obstructedCount:M})}catch(_){return e.warn(`[TouchLatency] Failed to measure touch latency: ${r(_)}`,_),{latencyMs:0,touchCoordinates:C,success:!1,error:r(_),sampleCount:T.length}}}}function zs(){return N.isUiPerfModeEnabled()&&YT()&&!Be(f.DISABLE_PERF_AUDIT)}function Ks(){return Be(f.TOUCH_LATENCY_SAMPLING)}var cp=1e4,dp=24,js=300000,lp=ak(),qe=null,up=500,Xs=["id","device_id","session_id","package_name","timestamp","passed","p50_ms","p90_ms","p95_ms","p99_ms","jank_count","missed_vsync_count","slow_ui_thread_count","frame_deadline_missed_count","cpu_usage_percent","touch_latency_ms","diagnostics_json","time_to_first_frame_ms","time_to_interactive_ms","frame_rate_fps","node_id","device_session_uuid"];function Ys(c){return{id:c.id,deviceId:c.device_id,sessionId:c.session_id,packageName:c.package_name,timestamp:c.timestamp,passed:c.passed===1,metrics:{p50Ms:c.p50_ms,p90Ms:c.p90_ms,p95Ms:c.p95_ms,p99Ms:c.p99_ms,jankCount:c.jank_count,missedVsyncCount:c.missed_vsync_count,slowUiThreadCount:c.slow_ui_thread_count,frameDeadlineMissedCount:c.frame_deadline_missed_count,cpuUsagePercent:c.cpu_usage_percent,touchLatencyMs:c.touch_latency_ms,timeToFirstFrameMs:c.time_to_first_frame_ms,timeToInteractiveMs:c.time_to_interactive_ms,frameRateFps:c.frame_rate_fps},diagnostics:c.diagnostics_json,nodeId:c.node_id,deviceSessionUuid:c.device_session_uuid}}class Om{timer;db;constructor({db:c,timer:d=i}={}){this.timer=d,this.db=c??null}getDb(){if(this.db)return this.db;return _e()}async recordAudit(c){try{let d=this.getDb(),h={device_id:c.deviceId,session_id:c.sessionId,package_name:c.packageName,timestamp:c.timestamp,passed:c.passed?1:0,p50_ms:c.metrics.p50Ms,p90_ms:c.metrics.p90Ms,p95_ms:c.metrics.p95Ms,p99_ms:c.metrics.p99Ms,jank_count:c.metrics.jankCount,missed_vsync_count:c.metrics.missedVsyncCount,slow_ui_thread_count:c.metrics.slowUiThreadCount,frame_deadline_missed_count:c.metrics.frameDeadlineMissedCount,cpu_usage_percent:c.metrics.cpuUsagePercent,touch_latency_ms:c.metrics.touchLatencyMs,diagnostics_json:c.diagnostics,time_to_first_frame_ms:c.metrics.timeToFirstFrameMs??null,time_to_interactive_ms:c.metrics.timeToInteractiveMs??null,frame_rate_fps:c.metrics.frameRateFps??null,node_id:c.nodeId??null,device_session_uuid:c.deviceSessionUuid??null};await d.insertInto("performance_audit_results").values(h).execute(),await this.cleanupRetention()}catch(d){e.error(`[PerformanceAuditRepository] Failed to store audit result: ${d}`)}}async listResults(c){let d=this.getDb(),h=Math.max(1,c.limit??50),g=Math.max(0,c.offset??0),w=d.selectFrom("performance_audit_results").select(Xs);if(c.deviceId)w=w.where("device_id","=",c.deviceId);if(c.deviceSessionUuid)w=w.where("device_session_uuid","=",c.deviceSessionUuid);if(c.startTime)w=w.where("timestamp",">=",c.startTime);if(c.endTime)w=w.where("timestamp","<=",c.endTime);let A=await w.orderBy("timestamp","desc").orderBy("id","desc").limit(h+1).offset(g).execute(),C=A.length>h;return{results:(C?A.slice(0,h):A).map(Ys),hasMore:C,nextOffset:C?g+h:null}}async listResultsSince(c){let d=this.getDb(),h=Math.min(Math.max(1,c.limit??50),up),g=d.selectFrom("performance_audit_results").select(Xs);if(c.deviceId)g=g.where("device_id","=",c.deviceId);if(c.sessionId)g=g.where("session_id","=",c.sessionId);if(c.packageName)g=g.where("package_name","=",c.packageName);if(c.startTime)g=g.where("timestamp",">=",c.startTime);if(c.endTime)g=g.where("timestamp","<=",c.endTime);if(c.sinceTimestamp){let A=c.sinceTimestamp,C=c.sinceId??0;g=g.where((T)=>T.or([T("timestamp",">",A),T.and([T("timestamp","=",A),T("id",">",C)])]))}return(await g.orderBy("timestamp","asc").orderBy("id","asc").limit(h).execute()).map(Ys)}async cleanupRetention(){await Ru(lp,()=>this.pruneToRowCap())}async pruneToRowCap(c=cp){try{await wu(this.getDb(),"performance_audit_results",c)}catch(d){e.warn(`[PerformanceAuditRepository] Retention cleanup failed: ${d}`)}}async pruneOldRecords(){try{let c=this.getDb(),h=new Date(this.timer.now()-dp*60*60*1000).toISOString(),g=await c.deleteFrom("performance_audit_results").where("timestamp","<",h).executeTakeFirst(),w=Number(g.numDeletedRows??0);if(w>0)e.info(`[PerformanceAuditRepository] Pruned ${w} old records`);return w}catch(c){return e.warn(`[PerformanceAuditRepository] Pruning failed: ${c}`),0}}startPeriodicPruning(){if(qe)return;qe=i.setInterval(()=>{this.pruneOldRecords().catch((c)=>{e.warn(`[PerformanceAuditRepository] Periodic pruning error: ${c}`)})},js),qe.unref(),e.info(`[PerformanceAuditRepository] Started periodic pruning (every ${js/1000}s)`)}stopPeriodicPruning(){if(qe)i.clearInterval(qe),qe=null,e.info("[PerformanceAuditRepository] Stopped periodic pruning")}}function wW(c){if(c.length===0)return[];let d=[...c].sort((g,w)=>w.contributionWeight-g.contributionWeight),h=Math.min(0.5,d[0].contributionWeight);return d.filter((g)=>g.contributionWeight>=h)}var pp=5000,mp=1048576;async function gi(c){let d=c;if(typeof d.getAndroidApiLevel==="function"){let h=await d.getAndroidApiLevel();if(h!==null&&h>=29)return"ActivityTaskManager"}return"ActivityManager"}function bi(c){let d=c.replace("+","").trim(),h=d.match(/^(\d+)s(\d+)ms$/);if(h)return Number.parseInt(h[1],10)*1000+Number.parseInt(h[2],10);let g=d.match(/^(\d+)ms$/);if(g)return Number.parseInt(g[1],10);let w=d.match(/^(\d+)s$/);if(w)return Number.parseInt(w[1],10)*1000;return null}function S3(c){let d=c.match(/^\s*(\d+\.\d+)\s+\d+\s+\d+\s+[VDIWEF]\s+(\w+):\s+(.*)$/);if(!d)return null;let h=Number.parseFloat(d[1]);if(Number.isNaN(h))return null;let g=d[2];if(g!=="ActivityManager"&&g!=="ActivityTaskManager")return null;return{timestampMs:Math.round(h*1000),logcatTag:g,message:d[3]}}function w3(c,d){let h=d==="Displayed"?/Displayed\s+(\S+?)(?:\s+for user \d+)?:/:/Fully drawn\s+(\S+?)(?:\s+for user \d+)?:/,g=c.match(h);return g?g[1]:null}function RW(c){let[d,h]=c.split("/"),g=h??"";if(g.startsWith("."))g=`${d}${g}`;return{packageName:d,activityName:g,componentName:c}}function R3(c){let d=c.match(/\+\s*\d+(?:s\d+ms|ms|s)/);if(!d)return null;return bi(d[0])}class P3{adb;device;logcatTagCache;constructor(c,d=v){if(this.device=c,d&&typeof d.create==="function")this.adb=d.create(c);else if(d)this.adb=d;else this.adb=v.create(c)}async captureDisplayedMetrics(c,d=new U){if(this.device.platform!=="android")return e.info("[DisplayedTimeMetrics] Skipping - not Android platform"),[];let h=await this.getPreferredLogcatTag();e.info(`[DisplayedTimeMetrics] Using logcat tag: ${h}`);let g=this.buildLogcatCommand(h);e.info(`[DisplayedTimeMetrics] Logcat command: ${g}`);try{let{stdout:w}=await d.track("adbLogcatDisplayed",()=>this.adb.executeCommand(g,{timeoutMs:pp,maxBuffer:mp}));e.info(`[DisplayedTimeMetrics] Logcat output length: ${w.length} chars`);let A=this.parseDisplayedMetrics(w,c);return e.info(`[DisplayedTimeMetrics] Parsed ${A.length} metrics for package ${c.packageName} (window: ${c.startTimestampMs} - ${c.endTimestampMs})`),A}catch(w){return e.warn(`[DisplayedTimeMetrics] Failed to read logcat: ${w}`),[]}}async getPreferredLogcatTag(){if(this.logcatTagCache)return this.logcatTagCache;return this.logcatTagCache=await gi(this.adb),this.logcatTagCache}buildLogcatCommand(c){return`shell logcat -d -v epoch -s ${c}:I`}parseDisplayedMetrics(c,d){let h=[],g=c.split(`
|
|
15
|
-
`),w=g.filter((A)=>A.includes("Displayed"));if(e.info(`[DisplayedTimeMetrics] Found ${w.length} 'Displayed' lines in logcat`),w.length>0)e.info(`[DisplayedTimeMetrics] Last few Displayed lines: ${w.slice(-3).join(" | ")}`);for(let A of g){let C=S3(A);if(!C)continue;let{timestampMs:T,logcatTag:k,message:D}=C;if(T<d.startTimestampMs||T>d.endTimestampMs){if(D.includes("Displayed")&&D.includes(d.packageName))e.info(`[DisplayedTimeMetrics] Filtered by timestamp: logcatTs=${T}, window=[${d.startTimestampMs}, ${d.endTimestampMs}]`);continue}let M=w3(D,"Displayed");if(!M)continue;let F=RW(M);if(F.packageName!==d.packageName)continue;let _=R3(D);if(_===null)continue;e.info(`[DisplayedTimeMetrics] Found metric: ${F.componentName} = ${_}ms`),h.push({packageName:F.packageName,activityName:F.activityName,componentName:F.componentName,displayedTimeMs:_,timestampMs:T,logcatTag:k})}return h}}var Si=500;function Js(c,d){if(c.startTimeTicks!==d.startTimeTicks)return null;let h=d.processTicks-c.processTicks,g=d.uptimeSeconds-c.uptimeSeconds;if(!Number.isFinite(h)||!Number.isFinite(g))return null;if(h<0||g<=0)return null;return h/(g*100)*100}function Ht(c,d){if(c===null||d===null)return null;return d>=c?d-c:d}function hp(c,d,h){let g=Ht(c.jankyFrames,d.jankyFrames);if(g!==null)return g;return h.length>0?Math.max(...h):null}function Qs(c,d,h){if(!(h>0))return null;let g=Ht(c.missedVsync,d.missedVsync),w=Ht(c.slowUiThread,d.slowUiThread),A=Ht(c.frameDeadlineMissed,d.frameDeadlineMissed),C=[g,w,A].filter((D)=>D!==null),T=hp(c,d,C);if(T===null)return null;let k=T*1000/h;return{jankPerSecond:Math.round(k*100)/100,missedVsync:g,slowUiThread:w,frameDeadlineMissed:A}}function Zs(c){let d=c.match(/^[ \t]*Janky frames:[ \t]*(\d+)/m);return d?parseInt(d[1],10):null}function ea(c){let d=c.lastIndexOf(")");if(d<0)return null;let h=c.slice(d+1).trim().split(/\s+/),g=parseInt(h[11]??"",10),w=parseInt(h[12]??"",10),A=parseInt(h[19]??"",10);if(![g,w,A].every(Number.isFinite))return null;return{processTicks:g+w,startTimeTicks:A}}var fp="No frames were rendered in the audit window, so there are no frame times to check.",yp="gfxinfo reported no rendered-frame count, so its frame times cannot be checked.";function vp(c){if(!c.totalFrames)return{p50Ms:null,p90Ms:null,p95Ms:null,p99Ms:null,frameTimeUnmeasured:c.totalFrames===0?fp:yp};return{p50Ms:c.percentile50th,p90Ms:c.percentile90th,p95Ms:c.percentile95th,p99Ms:c.percentile99th}}var gp=200,bp=100,Sp=500,wp=5000;class wi{adb;device;idle;capabilitiesDetector;touchLatencyTracker;repository=new Om;timer;constructor(c,d=v,h,g=i){this.timer=g,this.device=c,this.adb=d.create(c),this.idle=new _T(c,d),this.capabilitiesDetector=new Le(c,d),this.touchLatencyTracker=new vi(c,d,g,h)}async collectMetrics(c,d,h=new U,g){let w=g??{};e.info(`[PerformanceAudit] Collecting metrics for ${c}`);let[A,C,T,k]=await Promise.all([this.collectGfxMetrics(c,h),this.collectCpuMetrics(c,h),this.checkForAnr(c,h),this.calculateFrameRate(c,h)]),D=await this.measureTouchLatency(c,d,h,{windowBounds:w.windowBounds,touchPoint:w.touchPoint,skipTouchLatency:w.skipTouchLatency}),M=null,F=null;if(w.measureTtff)M=await this.measureTimeToFirstFrame(c,h);if(w.measureTti&&M!==null)F=await this.measureTimeToInteractive(c,M,h);return{...this.normalizeGfxMetrics(A),cpuUsagePercent:C.cpuUsagePercent??null,threadCount:C.threadCount??null,touchLatencyMs:D,anrDetected:T.anrDetected??!1,anrDetails:T.anrDetails??null,timeToFirstFrameMs:M,timeToInteractiveMs:F,frameRateFps:k,gfxinfoRaw:A.gfxinfoRaw??null,cpuStatsRaw:C.cpuStatsRaw??null}}normalizeGfxMetrics(c){return{p50Ms:c.p50Ms??null,p90Ms:c.p90Ms??null,p95Ms:c.p95Ms??null,p99Ms:c.p99Ms??null,...c.frameTimeUnmeasured!==void 0?{frameTimeUnmeasured:c.frameTimeUnmeasured}:{},jankCount:c.jankCount??null,missedVsyncCount:c.missedVsyncCount??null,slowUiThreadCount:c.slowUiThreadCount??null,frameDeadlineMissedCount:c.frameDeadlineMissedCount??null}}async readGfxSample(c,d){let{stdout:h}=await d.track("adbGfxinfo",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),g=this.idle.parseMetrics(h);return{stdout:h,counters:{totalFrames:g.totalFrames,jankyFrames:Zs(h),missedVsync:g.missedVsync,slowUiThread:g.slowUiThread,frameDeadlineMissed:g.frameDeadlineMissed}}}async collectGfxMetrics(c,d){try{let h=await this.readGfxSample(c,d),g=this.timer.now();await this.timer.sleep(Si);let w=await this.readGfxSample(c,d),A=this.timer.now()-g,C=this.idle.parseMetrics(w.stdout),T=Qs(h.counters,w.counters,A);return{...vp(C),jankCount:T?.jankPerSecond??null,missedVsyncCount:T?.missedVsync??null,slowUiThreadCount:T?.slowUiThread??null,frameDeadlineMissedCount:T?.frameDeadlineMissed??null,gfxinfoRaw:w.stdout}}catch(h){return e.warn(`[PerformanceAudit] Failed to collect gfx metrics: ${h}`),{p50Ms:null,p90Ms:null,p95Ms:null,p99Ms:null,jankCount:null,missedVsyncCount:null,slowUiThreadCount:null,frameDeadlineMissedCount:null,gfxinfoRaw:null}}}async readCpuSample(c,d){let{stdout:h}=await d.track("adbCpuStat",()=>this.adb.executeCommand(`shell cat /proc/${b(c)}/stat`)),{stdout:g}=await d.track("adbUptime",()=>this.adb.executeCommand("shell cat /proc/uptime")),w=ea(h),A=parseFloat(g.trim().split(/\s+/)[0]||"");if(!w||!Number.isFinite(A)||A<=0)return null;return{sample:{...w,uptimeSeconds:A},statRaw:h}}async collectCpuMetrics(c,d){try{let{stdout:h}=await d.track("adbGetPid",()=>this.adb.executeCommand(`shell pidof ${b(c)}`)),g=h.trim().split(/\s+/)[0];if(!g)return e.warn(`[PerformanceAudit] No PID found for ${c}`),{cpuUsagePercent:null,threadCount:null,cpuStatsRaw:null};let{stdout:w}=await d.track("adbThreadCount",()=>this.adb.executeCommand(`shell ps -T -p ${b(g)} | wc -l`)),A=parseInt(w.trim(),10)-1,C=await this.readCpuSample(g,d);await this.timer.sleep(Si);let T=await this.readCpuSample(g,d);return{cpuUsagePercent:C&&T?Js(C.sample,T.sample):null,threadCount:A,cpuStatsRaw:(T??C)?.statRaw??null}}catch(h){return e.warn(`[PerformanceAudit] Failed to collect CPU metrics: ${h}`),{cpuUsagePercent:null,threadCount:null,cpuStatsRaw:null}}}async checkForAnr(c,d){try{let{stdout:h}=await d.track("adbCheckAnr",()=>this.adb.executeCommand(`shell dumpsys activity processes | grep -A 20 ${b(c)}`,{maxBuffer:ie})),g=h.toLowerCase().includes("anr")||h.toLowerCase().includes("not responding");return{anrDetected:g,anrDetails:g?h:null}}catch(h){return e.warn(`[PerformanceAudit] Failed to check for ANR: ${h}`),{anrDetected:!1,anrDetails:null}}}async measureTouchLatency(c,d,h,g={}){let{windowBounds:w,touchPoint:A,skipTouchLatency:C}=g;if(C)return e.info("[PerformanceAudit] Touch latency measurement skipped (no verified-inert touch point available)"),null;if(!N.isUiPerfModeEnabled()||!Ks())return e.debug("[PerformanceAudit] Touch latency measurement skipped (sampling not enabled)"),null;if(!d)return e.warn("[PerformanceAudit] Touch latency measurement skipped (screen size not provided)"),null;try{e.info("[PerformanceAudit] Measuring touch latency with synthetic touches");let T=await h.track("touchLatencyMeasurement",()=>this.touchLatencyTracker.measureLatency(c,d,{sampleCount:3,maxWaitMs:gp,windowBounds:w,touchPoint:A},h));return this.resolveTouchLatency(T)}catch(T){return e.warn(`[PerformanceAudit] Failed to measure touch latency: ${T}`),null}}resolveTouchLatency(c){if(c.success){if(c.animating)e.warn(`[PerformanceAudit] Touch latency measured: ${c.latencyMs}ms (some samples were discounted as animating)`);else e.info(`[PerformanceAudit] Touch latency measured: ${c.latencyMs}ms`);return c.latencyMs}if(c.animating)e.warn("[PerformanceAudit] Touch latency measurement discarded: app is rendering frames on its own (animating) - latency cannot be attributed to the synthetic touch");else e.warn(`[PerformanceAudit] Touch latency measurement failed: ${c.error}`);return null}async calculateFrameRate(c,d){try{let{stdout:h}=await d.track("adbGfxinfoFrameRate",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),g=h.match(/Total frames rendered:\s*(\d+)/);if(!g)return null;let w=parseInt(g[1],10);if(w===0)return null;let C=(await this.capabilitiesDetector.getCapabilities()).refreshRate||60,T=h.match(/Janky frames:\s*(\d+)/),k=T?parseInt(T[1],10):0,D=this.idle.parseMetrics(h);if(D.percentile50th&&D.percentile50th>0){let F=1000/D.percentile50th;return Math.min(F,C)}if(k>0&&w>0){let M=w-k,F=1000/C,_=M*F+k*F*2,V=w*1000/_;return Math.min(V,C)}return C}catch(h){return e.warn(`[PerformanceAudit] Failed to calculate frame rate: ${h}`),null}}async measureTimeToFirstFrame(c,d){try{let h=await gi(this.adb),{stdout:g}=await d.track("adbLogcatTtff",()=>this.adb.executeCommand(`shell "logcat -d -s ${h}:I | grep -E 'Displayed.*'${b(c)} | tail -1"`));if(!g.trim())return e.debug("[PerformanceAudit] No TTFF data found in logcat"),null;let w=g.match(/\+\s*\d+(?:s\d+ms|ms|s)/);return w?bi(w[0]):null}catch(h){return e.warn(`[PerformanceAudit] Failed to measure TTFF: ${h}`),null}}async measureTimeToInteractive(c,d,h){try{let g=bp,w=Sp,A=wp,C=null,T=0;while(T<A){await h.track("adbGfxinfoTtiReset",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)} reset`,{maxBuffer:ie})),await i.sleep(g),T+=g;let{stdout:k}=await h.track("adbGfxinfoTtiAfter",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),D=this.idle.parseMetrics(k);if((D.missedVsync||0)>0||(D.slowUiThread||0)>0||(D.frameDeadlineMissed||0)>0){C=null;continue}if(C===null){C=T;continue}if(T-C>=w)return e.info(`[PerformanceAudit] TTI reached: ${d+C}ms`),d+C}return e.warn(`[PerformanceAudit] TTI measurement timed out after ${A}ms`),null}catch(g){return e.warn(`[PerformanceAudit] Failed to measure TTI: ${g}`),null}}validateMetrics(c,d){let h=[];if(this.appendPercentileViolations(h,c,d),c.jankCount!==null&&c.jankCount>d.jankCountThreshold)h.push({metric:"jankCount",threshold:d.jankCountThreshold,actual:c.jankCount,severity:"critical",contributionWeight:0.9});if(c.cpuUsagePercent!==null&&c.cpuUsagePercent>d.cpuUsageThresholdPercent)h.push({metric:"cpuUsage",threshold:d.cpuUsageThresholdPercent,actual:c.cpuUsagePercent,severity:"warning",contributionWeight:0.5});if(c.touchLatencyMs!==null&&c.touchLatencyMs>d.touchLatencyThresholdMs)h.push({metric:"touchLatency",threshold:d.touchLatencyThresholdMs,actual:c.touchLatencyMs,severity:"critical",contributionWeight:0.85});if(c.anrDetected)h.push({metric:"anr",threshold:0,actual:1,severity:"critical",contributionWeight:1});return h}appendPercentileViolations(c,d,h){if(d.p50Ms!==null&&d.p50Ms>h.p50ThresholdMs)c.push({metric:"p50",threshold:h.p50ThresholdMs,actual:d.p50Ms,severity:"warning",contributionWeight:0.6});if(d.p90Ms!==null&&d.p90Ms>h.p90ThresholdMs)c.push({metric:"p90",threshold:h.p90ThresholdMs,actual:d.p90Ms,severity:"warning",contributionWeight:0.7});if(d.p95Ms!==null&&d.p95Ms>h.p95ThresholdMs)c.push({metric:"p95",threshold:h.p95ThresholdMs,actual:d.p95Ms,severity:"critical",contributionWeight:0.8});if(d.p99Ms!==null&&d.p99Ms>h.p99ThresholdMs)c.push({metric:"p99",threshold:h.p99ThresholdMs,actual:d.p99Ms,severity:"warning",contributionWeight:0.4})}generateDiagnostics(c,d){if(d.length===0)return"No performance issues detected";let h=`Performance issues detected:
|
|
16
|
-
|
|
17
|
-
`,g=wW(d);h+=`Top contributors:
|
|
18
|
-
`;for(let C of g)h+=`- ${C.metric}: ${C.actual.toFixed(2)} (threshold: ${C.threshold.toFixed(2)}) [${C.severity}]
|
|
19
|
-
`;if(h+=`
|
|
20
|
-
Diagnostic details:
|
|
21
|
-
`,g.some((C)=>["p50","p90","p95","p99","jankCount"].includes(C.metric))&&c.gfxinfoRaw)h+=`
|
|
22
|
-
--- GFXINFO DUMP ---
|
|
23
|
-
`,h+=c.gfxinfoRaw,h+=`
|
|
24
|
-
--- END GFXINFO ---
|
|
25
|
-
`;if(g.some((C)=>C.metric==="cpuUsage")&&c.cpuStatsRaw)h+=`
|
|
26
|
-
--- CPU STATS ---
|
|
27
|
-
`,h+=`Thread count: ${c.threadCount}
|
|
28
|
-
`,h+=`CPU usage: ${c.cpuUsagePercent?.toFixed(2)}%
|
|
29
|
-
`,h+=c.cpuStatsRaw,h+=`
|
|
30
|
-
--- END CPU STATS ---
|
|
31
|
-
`;if(c.anrDetected&&c.anrDetails)h+=`
|
|
32
|
-
--- ANR DETECTED ---
|
|
33
|
-
`,h+=c.anrDetails,h+=`
|
|
34
|
-
--- END ANR ---
|
|
35
|
-
`;return h}async runAudit(c,d,h={}){let{screenSize:g,perf:w=new U,windowBounds:A,touchPoint:C,skipTouchLatency:T}=h;e.info(`[PerformanceAudit] Running audit for ${c}`);let k=ZL(this.device.deviceId),D=await this.capabilitiesDetector.getCapabilities(),M=await this.collectMetrics(c,g,w,{windowBounds:A,touchPoint:C,skipTouchLatency:T}),F=this.validateMetrics(M,d),_=F.length>0?this.generateDiagnostics(M,F):null,V=F.length===0,W=new Date().toISOString().split("T")[0];return await this.repository.recordAudit({deviceId:this.device.deviceId,sessionId:W,packageName:c,timestamp:new Date().toISOString(),passed:V,metrics:{p50Ms:M.p50Ms,p90Ms:M.p90Ms,p95Ms:M.p95Ms,p99Ms:M.p99Ms,jankCount:M.jankCount,missedVsyncCount:M.missedVsyncCount,slowUiThreadCount:M.slowUiThreadCount,frameDeadlineMissedCount:M.frameDeadlineMissedCount,cpuUsagePercent:M.cpuUsagePercent,touchLatencyMs:M.touchLatencyMs},diagnostics:_,deviceSessionUuid:k}),{passed:V,metrics:M,violations:F,diagnostics:_,deviceCapabilities:D}}}var Ri=m`datetime(created_at, '+' || ttl_hours || ' hours')`,Ci=m`datetime('now')`;class Pi{table;constructor(c){this.table=m.table(c)}async deleteExpired(c,d){let h=await m`
|
|
36
|
-
delete from ${this.table}
|
|
37
|
-
where ${Ri} < ${Ci}${this.andWhere(d)}
|
|
38
|
-
`.execute(c);return Number(h.numAffectedRows??0)}async selectValid(c,d){return(await m`
|
|
39
|
-
select * from ${this.table}
|
|
40
|
-
where ${Ri} >= ${Ci}${this.andWhere(d)}
|
|
41
|
-
order by created_at desc
|
|
42
|
-
`.execute(c)).rows}async insert(c,d){let h=Object.entries(d),g=m.join(h.map(([A])=>m.ref(A))),w=m.join(h.map(([,A])=>m.val(A)));await m`insert into ${this.table} (${g}) values (${w})`.execute(c)}async adjustLatestWeight(c,d,h,g){let w=h?m`min(weight * ${g.successMultiplier}, ${g.max})`:m`max(weight * ${g.failureMultiplier}, ${g.min})`,A=await m`
|
|
43
|
-
update ${this.table}
|
|
44
|
-
set weight = ${w}
|
|
45
|
-
where id = (
|
|
46
|
-
select id from ${this.table}
|
|
47
|
-
where ${Ri} >= ${Ci}${this.andWhere(d)}
|
|
48
|
-
order by created_at desc
|
|
49
|
-
limit 1
|
|
50
|
-
)
|
|
51
|
-
`.execute(c);return Number(A.numAffectedRows??0)}andWhere(c){return m.join(c.map((d)=>m` and ${m.ref(d.column)} = ${m.val(d.value)}`),m``)}}class xL{injectedDb;descriptor;repository;constructor(c,d){this.descriptor=c,this.repository=new Pi(c.tableName),this.injectedDb=d??null}get db(){return this.injectedDb??_e()}async cleanupExpiredThresholds(c,d,h=this.db){try{let g=await this.repository.deleteExpired(h,c);if(g>0)e.info(`[${this.descriptor.logPrefix}] Cleaned up ${g} expired thresholds for ${d}`)}catch(g){e.warn(`[${this.descriptor.logPrefix}] Failed to cleanup expired thresholds: ${g}`)}}async getValidThresholds(c,d,h,g=this.db){return await this.cleanupExpiredThresholds(d,h,g),await this.repository.selectValid(g,c)}calculateWeightedAverageThresholds(c){if(c.length===0)return null;let d={weight:yi.max/2,ttl_hours:WC.thresholdHours};for(let h of this.descriptor.modeColumns??[])d[h]=Ws(c.map((g)=>Number(g[h])))??60;for(let{column:h,round:g}of this.descriptor.weightedColumns){let w=Vs(c,(A)=>Number(A[h]),(A)=>A.weight);if(w===null)return null;d[h]=g?Math.round(w):w}return d}async storeThresholds(c,d,h=this.db){try{await this.repository.insert(h,c),e.info(`[${this.descriptor.logPrefix}] Stored new thresholds for ${d}`)}catch(g){throw e.error(`[${this.descriptor.logPrefix}] Failed to store thresholds: ${g}`),g}}async updateThresholdWeight(c,d,h){try{if(await this.cleanupExpiredThresholds(h.cleanupWhere??c,this.describeWhere(h.cleanupWhere??c)),await this.repository.adjustLatestWeight(this.db,c,d,yi)===0){e.warn(`[${this.descriptor.logPrefix}] ${h.missingMessage}`);return}e.debug(`[${this.descriptor.logPrefix}] ${h.updatedMessage}`)}catch(g){e.warn(`[${this.descriptor.logPrefix}] Failed to update threshold weight: ${g}`)}}describeWhere(c){return c.map((d)=>`${d.column} ${d.value}`).join(", ")}}var Rp={tableName:"performance_thresholds",logPrefix:"ThresholdManager",modeColumns:["refresh_rate"],weightedColumns:[{column:"frame_time_threshold_ms"},{column:"p50_threshold_ms"},{column:"p90_threshold_ms"},{column:"p95_threshold_ms"},{column:"p99_threshold_ms"},{column:"jank_count_threshold",round:!0},{column:"cpu_usage_threshold_percent"},{column:"touch_latency_threshold_ms"}]};class Ti{thresholds;constructor(c){this.thresholds=new xL(Rp,c)}get db(){return this.thresholds.db}getCurrentSessionId(){return new Date().toISOString().split("T")[0]}async cleanupExpiredThresholds(c){await this.cleanupExpiredThresholdsWith(this.db,c)}async cleanupExpiredThresholdsWith(c,d){await this.thresholds.cleanupExpiredThresholds(this.deviceWhere(d),`device ${d}`,c)}async getValidThresholds(c){return await this.getValidThresholdsWith(this.db,c)}async getValidThresholdsWith(c,d){return await this.thresholds.getValidThresholds(this.deviceWhere(d),this.deviceWhere(d),`device ${d}`,c)}calculateWeightedAverageThresholds(c){return this.thresholds.calculateWeightedAverageThresholds(c)}async getOrCreateThresholds(c,d){let h=this.db,g=async(C)=>{let T=await this.getValidThresholdsWith(C,c);if(T.length===0)return null;let k=this.calculateWeightedAverageThresholds(T);if(!k)return null;return e.info(`[ThresholdManager] Using weighted average of ${T.length} threshold entries for device ${c}`),{frameTimeThresholdMs:k.frame_time_threshold_ms,p50ThresholdMs:k.p50_threshold_ms,p90ThresholdMs:k.p90_threshold_ms,p95ThresholdMs:k.p95_threshold_ms,p99ThresholdMs:k.p99_threshold_ms,jankCountThreshold:k.jank_count_threshold,cpuUsageThresholdPercent:k.cpu_usage_threshold_percent,touchLatencyThresholdMs:k.touch_latency_threshold_ms}},w=async(C)=>{let T=await g(C);if(T)return T;e.info(`[ThresholdManager] Creating new thresholds for device ${c}`);let k=Le.calculateDefaultThresholds(d);return await this.storeThresholdsWith(C,c,d,{thresholds:k}),k};if(h.isTransaction)return w(h);return await g(h)??h.transaction().execute(w)}async storeThresholds(c,d,h,{weight:g=1,ttlHours:w=24}={}){await this.storeThresholdsWith(this.db,c,d,{thresholds:h,weight:g,ttlHours:w})}async storeThresholdsWith(c,d,h,{thresholds:g,weight:w=1,ttlHours:A=24}){let C=this.getCurrentSessionId(),T={device_id:d,session_id:C,refresh_rate:h.refreshRate,frame_time_threshold_ms:g.frameTimeThresholdMs,p50_threshold_ms:g.p50ThresholdMs,p90_threshold_ms:g.p90ThresholdMs,p95_threshold_ms:g.p95ThresholdMs,p99_threshold_ms:g.p99ThresholdMs,jank_count_threshold:g.jankCountThreshold,cpu_usage_threshold_percent:g.cpuUsageThresholdPercent,touch_latency_threshold_ms:g.touchLatencyThresholdMs,weight:w,ttl_hours:A};await this.thresholds.storeThresholds(T,`device ${d} session ${C}`,c)}async updateThresholdWeight(c,d,h){await this.thresholds.updateThresholdWeight([...this.deviceWhere(c),{column:"session_id",value:d}],h,{missingMessage:`No threshold found for device ${c} session ${d}`,updatedMessage:`Updated threshold weight (${h?"passed":"failed"})`})}deviceWhere(c){return[{column:"device_id",value:c}]}}var Aw="com.android.systemui",Ap="proud-lock",Yh=300,Pp=["NotificationCenter","NCNotification","NotificationList","NotificationShortLookView","NotificationLongLookView","PLPlatterView"],A3=["notification_panel","notification_stack","notification_stack_scroller","status_bar_expanded","quick_settings","quick_settings_panel","quick_settings_container","qs_panel","qs_frame","qs_header","shade_header","expanded_status_bar"],Ip=["NotificationPanel","NotificationShade","NotificationStack","QSPanel","QuickSettings","StatusBarExpanded"],et=(c)=>{if(!c||typeof c!=="object")return null;return we(c)},Mm=(c,d)=>{if(!c)return!1;if(d(c))return!0;let h=c.node;if(Array.isArray(h)){for(let g of h)if(Mm(g,d))return!0}else if(h&&typeof h==="object"){if(Mm(h,d))return!0}return!1},kp=new ve,qn=(c)=>{let d=new Set;return[...kp.project(c)].filter((h)=>h.parentIndex===void 0).sort((h,g)=>h.windowRank-g.windowRank||h.index-g.index).filter((h)=>{if(d.has(h.source))return!1;return d.add(h.source),!0}).map((h)=>h.source)},xp={notification_children_container:["com.android.systemui:id/notification_children_container"],notification_header:["android:id/notification_header","com.android.systemui:id/notification_header"],expand_button:["android:id/expand_button","android:id/expand_button_touch_container","com.android.systemui:id/expand_button"],status_bar_latest_event_content:["android:id/status_bar_latest_event_content"],notification_stack_scroller:["com.android.systemui:id/notification_stack_scroller"]},ed=(c,d)=>xp[d].some((h)=>c===h),T3=(c)=>{let d=String(c.packageName??c.package??"");if(d)return d===Aw;return pr(c).startsWith(`${Aw}:id/`)},Bte=(c)=>{let d=et(c);if(!d)return!1;let h=pr(d),g=String(d.className??d.class??"");if(!T3(d))return!1;let A=A3.some((T)=>h===`${Aw}:id/${T}`||h===T),C=Ip.some((T)=>g.includes(T));return A||C},PW=(c)=>qn(c).some((d)=>Mm(d,(h)=>pr(et(h))===Ap)),ta=(c)=>{let d=et(c);if(!d)return!1;return String(d.className??d.class??"")==="UIWindow"&&pr(d,["identifier"])==="SBCoverSheetWindow"&&Mm(c,(h)=>{let g=pr(et(h));return g==="combined-list-view"||g==="lockscreen-date-view"})},AW=(c)=>!PW(c)&&qn(c).some((d)=>Mm(d,ta)),$te=(c)=>{let d=et(c);if(!d)return!1;let h=String(d.className??d.class??""),g=hR(d,["content-desc","ios-accessibility-label"]),w=pr(d,["identifier"]);return ta(c)||Pp.some((A)=>h.includes(A)||g.includes(A)||w.includes(A))},k3=(c)=>pr(et(c)),Ute=1500,Hte=150,TW=["title","title_big","conversation_text","notification_title"];class Ii{observeScreen;appId;enclosingUpdatedAt;constructor(c,d,h){this.observeScreen=c;this.appId=d;this.enclosingUpdatedAt=h}async resolveInertTouchPoint(){try{let c=m9(this.enclosingUpdatedAt)+1,d=await this.observeScreen.execute({perf:new U,skipWaitForFresh:!1,minTimestamp:c,skipScreenshot:!0,skipBackStack:!0,skipAccessibilityAudit:!0,skipPerformanceAudit:!0});if(m9(d.updatedAt)<c)return e.warn("[PerformanceAudit] Re-observation did not yield a hierarchy newer than the enclosing observation; aborting inert-point re-derivation rather than reusing a stale capture"),null;if(d.activeWindow?.appId!==this.appId)return e.warn(`[PerformanceAudit] Foreground changed from ${this.appId} to ${d.activeWindow?.appId??"none"} during audit; aborting inert-point re-derivation`),null;let h=st(d,this.appId),{touchPoint:g,skipTouchLatency:w}=ki(h,d);if(w||!g)return null;return g}catch(c){return e.warn(`[PerformanceAudit] Failed to re-derive inert touch point: ${c}`),null}}}var Dp=1,Op="notification_permission_dialog";function Ep(c,d){if(!c.bounds||c.type!==Dp)return!1;return c.packageName===void 0||c.packageName===d}function st(c,d){let h=c.viewHierarchy?.windows;if(!h||h.length===0)return;let g=h.filter((A)=>Ep(A,d));return(g.find((A)=>A.isFocused)??g[0])?.bounds}var Mp=[{x:0.5,y:0.5},{x:0.25,y:0.25},{x:0.75,y:0.25},{x:0.25,y:0.75},{x:0.75,y:0.75},{x:0.5,y:0.08},{x:0.5,y:0.92},{x:0.08,y:0.5},{x:0.92,y:0.5}],Fp={x:0.5,y:0.95};function _p(c){return dt(c.clickable)||dt(c.focusable)||dt(c["long-clickable"])||kn(c.actions,"click")||kn(c.actions,"long_click")}function ca(c,d,h){return c>=h.left&&c<h.right&&d>=h.top&&d<h.bottom}function Np(c){return Number.isFinite(c.left)&&Number.isFinite(c.top)&&Number.isFinite(c.right)&&Number.isFinite(c.bottom)&&c.right-c.left>0&&c.bottom-c.top>0}function Bp(c,d,h=[]){let g=d.filter((T)=>T.bounds&&_p(T)),w=c.right-c.left,A=c.bottom-c.top,C=(T)=>({x:Math.floor(c.left+w*T.x),y:Math.floor(c.top+A*T.y)});for(let T of Mp){let k=C(T),D=g.some((F)=>ca(k.x,k.y,F.bounds)),M=h.some((F)=>ca(k.x,k.y,F));if(!D&&!M)return{point:k,inert:!0}}return e.warn("[PerformanceAudit] Could not find a fully inert touch point inside the app window (every scanned candidate overlapped an interactive element or content-hidden region) - falling back to a default point that may still activate a control"),{point:C(Fp),inert:!1}}function Hp(c,d=new K){if(!c.viewHierarchy)return c.elements?.clickable??[];return d.flattenViewHierarchy(c.viewHierarchy,{includeWindows:!0}).map((h)=>h.element)}function Lp(c){return(c.viewHierarchy?.contentHiddenRegions??[]).map((d)=>d.bounds)}var Vp=[(c)=>c?null:"no app window bounds were found",(c)=>c&&!Np(c)?"window bounds are malformed (zero-area, inverted, or non-finite): "+JSON.stringify(c):null,(c,d)=>d.viewHierarchy?.fresh===!1?"the view hierarchy is a stale cached snapshot (fresh: false), not verified against the device on this call":null,(c,d)=>d.viewHierarchy?.ctrlProxyIncomplete?"CtrlProxy reported an incomplete capture (ctrlProxyIncomplete) - the focused app's own root may have been withheld":null,(c,d)=>{let h=ib(d.viewHierarchy?.truncationReasons);return h.length>0?`view hierarchy is truncated (${h.join(", ")}) - the obstacle map may be incomplete`:null},(c,d)=>d.activeWindow?.appId===Aw?`a SystemUI overlay owns focus (activeWindow.appId === "${Aw}") - the app window beneath it cannot be safely probed`:null,(c,d)=>d.notificationPermissionDetected||d.activeWindow?.type===Op?"a notification-permission dialog owns the window - the underlying app's bounds/gfxinfo don't correspond to the same surface":null];function Up(c,d){for(let h of Vp){let g=h(c,d);if(g!==null)return g}return null}function ki(c,d,h=new K){let g=Up(c,d);if(g!==null||!c){if(g!==null)e.warn(`[PerformanceAudit] Skipping touch-latency measurement: ${g}`);return{skipTouchLatency:!0}}let w=Hp(d,h),A=Lp(d),{point:C,inert:T}=Bp(c,w,A);if(!T)return{skipTouchLatency:!0};return{touchPoint:C,skipTouchLatency:!1}}class CL{device;adbFactory;isEnabled;observeScreenProvider;constructor(c){this.device=c.device,this.adbFactory=c.adbFactory??v,this.isEnabled=c.isEnabled??zs,this.observeScreenProvider=c.observeScreenProvider}async run(c,d){if(!this.isEnabled())return;let h=this.device.platform;if(h!=="android"){e.debug("[PerformanceAudit] Skipping audit, only Android is supported");return}if(!c.activeWindow?.appId){e.debug("[PerformanceAudit] Skipping audit, no active app");return}try{await d.track("performanceAudit",async()=>{e.info(`[PerformanceAudit] Running UI performance audit for ${c.activeWindow?.appId}`);let g=new Le(this.device,this.adbFactory),w=new Ti,A=this.observeScreenProvider?.(),C=A?new Ii(A,c.activeWindow.appId,c.updatedAt):void 0,T=new wi(this.device,this.adbFactory,C),k=await g.getCapabilities(),D=await w.getOrCreateThresholds(this.device.deviceId,k),M=st(c,c.activeWindow.appId),{touchPoint:F,skipTouchLatency:_}=ki(M,c),V=await T.runAudit(c.activeWindow.appId,D,{screenSize:c.screenSize,perf:d,windowBounds:M,touchPoint:F,skipTouchLatency:_});c.performanceAudit=V;let W=new Date().toISOString().split("T")[0];if(await w.updateThresholdWeight(this.device.deviceId,W,V.passed),!V.passed)e.warn(`[PerformanceAudit] Performance audit FAILED with ${V.violations.length} violations`);else e.info("[PerformanceAudit] Performance audit PASSED");let{getPerformanceMonitor:G}=await import("./chunk-q9xmq595.js");G().startMonitoring(this.device.deviceId,c.activeWindow.appId,h)})}catch(g){e.error(`[PerformanceAudit] Failed to run performance audit: ${g}`)}}}var xi="android",da="android:id/aerr_";function la(c){if(!c.activeWindow?.appId||!c.elements)return!1;if(ue.has(c.activeWindow.appId))return!1;let h=st(c,c.activeWindow.appId)??{top:0,bottom:1/0,left:-1/0,right:1/0},g=c.systemInsets,w=Math.max(h.top,g.top),A=Math.min(h.bottom,(c.viewHierarchy?.screenHeight??1/0)-g.bottom),C=Math.max(h.left,g.left),T=Math.min(h.right,(c.viewHierarchy?.screenWidth??1/0)-g.right);return Object.values(c.elements).every((k)=>k.every(({bounds:D})=>D.bottom<=w||D.top>=A||D.right<=C||D.left>=T))}function Wp(c){return Boolean(c.activeWindow?.appId||c.viewHierarchy?.packageName||nt(c.viewHierarchy))}function Jh(c){if(!c.viewHierarchy?.hierarchy?.node)return;if(Mt(c))return{reason:"status_bar_only"};if(Wp(c))return;return{reason:"empty_active_window"}}function ua(c,d,h){if(c?.ctrlProxyIncomplete!==!0)return;if(h&&c.packageName===xi)return;let{packageName:g,ctrlProxyIncompleteReason:w}=c,A=d!==void 0&&g!==void 0&&g===d;if(A&&!yJ(w))return;return{sdkInt:c.sdkInt,reason:w,accessibilityTool:c.accessibilityTool,...A?{foregroundRead:!0}:{}}}function DL(c){let{freshness:d}=c;if(d?.isFresh===!1||d?.verified===!1||c.viewHierarchy?.fallbackToSpringboard===!0||Jh(c))return;return $p(c)}function $p(c){return c.activeWindow?.appId||c.viewHierarchy?.packageName||c.viewHierarchy?.foregroundActivity?.split("/")[0]||void 0}class Di{d;constructor(c){this.d=c}recordSingleDisplayTransition(c){let{result:d,observerMode:h,preserveDisplayState:g,explicitlyRouted:w,recordProvenance:A}=c;return!h&&!g&&!w&&Ce.record(this.d.device().deviceId,d,this.d.platformTraits().isIosMultiPanel()?"ios":"android",A)}reconcileSingleDisplayFreshness(c){let{result:d,recordProvenance:h}=c,g=Ce.revision(this.d.device().deviceId)!==h.revision,w=this.recordSingleDisplayTransition(c);return d.display.generation=g?h.identityRevision:Ce.identityRevision(this.d.device().deviceId),d.displayRevision=g?h.revision:Ce.revision(this.d.device().deviceId),{staleDisplay:g,geometryTransition:w}}async settleSingleDisplay(c,d,h){let{options:g,result:w,perf:A,signal:C,observerMode:T,preserveDisplayState:k}=c;await this.computeSingleDisplayFreshness(c,d,h);let{staleDisplay:D,geometryTransition:M}=this.reconcileSingleDisplayFreshness({result:w,observerMode:T,preserveDisplayState:k,explicitlyRouted:c.explicitlyRouted,recordProvenance:h.recordProvenance}),F=M?uo().currentGeneration(this.d.device().deviceId):c.cacheGeneration;if(this.d.device().platform==="android"&&(M||Ce.revision(this.d.device().deviceId)!==c.captureStart.revision))await this.resampleDeviceLock(w,C);if(this.d.identifyCapture(w,g?.freshness??"cached-ok"),c.iosLockState)Rt(w,await c.iosLockState);if(!D&&ho(c))await A.track("cacheResult",()=>uo().put(this.d.device().deviceId,w,F))}async resampleDeviceLock(c,d){delete c.deviceLock,delete c.deviceLockUnknown,await this.d.deviceStateCollector().collectDeviceLock(c,d)}async computeSingleDisplayFreshness(c,d,h){let{result:g,minTimestamp:w,signal:A,observerMode:C}=c,{foregroundIdentity:T}=d,{postCaptureForeground:k,getConfirmedFrameworkErrorDialog:D}=h,M=await this.d.windowIdentity().resolveStatusBarOnlyHierarchy(g,T,k,A);await this.d.windowIdentity().attributeFocusedOwnWindowToForeground(g,T,w);let F=await this.d.windowIdentity().resolveWindowIdentityMismatch(g,T,{postCaptureForeground:k,getConfirmedFrameworkErrorDialog:D,minTimestamp:w,signal:A});if(g.freshness=vR({requestedAfter:w>0?w:void 0,actualTimestamp:this.d.resolveObservationTimestampMs(g),hostAgeBasisMs:this.d.windowIdentity().resolveHostReceivedAtMs(g),now:this.d.timer().now(),verified:typeof g.viewHierarchy==="object"&&g.viewHierarchy!==null?g.viewHierarchy.fresh:void 0,...fo(c,h),missingForegroundWindow:Jh(g),statusBarOnlyHierarchy:M,windowIdentityMismatch:F,activityAttributionMismatch:k.activityAttributionMismatch,emptyFocusedWindow:this.d.device().platform==="android"&&la(g),incompleteCapture:await this.describeIncompleteSingleDisplay(c,h)}),F)bY(g);if(C&&g.freshness?.unavailableDetail)g.freshness.warning+=` ${g.freshness.unavailableDetail}`}async describeIncompleteSingleDisplay(c,d){let{viewHierarchy:h}=c.result,g=h?.ctrlProxyIncomplete===!0;return ua(h,g?await this.d.windowIdentity().confirmForegroundIdentity(d.postCaptureForeground,c.signal):void 0,g?await d.getConfirmedFrameworkErrorDialog():!1)}}var xT=0.02;function Gp(c,d,h){let{x:g,y:w}=c;switch(h){case 1:return{x:d.height-w,y:g};case 2:return{x:d.width-g,y:d.height-w};case 3:return{x:w,y:d.width-g};default:return c}}function kW(c,d,h){let{x:g,y:w}=c;switch(h){case 1:return{x:w,y:d.height-g};case 2:return{x:d.width-g,y:d.height-w};case 3:return{x:d.width-w,y:g};default:return c}}function EW(c,d){return d===1||d===3?{width:c.height,height:c.width}:c}function pa(c,d){let h=[{x:c.left,y:c.top},{x:c.right,y:c.top},{x:c.left,y:c.bottom},{x:c.right,y:c.bottom}].map(d);return{left:Math.min(...h.map((g)=>g.x)),top:Math.min(...h.map((g)=>g.y)),right:Math.max(...h.map((g)=>g.x)),bottom:Math.max(...h.map((g)=>g.y))}}function OL(c,d,h){return pa(c,(g)=>Gp(g,d,h))}function E3(c,d,h){return pa(c,(g)=>kW(g,d,h))}function ML(c,d,h){return{left:Math.max(0,Math.floor(c.left*d.x)),top:Math.max(0,Math.floor(c.top*d.y)),right:Math.min(h.width,Math.ceil(c.right*d.x)),bottom:Math.min(h.height,Math.ceil(c.bottom*d.y))}}function IW(c,d,h="snapshotOf"){let{width:g,height:w}=d.screenSize;if(![g,w].every((G)=>Number.isFinite(G)&&G>0))throw new t(`${h} requires finite, nonempty bounds and screen dimensions`);if([c.width,c.height].some((G)=>G<=0))throw new t(`${h} received an empty screenshot raster`);let C=d.platform==="ios"&&d.rasterOrientation!=="display"?d.rotation:0,T=[1,3].some((G)=>G===C)&&g>w&&c.width<c.height,k=C===2,[D,M]=T?[w,g]:[g,w],F=c.width/D,_=c.height/M;if(Math.abs(F-_)>xT)throw new t(`${h} screenshot and screen geometry have incompatible aspect ratios`);let V=[F,_].every((G)=>Math.abs((d.nativeScale??NaN)-G)<=xT)?"native-scale-confirmed":"raster-dimensions",W=[T,k].includes(!0)?"native":"display";return{pixelsPerNativeUnit:{x:F,y:_},scaleProvenance:V,quarterTurn:T,halfTurn:k,screenshotOrientation:W}}import*as qp from"fs/promises";import zp from"path";function Kp(c){let d=zp.extname(c).toLowerCase(),g={".png":"png",".jpg":"jpeg",".jpeg":"jpeg",".webp":"webp"}[d];if(!g)throw new t("Screenshot file has an unrecognized format.");return g}async function at(c,d,h,g={}){let{files:w=qp,timer:A=i,protection:C=$n}=g;await C.protect(c);let T=await w.stat(c);if(!T.isFile()||T.size===0)throw new t("Screenshot file is missing or empty.");let k=Number.isFinite(T.mtimeMs)?T.mtimeMs:A.now(),D=Kp(c),M=await C.protect(c);return{screenshotPath:c,screenshotExpiresAt:M,screenshotSource:d,screenshotCaptureSource:d==="fresh"?"device":"observation-cache",screenshotCapturedAt:new Date(k).toISOString(),screenshotAgeMs:Math.max(0,A.now()-k),screenshotFormat:D,screenshotMimeType:`image/${D}`,...h?{screenshotFreshFailure:{code:"SCREENSHOT_CAPTURE_FAILED",message:h,retryable:!0}}:{}}}class Oi{deps;constructor(c){this.deps=c}get device(){return this.deps.device()}get timer(){return this.deps.timer()}get screenshotRecorder(){return this.deps.screenshotRecorder()}get screenshotEvidenceFiles(){return this.deps.screenshotEvidenceFiles()}get pathProtection(){return this.deps.pathProtection()}async captureSettledScreenshot(c,d,h,{strict:g,displayId:w,screenshotOptions:A}){try{if(!this.screenshotRecorder.captureSettled)throw new t("Settled screenshot capture is unavailable");let C=await this.screenshotRecorder.captureSettled(c.observationId,{perf:d,signal:h,displayId:w,options:A}),T=await at(C,"fresh",void 0,{files:this.screenshotEvidenceFiles,timer:this.timer,protection:this.pathProtection});Object.assign(c,T);let k=Jr().getImageSizeForObservation(this.device.deviceId,c.observationId,C);await this.attachScreenshotRaster(c,k),this.refineIosPanelOrientation(c),c.screenshotSettled=!0}catch(C){if(h?.throwIfAborted(),g)throw new it(C,this.device.deviceId);c.screenshotSettled=!1,c.screenshotSettledError=r(C),e.warn(`[OBSERVE] Settled screenshot unavailable: ${c.screenshotSettledError}`,C)}}refineIosPanelOrientation(c){if(this.device.platform==="ios"&&(this.device.displays?.panels.length??0)>1){let d=c.screenshotImageSize;c.screenshotOrientation=d&&d.width>d.height===c.screenSize.width>c.screenSize.height?"display":"native"}}orientHierarchylessPanelToRaster(c,d){let{width:h,height:g}=c.screenSize;if(this.device.platform!=="ios"||Sc(c.viewHierarchy)||(this.device.displays?.panels.length??0)<2||![h,g].every((C)=>Number.isFinite(C)&&C>0))return!0;let w=(C,T)=>Math.abs(d.width/C-d.height/T)<=xT;if(w(h,g))return!0;if(w(g,h))return c.screenSize={...c.screenSize,width:g,height:h},c.rotation=bc(void 0,c.screenSize),!0;let A=`The ${c.display.role} panel screenshot (${d.width}x${d.height} px) fits neither orientation of its ${h}x${g} geometry, and no view hierarchy was available to confirm the rotation, so the screenshot raster scale is omitted. Observe from the session that owns the device to reconnect its hierarchy client, then retry.`;return e.warn(`[OBSERVE] ${A}`),ne(c,{phase:"screenshot",message:A}),!1}async attachScreenshotRaster(c,d){delete c.screenshotImageSize,delete c.screenshotPixelsPerNativeUnit,delete c.screenshotScaleProvenance;try{if(!d||![d.width,d.height].every((A)=>Number.isInteger(A)&&A>0)){e.warn("[OBSERVE] Could not read screenshot raster dimensions");return}c.screenshotImageSize={width:d.width,height:d.height};let h=c.viewHierarchy??{},g=te(this.device.platform,"Deriving the screenshot raster scale");if(!this.orientHierarchylessPanelToRaster(c,d))return;let w=IW(d,{platform:g,screenSize:c.screenSize,rotation:h.rotation??c.rotation,nativeScale:h.nativeScale,rasterOrientation:g==="ios"&&!((this.device.displays?.panels.length??0)>1&&d.width>d.height===c.screenSize.width>c.screenSize.height)?"native":"display"},"observe");c.screenshotPixelsPerNativeUnit=w.pixelsPerNativeUnit,c.screenshotScaleProvenance=w.scaleProvenance}catch(h){e.warn(`[OBSERVE] Could not derive screenshot raster scale: ${r(h)}`,h);return}}}function jp(c,d){return c?.key===d.key&&c.generation===d.generation}class Ei{deps;constructor(c){this.deps=c}get device(){return this.deps.device()}get adb(){return this.deps.adb()}get timer(){return this.deps.timer()}get requestedDisplay(){return this.deps.requestedDisplay()}get observedAndroidDisplayCache(){return this.deps.observedAndroidDisplayCache()}get screenshotService(){return this.deps.screenshotService()}get screenshotEvidenceFiles(){return this.deps.screenshotEvidenceFiles()}get pathProtection(){return this.deps.pathProtection()}settledScreenshots(){return this.deps.settledScreenshots()}async captureDeviceReadScreenshot(c,d,h,g={}){let{requireFreshScreenshot:w=!1,display:A=this.requestedDisplay}=g;c.screenshotCaptureAttempted=!0,c.screenshotOrientation=this.device.platform==="ios"?"native":"display";let C=await this.resolveReadDisplayId(c,{signal:d,display:A}),T={format:h?.format??"png",...h,displayId:C},k=this.screenshotService instanceof Mo?await this.screenshotService.executeObservationRead(T,d):await this.screenshotService.execute(T,d);if(d?.throwIfAborted(),k.success&&k.path){Object.assign(c,await at(k.path,"fresh",void 0,{files:this.screenshotEvidenceFiles,timer:this.timer,protection:this.pathProtection})),await this.settledScreenshots().attachScreenshotRaster(c,k.screenshotImageSize),c.screenshotSettled=!0;return}await this.handleDeviceReadScreenshotFailure(c,k.error??"Screenshot capture failed",C,w)}async handleDeviceReadScreenshotFailure(c,d,h,g){if(g)throw new t(`observe crop screenshot capture failed for device ${this.device.deviceId}: ${d}. Retry with a fresh settled capture.`);let w=this.eligibleCachedScreenshot(h,c.display);if(w)try{Object.assign(c,await at(w.path,"cached",d,{files:this.screenshotEvidenceFiles,timer:this.timer,protection:this.pathProtection})),await this.settledScreenshots().attachScreenshotRaster(c,w.imageSize)}catch(A){e.warn(`[OBSERVE] Cached screenshot unavailable: ${r(A)}`,A)}c.screenshotSettled=!1,c.screenshotSettledError=d}async resolveReadDisplayId(c,d={}){let{signal:h,display:g=this.requestedDisplay}=d;if(this.device.platform!=="android"||!g||g==="active")return;let w=Ai(this.device,g,{}),A=await this.observedAndroidDisplayCache.logicalIdForPanel(this.device,this.adb,w.key,h);return c.display={...c.display,key:w.key,role:w.role},A}eligibleCachedScreenshot(c,d){let h=uo().getRecentInMemoryForDevice(this.device.deviceId);if(!this.cachedScreenshotDisplayMatches(h,c,d))return;if(h?.screenshotPath)return{path:h.screenshotPath,imageSize:h.screenshotImageSize};let g=this.deviceWideScreenshotPath(c);return g?{path:g}:void 0}deviceWideScreenshotPath(c){return!Boolean(this.requestedDisplay&&this.requestedDisplay!=="active")&&c===void 0&&!this.hasMultiplePanels()?Jr().getPath(this.device.deviceId):void 0}hasMultiplePanels(){return(this.device.displays?.panels.length??0)>1}cachedScreenshotDisplayMatches(c,d,h){let g=[void 0,"active",c?.display.key,c?.display.role].includes(this.requestedDisplay),w=[void 0,c?.viewHierarchy?.displayId].includes(d),A=!this.hasMultiplePanels()||jp(c?.display,h);return g&&w&&A}}async function ma(c,d,h){if(d?.packageName!==xi)return!1;let g=new K,w=!1,A=!1,C=!1,T=!1,k=!1,D=!1;for(let F of g.extractRootNodes(d))g.traverseNode(F,(_)=>{let V=g.extractNodeProperties(_),W=V["resource-id"]??V.resourceId;w||=typeof W==="string"&&W.startsWith(da),A||=W===ir,C||=W===ar,T||=W===or;let G=V.text??V["content-desc"];k||=typeof G==="string"&&/\b(?:isn't|is not) responding\b/i.test(G),D||=G==="Wait"});if(!(w||k&&D||A&&C&&T))return!1;try{let{stdout:F}=await c.executeCommand('shell "dumpsys window"',{signal:h});return/mCurrentFocus=Window\{[^}\r\n]*Application (?:Error:|Not Responding)/.test(F)}catch(F){return e.debug("Failed to read focused framework window from dumpsys:",F),!1}}class Mi{deps;constructor(c){this.deps=c}get timer(){return this.deps.timer()}get device(){return this.deps.device()}get viewHierarchy(){return this.deps.viewHierarchy()}get deviceStateCollector(){return this.deps.deviceStateCollector()}get hierarchyPlatform(){return te(this.device.platform,"Observing the view hierarchy")}get platformValidator(){return this.deps.platformValidator()}get reconciler(){return this.deps.reconciler()}async refreshKnownStaleHierarchy(c,d,h,{remainingMs:g,sideSamples:w}){let A=this.timer.now(),C=await this.readIndependentHierarchy(c.viewHierarchy?.updatedAt,h?.signal,g,"Known-stale hierarchy refresh");if(C?.fresh===!0&&Sc(C)&&C.packageName===d&&this.platformValidator.validate(this.hierarchyPlatform,C).valid)await this.reconciler.primeRecapturedHierarchy?.(c,C,h?.signal),this.reconciler.applyRecapturedHierarchy(c,C),this.reconciler.recorrelateActiveWindowToRecapture(c,C),delete c.backStack,delete c.deviceLock,delete c.deviceLockUnknown,await this.resampleAfterStaleWindowRecovery(c,{...w,signal:h?.signal,budgetMs:g-(this.timer.now()-A)})}async resampleAfterStaleWindowRecovery(c,d){let{skipBackStack:h,displayId:g,signal:w,budgetMs:A}=d;if(A<=0)return;let C={...c,deviceLock:void 0,deviceLockUnknown:void 0,backStack:void 0,errors:void 0},T=new AbortController,k=w?AbortSignal.any([w,T.signal]):T.signal;try{await l(Promise.all([this.deviceStateCollector.collectDeviceLock(C,k),h?Promise.resolve():this.deviceStateCollector.collectBackStack(C,new U,k,g)]),{timer:this.timer,timeoutMs:A,signal:w,label:"Stale-window side-sample refresh",onTimeout:()=>T.abort()})}catch(D){o(w),e.warn(`[StaleHierarchyRecovery] Stale-window side-sample refresh failed: ${r(D)}`,D);return}if(C.deviceLockUnknown)c.deviceLockUnknown=C.deviceLockUnknown;if(C.deviceLock)c.deviceLock=C.deviceLock;if(C.backStack)c.backStack=C.backStack;for(let D of C.errors??[])ne(c,D)}async verifyCachedAndroidHierarchy(c,d){let h=c.viewHierarchy;if(!h||!this.needsCachedVerification(h,d))return;let g=this.timer.now(),w=await this.readIndependentHierarchy(h.updatedAt,d.signal,d.remainingMs,"Cached hierarchy verification");if(!w||!this.isVerifyingReplacement(w,h))return;let A=Ns(w,c.activeWindow);if(await this.reconciler.primeRecapturedHierarchy?.(c,w,d.signal),this.reconciler.applyRecapturedHierarchy(c,w),!A)this.reconciler.recorrelateActiveWindowToRecapture(c,w),delete c.backStack,delete c.deviceLock,delete c.deviceLockUnknown,await this.resampleAfterStaleWindowRecovery(c,{...d.sideSamples,signal:d.signal,budgetMs:d.remainingMs-(this.timer.now()-g)})}needsCachedVerification(c,d){return d.eligible&&this.device.platform==="android"&&c.fresh!==!0&&Sc(c)&&d.remainingMs>0}isVerifyingReplacement(c,d){return c.fresh===!0&&Sc(c)&&c.packageName===d.packageName&&this.platformValidator.validate(this.hierarchyPlatform,c).valid}async readIndependentHierarchy(c,d,h,g){let w=new AbortController,A=d?AbortSignal.any([d,w.signal]):w.signal;try{return await l(()=>this.viewHierarchy.getViewHierarchy({},{perf:new U,skipWaitForFresh:!0,minTimestamp:Math.max(1,c??1),signal:A,timeoutMs:h,requireFreshExtraction:!0}),{timer:this.timer,timeoutMs:h,signal:d,label:g,onTimeout:()=>w.abort()})}catch(C){o(d),e.warn(`[StaleHierarchyRecovery] ${g} failed: ${r(C)}`,C);return}}}async function ha(c,d,h=Qo){if(!c.success)throw new t(`Screenshot capture failed for device ${d}: ${c.error??"no error details"}`);if(!c.path)throw new t(`Screenshot capture succeeded for device ${d} but returned no file path.`);if(!await h(c.path))throw new t(`Screenshot capture succeeded for device ${d} but the file is missing: ${c.path}`);return c.path}var Xp=2;class _i{pathProtection;device;screenshotUtil;store;completionByJob=new Map;observationResultCountByJob=new Map;constructor(c,d,h=Jr(),g=$n){this.pathProtection=g;this.device=c,this.screenshotUtil=d,this.store=h}start(c,{perf:d=new U,signal:h,displayId:g,capture:w}={}){this.store.beginObservation(this.device.deviceId,c),d.startOperation("screenshot");let A=this.screenshotUtil.startTrackedCapture(Fi(g,w),{parentSignal:h,coalesceWithPending:!0,queueAfterPendingIfRunning:!0,onComplete:async(C)=>{if(this.completionByJob.set(C.jobId,{aborted:C.aborted,isLatest:C.isLatest}),!C.isLatest){this.store.endObservation(this.device.deviceId,c,tE);return}if(C.aborted){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,c,rP);return}try{await this.handleScreenshotResult(C.result,{ignoreCancel:!0})}catch(T){e.warn(`[OBSERVE] Failed to finalize screenshot capture: ${T}`)}}});this.recordObservationResult(A,c),A.promise.finally(()=>{d.endOperation("screenshot")}).catch((C)=>{e.debug(`[OBSERVE] Screenshot completion rejected: ${r(C)}`)})}async capture(c,{perf:d=new U,signal:h,displayId:g,capture:w}={}){this.store.beginObservation(this.device.deviceId,c),await this.captureWithOptions(c,d,h,{trackerOptions:{coalesceWithPending:!0,queueAfterPendingIfRunning:!0},request:Fi(g,w)})}async captureFresh(c,{perf:d=new U,signal:h,displayId:g,capture:w}={}){this.store.beginObservation(this.device.deviceId,c),await this.captureWithOptions(c,d,h,{trackerOptions:{queueAfterPending:!0},request:Fi(g,w)})}async captureSettled(c,{perf:d=new U,signal:h,displayId:g,options:w}={}){this.store.beginObservation(this.device.deviceId,c);try{return await d.track("screenshot",async()=>{for(let A=0;A<Xp;A++){let{result:C,cancelled:T}=await this.captureSettledAttempt(h,g,w);if(T&&A===0&&!h?.aborted){e.debug("[OBSERVE] Retrying screenshot cancelled by another capture");continue}if(C.path)await this.pathProtection.protect(C.path);let k=await ha(T?{success:!1,error:C.error??Ye}:C,this.device.deviceId);return this.store.update(this.device.deviceId,k),this.store.updateForObservation(this.device.deviceId,c,{path:k,imageSize:C.screenshotImageSize}),k}throw new t("Screenshot capture retry exhausted")})}catch(A){let C=r(A);throw this.store.updateForObservation(this.device.deviceId,c,{error:C}),e.warn(`[OBSERVE] Settled screenshot capture failed: ${C}`),u(A,`Failed to capture screenshot for device ${this.device.deviceId}`)}}async captureSettledAttempt(c,d,h){let g=this.screenshotUtil.startTrackedCapture({...h,format:h?.format??"png",displayId:d},{parentSignal:c,queueAfterPending:!0});Pe.registerCompletionReader(g.jobId);try{let w=await g.promise,A=Pe.getCompletion(g.jobId);return{result:w,cancelled:g.signal.aborted||A?.aborted===!0||A?.isLatest===!1||w.error?.includes(Ye)===!0}}finally{Pe.releaseCompletionReader(g.jobId)}}async captureWithOptions(c,d,h,{trackerOptions:g,request:w}){try{await d.track("screenshot",async()=>{let A=this.screenshotUtil.startTrackedCapture(w,{parentSignal:h,...g,onComplete:async(T)=>{if(this.completionByJob.set(T.jobId,{aborted:T.aborted,isLatest:T.isLatest}),!T.isLatest){this.store.endObservation(this.device.deviceId,c,tE);return}if(T.aborted){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,c,rP);return}try{await this.handleScreenshotResult(T.result,{ignoreCancel:!0})}catch(k){e.warn(`[OBSERVE] Failed to finalize screenshot capture: ${k}`)}}}),C=this.recordObservationResult(A,c);await A.promise,await C})}catch(A){let C=r(A);if(C.includes(Ye)){e.debug("[OBSERVE] Screenshot capture cancelled");return}this.store.update(this.device.deviceId,void 0,C),this.store.updateForObservation(this.device.deviceId,c,{error:C}),e.warn(`[OBSERVE] Screenshot capture failed: ${C}`)}}async handleScreenshotResult(c,d={}){let h=(w,A)=>{if(d.updateDeviceWide!==!1)this.store.update(this.device.deviceId,w,A);if(d.observationId)this.store.updateForObservation(this.device.deviceId,d.observationId,{path:w,error:A,imageSize:c.screenshotImageSize})};if(!c.success){let w=c.error||"Failed to capture screenshot";if(d.ignoreCancel&&w.includes(Ye)){if(e.debug("[OBSERVE] Screenshot capture cancelled"),d.observationId)this.store.endObservation(this.device.deviceId,d.observationId,rP);return}h(void 0,w),e.warn(`[OBSERVE] Screenshot capture failed: ${w}`);return}if(!c.path){h(void 0,"Screenshot capture returned no file path"),e.warn("[OBSERVE] Screenshot capture succeeded but no file path was returned");return}if(await this.pathProtection.protect(c.path),!await Qo(c.path)){h(void 0,"Screenshot file missing after capture"),e.warn(`[OBSERVE] Screenshot capture reported success but file missing: ${c.path}`);return}h(c.path)}recordObservationResult(c,d){Pe.registerCompletionReader(c.jobId),this.observationResultCountByJob.set(c.jobId,(this.observationResultCountByJob.get(c.jobId)??0)+1);let h=!1,g=()=>{if(h)return;h=!0,Pe.releaseCompletionReader(c.jobId);let w=(this.observationResultCountByJob.get(c.jobId)??1)-1;if(w<=0){this.observationResultCountByJob.delete(c.jobId),this.completionByJob.delete(c.jobId);return}this.observationResultCountByJob.set(c.jobId,w)};return c.promise.then(async(w)=>{let A=Pe.getCompletion(c.jobId)??this.completionByJob.get(c.jobId);if(g(),!A||A.aborted||!A.isLatest){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,d,A?.isLatest===!1?tE:rP);return}await this.handleScreenshotResult(w,{ignoreCancel:!0,observationId:d,updateDeviceWide:!1})}).catch((w)=>{g();let A=r(w);this.store.updateForObservation(this.device.deviceId,d,{error:A}),e.warn(`[OBSERVE] Failed to record screenshot for observation ${d}: ${A}`)})}}function Fi(c,d){return d?.hidePrototypes===!0?{displayId:c,hidePrototypes:!0}:{displayId:c}}function Yp(c){return typeof c==="number"?{timeoutMs:c}:c}class Ni{opts;constructor(c){this.opts=c}reportTransportFailureIfAny(c,d){if(c!=="android"||d.hierarchy?.transportFailure!==!0)return;try{this.opts.onAvailabilityLost?.(`CtrlProxy hierarchy connection lost: ${d.hierarchy.error??"transport failure"}`)}catch(h){e.warn("[HierarchyCollector] Failed to report lost availability:",h)}}async collect(c,d={}){let{queryOptions:h,perf:g=new U,skipWaitForFresh:w=!1,minTimestamp:A=0,signal:C,readOnly:T=!1,capturedHierarchy:k,readOptions:D}=d,{device:M,viewHierarchy:F,adb:_,timer:V}=this.opts;try{if(M.platform==="android"&&!T)await F.configureRecompositionTracking(!0,g,C);let W=V.now(),G=k??await F.getViewHierarchy(h,{perf:g,skipWaitForFresh:w,minTimestamp:A,signal:C,...Yp(D)});if(e.debug("Accessibility service availability cached as: true"),G)this.attachHierarchy(c,G,F,M);e.debug(`View hierarchy retrieval took ${V.now()-W}ms`)}catch(W){e.warn("Failed to get view hierarchy:",W);try{le.getInstance(M,{create:()=>_}).clearAvailabilityCache()}catch(G){e.debug(`[HierarchyCollector] Failed to clear availability cache: ${G}`)}this.reportHierarchyError(c,M,W)}}reportHierarchyError(c,d,h){let g=String(h);if(d.platform==="android"&&(g.includes(Oo)||g.includes("Failed to connect to accessibility service")))try{this.opts.onAvailabilityLost?.(`CtrlProxy hierarchy connection lost: ${g}`)}catch(w){e.warn("[HierarchyCollector] Failed to report lost availability:",w)}if(g.includes("null root node returned by UiTestAutomationBridge")||g.includes("cat:")&&g.includes("No such file or directory")||g.includes("screen appears to be off"))ne(c,{phase:"viewHierarchy",message:"Screen appears to be off or device is locked",cause:g});else ne(c,{phase:"viewHierarchy",message:"Failed to retrieve view hierarchy",cause:g})}attachHierarchy(c,d,h,g){if(c.viewHierarchy=d,this.reportTransportFailureIfAny(g.platform,d),d.updatedAt)c.updatedAt=d.updatedAt,e.debug(`Using updatedAt from view hierarchy: ${d.updatedAt}`);this.attachFocusedElements(c,d,h);try{let w=d.intentChooserDetected;if(c.intentChooserDetected=w,w)e.debug("[ObserveScreen] Intent chooser dialog detected in view hierarchy")}catch(w){e.warn(`[ObserveScreen] Failed to detect intent chooser: ${w}`)}if(d.notificationPermissionDetected!==void 0){if(c.notificationPermissionDetected=d.notificationPermissionDetected,d.notificationPermissionDetected)e.debug("[ObserveScreen] Notification permission dialog detected in view hierarchy")}}attachFocusedElements(c,d,h){let g=h.findFocusedElement(d);if(g)c.focusedElement=g,e.debug(`Found focused element: ${g.text||g["resource-id"]||"no text/id"}`);let w=h.findAccessibilityFocusedElement(d);if(w)c.accessibilityFocusedElement=w,e.debug(`Found accessibility-focused element: ${w.text||w["resource-id"]||w["content-desc"]||"no text/id/desc"}`)}async collectRaw(c,d,h){let{device:g,adbFactory:w,timer:A}=this.opts;try{if(g.platform==="android"){let C=(this.opts.androidRawClient??((k,D)=>E.getInstance(k,D)))(g,w),T=await C.requestHierarchySync(new U,!0,d,{displayId:h});if(h===void 0||h===0)C.invalidateCache();if(T?.hierarchy)c.rawViewHierarchy={json:JSON.stringify(T.hierarchy,null,2),source:"accessibility-service",timestamp:A.now(),device:{deviceId:g.deviceId,platform:g.platform}}}else{let C=x.getInstance(g),T=await C.requestHierarchySync(new U,!0,d);if(C.invalidateCache(),T?.hierarchy)c.rawViewHierarchy={xcuitest:JSON.stringify(T.hierarchy,null,2),source:"xcuitest",timestamp:A.now(),device:{deviceId:g.deviceId,platform:g.platform}}}}catch(C){e.warn("[ObserveScreen] Failed to collect raw view hierarchy:",C)}}extractScreenSize(c,d=!1){return c?cO(c,d):null}reconcileScreenDimensions(c,d){if(!c||typeof c==="string")return c;if(!d||d.width<=0||d.height<=0)return c;return c.screenWidth=d.width,c.screenHeight=d.height,c}}function fa(c){let d=/^\s*Current Driving State:\s*(\d+)\s*$/m.exec(c)?.[1];return d==="0"?"parked":d==="1"?"idling":d==="2"?"moving":void 0}function ya(c,d){for(let h of c.matchAll(/^\s*Display id:\s*(\d+)\s+UXR:\s*DO:\s*(true|false)\s+UxR:\s*(\d+)\s+time:/gm))if(Number(h[1])===d&&Number.isSafeInteger(Number(h[3])))return{requiresDistractionOptimization:h[2]==="true",activeRestrictions:Number(h[3])};return}function va(c,d){let h=c.trim().split(/\r?\n/).map((w)=>w.trim());if(h[0]===`No DO Activities for ${d}`)return new Set;if(h[0]!==`DO Activities for ${d}`)return;let g=h.slice(1).filter((w)=>w.length>0);if(g.some((w)=>!/^[\w$]+(?:\.[\w$]+)+$/.test(w)))return;return new Set(g)}async function sa(c,d,h,{timeoutMs:g,signal:w}={}){let A=await c.executeCommand(`shell pm list packages --user ${h}`,{timeoutMs:g,noRetry:!0,signal:w});return ji(A.stdout,d)}class Nm extends Error{details;constructor(c,d={kind:"unavailable",users:[]}){super(c);this.details=d}}class It{adb;constructor(c){this.adb=c}async resolve(c={}){if(c.explicitUserId!==void 0)return{userId:c.explicitUserId,source:"explicit"};if(c.currentUser){let A=await this.adb.executeCommand("shell am get-current-user",{noRetry:!0,signal:c.signal}),C=Number.parseInt(A.stdout.trim(),10);if(Number.isSafeInteger(C)&&C>=0)return{userId:C,source:"currentUser"}}let d=c.packageName?await this.readForeground(c):void 0;if(d?.match)return d.match;let h=await this.adb.listUsers(c.signal),g=await this.installedCandidates(c,h);return{...g!==h&&g.length===1?{userId:g[0].userId,source:"installedUser"}:this.selectDefaultUser(g,h),...d?.extra}}async readForeground(c){let d=await this.adb.getForegroundApp(c.signal),h=c.includeForegroundApp?{foregroundApp:d}:void 0;if(d&&d.packageName===c.packageName)return{match:{userId:d.userId,source:"foregroundPackage",...h}};return{extra:h}}selectDefaultUser(c,d){let h=c.filter((w)=>w.running&&(w.profileType??Fl(w.flags))==="managed");if(h.length===1)return{userId:h[0].userId,source:"managedProfile"};if(h.length>1)throw new Nm(`Android target user is ambiguous: ${h.length} managed profiles are running`,{kind:"ambiguous",users:d});let g=c.find((w)=>w.running&&(w.profileType??Fl(w.flags))==="primary");if(g)return{userId:g.userId,source:"primary"};throw new Nm("Android target user is unavailable: no running primary or uniquely selectable managed profile",{kind:"unavailable",users:d})}async installedCandidates(c,d){if(!c.installedOnly||!c.packageName||c.currentUser)return d;let h=d.filter((w)=>w.running);if(h.length<=1)return d;let g=[];for(let w of h)if(await sa(this.adb,c.packageName,w.userId,{signal:c.signal}))g.push(w);if(g.length>0)return g;return e.info(`Android app ${c.packageName} is not installed for any running user; checked users: ${h.map((w)=>w.userId).join(", ")}`),d}}async function oe(c,d,h){let g=await c.execute(["shell",...d],{signal:h});if(g.error)throw new t(`adb shell ${d.join(" ")} failed: ${g.error}`);return g.stdout.replace(/\r\n?/g,`
|
|
52
|
-
`).trim()}function Ge(c){throw new t(`unsupported on this image: ${c}`)}function er(c,d,h){throw new t(`Invalid ${c} value '${d}'. Expected one of: ${h.join(", ")}.`)}async function Da(c,d,h){let g=await c.execute([...d],{signal:h});if(g.error)throw new t(`adb ${d.join(" ")} failed: ${g.error}`);return`${g.stdout}
|
|
53
|
-
${g.stderr}`.replace(/\r\n?/g,`
|
|
54
|
-
`).trim()}function Qn(){let c=Promise.resolve();return(d)=>{let h=c.then(d,d);return c=h.catch(()=>{return}),h}}var Xh=(c)=>(d,h)=>new It(c).resolve({packageName:d,installedOnly:!0,signal:h}).then((g)=>g.userId);function _W(c){let d=c?.currentActivity;if(d?.name!=="com.android.systemui.car.activity.ActivityBlockingActivity")return;let h=c?.activities??[],g=h.findIndex((A)=>A.name===d.name&&A.taskId===d.taskId),w=g<0?void 0:h.slice(g+1).find((A)=>A.taskId!==d.taskId);return{blockedBy:d.name,...w?{blockedActivity:w.name}:{}}}class Bi{opts;constructor(c){this.opts=c}async collectAutomotive(c,d,h=0){if(this.opts.device.formFactor!=="automotive")return;let[g,w]=await Promise.all([this.readAutomotive(["dumpsys","car_service","--services","CarDrivingStateService"],d),this.readAutomotive(["dumpsys","car_service","--services","CarUxRestrictionsManagerService"],d)]),A=fa(g),C=ya(w,h);c.automotive={...A!==void 0?{drivingState:A}:{},...C?{uxRestrictions:C}:{},blocked:!1},await this.refreshAutomotiveForegroundActivity(c,d)}async refreshAutomotiveForegroundActivity(c,d){let h=c.automotive;if(!h)return;let g=await this.readForegroundDistractionOptimized(c,d),{drivingState:w,uxRestrictions:A}=h,C=EL(c),T=_W(c.backStack);c.automotive={...w!==void 0?{drivingState:w}:{},...A?{uxRestrictions:A}:{},...g!==void 0?{foregroundActivity:{distractionOptimized:g}}:{},blocked:T!==void 0||A?.requiresDistractionOptimization===!0&&g===!1,...T,...C?{hostRenderedUi:C}:{}}}async readForegroundDistractionOptimized(c,d){let{appId:h,activityName:g}=c.activeWindow??{};if(!h||!g)return;return va(await this.readAutomotive(["cmd","car_service","get-do-activities",h],d),h)?.has(g.replace(/^\./,`${h}.`))}async readAutomotive(c,d){try{return await oe(this.opts.adb,c,d)}catch(h){return e.warn("Failed to read automotive observation state:",h),""}}async collectWakefulness(c,d){let{adb:h}=this.opts;try{let g=await h.getWakefulness(d);if(g)c.wakefulness=g,c.wakefulnessSource="adb"}catch(g){e.warn("Failed to get wakefulness state:",g)}}async collectDeviceLock(c,d){let{adb:h}=this.opts;try{let g=await h.getDeviceLock(d);if(g)c.deviceLock=g}catch(g){e.warn("Failed to get device lock state:",g)}}async collectBackStack(c,d=new U,h,g=0){let{backStack:w,timer:A}=this.opts;try{let C=A.now(),T=await w.execute(d,h,g);c.backStack=T,e.debug(`Back stack retrieval took ${A.now()-C}ms`)}catch(C){e.warn("Failed to get back stack:",C),ne(c,{phase:"backStack",message:"Failed to retrieve back stack information",cause:String(C)})}}async collectForegroundIdentity(c,d={}){return(await this.collectForegroundSnapshot(c,d))?.packageName??void 0}async collectForegroundSnapshot(c,d={}){let{adb:h}=this.opts;try{return await h.getForegroundApp(c,{displayId:d.displayId??0})}catch(g){if(c?.aborted)e.debug("Failed to get ground-truth foreground app:",g);else e.warn("Failed to get ground-truth foreground app:",g);return null}}async collectFocusedSystemUiSurface(c){let{adb:d}=this.opts;try{let{stdout:h}=await d.executeCommand('shell "dumpsys window"',{signal:c});return Uie(h)}catch(h){return e.debug("Failed to read focused window surface from dumpsys:",h),!1}}async collectActiveWindow(c,d=!1){let{window:h,timer:g}=this.opts;try{let w=g.now(),A=d?await h.getActive(!0,void 0,{cacheResult:!1}):await h.getActive(!0);if(e.debug(`Bootstrap active window retrieval took ${g.now()-w}ms`),A)c.activeWindow=A}catch(w){e.warn("Failed to get bootstrap active window:",w),ne(c,{phase:"activeWindow",message:"Failed to retrieve active window information",cause:String(w)})}}}import Sm from"crypto";function Lt(c){let d=c.textSize;return typeof d==="number"&&Number.isFinite(d)&&d>0?d:null}var ga=new WeakMap;function ba(c){let d=ga.get(c);if(!d){let h=c.width+1;d=new Int32Array(h*(c.height+1));for(let g=0;g<c.height;g++){let w=0;for(let A=0;A<c.width;A++)w+=c.data[(c.width*g+A)*4+3]===255?1:0,d[(g+1)*h+A+1]=d[g*h+A+1]+w}ga.set(c,d)}return d}function Sa(c,d,{x:h,y:g,radius:w}){let A=Math.round(co(h-w,0,c.width-1)),C=Math.round(co(h+w,0,c.width-1)),T=Math.round(co(g-w,0,c.height-1)),k=Math.round(co(g+w,0,c.height-1)),D=c.width+1;return d[(k+1)*D+C+1]-d[T*D+C+1]-d[(k+1)*D+A]+d[T*D+A]>0}function Hi(c,d){return d.left>=0&&d.top>=0&&d.right<=c.width&&d.bottom<=c.height}var Jp=6,Qp=20,Zp=2,em=10,Vt=8,tm=256,rm=0.5,im=30,Ut=12;function wa(c,d){return Ae(c,d)<=20}function Ae(c,d){let h=c.r-d.r,g=c.g-d.g,w=c.b-d.b;return Math.sqrt(h*h+g*g+w*w)}class Li{resolve;constructor(c){this.resolve=c}isGlyphPixel(c,d,h,{color:g,point:w}){let{x:A,y:C}=w,T=Ae(g,h.textColor)<=im;if(!T&&wa(this.resolve(c,A,C),h.textColor)&&this.isFringeNear(c,d,w,{color:g,...h}))return!0;if(!T||Ae(g,h.textColor)>=Ae(g,h.backgroundColor))return!1;return[[Ut,0],[-Ut,0],[0,Ut],[0,-Ut]].filter(([D,M])=>wa(this.resolve(c,co(A+D,d.left,d.right-1),co(C+M,d.top,d.bottom-1)),h.backgroundColor)).length>=3}isFringeNear(c,d,h,{color:g,textColor:w,backgroundColor:A}){return this.isFringe(c,{left:Math.max(d.left,h.x-Vt),top:Math.max(d.top,h.y-Vt),right:Math.min(d.right,h.x+Vt),bottom:Math.min(d.bottom,h.y+Vt)},g,{text:w,background:A})}*levelPixels(c,d,h){let g=Math.ceil(d.left),w=Math.ceil(d.top),A=Math.ceil(d.right)-1,C=Math.ceil(d.bottom)-1;for(let T=w;T<=C;T++)for(let k=g;k<=A;k++)if(Ae(this.resolve(c,k,T),h)<=Zp)yield{x:k,y:T}}isFringe(c,d,h,{text:g,background:w}){if(!this.isAntiAliasingBlend(h,w,g))return!1;let A=Ae(h,g),C=Ae(h,w),T=(V,W)=>V>=0&&W>=0&&V<c.width&&W<c.height?this.resolve(c,V,W):null,k=(V)=>V!==null&&Ae(V,g)<A-Qp,D=(V)=>V!==null&&Ae(V,w)<C-em,M=(V,W,G,q)=>[1,2,3].some((X)=>k(T(V+G*X,W+q*X)))&&[1,2,3].some((X)=>D(T(V-G*X,W-q*X))),F=0,_=0;for(let V of this.levelPixels(c,d,h)){if(F++,M(V.x,V.y,1,0)||M(V.x,V.y,-1,0)||M(V.x,V.y,0,1)||M(V.x,V.y,0,-1))_++;if(F>=tm)break}return F>0&&_>=F*rm}isAntiAliasingBlend(c,d,h){let g=h.r-d.r,w=h.g-d.g,A=h.b-d.b,C=g*g+w*w+A*A;if(C===0)return!1;let T=((c.r-d.r)*g+(c.g-d.g)*w+(c.b-d.b)*A)/C;if(T<=0||T>=1)return!1;let k={r:d.r+T*g,g:d.g+T*w,b:d.b+T*A};return Ae(c,k)<=Jp}}var Aa=160,nm=24,om=32,sm=40,Vi=40,Wt=10,am=40,cm=16384,dm=65536,lm=0.6,Ca=3,um=65536;class Ui{config;getCachedContrast;constructor(c,d){this.config=c;this.getCachedContrast=d}fringe=new Li((c,d,h)=>this.resolvePixelColor(c,d,h));pixelRGBA(c,d,h){let g=Math.round(d),w=Math.round(h);if(g<0)g=0;else if(g>=c.width)g=c.width-1;if(w<0)w=0;else if(w>=c.height)w=c.height-1;let A=(c.width*w+g)*4;return{r:c.data[A],g:c.data[A+1],b:c.data[A+2],a:c.data[A+3]}}colorClusters(c,d=!0){let h=new Map,g=new Map;for(let w of c){let A=w.r<<16|w.g<<8|w.b,C=d?w.r>>3<<10|w.g>>3<<5|w.b>>3:A,T=(g.get(A)??0)+1;g.set(A,T);let k=h.get(C);if(k)k.r+=w.r,k.g+=w.g,k.b+=w.b,k.count++,k.coreCount=Math.max(k.coreCount,T);else h.set(C,{...w,count:1,coreCount:1})}return Array.from(h.values(),(w)=>({color:{r:Math.round(w.r/w.count),g:Math.round(w.g/w.count),b:Math.round(w.b/w.count)},count:w.count,coreCount:w.coreCount})).sort((w,A)=>A.count-w.count)}elementPixels(c,d){let h=Math.ceil(d.right)-Math.ceil(d.left),g=Math.ceil(d.bottom)-Math.ceil(d.top),w=h*g,A=Math.min(w,4096);return Array.from({length:A},(C,T)=>{let k=Math.floor(T*w/A);return this.resolvePixelColor(c,Math.ceil(d.left)+k%h,Math.ceil(d.top)+Math.floor(k/h))})}perimeterPixels(c,d){let h=[];for(let g=0;g<128;g++){let w=d.left+Math.floor((d.right-d.left-1)*g/127),A=d.top+Math.floor((d.bottom-d.top-1)*g/127);h.push(this.resolvePixelColor(c,w,d.top)),h.push(this.resolvePixelColor(c,w,d.bottom-1)),h.push(this.resolvePixelColor(c,d.left,A)),h.push(this.resolvePixelColor(c,d.right-1,A))}return h}interiorBounds(c){let d=Math.min(4,Math.floor((c.right-c.left-2)/2),Math.floor((c.bottom-c.top-2)/2));return{left:c.left+d,top:c.top+d,right:c.right-d,bottom:c.bottom-d}}inkBounds(c,d,h){let g=Math.ceil(d.left),w=Math.ceil(d.top),A=Math.ceil(d.right)-g,C=Math.ceil(d.bottom)-w,T=Math.max(1,Math.ceil(Math.sqrt(A*C/cm))),k=1/0,D=1/0,M=-1/0,F=-1/0,_=0,V=0;for(let X=0;X<C;X+=T)for(let Y=0;Y<A;Y+=T)if(_++,this.colorDistance(this.resolvePixelColor(c,g+Y,w+X),h)>Vi)V++,k=Math.min(k,Y),D=Math.min(D,X),M=Math.max(M,Y),F=Math.max(F,X);if(V===0||V>_*0.5)return null;let W=T+2,G={left:g+Math.max(0,k-W),top:w+Math.max(0,D-W),right:g+Math.min(A,M+W+1),bottom:w+Math.min(C,F+W+1)};return(G.right-G.left)*(G.bottom-G.top)<=A*C*0.5&&G.right-G.left>=2&&G.bottom-G.top>=2?G:null}hasSolidStroke(c,d,h,g=Wt){return!this.solidStrokeSeeds(c,d,h,g).next().done}*solidStrokeSeeds(c,d,h,g=Wt){let w=Math.ceil(d.left),A=Math.ceil(d.top),C=Math.ceil(d.right)-1,T=Math.ceil(d.bottom)-1,k=(C-w+1)*(T-A+1),D=Math.max(1,Math.ceil(Math.sqrt(k/dm))),M=(_,V)=>this.colorDistance(this.resolvePixelColor(c,_,V),h)<=g,F=(_,V)=>M(_,V)&&(_>w&&M(_-1,V)||_<C&&M(_+1,V))&&(V>A&&M(_,V-1)||V<T&&M(_,V+1));for(let _=A;_<=T;_+=D)for(let V=w;V<=C;V+=D)if(F(V,_))yield{x:V,y:_}}hasGlyphStrokes(c,d,h){let g={left:Math.max(0,d.left),top:Math.max(0,d.top),right:Math.min(c.width,d.right),bottom:Math.min(c.height,d.bottom)},w=new Set,A={pixels:um},C=0;for(let T of this.solidStrokeSeeds(c,g,h)){if(A.pixels<=0||C>=Ca)break;if(w.has(T.y*c.width+T.x))continue;let k=this.strokeRegion(c,g,h,{seed:T,visited:w,budget:A}),D=k.right-k.left+1,M=k.bottom-k.top+1;if(k.count<=D*M*lm)return!0;C+=Math.min(D,M)*3<=Math.max(D,M)?1:0}return C>=Ca}strokeRegion(c,d,h,{seed:g,visited:w,budget:A}){let C=Math.ceil(d.left),T=Math.ceil(d.top),k=Math.ceil(d.right)-1,D=Math.ceil(d.bottom)-1,M={count:0,left:g.x,top:g.y,right:g.x,bottom:g.y},F=[g.y*c.width+g.x];w.add(F[0]);while(F.length>0&&A.pixels>0){let _=F.pop(),V=_%c.width,W=Math.floor(_/c.width);A.pixels--,M.count++,M.left=Math.min(M.left,V),M.top=Math.min(M.top,W),M.right=Math.max(M.right,V),M.bottom=Math.max(M.bottom,W);let G=[V>C?_-1:-1,V<k?_+1:-1,W>T?_-c.width:-1,W<D?_+c.width:-1];for(let q of G)if(q>=0&&!w.has(q)&&this.isStrokePixel(c,q,h))w.add(q),F.push(q)}return M}isStrokePixel(c,d,h){let g=this.resolvePixelColor(c,d%c.width,Math.floor(d/c.width));return this.colorDistance(g,h)<=Wt}sampleElementColors(c,d){let h=this.interiorBounds(d),g=this.elementPixels(c,h),w=this.colorClusters(g),A=w[0].color,C=this.perimeterPixels(c,d),T=this.colorClusters(C),k=T.filter((J)=>this.isSimilarColor(J.color,A)).reduce((J,ee)=>J+ee.count,0),D=w.filter((J)=>!this.isSimilarColor(J.color,A)&&T.some((ee)=>this.isSimilarColor(J.color,ee.color))).reduce((J,ee)=>J+ee.count,0),M=T.filter((J)=>J.count>=51.2),F=this.perimeterPixels(c,this.interiorBounds(d)).filter((J)=>M.some((ee)=>this.colorDistance(J,ee.color)<=40)).length;if(k<51.2&&D>=g.length*0.1&&F>=256)A=this.averageColor(C);let _=this.inkBounds(c,h,A),V=_?this.elementPixels(c,_):g,G=(_?this.colorClusters(V):w).filter((J)=>J.count>=Math.max(2,V.length*0.0025)&&!this.isSimilarColor(J.color,A)&&(!_||this.colorDistance(J.color,A)>Vi)),q=(J)=>this.hasSolidStroke(c,_??h,J,this.colorDistance(J,A)<=am?0:Wt),X=(J,ee)=>this.fringe.isFringe(c,_??h,J,{text:ee,background:A}),Y=this.selectTextColor(G,A,T,{isSolidStroke:q,isFringe:X});return{textColor:(_?w.filter((J)=>J.count>=Math.max(2,g.length*0.0025)&&!this.isSimilarColor(J.color,A)&&this.colorDistance(J.color,A)<=Vi&&!T.some((ee)=>this.isSimilarColor(J.color,ee.color))&&this.hasGlyphStrokes(c,h,J.color)):[]).reduce((J,ee)=>this.getCachedContrast(ee.color,A)<this.getCachedContrast(J,A)?ee.color:J,Y),backgroundColor:A}}selectTextColor(c,d,h,{isSolidStroke:g,isFringe:w}){let A=c[0]?.count??0,C=c.filter((T)=>T.count>=A*0.25||T.coreCount>=T.count*0.8&&!h.some((k)=>this.isSimilarColor(T.color,k.color))&&!w(T.color,c[0].color)&&g(T.color));return C.reduce((T,k)=>{let D=this.getCachedContrast(k.color,d),M=this.getCachedContrast(T,d);return D<M?k.color:T},C[0]?.color??d)}async sampleBackgroundColors(c,d,h,g){let w=[];for(let A of g){let C=await this.sampleBackgroundAtPoint(c,d,h,{x:A.x,y:A.y});w.push({x:A.x,y:A.y,ratio:0,backgroundColor:C})}return w}backgroundColorsAtRadius(c,d,h,{x:g,y:w,radius:A}){let C=[];for(let T=-A;T<=A;T++)for(let k=-A;k<=A;k++){let D=co(g+T,d.left,d.right-1),M=co(w+k,d.top,d.bottom-1),F=this.resolvePixelColor(c,D,M);if(!this.isSimilarColor(F,h))C.push(F)}return C}async sampleBackgroundAtPoint(c,d,h,{x:g,y:w}){let A=[2,4,6,8];for(let C of A){let T=this.backgroundColorsAtRadius(c,d,h.textColor,{x:g,y:w,radius:C}),k=this.colorClusters(T)[0];if(k&&T.length>=(2*C+1)**2*0.2&&k.count>=T.length*0.2){let D=this.colorClusters(T.filter((M)=>this.isSimilarColor(M,k.color)),!1)[0].color;return this.fringe.isGlyphPixel(c,d,h,{color:D,point:{x:g,y:w}})?h.backgroundColor:D}}return h.backgroundColor}resolvePixelColor(c,d,h){let g=this.pixelRGBA(c,d,h);if(!this.config.compositeOverlays||g.a===255)return{r:g.r,g:g.g,b:g.b};let w=this.findUnderlyingColor(c,d,h);if(!w)return{r:g.r,g:g.g,b:g.b};return this.compositeColors(w,g)}underlyingColorAtRadius(c,d,h,g){for(let w=-g;w<=g;w++)for(let A=-g;A<=g;A++){if(g>1&&Math.abs(w)<g&&Math.abs(A)<g)continue;let C=Math.round(co(d+w,0,c.width-1)),T=Math.round(co(h+A,0,c.height-1)),k=(c.width*T+C)*4;if(c.data[k+3]===255)return{r:c.data[k],g:c.data[k+1],b:c.data[k+2]}}return null}findUnderlyingColor(c,d,h){let g=ba(c);for(let w=1;w<=12;w++)if(Sa(c,g,{x:d,y:h,radius:w}))return this.underlyingColorAtRadius(c,d,h,w);return null}compositeColors(c,d){let h=d.a/255;return{r:Math.round(d.r*h+c.r*(1-h)),g:Math.round(d.g*h+c.g*(1-h)),b:Math.round(d.b*h+c.b*(1-h))}}detectGradient(c){if(c.length<5)return null;let d=c.map((C)=>C.backgroundColor),h=this.calculateColorVariance(d);if(h<250)return null;let w=this.calculateGradientAxes(c),A=w.direction;if(this.colorDistance(w.startColor,w.endColor)<20)return null;return{isGradient:!0,direction:A,variance:h,startColor:w.startColor,endColor:w.endColor}}calculateColorVariance(c){let d=this.averageColor(c);return c.reduce((g,w)=>{let A=w.r-d.r,C=w.g-d.g,T=w.b-d.b;return g+A*A+C*C+T*T},0)/c.length/3}calculateGradientAxes(c){let d=[...c].sort((Z,se)=>Z.x-se.x),h=[...c].sort((Z,se)=>Z.y-se.y),g=this.averageColor(d.slice(0,3).map((Z)=>Z.backgroundColor)),w=this.averageColor(d.slice(-3).map((Z)=>Z.backgroundColor)),A=this.averageColor(h.slice(0,3).map((Z)=>Z.backgroundColor)),C=this.averageColor(h.slice(-3).map((Z)=>Z.backgroundColor)),T=this.colorDistance(g,w),k=this.colorDistance(A,C),D=d[0].x,M=d[d.length-1].x,F=h[0].y,_=h[h.length-1].y,V=this.closestSample(c,D,F).backgroundColor,W=this.closestSample(c,M,F).backgroundColor,G=this.closestSample(c,D,_).backgroundColor,q=this.closestSample(c,M,_).backgroundColor,X=this.colorDistance(V,q),Y=this.colorDistance(W,G);if(T>=k&&T>=X&&T>=Y)return{direction:"horizontal",startColor:g,endColor:w};if(k>=T&&k>=X&&k>=Y)return{direction:"vertical",startColor:A,endColor:C};if(X>=Y)return{direction:"diagonal-down",startColor:V,endColor:q};return{direction:"diagonal-up",startColor:G,endColor:W}}closestSample(c,d,h){let g=c[0],w=Number.POSITIVE_INFINITY;for(let A of c){let C=A.x-d,T=A.y-h,k=C*C+T*T;if(k<w)w=k,g=A}return g}getGradientSamplingPoints(c,d){let{left:h,top:g,right:w,bottom:A}=c,C=w-h,T=A-g,k=Math.max(1,Math.floor(Math.min(C,T)*0.1)),D=h+k,M=w-k-1,F=g+k,_=A-k-1,V=5,W=[];for(let G=0;G<5;G++){let q=G/4;if(d==="horizontal")W.push({x:Math.round(D+q*(M-D)),y:Math.round((F+_)/2)});else if(d==="vertical")W.push({x:Math.round((D+M)/2),y:Math.round(F+q*(_-F))});else if(d==="diagonal-up")W.push({x:Math.round(D+q*(M-D)),y:Math.round(_-q*(_-F))});else W.push({x:Math.round(D+q*(M-D)),y:Math.round(F+q*(_-F))})}return W}mergeSamples(c,d){let h=new Set,g=[];for(let w of[...c,...d]){let A=`${w.x},${w.y}`;if(h.has(A))continue;h.add(A),g.push(w)}return g}getSamplingPoints(c,d){let{left:h,top:g,right:w,bottom:A}=c,C=w-h,T=A-g,k=Math.max(1,Math.floor(Math.min(C,T)*0.1)),D=h+k,M=w-k-1,F=g+k,_=A-k-1,V=d===5?[0.5,0.1,0.9]:[0.1,0.5,0.9],W=[];if(d===5)return W.push({x:Math.round(D+V[0]*(M-D)),y:Math.round(F+V[0]*(_-F))}),W.push({x:Math.round(D),y:Math.round(F+V[0]*(_-F))}),W.push({x:Math.round(M),y:Math.round(F+V[0]*(_-F))}),W.push({x:Math.round(D+V[0]*(M-D)),y:Math.round(F)}),W.push({x:Math.round(D+V[0]*(M-D)),y:Math.round(_)}),W;for(let G of V)for(let q of V)W.push({x:Math.round(D+G*(M-D)),y:Math.round(F+q*(_-F))});if(d===13)W.push({x:Math.round(D),y:Math.round(F)}),W.push({x:Math.round(M),y:Math.round(F)}),W.push({x:Math.round(D),y:Math.round(_)}),W.push({x:Math.round(M),y:Math.round(_)});return W}detectTextShadow(c,d,h,g){let{left:w,top:A,right:C,bottom:T}=d,k=1,D=[{x:w+1,y:A+1},{x:C-1-1,y:A+1},{x:w+1,y:T-1-1},{x:C-1-1,y:T-1-1},{x:Math.round((w+C)/2),y:A+1},{x:Math.round((w+C)/2),y:T-1-1},{x:w+1,y:Math.round((A+T)/2)},{x:C-1-1,y:Math.round((A+T)/2)}],M=this.relativeLuminance(h),F=this.relativeLuminance(g),_=M>F;return D.reduce((W,G)=>{let q=this.resolvePixelColor(c,G.x,G.y);if(this.isSimilarColor(q,h))return W;let X=this.relativeLuminance(q);if(_&&X<F-0.05)return W+1;if(!_&&X>F+0.05)return W+1;return W},0)>=3}applyShadowAdjustment(c,d,h,g){if(!h||!this.isLargeText(d,g))return c;return Math.max(3,c-0.5)}requiredRatioFor(c,d,h,g){return this.applyShadowAdjustment(this.getRequiredContrastRatio(c,d,g),c,h,g)}isLargeText(c,d){if(!d||d<=0)return!1;let h=Lt(c);if(h!==null)return h*Aa/d>=nm;let w=(c.bounds.bottom-c.bounds.top)*Aa/d;return w>=om&&w<sm}isSimilarColor(c,d){return this.colorDistance(c,d)<=20}colorDistance(c,d){let h=c.r-d.r,g=c.g-d.g,w=c.b-d.b;return Math.sqrt(h*h+g*g+w*w)}averageColor(c){if(c.length===0)return{r:128,g:128,b:128};let d=c.reduce((h,g)=>({r:h.r+g.r,g:h.g+g.g,b:h.b+g.b}),{r:0,g:0,b:0});return{r:Math.round(d.r/c.length),g:Math.round(d.g/c.length),b:Math.round(d.b/c.length)}}relativeLuminance(c){let d=c.r/255,h=c.g/255,g=c.b/255,w=d<=0.03928?d/12.92:Math.pow((d+0.055)/1.055,2.4),A=h<=0.03928?h/12.92:Math.pow((h+0.055)/1.055,2.4),C=g<=0.03928?g/12.92:Math.pow((g+0.055)/1.055,2.4);return 0.2126*w+0.7152*A+0.0722*C}calculateContrastRatio(c,d){let h=this.relativeLuminance(c),g=this.relativeLuminance(d),w=Math.max(h,g),A=Math.min(h,g);return(w+0.05)/(A+0.05)}getRequiredContrastRatio(c,d,h){let g=this.isLargeText(c,h);if(d==="AAA")return g?4.5:7;else if(d==="AA")return g?3:4.5;else return g?3:4.5}}import Pa from"fs/promises";function pm(c){return{screenshots:c.maxCacheSize?.screenshots??10,colorPairs:c.maxCacheSize?.colorPairs??1000,elements:c.maxCacheSize?.elements??500,backgrounds:c.maxCacheSize?.backgrounds??200}}function mm(c){return{useMultiPointSampling:c.useMultiPointSampling??!0,detectGradients:c.detectGradients??!0,compositeOverlays:c.compositeOverlays??!1,detectTextShadows:c.detectTextShadows??!1,samplingPoints:c.samplingPoints??9,enableScreenshotCache:c.enableScreenshotCache??!0,enableColorPairCache:c.enableColorPairCache??!0,enableElementCache:c.enableElementCache??!0,enableBackgroundCache:c.enableBackgroundCache??!0,screenshotCacheTTL:c.screenshotCacheTTL??60000,maxCacheSize:pm(c)}}class Gt{deps;imageAnalysis;config;timer;backend;screenshotCache=new Map;screenshotHits=0;screenshotMisses=0;contrastCache=new Map;colorPairHits=0;colorPairMisses=0;elementCache=new Map;elementHits=0;elementMisses=0;bgColorCache=new Map;bgColorHits=0;bgColorMisses=0;constructor(c={},d=i,h=Ps(),g={readFile:Pa.readFile}){this.deps=g;this.timer=d,this.backend=h,this.config=mm(c),this.imageAnalysis=new Ui(this.config,(w,A)=>this.getCachedContrast(w,A))}async checkContrast(c,d,h,g){try{if(this.config.enableElementCache){let _=this.elementCacheKey(d,h,g),V=await this.getScreenshotFingerprint(c),W=this.elementCache.get(_);if(W&&W.screenshotFingerprint===V)return this.elementHits++,W.result;this.elementMisses++}let{left:w,top:A,right:C,bottom:T}=d.bounds,k=C-w,D=T-A;if(k<2||D<2)return null;let M=await this.getOrLoadScreenshot(c),F=await this.checkContrastWithImage(M,d,h,g);if(F&&this.config.enableElementCache){let _=this.elementCacheKey(d,h,g),V=await this.getScreenshotFingerprint(c);this.elementCache.set(_,{result:F,timestamp:this.timer.now(),screenshotFingerprint:V}),this.cleanupCache(this.elementCache,this.config.maxCacheSize.elements)}return F}catch(w){return e.warn(`Contrast checking error: ${r(w)}`,w),null}}getBatchCachedContrast(c,d,h,g){if(!this.config.enableElementCache)return;let w=this.elementCacheKey(c,d,g),A=this.elementCache.get(w);if(A&&A.screenshotFingerprint===h)return this.elementHits++,A;this.elementMisses++;return}cacheBatchContrast(c,d,h,{result:g,density:w}){if(g&&this.config.enableElementCache){let A=this.elementCacheKey(c,d,w);this.elementCache.set(A,{result:g,timestamp:this.timer.now(),screenshotFingerprint:h})}}async checkContrastBatch(c,d,h,g){return(await this.checkContrastBatchWithCoverage(c,d,h,g)).results}async checkContrastBatchWithCoverage(c,d,h,g){let w=new Map,A=[];try{let C=await this.getOrLoadScreenshot(c),T=await this.getScreenshotFingerprint(c);for(let k of d){if(!Hi(C,k.bounds)){A.push(k);continue}w.set(k,await this.checkBatchElement(C,k,h,{screenshotFingerprint:T,density:g}))}if(this.config.enableElementCache)this.cleanupCache(this.elementCache,this.config.maxCacheSize.elements)}catch(C){e.warn(`Batch contrast checking error: ${r(C)}`,C),A.length=0;for(let T of d)w.set(T,null)}return{results:w,outsideImage:A}}async checkBatchElement(c,d,h,{screenshotFingerprint:g,density:w}){try{let A=this.getBatchCachedContrast(d,h,g,w);if(A)return A.result;let C=await this.checkContrastWithImage(c,d,h,w);return this.cacheBatchContrast(d,h,g,{result:C,density:w}),C}catch(A){return e.warn(`Error checking contrast for element: ${r(A)}`,A),null}}async checkContrastWithImage(c,d,h,g){let{left:w,top:A,right:C,bottom:T}=d.bounds,k=C-w,D=T-A;if(k<2||D<2)return null;if(!Hi(c,d.bounds))return null;let{textColor:M,backgroundColor:F}=this.imageAnalysis.sampleElementColors(c,d.bounds);if(!this.config.useMultiPointSampling){let ce=F,pe=this.getCachedContrast(M,ce),yt=this.config.detectTextShadows?this.imageAnalysis.detectTextShadow(c,d.bounds,M,ce):!1,Rn=this.imageAnalysis.getRequiredContrastRatio(d,h,g),Bc=this.imageAnalysis.applyShadowAdjustment(Rn,d,yt,g),Hc=pe>=this.imageAnalysis.requiredRatioFor(d,"AA",yt,g),Lc=pe>=this.imageAnalysis.requiredRatioFor(d,"AAA",yt,g);return{ratio:pe,minRatio:pe,maxRatio:pe,avgRatio:pe,samples:[{x:Math.floor((w+C)/2),y:Math.floor((A+T)/2),ratio:pe,backgroundColor:ce}],textColor:M,backgroundColor:ce,shadowDetected:yt,baseRequiredRatio:Rn,meetsAA:Hc,meetsAAA:Lc,requiredRatio:Bc}}let _=this.imageAnalysis.getSamplingPoints(d.bounds,this.config.samplingPoints),V=await this.imageAnalysis.sampleBackgroundColors(c,d.bounds,{textColor:M,backgroundColor:F},_),W=this.config.detectGradients?this.imageAnalysis.detectGradient(V):null,G=V,q;if(W?.isGradient){q=W;let ce=this.imageAnalysis.getGradientSamplingPoints(d.bounds,q.direction),pe=await this.imageAnalysis.sampleBackgroundColors(c,d.bounds,{textColor:M,backgroundColor:F},ce);G=this.imageAnalysis.mergeSamples(V,pe)}let X=G.map((ce)=>{let pe=this.getCachedContrast(M,ce.backgroundColor);return{...ce,ratio:pe}}),Y=X.map((ce)=>ce.ratio),Z=Math.min(...Y),se=Math.max(...Y),J=Y.reduce((ce,pe)=>ce+pe,0)/Y.length,ee=this.imageAnalysis.averageColor(X.map((ce)=>ce.backgroundColor));this.setBackgroundCache(d.bounds,ee);let mt=this.config.detectTextShadows?this.imageAnalysis.detectTextShadow(c,d.bounds,M,ee):!1,Sn=this.imageAnalysis.getRequiredContrastRatio(d,h,g),Fc=this.imageAnalysis.applyShadowAdjustment(Sn,d,mt,g),_c=Z>=this.imageAnalysis.requiredRatioFor(d,"AA",mt,g),Nc=Z>=this.imageAnalysis.requiredRatioFor(d,"AAA",mt,g);return{ratio:Z,minRatio:Z,maxRatio:se,avgRatio:J,samples:X,textColor:M,backgroundColor:ee,gradient:q,shadowDetected:mt,baseRequiredRatio:Sn,meetsAA:_c,meetsAAA:Nc,requiredRatio:Fc}}async getOrLoadScreenshot(c){if(!this.config.enableScreenshotCache)return await this.decodeScreenshot(c);let d=this.screenshotCache.get(c),h=this.timer.now();if(d&&h-d.timestamp<this.config.screenshotCacheTTL){let A=await this.getScreenshotFingerprint(c);if(d.fingerprint===A)return this.screenshotHits++,d.image}this.screenshotMisses++;let g=await this.decodeScreenshot(c),w=await this.getScreenshotFingerprint(c);return this.screenshotCache.set(c,{image:g,timestamp:h,fingerprint:w}),this.cleanupCache(this.screenshotCache,this.config.maxCacheSize.screenshots),g}async decodeScreenshot(c){let d=await this.deps.readFile(c);return this.backend.rawPixels(d)}async getScreenshotFingerprint(c){try{let d=await Pa.stat(c);return`${c}:${d.mtime.getTime()}:${d.size}`}catch(d){return e.warn(`Failed to stat contrast screenshot ${c}; using timestamp: ${r(d)}`,d),`${c}:${this.timer.now()}`}}elementCacheKey(c,d,h){return JSON.stringify({text:c.text,bounds:c.bounds,class:c.class,textSize:Lt(c),wcagLevel:d,density:h&&h>0?h:null})}getCachedContrast(c,d){if(!this.config.enableColorPairCache)return this.imageAnalysis.calculateContrastRatio(c,d);let h=this.colorPairKey(c,d),g=this.contrastCache.get(h);if(g!==void 0)return this.colorPairHits++,g;return this.colorPairMisses++,g=this.imageAnalysis.calculateContrastRatio(c,d),this.contrastCache.set(h,g),this.cleanupCache(this.contrastCache,this.config.maxCacheSize.colorPairs),g}colorPairKey(c,d){let h=c.r+c.g+c.b,g=d.r+d.g+d.b,[w,A]=h>g?[c,d]:[d,c];return`${w.r},${w.g},${w.b}:${A.r},${A.g},${A.b}`}clearCaches(){this.screenshotCache.clear(),this.contrastCache.clear(),this.elementCache.clear(),this.bgColorCache.clear(),this.screenshotHits=0,this.screenshotMisses=0,this.colorPairHits=0,this.colorPairMisses=0,this.elementHits=0,this.elementMisses=0,this.bgColorHits=0,this.bgColorMisses=0}getCacheStats(){return{screenshots:{size:this.screenshotCache.size,hits:this.screenshotHits,misses:this.screenshotMisses},colorPairs:{size:this.contrastCache.size,hits:this.colorPairHits,misses:this.colorPairMisses},elements:{size:this.elementCache.size,hits:this.elementHits,misses:this.elementMisses},backgrounds:{size:this.bgColorCache.size,hits:this.bgColorHits,misses:this.bgColorMisses}}}cleanupCache(c,d){if(c.size<=d)return;let h=Array.from(c.entries()).sort((w,A)=>{if(typeof w[1]==="number"||typeof A[1]==="number")return 0;return w[1].timestamp-A[1].timestamp}),g=c.size-d;for(let w=0;w<g;w++)c.delete(h[w][0])}setBackgroundCache(c,d){if(!this.config.enableBackgroundCache)return;let h=`${c.left},${c.top},${c.right},${c.bottom}`;if(this.bgColorCache.set(h,d),this.bgColorCache.size>this.config.maxCacheSize.backgrounds){let g=this.bgColorCache.keys().next().value;if(g)this.bgColorCache.delete(g)}}}var hm=1,zt=2,fm=3;function ym(c){let d=c.occlusionState;return d==="partial"||d==="hidden"}function vm(c,d){if(c.type===zt)return!(d?.type===zt||d?.windowLayer!==void 0&&c.windowLayer!==void 0&&d.windowLayer>c.windowLayer);if(c.type!==hm&&c.type!==fm)return!1;return d?.windowLayer!==void 0&&c.windowLayer!==void 0&&c.windowLayer>d.windowLayer}function gm(c,d,h){let g=d===void 0?void 0:h.find((w)=>w.id===d);return h.some((w)=>{let A=Tt(w.bounds);return A!==null&&w!==g&&vm(w,g)&&$t(c.bounds,A)!==null})}function Ta(c,d,h=[]){return!ym(c)&&!gm(c,d,h)}function Ia(c,d,h=[]){let g=d===void 0?void 0:h.find((A)=>A.id===d);if(g)return g.type===zt;let w=c.package??c["resource-id"]?.split(":id/")[0];return w!==void 0&&h.some((A)=>A.type===zt&&A.packageName===w)}class Wi{injectedDb;constructor({db:c}={}){this.injectedDb=c??null}get db(){return this.injectedDb??_e()}async get(c){return await this.db.selectFrom("accessibility_baselines").selectAll().where("screen_id","=",c).executeTakeFirst()??null}async list(){return this.db.selectFrom("accessibility_baselines").selectAll().execute()}async upsert(c,d,h){await this.db.insertInto("accessibility_baselines").values({screen_id:c,violations_json:d,updated_at:h}).onConflict((g)=>g.column("screen_id").doUpdateSet({violations_json:d,updated_at:h})).execute()}async delete(c){await this.db.deleteFrom("accessibility_baselines").where("screen_id","=",c).execute()}async deleteAll(){await this.db.deleteFrom("accessibility_baselines").execute()}async deleteOlderThan(c){let d=await this.db.deleteFrom("accessibility_baselines").where(m`datetime(updated_at)`,"<",m`datetime(${c})`).executeTakeFirst();return Number(d.numDeletedRows)||0}}var bm=j(mo((c)=>typeof c==="object"&&c!==null&&("fingerprint"in c)&&typeof c.fingerprint==="string"));class NL{repository;constructor(c){this.repository=new Wi({db:c})}async getBaseline(c){let d=await this.repository.get(c);if(!d)return null;let h=this.parseViolations(d.violations_json,d.screen_id);if(h===null)return null;return{screenId:d.screen_id,violations:h,updatedAt:d.updated_at}}parseViolations(c,d){try{return bm.parse(JSON.parse(c))}catch(h){return e.warn(`[BaselineManager] Corrupt violations_json for screen "${d}"; ignoring baseline row`,h),null}}async saveBaseline(c,d){let h=new Date().toISOString(),g=JSON.stringify(d);await this.repository.upsert(c,g,h)}async clearBaseline(c){await this.repository.delete(c)}async listBaselines(){let c=await this.repository.list(),d=[];for(let h of c){let g=this.parseViolations(h.violations_json,h.screen_id);if(g===null)continue;d.push({screenId:h.screen_id,violations:g,updatedAt:h.updated_at})}return d}async clearAllBaselines(){await this.repository.deleteAll()}async cleanupOldBaselines(c=WC.baselineDays){let d=SW(c);return this.repository.deleteOlderThan(d)}}var wm="no screenshot for this observation",Rm="text elements are covered by the keyboard or another window, or partly hidden, so the screenshot does not show them",Am="text elements extend beyond the screenshot";function Pm(c){return[{count:c.covered,reason:Rm},{count:c.outsideImage,reason:Am}].filter(({count:d})=>d>0).map(({count:d,reason:h})=>({check:"insufficient-contrast",reason:`${d} ${h}`}))}var Zh=50,ka={error:0,warning:1,info:2};function xa(c){let d=c.violations.length;if(d<=Zh)return c;let h=[...c.violations].sort((A,C)=>ka[A.severity]-ka[C.severity]),g=h.slice(0,Zh),w={};for(let A of h.slice(Zh))w[A.type]=(w[A.type]??0)+1;return{...c,violations:g,violationsTruncated:{total:d,omitted:d-g.length,omittedByType:w}}}function Tm(c){if(we(c).class||!c.node)return c;let d=Array.isArray(c.node)?c.node:[c.node];return d.find((h)=>we(h)["resource-id"])??d.find((h)=>we(h).class)??c}function km(c,d,h){let g=pd(c,h)?.filter((A)=>A.type===1&&(A.packageName===void 0||A.packageName===d)&&A.hierarchy),w=g?.find((A)=>A.isFocused)??g?.find((A)=>A.isActive)??g?.reduce((A,C)=>!A||(C.windowLayer??-1/0)>(A.windowLayer??-1/0)?C:A,void 0);if(!w?.hierarchy)return;return Tm(w.hierarchy)}class Fm{contrastChecker;baselineStore;timer;constructor(c=i,d=new NL,h=new Gt({},c)){this.contrastChecker=h,this.baselineStore=d,this.timer=c}async audit(c,d,{screenshotPath:h,packageName:g,config:w},A){let{density:C,windows:T,descendantLabelled:k,elementWindowIds:D}=typeof A==="number"?{density:A}:A??{};c=c.filter((X)=>!Ia(X,D?.get(X),T));let M=[];M.push(...this.checkMissingContentDescriptions(c,k));let F;if(h)F=await this.checkContrastRatios(c,h,w,{density:C,coverage:{windows:T??[],elementWindowIds:D}}),M.push(...F.violations);M.push(...this.checkTouchTargetSizes(c,w.level,C)),M.push(...this.checkFormInputLabels(c,d,C));let _=this.generateScreenId(g,d,T),V=M,W=0;if(w.useBaseline){let X=await this.baselineStore.getBaseline(_);if(X){let Y=new Set(X.violations.map((Z)=>Z.fingerprint));V=M.filter((Z)=>!Y.has(Z.fingerprint)),W=M.length-V.length}}let G=this.generateSummary(M,V,W,w),q=F?Pm(F):[{check:"insufficient-contrast",reason:wm}];if(q.length>0)G.notEvaluated=q;return{config:w,summary:G,violations:V,timestamp:this.timer.now(),screenId:_}}async saveBaseline(c){await this.baselineStore.saveBaseline(c.screenId,c.violations)}async clearBaseline(c){await this.baselineStore.clearBaseline(c)}checkMissingContentDescriptions(c,d){let h=[];for(let g of c){if(g.text||g["content-desc"])continue;if(d?.has(g))continue;if(g.clickable||g.focusable||g.checkable)h.push({type:"missing-content-description",severity:"error",criterion:"1.1.1",message:`Interactive element (${g.class||"unknown"}) lacks accessible label`,element:g,details:{explanation:"Clickable, focusable, or checkable elements must have a text label or content-desc for screen readers"},fingerprint:this.generateFingerprint(g,"missing-content-description")})}return h}async checkContrastRatios(c,d,{level:h,contrast:g},{density:w,coverage:A}){let C=[],T=c.filter((V)=>V.text&&V.text.trim().length>0),k=T.filter((V)=>Ta(V,A.elementWindowIds?.get(V),A.windows)),D=T.length-k.length,M=g?new Gt(g,this.timer):this.contrastChecker,{results:F,outsideImage:_}=await M.checkContrastBatchWithCoverage(d,k,h,w);for(let[V,W]of F.entries())if(W&&W.minRatio<W.requiredRatio){let G=W.minRatio.toFixed(2),q=W.maxRatio.toFixed(2),X=W.avgRatio.toFixed(2),Y=W.shadowDetected?" (shadow-enhanced)":"";C.push({type:"insufficient-contrast",severity:h==="AAA"?"warning":"error",criterion:"1.4.3",message:`Text has insufficient contrast ratio: ${G}:1 (required: ${W.requiredRatio}:1)`,element:V,details:{contrastRatio:parseFloat(G),contrastMinRatio:parseFloat(G),contrastMaxRatio:parseFloat(q),contrastAvgRatio:parseFloat(X),requiredRatio:W.requiredRatio,explanation:`Text color RGB(${W.textColor.r},${W.textColor.g},${W.textColor.b}) on background RGB(${W.backgroundColor.r},${W.backgroundColor.g},${W.backgroundColor.b}). Samples min/avg/max=${G}/${X}/${q}${Y}.`},fingerprint:this.generateFingerprint(V,"insufficient-contrast")})}return{violations:C,covered:D,outsideImage:_.length}}checkTouchTargetSizes(c,d,h){let g=[];if(!h||h<=0)return g;let w=44,A=h,C=w*(A/Fm.BASELINE_DENSITY_DPI);for(let T of c){if(!T.clickable)continue;let k=T.bounds.right-T.bounds.left,D=T.bounds.bottom-T.bounds.top;if(k<C||D<C){let M=Math.floor(k*Fm.BASELINE_DENSITY_DPI/A),F=Math.floor(D*Fm.BASELINE_DENSITY_DPI/A);g.push({type:"touch-target-too-small",severity:d==="AAA"?"error":"warning",criterion:"2.5.5",message:`Touch target is too small: ${M}x${F}dp (minimum: ${w}x${w}dp)`,element:T,details:{actualSize:{width:M,height:F},requiredSize:{width:w,height:w},explanation:"Touch targets should be at least 44x44 dp to be easily tappable"},fingerprint:this.generateFingerprint(T,"touch-target-too-small")})}}return g}checkFormInputLabels(c,d,h){let g=[],w=c.filter((T)=>T.class?.includes("EditText")||T.class?.includes("Spinner")||T.class?.includes("CheckBox")||T.class?.includes("RadioButton")),A=c.filter((T)=>(!T.class||T.class.includes("TextView"))&&T.text),C=this.labelGapThresholdPx(h);for(let T of w)if(!(T.text||T["content-desc"]||this.hasNearbyLabel(T,A,C)))g.push({type:"unlabeled-form-input",severity:"error",criterion:"3.3.2",message:`Form input (${T.class||"unknown"}) lacks accessible label`,element:T,details:{explanation:"Form inputs must have associated labels for screen reader users to understand their purpose"},fingerprint:this.generateFingerprint(T,"unlabeled-form-input")});return g}static LABEL_GAP_DP=50;static BASELINE_DENSITY_DPI=160;static FALLBACK_DENSITY_DPI=320;labelGapThresholdPx(c){let d=c&&c>0?c:Fm.FALLBACK_DENSITY_DPI;return Fm.LABEL_GAP_DP*(d/Fm.BASELINE_DENSITY_DPI)}hasNearbyLabel(c,d,h){let g=1/0;for(let w of d){let A=this.boundingBoxGap(c.bounds,w.bounds);if(A<g)g=A}return g<=h}boundingBoxGap(c,d){let h=Math.max(0,c.left-d.right,d.left-c.right),g=Math.max(0,c.top-d.bottom,d.top-c.bottom);return Math.sqrt(h*h+g*g)}generateFingerprint(c,d){let h=JSON.stringify({type:d,resourceId:c["resource-id"],class:c.class,bounds:c.bounds,text:c.text});return Sm.createHash("md5").update(h).digest("hex")}generateScreenId(c,d,h){let g=this.resolveRootNode(d,c,h),w=we(g),A=w.class||"unknown",C=w["resource-id"]||"";return`${c}:${A}:${C}`}resolveRootNode(c,d,h){if(h&&h.length>1){let w=km(c,d,h);if(w)return w}let g=c.node;if(Array.isArray(g)&&g.length>0)return g[g.length-1];if(g&&typeof g==="object")return g;return c}generateSummary(c,d,h,g){let w={error:d.filter((k)=>k.severity==="error").length,warning:d.filter((k)=>k.severity==="warning").length,info:d.filter((k)=>k.severity==="info").length},A={"missing-content-description":0,"insufficient-contrast":0,"touch-target-too-small":0,"unlabeled-form-input":0};for(let k of d)A[k.type]++;let C=!0,T;if(g.failureMode==="strict"&&d.length>0)C=!1,T=`Found ${d.length} accessibility violation(s) in strict mode`;else if(g.failureMode==="threshold"){let k=g.minSeverity||"warning",D=d.filter((M)=>{if(k==="error")return M.severity==="error";if(k==="warning")return M.severity==="error"||M.severity==="warning";return!0});if(D.length>0)C=!1,T=`Found ${D.length} violation(s) at or above ${k} severity`}return{totalViolations:c.length,bySeverity:w,byType:A,baselinedViolations:h,passed:C,failureReason:T}}}function Ea(c,d){let h=we(c.source).windowId;if(typeof h==="number"&&Number.isInteger(h))return h;return c.parentIndex===void 0?void 0:Ea(d[c.parentIndex],d)}var Em=/Image|Icon/i;function Bm(c,d,h){if(/\p{L}/u.test(c??""))return!0;return/\p{N}/u.test(c??"")&&Hm(d,h)}function Hm(c,d){let h=0;for(let g=d.index+1;g<c.length;g++){let w=c[g];if(w.rootGroup!==d.rootGroup||w.depth<=d.depth)break;if(Em.test(w.className??""))return!1;if((w.element?.text??"").trim()||(w.element?.["content-desc"]??"").trim())h+=1}return h===1}function FL(c,d=new ve){let h=d.project(ft(c)??c),g=[],w=new Set,A=new Map;for(let C of h){if(C.rootGroup!==0||!C.element)continue;g.push(C.element);let T=Ea(C,h);if(T!==void 0)A.set(C.element,T);if(!Boolean(C.element.text||C.element["content-desc"])&&C.affordances.includes("tap")&&Bm(C.displayedLabel,h,C))w.add(C.element)}return{elements:g,descendantLabelled:w,windowIds:A}}async function xW(c){if(!c)return;try{return await Qo(c)?c:void 0}catch(d){e.warn(`[AccessibilityAudit] Failed to check observation screenshot: ${d}`);return}}class $i{device;screenshotPathResolver;getConfig;contrastChecker;constructor(c){this.device=c.device,this.contrastChecker=c.contrastChecker,this.screenshotPathResolver=c.screenshotPathResolver??(()=>Promise.resolve(void 0)),this.getConfig=c.getConfig??(()=>N.getAccessibilityAuditConfig())}async run(c,d){let h=this.getConfig();if(!h)return;if(this.device.platform!=="android"){e.debug("[AccessibilityAudit] Skipping audit, only Android is supported");return}if(!c.viewHierarchy?.hierarchy){e.debug("[AccessibilityAudit] Skipping audit, no view hierarchy available");return}if(!c.activeWindow?.appId){e.debug("[AccessibilityAudit] Skipping audit, no active app");return}try{await d.track("accessibilityAudit",async()=>{e.info(`[AccessibilityAudit] Running WCAG ${h.level} audit for ${c.activeWindow?.appId}`);let g=new Fm(void 0,void 0,this.contrastChecker),{elements:w,descendantLabelled:A,windowIds:C}=FL(c.viewHierarchy),T=await this.screenshotPathResolver(c.observationId),k=await g.audit(w,c.viewHierarchy.hierarchy,{screenshotPath:T,packageName:c.activeWindow.appId,config:h},{density:c.viewHierarchy.density,windows:c.viewHierarchy.windows,descendantLabelled:A,elementWindowIds:C});if(c.accessibilityAudit=xa(k),!k.summary.passed)e.warn(`[AccessibilityAudit] Accessibility audit FAILED with ${k.violations.length} violations (${k.summary.bySeverity.error} errors, ${k.summary.bySeverity.warning} warnings)`);else e.info("[AccessibilityAudit] Accessibility audit PASSED")})}catch(g){e.error(`[AccessibilityAudit] Failed to run accessibility audit: ${g}`)}}}class Ma{DEFAULT_TTL_MS=60000;cache;timer;constructor(c=new Af){this.timer=c,this.cache=new on(c,{ttlMs:this.DEFAULT_TTL_MS})}async isVoiceOverEnabled(c,d,{featureFlags:h,timeoutMs:g,signal:w}={}){return await this.resolveVoiceOverState(c,d,{featureFlags:h,timeoutMs:g,signal:w})===!0}async isVoiceOverActiveOrUnknown(c,d,{featureFlags:h,timeoutMs:g,signal:w}={}){let A=await this.resolveVoiceOverState(c,d,{featureFlags:h,timeoutMs:g,signal:w});if(A===null)return e.warn(`[IosVoiceOverDetector] VoiceOver state for device ${c} could not be determined; treating as enabled (fail-safe) so the tap path takes the activation gesture instead of a plain touch`),!0;return A}async resolveState(c,d,{featureFlags:h,timeoutMs:g,signal:w}={}){return this.resolveVoiceOverState(c,d,{featureFlags:h,timeoutMs:g,signal:w})}async resolveVoiceOverState(c,d,{featureFlags:h,timeoutMs:g,signal:w}={}){if(h?.isEnabled("force-accessibility-mode"))return e.debug(`[IosVoiceOverDetector] Force-enabled via feature flag for device ${c}`),!0;if(h&&!h.isEnabled("accessibility-auto-detect"))return e.debug(`[IosVoiceOverDetector] Auto-detection disabled via feature flag for device ${c}`),!1;let A=this.cache.get(c);if(A!==void 0)return e.debug(`[IosVoiceOverDetector] Using cached result for device ${c}: enabled=${A}`),A;e.debug(`[IosVoiceOverDetector] Detecting VoiceOver state for device ${c}`);let C=this.timer.now(),T=await this.detectVoiceOverState(c,d,g,w),k=this.timer.now()-C;if(k>50)e.warn(`[IosVoiceOverDetector] Detection took ${k}ms (target: <50ms) for device ${c}`);else e.debug(`[IosVoiceOverDetector] Detection completed in ${k}ms for device ${c}`);if(T!==null)this.cache.set(c,T);return T}invalidateCache(c){e.debug(`[IosVoiceOverDetector] Invalidating cache for device ${c}`),this.cache.delete(c)}clearAllCache(){e.debug("[IosVoiceOverDetector] Clearing all cached entries"),this.cache.clear()}async detectVoiceOverState(c,d,h,g){try{let w=await d.requestVoiceOverState(h,void 0,g);if(!w.success)return e.warn(`[IosVoiceOverDetector] VoiceOver detection failed for ${c}: ${w.error}`),null;return e.debug(`[IosVoiceOverDetector] VoiceOver state for device ${c}: enabled=${w.enabled}`),w.enabled}catch(w){return e.error(`[IosVoiceOverDetector] Failed to detect VoiceOver state for device ${c}:`,w),null}}}var Ao=new Ma;class Gi{device;adb;featureFlags;detector;iosDetector;iosClient;constructor(c){this.device=c.device,this.adb=c.adb,this.featureFlags=c.featureFlags,this.detector=c.accessibilityDetector??ni,this.iosDetector=c.iosVoiceOverDetector??Ao,this.iosClient=c.iosClient}async run(c,d,h){try{await d.track("accessibilityDetection",async()=>{o(h);let g=this.featureFlags??sr.getInstance();if(this.device.platform==="android"){let w=await this.detector.resolveState(this.device.deviceId,this.adb,g);if(w===null){delete c.accessibilityState;return}let{enabled:A,service:C}=w,T=!g.isEnabled("force-accessibility-mode")&&!g.isEnabled("accessibility-auto-detect");c.accessibilityState={enabled:A,service:C,detectionSkipped:T},e.debug(`[AccessibilityDetector] Android accessibility state: enabled=${A}, service=${C}`)}else if(this.device.platform==="ios"){let w=this.iosClient??x.getInstance(this.device),A=await this.iosDetector.resolveState(this.device.deviceId,w,{featureFlags:g});if(A===null){delete c.accessibilityState;return}c.accessibilityState={enabled:A,service:A?"voiceover":"unknown"},e.debug(`[IosVoiceOverDetector] iOS VoiceOver state: enabled=${A}`)}})}catch(g){e.error(`[detectAccessibilityState] Failed to detect accessibility state: ${g}`)}}}function Fe(c){return c.timeoutMs+Math.max(0,c.budgetExtensionMs?.()??0)}var Vm=100,ct=Symbol("observe-poll-budget-expired"),qi=Symbol("observe-poll-reconciliation-unconfirmed");async function _a(c,{timer:d,remainingMs:h,signal:g,label:w}){if(h<0)return ct;let A=new AbortController,C=Error(`${w} exceeded the remaining ${h}ms budget`);try{return await l(()=>c(je(g,A.signal)),{timer:d,timeoutMs:h+1,signal:g,label:w,timeoutError:()=>C})}catch(T){if(T!==C)throw T;return A.abort(new DOMException(C.message,"TimeoutError")),e.debug(`[ObservePoll] ${C.message}; aborted the read`),ct}}function Um(c,d,h){return h!==void 0&&(d<=0||c.hardBudget===!0&&d<Vm)}function Ki(c){return c.wakefulness==="Asleep"}function Wm(c){return Ki(c)&&c.wakefulnessSource==="adb"}function Na(c){let d=c.viewHierarchy;if(!d||typeof d.hierarchy!=="object"||d.hierarchy===null||"error"in d.hierarchy)return;return un(d)}function Ba(c,d,h){if(c)return d!==void 0&&d>0?d:0;return h!==void 0&&h>0?h+1:0}async function $m(c,d,h,g){let w=Error("Observe poll finalization deadline reached"),A;try{await l(c,{timer:d,timeoutMs:Math.max(0,h),signal:g,label:"Observe poll finalization",timeoutError:()=>w}),A="settled"}catch(C){if(g?.aborted)A="aborted";else if(C===w)A="deadline";else throw C}if(A==="settled")return;c.then(()=>{e.debug("[ObservePoll] Background terminal finalization settled after poll completion")}).catch((C)=>{e.debug(`[ObservePoll] Background terminal finalization failed: ${C}`)})}function Gm(c){return Na(c)!==void 0&&c.freshness?.isFresh!==!1&&c.freshness?.verified!==!1}function qm(c){return c.freshness?.isFresh===!1||c.freshness?.verified===!1}function zm(c,d){return{capture:d??c,canProcessRecomposition:d!==void 0}}function Km(c,d,h){return c!==void 0&&(d===void 0||c>=d)&&!h}function Ha(c,d){let h=Na(c),g=qm(c);if(d.enteringReference===void 0&&h!==void 0)d.enteringReference=h;let w=Km(h,d.deviceFloor,g);if(w&&h!==void 0)d.deviceFloor=d.deviceFloor===void 0?h:Math.max(d.deviceFloor,h);let A=h!==void 0&&d.enteringReference!==void 0&&h>d.enteringReference&&w;if(A)d.hasPostInvocationEvidence=!0;return{isAdmissibleEvidence:w,isPostInvocation:A}}function jm(c,d,h){let g=Ki(c)&&c.wakefulnessSource==="hierarchy";return Wm(c)||Ki(c)&&d&&(!g||h)}function Xm(c,d,h){if(c.isAdmissibleEvidence)return{previous:c.capture.observation,newestTrustworthyCapture:c.capture};return{previous:d,newestTrustworthyCapture:h}}function Ym(c,d,h,{original:g,capture:w}){if(!h.stopped)return;let{options:A,timer:C,start:T,onObservation:k}=c,D=A.resumeOnTerminalMismatch?Ha(w.observation,d):{isAdmissibleEvidence:!0,isPostInvocation:!0};if(D.isAdmissibleEvidence&&D.isPostInvocation&&k(w.observation,g,h.polls))return;if(h.stopped=!1,h.terminalReason="timeout",A.resumeOnTerminalMismatch&&C.now()-T<Fe(A))return{kind:"resume",outcome:h,capture:w,isAdmissibleEvidence:D.isAdmissibleEvidence};return}function Qm(c,d){let{observeScreen:h,timer:g,options:w,start:A}=c;return async(C,T=!0,k,D)=>{let M=await Zm(h,g,w,{start:A,observation:C.observation,minTimestamp:Ba(d.hasPostInvocationEvidence,d.deviceFloor,d.enteringReference)});if(C.waitMs=g.now()-A,M===qi){if(C.stopped)C.stopped=!1,C.terminalReason="timeout"}else if(M){let F=C.observation;C.observation=M.observation,C.polls++,k=M.generation,D=M.cachedAt,T=Gm(M.observation);let _=Ym(c,d,C,{original:F,capture:M});if(_)return _}if(o(w.signal),w.skipRecompositionTracking&&T&&h.processRecomposition){let F=(async()=>{await h.processRecomposition(C.observation),await h.cacheObserveResult?.(C.observation,k,D)})();await $m(F,g,Fe(w)-(g.now()-A),w.signal)}else await h.cacheObserveResult?.(C.observation,k,D);return{kind:"terminal",outcome:C}}}async function Yi(c,d,h,{minTimestamp:g,timeoutMs:w,readBackStackEachPoll:A=h.readBackStackEachPoll,signal:C=h.signal}){let T=c.captureCacheGeneration?.(),k=d.now();return{observation:await c.execute({display:h.display,freshness:h.display===void 0?void 0:"fresh",minTimestamp:g,timeoutMs:w,skipWaitForFresh:h.skipWaitForFresh??!1,requireFreshExtraction:h.requireFreshExtraction,signal:C,skipScreenshot:!0,skipStaleWindowRecovery:!0,skipCache:!0,skipBackStack:A===!0?void 0:!0,skipAccessibilityAudit:!0,skipPerformanceAudit:h.skipPerformanceAudit,skipRecompositionTracking:h.skipRecompositionTracking}),generation:T,cachedAt:k}}function Fa(c,d,h,{start:g,label:w}){if(h.hardBudget)return _a(c,{timer:d,remainingMs:Fe(h)-(d.now()-g),signal:h.signal,label:w});return l(()=>c(h.signal),{timer:d,signal:h.signal,label:w})}async function Zm(c,d,h,{start:g,observation:w,minTimestamp:A}){if(h.readBackStackEachPoll||!c.collectDeferredBackStack)return;let C=await Fa((T)=>c.collectDeferredBackStack(w,{signal:T}),d,h,{start:g,label:"Observe poll terminal back stack"});if(o(h.signal),C===ct)return qi;if(!C)return;try{let T=await Fa((k)=>Yi(c,d,h,{minTimestamp:A,readBackStackEachPoll:!0,signal:k}),d,h,{start:g,label:"Observe poll attribution reconciliation"});return o(h.signal),T===ct?qi:T}catch(T){o(h.signal),e.warn("[ObservePoll] Terminal attribution poll failed; returning original observation",T);return}}async function eh(c,d,h,{start:g,minTimestamp:w,lastCapture:A}){let C=Fe(h)-(d.now()-g),T=Math.max(1,C);if(!h.hardBudget)return{capture:await Yi(c,d,h,{minTimestamp:w,timeoutMs:T})};let k=await _a((D)=>Yi(c,d,h,{minTimestamp:w,timeoutMs:T,signal:D}),{timer:d,remainingMs:C,signal:h.signal,label:"Observe poll read"});if(o(h.signal),k!==ct)return{capture:k};if(!A)throw new t(`Observe poll read did not finish within its ${Fe(h)}ms budget`);return{expired:A}}async function CT(c,d,h,g){let w=d.now(),A,C,T=0,k={enteringReference:h.initialMinTimestampMs,deviceFloor:h.initialMinTimestampMs,hasPostInvocationEvidence:!1},D,M=Qm({observeScreen:c,timer:d,options:h,start:w,onObservation:g},k),F=async(V)=>{let{capture:W,canProcessRecomposition:G}=zm(V,D);return(await M({observation:W.observation,polls:T,waitMs:d.now()-w,stopped:!1,terminalReason:"timeout"},G,W.generation,W.cachedAt)).outcome},_=()=>Fe(h)-(d.now()-w);while(!0){if(o(h.signal),Um(h,_(),C))return F(C);let V=Ba(k.hasPostInvocationEvidence,k.deviceFloor,k.enteringReference),W=await eh(c,d,h,{start:w,minTimestamp:V,lastCapture:C});if(o(h.signal),"expired"in W)return F(W.expired);let{capture:G}=W,{observation:q,generation:X,cachedAt:Y}=G;T++,C=G;let{isAdmissibleEvidence:Z,isPostInvocation:se}=Ha(q,k);if(Z)D=G;if(jm(q,Z,se))return(await M({observation:q,polls:T,waitMs:d.now()-w,stopped:!1,terminalReason:"screen_off"},Z,X,Y)).outcome;if(Z&&g(q,A,T)&&se){let ee=await M({observation:q,polls:T,waitMs:d.now()-w,stopped:!0,terminalReason:"matched"},!0,X,Y);if(ee.kind==="terminal")return ee.outcome;T=ee.outcome.polls,C=ee.capture,{previous:A,newestTrustworthyCapture:D}=Xm(ee,q,D),await P(d.sleep(Math.min(Math.max(1,h.pollMs),Math.max(0,Fe(h)-(d.now()-w)))),h.signal);continue}if(Z)A=q;if(_()<=0)return F(G);await P(d.sleep(Math.min(h.pollMs,Math.max(0,Fe(h)-(d.now()-w)))),h.signal)}}var th=new Set(["text","view-id","visible-to-user"]),rh=["text","visible-to-user"];function ut(c){let d=c.split("\x00");if(d.length!==4)return;return[d[0],d[1],d[3]].join("\x00")}function ih(c,d){return Ua(Object.keys(hO(c.attributes,d.attributes)))}function Ua(c){return rh.some((d)=>c.includes(d))&&c.every((d)=>th.has(d))}function La(c){let d=new Map;for(let h of H$(c)){let g=ut(h.key);if(g===void 0)continue;let w=h.pathKey.split(Gj).map((A)=>ut(A)??A).join(Gj);d.set(g,d.has(g)?null:w)}return d}function Ji(c,d){let h=La(c),g=La(d),w=new Set;for(let A of new Set([...h.keys(),...g.keys()])){let C=h.get(A);if(C===void 0||C===null||C!==g.get(A))w.add(A)}return w}function Va(c){let d=new Map;for(let h of c){let g=ut(h.key);if(g!==void 0)d.set(g,[...d.get(g)??[],h])}return d}function $a(c){return Ua(Object.keys(c.changes))}function Ga(c,d){let h=new Set,g=Va(c.added);for(let[w,A]of Va(c.removed)){let C=g.get(w);if(A.length===1&&C?.length===1&&ih(A[0],C[0]))h.add(w)}for(let w of c.changed){let A=ut(w.key);if(A!==void 0&&$a(w))h.add(A)}for(let w of d)h.delete(w);return h}class Qi{volatile=new Set;previousChanges=new Set;get volatileCount(){return this.volatile.size}reset(){this.volatile.clear(),this.previousChanges=new Set}mask(c,d=new Set){let h=Ga(c,d),g=new Set([...h].filter((w)=>this.volatile.has(w)));for(let w of h)if(this.previousChanges.has(w))this.volatile.add(w);return this.previousChanges=h,qa(c,g)}}function qa(c,d){let h=(g)=>{let w=ut(g);return w!==void 0&&d.has(w)};return{...c,added:c.added.filter((g)=>!h(g.key)),removed:c.removed.filter((g)=>!h(g.key)),changed:c.changed.filter((g)=>!$a(g)||!h(g.key))}}function za(c,d=new Set){let h=Ga(c,d);return{ticks:h.size,rest:qa(c,h)}}var nh=2500,oh=150,sh=2;function LL(c){return c.added.length===0&&c.removed.length===0&&c.changed.length===0&&c.fields===void 0}function ah(c,d,h){if(d===void 0||ot(d.viewHierarchy)>0||!yf(d,h))return;c.mask(Cp(d,h),Ji(d,h))}class Lm{observeScreen;timer;constructor(c,d=i){this.observeScreen=c;this.timer=d}async captureScreenshot(c,d){await this.observeScreen.captureScreenshot?.(void 0,{signal:d,observation:c})}async execute(c={}){let d=c.timeoutMs??nh,h=c.pollMs??oh,g=c.stableReads??sh,w=0,A=!1,C=new Qi,T=!1,k=Math.max(0,c.volatileExtensionMs??0),D=await CT(this.observeScreen,this.timer,{display:c.display,timeoutMs:d,pollMs:h,signal:c.signal,initialMinTimestampMs:c.initialMinTimestampMs,skipWaitForFresh:c.skipWaitForFresh,get requireFreshExtraction(){return A||c.requireFreshExtraction},resumeOnTerminalMismatch:c.resumeOnTerminalMismatch,hardBudget:c.hardBudget,budgetExtensionMs:()=>T?k:0,skipPerformanceAudit:c.skipPerformanceAudit,skipRecompositionTracking:c.skipRecompositionTracking},(M,F)=>{if(A=ot(M.viewHierarchy)>0,A)return T=!1,w=0,C.reset(),!1;if(F===void 0)return ah(C,c.referenceObservation,M),w=1,w>=g;if(!yf(F,M))return T=!1,C.reset(),w=1,w>=g;let _=Cp(F,M),V=Ji(F,M),W=za(_,V);return T=LL(W.rest)&&(W.ticks>0||T),w=LL(C.mask(_,V))?w+1:1,w>=g});return{observation:D.observation,settled:D.stopped,polls:D.polls,waitMs:D.waitMs,terminalReason:D.terminalReason==="matched"?"settled":D.terminalReason}}}function Ka(c){if(c?.cacheStore)Gie(c.cacheStore);if(c?.screenshotStateStore)Yie(c.screenshotStateStore)}function ja(c){let{device:d,identity:h}=c;return{createHierarchyCapture(g,w){return vn(d,{viewHierarchy:h.viewHierarchy(),settle:new Lm(c.observeScreenProvider(),g),timer:g,ids:w})},createScreenshotRecorder(g,w){return new _i(d,g,Jr(),w)},createHierarchyCollector(g){return new Ni({device:d,viewHierarchy:h.viewHierarchy(),adb:c.adb(),adbFactory:c.adbFactory(),timer:h.timer(),onAvailabilityLost:g?.onAvailabilityLost??(d.platform==="android"?(w)=>{let A=g?.daemonState;(A?A.isInitialized()?A.getSessionManager():void 0:R.sessionManager())?.invalidateAutomationReadinessForDevice(d.deviceId,w)}:void 0)})},createDeviceStateCollector(g,w){return new Bi({device:d,window:g,backStack:w,adb:c.adb(),timer:h.timer()})},createPerformanceAuditor(){return new CL({device:d,adbFactory:c.adbFactory(),observeScreenProvider:c.observeScreenProvider})},createAccessibilityAuditor(){return new $i({device:d,screenshotPathResolver:(g)=>xW(Jr().getPathForObservation(h.device().deviceId,g))})},createAccessibilityStateDetector(){return new Gi({device:d,adb:c.adb()})},createWindowIdentity(){return new mi({deviceStateCollector:h.deviceStateCollector,timer:h.timer,resolveObservationTimestampMs:h.resolveObservationTimestampMs})},createReconciler(){return new pi({xrDisplaySize:c.xrDisplaySize,viewHierarchy:h.viewHierarchy,deviceStateCollector:h.deviceStateCollector,device:h.device,platformValidator:h.platformValidator,resolveObservationTimestampMs:h.resolveObservationTimestampMs,extractScreenSizeFromHierarchy:h.extractScreenSizeFromHierarchy})}}}var Kt=/^\s*(?:Task\s+id\s+#(\d+)\b|\*?\s*TaskRecord\{\S+\s+#(\d+)\b(.*))$/,jt=/^\s*\*\s*Task\{\S+\s+#(\d+)\b(.*)$/;var ch=/^\s*(?:Stack|RootTask)\s+#\d+:(.*)$/,Xa=/(?:^|\s)mode=([^\s}]+)/,dh=/^\s*mBounds=Rect\((-?\d+), (-?\d+) - (-?\d+), (-?\d+)\)/,lh=/^\s*bounds=\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/,uh=/^\s*CurrentConfiguration=.*?winConfig=\{\s*mBounds=Rect\((-?\d+), (-?\d+) - (-?\d+), (-?\d+)\)/,ph=/^\s*CurrentConfiguration=.*?\smWindowingMode=([^\s}]+)/,mh=/^\s*\*\s/;function Zi(c){if(!c)return;let[d,h,g,w]=c.slice(1,5).map((A)=>Number.parseInt(A,10));return g>d&&w>h?{left:d,top:h,right:g,bottom:w}:void 0}function hh(c){let d=c.match(jt);if(d)return{id:Number.parseInt(d[1],10),tail:d[2]};let h=c.match(Kt);if(h)return{id:Number.parseInt(h[1]??h[2],10),tail:h[3]??""};return}class Ya{evidence=new Map;rootTask;current;ownFields=!1;line(c){if(/^\S/.test(c)){this.rootTask=void 0,this.current=void 0;return}let d=c.match(ch);if(d){this.rootTask={mode:d[1].match(Xa)?.[1]},this.current=void 0;return}let h=hh(c);if(h){this.startTask(h.id,h.tail);return}if(mh.test(c))this.ownFields=!1;this.fields(c)}startTask(c,d){let h=this.evidence.get(c)??{};this.evidence.set(c,h),h.headerMode??=d.match(Xa)?.[1],h.rootTaskMode??=this.rootTask?.mode,h.rootTaskBounds??=this.rootTask?.bounds,this.current=h,this.ownFields=!0}fields(c){let d=c.match(dh);if(d){this.overrideBounds(Zi(d));return}if(this.current)this.taskFields(this.current,c)}overrideBounds(c){if(this.current&&this.ownFields)this.current.override??=c;else if(this.rootTask&&!this.current)this.rootTask.bounds=c}taskFields(c,d){let h=d.match(lh);if(h&&this.ownFields){c.resolved??=Zi(h);return}let g=d.match(uh);if(g)c.activityBounds??=Zi(g),c.activityMode??=d.match(ph)?.[1]}}function Ja(c){let d=new Ya;for(let g of c.split(/\r?\n/))d.line(g);let h=new Map;for(let[g,w]of d.evidence){let A=w.headerMode??w.rootTaskMode??w.activityMode,C=w.resolved??w.override??w.rootTaskBounds??w.activityBounds;h.set(g,{...A===void 0?{}:{windowingMode:A},...C===void 0?{}:{bounds:C}})}return h}function Qa(c,d){for(let h of c){let g=d.get(h.id);if(g?.windowingMode!==void 0)h.windowingMode=g.windowingMode;if(g?.bounds!==void 0)h.bounds=g.bounds}}var fh=/(?:^|\s)A=([^\s}]+)/,yh=/(?:^|\s)a?I=([^\s}]+)/,vh=/(?:^|\s)U=(\d+)(?=\s|})/,gh=/Hist\s+#(\d+):\s+ActivityRecord\{\S+\s+u(\d+)\s+([^\s}]+)([^\n]*\})/;function tc(c){let d=c.match(gh);if(!d)return;let h=d[4].match(/(?:^|[\s}])t(\d+)(?=[\s}]|$)/);return{histIndex:parseInt(d[1],10),userId:parseInt(d[2],10),component:d[3],taskId:h?parseInt(h[1],10):void 0}}var rc=/\bHist\s+#\d+:/,ic=/^\s*rootOfTask=(true|false)\b/;function Za(c){let d=c.match(jt);if(d)return ec(parseInt(d[1],10),d[2]);let h=c.match(Kt);if(h)return h[1]!==void 0?{id:parseInt(h[1],10)}:ec(parseInt(h[2],10),h[3]);return}function ec(c,d){let h=d.match(fh),g=d.match(yh),w=d.match(vh);return{id:c,userId:w?parseInt(w[1],10):void 0,affinity:h?h[1]:void 0,component:g?g[1]:void 0}}function en(c,d){let h=c.get(d);if(h===void 0)h={},c.set(d,h);return h}function bh(c,d){if(d.userId!==void 0)c.userId=d.userId;if(d.affinity)c.affinity=d.affinity;if(d.component)c.rootActivity=d.component,c.packageName=d.component.split("/")[0]}function Sh(c,d,h,{histRoots:g,openHist:w}){let A=tc(c);if(A){let C=A.taskId??d;if(h.set(C,(h.get(C)??0)+1),A.histIndex===0)en(g,C).firstHist0??=A.component;w={owner:C,component:A.component,histIndex:A.histIndex}}else if(rc.test(c))h.set(d,(h.get(d)??0)+1),w=void 0;return w}function wh(c,d,h){let g=c.match(/launchedFromPackage=([^\s]+)/);if(g&&h){if(h.launchedFromPackage=g[1]==="null"?void 0:g[1],h.histIndex===0&&h.launchedFromPackage!==void 0)en(d,h.owner).firstHist0LaunchedFromPackage??=h.launchedFromPackage}let w=c.match(ic);if(w&&h){if(w[1]==="true"){let A=en(d,h.owner);if(A.authoritative===void 0)A.authoritative=h.component,A.authoritativeLaunchedFromPackage=h.launchedFromPackage}h=void 0}return h}function Rh(c,d){let h=d.match(/affinity=([^\s]+)/);if(h)c.affinity=h[1];let g=d.match(/realActivity=([^\s]+)/);if(g){let A=g[1];if(c.packageName=A.split("/")[0],!c.rootActivity)c.rootActivity=A}let w=d.match(/numActivities=(\d+)/);if(w)c.numActivities=parseInt(w[1],10)}function Ah(c,d,h){if(c.numActivities===void 0)c.numActivities=d.get(c.id)??0;let g=h.get(c.id),w=g?.authoritative!==void 0?g.authoritativeLaunchedFromPackage:g?.firstHist0LaunchedFromPackage;if(w!==void 0)c.launchedFromPackage=w;if(g===void 0||g.firstHist0===void 0)return;let A=g.authoritative??g.firstHist0;if(c.rootActivity===void 0)c.rootActivity=A;if(c.packageName===void 0)c.packageName=A.split("/")[0]}class BL{adb;timer;constructor(c,d=v,h=i){this.adb=d.create(c),this.timer=h}parseActivities(c){let d=[],h=c.split(/\r?\n/),g=-1,w,A;for(let C=0;C<h.length;C++){let T=h[C],k=Za(T);if(k)g=k.id,w=k.affinity,A=void 0,e.debug(`[BACK_STACK] Found task ID: ${g}`);let D=T.match(/affinity=([^\s]+)/);if(D)w=D[1],e.debug(`[BACK_STACK] Found task affinity: ${w}`);let M=tc(T);if(M){let{histIndex:_,component:V}=M,W=M.taskId??g,G=V.split("/"),q=G[0],X=G[1]||"";if(X.startsWith("."))X=q+X;let Y={name:X,taskId:W,userId:M.userId,taskAffinity:w,isTaskRoot:_===0};d.push(Y),A=Y,e.debug(`[BACK_STACK] Found activity: ${X} (task: ${W})`);continue}if(rc.test(T)){A=void 0;continue}let F=T.match(ic);if(F&&A)A.isTaskRoot=F[1]==="true",A=void 0}return d}parseTasks(c){let d=new Map,h=c.split(/\r?\n/),g=-1,w={id:-1},A=new Map,C=new Map,T,k=()=>{if(g===-1||w.id===void 0)return;d.set(g,w)};for(let D=0;D<h.length;D++){let M=h[D],F=Za(M);if(F)k(),g=F.id,w=d.get(g)??{id:g},bh(w,F),T=void 0,e.debug(`[BACK_STACK] Parsing task: ${g}`);if(g===-1)continue;T=Sh(M,g,A,{histRoots:C,openHist:T}),T=wh(M,C,T),Rh(w,M)}k();for(let D of d.values())Ah(D,A,C);return Array.from(d.values())}getCurrentActivity(c,d){let h=jw(c,d);if(h.displayCount>0)return h.activity?{name:h.activity.activityName,taskId:h.activity.taskId,userId:h.activity.userId}:void 0;let g=c.split(/\r?\n/);for(let w of g){let A=w.match(/(mResumedActivity|mFocusedActivity|topResumedActivity)\s*[:=].*?u(\d+)\s+([^\s]+)(?:\s+t(\d+))?/);if(A){let C=parseInt(A[2],10),T=A[3],k=A[4]?parseInt(A[4],10):-1,D=T.split("/"),M=D[0],F=D[1]||"";if(F.startsWith("."))F=M+F;return e.debug(`[BACK_STACK] Current activity: ${F} (task: ${k})`),{name:F,taskId:k,userId:C}}}return}async execute(c=new U,d,h=0){let g=this.timer.now();try{e.info("[BACK_STACK] Fetching back stack information via dumpsys");let w=await c.track("dumpsysActivities",()=>this.adb.executeCommand("shell dumpsys activity activities",{maxBuffer:ie,signal:d})),[A,C,T]=await c.track("parseBackStack",()=>Promise.all([Promise.resolve(this.parseActivities(w.stdout)),Promise.resolve(this.parseTasks(w.stdout)),Promise.resolve(this.getCurrentActivity(w.stdout,h))]));Qa(C,Ja(w.stdout));let k=T?.taskId||-1,D=A.filter((V)=>V.taskId===k),M=Math.max(0,D.length-1),F={depth:M,activities:A,tasks:C,currentActivity:T,displayCount:jw(w.stdout).displayCount,currentTaskId:k,capturedAt:this.timer.now(),source:"adb"},_=this.timer.now()-g;return e.info(`[BACK_STACK] Back stack retrieved in ${_}ms: depth=${M}, activities=${A.length}, tasks=${C.length}, currentActivity=${T?.name||"unknown"}`),F}catch(w){let A=this.timer.now()-g;return e.warn(`[BACK_STACK] Failed to get back stack after ${A}ms: ${w}`),{depth:0,activities:[],tasks:[],capturedAt:this.timer.now(),partial:!0,source:"adb"}}}}var Ch=(c)=>{if(c.platform==="android")return E.getExistingInstance(c.deviceId)?.getBoundSessionId()??null;if(c.platform==="ios")return x.getExistingInstance(c.deviceId)?.getBoundSessionId()??null;return null};function Ph(c=Ch){return(d)=>{let h=d?c(d):null;return h?fe.getInstanceForSession(h):fe.getInstance()}}var CW=Ph();function DT(c){if(!c||Object.keys(c).length===0)return"";return Dr(Th(c))}function ro(c){let d=c?.trim();return d?d.toLowerCase():void 0}function Th(c){let d={...c};return delete d.deviceId,delete d.sessionUuid,d}class $L{db;timer;constructor({db:c,timer:d=i}={}){this.timer=d,this.db=c??null}getDb(){if(this.db)return this.db;return _e()}async recordOutcome(c){let d=this.getDb(),h=Vr(this.timer),g=DT(c.toolArgs??void 0),w={app_id:c.appId,prediction_id:c.predictionId,timestamp:c.timestamp,from_screen:c.fromScreen,predicted_screen:c.predictedScreen,actual_screen:c.actualScreen,tool_name:c.toolName,tool_args:g,predicted_elements:c.predictedElements.length>0?JSON.stringify(c.predictedElements):null,found_elements:c.foundElements.length>0?JSON.stringify(c.foundElements):null,confidence:c.confidence,match_score:c.matchScore,correct:c.correct?1:0,partial_match:c.partialMatch?1:0,error_type:c.errorType??null,created_at:h};await d.insertInto("prediction_outcomes").values(w).execute(),await this.upsertTransitionStats({appId:c.appId,fromScreen:c.fromScreen,toScreen:c.predictedScreen,toolName:c.toolName,toolArgs:c.toolArgs},c.confidence,c.correct)}async upsertTransitionStats(c,d,h){let g=this.getDb(),w=Vr(this.timer),A=DT(c.toolArgs??void 0),C=Math.pow(d-(h?1:0),2),T=h?1:0,k={app_id:c.appId,from_screen:c.fromScreen,to_screen:c.toScreen,tool_name:c.toolName,tool_args:A,attempts:1,successes:T,total_confidence:d,brier_score_sum:C,updated_at:w,created_at:w};return await g.insertInto("prediction_transition_stats").values(k).onConflict((M)=>M.columns(["app_id","from_screen","to_screen","tool_name","tool_args"]).doUpdateSet((F)=>({attempts:F("prediction_transition_stats.attempts","+",1),successes:F("prediction_transition_stats.successes","+",T),total_confidence:F("prediction_transition_stats.total_confidence","+",d),brier_score_sum:F("prediction_transition_stats.brier_score_sum","+",C),updated_at:w}))).returningAll().executeTakeFirstOrThrow()}async getTransitionStatsForScreen(c,d){return this.getDb().selectFrom("prediction_transition_stats").selectAll().where("app_id","=",c).where("from_screen","=",d).execute()}}class tn{tapByText=new Map;tapById=new Map;swipeByText=new Map;swipeById=new Map;swipeByDesc=new Map;constructor(c){c.forEach((d,h)=>{let g=d.interaction?.toolName;if(g==="tapOn")this.indexTapEdge(d,h);else if(g==="swipeOn")this.indexSwipeEdge(d,h)})}indexTapEdge(c,d){let h=c.interaction?.args;this.addKey(this.tapByText,ro(h?.text),c,d),this.addKey(this.tapById,ro(h?.elementId??h?.id),c,d)}indexSwipeEdge(c,d){let g=c.interaction?.args?.container||c.interaction?.uiState?.scrollPosition?.container;if(!g)return;this.addKey(this.swipeByText,ro(g.text),c,d),this.addKey(this.swipeById,ro(g.elementId||g.resourceId),c,d),this.addKey(this.swipeByDesc,ro(g.contentDesc),c,d)}addKey(c,d,h,g){if(!d||c.has(d))return;c.set(d,{edge:h,index:g})}findMatch(c){let d=ro(c.text),h=ro(c.contentDesc),g=ro(c.resourceId),w,A=(C)=>{if(C&&(!w||C.index<w.index))w=C};if(c.clickable){if(d)A(this.tapByText.get(d));if(h)A(this.tapByText.get(h));if(g)A(this.tapById.get(g))}if(c.scrollable){if(d)A(this.swipeByText.get(d));if(h)A(this.swipeByText.get(h)),A(this.swipeByDesc.get(h));if(g)A(this.swipeById.get(g))}return w?.edge}}class rn{resolveNavigationGraph;elementParser;historyRepository;DEFAULT_CONFIDENCE=0.5;constructor(c=CW,d={}){this.resolveNavigationGraph=c;this.elementParser=d.elementParser??new K,this.historyRepository=d.historyRepository??new $L}async generate(c,d){if(!c.viewHierarchy)return;let h=this.resolveNavigationGraph(d),g=h.getCurrentScreen();if(!g)return;let w=h.getCurrentAppId();if(w&&c.activeWindow?.appId&&w!==c.activeWindow.appId)return;let C=(await h.getEdgesFrom(g)).filter((k)=>k.interaction?.toolName==="tapOn"||k.interaction?.toolName==="swipeOn");if(C.length===0)return;let T=this.extractInteractables(c.viewHierarchy);if(T.length===0)return;return this.buildPredictions(T,C,h,{currentScreen:g,appId:w})}async buildPredictions(c,d,h,{currentScreen:g,appId:w}){let A=[],C=[],T=new Set,k=new Map,D=w?await this.historyRepository.getTransitionStatsForScreen(w,g):[],M=new Map;for(let _ of D){let V=this.buildTransitionKey(_.from_screen,_.to_screen,_.tool_name,_.tool_args);M.set(V,_)}let F=new tn(d);for(let _ of c){let V=F.findMatch(_);if(!V||!V.interaction)continue;let W=Ih(V,_);if(!W)continue;let G=this.buildEdgeKey(V);if(!T.has(G)){let q=await this.getPredictedElements(h,V.to,k),X=this.getAdjustedConfidence(M.get(this.buildTransitionKey(g,V.to,V.interaction.toolName,DT(V.interaction.args))));A.push({action:V.interaction.toolName,target:W,predictedScreen:V.to,predictedElements:q.length>0?q:void 0,confidence:X}),T.add(G)}C.push({elementId:_.resourceId,elementText:_.text,elementContentDesc:_.contentDesc,predictedOutcome:{screenName:V.to,basedOn:"navigation_graph"}})}if(A.length===0&&C.length===0)return;return{likelyActions:A,interactableElements:C}}extractInteractables(c){if(!c)return[];let d=this.elementParser.flattenViewHierarchy(c),h=[];for(let{element:g}of d){let w=g.clickable===!0||g.clickable==="true",A=g.scrollable===!0||g.scrollable==="true";if(!w&&!A)continue;h.push({element:g,text:g.text,contentDesc:g["content-desc"],resourceId:g["resource-id"],clickable:w,scrollable:A})}return h}buildEdgeKey(c){let d=c.interaction?.args??{};return`${c.from}:${c.to}:${c.interaction?.toolName}:${JSON.stringify(d)}`}buildTransitionKey(c,d,h,g){return`${c}:${d}:${h}:${g}`}getAdjustedConfidence(c){if(!c)return this.DEFAULT_CONFIDENCE;let d=c.attempts,h=d>0?c.successes/d:this.DEFAULT_CONFIDENCE;return this.adjustConfidence(this.DEFAULT_CONFIDENCE,h,d)}adjustConfidence(c,d,h){let g=Math.min(h/100,0.8),w=1-g,A=c*w+d*g;return Math.max(0,Math.min(1,A))}async getPredictedElements(c,d,h){if(h.has(d))return h.get(d)??[];let g=await c.getEdgesFrom(d),w=new Set;for(let C of g){let T=C.interaction?.uiState?.selectedElements;if(!T)continue;for(let k of T){let D=k.text||k.resourceId||k.contentDesc;if(D)w.add(D)}}let A=Array.from(w);return h.set(d,A),A}}function Ih(c,d){let h=c.interaction?.args,g=c.interaction?.uiState,w=c.interaction?.toolName;if(w==="tapOn")return kh(h,d);if(w==="swipeOn")return xh(h,g);return null}function kh(c,d){let h=c?.text??d.text,g=c?.elementId??c?.id??d.resourceId,w=d.contentDesc;if(!h&&!g&&!w)return null;return{text:h,elementId:g,contentDesc:w}}function xh(c,d){let{container:h,lookFor:g}=Dh(c,d),w={};if(h)w.container=nc(h);if(g)w.lookFor=nc(g);if(!w.container&&!w.lookFor)return null;return w}function Dh(c,d){let h=c?.container||d?.scrollPosition?.container,g=c?.lookFor||d?.scrollPosition?.targetElement;return{container:h,lookFor:g}}function nc(c){return{text:c.text,elementId:c.elementId||c.resourceId,contentDesc:c.contentDesc}}class nn{inner;timer;observeBudgetMs;constructor(c,d,h=750){this.inner=c;this.timer=d;this.observeBudgetMs=h}async read(c,d){let h=Error("iOS lock-state reading pending");try{return await l(()=>this.inner.read(c),{timer:this.timer,signal:d,timeoutMs:this.observeBudgetMs,label:"iOS lock-state observation",timeoutError:()=>h})}catch(g){if(d?.aborted)return e.debug("[iOS] Lock-state caller aborted"),{kind:"unknown",reason:"pending",message:"caller aborted"};if(g===h)return e.debug("[iOS] Lock-state probe still pending after observe budget"),{kind:"unknown",reason:"pending"};return e.warn(`[iOS] Budgeted lock-state probe failed: ${r(g)}`,g),{kind:"unknown",reason:"error",message:r(g)}}}}class sn{inner;timer;options;entries=new Map;settling=new Set;epochs=new Map;lockTransitions=new Map;constructor(c,d,h={}){this.inner=c;this.timer=d;this.options=h}invalidate(c,d={}){if(this.entries.delete(c),this.settling.add(c),this.epochs.set(c,(this.epochs.get(c)??0)+1),d.expectLocked)this.lockTransitions.set(c,this.timer.now()+(this.options.lockTransitionMs??5000));else this.lockTransitions.delete(c)}async read(c,d){try{return await l(()=>this.sharedRead(c),{timer:this.timer,signal:d,label:"iOS lock-state cache"})}catch(h){if(d?.aborted)return e.debug("[iOS] Lock-state cache caller aborted"),{kind:"unknown",reason:"pending",message:"caller aborted"};return e.warn(`[iOS] Lock-state cache failed: ${r(h)}`,h),{kind:"unknown",reason:"error",message:r(h)}}}sharedRead(c){let d=this.entries.get(c);if(d?.reading){if(this.timer.now()<d.expiresAt){let g=d.reading.kind==="known"?void 0:this.staleReading(d);return Promise.resolve(g??d.reading)}}if(!d?.flight)d={expiresAt:0,epoch:this.epochs.get(c)??0,lastKnown:d?.lastKnown},this.entries.set(c,d),d.flight=this.fill(c,d);let h=this.staleReading(d);return h?Promise.resolve(h):d.flight}staleReading(c){let d=c.lastKnown;if(!d)return;let h=d.lock.locked?this.options.staleLockedMs??1e4:this.options.staleUnlockedMs??120000;return this.timer.now()-d.staleSince<h?{kind:"known",lock:d.lock}:void 0}async readInner(c){try{return await Je(async()=>this.inner.read(c))}catch(d){return this.probeFailure(d)}}probeFailure(c){return e.warn(`[iOS] Shared lock-state probe failed: ${r(c)}`,c),{kind:"unknown",reason:"error",message:r(c)}}isCurrent(c,d){return(this.epochs.get(c)??0)===d.epoch}awaitingLock(c,d,h){let g=this.lockTransitions.get(c);return g!==void 0&&this.isCurrent(c,d)&&h.kind==="known"&&!h.lock.locked&&this.timer.now()<g}async awaitLockTransition(c,d,h){let g=h;while(this.awaitingLock(c,d,g))await this.timer.sleep(this.options.lockTransitionPollMs??250),g=await this.readInner(c);return g}async fill(c,d){let h;try{h=await Je(async()=>this.inner.read(c))}catch(g){h=this.probeFailure(g)}if(this.awaitingLock(c,d,h))h=await this.awaitLockTransition(c,d,h);if(this.isCurrent(c,d)){let g=this.options.failureTtlMs??5000;if(h.kind==="known"){if(this.lockTransitions.delete(c),g=h.lock.locked?this.options.lockedTtlMs??2000:this.options.knownTtlMs??30000,this.settling.delete(c))g=Math.min(g,this.options.settleTtlMs??2000)}if(d.reading=h,d.expiresAt=this.timer.now()+g,h.kind==="known")d.lastKnown={lock:h.lock,staleSince:d.expiresAt};d.flight=void 0}return h}}var Oh;function hu(){return Oh??=new sn(new AT(new L,{timeoutMs:4000}),i)}var Eh={getViewHierarchy:async()=>({hierarchy:{error:"Hierarchy connection unavailable",unavailableReason:"connection_lost"}}),configureRecompositionTracking:async()=>{},findFocusedElement:()=>null,findAccessibilityFocusedElement:()=>null,filterOffscreenNodes:(c)=>c};function ae(c,d){return c??d()}function oc(c,d,h){return c?d():h()}function sc(c){let{device:d,adbFactory:h,dependencies:g}=c;return ae(g?.viewHierarchy,()=>oc(g?.deviceReadOnly,()=>Eh,()=>new Xi(d,h)))}function Mh(c){let{device:d,adbFactory:h,timer:g,idGenerator:w,wiring:A,dependencies:C}=c,T=C?.deviceReadOnly;return{hierarchyCapture:ae(C?.hierarchyCapture,()=>A.createHierarchyCapture(g,w)),screenshotService:ae(C?.screenshot,()=>oc(T,()=>Mo.forObservationRead(d),()=>new Mo(d,{adbFactory:h}))),window:ae(C?.window,()=>new Il(d,h)),backStack:ae(C?.backStack,()=>new BL(d,h)),predictiveUIState:ae(C?.predictiveUIState,()=>new rn)}}function Fh(c,d){let{wiring:h,dependencies:g}=c,w=g?.screenshotPathProtection??$n;return{pathProtection:w,screenshotRecorder:ae(g?.screenshotRecorder,()=>h.createScreenshotRecorder(d.screenshotService,w)),screenshotEvidenceFiles:g?.screenshotEvidenceFiles}}function _h(c,d){let{wiring:h,dependencies:g}=c;return{hierarchyCollector:ae(g?.hierarchyCollector,()=>h.createHierarchyCollector(g)),deviceStateCollector:ae(g?.deviceStateCollector,()=>h.createDeviceStateCollector(d.window,d.backStack)),iosLockStateProbe:ae(g?.iosLockStateProbe,()=>new nn(hu(),c.timer)),performanceAuditor:ae(g?.performanceAuditor,()=>h.createPerformanceAuditor()),accessibilityAuditor:ae(g?.accessibilityAuditor,()=>h.createAccessibilityAuditor()),accessibilityStateDetector:ae(g?.accessibilityStateDetector,()=>h.createAccessibilityStateDetector()),platformValidator:ae(g?.platformValidator,()=>new Qr),windowIdentity:ae(g?.windowIdentityFreshnessResolver,()=>h.createWindowIdentity()),reconciler:ae(g?.activeWindowAttributionReconciler,()=>h.createReconciler())}}function Nh(c,d){return Ka(c.dependencies),{...Fh(c,d),..._h(c,d)}}function ac(c){let d=Mh(c);return{sources:d,services:Nh(c,d)}}var cc={screenSizeUnits:()=>"physical-pixels",settledScreenshotOrientation:()=>"display",isIosMultiPanel:()=>!1,grantsObservationRead:(c)=>c.viewHierarchy?.fresh===!0},Bh={...cc,grantsObservationRead:()=>!0};function Hh(c){return{screenSizeUnits:()=>"points",settledScreenshotOrientation:()=>"native",isIosMultiPanel:()=>(c().displays?.panels.length??0)>1,grantsObservationRead:(d)=>Cs(d.viewHierarchy)}}function dc(c,d){if(c==="ios")return Hh(d);return c==="android"?cc:Bh}function an(c,d,h){let{result:g,displayRequest:w}=d,A=w!==void 0&&w!=="active",C=A?Ai(c,w,{activePanelKey:h?.display.key,posture:g.display.posture}):void 0;return{explicitlyRouted:A,requestedPanel:C}}function lc(c,d,h,g){if(h)return;if(Ce.checkIdentity(c,d.display,"ios"),g)Ce.checkIosGeometry(c,d.screenSize,d.observationId,d.display)}function Lh(c){return Boolean(c.viewHierarchy?.hierarchy?.error||c.viewHierarchy?.hierarchy?.unavailableReason||c.viewHierarchy?.ctrlProxyIncomplete&&!c.viewHierarchy.hierarchy?.node)}function Vh(c,d){let h=c.viewHierarchy?.hierarchy;if(d!==0&&(h?.error||h?.unavailableReason))return new Kn(h.unavailableDetail??h.error??"Selected display hierarchy is unavailable");return new Kn("CtrlProxy APK too old for display routing; update it and retry the observation.")}function Uh({result:c,requestedPanel:d,requestedDisplayId:h,preserveDisplayState:g},w,A){if(h!==void 0&&typeof w!=="number"&&!A&&!(g&&Lh(c)))throw Vh(c,h);if(h!==void 0&&typeof w==="number"&&w!==h)throw new Kn(`Selected display "${d?.key}" returned hierarchy for display ${w}; retry the observation.`)}function Wh(c,d){if(c&&d&&c.key!==d.key)throw new Kn(`Selected display "${c.key}" returned content from "${d.key}"; retry the observation.`)}class cn{deps;constructor(c){this.deps=c}resolveTarget(c){return this.resolveTargetAsync(c)}async resolveTargetAsync(c){let{result:d,androidDisplayCache:h,signal:g}=c,w=this.deps.device(),A=this.deps.adb(),C=await h.resolve(w,A,g);if(C)d.display=C.display;let{explicitlyRouted:T,requestedPanel:k}=an(w,c,C),D=k?await h.logicalIdForPanel(w,A,k.key,g):void 0;if(k)d.display={...d.display,key:k.key,role:k.role};return{observedAndroid:C,explicitlyRouted:T,requestedPanel:k,requestedDisplayId:D}}bindFinalDisplay(c){if(!this.deps.device().displays?.panels.length)return{recordProvenance:c.recordProvenance};return this.bindFinalDisplayAsync(c)}async bindFinalDisplayAsync(c){let{result:d,androidDisplayCache:h,observedAndroid:g,requestedPanel:w,explicitlyRouted:A,signal:C}=c,T=c.recordProvenance,k=this.deps.device(),D=this.deps.adb(),M=d.viewHierarchy?.displayId,F=d.viewHierarchy?.panelUniqueId;Uh(c,M,F);let _=typeof M==="number"||F?await h.panelForLogicalId(k,D,M,{signal:C,identity:{panelUniqueId:F,panelFingerprint:d.viewHierarchy?.panelFingerprint},allowProbe:A}):void 0;Wh(w,_);let V=Ce.geometryChanged(k.deviceId,d.screenSize),W=V&&!A?await h.resolve(k,D,C,!0):g;return d.display.posture=await h.posture(k,D,C,V&&!A),this.applyBoundPanel(c,k,_?.key,W?.display.key),T=this.recordFinalIdentity(c,k,T),{recordProvenance:T}}applyBoundPanel({result:c,displayRequest:d,requestedPanel:h},g,w,A){let C=h??Ai(g,d,{focusedPanelKey:w,activePanelKey:A,posture:c.display.posture});c.display={...c.display,key:C.key,role:C.role}}recordFinalIdentity({result:c,explicitlyRouted:d,preserveDisplayState:h,observerMode:g},w,A){if(!d&&!h&&!g&&Ce.revision(w.deviceId)===A.revision)Ce.checkIdentity(w.deviceId,c.display),A={revision:Ce.revision(w.deviceId),identityRevision:Ce.identityRevision(w.deviceId)};return A}}class dn{deps;constructor(c){this.deps=c}resolveTarget(c){let{explicitlyRouted:d,requestedPanel:h}=an(this.deps.device(),c,void 0);return{observedAndroid:void 0,explicitlyRouted:d,requestedPanel:h,requestedDisplayId:void 0}}bindFinalDisplay(c){let{result:d,displayRequest:h,explicitlyRouted:g,preserveDisplayState:w,observerMode:A}=c,C=c.recordProvenance,T=this.deps.device();if(d.display=rO(T,d.viewHierarchy,Fj(d)),!A&&!w&&Ce.revision(T.deviceId)===C.revision)lc(T.deviceId,d,g,(T.displays?.panels.length??0)>1),C={revision:Ce.revision(T.deviceId),identityRevision:Ce.identityRevision(T.deviceId)};let k=Ai(T,h,{focusedPanelKey:d.display.key,activePanelKey:d.display.key,posture:d.display.posture});if(g&&k.key!==d.display.key)throw new Kn(`Display "${k.key}" is not the active panel on iOS. Active panel: ${d.display.key}`);return{recordProvenance:C}}}var uc=new Set(["com.android.permissioncontroller","com.google.android.permissioncontroller"]),pc="android.permission.POST_NOTIFICATIONS";function ln(c){return c!==void 0&&uc.has(c)}function I3(c){return ln(c)||c!==void 0&&/permissioncontroller/i.test(c)}function $h(c,d){return c===d||c.startsWith(`${d}.`)}function DW(c){if(!c||!ln(c.appId)||c.activityName==="")return c;return[...uc].some((h)=>$h(c.activityName,h))?c:{...c,activityName:""}}function qh(c){let d=c.text??c["content-desc"];return typeof d==="string"&&d.trim()!==""?d.trim():void 0}function Qh(c,d){if(c.enabled!==void 0&&!ht(c.enabled))return!1;if(c.package!==void 0&&c.package!==d)return!1;let h=c["resource-id"]??"",g=typeof c.class==="string"?c.class:"";return/button/i.test(h)||/Button$/.test(g)}function ef(c,d){let h=(c.elements?.clickable??[]).filter((g)=>Qh(g,d)).map(qh).filter((g)=>g!==void 0);return[...new Set(h)]}function qte(c,d){let h=tf(d);if(!d||!h||h===c)return;let g=rf(d);if(!(g?I3(h):ln(h)))return;return{kind:"permission_dialog",packageName:h,...g?{permission:pc}:{},actions:ef(d,h)}}function tf(c){return c?.activeWindow?.appId||c?.viewHierarchy?.packageName}function rf(c){return c.notificationPermissionDetected===!0||c.activeWindow?.type==="notification_permission_dialog"}function Vte(c){let d=c.permission===pc?"a notification permission dialog":"a permission dialog",h=c.actions.length>0?`tap ${c.actions.map((g)=>`"${g}"`).join(" or ")}`:"answer it with tapOn";return`blocked by ${d} (${c.packageName}); ${h}, or pre-grant with setAppPermissions`}var nf=1;function mc(c){if(typeof c!=="string")return;let d=c.trim();return d.length>0?d:void 0}function of(c,d){let h=new Set(OY(c).map((A)=>A.id)),g=(pd(c.hierarchy,c.windows)??[]).filter((A)=>A.type===nf&&A.hierarchy!==void 0&&(A.packageName===void 0||A.packageName===d)&&!h.has(A.id)),w=g.toSorted((A,C)=>(C.windowLayer??0)-(A.windowLayer??0))[0];return(g.find((A)=>A.isFocused)??g.find((A)=>A.isActive)??w)?.hierarchy}function sf(c){let d=[c];while(d.length>0){let h=d.shift(),g=mc(we(h)["pane-title"]);if(g)return g;let w=h.node;if(w)d.unshift(...Array.isArray(w)?w:[w])}return}function OW(c,d){let h=mc(c?.packageName);if(!c||!h)return;if(d?.platform==="android"&&d.source==="sdk"&&d.components.bundleId===h)return d;let g=of(c,h),w=g?sf(g):void 0;if(!w)return;return{platform:"android",source:"heuristic",confidence:"medium",key:JSON.stringify([["package",h],["paneTitle",w]]),components:{bundleId:h,navigationTitle:w}}}function pn(c){if((c.backStack?.displayCount??0)>1&&c.activeWindow){let d=$e(c);if(d)c.activeWindow={...c.activeWindow,appId:d.packageName,activityName:d.activityName}}}function af(c){let d=c.viewHierarchy,h=d?.packageName,g=c.activeWindow?.appId,w=d?.sources?.length===1&&d.sources[0]==="uiautomator";if(!h||!g||!w||!c.activeWindow)return!1;return c.activeWindow={...c.activeWindow,appId:h,activityName:""},!0}class mn{deps;xrDisplaySize;constructor(c){this.deps=c;this.xrDisplaySize=c.xrDisplaySize??new Ke(c)}async collect(c){let{result:d,queryOptions:h,perf:g,skipWaitForFresh:w,minTimestamp:A,signal:C,readOnly:T,capturedHierarchy:k,readOptions:D}=c;g.serial("phase1_hierarchy"),await this.deps.hierarchyCollector().collect(d,{queryOptions:h,perf:g,skipWaitForFresh:w,minTimestamp:A,signal:C,readOnly:T,capturedHierarchy:k,readOptions:D}),g.end();let M=d.viewHierarchy;if(M?.screenWidth&&M?.screenHeight){d.screenSize={width:M.screenWidth,height:M.screenHeight},await this.xrDisplaySize.prime(d,M,C,c.displayId),this.xrDisplaySize.applyCached(d,M,c.displayId),this.applyHierarchyDeviceMetadata(d,M);let F=this.startDeviceStateTasks(c,!M.wakefulness);if(F.length>0)await Promise.all(F);e.debug("[OBSERVE] Using device metadata from accessibility service")}else this.applyKnownPanelScreenSize(d),await Promise.all(this.startDeviceStateTasks(c,!0));if(!d.activeWindow)await this.deps.deviceStateCollector().collectActiveWindow(d,T);if(this.backfillActiveWindowPackage(d),pn(d),await this.applyAndroidScreenIdentity(d),d.activeWindow=DW(d.activeWindow),this.deps.device().formFactor==="automotive")await this.deps.deviceStateCollector().collectAutomotive(d,C,c.displayId);if(d.notificationPermissionDetected&&d.activeWindow)d.activeWindow.type="notification_permission_dialog"}applyHierarchyDeviceMetadata(c,d){if(d.rotation!==void 0)c.rotation=d.rotation;if(d.systemInsets)c.systemInsets=d.systemInsets;if(d.insets)c.insets=d.insets;if(d.foregroundActivity&&!ci(d.foregroundActivity))this.applyAndroidForegroundActivity(c,d.foregroundActivity)}startDeviceStateTasks({result:c,perf:d,signal:h,skipBackStack:g,displayId:w},A){let C=[];if(A)C.push(d.track("wakefulness",()=>this.deps.deviceStateCollector().collectWakefulness(c,h)));else c.wakefulness=c.viewHierarchy?.wakefulness,c.wakefulnessSource="hierarchy";if(C.push(d.track("deviceLock",()=>this.deps.deviceStateCollector().collectDeviceLock(c,h))),!g)C.push(d.track("backStack",()=>this.deps.deviceStateCollector().collectBackStack(c,d.fork(),h,w)));return C}backfillActiveWindowPackage(c){if(af(c))return;if(c.viewHierarchy?.packageName&&!c.activeWindow?.appId)c.activeWindow=c.activeWindow?{...c.activeWindow,appId:c.viewHierarchy.packageName}:{appId:c.viewHierarchy.packageName,activityName:"",layoutSeqSum:0}}async applyAndroidScreenIdentity(c){let d=c.viewHierarchy?.packageName;if(!d)return;let h;try{h=await this.deps.viewHierarchy().getScreenIdentity?.(d)}catch(w){e.debug(`[Android] SDK screen identity read failed; using hierarchy identity: ${r(w)}`)}let g=OW(c.viewHierarchy,h);if(g)c.screenIdentity=g}applyAndroidForegroundActivity(c,d){let h=d.split("/"),g=h[0],w=h[1]?.startsWith(".")?g+h[1]:h[1]||"";c.activeWindow={appId:g,activityName:w,layoutSeqSum:0}}applyKnownPanelScreenSize(c){if(e.warn("[OBSERVE] No screen dimensions from accessibility service"),c.screenSize.width>0&&c.screenSize.height>0)return;let d=this.deps.device(),h=c.display?.key,g=h?d.displays?.panels.find((w)=>w.key===h):VD(d.displays,"active",{focusedPanelKey:Ce.observedPanel(d.deviceId)?.key});if(!g){e.warn(`[OBSERVE] Display ${h} is not in the display inventory; leaving screen size unknown`);return}if(g.sizePx.width>0&&g.sizePx.height>0)c.screenSize={...g.sizePx}}}var cf="sdkBridge",hc="sdk-element-id";function Tv(c){let d=c[hc],h=Number(c[HC]);if(typeof d!=="string"||d.length===0||!Number.isSafeInteger(h))return null;return{elementId:d,observationIdentity:h}}function zC(c,d){let h=c?.hierarchy?.node,g=Array.isArray(h)?[...h]:h&&typeof h==="object"?[h]:[];for(let w=g.pop();w;w=g.pop()){let A=Tv(we(w));if(A&&(d===void 0||A.elementId===d))return A;g.push(...Ra(w))}return null}function fc(c,d){if(!c.visible)return null;let h=c.enabled,g=c.role.toLowerCase()==="textfield",w={"resource-id":c.id,"test-tag":c.id,class:c.role,role:g?"textfield":c.role,...g?{focusable:"true","input-type":"text",actions:["set_text"]}:{},bounds:{...c.bounds},enabled:String(c.enabled),[hc]:c.id,[HC]:String(d),...c.label!==void 0?{"content-desc":c.label}:{},...c.value!==void 0?{text:c.value}:{},...h?{clickable:"true"}:{},...c.focused?{focused:"true"}:{}},A=c.children.map((C)=>fc(C,d)).filter((C)=>C!==null);return{$:w,extras:{"sdk.source":cf},...A.length>0?{node:A}:{}}}function pt(c){if(c===null||typeof c!=="object")return null;let{left:d,top:h,right:g,bottom:w}=c;if([d,h,g,w].some((A)=>typeof A!=="number"))return null;return`${d},${h},${g},${w}`}function yc(c,d){if(!c.visible)return;let h=pt(c.bounds);if(h){for(let g of[c.id,c.label,c.value])if(g)d.add(`${h}|${g}`)}for(let g of c.children)yc(g,d)}function lf(c,d){if(Ra(c).length>0)return!1;let h=pt(qt(c));if(!h)return!1;let g=we(c);return["resource-id","content-desc","text"].some((w)=>{let A=g[w];return typeof A==="string"&&A.length>0&&d.has(`${h}|${A}`)})}function vc(c,d){let h=Ra(c);if(h.length===0)return 0;let g=h.filter((A)=>!lf(A,d)),w=h.length-g.length;c.node=g;for(let A of g)w+=vc(A,d);return w}function gc(c){return 1+Ra(c).reduce((d,h)=>d+gc(h),0)}function wc(c,d){let h=c.hierarchy?.node;if(!h||!d.root||d.coordinateSpace!=="screen")return null;let g=fc(d.root,d.captureIdentity);if(!g)return null;let w=new Set;yc(d.root,w);let A=vc(h,w);return h.node=[...Ra(h),g],{attached:gc(g),deduplicated:A}}var hn=2000;function uf(c){let d=c.enabled??(()=>N.isIosSdkObservationBridgeEnabled()),h=c.timer??i,g=(w)=>w.failure??w.error??"no observation";return{async observe(w,A,C=1/0){let T=h.now()+Math.max(0,C),k=()=>Math.max(0,Math.min(hn,T-h.now())),D=d()?c.client():null;if(!D||k()<=0)return{kind:"none"};let M;try{M=await D.getObservationBridgeStateForIos(w,k())}catch(V){return e.debug(`[iOS] SDK bridge discovery failed; observing with XCTest: ${r(V)}`),{kind:"none"}}if(M.status!=="available")return e.debug(`[iOS] SDK bridge unavailable for ${w}: ${M.reason}`),{kind:"none"};if(k()<=0)return{kind:"unavailable",detail:"search budget exhausted"};let F;try{F=await D.requestSdkObservationForIos({timeoutMs:k(),signal:A})}catch(V){return e.warn(`[iOS] SDK bridge snapshot failed for ${w}: ${r(V)}`,V),{kind:"unavailable",detail:r(V)}}if(_k(F),F.success&&F.observation)return{kind:"observation",observation:F.observation};let _=g(F);return e.warn(`[iOS] SDK bridge snapshot unavailable for ${w}: ${_}`),{kind:"unavailable",detail:_}}}}function MW(c,d){return uf({client:()=>x.getExistingInstance(c.deviceId),timer:d})}async function NW(c,d,h,g){let w=c.packageName;if(!w)return{};let A=await d.observe(w,h,g);if(A.kind==="none")return{};if(A.kind==="observation"&&A.observation.bundleId!==void 0&&A.observation.bundleId!==w)return e.debug(`[iOS] SDK snapshot app ${A.observation.bundleId} differs from hierarchy app ${w}; skipping merge`),{backend:"xctest",fallbackReason:"unavailable"};let C=A.kind==="observation"?wc(c,A.observation):null;if(C)return Wj(c),e.debug(`[iOS] Merged ${C.attached} SDK bridge nodes (${C.deduplicated} XCTest duplicates removed)`),{backend:"sdk"};return{backend:"xctest",fallbackReason:"unavailable"}}var mf="sdkWebBridge",Rc="web-view-id";var Tc="web-element-id",hf="web-origin",Ic="web-document-id",kc="web-role",ff=new Set(["input","textarea"]);function Wte(c){let d=c[kc],h=typeof d==="string"&&ff.has(d)?FW(c):null;return h?.documentId?h:null}var vf=new Set(["input","textarea","textbox","searchbox","combobox"]),gf=new Set(["text","search","email","url","tel","password","number"]);function bf(c,d){if(d!=="input")return vf.has(d);return gf.has((c.inputType??"text").toLowerCase())}var Sf="[REDACTED]",wf="WKWebView";function FW(c){let d=c[Rc],h=c[qC],g=c[Tc];if(typeof d!=="string"||typeof h!=="string"||typeof g!=="string"||!d||!h||!g)return null;let w=c[Ic];return typeof w==="string"&&w?{webViewId:d,snapshotId:h,elementId:g,documentId:w}:{webViewId:d,snapshotId:h,elementId:g}}function zte(c,d,h){let g=c?.hierarchy?.node,w=Array.isArray(g)?[...g]:g&&typeof g==="object"?[g]:[];for(let A=w.pop();A;A=w.pop()){let C=FW(we(A));if(C&&C.webViewId===d&&C.elementId===h)return C;w.push(...Ra(A))}return null}function Rf(c){if(c===null||typeof c!=="object")return null;let{left:d,top:h,right:g,bottom:w}=c;if(typeof d!=="number"||typeof h!=="number"||typeof g!=="number"||typeof w!=="number")return null;return{left:d,top:h,right:g,bottom:w}}function Cf(c){let d=we(c);return(d.class??d.className)===wf}function UL(c){let d=[],h=(A)=>{if(Cf(A)){d.push(A);return}Ra(A).forEach(h)},g=c?.hierarchy?.node;return(Array.isArray(g)?g:g&&typeof g==="object"?[g]:[]).forEach(h),d}function Pf(c){if(!c||!URL.canParse(c))return;let d=new URL(c).origin;return d==="null"?void 0:d}function If(c,d){if(!(c!==void 0&&[c.offsetLeft,c.offsetTop,c.width].every(Number.isFinite)&&c.width>0))return{offsetLeft:0,offsetTop:0,pointsPerPixel:1};return{offsetLeft:c.offsetLeft,offsetTop:c.offsetTop,pointsPerPixel:(d.right-d.left)/c.width}}function xf(c,d,h){let[g,w,A,C]=c.bounds;if([g,w,A,C].some((V)=>V===void 0||!Number.isFinite(V)))return null;let T=d.left+(g-h.offsetLeft)*h.pointsPerPixel,k=d.top+(w-h.offsetTop)*h.pointsPerPixel,D=Math.trunc(Math.max(d.left,T)),M=Math.trunc(Math.max(d.top,k)),F=Math.trunc(Math.min(d.right,T+A*h.pointsPerPixel)),_=Math.trunc(Math.min(d.bottom,k+C*h.pointsPerPixel));return F>D&&_>M?{left:D,top:M,right:F,bottom:_}:null}function Df(c){let d=new Set,h=new Set;for(let{id:g}of c)(d.has(g)?h:d).add(g);return h}function Of(c,d){if(c.value!==Sf)return c.value?{text:c.value}:{};return typeof d?.value==="string"?{}:{[yE]:"true"}}function Ef(c,d,h,{origin:g,native:w}={}){let A=c.role??"element",C=bf(c,A);return{$:{class:A,role:C?"textfield":A,...C?{focusable:"true","input-type":"text"}:{},enabled:String(c.enabled),...c.label?{"content-desc":c.label}:{},...Of(c,w),...c.enabled?{clickable:"true"}:{},...c.focused&&!w?{focused:"true"}:{},...w,bounds:d,[Rc]:h.webViewId,[qC]:h.snapshotId,...h.documentId?{[Ic]:h.documentId}:{},[Tc]:c.id,[kc]:A,...g?{[hf]:g}:{}},extras:{"sdk.source":mf}}}function Mf(c,d){let h=pt(d);return h?[c.label,c.value].flatMap((g)=>g?[`${h}|${g}`]:[]):[]}function xc(c,d,h,g){let w=Ra(c);if(w.length===0)return 0;let A=0,C=w.flatMap((T)=>{let k=Ra(T).length===0?Ff(T,d):void 0;if(k===void 0)return A+=xc(T,d,h,g),[T];if(A+=1,g.has(k))return[];g.add(k);let D=Object.fromEntries(Object.entries(we(T)).filter(([M])=>M!=="bounds"));return[h(k,D)]});return c.node=C,A}function Ff(c,d){let h=pt(qt(c));if(!h)return;let g=we(c),w=new Set(["resource-id","content-desc","text"].flatMap((A)=>{let C=g[A],T=typeof C==="string"&&C?d.get(`${h}|${C}`):void 0;return T===void 0?[]:[T]}));return w.size===1?[...w][0]:void 0}function Dc(c,d){let h=UL(c);if(d.length!==1||h.length!==1)return null;let g={webViews:0,attached:0,deduplicated:0};return h.forEach((w,A)=>{let{webViewId:C,snapshot:T}=d[A],k=Rf(qt(w));if(!T||!k)return;let D=Pf(T.url),M=Df(T.elements),F=If(T.viewport,k),_=T.elements.flatMap((Y)=>{let Z=Y.id!==""&&!M.has(Y.id),se=Y.visible&&Z?xf(Y,k,F):null;return se?[{element:Y,bounds:se}]:[]});if(_.length===0)return;let V=new Map,W=new Set;_.forEach(({element:Y,bounds:Z},se)=>{for(let J of new Set(Mf(Y,Z)))if(V.has(J))W.add(J);else V.set(J,se)}),W.forEach((Y)=>V.delete(Y));let G=(Y,Z)=>{let{element:se,bounds:J}=_[Y],ee={webViewId:C,snapshotId:T.snapshotId,documentId:T.documentId};return Ef(se,J,ee,{origin:D,native:Z})},q=new Set;g.deduplicated+=xc(w,V,G,q);let X=_.flatMap((Y,Z)=>q.has(Z)?[]:[G(Z)]);w.node=[...Ra(w),...X],g.webViews+=1,g.attached+=_.length}),g.webViews>0?g:null}async function _f(c,d){try{return await c.requestSdkWebSnapshotForIos(d)}catch(h){return e.warn(`[iOS] SDK web-view snapshot failed: ${r(h)}`,h),null}}function Nf(c){let d=c.enabled??(()=>N.isIosSdkObservationBridgeEnabled()),h=c.timer??i;return{async snapshots(g,w=1/0){let A=h.now()+Math.max(0,w),C=()=>Math.max(0,Math.min(hn,A-h.now())),T=d()?c.client():null;if(!T)return[];let k=C();if(k===0)return e.debug("[iOS] SDK web-view snapshot skipped: time budget exhausted"),[];let D=await _f(T,{signal:g,timeoutMs:k});if(D&&!D.success&&D.failure==="bad_reply")e.warn(`[iOS] SDK web-view snapshot failed: ${D.error??D.failure}`);let M=D?.webViews??[];if(M.length>1)return M.map(({webViewId:F})=>({webViewId:F}));return M.map(({webViewId:F})=>({webViewId:F,...D?.success&&D.snapshot&&D.webViewId===F?{snapshot:D.snapshot}:{}}))}}}function OT(c,d){return Nf({client:()=>x.getExistingInstance(c.deviceId),timer:d})}async function LW(c,d,h,g){if(UL(c).length!==1)return null;let w=await d.snapshots(h,g),A=Dc(c,w);if(A)Wj(c),e.debug(`[iOS] Merged ${A.attached} DOM elements from ${A.webViews} web view(s) (${A.deduplicated} XCTest duplicates removed)`);else if(w.length>0)e.debug(`[iOS] ${w.length} registered web view(s) not merged: no snapshot, or no one-to-one WKWebView match`);return A}var Bf="com.apple.springboard";class yn{deps;constructor(c){this.deps=c}async collect({result:c,queryOptions:d,perf:h,skipWaitForFresh:g,minTimestamp:w,signal:A,readOnly:C,capturedHierarchy:T,readOptions:k}){h.serial("ios_collect"),await this.deps.hierarchyCollector().collect(c,{queryOptions:d,perf:h,skipWaitForFresh:g,minTimestamp:w,signal:A,readOnly:C,capturedHierarchy:T,readOptions:k});let D=await this.readLiveIosPanel(A);Cie(c,D),this.dropHomeScreenOfOtherPanel(c,D),this.applyIosScreenMetadata(c),this.applyLiveIosPanelSize(c),this.applyIosInsetsAndRotation(c),this.projectIosObservationHierarchy(c),await this.mergeSdkBridgeObservation(c,A),await this.mergeSdkWebSnapshots(c,A);let M;try{M=await this.deps.viewHierarchy().getScreenIdentity?.(c.viewHierarchy?.packageName,c.viewHierarchy?.updatedAt)}catch(_){e.debug(`[iOS] SDK screen identity refresh failed; using hierarchy identity: ${_}`)}let F=AR(c.viewHierarchy,c.screenSize);c.screenIdentity=F?.components.modalClass?F:M??F,h.end()}async mergeSdkBridgeObservation(c,d){if(!c.viewHierarchy)return;let h=this.deps.sdkBridge?.()??MW(this.deps.device()),g=await NW(c.viewHierarchy,h,d);if(g.backend)c.backend=g.backend;if(g.fallbackReason)c.fallbackReason=g.fallbackReason}async mergeSdkWebSnapshots(c,d){if(!c.viewHierarchy)return;let h=this.deps.sdkWeb?.()??OT(this.deps.device());if(await LW(c.viewHierarchy,h,d)&&!c.backend)c.backend="sdk"}dropHomeScreenOfOtherPanel(c,d){let h=c.viewHierarchy;if(!d||h?.packageName!==Bf)return;let g=xie(this.deps.device().displays?.panels??[],h);if(g&&g.key!==d.key)c.viewHierarchy=void 0,ne(c,{phase:"viewHierarchy",message:`The home screen is not observable on the ${d.role} panel: the runner only sees the ${g.role} panel's SpringBoard. Launch an app, or setPosture closed to return to the ${g.role} panel.`})}async readLiveIosPanel(c){let d=this.deps.device(),h=d.displays?.panels??[];if(h.length<2)return;if(!this.deps.iosDisplayInfoSource){e.debug("[iOS] Live panel source unavailable; using runner size");return}try{let g=await this.deps.iosDisplayInfoSource.readDisplays({deviceId:d.deviceId,signal:c});c?.throwIfAborted();let w=C$(g,h);if(!w)e.debug("[iOS] No unique active CoreDevice panel; using runner size");return w}catch(g){if(c?.aborted)throw g;e.warn(`[iOS] Live panel read failed; using runner size: ${r(g)}`,g);return}}applyLiveIosPanelSize(c){let d=Fj(c);if(!d?.scale||d.scale<=0)return;let h=d.sizePx.width/d.scale,g=d.sizePx.height/d.scale,w=c.screenSize;if(w.width===h&&w.height===g||w.width===g&&w.height===h)return;let A=c.viewHierarchy?.rotation===1||c.viewHierarchy?.rotation===3;c.screenSize=A?{width:g,height:h}:{width:h,height:g}}applyIosScreenMetadata(c){let d=this.deps.hierarchyCollector().extractScreenSize(c.viewHierarchy,(this.deps.device().displays?.panels.length??0)>1);if(d)c.screenSize=d,e.debug(`[iOS] Extracted screen size from hierarchy: ${d.width}x${d.height}`);else if(c.viewHierarchy?.screenWidth&&c.viewHierarchy?.screenHeight)c.screenSize={width:c.viewHierarchy.screenWidth,height:c.viewHierarchy.screenHeight},e.debug(`[iOS] Using screen size from CtrlProxy iOS: ${c.screenSize.width}x${c.screenSize.height}`);else e.warn("[iOS] Failed to extract screen size from hierarchy")}applyIosInsetsAndRotation(c){if(c.viewHierarchy?.insets)c.insets=c.viewHierarchy.insets;if(c.viewHierarchy?.systemInsets)c.systemInsets=c.viewHierarchy.systemInsets;c.rotation=bc(c.viewHierarchy?.rotation,c.screenSize)}projectIosObservationHierarchy(c){if(c.viewHierarchy&&c.screenSize?.width>0&&c.screenSize?.height>0){this.deps.hierarchyCollector().reconcileScreenDimensions(c.viewHierarchy,c.screenSize);let d=c.viewHierarchy,h=(this.deps.device().displays?.panels.length??0)>1;c.viewHierarchy=Vg("ios",d,h),qie(d,c.viewHierarchy,h)}if(c.viewHierarchy?.packageName&&!c.activeWindow)c.activeWindow={appId:c.viewHierarchy.packageName,activityName:"",layoutSeqSum:0}}}var Hf=/\bFLAG_ROUND\b/,Lf=/DisplayInfo\{[^\n]*\bdisplayId 0\b/,Vf=/DisplayDeviceInfo\{[^\n]*\btype INTERNAL\b/;function Uf(c){let d=c.split(/\r?\n/),h=d.find((g)=>Lf.test(g))??d.find((g)=>Vf.test(g));return h===void 0?void 0:Hf.test(h)}class HL{adb;cached;constructor(c){this.adb=c}async isScreenRound(c){if(this.cached)return this.cached.value;try{let d=await this.adb.executeCommand("shell dumpsys display",{timeoutMs:2000,maxBuffer:ie,noRetry:!0,signal:c});return this.cached={value:Uf(d.stdout)},this.cached.value}catch(d){c?.throwIfAborted(),e.debug(`isScreenRound unavailable: ${r(d)}`);return}}}import*as Wf from"fs/promises";async function Oc(c,d,{files:h=Wf,store:g=Jr()}={}){let w=c.observationId?g.getPathForObservation(d,c.observationId):void 0;if(!w)return;try{let{mtimeMs:A}=await h.stat(w);if(Number.isFinite(A))c.screenshotCapturedAt=new Date(A).toISOString()}catch(A){e.debug(`[OBSERVE] screenshot capture time unavailable: ${r(A)}`)}}function Ec(c){if(!c?.layoutWarnings)return c;let d=Ib(c.layoutWarnings);return d===c.layoutWarnings?c:{...c,layoutWarnings:d}}class xe{device;adb;adbFactory;timer;observedAndroidDisplayCache;requestedDisplay;deferredBackStackDisplays=new WeakMap;idGenerator;viewHierarchy;hierarchyCapture;selectedDisplayRead;predictiveUIState;screenshotRecorder;screenshotService;screenshotEvidenceFiles;pathProtection;hierarchyCollector;deviceStateCollector;iosLockStateProbe;performanceAuditor;accessibilityAuditor;accessibilityStateDetector;elementsBuilder;reconciler;staleRecovery;settledScreenshots;deviceReadScreenshot;androidCollector;displayBinding;platformTraits;iosCollector;windowIdentity;platformValidator;safeAreaAuditor;allDisplays;captureStage;reconcileStage;enrichStage;screenRound;settleStage;xrDisplaySize;static getRecentCachedObservation(){let c=uo().getRecentInMemoryEntry();if(!c)return;let d=Ec(c.result);return d?{deviceId:c.deviceId,result:d}:void 0}static getRecentCachedResult(){return xe.getRecentCachedObservation()?.result}static getRecentCachedResultForDevice(c){return Ec(uo().getRecentInMemoryForDevice(c))}static getRecentCachedScreenshotPathForDevice(c){return Jr().getPath(c)}static getRecentCachedScreenshotErrorForDevice(c){return Jr().getError(c)}static getRecentCachedScreenshotPathForObservation(c,d){return Jr().getPathForObservation(c,d)}static getRecentCachedScreenshotErrorForObservation(c,d){return Jr().getErrorForObservation(c,d)}static clearCache(c){if(uo().clear(c),Jr().clear(c),c)Pe.cancelJob(c);else Pe.clear()}static defaultObserveScreenCache={clearForDevice(c){xe.clearCache(c)}};constructor(c,d=v,h,{timer:g=i,idGenerator:w=B}={}){this.device=c,this.adbFactory=d,this.adb=d.create(c),this.timer=g,this.observedAndroidDisplayCache=new hr(g),this.requestedDisplay=h?.display,this.selectedDisplayRead=h?.selectedDisplayRead??{},this.idGenerator=w,this.screenRound=new HL(this.adb);let A=this.xrDisplaySize=new Ke({device:()=>this.device,adb:()=>this.adb,xrDetector:Sw,readDisplaySize:()=>MC(this.adb,{timeoutMs:1000}),hierarchyCollector:()=>this.hierarchyCollector}),C=ja({xrDisplaySize:A,device:c,adb:()=>this.adb,adbFactory:()=>this.adbFactory,observeScreenProvider:()=>this,identity:{device:()=>this.device,viewHierarchy:()=>this.viewHierarchy,deviceStateCollector:()=>this.deviceStateCollector,timer:()=>this.timer,platformValidator:()=>this.platformValidator,resolveObservationTimestampMs:(F)=>this.resolveObservationTimestampMs(F),extractScreenSizeFromHierarchy:(F)=>this.extractScreenSizeFromHierarchy(F)}}),T={device:c,adbFactory:this.adbFactory,timer:g,idGenerator:w,wiring:C,dependencies:h};this.viewHierarchy=sc(T);let{sources:k,services:D}=ac(T);this.hierarchyCapture=k.hierarchyCapture,this.screenshotService=k.screenshotService,this.predictiveUIState=k.predictiveUIState,this.pathProtection=D.pathProtection,this.screenshotRecorder=D.screenshotRecorder,this.screenshotEvidenceFiles=D.screenshotEvidenceFiles,this.hierarchyCollector=D.hierarchyCollector,this.deviceStateCollector=D.deviceStateCollector,this.iosLockStateProbe=D.iosLockStateProbe,this.performanceAuditor=D.performanceAuditor,this.accessibilityAuditor=D.accessibilityAuditor,this.accessibilityStateDetector=D.accessibilityStateDetector,this.elementsBuilder=new Dg,this.platformValidator=D.platformValidator,this.safeAreaAuditor=new h9,this.windowIdentity=D.windowIdentity,this.reconciler=D.reconciler,this.settledScreenshots=new Oi({device:()=>this.device,timer:()=>this.timer,screenshotRecorder:()=>this.screenshotRecorder,screenshotEvidenceFiles:()=>this.screenshotEvidenceFiles,pathProtection:()=>this.pathProtection}),this.deviceReadScreenshot=new Ei({device:()=>this.device,adb:()=>this.adb,timer:()=>this.timer,requestedDisplay:()=>this.requestedDisplay,observedAndroidDisplayCache:()=>this.observedAndroidDisplayCache,screenshotService:()=>this.screenshotService,screenshotEvidenceFiles:()=>this.screenshotEvidenceFiles,pathProtection:()=>this.pathProtection,settledScreenshots:()=>this.settledScreenshots}),this.staleRecovery=new Mi({timer:()=>this.timer,device:()=>this.device,viewHierarchy:()=>this.viewHierarchy,deviceStateCollector:()=>this.deviceStateCollector,platformValidator:()=>this.platformValidator,reconciler:()=>this.reconciler}),this.androidCollector=new mn({xrDisplaySize:A,hierarchyCollector:()=>this.hierarchyCollector,deviceStateCollector:()=>this.deviceStateCollector,viewHierarchy:()=>this.viewHierarchy,device:()=>this.device}),this.platformTraits=dc(c.platform,()=>this.device);let M={device:()=>this.device,adb:()=>this.adb};this.displayBinding=c.platform==="ios"?new dn(M):new cn(M),this.iosCollector=new yn({iosDisplayInfoSource:h?.iosDisplayInfoSource,hierarchyCollector:()=>this.hierarchyCollector,sdkBridge:h?.sdkBridge,viewHierarchy:()=>this.viewHierarchy,device:()=>this.device}),this.createStages()}createStages(){this.allDisplays=new fr({device:()=>this.device,timer:()=>this.timer,pathProtection:()=>this.pathProtection,executeSingleDisplay:(c)=>this.executeSingleDisplay(c),captureDeviceReadScreenshot:(...c)=>this.captureDeviceReadScreenshot(...c),createCriticalFallback:(c)=>this.createCriticalFallback(c),createBaseResult:()=>this.createBaseResult()}),this.captureStage=new Yr({device:()=>this.device,timer:()=>this.timer,displayBinding:()=>this.displayBinding,hierarchyCapture:()=>this.hierarchyCapture,hierarchyCollector:()=>this.hierarchyCollector,deviceStateCollector:()=>this.deviceStateCollector,iosLockStateProbe:()=>this.iosLockStateProbe,observedAndroidDisplayCache:()=>this.observedAndroidDisplayCache,requestedDisplay:()=>this.requestedDisplay,selectedDisplayRead:()=>this.selectedDisplayRead,createBaseResult:()=>this.createBaseResult(),createCriticalFallback:(c,d)=>this.createCriticalFallback(c,d),collectAllData:(c,d)=>this.collectAllData(c,d)}),this.reconcileStage=new Zr({device:()=>this.device,timer:()=>this.timer,windowIdentity:()=>this.windowIdentity,staleRecovery:()=>this.staleRecovery,displayBinding:()=>this.displayBinding,platformValidator:()=>this.platformValidator,deviceStateCollector:()=>this.deviceStateCollector,reconcileActiveWindowAttribution:(c,d)=>this.reconcileActiveWindowAttribution(c,d),isConfirmedFrameworkErrorDialog:(c,d)=>this.isConfirmedFrameworkErrorDialog(c,d)}),this.enrichStage=new oi({device:()=>this.device,isAndroidXr:()=>this.xrDisplaySize.isXrCached(),timer:()=>this.timer,platformTraits:()=>this.platformTraits,screenshotRecorder:()=>this.screenshotRecorder,pathProtection:()=>this.pathProtection,performanceAuditor:()=>this.performanceAuditor,accessibilityAuditor:()=>this.accessibilityAuditor,accessibilityStateDetector:()=>this.accessibilityStateDetector,predictiveUIState:()=>this.predictiveUIState,safeAreaAuditor:()=>this.safeAreaAuditor,elementsBuilder:()=>this.elementsBuilder,screenRound:()=>this.screenRound,deferredBackStackDisplays:()=>this.deferredBackStackDisplays,stampScreenSizeUnits:(c)=>this.stampScreenSizeUnits(c),processRecomposition:(c,d)=>this.processRecomposition(c,d),captureSettledScreenshot:(...c)=>this.captureSettledScreenshot(...c)}),this.settleStage=new Di({device:()=>this.device,timer:()=>this.timer,windowIdentity:()=>this.windowIdentity,deviceStateCollector:()=>this.deviceStateCollector,platformTraits:()=>this.platformTraits,identifyCapture:(c,d)=>this.identifyCapture(c,d),resolveObservationTimestampMs:(c)=>this.resolveObservationTimestampMs(c)})}async executeDeviceRead(c,d="settled",h,g={}){let{requireFreshScreenshot:w=!1,timeoutMs:A}=g;if(this.requestedDisplay==="all")return this.allDisplays.execute({observerMode:!0,skipCache:!0,skipRecompositionTracking:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,screenshot:"none",signal:c,timeoutMs:A,deviceReadScreenshot:d==="none"?void 0:h??{}});let C=await this.execute({observerMode:!0,skipCache:!0,skipRecompositionTracking:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,screenshot:"none",signal:c});if(C.viewHierarchy?.hierarchyServiceStarted)C.hierarchyServiceStarted=!0,delete C.viewHierarchy.hierarchyServiceStarted;if(d==="none")return C.screenshotCaptureAttempted=!1,C;if(await this.captureDeviceReadScreenshot(C,c,h,{requireFreshScreenshot:w}),C.screenshotPath)C.screenshotExpiresAt=await this.pathProtection.protect(C.screenshotPath);return C}captureDeviceReadScreenshot(...c){return this.deviceReadScreenshot.captureDeviceReadScreenshot(...c)}async appendRawViewHierarchy(c,d){if(!c.viewHierarchy)return;let h=await this.deviceReadScreenshot.resolveReadDisplayId(c,{signal:d});await this.hierarchyCollector.collectRaw(c,d,h)}async readCachedObservationForTarget(){let c=await uo().getMostRecent(this.device.deviceId);if(!c||(this.device.displays?.panels.length??0)<=1)return c;let d=Ce.currentObservedPanel(this.device.deviceId),h=![void 0,"active"].includes(this.requestedDisplay),g=d||h?void 0:this.device.platform==="android"?(await this.observedAndroidDisplayCache.resolve(this.device,this.adb)).display:rO(this.device,c.viewHierarchy),{key:w,posture:A}=g??{},C=Ai(this.device,this.requestedDisplay,{focusedPanelKey:d?.key,activePanelKey:w,posture:A,displayPin:xu()});return c.display?.key===C.key?c:void 0}async getMostRecentCachedObserveResult(){LR(this.device,this.requestedDisplay);let c=this.timer.now();try{e.debug("[OBSERVE_CACHE] Getting most recent cached observe result");let d=await this.readCachedObservationForTarget(),h=d&&this.device.platform==="ios"?{...d,rotation:bc(d.viewHierarchy?.rotation,d.screenSize)}:d,g=this.timer.now()-c;if(h){await _b(h,this.pathProtection),e.debug(`[OBSERVE_CACHE] Found recent result in cache (${g}ms)`),this.identifyCapture(h,"cached-ok");let w=vR({actualTimestamp:this.resolveObservationTimestampMs(h),hostAgeBasisMs:this.windowIdentity.resolveHostReceivedAtMs(h),now:this.timer.now()});w.requestedAfter=h.freshness?.requestedAfter;let A=h.displayRevision!==void 0&&h.displayRevision!==Ce.revision(this.device.deviceId)||Ce.geometryChanged(this.device.deviceId,h.screenSize);if(h.freshness?.isFresh===!1)return Zz(h,{...h,freshness:{...h.freshness,ageMs:w.ageMs}});return{...h,freshness:A?{...w,isFresh:!1,category:"cache_age",warning:"Display changed since this observation was captured; observe again."}:w}}return e.debug(`[OBSERVE_CACHE] No cached observe result available (${g}ms)`),{...this.createBaseResult(),error:"No cached observe result available"}}catch(d){let h=this.timer.now()-c;return e.warn(`[OBSERVE_CACHE] Error getting cached observe result after ${h}ms: ${d}`),{...this.createBaseResult(),error:"Failed to retrieve cached observe result"}}}async execute(c){if((c?.display??this.requestedDisplay)==="all")return this.allDisplays.execute(c);return this.executeSingleDisplay(c)}async executeSingleDisplay(c){let d=this.captureStage.resolveSingleDisplayIntent(c);try{let h=await this.captureStage.beginSingleDisplay(d),g=await this.captureStage.captureSingleDisplay(h);if(g.earlyResult)return g.earlyResult;let w=await this.reconcileStage.reconcileSingleDisplay(h,g);return await this.enrichStage.enrichSingleDisplay(h),await this.settleStage.settleSingleDisplay(h,g,w),await this.enrichStage.publishSingleDisplay(h)}catch(h){if(h instanceof mj)throw h;return await this.captureStage.failSingleDisplay(h,d)}}createCriticalFallback(c,d={}){let{fallback:h=this.createBaseResult()}=d,g=c instanceof Error?c.stack||c.message:String(c);return this.stampScreenSizeUnits(h),ne(h,{phase:"critical",message:"Observation failed due to device access error",cause:g}),h.freshness=vR({now:this.timer.now(),unavailable:!0,unavailableReason:"unknown",unavailableDetail:g}),h}identifyCapture(c,d){if(c.viewHierarchy&&typeof c.viewHierarchy==="object"&&!c.viewHierarchy.hierarchy?.error)vd(te(this.device.platform,"Observing the view hierarchy"),c.viewHierarchy,d,{timer:this.timer,ids:this.idGenerator,captureId:c.observationId,iosMultiPanel:this.platformTraits.isIosMultiPanel()})}async processRecomposition(c,d){await Bn.getInstance().processObservation(c,this.device)}async screenshotDisplayId(c,d){if(this.device.platform!=="android"||this.requestedDisplay==="active")return;let h=this.requestedDisplay||d?.display?.key;if(!h)return;try{let g=Ai(this.device,h,{}),w=await this.observedAndroidDisplayCache.logicalIdForPanel(this.device,this.adb,g.key,c);return!this.requestedDisplay&&w===0?void 0:w}catch(g){if(this.requestedDisplay)throw g;e.debug(`Screenshot panel "${h}" could not be mapped; using default display: ${r(g).replace(/\s+/g," ")}`);return}}async captureScreenshot(c=new U,{signal:d,observation:h,screenshot:g,screenshotOptions:w}={}){let A=h??this.createBaseResult(),C=await this.screenshotDisplayId(d,h),T=Im(g),k=si(w);if(h){if(h.screenshotCaptureAttempted=!0,ai(h,k),T==="settled")h.screenshotOrientation=this.platformTraits.settledScreenshotOrientation()}if(T==="settled")await this.captureSettledScreenshot(A,c,d,{strict:g==="settled",displayId:C,screenshotOptions:w});else if(await this.screenshotRecorder.captureFresh(A.observationId,{perf:c,signal:d,displayId:C,capture:k}),h)await Oc(h,this.device.deviceId,{files:this.screenshotEvidenceFiles});if(h)await this.runAccessibilityAudit(h,c)}captureSettledScreenshot(...c){return this.settledScreenshots.captureSettledScreenshot(...c)}async runAccessibilityAudit(c,d=new U){await this.accessibilityAuditor.run(c,d)}appendError(c,d){ne(c,{phase:"critical",message:d})}extractScreenSizeFromHierarchy(c){return this.hierarchyCollector.extractScreenSize(c,this.platformTraits.isIosMultiPanel())}createBaseResult(){return{observationId:this.idGenerator.next(),deviceId:this.device.deviceId,display:{key:"0",role:"unknown",posture:"unknown",generation:0},updatedAt:new Date(this.timer.now()).toISOString(),screenSize:{width:0,height:0},systemInsets:{top:0,right:0,bottom:0,left:0},insets:{available:!1,source:"unavailable",units:"unknown"}}}stampScreenSizeUnits(c){c.screenSize={...c.screenSize,units:this.platformTraits.screenSizeUnits()}}captureCacheGeneration(){return uo().currentGeneration(this.device.deviceId)}async cacheObserveResult(c,d,h){if(c.displayRevision!==void 0&&c.displayRevision!==Ce.revision(this.device.deviceId))return;let g=uo(),w=h??this.timer.now(),A=g.getRecentInMemoryForDevice(this.device.deviceId),C=g.getRecentCachedAtForDevice(this.device.deviceId);if(A!==void 0&&A.observationId!==c.observationId&&C!==void 0&&C>w){e.debug(`[OBSERVE_CACHE] Skipping deferred observe result for device ${this.device.deviceId}: a more recently cached observation already exists`);return}await g.put(this.device.deviceId,c,d,w)}async collectDeferredBackStack(c,d={}){let h=this.deferredBackStackDisplays.get(c);if(h===void 0||this.device.platform!=="android"||c.backStack)return!1;await this.deviceStateCollector.collectBackStack(c,new U,d.signal,h);let g=$e(c),w=c.activeWindow,A=Boolean(g&&w&&!ue.has(c.viewHierarchy?.packageName??"")&&!ue.has(w.appId)&&ui(c,w,g));return pn(c),await this.deviceStateCollector.refreshAutomotiveForegroundActivity(c,d.signal),A}collectAllData(c,d={}){let h={result:c,queryOptions:d.queryOptions,perf:d.perf??new U,skipWaitForFresh:d.skipWaitForFresh??!1,minTimestamp:d.minTimestamp??0,signal:d.signal,readOnly:d.readOnly??!1,capturedHierarchy:d.capturedHierarchy,readOptions:d.readOptions};switch(this.device.platform){case"android":return this.androidCollector.collect({...h,skipBackStack:d.skipBackStack??!1,displayId:d.displayId??0});case"ios":return this.iosCollector.collect(h);default:return Promise.resolve()}}reconcileActiveWindowAttribution(c,d={}){return this.reconciler.reconcileActiveWindowAttribution(c,d)}applyRecapturedHierarchy(c,d){return this.reconciler.applyRecapturedHierarchy(c,d)}recorrelateActiveWindowToRecapture(c,d){return this.reconciler.recorrelateActiveWindowToRecapture(c,d)}recaptureHierarchyForSystemUiOverlay(c,d){return this.reconciler.recaptureHierarchyForSystemUiOverlay(c,d)}recaptureHierarchyForBackStackAttribution(c,d,h){return this.reconciler.recaptureHierarchyForBackStackAttribution(c,d,h)}isConfirmedFrameworkErrorDialog(c,d){return ma(this.adb,c,d)}resolveObservationTimestampMs(c){return c.viewHierarchy?.updatedAt}}function qL(c,d){return new xe(c,d,c.platform==="ios"?{iosDisplayInfoSource:Cu()}:void 0)}class ei{invalidate(c,d){if(c.platform==="android")E.getExistingInstance(c.deviceId)?.invalidateCache();else{let h=x.getExistingInstance(c.deviceId);if(d)h?.invalidateCache();else h?.clearCache()}if(xe.clearCache(c.deviceId),c.platform==="android")Kie(c.deviceId)}retireAppProcess(c,d){if(c.platform==="android")E.getExistingInstance(c.deviceId)?.clearSdkScreenIdentity(d)}}async function Wr(c,d,h={}){await R.devicePoolWrites()?.reconcileDiscoveryObservation(c,d,h)}class Oa extends t{errorCode;constructor(c,d){super(c);this.errorCode=d}}function td(c,d,h={}){let g=h.clock??i,w=h.log??e,A,C,T=async()=>{let k=g.now();try{let D=await d();return A=D,w.info(`[lazy-feature] ${c} module loaded in ${g.now()-k} ms`),D}catch(D){throw C=void 0,w.warn(`[lazy-feature] ${c} module failed to load`,D),u(D,`Failed to load the ${c} module`)}};return{load:()=>{if(A!==void 0)return Promise.resolve(A);return C??=T(),C},loaded:()=>A}}function gu(c){return x.getInstance(c)}class Mc{restored=new Set;removed=new Set;identityChanged=new Set;onDeviceRestored(c){return this.restored.add(c),()=>{this.restored.delete(c)}}onDeviceRemoved(c){return this.removed.add(c),()=>{this.removed.delete(c)}}onDeviceIdentityChanged(c){return this.identityChanged.add(c),()=>{this.identityChanged.delete(c)}}removedListenersForTesting(){return[...this.removed]}clearRemovedListenersForTesting(){this.removed.clear()}deviceRestored(c){this.emit(this.restored,c)}deviceRemoved(c){this.emit(this.removed,c)}deviceIdentityChanged(c){this.emit(this.identityChanged,c)}emit(c,d){for(let h of[...c])try{h(d)}catch(g){e.warn(`[StreamDeviceLifecycle] listener failed for ${d}: ${r(g)}`,g)}}}var gn=null;function aa(){if(!gn){let c=new Mc;gn=c,nr({name:"stream-device-lifecycle",prepareForIncarnationChange:(d)=>c.deviceRestored(d),onDeviceIncarnationChanged:(d)=>c.deviceRestored(d)})}return gn}import*as he from"fs";import*as Ve from"path";class jC{filePath;constructor(c=$f()){this.filePath=c}read(){try{return he.existsSync(this.filePath)?he.readFileSync(this.filePath,"utf8"):null}catch(c){return e.debug(`Failed to read startup failure tracker file: ${c}`),null}}write(c){let d=Ve.dirname(this.filePath);he.mkdirSync(d,{recursive:!0});let h=Ve.join(d,`.${Ve.basename(this.filePath)}.${process.pid}.tmp`);he.writeFileSync(h,c,{mode:384}),he.renameSync(h,this.filePath)}clear(){try{if(he.existsSync(this.filePath))he.rmSync(this.filePath,{force:!0})}catch(c){e.debug(`Failed to clear startup failure tracker file: ${c}`)}}}function $f(){return Ve.join(Qe(fn.STATE),"daemon-startup-failures.json")}
|
|
55
|
-
export{Ro,PT,wL,Ste,Sw,ra,wte,MC,Rte,uW,AT,ww,fu,NC,Rw,p3,Pte,Er,sr,RL,Ate,Im,TT,ol,Ue,dr,na,Tte,zh,jh,Ms,pW,Kh,Gh,PL,FC,kte,Ete,Rv,kT,Ite,ET,AL,_m,ia,TL,m3,mW,LC,_te,sl,BC,fW,xm,xte,hW,gW,Pw,$C,Cte,sp,Dte,oa,f3,Pv,Po,UC,yW,vW,zi,vn,kL,EL,Cm,Dm,h3,bW,Ote,g3,Mte,y3,v3,bc,Sc,al,HC,qC,bn,IL,IT,b3,Nte,Av,_L,Fte,_T,VC,SW,WC,Lte,Om,wW,S3,w3,RW,R3,P3,xL,Aw,Yh,A3,et,Mm,qn,ed,T3,Bte,PW,AW,$te,k3,Ute,Hte,TW,CL,Jh,DL,xT,kW,EW,OL,E3,ML,IW,sa,Nm,It,oe,Ge,er,Da,Qn,Xh,_W,NL,Zh,Fm,FL,xW,Ao,CT,LL,Lm,BL,CW,DT,ro,$L,hu,I3,DW,qte,Vte,OW,Tv,zC,MW,NW,Wte,FW,zte,UL,OT,LW,HL,xe,qL,ei,Wr,Oa,td,gu,aa,jC};
|
|
56
|
-
|
|
57
|
-
//# debugId=0AD75E171B5C599064756E2164756E21
|