@kaeawc/auto-mobile 0.0.92 → 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/schemas/test-plan.schema.json +370 -52
- package/dist/src/ble-peripheral.py +153 -0
- package/dist/src/{chunk-r14wwk37.js → chunk-026y62r9.js} +12 -12
- package/dist/src/chunk-0jyfg947.js +4 -0
- package/dist/src/{chunk-950qcq1e.js → chunk-0zfpp1wh.js} +4 -4
- package/dist/src/chunk-13qxf7ym.js +7 -0
- package/dist/src/chunk-1scenrk7.js +4 -0
- package/dist/src/chunk-1vb5ph1k.js +4 -0
- package/dist/src/chunk-20g565q7.js +5 -0
- package/dist/src/chunk-21h6dhdm.js +5 -0
- package/dist/src/{chunk-2e6s75qv.js → chunk-25mfpthk.js} +8 -8
- package/dist/src/{chunk-9rkfyt6q.js → chunk-2b39zyxc.js} +3 -3
- package/dist/src/chunk-2gzd6wbd.js +4 -0
- package/dist/src/{chunk-eka89q3k.js → chunk-3dntffy9.js} +1 -1
- package/dist/src/chunk-3gfczcsn.js +4 -0
- package/dist/src/chunk-3h5jz1vb.js +9 -0
- package/dist/src/chunk-41zcy6b3.js +5 -0
- 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-5wk1t46v.js +5 -0
- package/dist/src/chunk-661c50hh.js +17 -0
- package/dist/src/chunk-68n6bjjd.js +21 -0
- package/dist/src/{chunk-zg67wjkh.js → chunk-69pmjdf2.js} +3 -3
- package/dist/src/chunk-6hrj3jt6.js +145 -0
- package/dist/src/{chunk-b4cxdzwy.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-7k7gjg2t.js +7 -0
- 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-r20pe1nv.js → chunk-96r3bpg7.js} +3 -3
- package/dist/src/chunk-97x887te.js +4 -0
- package/dist/src/{chunk-sz1a7p43.js → chunk-99a6tbvd.js} +1 -1
- package/dist/src/chunk-9p5d2994.js +5 -0
- package/dist/src/{chunk-w7zsh13a.js → chunk-9q265er0.js} +4 -4
- package/dist/src/chunk-9xgnrv5w.js +5 -0
- package/dist/src/chunk-9xgsmshb.js +5 -0
- package/dist/src/chunk-a02d1wgv.js +4 -0
- package/dist/src/{chunk-km0dy5vc.js → chunk-a9ps00a1.js} +10 -10
- package/dist/src/chunk-aewdveet.js +5 -0
- package/dist/src/chunk-b3tdtq7r.js +9 -0
- package/dist/src/chunk-bn7jx7a2.js +4 -0
- package/dist/src/chunk-bnyw27ja.js +4 -0
- package/dist/src/{chunk-s1zq65ny.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-cb1ga9rd.js +7 -0
- package/dist/src/chunk-cn7fwy7k.js +4 -0
- package/dist/src/chunk-cnvy4a64.js +4 -0
- package/dist/src/chunk-cqhw4yr6.js +5 -0
- package/dist/src/{chunk-v90es00d.js → chunk-ctmfshjc.js} +2 -2
- package/dist/src/chunk-ctwmhz13.js +4 -0
- package/dist/src/{chunk-qv2918jt.js → chunk-d3jx9bz5.js} +2 -2
- package/dist/src/{chunk-wry6skrm.js → chunk-d6rb08ga.js} +1 -1
- package/dist/src/chunk-ddqhj4eg.js +5 -0
- package/dist/src/{chunk-d57432wq.js → chunk-ddrhs1c3.js} +2 -2
- package/dist/src/chunk-dnjnh9p6.js +4 -0
- package/dist/src/{chunk-ajsrz473.js → chunk-dw5rwgya.js} +3 -3
- package/dist/src/chunk-e0870khr.js +5 -0
- 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-g2js4c2v.js +971 -0
- package/dist/src/chunk-g3af2qbk.js +5 -0
- package/dist/src/chunk-gadtna7s.js +11 -0
- package/dist/src/{chunk-c9nk1r78.js → chunk-gcyx407v.js} +3 -3
- package/dist/src/{chunk-jdqvcq0a.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-2v7tw1nj.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-kd9vfaxh.js +5 -0
- package/dist/src/{chunk-34zxqcmq.js → chunk-kdczmgwk.js} +3 -3
- package/dist/src/chunk-ke3wn14v.js +4 -0
- package/dist/src/chunk-kh5n7m6w.js +4 -0
- package/dist/src/{chunk-0dfnyfkh.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-stfzjr9y.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-9y5bcy28.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-qj1tbnv2.js +8 -0
- package/dist/src/chunk-qnh9egwr.js +4 -0
- package/dist/src/chunk-qy3khhf8.js +8 -0
- package/dist/src/chunk-r0vp315h.js +11 -0
- package/dist/src/chunk-r4j43b9s.js +237 -0
- package/dist/src/{chunk-4pfftt07.js → chunk-r54cxxze.js} +3 -3
- package/dist/src/chunk-r6pvhj33.js +325 -0
- 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-s3y3zfcx.js +14 -0
- package/dist/src/chunk-s4g43k75.js +5 -0
- package/dist/src/chunk-sfqe223f.js +311 -0
- package/dist/src/chunk-sqdrxjw5.js +7 -0
- package/dist/src/{chunk-0w1spptt.js → chunk-t54k47em.js} +4 -4
- package/dist/src/chunk-tek4pnvv.js +26 -0
- package/dist/src/chunk-tn74y7af.js +4 -0
- package/dist/src/chunk-tvq0nzam.js +5 -0
- package/dist/src/chunk-tx4f0h9c.js +6 -0
- 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-w5yypt53.js +42 -0
- package/dist/src/{chunk-r0f1q783.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-8en08r7q.js → chunk-wpe46vsa.js} +3 -3
- package/dist/src/chunk-wxdjeb4k.js +27 -0
- 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-jhnbfj19.js → chunk-xn9m3xc2.js} +5 -5
- package/dist/src/{chunk-a4k9rt7z.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/ios/CameraPosterInjection/Injection/CameraPosterInjection.m +466 -0
- package/package.json +4 -3
- package/schemas/test-plan.schema.json +370 -52
- package/dist/src/chunk-09442h7v.js +0 -4
- package/dist/src/chunk-0e4gm1kj.js +0 -5
- package/dist/src/chunk-0eb8576f.js +0 -4
- package/dist/src/chunk-0rjm4nx7.js +0 -5
- package/dist/src/chunk-1zmh2eak.js +0 -4
- package/dist/src/chunk-28k63ha3.js +0 -5
- package/dist/src/chunk-2d4wmp8b.js +0 -4
- package/dist/src/chunk-32jpxz2y.js +0 -323
- package/dist/src/chunk-3jmvqygr.js +0 -238
- package/dist/src/chunk-3swvfhqt.js +0 -5
- package/dist/src/chunk-44bt78m9.js +0 -5
- package/dist/src/chunk-488vt2bp.js +0 -4
- package/dist/src/chunk-4fgdhcwx.js +0 -5
- package/dist/src/chunk-4jp2se4w.js +0 -4
- package/dist/src/chunk-4vhr9e4t.js +0 -4
- package/dist/src/chunk-4xd6zs3y.js +0 -15
- package/dist/src/chunk-51567pg8.js +0 -4
- package/dist/src/chunk-5agqsfev.js +0 -4
- package/dist/src/chunk-5d706gmr.js +0 -4
- package/dist/src/chunk-5kd4rqk7.js +0 -5
- package/dist/src/chunk-61t538bm.js +0 -4
- package/dist/src/chunk-6d3mmqxt.js +0 -54
- package/dist/src/chunk-6hyt398x.js +0 -5
- package/dist/src/chunk-6mnr8kpm.js +0 -4
- package/dist/src/chunk-79q5xsdc.js +0 -42
- package/dist/src/chunk-7bdgand3.js +0 -4
- package/dist/src/chunk-84cp9dw5.js +0 -4
- package/dist/src/chunk-86f2h5ww.js +0 -5
- package/dist/src/chunk-8cghfzb2.js +0 -19
- package/dist/src/chunk-9tf2p9y9.js +0 -5
- package/dist/src/chunk-a2sc4jm0.js +0 -5
- package/dist/src/chunk-aa5ng3d1.js +0 -4
- package/dist/src/chunk-b3h0a6ca.js +0 -4
- package/dist/src/chunk-b6a737qt.js +0 -4
- package/dist/src/chunk-bn64x5z5.js +0 -5
- package/dist/src/chunk-bvh649za.js +0 -12
- package/dist/src/chunk-c9tyfg4j.js +0 -26
- package/dist/src/chunk-cfsdfqnm.js +0 -4
- package/dist/src/chunk-cxyf04jc.js +0 -7
- package/dist/src/chunk-da08tx5v.js +0 -4
- package/dist/src/chunk-f2tc08m2.js +0 -4
- package/dist/src/chunk-f8tnk179.js +0 -5
- package/dist/src/chunk-f9s1kkhx.js +0 -5
- package/dist/src/chunk-fbp8a4rx.js +0 -4
- package/dist/src/chunk-fd2z0sze.js +0 -4
- package/dist/src/chunk-fk927f4q.js +0 -54
- package/dist/src/chunk-fxmr3a0f.js +0 -4
- package/dist/src/chunk-gaqwhd44.js +0 -4
- package/dist/src/chunk-ggtd5x5a.js +0 -5
- package/dist/src/chunk-gndcfrm7.js +0 -4
- package/dist/src/chunk-h3n4adc6.js +0 -310
- package/dist/src/chunk-h5pjbb83.js +0 -4
- package/dist/src/chunk-hgnnh302.js +0 -4
- package/dist/src/chunk-hmke8nhx.js +0 -5
- package/dist/src/chunk-j2bx12hn.js +0 -4
- package/dist/src/chunk-j70y1a2g.js +0 -4
- package/dist/src/chunk-js1jpyxp.js +0 -6
- package/dist/src/chunk-kbjq0qvb.js +0 -4
- package/dist/src/chunk-kfwx57xd.js +0 -4
- package/dist/src/chunk-kzwctna2.js +0 -4
- package/dist/src/chunk-m9ehyehy.js +0 -4
- package/dist/src/chunk-mct91p1f.js +0 -4
- package/dist/src/chunk-mf9spd4g.js +0 -5
- package/dist/src/chunk-mgrcansb.js +0 -4
- package/dist/src/chunk-mqc1d0eb.js +0 -6
- package/dist/src/chunk-n1zmpk0z.js +0 -4
- package/dist/src/chunk-ncyjf63g.js +0 -4
- package/dist/src/chunk-nr64d21q.js +0 -973
- package/dist/src/chunk-nwm2pq5v.js +0 -168
- package/dist/src/chunk-pm06b05d.js +0 -9
- package/dist/src/chunk-q50s00ry.js +0 -4
- package/dist/src/chunk-qwye1958.js +0 -14
- package/dist/src/chunk-r8z9pfve.js +0 -5
- package/dist/src/chunk-rdpgkjf6.js +0 -4
- package/dist/src/chunk-rkr0dks9.js +0 -5
- package/dist/src/chunk-rn84t3sf.js +0 -11
- package/dist/src/chunk-s123kn7n.js +0 -4
- package/dist/src/chunk-s73qn3fx.js +0 -4
- package/dist/src/chunk-sjn0nj4p.js +0 -5
- package/dist/src/chunk-sns0c35v.js +0 -7
- package/dist/src/chunk-t4dr5c8v.js +0 -8
- package/dist/src/chunk-tc8k9c1j.js +0 -4
- package/dist/src/chunk-teznhase.js +0 -4
- package/dist/src/chunk-ty9xgmz4.js +0 -4
- package/dist/src/chunk-tyazf3sk.js +0 -145
- package/dist/src/chunk-v6npjrjm.js +0 -5
- package/dist/src/chunk-vbvtzkwz.js +0 -5
- package/dist/src/chunk-vefd8qee.js +0 -8
- package/dist/src/chunk-vs9r72ta.js +0 -17
- package/dist/src/chunk-w2mwa0jk.js +0 -4
- package/dist/src/chunk-w88k0bgr.js +0 -4
- package/dist/src/chunk-wzdt0enk.js +0 -4
- package/dist/src/chunk-xhhv854c.js +0 -4
- package/dist/src/chunk-y58270hd.js +0 -4
- package/dist/src/chunk-yk0hmbex.js +0 -4
- package/dist/src/chunk-ympy4fdz.js +0 -28
- package/dist/src/chunk-yw436axy.js +0 -4
- package/dist/src/chunk-z04jrpjy.js +0 -5
- package/dist/src/chunk-z2xznczw.js +0 -4
- package/dist/src/chunk-z4xnrgps.js +0 -4
- package/dist/src/chunk-z7csyszv.js +0 -4
- package/dist/src/chunk-z8t0v07j.js +0 -11
- package/dist/src/chunk-z916af47.js +0 -228
- package/dist/src/chunk-zcr8he8q.js +0 -5
- package/dist/src/chunk-zd9vmkzn.js +0 -9
- package/dist/src/chunk-zj939v0h.js +0 -5
- package/dist/src/chunk-zkdjwtc1.js +0 -4
- package/dist/src/chunk-zkv5kzt6.js +0 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{uB,zv,Zt,Ni,gB,w,QT,lz,cd,Lre,rY,Nr,ze,Gr,Io,Xw,nn,Gv,fz,Us,Iu,nY,wg,Ure,Fr,Hs,tb,rb,He,H,Xe,me,an,U,DB,pk,hne,_c,xc,rr,kn,Bz,$z,nt,ae,ie,Jr,lR,Ye,ob,v,ys,z,Ng,hR,Tne,Cp,ab,gR,ga,Ve,xu,Vr,ao,Jo,Do,yR,hk,vR,Yn,L,Xo,Oo,ke,bR,Xz,Al,b,vt,fd,De,AY,qne,Vne,li,Gi,Bg,co,le,Ou,Ak,Mu,he,Wg,Mo,o,P,Up,ya,Rb,xl,OR,mr,dt,Rr,HY,Sj,Pb,FR,N,lt,wt,Ut,uo,js,K,Tj,qn,XD,fe,qR,Yg,_j,ZD,t9,Pe,Jg,Die,Uk,Rs,QD,zR,ts,f$,Jn,y$,xb,ve,Mj,jk,Nj,rs,Ka,sO,Zg,Xk,Rf,Hu,aO,Qg,Pf,ey,$j,Gs,Xn,Nl,Zn,x$,rP,Ei,dO,qu,Zk,Ee,Af,Vu,po,jie,lO,N$,lP,Vj,Ef,gr,G$,loe,uoe,n2,RO,Lc,As,O,Ar,Bl,Soe,d2,IO,l2,cy,_O,N9,hn,woe,kd,Roe,u2,dy,Vb,L9,ly,h2,iU,NO,Df,jp,Eoe,mo,Ioe,wP,vE,Qr,_oe,Vn,Wb,No,x,Ce,E,UO,Loe,Qi}from"./chunk-sfqe223f.js";import{$f,i,Uf,Hf,Tr,Se,Je,hi,vn,gi,Q,zl,HK,OE,ut,$d,Ud,jl,Vf,Ui,dr,re,$8,lM,we,Ea,qt,Qu,l,st,e}from"./chunk-r0vp315h.js";import{h,Y,I,pt,W8,$e,ep}from"./chunk-5wk1t46v.js";import{B,f,kt,_e,zO,jr}from"./chunk-r6pvhj33.js";import{ho,y,yr,j,Dt,n,a,m,S,s,Fo,p,_,EP}from"./chunk-w5yypt53.js";import{bt,Vt,lD,se}from"./chunk-9xgnrv5w.js";import{r,t,u}from"./chunk-2b39zyxc.js";import{Ft}from"./chunk-j69g8b50.js";var ws="device_assigned_to_binding";class oi extends t{deviceId;code=ws;retryable=!1;platform;stableId;scopeKey;declaredBinding;constructor(c,d,g){super(`${c} refused: device '${d}' (${g.platform} ${g.stableDeviceId}) is `+(g.holder==="session_broker"?`assigned to binding ${g.bindingIndex}`:"reserved for bindings")+` (code ${ws}). It stays reserved while idle; use another device, or reset the binding's scope to release it.`);this.deviceId=d;this.name="DeviceAssignedToBindingError",this.platform=g.platform,this.stableId=g.stableDeviceId,this.scopeKey=g.scopeKey,this.declaredBinding=g.bindingIndex}toPayload(){return{code:this.code,deviceId:this.deviceId,platform:this.platform,stableId:this.stableId,scopeKey:this.scopeKey,declaredBinding:this.declaredBinding,retryable:!1}}}var Ps="capacity_exhausted";class $n extends t{code=Ps;retryable=!0;details;constructor(c,d){super(d);this.name="BootCapacityExhaustedError",this.details={...c,code:Ps,retryable:!0}}get retryAfterMs(){return this.details.retryAfterMs}get limit(){return this.details.limit}get booted(){return this.details.booted}get platform(){return this.details.platform}}var Is=["none","notch","dynamic_island","hole_punch","any"],yp=new Set(["iphone-se","iphone-se-2nd-generation","iphone-se-3rd-generation","iphone-6","iphone-6-plus","iphone-6s","iphone-6s-plus","iphone-7","iphone-7-plus","iphone-8","iphone-8-plus","ipod-touch-7th-generation"]),gp=new Set(["iphone-x","iphone-xr","iphone-xs","iphone-xs-max","iphone-11","iphone-11-pro","iphone-11-pro-max","iphone-12","iphone-12-mini","iphone-12-pro","iphone-12-pro-max","iphone-13","iphone-13-mini","iphone-13-pro","iphone-13-pro-max","iphone-14","iphone-14-plus","iphone-16e"]),bp=new Set(["iphone-14-pro","iphone-14-pro-max","iphone-15","iphone-15-plus","iphone-15-pro","iphone-15-pro-max","iphone-16","iphone-16-plus","iphone-16-pro","iphone-16-pro-max","iphone-17","iphone-17-pro","iphone-17-pro-max","iphone-air","iphone-17e"]),wp=new Set(["pixel","pixel_2","pixel_2_xl","pixel_3","pixel_3a","pixel_3a_xl","pixel_4","pixel_4_xl","pixel_c","pixel_tablet","nexus 5x","medium phone","small phone"]),Rp=new Set(["pixel_3_xl"]),Ap=new Set(["pixel_4a","pixel_4a_5g","pixel_5","pixel_5a","pixel_6","pixel_6_pro","pixel_6a","pixel_7","pixel_7_pro","pixel_7a","pixel_8","pixel_8_pro","pixel_8a","pixel_9","pixel_9_pro","pixel_9_pro_xl","pixel_9_pro_fold"]);function Pp(c){return c.startsWith("com.apple.CoreSimulator.SimDeviceType.")?c.slice(38).toLowerCase().replaceAll(/-+/g,"-").replaceAll(/(^-|-$)/g,""):""}function Ow(c,d){if(c==="ios"){let R=Pp(d);if(yp.has(R)||R.startsWith("ipad-"))return"none";if(gp.has(R))return"notch";if(bp.has(R))return"dynamic_island";return"unknown"}let g=d.toLowerCase();if(wp.has(g))return"none";if(Rp.has(g))return"notch";if(Ap.has(g))return"hole_punch";return"unknown"}var Cs=30,Qt="com.apple.CoreSimulator.",Ip="system-images;",Dp=["phone","tablet","foldable","tv","watch","automotive","xr-headset","xr-glasses"],Ds=p(Dp).optional().describe("Required device family, independent of the exact model and creation default");function Tp(c){let d=nn(c);return d?.tag==="google_apis_playstore"&&d.apiLevel>=Cs}var Ts=n().min(1).describe("Installed Android system-image package identifier"),xs=n().min(1).describe("Android avdmanager device profile identifier"),Po={ios:{platform:"ios",catalog:"automobile:devices/images/ios",example:{runtime:"com.apple.CoreSimulator.SimRuntime.iOS-26-5",deviceType:"com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro"}},watchos:{platform:"watchos",catalog:"automobile:devices/images/watchos",example:{runtime:"com.apple.CoreSimulator.SimRuntime.watchOS-11-0",deviceType:"com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-10-46mm"}},tvos:{platform:"tvos",catalog:"automobile:devices/images/tvos",example:{runtime:"com.apple.CoreSimulator.SimRuntime.tvOS-26-5",deviceType:"com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-4K"}},visionos:{platform:"visionos",catalog:"automobile:devices/images/visionos",example:{runtime:"com.apple.CoreSimulator.SimRuntime.xrOS-26-5",deviceType:"com.apple.CoreSimulator.SimDeviceType.Apple-Vision-Pro-4K"}}};function xp(c){return`pass spec { runtime, deviceType } with exact CoreSimulator identifiers, e.g. ${JSON.stringify(c.example)}; list the host's identifiers with ${c.catalog}`}function ks(c){return(d)=>d.input===void 0?c:void 0}function qe(c,d,g){return n({error:ks(`is required: a CoreSimulator ${c==="runtime"?"runtime":"device-type"} identifier such as '${d.example[c]}'; list the host's identifiers with `+d.catalog)}).min(1).describe(g)}function er(c){return{error:ks(`is required for ${c.platform}: ${xp(c)}`)}}var kp=n().min(1).describe("CoreSimulator runtime identifier"),Ep=n().min(1).describe("CoreSimulator device-type identifier"),ir=p(Is).optional().describe("Required display cutout class for the exact device type; 'any' accepts every class");function ni(c,d){if(c.runtime.startsWith(Qt))d.addIssue({code:"custom",message:"Android runtime must be an Android system-image identifier",path:["runtime"]});if(c.deviceType?.startsWith(Qt))d.addIssue({code:"custom",message:"Android deviceType must be an Android avdmanager device profile identifier",path:["deviceType"]});let g=c.configuration?.memoryMb;if(g!==void 0&&g<cd&&Tp(c.runtime))d.addIssue({code:"custom",message:`memoryMb must be at least ${cd} for Android API ${Cs}+ Play Store images`,path:["configuration","memoryMb"]})}function Es(c,d){if(c.runtime.startsWith(Ip))d.addIssue({code:"custom",message:"iOS runtime must be a CoreSimulator runtime identifier",path:["runtime"]});if(c.deviceType!==void 0&&!c.deviceType.startsWith(Qt)){let g=Po.ios;d.addIssue({code:"custom",message:`iOS deviceType must be a full CoreSimulator device-type identifier (${Qt}SimDeviceType.${c.deviceType}, not '${c.deviceType}'), e.g. '${g.example.deviceType}'; list the host's identifiers with ${g.catalog}`,path:["deviceType"]})}}var Os={runtime:Ts,deviceType:xs,displayCutout:ir,configuration:QT.optional()},Ms=s({runtime:qe("runtime",Po.ios,"CoreSimulator runtime identifier"),deviceType:qe("deviceType",Po.ios,"CoreSimulator device-type identifier"),displayCutout:ir},er(Po.ios)).strict().superRefine(Es),Cte=s({runtime:Ts,deviceType:xs.optional(),deviceFamily:Ds,displayCutout:ir,configuration:QT.optional()}).strict().superRefine(ni),Dte=s({runtime:kp,deviceType:Ep.optional(),deviceFamily:Ds,displayCutout:ir}).strict().superRefine(Es),xL=s({runtime:qe("runtime",Po.watchos,"watchOS CoreSimulator runtime identifier"),deviceType:qe("deviceType",Po.watchos,"Apple Watch CoreSimulator device-type identifier")},er(Po.watchos)).strict(),RW=xL,_s=s({runtime:qe("runtime",Po.tvos,"tvOS CoreSimulator runtime identifier"),deviceType:qe("deviceType",Po.tvos,"Apple TV CoreSimulator device-type identifier")},er(Po.tvos)).strict(),Ns=s({runtime:qe("runtime",Po.visionos,"visionOS CoreSimulator runtime identifier"),deviceType:qe("deviceType",Po.visionos,"Apple Vision Pro CoreSimulator device-type identifier")},er(Po.visionos)).strict();var CL=["pixel-baseline","samsung-oneui","xiaomi-hyperos","oneplus-oxygenos","oppo-coloros","motorola","huawei-emui","vivo-funtouch","realme-ui","meizu-flyme","asus-zenui","sony-xperia","tecno-hios"],Um=["samsung-dex","knox","flip-cover-screen","spen-air-actions","oem-systemui","oem-unused-app-triggers","firmware-update-exemption-reset","xiaomi-proprietary-appops"];var Ke=250,Vs=Q({initialDelayMs:Ke,multiplier:2,maxDelayMs:4000}),$s=3,Ws=90000,ci=3,Ks=8000,zs=3,qs=5000,Pt=2000,di=1000,Xs=5000,Ys=2,ui="17.0";class Ao 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:g=!1,phase:R,...A}={}){super(c);this.retryableAndroidFrameworkFailure=d,this.deadlineExhausted=g,this.phase=R,this.attempts=A.attempts,this.diagnosticCause=A.diagnosticCause,this.failureKind=A.failureKind}}var Js=4000;function Qs(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 ue(c){let d=r(c),g=Ka(d);if(g.length<=Js)return g;let R=Math.floor((Js-32)/2);return`${g.slice(0,R)}
|
|
3
|
+
...[diagnostic truncated]...
|
|
4
|
+
${g.slice(-R)}`}async function Zs(c,d,g,R){let A=Number.isNaN(R)?1:Math.floor(R??ci),C=Math.max(1,Math.min(ci,A)),D=[];for(let T=1;T<=C;T+=1){g.throwIfCallerCancelled(c),d.resetSetupState();let k=await g.runPhase(c,"runner-setup",T,{operation:(F)=>d.setup(!1,c.perf,F,g.remainingForPhase(c,"runner-setup"))}).catch((F)=>{if(F instanceof Ao&&D.length>0)g.fail(c,"runner-setup",T,{detail:F.diagnosticCause,deadlineExhausted:F.deadlineExhausted,failureKind:F.failureKind,previousAttemptDetails:D});throw F});if(c.onRunnerSetup?.(),g.throwIfCallerCancelled(c),k.success)break;let M=k.retryableStartupFailure===!0&&g.remainingForPhase(c,"runner-setup")<=0;if(!k.retryableStartupFailure||M||T===C)g.fail(c,"runner-setup",T,{detail:k.error??k.message,deadlineExhausted:M,previousAttemptDetails:D});D.push(`attempt ${T}/${C}: ${ue(k.error??k.message).slice(0,500)}`)}}class pi{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:g,nowMs:R}){if(c||!d||!g){this.clearOverload();return}if(this.consecutiveTimeouts++,!this.overloaded)return;if(this.backoffAttempt++,this.processRestarted)this.overloadedSinceRestartMs??=R}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 mi=2000,ea=1000;class it{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,g,{operation:R,operationDeadlineMs:A}){let C=Math.min(this.remainingForPhase(c,d),A===void 0?Number.POSITIVE_INFINITY:Math.max(0,A-this.timer.now()));if(C<=0)this.fail(c,d,g,{detail:"readiness budget exhausted before phase started",deadlineExhausted:!0});let D=!1,T,k=!1,M=()=>{k=this.timer.now()>=this.totalDeadlineMs(c)};if(c.signal?.addEventListener("abort",M,{once:!0}),c.signal?.aborted)M();let F=()=>{let X=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(`${X} timed out: readiness phase exceeded the remaining deadline. Retry device acquisition.`)},V=(X)=>k?T===void 0?F():u(T,`Runner readiness ${d} failed`):X,W=this.timer.now(),G=!1,q=()=>{if(G)return;G=!0;let X=Math.max(0,this.timer.now()-W);c.phaseElapsedMs[d]=(c.phaseElapsedMs[d]??0)+X};try{return await Bg({timer:this.timer,timeoutMs:C,deadline:it.movableDeadline(c,d,A),signal:c.signal,graceMs:ea,label:`Runner readiness ${d}`,preferOperationFailureOnTimeout:!0,explicitAbortError:V,defaultAbortError:()=>V(c.signal?.reason),timeoutError:()=>(D=!0,F()),onRaceSettled:q},async(X)=>{try{return await rr(`readiness:${d}`,()=>H(X,()=>R(X)))}catch(J){throw T=J,J}})}catch(X){if(q(),!k)this.throwIfCallerCancelled(c,X);return this.fail(c,d,g,{detail:X,deadlineExhausted:D||k})}finally{c.signal?.removeEventListener("abort",M),q()}}async awaitAbortSettlement(c){let d=Error("Abort settlement grace expired");try{await l(c.then(()=>{return},()=>{return}),{timer:this.timer,timeoutMs:ea,label:"Abort settlement grace",timeoutError:()=>d})}catch(g){if(g!==d)throw g}}probeTimeout(c){return Math.max(1,Math.min(mi,this.remainingForPhase(c,"runner-health")))}static isSetupPhase(c){return c==="runner-setup"||c==="package-compatibility"}static movableDeadline(c,d,g){return g===void 0&&it.isSetupPhase(d)?c.deadline:void 0}totalDeadlineMs(c){return c.deadline?.deadlineMs??c.totalDeadlineMs}phaseDeadlineMs(c,d){if(it.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,g,{detail:R,...A}){let{device:C}=c,D=`platform=${C.platform} requested=[${c.requestedIdentity}] resolved=[${C.name} (${C.deviceId})]`,T=this.remainingForPhase(c,d),k=Object.entries(c.phaseElapsedMs).map(([W,G])=>`${Qs(W)}=${G}`).join(" "),M=`${c.operationName??"startDevice"} automation runner readiness failed: ${D} phase=${d} attempts=${g} remainingBudgetMs=${T}${k?` ${k}`:""}`,F=[ue(R),...A.previousAttemptDetails??[]].join("; "),V=new Ao(A.failureKind?`${F}; ${M}`:`${M}: ${F}`,{retryableAndroidFrameworkFailure:C.platform==="android"&&it.isSetupPhase(d)&&(Al(R)||Xz(R)||$z(R)),deadlineExhausted:A.deadlineExhausted??!1,phase:d,attempts:g,diagnosticCause:R,failureKind:A.failureKind});if(A.deadlineExhausted)c.deadlineFailure=V;throw V}}class nr{dependencies;phases;constructor(c,d){this.dependencies=c;this.phases=d}async isResponsive(c,d,g){let R=c.deadlineFailure;try{return await this.probeUntilEvidence(c,d,g)}catch(A){if(!this.isHealthWindowExhaustion(c,A))throw A;return c.deadlineFailure=R,e.info(`[RunnerReadiness] iOS post-setup health window exhausted; restarting runner: ${A.message}`),!1}}isHealthWindowExhaustion(c,d){return d instanceof Ao&&d.deadlineExhausted&&(d.phase==="runner-health"||d.phase==="runner-connect")&&!c.signal?.aborted&&this.phases.remainingForPhase(c,"runner-setup")>0}async probeUntilEvidence(c,d,g){let R=Math.max(1,this.dependencies.iosPostSetupRestartMinFailedProbes??zs);for(let A=1;A<=R;A++){let C=d.runnerSnapshot?.().xcTestProcess;if(await this.isResponsiveOnce(c,g,A))return!0;if(C&&nr.exitedRunnerIsCurrent(d,C))return!1;let D=await this.phases.runPhase(c,"runner-health",A,{operation:()=>d.checkRunningWithReason?.()??Promise.resolve(void 0)});if(D?.ok===!1&&D.reason==="refused")return!1;if(A<R)await this.dependencies.timer.sleep(Math.min(Ke,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 g=c.runnerSnapshot?.().xcTestProcess??null;return g===null||g===d}async isResponsiveOnce(c,d,g){if(!(d.isConnected()||await this.phases.runPhase(c,"runner-connect",g,{operation:(C)=>d.connectWithoutSetup(C)})))return!1;let A=g===1?Math.min(Ks,this.phases.remainingForPhase(c,"runner-health")):this.phases.probeTimeout(c);return await this.phases.runPhase(c,"runner-health",g,{operation:()=>d.verifyServiceReady(1,0,A)})}}var fi="com.android.systemui",Op="System UI isn't responding",Mp="Wait",vi="android:id/alertTitle",yi="android:id/button2",bi="android:id/button1",_p=3;function Si(c,d=new js){let g=d.extractWindowRootGroups(c,"topmost-first")[0]??d.extractRootNodes(c);if(g.length===0)return;let R={systemUi:Hp(c)||Lp(c),systemWindow:Vp(c),titleFound:!1,alertTitleFound:!1,closeAppResourceFound:!1};for(let D of g)d.traverseNode(D,(T)=>Bp(T,d,R));let A=Fp(R)?R.waitBounds:void 0;if(A)return{waitBounds:A};let C=Np(R)?R.waitBoundsByResourceId:void 0;if(C)return{waitBounds:C};return}function Fp(c){return c.titleFound&&c.waitBounds!==void 0&&c.systemUi}function Np(c){return c.systemUi&&c.systemWindow&&c.alertTitleFound&&c.closeAppResourceFound&&c.waitBoundsByResourceId!==void 0}function Bp(c,d,g){let R=d.extractNodeProperties(c),A=or(R.text,R["content-desc"]),C=or(R.packageName,or(R.package,R["package-name"])),D=or(R["resource-id"],R.resourceId);if(g.systemUi||=C===fi,g.titleFound||=A===Op,g.alertTitleFound||=D===vi,g.closeAppResourceFound||=D===bi,A===Mp)g.waitBounds??=ta(d,c);if(D===yi)g.waitBoundsByResourceId??=ta(d,c)}function or(c,d){return String(c??d??"")}function ta(c,d){return c.parseBounds(qt(d))??void 0}function Lp(c){return ra(c)?.packageName===fi}function Hp(c){return c.packageName===fi}function Vp(c){return ra(c)?.type===_p}function ra(c){let d=c.windows;if(!d||d.length===0)return;return d.reduce((g,R)=>(R.windowLayer??0)>(g.windowLayer??0)?R:g)}function ia(c){return{x:Math.floor((c.left+c.right)/2),y:Math.floor((c.top+c.bottom)/2)}}class OT extends Ao{}var wi=1000,$p=2,Wp=5000;class Ri{timer;phases;constructor(c,d){this.timer=c;this.phases=d}async recoverIfPresent(c,d){let g=this.systemUiAnrClient(c,d);if(!g)return;let R=Math.min(c.healthDeadlineMs??c.totalDeadlineMs,this.timer.now()+Wp),A=await this.readSystemUiAnrHierarchy(c,g,R),C=Si(A??{hierarchy:{}});if(!C)return;await this.selectSystemUiAnrWait(c,g,C.waitBounds,R),await this.waitForSystemUiAnrRecovery(c,g,R,A?.updatedAt)}systemUiAnrClient(c,d){if(c.device.platform!=="android"||!d.getAccessibilityHierarchy||!d.requestTapCoordinates)return;return{getAccessibilityHierarchy:(...g)=>d.getAccessibilityHierarchy(...g),requestTapCoordinates:(...g)=>d.requestTapCoordinates(...g)}}async readSystemUiAnrHierarchy(c,d,g,{minTimestamp:R=0,required:A=!1}={}){let C=Math.min(this.phases.probeTimeout(c),this.remainingSystemUiAnrRecoveryBudget(g));if(C<=0){if(this.phases.throwIfCallerCancelled(c),!A)return null;throw this.systemUiAnrRecoveryRequired(c,"recovery budget expired before the dialog state could be confirmed")}try{let D=await this.phases.runPhase(c,"runner-health",1,{operation:async(k)=>await d.getAccessibilityHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:R,disableAllFiltering:!0,signal:k,timeoutMs:C})}),T=this.isSystemUiAnrHierarchyUnavailable(D,R);if(T&&A)throw this.systemUiAnrRecoveryRequired(c,"could not confirm dialog recovery: hierarchy unavailable");return T?null:D}catch(D){if(D instanceof OT)throw D;if(this.phases.throwIfCallerCancelled(c,D),!A)return null;throw this.systemUiAnrRecoveryRequired(c,`could not confirm dialog recovery: ${ue(D)}`)}}isSystemUiAnrHierarchyUnavailable(c,d){if(c===null||c.fresh===!1)return!0;return c.updatedAt!==void 0&&c.updatedAt<d}async selectSystemUiAnrWait(c,d,g,R){let{x:A,y:C}=ia(g);try{let D=await this.phases.runPhase(c,"runner-health",1,{operation:async()=>await d.requestTapCoordinates({x:A,y:C,duration:10,timeoutMs:Math.min(this.phases.probeTimeout(c),this.remainingSystemUiAnrRecoveryBudget(R))})});if(!D.success)throw Error(D.error??"unknown tap failure")}catch(D){throw this.phases.throwIfCallerCancelled(c,D),this.systemUiAnrRecoveryRequired(c,`could not select Wait: ${ue(D)}`)}}async waitForSystemUiAnrRecovery(c,d,g,R){let A=0,C=(R??0)+1;while(this.remainingSystemUiAnrRecoveryBudget(g)>0){await this.timer.sleep(Math.min(wi,this.remainingSystemUiAnrRecoveryBudget(g)));let D=await this.readSystemUiAnrHierarchy(c,d,g,{minTimestamp:C,required:!0});if(C=Math.max(C,(D?.updatedAt??0)+1),Si(D??{hierarchy:{}})){A=0;continue}if(A++,A>=$p)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 OT(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 na(c){return(c.isLastConnectionFailureForwardingLeaseConflict?.()??!1)&&!(c.isLastConnectionFailureTransientLeaseConflict?.()??!1)}var Gp=10;class DL{dependencies;phases;anrRecovery;iosPostSetupProbe;constructor(c){this.dependencies=c;this.phases=new it(c.timer),this.iosPostSetupProbe=new nr(c,this.phases),this.anrRecovery=new Ri(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 pi({backoff:this.dependencies.androidHealthProbeBackoff??Vs,baseDelayMs:Ke,minConsecutiveTimeouts:$s,failAfterRestartMs:this.dependencies.ctrlProxyUnresponsiveAfterRestartFailMs??Ws}),lastSuccessfulRebindMs:Number.NEGATIVE_INFINITY,failedHealthProbesSinceRecovery:0},g=po(c.device.platform,c.device.deviceId),R=await this.acquireReadinessTurn(d,g);try{c.signal?.throwIfAborted(),c.assertCanSetup?.(),await this.ensureReadyUncoordinated(d)}finally{R()}}async ensureReadyUncoordinated(c){let d=c.perf,g=async()=>{if(c.device.platform==="android"){await this.ensureAndroidReady(c);return}await this.ensureIosReady(c)};if(!d)return g();return _c(xc(d),g)}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 lO(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(g){this.phases.throwIfCallerCancelled(c,g),this.phases.fail(c,"runner-setup",1,{detail:ue(g),deadlineExhausted:!0})}}async ensureAndroidReady(c){this.phases.throwIfCallerCancelled(c);let d=this.inspectAndroidFrameworkBestEffort(c);try{let g="Android framework readiness budget exhausted";await new kn(this.dependencies.timer).executeOrThrow(async(R)=>{if(this.phases.throwIfCallerCancelled(c),this.phases.remainingForPhase(c,"runner-setup")<=0)this.phases.fail(c,"runner-setup",R,{detail:g,deadlineExhausted:!0});if(R>1)this.dependencies.getAndroidManager(c.device).resetSetupState();await this.ensureAndroidReadyAttempt(c),this.phases.throwIfCallerCancelled(c)},{maxAttempts:Math.ceil(this.phases.remainingForPhase(c,"runner-setup")/Ke)+1,signal:c.signal,delays:()=>Math.min(Ke,this.phases.remainingForPhase(c,"runner-setup")),shouldRetry:(R)=>R instanceof Ao&&R.retryableAndroidFrameworkFailure&&this.phases.remainingForPhase(c,"runner-setup")>0,onRetry:(R)=>{g=ue(R),e.debug(`Retrying Android framework setup: ${g}`)}})}catch(g){throw this.phases.throwIfCallerCancelled(c,g),g}finally{await d?.(),this.phases.throwIfCallerCancelled(c)}}async ensureAndroidReadyAttempt(c){let d=this.dependencies.getAndroidManager(c.device),g=this.dependencies.getAndroidClient(c.device);if(c.skipCtrlProxyDownload){await this.ensureAndroidReadyWithoutDownloads(c,d,g);return}let R=await this.phases.runPhase(c,"package-compatibility",1,{operation:(D)=>d.ensureCompatibleVersion({allowDownloadWhenInstalled:!0,bypassVersionCheckCache:!1},D)});this.assertAndroidCompatibility(c,R);let[A,C]=await this.phases.runPhase(c,"runner-setup",1,{operation:async(D)=>[await d.isInstalled(D),await d.isEnabled(D)]});if(await this.isResponsiveFastPath(c,g,A&&C)){await this.anrRecovery.recoverIfPresent(c,g);return}d.reopenSetupGate(),await this.setupAndroidRunner(c,d),await this.waitForResponsiveClient(c,g,d),await this.anrRecovery.recoverIfPresent(c,g)}inspectAndroidFrameworkBestEffort(c){let d=this.dependencies.getAndroidFrameworkReadiness;if(!d)return;let g=Math.max(0,c.totalDeadlineMs-this.dependencies.timer.now());if(g<=0)return;let R=new AbortController,A=c.signal?AbortSignal.any([c.signal,R.signal]):R.signal,C=Math.min(mi,g),D=this.dependencies.timer.setTimeout(()=>R.abort(Error("Android framework inspection timed out")),C),T=Promise.resolve().then(()=>(A.throwIfAborted(),d(c.device,A,C))).then((k)=>{if(!k.ready)e.debug(`Android framework inspection is not ready yet: ${k.unavailableResources?.join(", ")??"unknown resources"}${k.diagnostic?`; ${ue(k.diagnostic)}`:""}`)},(k)=>{e.debug(`Android framework inspection failed: ${ue(k)}`)}).finally(()=>this.dependencies.timer.clearTimeout(D));return async()=>{R.abort(Error("Android readiness inspection finished")),this.dependencies.timer.clearTimeout(D),await this.phases.awaitAbortSettlement(T)}}async ensureAndroidReadyWithoutDownloads(c,d,g){let[R,A]=await this.phases.runPhase(c,"runner-setup",1,{operation:async(D)=>[await d.isInstalled(D),await d.isEnabled(D)]});if(!R)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,g,A)){await this.anrRecovery.recoverIfPresent(c,g);return}if(!A)await this.phases.runPhase(c,"runner-setup",1,{operation:()=>d.enable()});await this.waitForResponsiveClient(c,g,d),await this.anrRecovery.recoverIfPresent(c,g)}assertAndroidCompatibility(c,d){if(!(d.status==="failed"||d.status==="skipped"||d.acceptedPreinstalled===!0))return;let R=[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((A)=>Boolean(A));this.phases.fail(c,"package-compatibility",1,{detail:d.cause??R.join("; ")})}async isResponsiveFastPath(c,d,g){if(!g||!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 g=await this.phases.runPhase(c,"runner-setup",1,{operation:(T)=>d.setup(!1,c.perf,T)});if(!g.success)this.phases.fail(c,"runner-setup",1,{detail:g.cause??g.error??g.message});let R=Math.min(c.totalDeadlineMs,this.dependencies.timer.now()+qs),A=0,C=!1,D=!1;for(;;){if(A++,[C,D]=await this.phases.runPhase(c,"runner-setup",A,{operation:async(T)=>[await d.isInstalled(T),await d.isEnabled(T,{bypassCache:A>1})],operationDeadlineMs:R}),C&&D)return;if(!C||this.dependencies.timer.now()>=R)break;if(this.phases.throwIfCallerCancelled(c),await this.dependencies.timer.sleep(Math.min(Ke,R-this.dependencies.timer.now())),this.phases.throwIfCallerCancelled(c),this.dependencies.timer.now()>=R)break;await this.phases.runPhase(c,"runner-setup",A,{operation:()=>d.enable(),operationDeadlineMs:R})}if(!C||!D)this.phases.fail(c,"runner-setup",A,{detail:`CtrlProxy state after setup: installed=${C}, enabled=${D}`})}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 g=this.dependencies.getIosManager(c.device),R=this.dependencies.getIosClient(c.device,g.getServicePort());if(R.isConnected()){if(this.phases.startHealthWindow(c),await this.phases.runPhase(c,"runner-health",1,{operation:()=>R.verifyServiceReady(1,0,this.phases.probeTimeout(c))}))return;g.resetSetupState(),await this.phases.runPhase(c,"runner-setup",1,{operation:(C)=>g.forceRestart({signal:C,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-health")})}),c.healthDeadlineMs=null,R=this.dependencies.getIosClient(c.device,g.getServicePort()),await this.waitForResponsiveClient(c,R);return}if(c.skipCtrlProxyDownload){await this.ensureIosReadyWithoutDownloads(c,g);return}await Zs(c,g,this.phases,this.dependencies.iosSetupMaxAttempts),R=this.dependencies.getIosClient(c.device,g.getServicePort()),await this.ensureIosClientReadyAfterStart(c,g,R)}assertIosRuntimeCompatible(c){let d=c.device.iosVersion??c.device.osVersion,g=uB(d,ui);if(g!==null&&g<0)this.phases.fail(c,"runner-setup",1,{detail:`iOS runtime ${d} is below the CtrlProxy minimum ${ui}; 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:(A)=>d.start({signal:A,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-setup")})});let R=this.dependencies.getIosClient(c.device,d.getServicePort());await this.ensureIosClientReadyAfterStart(c,d,R)}async ensureIosClientReadyAfterStart(c,d,g){if(this.phases.startHealthWindow(c),await this.iosPostSetupProbe.isResponsive(c,d,g))return;d.resetSetupState(),await this.phases.runPhase(c,"runner-setup",1,{operation:(A)=>d.forceRestart({signal:A,minimumHealthPollDurationMs:this.phases.remainingForPhase(c,"runner-setup")})}),c.healthDeadlineMs=null;let R=this.dependencies.getIosClient(c.device,d.getServicePort());await this.waitForResponsiveClient(c,R)}async waitForResponsiveClient(c,d,g){let R={release:c.device.platform==="android"?d.beginReadinessHold?.():void 0};try{await this.pollResponsiveClient(c,d,R,g)}finally{R.release?.()}}async pollResponsiveClient(c,d,g,R){this.phases.startHealthWindow(c);let A=0,C=d.isConnected(),D=C?"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,g,A);if(A++,C=d.isConnected(),!C){if(c.androidProbeOverload.recordDisconnect(),D="runner-connect",await this.rebindUnhealthyAndroidAccessibilityService(c,R,A,d),C=await this.phases.runPhase(c,D,A,{operation:()=>d.waitForConnection(1,0)}),!C&&na(d))await this.failUnresponsiveClient(c,d,D,{attempts:A})}if(C){if(D="runner-health",await this.probeResponsiveClient(c,d,A,R))return}if(c.device.platform==="android"&&this.dependencies.timer.now()-T>=wi)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,C),k))}await this.failUnresponsiveClient(c,d,D,{attempts:A})}healthProbeRetryDelay(c,d){if(c.device.platform!=="android"||!d)return Ke;return c.androidProbeOverload.retryDelayMs()}async probeResponsiveClient(c,d,g,R){let A=this.phases.probeTimeout(c),C=this.dependencies.timer.now(),D=await this.phases.runPhase(c,"runner-health",g,{operation:()=>d.verifyServiceReady(1,0,A)});if(c.device.platform!=="android")return D;let T=this.dependencies.timer.now();if(c.androidProbeOverload.recordProbe({ready:D,connected:d.isConnected(),timedOut:T-C>=A-Gp,nowMs:T}),D)return!0;return await this.recoverConnectedButUnresponsiveAndroid(c,R,d,g),await this.failPersistentlyUnresponsiveAndroid(c,d,g),!1}async replaceClosedAndroidClient(c,d,g,R){if(!d.isClosed?.())return d;g.release?.(),g.release=void 0;let A=this.dependencies.getAndroidClient(c.device);if(e.info(`[RunnerReadiness] Re-resolved closed CtrlProxy client for ${c.device.deviceId}`),g.release=A.beginReadinessHold?.(),A.isClosed?.())await this.failUnresponsiveClient(c,A,"runner-connect",{attempts:R,deadlineExhausted:!1});return A}async rebindUnhealthyAndroidAccessibilityService(c,d,g,R){if(c.device.platform!=="android"||!d?.rebindIfUnhealthy||c.ctrlProxyAccessibilityRebindAttempted||this.dependencies.timer.now()-c.lastCtrlProxyRebindMs<di)return;let A=await this.phases.runPhase(c,"runner-connect",g,{operation:async()=>{try{return await d.rebindIfUnhealthy()}catch(C){if(!(C instanceof bR))throw C;return e.warn(`[CTRL_PROXY] Accessibility rebind inspection unavailable: ${C}`,C),!1}}});if(c.lastCtrlProxyRebindMs=this.dependencies.timer.now(),c.ctrlProxyAccessibilityRebindAttempted||=A,A)R.resetConnectionBudget?.()}async recoverConnectedButUnresponsiveAndroid(c,d,g,R){if(c.device.platform!=="android"||!d)return;if(c.failedHealthProbesSinceRecovery++,this.dependencies.timer.now()-c.lastConnectedRecoveryMs<di)return;let A=c.failedHealthProbesSinceRecovery;if(c.lastConnectedRecoveryMs=this.dependencies.timer.now(),d.rebindIfUnhealthy&&!c.ctrlProxyAccessibilityRebindAttempted){let D=await this.phases.runPhase(c,"runner-health",R,{operation:()=>d.rebindIfUnhealthy()});if(c.ctrlProxyAccessibilityRebindAttempted||=D,D){c.failedHealthProbesSinceRecovery=0,c.lastSuccessfulRebindMs=this.dependencies.timer.now(),g.resetConnectionBudget?.();return}}if(!this.canEscalateToProcessRestart(c,d,A))return;if(c.ctrlProxyProcessRestartAttempted=!0,await this.phases.runPhase(c,"runner-health",R,{operation:()=>d.forceRestartProcess()}))c.androidProbeOverload.recordProcessRestart(),g.resetConnectionBudget?.()}async failPersistentlyUnresponsiveAndroid(c,d,g){if(d.isConnected()&&c.androidProbeOverload.shouldFailFast(this.dependencies.timer.now()))await this.failUnresponsiveClient(c,d,"runner-health",{attempts:g,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,g){if(c.ctrlProxyProcessRestartAttempted||!d.forceRestartProcess)return!1;if(g<Ys)return!1;return this.dependencies.timer.now()-c.lastSuccessfulRebindMs>=Xs}async failUnresponsiveClient(c,d,g,{attempts:R,deadlineExhausted:A=!0,detail:C}){if(g==="runner-connect"&&(d.isLastConnectionFailureForwardingLeaseConflict?.()??!1)){let k=d.getLastConnectionFailureMessage?.();if(k)this.phases.fail(c,g,R,{detail:k})}if(g==="runner-connect")this.failForwardUnavailableClient(c,d,R,A);let T=g==="runner-connect"?await this.runnerConnectFailureDiagnostic(c):await this.runnerHealthFailureDiagnostic(c,g);this.phases.fail(c,g,R,{detail:`${C??this.unresponsiveClientRecoveryNote(c,g)}${T}`,deadlineExhausted:A})}failForwardUnavailableClient(c,d,g,R){let A=d.getForwardFailureCause?.()??(d.isClosed?.()?`CtrlProxy client for ${c.device.deviceId} is closed; adb forward unavailable`:void 0);if(A)this.phases.fail(c,"runner-connect",g,{detail:A,deadlineExhausted:R,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 g=await this.collectBoundedAndroidDiagnostic(c,d,"runner-connect");if(!g)return"";let R=[g.primaryUserStartState?`primaryUserStartState=${g.primaryUserStartState}`:void 0,g.deviceLock?`deviceLock=${g.deviceLock.locked?"locked":"unlocked"}`:void 0].filter((A)=>Boolean(A));return R.length>0?`; ${R.join(" ")}`:""}async runnerHealthFailureDiagnostic(c,d){let g=this.dependencies.getAndroidRunnerHealthDiagnostic;if(c.device.platform!=="android"||d!=="runner-health"||!g)return"";let R=await this.collectBoundedAndroidDiagnostic(c,g,"runner-health");if(!R)return"";return`; sys.boot_completed=${R.sysBootCompleted} adbDevices=${R.adbDevices} emulatorQemuHealth=${R.emulatorQemuHealth}`}async collectBoundedAndroidDiagnostic(c,d,g){try{let R=new AbortController,A=c.signal?AbortSignal.any([c.signal,R.signal]):R.signal,C=d(c.device,A);C.catch((k)=>{e.debug(`Android readiness diagnostic rejection observed: ${r(k)}`)});let D=Error(`${g} diagnostic timed out`),T;try{T=await l(C,{timer:this.dependencies.timer,timeoutMs:Pt,label:`${g} diagnostic`,timeoutError:()=>D,onTimeout:()=>R.abort(D)})}catch(k){if(k!==D)throw k}if(!T)return;return T}catch(R){e.debug(`Failed to collect Android ${g} diagnostic: ${r(R)}`);return}}}class MT{ports;firstObservationMs;attempt=0;backoff;budgetMs;constructor(c){this.ports=c;this.backoff=c.backoff??Q({initialDelayMs:100,maxDelayMs:1000}),this.budgetMs=c.budgetMs??5000}remainingMs(){return this.firstObservationMs??=this.ports.timer.now(),Math.max(0,this.budgetMs-(this.ports.timer.now()-this.firstObservationMs))}async waitForNextAttempt(){let{timer:c,getSignal:d}=this.ports,g=d();g?.throwIfAborted();let R=this.remainingMs();if(R<=0)return!1;let A=Math.min(this.backoff.delayForAttempt(++this.attempt),R);if(A<=0)return!1;let C;try{await l(()=>new Promise((D)=>{C=c.setTimeout(D,A)}),{timer:c,signal:g,label:"Exact device adb transport wait"})}finally{if(C!==void 0)c.clearTimeout(C)}return g?.throwIfAborted(),!0}}class qC extends t{operation;phase;elapsedMs;code="timeout";retryable=!0;budgetMs;device;constructor(c,d,g,{budgetMs:R,device:A}){super(`${c} timeout exhausted while ${d}; `+(A?`device=${A}; `:"")+`remainingBudgetMs=0; elapsedMs=${g}; budgetMs=${R}; origin=DeviceBootService`);this.operation=c;this.phase=d;this.elapsedMs=g;this.budgetMs=R,this.device=A}}function Te(c,d){return{...c,...Kp(c,d),...zp(c,d),capabilityInventory:c.capabilityInventory??d.capabilityInventory}}function Kp(c,d){return{iosVersion:c.iosVersion??d.iosVersion,apiLevel:c.apiLevel??d.apiLevel,osVersion:c.osVersion??d.osVersion,runtimeId:c.runtimeId??d.runtimeId,runtime:c.runtime??d.runtime}}function zp(c,d){return{deviceType:c.deviceType??d.deviceType,formFactor:c.formFactor??d.formFactor,screenWidth:c.screenWidth??d.screenWidth,screenHeight:c.screenHeight??d.screenHeight,screenDensity:c.screenDensity??d.screenDensity,model:c.model??d.model,architecture:c.architecture??d.architecture}}function sr(c,d){return d.find((g)=>g.platform===c.platform&&(g.deviceId===c.deviceId||c.platform==="android"&&ae(c.deviceId)&&g.name===c.name))}var Ai=1000,oa=5000;function OL(c,d,g){let R=typeof c.once!=="function"||c.exitCode!==null||c.signalCode!==null,A=R?Promise.resolve():new Promise((C)=>{c.once("exit",()=>C())});try{c.kill()}catch(C){e.warn(`[ColdBoot] Failed to cancel cold boot ${d}: ${r(C)}`,C)}return{exited:A,confirmed:c.terminationConfirmed??(R?Promise.resolve(!0):qp(A,c,d,g))}}async function qp(c,d,g,R){if(await sa(c,R))return!0;e.warn(`[ColdBoot] Cold boot ${g} did not exit within ${Ai}ms; escalating to SIGKILL`);try{d.kill("SIGKILL")}catch(C){e.debug(`[ColdBoot] SIGKILL for cold boot ${g} failed: ${r(C)}`)}let A=await sa(c,R);if(!A)e.warn(`[ColdBoot] Cold boot ${g} did not exit within ${Ai}ms of SIGKILL`);return A}async function sa(c,d){let g=Error("Cold boot exit wait timed out");try{return await l(c.then(()=>!0),{timer:d,timeoutMs:Ai,label:"Cold boot exit",timeoutError:()=>g})}catch(R){if(R===g)return!1;throw R}}function aa(c){if(typeof c==="object"&&c!==null&&typeof c.unref==="function")c.unref()}function Xp(c,d,g,{timer:R,isProcessRunning:A=st,processGeneration:C=kt}){let D=c.pid,T=D===void 0?void 0:C.current(D);return new Promise((k)=>{let M,F=!1,V=()=>{if(F=!0,M!==void 0)R.clearTimeout(M),M=void 0;k()};if(d.then(V,V),D===void 0)return;let W=()=>{if(M=void 0,F)return;if(T!==void 0&&C.compare(D,T)==="different"){e.warn(`[ColdBoot] Cold boot ${g} process ${D} now names a different process; releasing its AVD`),V();return}if(!A(D)){e.warn(`[ColdBoot] Cold boot ${g} process ${D} is gone; releasing its AVD`),V();return}M=R.setTimeout(W,oa),aa(M)};M=R.setTimeout(W,oa),aa(M)})}async function PW(c,d,g,R={}){let{exited:A,confirmed:C}=OL(c,d,g);try{if(await C)return{state:"confirmed"}}catch(T){if(c.terminationConfirmed!==void 0)return e.warn(`[startDevice] Resource cleanup for ${d} was unconfirmed: ${r(T)}`,T),{state:"cleanup-unconfirmed"};return e.warn(`[startDevice] Could not observe exit of emulator process ${c.pid??"unknown"}: ${r(T)}`,T),{state:"unobservable"}}if(c.terminationConfirmed!==void 0)return e.warn(`[startDevice] Resource cleanup for ${d} was unconfirmed`),{state:"cleanup-unconfirmed"};e.warn(`[startDevice] Emulator process ${c.pid??"unknown"} for ${d} survived SIGTERM and SIGKILL; holding the AVD lifecycle lease until it is gone`);let D=Xp(c,A,d,{timer:g,isProcessRunning:R.isProcessRunning,processGeneration:R.processGeneration});return R.markHeldByUnkillableProcess?.(c.pid),{state:"survived",gone:D}}async function ca(c,d){let g=d.deadlineMs-d.timer.now();if(d.signal?.aborted||g<=0)return"pending";let R=Error("Request ended before the emulator termination settled");try{return(await l(c,{timer:d.timer,timeoutMs:g,signal:d.signal,label:"Cold boot termination",timeoutError:()=>R})).state}catch(A){if(A===R||d.signal?.aborted)return"pending";throw A}}var Yp=1000;class Ii{dependencies;timer;constructor(c,d){this.dependencies=c;this.timer=d}async discoverBootedDevices(c,d,g,{bypassAndroidCache:R=!1,awaitAbortSettlement:A=!0,presentationOrder:C}={}){let D=c==="android"||C!==void 0,T={skipForeignEnrichment:!0,...R?{bypassAndroidDeviceListCache:!0}:{},...C!==void 0?{presentationOrder:C}:{}};if(D){let k=await this.runPhase(d,g,(M)=>this.dependencies.deviceManager.getBootedDevicesDetailed(c,{...T,signal:M}),A);if(c==="android"&&!k.succeededPlatforms.has("android"))throw new Gr(k.discoveryErrors?.android);return k.devices.filter((M)=>!M.foreignOwned)}return await this.runPhase(d,g,()=>this.dependencies.deviceManager.getBootedDevices(c),A)}async enrichBootedDeviceFromImage(c,d){let g=await this.runPhase(d,`resolving ${c.platform} device metadata`,(A)=>this.dependencies.deviceManager.listDeviceImages(c.platform,A)),R=sr(c,g);return{device:R?Te(c,R):c,image:R}}async recheckRunningState(c,d){if(c.platform!=="android")return c;let g=new MT({timer:this.timer,getSignal:()=>d.signal,budgetMs:Math.min(5000,Math.max(0,d.deadlineMs-this.timer.now()))});while(await g.waitForNextAttempt()){if(d.deadlineMs<=this.timer.now())break;let A=(await this.runPhase(d,"rechecking Android image running state",(C)=>((this.dependencies.invalidateAndroidDeviceList??ob)(),this.dependencies.deviceManager.listDeviceImages("android",C)))).find((C)=>C.name===c.name);if(!A)break;if(A.isRunningStateKnown===!1)continue;if(A.isRunning)throw new Gr(void 0,`Cannot safely cold-boot Android AVD '${c.name}': it turned out to be running. Retry the request.`);return A}return c}async bootImageOnceWithOwnedLaunchTracking(c,d,g,R){let A=()=>{},C=await this.runPhase(d,"starting the device",async(V)=>{let W=await this.startDeviceOwningCancelledLaunch(c,d),G=()=>{if(W)OL(W,c.name,this.timer).confirmed.catch((q)=>{e.warn(`[startDevice] Late start handle cleanup failed for ${c.name}: ${r(q)}`,q)})};if(V.aborted)G();else V.addEventListener("abort",G,{once:!0}),A=()=>V.removeEventListener("abort",G);return W});A();let D,T,k=()=>{if(!C)return Promise.resolve({state:"confirmed"});return D??=this.terminateOwnedHandle(C,c,d),D},M=()=>(T??=this.awaitOwnedCleanup(k(),d),T),F=()=>{k()};d.signal?.addEventListener("abort",F,{once:!0});try{await this.reportProgress(d,g,60,"Device started, waiting for readiness...");let V=await this.runPhase(d,"waiting for device boot readiness",()=>Pf(this.dependencies.deviceManager,c,C,{timeoutMs:this.remaining(d,"waiting for device boot readiness"),signal:d.signal,timer:this.timer,cancelOwnedBoot:async()=>{await M()},createTimeoutError:()=>this.timeoutError(d,"waiting for device boot readiness"),readinessOptions:c.platform==="android"&&(R||d.freshProvision===!0)?{freshProvision:!0}:void 0}));return await this.reportProgress(d,g,100,"Device is ready for use"),{device:Te(V,c),source:"cold-boot",sourceImage:c,processHandle:C,processId:C?.pid,provisioned:R}}catch(V){let W=await M();throw Jp(V,W,C)}finally{d.signal?.removeEventListener("abort",F)}}async terminateOwnedHandle(c,d,g){let R=await PW(c,d.name,this.timer,{markHeldByUnkillableProcess:(A)=>g.lifecycleLease?.markHeldByUnkillableProcess?.(A),isProcessRunning:this.dependencies.isProcessRunning});if(R.state==="survived")g.unconfirmedProcessExits.push(R.gone),this.dependencies.retainLeaseUntil?.(R.gone);return R}async awaitOwnedCleanup(c,d){if(!this.canHoldCleanup(d))return(await c).state;let g=await ca(c,{timer:this.timer,deadlineMs:d.deadlineMs,signal:d.signal});if(g==="pending")this.holdLeaseUntilSettled(c,d);return g}canHoldCleanup(c){return this.dependencies.cleanupMayOutliveRequest===!0&&(c.ownsLifecycleLease||this.dependencies.retainLeaseUntil!==void 0)}holdLeaseUntilSettled(c,d){let g=c.then((R)=>R.state==="survived"?R.gone:void 0,()=>{return});d.pendingTerminations.push(g),this.dependencies.retainLeaseUntil?.(g)}async startDeviceOwningCancelledLaunch(c,d){try{return await this.dependencies.deviceManager.startDevice(c,this.remaining(d,"starting the device"),d.request.cameraPosterPath===void 0&&d.request.discardSnapshotOnExit!==!0?void 0:{...d.request.cameraPosterPath===void 0?{}:{cameraPosterPath:d.request.cameraPosterPath},...d.request.discardSnapshotOnExit===!0?{discardSnapshotOnExit:!0}:{}})}catch(g){if(Zg(g)&&g.process)this.ownCancelledLaunchTermination(this.terminateOwnedHandle(g.process,c,d),d);throw g}}ownCancelledLaunchTermination(c,d){if(this.canHoldCleanup(d)){this.holdLeaseUntilSettled(c,d);return}d.unheldLaunchTermination=c}async reportProgress(c,d,g,R){if(!d)return;await this.runPhase(c,`reporting ${g}% device boot progress`,()=>d.report(g,100,R),!1)}remaining(c,d){let g=Math.floor(c.deadlineMs-this.timer.now());if(g<=0)throw this.timeoutError(c,d);return g}async runPhase(c,d,g,R=!0){let A=this.remaining(c,d);if(c.signal?.aborted)throw new t(`startDevice cancelled while ${d}`);return await Bg({timer:this.timer,timeoutMs:A,signal:c.signal,graceMs:Yp,label:d,timeoutError:()=>this.timeoutError(c,d),defaultAbortError:()=>new t(`startDevice cancelled while ${d}`),awaitAbortSettlement:R,preferOperationFailureOnTimeout:!0},(C)=>H(C,()=>g(C)))}timeoutError(c,d){return new qC(c.operationName,d,this.timer.now()-c.startedAtMs,{budgetMs:Math.max(0,c.deadlineMs-c.startedAtMs),device:c.deviceLabel??c.request.name??c.request.deviceId})}}function Jp(c,d,g){let R=g?.pid??"unknown";if(d==="cleanup-unconfirmed")return Pi(c,"Cleanup also failed: device shutdown could not be confirmed.");if(d==="survived")return Pi(c,`Cleanup also failed: emulator process ${R} did not exit after SIGTERM and SIGKILL, so its AVD stays reserved until the process is gone (its liveness is re-checked periodically); terminate that process manually if it does not.`);if(d==="unobservable")return Pi(c,`Cleanup also failed: the exit of emulator process ${R} could not be observed, so its AVD was released; terminate that process manually if it is still running.`);return c}function Pi(c,d){if(c instanceof Error&&!(c instanceof DOMException)){let g=Object.create(Object.getPrototypeOf(c),Object.getOwnPropertyDescriptors(c));return Object.defineProperty(g,"message",{value:`${c.message} ${d}`,writable:!0,configurable:!0}),g}return new t(`${r(c)} ${d}`,{cause:c})}var Qp=["android","ios","watchos","tvos","visionos"],Zp=["watchos","tvos","visionos"],em=` startDevice platforms: ${Qp.join(", ")}. The iOS images above never include Apple Watch, Apple TV or Apple Vision Pro simulators: start a watch with platform: "watchos" (an Apple TV with "tvos", a Vision Pro with "visionos") and its UDID or exact name. To create a simulator, enable provisionDevice (enableTools) and call it with device {"platform":"ios","name":"<name>","spec":{"runtime":"<runtime identifier>","deviceType":"<device type identifier>","displayCutout":"any"}} (for a watch, "platform":"watchos" with a watchOS runtime and Apple Watch device type); remove it with deleteDevice.`;async function fa(c,{deviceId:d,platform:g},R){if(g!=="ios")return;return(await Promise.all(Zp.map(async(C)=>{try{return(await c.listDeviceImages(C,R)).some((T)=>T.deviceId===d)?C:void 0}catch(D){R?.throwIfAborted(),e.warn(`[DeviceBoot] ${C} simulator lookup for '${d}' failed: ${r(D)}`,D);return}}))).find((C)=>C!==void 0)}function ha(c,d,g,R){if(R)return new t(`Device '${c.deviceId}' is a ${Ui[R]} simulator, not an iOS simulator. Call startDevice with platform: "${R}" and the same deviceId.`);return new t(`Device '${c.deviceId}' not found. Available booted: ${d.map((A)=>A.deviceId).join(", ")||"none"}. Available images: ${g.map((A)=>A.name).join(", ")||"none"}.`+(c.platform==="ios"?em:""))}class It extends t{candidateSerials;code="target_identity_unresolved";retryable=!0;retryAfterMs=fd;deviceId;constructor(c,d){super(c);this.candidateSerials=d;if(d.length===1)this.deviceId=d[0]}toPayload(){return{code:this.code,retryable:this.retryable,retryAfterMs:this.retryAfterMs,candidateSerials:this.candidateSerials,...this.deviceId!==void 0?{deviceId:this.deviceId}:{}}}}class VC extends It{avdName;constructor(c,d){super(`target_identity_unresolved: Cannot prove whether Android AVD '${c}' is already running; AVD name is unavailable for ${d.join(", ")}. Retry after identity discovery recovers.`,d);this.avdName=c}toPayload(){return{...super.toPayload(),avdName:this.avdName}}}function cr(c,d){let g=c.filter((R)=>!R.foreignOwned&&R.platform==="android"&&ae(R.deviceId)&&R.name===`Unknown (${R.deviceId})`).map((R)=>R.deviceId);if(g.length>0)throw new VC(d,[...new Set(g)].toSorted())}function va(c,d,g,R){if(!g||c.platform!=="android")return;if(!R)cr(d,c.name);let A=c.deviceId&&ae(c.deviceId)?d.find((C)=>!C.foreignOwned&&C.deviceId===c.deviceId&&C.name!==c.name):void 0;if(A)throw new t(`target_identity_mismatch: Configured Android AVD '${c.name}' lists serial '${c.deviceId}', but that serial is running '${A.name}'. Refresh device inventory and retry.`)}class Ci{get(c){return Bz(c)}}var Ct=h.ALLOW_DEVICE_CREATE.name,ba="AutoMobile";class Sa{environment;constructor(c=new Ci){this.environment=c}isCreationAllowed(c){if(typeof c==="boolean")return c;return W8(this.environment.get(Ct))}describeSource(c){if(typeof c==="boolean")return`--create-if-missing=${c}`;let d=this.environment.get(Ct);if(d===void 0)return"default (off)";return`${Ct}=${d}`}}var Di=null;function Mw(){if(!Di)Di=new Sa;return Di}var wa={cleanup_failed:!1,creation_not_allowed:!1,device_lost:!0,device_owned_by_other_session:!0,device_owned_by_other_daemon:!0,device_cleanup_in_progress:!0,session_creation_timeout:!0,device_shutting_down:!0,device_assigned_to_binding:!1,device_offline:!0,discovery_incomplete:!0,capacity_exhausted:!0,identity_conflict:!1,timeout:!0,unsupported:!1,platform_command_failed:!1,resource_profile_unproven:!1,unsafe_device_resource_combination:!1,runtime_incompatible:!1,requires_real_device:!1};class Ue extends t{code;retryable;diagnostics;constructor(c,d,g=wa[c],R={}){super(d);this.code=c;this.retryable=g;this.diagnostics=R;this.name="ProvisionDeviceError"}}class ng extends Ue{constructor(c){super("platform_command_failed",c);this.name="ProvisionDeviceCreateRejectedError"}}function Ra(c){return`${c[0]}.${c[1]}.${c[2]}`}function WC(c){return c.minRuntimeVersionString!==void 0||c.maxRuntimeVersionString!==void 0||c.minRuntimeVersion!==0||c.maxRuntimeVersion!==0}function Aa(c,d){return c!==void 0?hR(c):Tne(d)}function Pa(c){if(!WC(c))return;let d=Aa(c.minRuntimeVersionString,c.minRuntimeVersion),g=Aa(c.maxRuntimeVersionString,c.maxRuntimeVersion);return d&&g&&Cp(d,g)<=0?{min:d,max:g}:void 0}var tm=[65535,255,255];function rm(c){return!Number.isFinite(c[0])||Cp(c,tm)>=0}function Ia(c){return{minVersion:Ra(c.min),maxVersion:rm(c.max)?null:Ra(c.max)}}function zC(c){let d=Pa(c);return d?Ia(d):void 0}function Rc(c,d){let g=Pa(c);if(!g)return{status:"unknown",reason:WC(c)?"device type runtime range is malformed":"device type has no runtime range metadata"};let R=Ia(g),A=hR(d);if(!A)return{status:"unknown",bounds:R,reason:"runtime version is missing or malformed"};return{status:Cp(A,g.min)>=0&&Cp(A,g.max)<=0?"supported":"unsupported",bounds:R}}function Ca(c){let d=Ud(c);return{kind:c,accepts:(g)=>d.includes(g),rank:(g)=>d.indexOf(g),deviceProfile:jl(c),namePrefix:`android-${c}`}}var Ti={"xr-headset":Ca("xr-headset"),"xr-glasses":Ca("xr-glasses")},Da={"xr-headset":"google-xr","xr-glasses":"ai-glasses"},im={"xr-headset":34,"xr-glasses":36};function Ta(c,{bounds:d,range:g,installed:R,abi:A}){let C=c==="xr-headset"?"Android XR headset":"Android XR glasses",D=im[c],T=`No installed ${C} system image (${Ud(c).join(", ")}) matches the requested API range ${g}. Installed images: ${R}. `;if(D<d.min||d.max!==void 0&&D>d.max)return T+`No ${C} system image is available in the requested API range: the known image is API ${D} (${Da[c]}). Widen minOsVersion/maxOsVersion to include API ${D}, then retry. 'sdkmanager --list --channel=3' shows the XR API levels published.`;return T+`AutoMobile does not download system images. Install one with 'sdkmanager --channel=3 --install "system-images;android-${D};${Da[c]};${A}"', then retry. XR images are published on the canary channel: 'sdkmanager --list --channel=3' shows the API levels and ABIs available.`}function xa(c,d){let g=Ud("watch");return{kind:"watch",accepts:(R)=>g.includes(R),rank:(R)=>g.indexOf(R),deviceProfile:Vf({profileId:d})==="watch"?d?.trim():jl("watch",c),namePrefix:"android-watch"}}function ka(c,d,g){let R=Ud("watch");return`No installed Wear OS system image (${R.join(", ")}) matches the requested API range ${c} and host ABIs ${g.join(" or ")}. Installed images: ${d}. AutoMobile does not download system images. Install one with 'sdkmanager "system-images;android-<api>;${R[0]};${g[0]}"', then retry.`}function Oa(c,d=B){let g=c.replace(/[^A-Za-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"device",R=d.next().replace(/-/g,"").slice(0,8);return`${ba}-${g}-${R}`}var Oi={phone:"iPhone",tablet:"iPad"};function Ba(c){switch(c){case void 0:case"phone":return"phone";case"tablet":return"tablet";case"foldable":case"tv":case"watch":case"automotive":case"xr-headset":case"xr-glasses":case"unknown":throw new t(`iOS provisioning supports only phone or tablet form factors, not '${c}'.`)}}function Ha(c,d="phone"){if(d==="phone"&&ys(c.identifier))return!1;let g=Oi[d];return c.productFamily===g||c.name.startsWith(g)}function Ma(c){let d=c.match(/\d+/g);if(!d)return-1;return d.reduce((g,R)=>Math.max(g,Number.parseInt(R,10)),-1)}function nm(c,d){if(c.length===0)throw new t("No iOS simulator device types are available from 'xcrun simctl list devicetypes'. Install an iOS platform via Xcode > Settings > Components.");let g=Ba(d.formFactor);if(d.name){let C=d.name.trim().toLowerCase(),D=c.find((T)=>T.name.toLowerCase()===C);if(D)return D}let R=Oi[g],A=c.filter((C)=>Ha(C,g));if(A.length===0)throw new t(`No ${R} simulator device type is available. Available device types: ${c.map((C)=>C.name).join(", ")}.`);return[...A].sort((C,D)=>{let T=Ma(D.name)-Ma(C.name);if(T!==0)return T;let k=C.name.length-D.name.length;if(k!==0)return k;return C.name.localeCompare(D.name)})[0]}function om(c,d){let{status:g}=Rc(c,d);return g==="supported"||g==="unknown"&&!WC(c)}function sm(c,d,g,R){let A=R?Oi[g]:"iOS";return new t(`No installed ${A} simulator device type supports the matching runtime(s) ${d.join(", ")}. Available device types: ${c.map((C)=>C.name).join(", ")}.`)}async function Mi(c,d,g){let R=Ba(d.formFactor),A=await c.getDeviceTypes(g);if(A.length===0)throw new t("No iOS simulator device types are available from 'xcrun simctl list devicetypes'. Install an iOS platform via Xcode > Settings > Components.");let C=await c.resolveRuntimeIdentifiersForBounds(d.minOsVersion,d.maxOsVersion,g),D=d.name?.trim().toLowerCase(),T=D?A.find((F)=>F.name.toLowerCase()===D):void 0,k=[],M=0;for(let F of C){let V=zv(F);if(!V)throw new t(`Cannot determine the iOS version from resolved runtime '${F}'.`);k.push(V);let W=A.filter((G)=>om(G,V));if(M+=W.length,T){if(W.includes(T))return{deviceType:T,runtime:F};continue}if(W.some((G)=>Ha(G,R)))return{deviceType:nm(W,{...d,formFactor:R}),runtime:F}}if(T)throw new t(`Requested iOS device type '${T.name}' does not support runtime ${k.join(", ")}. Choose a compatible device type or adjust the requested OS range.`);throw sm(A,k,R,M>0)}var xi=["google_apis","default","google_apis_playstore"],am=new Set([...xi,"google_apis_ps16k","google_apis_playstore_ps16k","google_apis_tablet","google_apis_playstore_tablet","google_atd","aosp_atd"]);function cm(c){let d=xi.indexOf(c);return d===-1?xi.length:d}var Va={kind:"handheld",accepts:(c)=>am.has(c),rank:cm,namePrefix:"android"},Tt=Ud("tv"),Ua={kind:"tv",accepts:(c)=>Tt.includes(c),rank:(c)=>Tt.indexOf(c),deviceProfile:jl("tv"),namePrefix:"android-tv"},ki=Ud("automotive"),$a={kind:"automotive",accepts:(c)=>ki.includes(c),rank:(c)=>ki.indexOf(c),deviceProfile:jl("automotive"),namePrefix:"android-automotive"};function Wa(c,d,g){if(c==="tv")return Ua;if(c==="automotive")return $a;if(c==="xr-headset"||c==="xr-glasses")return Ti[c];if(c==="watch")return xa(d?.screenRound,g);return Va}var dm=36,Ga=34;function Nw(c){return c==="arm64"?["arm64-v8a","x86_64"]:["x86_64","x86"]}function _a(c,d){let g=d.indexOf(c);return g===-1?d.length:g}var lm=/^\d+(?:\.\d+)*[A-Za-z]?$/;function um(c){let d=/^(\d+)/.exec(c);return d?Number(d[1]):void 0}function Na(c,d){if(!c)return;let g=c.trim(),R=fz(g);if(R!==void 0)return e.debug(`[DeviceProvisioner] Treating ${d}OsVersion '${g}' as an API level`),R;let A=Lre(g);if(A)return d==="min"?A.min:A.max;if(!lm.test(g)){let C=um(g);if(C!==void 0)return e.debug(`[DeviceProvisioner] ${d}OsVersion '${g}' carries a qualifier the release table doesn't parse; falling back to its leading major ${C} as an API level (pre-#6132 lenient behavior; full qualifier ordering is tracked in #6182).`),C}throw new t(`Unrecognized Android ${d}OsVersion '${c}'. Pass a release version such as '14' (Android 14) or an API level such as 34.`)}function xt(c,d){if(c===void 0||d===void 0)return"any";return c.trim()===String(d)?c:`${c} (API ${d})`}function yt(c){let{criteria:d,requestedMin:g,min:R,max:A}=c;return`(min=${g!==void 0&&g>=Gv?xt(d.minOsVersion,R):`API ${Gv} (CtrlProxy runner minSdk)`}, max=${xt(d.maxOsVersion,A)})`}function Qe(c){return c.map((d)=>d.packageName).join(", ")||"none"}function pm(c,d,g){if(d.length===0)throw new t(`No installed Android system image matches the requested API range ${yt(g)}. Installed images: ${Qe(c)}. Install one with 'sdkmanager "system-images;android-<api>;google_apis;<abi>"'.`);let R=d.filter((A)=>Va.accepts(A.tag));if(R.length===0){let{criteria:A,min:C,max:D}=g;throw new t(`No installed handheld (phone) Android system image matches the requested API range (min=${xt(A.minOsVersion,C)}, max=${xt(A.maxOsVersion,D)}). Only non-handheld images (Wear OS, TV, Automotive, XR or similar) are installed in that range: ${Qe(d)}. Default provisioning never creates an AVD from them. Install a phone image with 'sdkmanager "system-images;android-<api>;google_apis;<abi>"'.`)}return R}var mm={handheld:"google_apis_playstore",tv:"google-tv",automotive:"android-automotive-playstore","xr-headset":"android-xr-v3-playstore"};function fm(c,d){let g=c.filter((R)=>Xw(R.tag));if(g.length===0){let R=mm[d.kind],A=R===void 0?`No Google Play ${d.kind} image is known; remove requires.playStore for this form factor. `:`Install one with 'sdkmanager "system-images;android-<api>;${R};<abi>"'. `;throw new t(`requires.playStore needs a Google Play system image, and none is installed for this request: ${Qe(c)}. `+A+"Play Store images refuse adb root, so root-dependent features will report that they need a non-Play image.")}return g}function hm(c,d,g,R){let A=c.filter((T)=>nY(T.tag));if(A.length>0)return A;let C=Math.min(Math.max(g.min,Ga),g.max??Number.POSITIVE_INFINITY),D=Nw(R);throw new t(`requires.vehicle.motion needs a non-Play Android Automotive system image (android-automotive), and none is installed in the requested API range ${yt(g)}: ${Qe(d)}. Play Store car images are user builds that refuse driving-state simulation. AutoMobile does not download system images. Install one with 'sdkmanager "system-images;android-${C};android-automotive;${D[0]}"', then retry.`)}function _i(c){return`AutoMobile does not download system images. Install one with 'sdkmanager "${c}"'`}function vm(c,d,g,R){let A=d.filter((T)=>Ua.accepts(T.tag));if(A.length>0)return A;let C=g.max??Math.max(g.min,dm),D=Nw(R);throw new t(`No installed Android TV system image (${Tt.join(", ")}) matches the requested API range ${yt(g)}. Installed images: ${Qe(c)}. `+_i(`system-images;android-${C};android-tv;${D[0]}`)+` (or google-tv in place of android-tv), then retry. This host runs ${D.join(" or ")} images; 'sdkmanager --list' shows the ABIs published for each API level.`)}function ym(c,d,g,R){let A=d.filter((T)=>$a.accepts(T.tag));if(A.length>0)return A;let C=Math.min(Math.max(g.min,Ga),g.max??Number.POSITIVE_INFINITY),D=Nw(R);throw new t(`No installed Android Automotive system image (${ki.join(", ")}) matches the requested API range ${yt(g)}. Installed images: ${Qe(c)}. AutoMobile does not download system images. Install one with 'sdkmanager "system-images;android-${C};android-automotive;${D[0]}"', then retry. This host runs ${D.join(" or ")} images; 'sdkmanager --list' shows the ABIs published for each API level.`)}function gm(c,{images:d,inRange:g,bounds:R,architecture:A}){let C=g.filter((M)=>Ti[c].accepts(M.tag));if(C.length>0)return C;let[D]=Nw(A),[T,k]=[yt(R),Qe(d)];throw new t(Ta(c,{bounds:R,range:T,installed:k,abi:D}))}function bm(c,d){let{images:g,inRange:R,bounds:A,architecture:C}=d;switch(c.kind){case"watch":{let D=Nw(C),T=R.filter((k)=>c.accepts(k.tag)&&D.includes(k.abi));if(T.length>0)return T;throw new t(ka(yt(A),Qe(g),D))}case"tv":return vm(g,R,A,C);case"automotive":return ym(g,R,A,C);case"xr-headset":case"xr-glasses":return gm(c.kind,d);case"handheld":return pm(g,R,A)}}function Sm(c,d,g){let R=Wa(d.formFactor,d.requires),A=Na(d.minOsVersion,"min"),C=Na(d.maxOsVersion,"max");if(C!==void 0&&C<Gv)throw new t(`Requested Android maxOsVersion ${xt(d.maxOsVersion,C)} is below API ${Gv}, the minimum SDK the AutoMobile CtrlProxy runner APK supports. A lower AVD would boot but never install the runner and become automation-ready. Request Android 7.0 (API 24) or newer.`);let D=Math.max(A??Gv,Gv),T=c.filter((X)=>{if(X.apiLevel<D)return!1;if(C!==void 0&&X.apiLevel>C)return!1;return!0}),k={criteria:d,requestedMin:A,min:D,max:C},M=bm(R,{images:c,inRange:T,bounds:k,architecture:g}),F=Nw(g),V=d.requires?.playStore?fm(M,R):M,W=d.requires?.vehicle?.motion==="supported"?hm(V,c,k,g):V,G=W.filter((X)=>F.includes(X.abi));return[...G.length>0?G:W].sort((X,J)=>{let Z=J.apiLevel-X.apiLevel;if(Z!==0)return Z;let ee=_a(X.abi,F)-_a(J.abi,F);if(ee!==0)return ee;let ne=R.rank(X.tag)-R.rank(J.tag);if(ne!==0)return ne;let de=Us(J.apiIdentifier,X.apiIdentifier);if(de!==0)return de;let te=(J.extensionLevel??0)-(X.extensionLevel??0);if(te!==0)return te;return X.packageName.localeCompare(J.packageName)})[0]}function wm(c,d){let g=c?.trim();return g&&g.toLowerCase()!==d.toLowerCase()?g:d}class ur{dependencies;idGenerator;architecture;constructor(c){this.dependencies=c;this.idGenerator=c.idGenerator??B,this.architecture=c.architecture??process.arch}async provision(c,d,g=this.dependencies.identityHooks){if(c.platform==="ios")return this.provisionIos(c,d,g);if(c.platform==="android")return this.provisionAndroid(c,d,g);throw new t(`Device creation requires an explicit platform; got '${c.platform}'.`)}async provisionIos(c,d,g){let R=this.dependencies.iosCreator();if(!R)throw new t("Cannot create an iOS simulator: iOS simulator tools (xcrun simctl) are not available.");let{deviceType:A,runtime:C}=await Mi(R,c,d),D=wm(c.name,A.name),T=this.dependencies.createdDeviceName?.(D)??Oa(D,this.idGenerator),k=await g?.reserveBeforeCreate({platform:"ios",name:T,deviceType:A.identifier,runtimeId:C,runtime:C}),M=d&&k?AbortSignal.any([d,k]):d??k,F;try{F=this.dependencies.simulatorCreation?(await this.dependencies.simulatorCreation.create({name:T,deviceType:A.identifier,runtime:C,signal:M})).udid:await R.createSimulator(T,A.identifier,C,M)}catch(W){throw u(W,`Failed to create iOS simulator '${T}' (deviceType=${A.identifier}, runtime=${C})`)}let V={platform:"ios",name:T,deviceId:F,deviceType:A.identifier,runtimeId:C,runtime:C};return e.info(`[DeviceProvisioner] Created iOS simulator '${T}' (udid=${F}, deviceType=${A.identifier}, runtime=${C}). Delete it with 'xcrun simctl delete `+F+"' when no longer needed."),await g?.bindAfterCreate(V),this.applyPrebootProfile(F,V,M)}async applyPrebootProfile(c,d,g){let R=await this.dependencies.prebootProfile?.apply(c,{},g);return{...d,...R?.applied&&R.resources.length?{prebootDisabledResources:R.resources}:{}}}async provisionAndroid(c,d,g){let R=Wa(c.formFactor,c.requires,c.name),A=this.dependencies.androidCreator(),C;try{C=await A.listInstalledSystemImages(d)}catch(W){throw u(W,"Failed to list installed Android system images for AVD creation")}let D=Sm(C,c,this.architecture),T=Oa(c.name??`${R.namePrefix}-${D.apiLevel}`,this.idGenerator),k=await g?.reserveBeforeCreate({platform:"android",name:T,deviceType:R.deviceProfile,runtimeId:D.packageName,runtime:`android-${D.apiIdentifier}`}),M=d&&k?AbortSignal.any([d,k]):d??k,F=await A.createAvd({name:T,package:D.packageName,...R.deviceProfile?{device:R.deviceProfile}:{}},M);if(!F.success)throw new ng(`Failed to create Android AVD '${T}' from ${D.packageName}: ${F.message}`);let V=await this.androidCreatedDevice(T,D,R.deviceProfile);return e.info(`[DeviceProvisioner] Created Android AVD '${T}' (systemImage=${D.packageName}, api=${D.apiIdentifier}, tag=${D.tag}, abi=${D.abi}${R.deviceProfile?`, device=${R.deviceProfile}`:""}). Delete it with 'avdmanager delete avd -n ${T}' when no longer needed.`),await g?.bindAfterCreate(V),V}async androidCreatedDevice(c,d,g){let R={platform:"android",name:c,isRunning:!1,deviceType:g,runtimeId:d.packageName},A=this.dependencies.androidConfigReader?(await sO(this.dependencies.androidConfigReader,[R]))[0]:void 0;return{...A?{configuredImage:A}:{},platform:"android",name:c,deviceType:A?.deviceType??g,runtimeId:d.packageName,runtime:`android-${d.apiIdentifier}`}}}function Fi(){return{listInstalledSystemImages:(c)=>Hu(void 0,void 0,c),createAvd:(c,d)=>aO(c,void 0,d)}}function Fw(c=()=>new L(null),d,g){return new ur({iosCreator:c,simulatorCreation:g,prebootProfile:new Ng,androidCreator:Fi,androidConfigReader:new Nr,identityHooks:d})}class pr{run(c,d,g){return d()}}var Rm="AutoMobile CI iPhone";class za{dependencies;constructor(c){this.dependencies=c}async run(c,d,g){if(!this.isOwnedTarget(c))return d();let R;try{return await d()}catch(A){if(g?.aborted||A instanceof $n)throw A;R=A}this.throwIfCancelled(g);try{await this.recover(g,()=>this.dependencies.shutdown(c),!0)}catch(A){if(A instanceof hk)throw e.warn("[CI iOS boot] simulator shutdown remains pending; skipping erase and boot retry",A),R;throw A}this.throwIfCancelled(g),await this.recover(g,()=>this.dependencies.erase(c.deviceId)),this.throwIfCancelled(g);try{return await d()}catch{throw this.throwIfCancelled(g),R}}isOwnedTarget(c){return c.platform==="ios"&&c.name===this.dependencies.ownedSimulatorName&&Boolean(c.deviceId)}throwIfCancelled(c){if(c?.aborted)throw new t("startDevice cancelled while recovering the CI iOS simulator")}async recover(c,d,g=!1){let R=Promise.resolve().then(d).catch((A)=>{if(g&&A instanceof hk)throw A;e.debug(`[CI iOS boot] recovery command failed: ${A}`)});if(!c){await R;return}this.throwIfCancelled(c);try{await l(R,{timer:i,signal:c,label:"CI iOS simulator recovery"})}catch(A){if(c.aborted)throw new t("startDevice cancelled while recovering the CI iOS simulator");throw A}}}function Am(c){return I(Y.CI,c)==="true"&&I(Y.GITHUB_ACTIONS,c)==="true"}function Pm(c,d){return c.platform==="ios"&&!c.name&&!c.deviceId&&Am(d)}function Im(c,d){return{...c,name:d,matchNamedDeviceIgnoringOsVersion:!0}}async function Ote(c,d=process.env,g){if(!Pm(c,d))return;let R=g?.simctl??new L,{runtime:A}=await Mi(R,c),C=zv(A)??A,D=`${Rm} (${C})`,T=new Xn(null,R);return{request:Im(c,D),deviceManager:T,deviceProvisioner:new ur({iosCreator:()=>R,androidCreator:Fi,createdDeviceName:()=>D}),recovery:new za({ownedSimulatorName:D,shutdown:async(k)=>{await T.killDevice({name:k.name,platform:"ios",deviceId:k.deviceId})},erase:(k)=>R.eraseSimulator(k)})}}class gt extends t{avdName;candidateSerials;code="identity_conflict";constructor(c,d){super(`identity_conflict: Android AVD '${c}' is claimed by multiple running emulators: ${d.join(", ")}. Pass an explicit deviceId (ADB serial) to select one.`);this.avdName=c;this.candidateSerials=d}}var Bi=5000;function qa(c){return c.name!==void 0&&c.matchExactName!==!0||c.minOsVersion!==void 0||c.maxOsVersion!==void 0||c.formFactor!==void 0||c.requires!==void 0||c.screenSize!==void 0}function Li(c,d){if(d.platform!=="android")return;if(c.platform!==d.platform||c.name!==d.name)throw new t(`target_identity_mismatch: Configured ${d.platform} image '${d.name}' (${d.deviceId??"no runtime ID"}) resolved to '${c.name}' (${c.deviceId}). Retry after device discovery refreshes.`)}function Xa(c,d){if(c.name!==void 0&&c.matchExactName!==!0)cr([d],c.name)}function Ya(c,d){if(c.matchExactName&&c.name&&c.platform==="android")cr(d,c.name)}function Ja(c,d){if(c.matchExactName&&c.name&&d.name!==c.name)throw new t(`target_identity_mismatch: Requested ${c.platform} device '${c.name}' resolved to '${d.name}' (${d.deviceId}).`)}function ot(c,d){let g=new Map(c.filter((A)=>!A.foreignOwned&&A.platform==="android"&&A.name===d&&ae(A.deviceId)).map((A)=>[A.deviceId,A])),R=[...g.values()];if(R.length>1)throw new gt(d,[...g.keys()].toSorted());return R[0]}var Et=new WeakMap;function R3(c=Gs()){return{listInFlightAndroidColdBootAvdNames:()=>[...Et.get(c)?.keys()??[]]}}function ja(c,d,g){try{c?.(d,g)}catch(R){e.warn(`[DeviceBootService] Android cold-boot tracking listener failed: ${r(R)}`,R)}}function Cm(c,d,g){let R=Et.get(c)??new Map;Et.set(c,R);let A=R.get(d)??0;if(R.set(d,A+1),A===0)ja(g,d,"claimed");return()=>{let C=(R.get(d)??1)-1;if(C>0){R.set(d,C);return}if(R.delete(d),R.size===0)Et.delete(c);ja(g,d,"released")}}function fr(c,d){return(Et.get(c)?.get(d)??0)>0}function Hi(c,d,g){return d.platform==="android"?Cm(c,d.name,g):void 0}function hr(c,d){if(c.platform==="android")return ot(d,c.name);return c.deviceId?d.find((g)=>g.deviceId===c.deviceId):void 0}function Qa(c,d,g,R){let A=c==="android"?ot(d,g):d.find((C)=>C.name===g);return A&&Iu(A,R)?A:null}function Za(c,d,g,R){return new t(`No ${c.platform} device matching criteria found. ${c.minOsVersion?`minOsVersion>=${c.minOsVersion} `:""}${c.maxOsVersion?`maxOsVersion<=${c.maxOsVersion} `:""}${c.name?`name=${c.name} `:""}${wg(d,R)} Available images: ${g.map((A)=>`${A.name}${A.osVersion?` (v${A.osVersion})`:""}`).join(", ")||"none"}.`)}function vr(c,d){return{..."configuredImage"in c?c.configuredImage:{},name:c.name,platform:c.platform,deviceId:"deviceId"in c?c.deviceId:void 0,isRunning:!1,formFactor:d.formFactor,runtimeId:c.runtimeId,runtime:c.runtime,deviceType:c.deviceType}}function Vi(c,d){let g=new Map(d.filter((A)=>A.deviceId).map((A)=>[A.deviceId,A])),R=new Map(d.map((A)=>[A.name,A]));return c.map((A)=>{let C=A.platform==="android"&&ae(A.deviceId),D=(A.deviceId?g.get(A.deviceId):void 0)??(C?R.get(A.name):void 0);return D?.platform===A.platform?Te(A,D):A})}function br(c,d,g){return d?.has(c.name)===!0||c.deviceId!==void 0&&g?.has(c.deviceId)===!0}async function ec(c,d,g){let A=(await c.execution.discoverBootedDevices(re(d.platform,"Starting a device"),g,"revalidating the running device after lifecycle wait",{bypassAndroidCache:d.platform==="android"})).find((C)=>C.deviceId===d.deviceId);if(!A)throw new t("Selected running device disappeared during lifecycle wait; retry device selection");return{platform:A.platform,stableId:A.platform==="android"?A.name:A.deviceId}}async function tc(c,d,g){let R=await c.execution.runPhase(g,"revalidating the device image after lifecycle wait",(k)=>c.dependencies.deviceManager.listDeviceImages(d.platform,k)),A=g.request,C={platform:A.platform,name:A.name,minOsVersion:A.matchNamedDeviceIgnoringOsVersion?void 0:A.minOsVersion,maxOsVersion:A.matchNamedDeviceIgnoringOsVersion?void 0:A.maxOsVersion,formFactor:A.formFactor,requires:A.requires,screenSize:A.screenSize},D=R.filter((k)=>!br(k,A.excludeDeviceNames,A.excludeDeviceIds)&&Iu(k,C)),T=A.deviceId?D.find((k)=>k.deviceId===A.deviceId||k.name===A.deviceId):A.matchExactName&&A.name?D.find((k)=>k.name===A.name):c.dependencies.deviceMatcher.matchDeviceImage(C,D,c.dependencies.matchingStrategy);if(!T)throw new t("Selected device image disappeared during lifecycle wait; retry device selection");return{platform:T.platform,stableId:T.platform==="android"?T.name:T.deviceId}}async function rc(c,d,g,R=!0){if(d.platform==="android"){let T=await c.execution.discoverBootedDevices(d.platform,g,"re-checking the running device after the shared lifecycle lease settled",{bypassAndroidCache:!0,awaitAbortSettlement:!0}),k=ot(T,d.name);return k&&!fr(c.lifecycleCoordinator,d.name)?k:void 0}let C=(T)=>c.dependencies.deviceManager.getBootedDevicesDetailed(d.platform,{bypassIosDeviceListCache:!0,skipPhysicalIosDiscovery:!0,signal:T}),D=await c.execution.runPhase(g,"re-checking the running device after the shared lifecycle lease settled",(T)=>R?$i(c,"re-checking the running device after the shared lifecycle lease settled",T,C):C(T));return D?.succeededPlatforms.has("ios")?hr(d,D.devices):void 0}async function $i(c,d,g,R){let A=new AbortController,C=Error(`${d} timed out`);try{return await l(R(AbortSignal.any([g,A.signal])),{timer:c.timer,timeoutMs:Bi,signal:g,label:d,timeoutError:()=>C,onTimeout:()=>A.abort(C)})}catch(D){if(D!==C)throw D;e.warn(`[startDevice] Simulator re-check did not answer within ${Bi}ms; continuing to the boot path`);return}}import{promises as ic}from"fs";import{homedir as Dm}from"os";import{join as Tm}from"path";function xm(){return{readFile:(c,d)=>ic.readFile(c,d),writeFile:(c,d,g)=>ic.writeFile(c,d,g),environment:process.env,homeDirectory:Dm}}function km(c){return c?.signal}class Sr{dependencies;constructor(c=xm()){this.dependencies=c}async setMemoryMb(c,d,g){if(!Number.isInteger(d)||d<=0)throw new Ue("platform_command_failed",`Android AVD memoryMb must be a positive integer; got ${d}.`);return this.setConfiguration(c,{memoryMb:d},g)}async setConfiguration(c,d,g){let R=km(g);o(R);let A=QT.parse(d),C=new Map;for(let W of Object.keys(A)){let G=A[W];if(G!==void 0)C.set(lz[W],typeof G==="boolean"?G?"yes":"no":String(G))}if(A.gpuMode!==void 0)C.set("hw.gpu.enabled","yes");let D=rY(this.dependencies.environment,this.dependencies.homeDirectory()),T=Tm(D,`${c}.avd`,"config.ini"),k=await P(this.dependencies.readFile(T,"utf8"),R);o(R);let M=k.split(/\r?\n/),F=new Set,V=M.map((W)=>{let G=W.slice(0,W.indexOf("=")).trim();if(C.has(G))return F.add(G),`${G}=${C.get(G)}`;return W});for(let[W,G]of C){if(F.has(W))continue;if(V.at(-1)!=="")V.push("");V.push(`${W}=${G}`,"")}o(R),await this.dependencies.writeFile(T,V.join(`
|
|
5
|
+
`),"utf8")}}function Em(c,d){let g=nn(c.runtime);if(!g||!d)return!1;return d.apiLevel===g.apiLevel&&d.tag===g.tag&&d.architecture===g.architecture&&d.deviceName===c.deviceType&&d.systemImagePackage===g.systemImagePackage}function AW(c,d){return Em(c,d)&&(c.configuration?.memoryMb===void 0||d?.ramSizeMb===c.configuration.memoryMb)&&Object.entries(c.configuration??{}).every(([g,R])=>g==="memoryMb"||R===void 0||(g!=="gpuMode"||d?.gpuEnabled===!0)&&d?.hardware?.[g]===R)}function TW(c,d){if(d.isAvailable===!1)return"unavailable";if(d.runtime!==c.runtime||d.deviceType!==c.deviceType)return"mismatch";return}function kW(c,d){let g=Ow(c,d.deviceType),R=d.displayCutout;if(R===void 0||R==="any")return{kind:"resolved",displayCutout:g};if(g==="unknown")return{kind:"unsupported",message:`Display cutout preference '${R}' is unsupported for ${c} device type '${d.deviceType}' because its cutout class is unknown.`};if(g!==R)return{kind:"identity_conflict",message:`Exact ${c} device type '${d.deviceType}' has display cutout '${g}', not requested '${R}'.`};return{kind:"resolved",displayCutout:g}}function EW(c,d,g){let R=d.find((T)=>T.identifier===c.runtime),A=g.find((T)=>T.identifier===c.deviceType);if(!R||!A)return;let C=Rc(A,R.version),D=!R.isAvailable;if(!D&&C.status!=="unsupported")return;return{unavailable:D,runtime:R,bounds:C.bounds,compatibleRuntimes:d.filter((T)=>T.isAvailable&&Rc(A,T.version).status==="supported").map((T)=>({id:T.identifier,version:T.version}))}}function P3(c,d){return new Ue("device_assigned_to_binding",`${d}: ${c.message}`,!1,{deviceId:c.deviceId,binding:{scopeKey:c.scopeKey,declaredBinding:c.declaredBinding,stableId:c.stableId}})}class nc{dependencies;async configureAndroid(c,d,g){let R=this.dependencies.androidConfigWriter;if(R.setConfiguration)await R.setConfiguration(c,d,{signal:g});else if(Object.keys(d).some((A)=>A!=="memoryMb"))throw new Ue("unsupported","The configured AVD writer does not support emulator hardware controls.");else if(d.memoryMb!==void 0)await R.setMemoryMb(c,d.memoryMb,{signal:g})}lifecycleCoordinator;timer;constructor(c){this.dependencies=c;this.lifecycleCoordinator=c.lifecycleCoordinator??Gs(),this.timer=c.timer??i}async provision(c){let d=this.resolveDisplayCutout(c),g=c.lifecycleLease===void 0,R=c.lifecycleLease??await this.lifecycleCoordinator.reserve(this.initialLifecycleIdentity(c),{operation:"provision",deadlineMs:c.deadlineMs??this.timer.now()+300000,signal:c.signal}),A=[c.signal,R.signal].filter((D)=>D!==void 0),C={...c,signal:A.length===1?A[0]:AbortSignal.any(A)};try{o(C.signal);let D=await this.provisionLocked(C,d),T=D.device.platform==="android"?D.device.name:D.device.deviceId;if(!T)throw new Ue("identity_conflict",`Exact iOS simulator '${c.name}' has no UDID.`);return await R.bindCanonicalIdentity({platform:D.device.platform,stableId:T},async()=>{let M=(await this.dependencies.listDeviceImages(D.device.platform)).find((F)=>F.platform===D.device.platform&&(D.device.platform==="android"?F.name===c.name:F.deviceId===T));if(!M)throw new t(`Provisioned device '${T}' disappeared during lifecycle wait`);return{platform:M.platform,stableId:M.platform==="android"?M.name:M.deviceId}}),D}finally{if(g)R.release()}}async assertAdoptable(c,d){let g=d.platform==="android"?d.name:d.deviceId;if(!this.dependencies.assertAdoptable||!g)return;try{await this.dependencies.assertAdoptable({platform:re(d.platform,"Adopting an existing device"),stableId:g})}catch(R){if(R instanceof oi)throw P3(R,`Cannot adopt existing ${c.platform} device '${c.name}'`);throw R}}initialLifecycleIdentity(c){if(c.platform==="android"||c.deviceId)return{kind:"stable",platform:c.platform,stableId:c.platform==="android"?c.name:c.deviceId};return{kind:"selector",platform:"ios",selector:c.name}}async provisionLocked(c,d){let g=await rr("provision:listDeviceImages",()=>this.dependencies.listDeviceImages(c.platform)),R=this.findExisting(g,c);if(R)return await this.assertAdoptable(c,R),await rr("provision:matchExisting",()=>this.assertExistingMatches(c,R)),{device:R,created:!1,resolvedSpec:this.withResolvedDisplayCutout(c.spec,d)};if(c.platform==="ios"&&c.deviceId!==void 0)throw new Ue("identity_conflict",`Exact iOS simulator '${c.name}' with UDID '${c.deviceId}' was not found.`);if(!this.dependencies.isCreationAllowed(!0))throw new Ue("creation_not_allowed",`Device creation is disabled; cannot provision exact ${c.platform} device '${c.name}'.`);if(c.platform==="android")await this.assertAndroidTvImageInstalled(c,c.spec);else await this.assertIosPairCompatible(c,c.spec);if(await c.assertCapacityBeforeCreate?.(c.signal),c.onBeforeCreate?.(),c.platform==="android")return await rr("provision:createAndroid",()=>this.createAndroid(c,c.spec,d));return await rr("provision:createIos",()=>this.createIos(c,c.spec,d))}async readIosCompatibilityCatalog(c,d){try{let[g,R]=await Promise.all([c.getRuntimesChecked(void 0,d),c.getDeviceTypesChecked(d)]);return{runtimes:g,deviceTypes:R}}catch(g){o(d),e.warn(`iOS runtime compatibility check skipped: ${r(g)}`,g);return}}async assertIosPairCompatible(c,d){let g=this.dependencies.iosRuntimeCatalog;if(!g)return;let R=await this.readIosCompatibilityCatalog(g,c.signal);if(!R)return;let A=EW(d,R.runtimes,R.deviceTypes);if(!A)return;let{runtime:C,bounds:D,compatibleRuntimes:T,unavailable:k}=A;throw Mm(c,d,{reason:k?`Runtime '${d.runtime}' is not available (${C.availabilityError??"CoreSimulator marked it unavailable"}), so iOS simulator '${c.name}' with device type '${d.deviceType}' cannot be created.`:`Device type '${d.deviceType}' does not support runtime '${d.runtime}' (version ${C.version}; supported ${Om(D)}), so iOS simulator '${c.name}' was not created.`,bounds:D,compatibleRuntimes:T})}resolveDisplayCutout(c){let d=kW(c.platform,c.spec);if(d.kind!=="resolved")throw new Ue(d.kind,d.message);return d.displayCutout}withResolvedDisplayCutout(c,d){return{...c,displayCutout:d}}findExisting(c,d){if(d.platform!=="ios")return c.find((A)=>A.name===d.name||d.deviceId!==void 0&&A.deviceId===d.deviceId);if(d.deviceId!==void 0)return c.find((A)=>A.deviceId===d.deviceId);let g=c.filter((A)=>A.name===d.name),R=d.spec;return g.find((A)=>A.isAvailable!==!1&&A.runtime===R.runtime&&A.deviceType===R.deviceType)??g.find((A)=>A.runtime===R.runtime&&A.deviceType===R.deviceType)??g[0]}async assertExistingMatches(c,d){if(d.platform!==c.platform)throw new Ue("identity_conflict",`Requested ${c.platform} device '${c.name}' conflicts with existing ${d.platform} device.`);if(d.name!==c.name)throw new Ue("identity_conflict",`Requested device name '${c.name}' conflicts with existing '${d.name}' for the supplied identity.`);if(c.platform==="android"){await this.assertAndroidExistingMatches(c,d);return}this.assertIosExistingMatches(c,d)}async assertAndroidExistingMatches(c,d){let g=c.spec,R=await this.dependencies.androidConfigReader.readConfig(d.name);if(AW(g,R))return;throw new Ue("identity_conflict",`Existing Android AVD '${d.name}' does not match the requested runtime, device type, and configuration.`)}assertIosExistingMatches(c,d){let g=c.spec,R=TW(g,d);if(R==="unavailable")throw new Ue("identity_conflict",`Existing iOS simulator '${d.name}' is unavailable: ${d.availabilityError??"CoreSimulator marked it unavailable"}.`);if(R==="mismatch")throw new Ue("identity_conflict",`Existing iOS simulator '${d.name}' does not match the requested runtime and device type.`)}async assertAndroidTvImageInstalled(c,d){let g=nn(d.runtime);if(g&&Tt.includes(g.tag)){let R;try{R=await this.dependencies.avdManager.listInstalledSystemImages(c.signal)}catch(A){throw u(A,"Failed to list installed Android system images for AVD creation")}if(!R.some((A)=>A.packageName===d.runtime))throw new t(`No installed Android TV system image matches the requested package '${d.runtime}'. `+_i(d.runtime)+", then retry.")}}async createAndroid(c,d,g){let R;try{R=await this.dependencies.avdManager.createAvd({name:c.name,package:d.runtime,device:d.deviceType},{signal:c.signal})}catch(A){throw Rf(),A}if(!R.success)throw new ng(`Failed to create Android AVD '${c.name}': ${R.message}`);if(Rf(),d.configuration)await this.configureAndroid(c.name,d.configuration,c.signal);return{created:!0,device:(await sO(this.dependencies.androidConfigReader,[{name:c.name,platform:"android",isRunning:!1,deviceType:d.deviceType,runtimeId:d.runtime}]))[0],resolvedSpec:this.withResolvedDisplayCutout(d,g)}}async createIos(c,d,g){let R=this.dependencies.simulatorCreation?(await this.dependencies.simulatorCreation.create({name:c.name,deviceType:d.deviceType,runtime:d.runtime,resources:c.resources,signal:c.signal})).udid:await this.dependencies.iosSimulator.createSimulator(c.name,d.deviceType,d.runtime,c.signal),A=await this.dependencies.prebootProfile?.apply(R,{resources:c.resources},c.signal);return{...A?.applied&&A.resources.length?{prebootDisabledResources:A.resources}:{},created:!0,device:{name:c.name,platform:"ios",deviceId:R,isRunning:!1,runtime:d.runtime,deviceType:d.deviceType},resolvedSpec:this.withResolvedDisplayCutout(d,g)}}}function Om(c){return c?`${c.minVersion} to ${c.maxVersion??"no maximum"}`:"unknown bounds"}function Mm(c,d,g){let R=g.compatibleRuntimes.length?g.compatibleRuntimes.map((A)=>A.id).join(", "):"none installed";return new Ue("runtime_incompatible",`${g.reason} Compatible installed runtimes: ${R}.`,void 0,{runtimeCompatibility:{requestedRuntime:d.runtime,requestedDeviceType:d.deviceType,...g.bounds?{bounds:g.bounds}:{},compatibleRuntimes:g.compatibleRuntimes}})}function Mte(c,d,{androidConfigWriter:g=new Sr,assertAdoptable:R,simulatorCreation:A,ios:C}={}){let D=new Xk;return new nc({assertAdoptable:R,listDeviceImages:c.listDeviceImages.bind(c),isCreationAllowed:d.isCreationAllowed.bind(d),avdManager:{listInstalledSystemImages:(T)=>Hu(void 0,void 0,T),createAvd:(T,k)=>D.createAvd(T,k)},androidConfigReader:new Nr,androidConfigWriter:g,simulatorCreation:A,prebootProfile:new Ng,iosSimulator:new L(null),iosRuntimeCatalog:new L(null),...C})}class NT extends It{constructor(c){super(`target_identity_unresolved: Android emulator '${c}' is listed by adb but did not answer its AVD-name probe, so it cannot be resolved for lifecycle coordination. Retry once it responds; if it stays unresponsive, call killDevice for it and then startDevice.`,[c])}}class Lw{dependencies;execution;bootRecovery;timer;lifecycleCoordinator;constructor(c){this.dependencies=c;this.bootRecovery=c.bootRecovery??new pr,this.timer=c.timer??i,this.execution=new Ii(c,this.timer),this.lifecycleCoordinator=c.lifecycleCoordinator??(c.timer?new $j(c.timer):Gs())}async boot(c,d){Nj(c,c.cameraPosterPath);let g=c.timeoutMs??Ve,R={request:c,operationName:c.operationName??"startDevice",startedAtMs:this.timer.now(),deadlineMs:c.totalDeadlineMs??this.timer.now()+g,signal:c.signal,lifecycleLease:this.dependencies.lifecycleLease,ownsLifecycleLease:!1,unconfirmedProcessExits:[],pendingTerminations:[],freshProvision:c.freshProvision===!0};if(!R.lifecycleLease&&!this.dependencies.onIdentityResolved)R.lifecycleLease=await this.lifecycleCoordinator.reserve(ey(c.platform,c),{operation:"start",deadlineMs:R.deadlineMs,signal:c.signal}),R.ownsLifecycleLease=!0,R.signal=c.signal?AbortSignal.any([c.signal,R.lifecycleLease.signal]):R.lifecycleLease.signal;try{if(c.deviceId)return await this.bootKnownDevice({...c,deviceId:c.deviceId},R,d);return await this.bootMatchingDevice(c,R,d)}finally{this.releaseOwnedLifecycleLease(R)}}releaseOwnedLifecycleLease(c){if(!c.ownsLifecycleLease)return;let d=c.lifecycleLease;if(c.unconfirmedProcessExits.length===0&&c.pendingTerminations.length===0){d?.release();return}this.releaseOnceProcessesSettle(c,d)}async releaseOnceProcessesSettle(c,d){await Promise.allSettled(c.pendingTerminations),await Promise.allSettled(c.unconfirmedProcessExits),d?.release()}async bindLifecycleIdentity(c,d,g=async()=>d){if(c.lifecycleLease)await c.lifecycleLease.bindCanonicalIdentity(d,g);await this.dependencies.onIdentityResolved?.(d)}async bootKnownDevice(c,d,g){let{deviceManager:R}=this.dependencies,A={platform:c.platform,minOsVersion:c.minOsVersion,maxOsVersion:c.maxOsVersion,name:c.name,formFactor:c.formFactor,requires:c.requires,screenSize:c.screenSize},C=await this.execution.discoverBootedDevices(c.platform,d,"discovering running devices",{bypassAndroidCache:c.platform==="android",awaitAbortSettlement:!0,presentationOrder:c.presentationOrder}),D=qa(c),T=C.find((W)=>W.deviceId===c.deviceId);if(T)return await this.waitForKnownRunningDevice(T,c,A,{context:d,hasExplicitConstraints:D,progress:g});let k=this.dependencies.assertExplicitDeviceNotForeignOwned;if(k)await this.execution.runPhase(d,"checking explicit device ownership",()=>k(c.deviceId,c.platform));let M=await this.execution.runPhase(d,"listing device images",()=>R.listDeviceImages(c.platform)),F=M.find((W)=>W.deviceId===c.deviceId||c.platform==="android"&&W.name===c.deviceId);if(!F){let W=await this.execution.runPhase(d,"checking simulator platform",(G)=>fa(R,c,G));throw ha(c,C,M,W)}if(D&&!Iu(F,A))throw new t(`Device '${c.deviceId}' does not satisfy the requested constraints. ${wg(A,[F])}`);let V=await this.bootMatchedImage(F,d,g,{presentationOrder:c.presentationOrder,preferRunning:c.preferRunning,exactTarget:c.platform==="android"&&c.deviceId===F.name});return Li(V.device,F),V}async waitForKnownRunningDevice(c,d,g,{context:R,hasExplicitConstraints:A,progress:C}){Xa(d,c);let D=await this.enrichKnownRunningDevice(c,d.deviceId,A,R);rb.bindDeviceExecution(D.device.deviceId);let[T]=await QD([D.device],g.requires,this.dependencies.displayInventory??Rs,R.signal);if(A&&!Iu(T,g))throw new t(`Device '${d.deviceId}' does not satisfy the requested constraints. ${wg(g,[{...T,booted:!0}])}`);let k=await this.waitForRunningDevice(T,R,C);return D.image?{...k,device:Te(k.device,D.image),sourceImage:D.image}:k}async enrichKnownRunningDevice(c,d,g,R){let A=c.platform==="ios"&&c.iosVersion===void 0&&c.osVersion===void 0,C=c.platform==="android"?ae(c.deviceId):c.deviceId.includes("-")&&c.deviceId.length>30;if(g||A||C)try{return await this.execution.enrichBootedDeviceFromImage(c,R)}catch(D){if(g)throw D;e.warn(`[DeviceBootService] Exact device '${d}' metadata enrichment failed; adopting discovered device: ${r(D)}`,D)}return{device:c,image:void 0}}async bootMatchingDevice(c,d,g){let{deviceManager:R,deviceMatcher:A,matchingStrategy:C}=this.dependencies,D={platform:c.platform,minOsVersion:c.minOsVersion,maxOsVersion:c.maxOsVersion,name:c.name,formFactor:c.formFactor,requires:c.requires,screenSize:c.screenSize},T=c.matchNamedDeviceIgnoringOsVersion?{...D,minOsVersion:void 0,maxOsVersion:void 0}:D,M=(await this.execution.runPhase(d,"listing device images",()=>R.listDeviceImages(c.platform))).filter((q)=>!br(q,c.excludeDeviceNames,c.excludeDeviceIds)),F=[],V=await this.findRunningMatch(c,T,M,{context:d,progress:g,candidates:F});if(V)return V;let W=c.matchExactName&&c.name?M.find((q)=>q.name===c.name&&Iu(q,T))??null:A.matchDeviceImage(T,M,C);if(W){let q=await this.bootMatchedImage(W,d,g,{presentationOrder:c.presentationOrder,preferRunning:c.preferRunning,exactTarget:c.matchExactName===!0});if(c.matchExactName)Li(q.device,W);return q}if(c.matchExactName&&c.name){if(M.some((q)=>q.name===c.name))throw new t(`No ${c.platform} device matching criteria found for exact target '${c.name}'. `+wg(T,M));throw new t(`target_not_found: Configured ${c.platform} device '${c.name}' was not found; an exact target cannot be replaced or created by acquisition.`)}let G=[...F,...M.filter((q)=>!F.some((X)=>X.name===q.name))];return this.provisionAndBoot(c,D,M,{context:d,progress:g,candidates:G})}async findRunningMatch(c,d,g,{context:R,progress:A,candidates:C}){if(c.preferRunning===!1)return;let D=await this.execution.discoverBootedDevices(c.platform,R,"discovering running devices",{bypassAndroidCache:c.matchExactName&&c.name!==void 0,awaitAbortSettlement:!1,presentationOrder:c.presentationOrder});Ya(c,D);let{excludeDeviceNames:T,excludeDeviceIds:k}=c,M=T||k?D.filter((q)=>!T?.has(q.name)&&!k?.has(q.deviceId)):D,F=await tb(void 0,()=>QD(Vi(M,g),d.requires,this.dependencies.displayInventory??Rs,R.signal));C?.push(...F);let V=c.matchExactName&&c.name?Qa(c.platform,F,c.name,d):this.matchBootedPreferringUndeferred(d,F,c.deferDeviceIds);if(!V)return;await this.execution.reportProgress(R,A,100,"Found matching running device");let W=sr(V,g),G=await this.waitForRunningDevice(V,R,A);return Ja(c,G.device),W?{...G,device:Te(G.device,W),sourceImage:W}:G}matchBootedPreferringUndeferred(c,d,g){let{deviceMatcher:R,matchingStrategy:A}=this.dependencies,C=g?.size?d.filter((D)=>!g.has(D.deviceId)):d;return R.matchBootedDevice(c,C,A)??(C.length<d.length?R.matchBootedDevice(c,d,A):null)}adoptAfterLeasePolicy(c,d,g,R){let A=c.ownsLifecycleLease||this.dependencies.allowExternalLeaseAdoptionRecheck===!0,C=g===!1&&!d.isRunning;if(!A||C)return"never";return d.platform==="ios"||R?"always":"if-queued"}async bootMatchedImage(c,d,g,{presentationOrder:R,preferRunning:A,exactTarget:C}){let D=re(c.platform,"Starting a device");if(!c.isRunning&&c.platform!=="android")return this.bootImage(c,d,g,{provisioned:!1,adoptAfterLease:this.adoptAfterLeasePolicy(d,c,A,!1)});let T=await this.execution.discoverBootedDevices(D,d,"resolving the running device image",{bypassAndroidCache:c.platform==="android",awaitAbortSettlement:!0,presentationOrder:R});va(c,T,C===!0,d.freshProvision===!0);let k=hr(c,T),M=c.platform==="android"&&fr(this.lifecycleCoordinator,c.name),F=A===!1&&!c.isRunning,V=this.adoptAfterLeasePolicy(d,c,A,M);if(!k)return this.bootImage(c,d,g,{provisioned:!1,adoptAfterLease:V});if(M||F)return this.bootImage(c,d,g,{provisioned:!1,adoptAfterLease:V});let W=await this.waitForRunningDevice(Te(k,c),d,g);return{...W,device:Te(W.device,c),sourceImage:c}}async provisionAndBoot(c,d,g,{context:R,progress:A,candidates:C=g}){let D=C.map((W)=>({...W,booted:"isRunning"in W?W.isRunning:!0}));if(!this.dependencies.deviceCreationGate.isCreationAllowed(c.createIfMissing))throw Za(c,d,g,D);Ure(d,D);let T=this.dependencies.checkBootCapacity??((W,G)=>Xo.assertBootCapacityAvailable(W,{signal:G}));await this.execution.runPhase(R,"checking boot capacity",(W)=>T(d.platform,W));let k,M,F,V=this.provisioningIdentityHooks(R,(W)=>{k=W},(W)=>{M=W});try{let W=await this.execution.runPhase(R,"provisioning a device",(q)=>(F=this.dependencies.deviceProvisioner.provision(d,q,V),F));return k=W,{...await this.bootImage(vr(W,c),R,A,{provisioned:!0}),...W.prebootDisabledResources?{prebootDisabledResources:W.prebootDisabledResources}:{}}}catch(W){throw await this.rollbackFailedProvisioning(c,W,{created:k,creationStarted:M,provisioning:F}),W}}async rollbackFailedProvisioning(c,d,{created:g,creationStarted:R,provisioning:A}){if(g)await this.dependencies.rollbackCreatedDevice?.(vr(g,c),d);else if(R&&!(d instanceof ng))await this.dependencies.rollbackCreatedDevice?.(vr(R,c),d,{pendingCreation:A})}provisioningIdentityHooks(c,d,g){return{reserveBeforeCreate:async(R)=>{if(R.platform==="android")await this.bindLifecycleIdentity(c,{platform:"android",stableId:R.name});return g(R),c.signal},bindAfterCreate:async(R)=>{if(d(R),R.platform==="ios"){if(!R.deviceId)throw new t(`Created iOS simulator '${R.name}' has no lifecycle identity.`);await this.bindLifecycleIdentity(c,{platform:"ios",stableId:R.deviceId})}}}}async waitForRunningDevice(c,d,g){if(Nj(c,d.request.cameraPosterPath),d.request.cameraPosterPath!==void 0&&c.platform==="android")throw new t(!ae(c.deviceId)?"cameraPosterPath is unsupported on physical Android devices. Use a stopped Android emulator.":"cameraPosterPath is unsupported on a running Android emulator. Stop it before requesting a poster.");if(c.platform==="ios")await this.bindLifecycleIdentity(d,{platform:"ios",stableId:c.deviceId},async()=>await this.revalidateRunningIdentity(c,d));else if(c.deviceId.startsWith("emulator-")&&c.name!==`Unknown (${c.deviceId})`)await this.bindLifecycleIdentity(d,{platform:"android",stableId:c.name},async()=>await this.revalidateRunningIdentity(c,d));let R={...c,isRunning:!0},A=0;return this.bootRecovery.run(R,async()=>{if(A++,A>1)return this.bootImageOnce(R,d,g,!1);let C=await this.execution.runPhase(d,"waiting for a running device",(D)=>this.dependencies.deviceManager.waitForDeviceReady({...c,isRunning:!0},this.execution.remaining(d,"waiting for a running device"),void 0,{signal:D}));return{device:{...c,...C},source:"booted",provisioned:!1}},d.signal)}async revalidateRunningIdentity(c,d){return ec({execution:this.execution},c,d)}async revalidateImageIdentity(c,d){return tc({execution:this.execution,dependencies:this.dependencies},c,d)}async findRunningImageAfterLease(c,d,g=!0){return rc({execution:this.execution,dependencies:this.dependencies,lifecycleCoordinator:this.lifecycleCoordinator,timer:this.timer},c,d,g)}async boundedIosRecheck(c,d,g){return $i({timer:this.timer},c,d,g)}async bootImage(c,d,g,{provisioned:R,adoptAfterLease:A="never"}){if(d.deviceLabel=c.deviceId?`${c.name} (${c.deviceId})`:c.name,c.isRunningStateKnown===!1)c=await this.execution.recheckRunningState(c,d);if(Qg(c),c.platform==="ios"&&!c.deviceId)throw new t("iOS simulator deviceId (UDID) is required to start a simulator.");let C=!1;await this.bindLifecycleIdentity(d,{platform:c.platform,stableId:c.platform==="android"?c.name:c.deviceId},async()=>(C=!0,await this.revalidateImageIdentity(c,d)));let D=A==="always"||A==="if-queued"&&C;if(D){let k=await this.adoptRunningImageAfterLease(c,d,g);if(k)return k}let T=Hi(this.lifecycleCoordinator,c,this.dependencies.onAndroidColdBootTrackingChanged);try{return await this.bootRecovery.run(c,async()=>this.bootImageAdoptingAlreadyRunning(c,d,g,{provisioned:R,adoptRunningAfterLease:D}),d.signal)}finally{T?.()}}async adoptRunningImageAfterLease(c,d,g,R=!0){let A=await this.findRunningImageAfterLease(c,d,R);if(!A)return;return{...await this.waitForRunningDevice(Te(A,c),d,g),sourceImage:c}}async bootImageAdoptingAlreadyRunning(c,d,g,{provisioned:R,adoptRunningAfterLease:A}){try{return await this.bootImageOnce(c,d,g,R)}catch(C){if(!A||c.platform!=="ios"||!(C instanceof vR))throw C;let D=await this.adoptRunningImageAfterLease(c,d,g,!1);if(!D)throw C;return D}}async bootImageOnce(c,d,g,R){let A=Hi(this.lifecycleCoordinator,c,this.dependencies.onAndroidColdBootTrackingChanged);try{return await this.execution.bootImageOnceWithOwnedLaunchTracking(c,d,g,R)}catch(C){throw await d.unheldLaunchTermination,C}finally{A?.()}}}var _m="android.hardware.touchscreen",Fm=["android.software.leanback","android.hardware.type.television"],Nm=300000,Bm=3000;function oc(c){let d=c.trim();if(d==="true")return!0;return d==="false"?!1:null}function Lm(c){let d=new Set(c.split(/\r?\n/).map((g)=>g.trim()).filter((g)=>g.length>0));return d.size===1?oc([...d][0]):null}class sc{timer;ttlMs;incarnationOf;cache=new Map;constructor(c=i,d=Nm,g=Ni){this.timer=c;this.ttlMs=d;this.incarnationOf=g}forget(c){this.cache.delete(c)}async hasTouchscreen(c,d,g){let R=this.cache.get(d);if(R&&R.incarnation===this.incarnationOf(d)&&this.timer.now()-R.readAt<this.ttlMs)return R.value;let A=await wr(c,d,_m,{signal:g});if(A===null)return this.cache.delete(d),null;if(A===!1)return this.remember(d,!1);for(let C of Fm){let D=await wr(c,d,C,{signal:g});if(D===null)return this.cache.delete(d),!0;if(D)return this.remember(d,!1)}return this.remember(d,!0)}remember(c,d){return this.cache.set(c,{readAt:this.timer.now(),value:d,incarnation:this.incarnationOf(c)}),d}}async function wr(c,d,g,{signal:R,logTag:A="TouchscreenFeature"}={}){let C;try{let D=await c.executeCommand(`shell pm has-feature ${g}`,{noRetry:!0,timeoutMs:Bm,...R?{signal:R}:{}});C=oc(D.stdout)}catch(D){if(R?.throwIfAborted(),C=Lm(Jr(D).stdout),C===null)return e.warn(`[${A}] ${g} probe failed for ${d}: ${r(D)}`,D),null}if(C===null)e.warn(`[${A}] unrecognized pm has-feature ${g} output for ${d}`);return C}var ac=new sc,Nte=ac;function IW(c){ac.forget(c)}Zt({name:"android-touchscreen-feature",onDeviceIdentityReplaced:IW,onDeviceIncarnationChanged:IW});var $m="android.software.xr.api.spatial",ef=300000,Pr=(c)=>!!c&&(c.startsWith("com.android.systemui.xr")||c.startsWith("com.android.systemui/.xr"));function tf(c){return!!c&&(c.activities.some((d)=>Pr(d.name))||c.tasks.some((d)=>Pr(d.packageName)||Pr(d.rootActivity)||Pr(d.topActivity)))}function cc({device:c,backStack:d}){return c.formFactor==="xr-headset"||c.formFactor==="xr-glasses"||tf(d)}class dc{timer;ttlMs;cache=new Map;constructor(c=i,d=ef){this.timer=c;this.ttlMs=d}async isAndroidXr(c){let{device:d,adb:g,signal:R}=c;if(d.platform!=="android")return!1;let A=this.cache.get(d.deviceId);if(A&&this.timer.now()-A.readAt<this.ttlMs)return A.value;if(!g)return cc(c);let C=await wr(g,d.deviceId,$m,{signal:R,logTag:"AndroidXrDetector"});if(C===null)return this.cache.delete(d.deviceId),cc(c);return this.cache.set(d.deviceId,{readAt:this.timer.now(),value:C}),C}}var Bw=new dc;function da(c,d=Bw){return d.isAndroidXr(c)}function rf(c){return c===void 0||c==="unknown"||c==="xr-headset"||c==="xr-glasses"}class Ot{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,g,R=d.displayId??0){let A=this.deps.device();if(A.platform!=="android"||R!==0||!this.deps.readDisplaySize)return;let C=this.key(d);if(this.displaySizes.has(C))return;let D=await this.isXr(c,g);if(this.xrDevices.set(A.deviceId,D),!D)return;try{let T=await this.deps.readDisplaySize(),k=d.rotation===1||d.rotation===3;this.displaySizes.set(C,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 g=this.deps.device();return da({device:g,adb:rf(g.formFactor)?this.deps.adb?.():void 0,backStack:c.backStack,signal:d},this.deps.xrDetector)}applyCached(c,d,g=d.displayId??0){if(this.deps.device().platform!=="android"||g!==0)return;let R=this.displaySizes.get(this.key(d));if(R)c.screenSize={...R},this.deps.hierarchyCollector().reconcileScreenDimensions(d,R),d.pixelWidth=R.width,d.pixelHeight=R.height}}function Fte(c){let d=(A,C)=>Math.min(Math.max(A,0),Math.max(C-1,0)),g=(A,C)=>d(Math.round((C?c.xMax-A:A-c.xMin)/(c.xMax-c.xMin+1)*c.displayWidth),c.displayWidth),R=(A,C)=>d(Math.round((C?c.yMax-A:A-c.yMin)/(c.yMax-c.yMin+1)*c.displayHeight),c.displayHeight);return{toScreenPoint(A,C){switch(c.rotation){case 1:return{x:R(C,!1),y:g(A,!0)};case 2:return{x:g(A,!0),y:R(C,!0)};case 3:return{x:R(C,!0),y:g(A,!1)};default:return{x:g(A,!1),y:R(C,!1)}}}}}async function jC(c,d={}){let{stdout:g}=d.timeoutMs===void 0?await c.executeCommand("shell wm size"):await c.executeCommand("shell wm size",{timeoutMs:d.timeoutMs,noRetry:!0}),R=g.match(/Override size:\s*(\d+)x(\d+)/)??g.match(/Physical size:\s*(\d+)x(\d+)/);if(!R)throw Error(`Could not parse display size from wm size output: ${g}`);return{width:parseInt(R[1],10),height:parseInt(R[2],10)}}async function Lte(c){try{let{stdout:d}=await c.executeCommand("shell wm density"),g=d.match(/Physical density:\s*(\d+)/);if(g)return parseInt(g[1],10)/160}catch(d){e.warn(`[AxisRanges] Failed to query density; using 440 dpi: ${r(d)}`,d)}return 2.75}class Wi{d;constructor(c){this.d=c}async execute(c){let d=c?.deviceReadScreenshot;x$(re(this.d.device().platform,"Observing all displays")),rP(this.d.device(),"all");let g=this.d.timer().now()+(c?.timeoutMs??15000),R=await this.readAggregatePanel("active",{options:c,deadline:g,deviceReadScreenshot:d}),A=this.d.device().displays?.panels.filter($d);if(!A?.length)return R;let C=this.activePanelKey(A,R.display.key),D=[];for(let k of A){let M=k.key===C?R:await this.readAggregatePanel(k.key,{options:{...c,skipScreenshot:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,skipRecompositionTracking:!0},deadline:g}),{display:F,screenSize:V,xrPanelSpace:W,viewHierarchy:G,elements:q,screenshotPath:X,screenshotExpiresAt:J,systemInsets:Z,insets:ee,activeWindow:ne}=M;D.push({display:{...F,key:k.key,role:k.role},screenSize:V,...W?{xrPanelSpace:W}:{},viewHierarchy:G,elements:q,screenshotPath:X,screenshotExpiresAt:J,systemInsets:Z,insets:ee,activeWindow:ne,freshness:M.freshness??FR({now:this.d.timer().now(),unavailable:!0})})}let T={...R,displays:D};return await Wb(T,this.d.pathProtection()),T}activePanelKey(c,d){let g=this.d.device();if(g.displays?.panels.some((R)=>R.key===d&&!$d(R)))return;if(c.some((R)=>R.key===d))return d;return Ei(g,"active",{focusedPanelKey:Ce.observedPanel(g.deviceId)?.key}).key}async readAggregatePanel(c,d){let{options:g,deadline:R,deviceReadScreenshot:A}=d,C=Math.max(0,R-this.d.timer().now()),D=new AbortController,T=g?.signal,k=T?AbortSignal.any([T,D.signal]):D.signal,M=C===0;try{if(T?.throwIfAborted(),M)throw new Zn("Observe deadline reached; retry this panel separately.");return await l(async()=>{let F=await this.d.executeSingleDisplay({...g,display:c,signal:k,timeoutMs:C,skipCache:!0,preserveDisplayState:!0});if(A!==void 0)await this.d.captureDeviceReadScreenshot(F,k,A,{display:c});return F},{timer:this.d.timer(),timeoutMs:C,signal:T,label:`Observe display ${c}`,onTimeout:()=>{M=!0,D.abort()}})}catch(F){if(T?.throwIfAborted(),e.warn(`[ObserveScreen] Display ${c} unavailable: ${r(F)}`,F),c==="active"&&!M)return this.d.createCriticalFallback(F);let V=this.d.createBaseResult(),W=Ei(this.d.device(),c,{focusedPanelKey:Ce.observedPanel(this.d.device().deviceId)?.key});return V.display={...V.display,key:W.key,role:W.role,generation:Ce.identityRevision(this.d.device().deviceId)},V.screenSize={...W.sizePx,units:"physical-pixels"},V.freshness=FR({now:this.d.timer().now(),unavailable:!0,unavailableReason:M?"request_timed_out":"unknown",unavailableDetail:r(F)}),V}}}var lc="com.apple.springboard.lockstate",nf=2000;function _W(c){return c.kind==="known"?c.lock:void 0}function Ir(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 FT{executor;options;constructor(c=new L,d={}){this.executor=c;this.options=d}async read(c,d){try{let g=await this.executor.executeCommand(Vj(c,lc),this.options.timeoutMs??nf,d);if(g.stderr?.trim())return e.warn(`[iOS] Lock-state probe failed: ${g.stderr.trim()}`),{kind:"unknown",reason:"error",message:g.stderr.trim()};let R=g.stdout.split(`
|
|
6
|
+
`).find((C)=>C.trim().startsWith(`${lc} `)),A=lP(R??"");if(A===null)return e.warn("[iOS] Lock-state probe returned unparseable output"),{kind:"unknown",reason:"unparseable"};return{kind:"known",lock:{locked:A,keyguardShowing:A}}}catch(g){return e.warn(`[iOS] Lock-state probe failed: ${r(g)}`,g),{kind:"unknown",reason:g instanceof Io?"timeout":"error",message:r(g)}}}}var uc=new Set(["debug","tool-results-no-structured-content"]),$w=[{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 sf=Dt(y(),yr());function af(c,d,g=e){if(!d)return null;try{return sf.parse(JSON.parse(d))}catch(R){return g.warn(`[FeatureFlagRepository] Ignoring invalid config_json for flag "${c}": ${r(R)}`),null}}class Ki{injectedDb;logger;timer;constructor({db:c,timer:d=i,log:g}={}){this.timer=d,this.injectedDb=c??null,this.logger=g??e}async ensureReady(){if(!this.injectedDb)await zO()}getDb(){return this.injectedDb??_e()}async ensureFlags(c){if(await this.ensureReady(),c.length===0)return;let d=this.getDb(),g=jr(this.timer);await d.insertInto("feature_flags").values(c.map((R)=>({key:R.key,enabled:R.defaultValue?1:0,config_json:R.defaultConfig?JSON.stringify(R.defaultConfig):null,updated_at:g}))).onConflict((R)=>R.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((g)=>({key:g.key,enabled:g.enabled===1,config:af(g.key,g.config_json,this.logger),updatedAt:g.updated_at}))}async upsertFlag(c,d,g){await this.ensureReady();let R=this.getDb(),A=jr(this.timer),C=g?JSON.stringify(g):null;await R.insertInto("feature_flags").values({key:c,enabled:d?1:0,config_json:C,updated_at:A}).onConflict((D)=>D.column("key").doUpdateSet((T)=>({enabled:d?1:0,config_json:g===void 0?T.ref("feature_flags.config_json"):C,updated_at:A}))).execute()}}var pc=!1;function mc(c){pc=c}function Pu(){return pc}var Me={level:"AA",failureMode:"report",useBaseline:!1,minSeverity:"warning",contrast:{useMultiPointSampling:!0,detectGradients:!0,compositeOverlays:!1,detectTextShadows:!1,samplingPoints:9}};class zi{apply(c,d,g){switch(c){case"debug":mc(d);break;case"debug-perf":DB(d);break;case"ui-perf-mode":N.setUiPerfMode(d);break;case"mem-perf-audit":N.setMemPerfAuditMode(d);break;case"accessibility-audit":N.setAccessibilityAuditConfig(d?cf(g):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 cf=(c)=>{if(!c)return Me;let d=c.level==="A"||c.level==="AA"||c.level==="AAA"?c.level:Me.level,g=c.failureMode==="report"||c.failureMode==="threshold"||c.failureMode==="strict"?c.failureMode:Me.failureMode,R=c.minSeverity==="error"||c.minSeverity==="warning"||c.minSeverity==="info"?c.minSeverity:Me.minSeverity,A=typeof c.useBaseline==="boolean"?c.useBaseline:Me.useBaseline,C=df(c.contrast);return{level:d,failureMode:g,minSeverity:R,useBaseline:A,contrast:C}},df=(c)=>{if(!c||typeof c!=="object")return Me.contrast;let d=c,g=lf(d);return{useMultiPointSampling:typeof d.useMultiPointSampling==="boolean"?d.useMultiPointSampling:Me.contrast?.useMultiPointSampling,detectGradients:typeof d.detectGradients==="boolean"?d.detectGradients:Me.contrast?.detectGradients,compositeOverlays:typeof d.compositeOverlays==="boolean"?d.compositeOverlays:Me.contrast?.compositeOverlays,detectTextShadows:typeof d.detectTextShadows==="boolean"?d.detectTextShadows:Me.contrast?.detectTextShadows,samplingPoints:g}},lf=(c)=>c.samplingPoints===5||c.samplingPoints===9||c.samplingPoints===13?c.samplingPoints:Me.contrast?.samplingPoints;class qi{notifyToolListChanged(){}}var KC="notifications/resources/updated";class fc{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(g){e.warn("[ResourceUpdatedBroadcaster] resource update listener failed",g)}}clearForTesting(){this.listeners.clear()}}var Uw=new fc;var A3={tools:"notifications/tools/list_changed",resources:"notifications/resources/list_changed"};function Bte(c){for(let[d,g]of Object.entries(A3))if(g===c)return d;return}class hc{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(g){e.warn(`[ListChangedBroadcaster] listener failed for ${c} list_changed: ${g}`)}}clearForTesting(){this.listeners.clear()}}var _r=new hc;class ar{repository;applier;definitions;notifier;static instance=null;definitionByKey;initialized=!1;flagsByKey=new Map;configsByKey=new Map;static getInstance(){if(!ar.instance)ar.instance=new ar(new Ki,new zi);return ar.instance}static peekInstanceForTesting(){return ar.instance}static setInstanceForTesting(c){ar.instance=c}constructor(c,d,g=$w,R=new qi){this.repository=c;this.applier=d;this.definitions=g;this.notifier=R;this.definitionByKey=new Map(g.map((A)=>[A.key,A]))}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((g)=>[g.key,g]));for(let g of this.definitions){let R=d.get(g.key),A=R?R.enabled:g.defaultValue,C=R?.config??g.defaultConfig??null;this.flagsByKey.set(g.key,A),this.configsByKey.set(g.key,C),this.applier.apply(g.key,A,C)}this.initialized=!0,_r.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,g){await this.initialize();let R=this.definitionByKey.get(c);if(!R)throw Error(`Unknown feature flag: ${c}`);let A=g!==void 0?g:this.configsByKey.get(c)??R.defaultConfig??null,C=this.flagsByKey.get(c)??R.defaultValue;if(await this.repository.upsertFlag(c,d,g),this.flagsByKey.set(c,d),g!==void 0)this.configsByKey.set(c,A);if(this.applier.apply(c,d,A),d!==C&&uc.has(c))this.notifier.notifyToolListChanged();return{key:R.key,label:R.label,description:R.description,enabled:d,config:A}}async setFlagConfig(c,d){await this.initialize();let g=this.definitionByKey.get(c);if(!g)throw Error(`Unknown feature flag: ${c}`);let R=this.flagsByKey.get(c)??g.defaultValue;return await this.repository.upsertFlag(c,R,d),this.configsByKey.set(c,d),this.applier.apply(c,R,d),{key:g.key,label:g.label,description:g.description,enabled:R,config:d}}isEnabled(c){let d=this.definitionByKey.get(c);if(!d)return!1;return this.flagsByKey.get(c)??d.defaultValue}}var DD=h.ACTION_OBSERVATION_SKIP_SCREENSHOT.name,TD=h.OBSERVE_WAIT_FOR_SKIP_SCREENSHOT.name;function vc(c){return c?.trim().toLowerCase()!=="false"&&c?.trim()!=="0"}function ML(c=process.env){return vc(I(h.ACTION_OBSERVATION_SKIP_SCREENSHOT,c))}function $te(c=process.env){return vc(I(h.OBSERVE_WAIT_FOR_SKIP_SCREENSHOT,c))}var ED=h.OBSERVE_SETTLED_SCREENSHOT.name;function Hm(c,d=process.env,g=ar.getInstance()){if(c!==void 0)return c;let R=I(h.OBSERVE_SETTLED_SCREENSHOT,d);if(R!==void 0)return["true","1"].includes(R.trim().toLowerCase())?"settled":"async";return g.isEnabled("observe-settled-screenshot")?"settled":"async"}function uf(c){return c?.freshness?c.freshness==="cached-ok":c?.skipWaitForFresh??!0}function yc(c,d){return(c.result.backStack?.displayCount??0)<2&&(d.displayCount??0)>1&&(c.requestedDisplayId??c.observedAndroid?.logicalId)===0}function gc(c){return{preserveDisplayState:c?.preserveDisplayState===!0,observerMode:c?.observerMode===!0,queryOptions:c?.queryOptions,skipWaitForFresh:uf(c),minTimestamp:c?.minTimestamp??0,signal:c?.signal,skipBackStack:c?.skipBackStack??!1,screenshotMode:c?.skipScreenshot?"none":Hm(c?.screenshot)}}function bc(c){let{options:d}=c;return!c.observerMode&&!c.preserveDisplayState&&!d?.skipCache&&!d?.skipRecompositionTracking}function pf(c,d){let g=c.viewHierarchy?.hierarchy;return d&&g?.unavailableReason!==void 0||g===void 0||g.error!==void 0||c.viewHierarchy?.ctrlProxyIncomplete===!0&&!g.node}function Sc(c,d){let{result:g,requestedDisplayId:R}=c,A=c.routedAggregateSecondary&&d.sampledForeground===null,C=g.viewHierarchy?.hierarchy;return{unavailable:A||!d.hierarchyPlatformValid||pf(g,c.preserveDisplayState),unavailableReason:C?.unavailableReason??(A?"unknown":void 0),unavailableDetail:C?.unavailableDetail??(A?`The foreground app of display ${R} could not be determined.`:void 0)}}function wc(c,d){let g=hne(d.getTimings());if(!g)return;if(c.perfTiming=g.data,g.truncated)c.perfTimingTruncated=!0}var Cc=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(Cc).optional()}}),mf=s({hierarchy:Cc,updatedAt:a().finite(),packageName:n(),screenWidth:a().positive().finite(),screenHeight:a().positive().finite()});function Xi(c){return mf.safeParse(c).success}function LT(c){if(!Xi(c))throw new t("Invalid visionOS hierarchy; reconnect the runner.");let d=c.hierarchy,g=d.bounds,R=g.right-g.left,A=g.bottom-g.top;if(R<=0||A<=0)throw new t("Invalid visionOS window bounds; reconnect the runner.");return zR({...c,hierarchy:hf(d),screenWidth:R,screenHeight:A})}function Yi(c){return Array.isArray(c.node)?c.node:c.node?[c.node]:[]}function Cr(c){return[c,...Yi(c).flatMap(Cr)]}function Dc(c){return{...c,space:"ornament",...c.node&&{node:Yi(c).map(Dc)}}}function Ic(c){let g=("resource-id"in c?c["resource-id"]:c.resourceId)||c.text;return g?JSON.stringify([c.className,g]):void 0}function ff(c,d){let g=c.bounds;return c.className==="4"&&g.left===0&&g.top===0&&g.right>0&&g.bottom>0&&g.right<d.right-d.left&&g.bottom<d.bottom-d.top}function hf(c){let d=Yi(c),g=c.bounds,R=new Set;for(let A=0;A<d.length;A++){let C=d[A],D=C.bounds;if(!ff(C,g))continue;let T=d.findIndex((V,W)=>W>A&&V.className==="4"),k=C.node?Cr(C):d.slice(A,T<0?d.length:T).flatMap(Cr),M=new Set(k),F=new Set(d.flatMap(Cr).filter((V)=>!M.has(V)).map(Ic).filter(Boolean));if(k.some((V)=>{let W=V.bounds,G=Ic(V);return W.left<0||W.top<0||W.right>D.right||W.bottom>D.bottom||G!==void 0&&F.has(G)}))continue;for(let V of k)R.add(V)}return{...c,node:d.map((A)=>R.has(A)?Dc(A):A)}}import{AsyncLocalStorage as vf}from"async_hooks";var at=new vf;function yf(c,d){return c.labelSessionUuids??d?.labelSessionUuids}function gf(c,d){return c.routingBaseSessionUuid??d?.routingBaseSessionUuid}function bf(c,d){return c.callerMcpSessionId??d?.callerMcpSessionId}function Sf(c,d){return c.deviceConnectionKey??d?.deviceConnectionKey}function wf(c,d){return Object.hasOwn(c,"requestDeadline")?c.requestDeadline:d?.requestDeadline}var ml=async(c,d)=>{let g=at.getStore();return at.run({...g,...c,planRequest:c.planRequest??g?.planRequest,routingSessionUuid:c.routingSessionUuid??g?.routingSessionUuid,callerMcpSessionId:bf(c,g),deviceConnectionKey:Sf(c,g),execution:c.execution??g?.execution,requestDeadline:wf(c,g),toolSelectionProfileUuid:c.toolSelectionProfileUuid??g?.toolSelectionProfileUuid,labelSessionUuids:yf(c,g),routingBaseSessionUuid:gf(c,g),sessionToolSelectionService:c.sessionToolSelectionService??g?.sessionToolSelectionService},()=>tb((c.execution??g?.execution)?.deviceBinding,d))},Fe=()=>at.getStore(),lr=()=>at.getStore()?.autolockMcpSessionId,la=()=>at.getStore()?.oneShotCli===!0,Ute=()=>at.getStore()?.acceptanceDiscoveryOrder,ig=()=>{let c=at.getStore();return c?.autolockMcpSessionId??c?.callerMcpSessionId};function og(){return Fe()?.execution}function Fs(){return Fe()?.requestDeadline}function xW(){return Fe()?.planLockNamespace}function sg(){return Fe()?.explicitObserveDeviceRead===!0}import{access as Ec}from"fs/promises";import{join as If}from"path";var Ji="AutoMobileVisionTest";class Zi{dependencies;builds=new nt;constructor(c){this.dependencies=c}async resolve(c){c?.throwIfAborted();let d=(this.dependencies.override??(()=>pt(h.VISIONOS_RUNNER_XCTESTRUN)))();if(d){let C=Se(d);return await(this.dependencies.access??Ec)(C),C}let g=this.dependencies.builder,R=await g.getXctestrunPath("visionSimulator",{scheme:Ji});if(R)return R;let A=g.getConfig();return await this.builds.run(A.derivedDataPath,async(C)=>await H(C,async()=>{let D=async()=>{C?.throwIfAborted();let T=If(Se(A.projectRoot),"ios","control-proxy","CtrlProxy.xcodeproj");try{await(this.dependencies.access??Ec)(T)}catch(M){throw new t(`Visionos runner project is unavailable; set ${h.VISIONOS_RUNNER_XCTESTRUN.name} to a prebuilt visionos runner xctestrun. The published package does not include the visionos project.`,{cause:M})}await(this.dependencies.xcodebuild??new Jn).executeCommand(["build-for-testing","-project",T,"-scheme",Ji,"-destination","generic/platform=visionOS Simulator","-derivedDataPath",A.derivedDataPath,"CODE_SIGNING_ALLOWED=NO"],{signal:C,timeoutMs:120000});let k=await g.getXctestrunPath("visionSimulator",{scheme:Ji});if(!k)throw new t(`No xrsimulator xctestrun found in ${A.derivedDataPath}/Build/Products after building AutoMobileVisionTest; set ${h.VISIONOS_RUNNER_XCTESTRUN.name} to a prebuilt visionos runner.`);return k};return g.runExclusiveOnDerivedData?await g.runExclusiveOnDerivedData(D):await D()}),c,{cancelWhenAllWaitersAbort:!0})}}class je extends t{errorCode;constructor(c,d,g){super(c,g);this.errorCode=d}}import Cf from"ws";var Oc=5000,Tf=20000,xf=(c)=>{let d=new Cf(c);return{send:(g)=>d.send(g),close:()=>d.close(),onMessage:(g)=>{d.on("message",(R)=>g(R.toString()))},onFailure:(g)=>{d.on("error",g),d.on("close",()=>g(Error("Visionos runner disconnected; reconnect it.")))}}};function kf(c){return c==="request_hierarchy"?"hierarchy_update":`${c.slice(8)}_result`}function Of(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 Mf(c){return c.type==="request_hierarchy"?Tf:Oc}class en{options;socket;pending=new Map;sequence=0;supported=new Set;ready;resolveReady;rejectReady;failure;constructor(c,d={}){this.options=d;this.ready=new Promise((g,R)=>{this.resolveReady=g,this.rejectReady=R}),this.ready.then(void 0,()=>{}),this.socket=(d.factory??xf)(c),this.socket.onMessage((g)=>this.receive(g)),this.socket.onFailure((g)=>this.fail(u(g,"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??Oc,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 g=d;if(g.type==="connected")this.connected(g);else this.reply(g)}catch(d){this.fail(u(d,"Invalid visionos runner response")),this.socket.close()}}connected(c){if(c.platform!=="visionos"){this.fail(new je("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 g=String(c.error??"Visionos command failed");if(g.includes("kAXErrorAPIDisabled")){d.reject(new je(Of(d.type),"accessibility_api_disabled",{cause:g}));return}d.reject(new je(g,String(c.errorCode??"command_failed")))}else if(c.type===kf(d.type)&&(c.success===!0||d.type==="request_hierarchy"&&c.success===void 0))d.resolve(c.data)}async request(c,d,g){let R=this.options.timer??i,A=g?.timeoutMs??this.options.timeoutMs??Mf(c),C=String(++this.sequence),D=new AbortController,T=c.type!=="request_hierarchy",k=!1,M=!1,F=d?AbortSignal.any([d,D.signal]):D.signal;try{return await l(async()=>{if(await this.ready,F.throwIfAborted(),this.failure)throw this.failure;if(!this.supported.has(c.type))throw new je(`The visionos runner does not support ${c.type}.`,"unsupported_on_visionos");return new Promise((V,W)=>{this.pending.set(C,{type:c.type,resolve:(G)=>{M=!0,V(G)},reject:(G)=>{M=!0,W(G)}}),this.socket.send(JSON.stringify({...c,requestId:C})),k=!0})},{timer:R,timeoutMs:A,signal:F,label:`Visionos runner ${c.type}`})}catch(V){if(k&&!M&&T&&!d?.aborted)throw new je(`Visionos runner ${c.type} got no reply within ${A}ms and may still be applied; observe before retrying.`,"input_outcome_unknown",{cause:V});throw V}finally{D.abort(),this.pending.delete(C)}}async hierarchy(c,d){let g=await this.request({type:"request_hierarchy"},c,d);if(!Xi(g))throw new t("Invalid visionos hierarchy; reconnect the runner.");return g}close(){this.fail(new t("Visionos runner closed; reconnect it.")),this.socket.close()}}class Mc{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 g=this.runners.get(c);return g?.client===d?g.targetBundleId:void 0}register(c,d,g){if(this.runners.has(c))throw new t(`A visionos runner is already registered for ${c}.`);return this.runners.set(c,{client:d,targetBundleId:g}),()=>{if(this.runners.get(c)?.client===d)this.runners.delete(c)}}}var ag=new Mc;import{rm as _f}from"fs/promises";function Ff(c){for(let[d,g]of[["stdout",c.stdout],["stderr",c.stderr]])g?.on("data",(R)=>{e.debug(`Visionos runner ${d}: ${String(R).trimEnd()}`)})}class tn{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(ag.get(c.deviceId))throw new t("Visionos runner is already connected.");c.signal?.throwIfAborted();let d=c.bundleId?.trim()||void 0,g=await this.dependencies.writeRunnerEnvironment(c.xctestrun,{AM_PORT:String(c.port),...d?{AM_BUNDLE_ID:d}:{}},`visionos-${c.deviceId}`),R=!1,A=()=>{if(!R&&g!==c.xctestrun)R=!0,_f(g,{force:!0}).catch((C)=>{e.warn("Failed to remove visionos runner xctestrun copy",C)})};try{return await this.launchPrepared({...c,bundleId:d,xctestrun:g},A)}catch(C){throw A(),u(C,"Failed to launch visionos runner")}}async launchPrepared(c,d){let g=this.dependencies.timer??i;c.signal?.throwIfAborted();let R=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}),A={exited:!1,unregister:()=>{}},C=()=>{A.exited=!0,A.unregister(),A.client?.close(),d()},D=()=>{let T=!A.exited;if(C(),T)R.kill("SIGTERM")};Ff(R),R.once("exit",C),R.once("error",C);try{return await l(()=>this.waitForRunner(c,A),{timer:g,timeoutMs:60000,label:"Visionos runner startup",onTimeout:D,signal:c.signal}),{stop:D}}catch(T){throw D(),u(T,"Failed to launch visionos runner")}}async waitForRunner(c,d){let g=this.dependencies.timer??i;while(!d.exited){let R=(this.dependencies.connect??((A)=>new en(A,{timer:g})))(`ws://127.0.0.1:${c.port}/ws`);d.client=R;try{await R.waitUntilConnected(c.signal)}catch(A){if(R.close(),d.exited||c.signal?.aborted||A instanceof je)throw u(A,"Visionos runner exited during startup");e.debug("Visionos runner not ready during startup",A),await g.sleep(100);continue}if(d.exited)break;c.signal?.throwIfAborted(),d.unregister=ag.register(c.deviceId,R,c.bundleId);return}throw new t("Visionos runner exited before becoming ready; check the prebuilt test bundle.")}}class Dr{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 g of this.uninstallListeners)g(c,d)}onUninstalled(c){this.uninstallListeners.push(c)}}var NL=new Dr;var GC="dev.jasonpearson.automobile.ctrlproxy.vision";class Nc{dependencies;starts=new nt;runners=new Map;observedSessions=new WeakSet;constructor(c){this.dependencies=c;c.appUninstalls?.onUninstalled((d,g)=>this.appUninstalled(d,g))}appUninstalled(c,d){let g=this.runners.get(c);if(g&&(g.bundleId??GC)===d)return g.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:g}=c;if(g)this.observeSessions(g);if(ag.get(d)?.isUsable()&&!this.needsRestart(d))return{};this.stop(d);let R=this.dependencies.targetBundleId?.(d),A={controller:new AbortController,bundleId:R},C=He(c.signal,A.controller.signal);this.runners.set(d,A);try{let D=await this.dependencies.artifacts.resolve(C);C.throwIfAborted(),A.port=this.dependencies.ports.allocate(d);let T=await this.dependencies.launcher.launch({deviceId:d,xctestrun:D,port:A.port,bundleId:R,signal:C});if(A.stop=T.stop,C.aborted||this.runners.get(d)!==A){if(this.runners.get(d)!==A)T.stop();throw new t("the visionos session ended during runner startup")}return{stop:()=>{if(this.runners.get(d)===A)this.stop(d)}}}catch(D){if(this.runners.get(d)===A)this.stop(d);let T=r(D);return e.warn(`[VisionosRunner] Runner unavailable for ${d}: ${T}`,D),{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:g}){this.observeSessions(g);let R=this.runners.get(c);if(!g.hasSession(d)){if(!R?.ownerSession)this.stop(c);return"the visionos session ended before runner startup"}if(R)R.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(g){e.warn(`[VisionosRunner] Failed to stop runner for ${c}`,g)}finally{if(d.port!==void 0)this.dependencies.ports.release(c,d.port)}}stopSession(c){for(let[d,g]of this.runners)if(g.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,g)=>{if(this.runners.get(g)?.ownerSession===d)this.stop(g)})}}var rn;function Hte(c){rn=c}function Fc(){if(!rn)throw new t("Visionos runner builder has not been registered by the server.");return rn()}function Nf(c){return{getXctestrunPath:(d,g)=>c().getXctestrunPath(d,g),getConfig:()=>c().getConfig(),runExclusiveOnDerivedData:(d)=>{let g=c();return g.runExclusiveOnDerivedData?g.runExclusiveOnDerivedData(d):d()}}}var Le;function Bf(){if(!Le)Le=new Nc({artifacts:new Zi({builder:Nf(Fc)}),launcher:new tn({writeRunnerEnvironment:(c,d,g)=>Fc().writeRunnerEnvironment(c,d,`${g}-${B.next()}`)}),targetBundleId:(c)=>NL.get(c)??globalThis.process.env.CTRL_PROXY_IOS_BUNDLE_ID,appUninstalls:NL,ports:{allocate:(c)=>ke.allocate(`visionos:${c}`,{reservedPorts:Oo}),release:(c,d)=>ke.releaseIfAllocated(`visionos:${c}`,d)}}),process.once("exit",()=>Le?.stopAll());return Le}function qte(){Le?.stopAll()}async function Bv(c,d,g){if(d?.throwIfAborted(),!ag.get(c)?.isUsable()||(g??Le)?.needsRestart?.(c)){g??=Bf();let R=await g.start({deviceId:c,signal:d});if(d?.throwIfAborted(),R.runnerUnavailable)throw new t(`visionOS window-app runner unavailable: ${R.runnerUnavailable}`)}return Wf(c,g),ag.require(c)}function Lf(c){let d=r(c);return d.includes(GC)&&/is not running|not installed/i.test(d)}async function BT(c,d,g,R){try{return await g()}catch(A){let C=R??Le;if(d?.aborted||!Lf(A)||!C?.appUninstalled)throw A;if(C.appUninstalled(c,GC),!C.needsRestart?.(c))throw A;return e.warn(`[VisionosRunner] Host app of the runner for ${c} is gone; restarting the runner: ${r(A)}`,A),g()}}async function Vte(c,d,g){let R=g??Le;if(d?.aborted||!R?.appUninstalled(c,GC))return!1;return e.warn(`[VisionosRunner] launchApp found the host app of the runner for ${c} missing; restarting the runner`),await Bv(c,d,R),!0}function Wf(c,d){let g=Fe()?.routingSessionUuid,R=w.sessionManager();if(g&&R){let A=(d??Le)?.attach({deviceId:c,ownerSession:g,sessions:R});if(A)throw new t(A)}}function $T(c){Le?.stop(c)}class St extends Ef{displayId;detail;constructor(c,d={}){let g=d.ownerPackage?` owned by ${d.ownerPackage}`:"",R=d.uniqueId?` (${d.uniqueId})`:"";super(`Display ${c}${R} is a private virtual display${g}. 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 Bc=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(Bc).optional()}}),Gf=s({hierarchy:Bc,updatedAt:a().finite(),packageName:n(),screenWidth:a().positive().finite(),screenHeight:a().positive().finite()});function FL(c){return Gf.safeParse(c).success}function qm(c){if(!FL(c))throw new t("Invalid tvOS hierarchy; reconnect the runner.");return zR({...c,hierarchy:Vc(c.hierarchy)})}function Hc(c,d){let g=c.bounds;if(c.checkable==="true"&&(c.checked==="true"||c.checked==="false")&&g&&g.left>=d.left&&g.top>=d.top&&g.right<=d.right&&g.bottom<=d.bottom)return c.checked;let R=[c.node??[]].flat();for(let A of R){let C=Hc(A,d);if(C!==void 0)return C}return}function Vc(c){let d=[c.node??[]].flat(),g=c.focused==="true"&&c.bounds?Hc(c,c.bounds):void 0;return{...c,...g!==void 0?{checkable:"true",checked:g}:{},...c.node?{node:d.map(Vc)}:{}}}class Uc{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 Ls=new Uc;import*as be from"fs/promises";import Ne from"path";var $c="tvos-runner",Kf="automobile-runner-",zf="tvos-runner.json";class on{deps;cache;cacheDir;env;timer;fileSystem;flights=new nt;constructor(c={}){this.deps=c;this.timer=c.timer??i,this.cache=new co({downloader:c.downloader,checksumCalculator:c.checksumCalculator,timer:this.timer}),this.cacheDir=Ne.resolve(c.cacheDir??Je($c)),this.env=c.env??process.env,this.fileSystem=c.fileSystem??be}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??Vne(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=Ne.join(this.cacheDir,c.toLowerCase()),g=Ne.join(d,zf),R=null;if(await this.cache.isCached({label:"[TVOS_RUNNER]",subject:"runner",expectedSha256:c,metadataPath:g,parseMetadata:(A)=>typeof A==="object"&&A!==null&&("sha256"in A)&&typeof A.sha256==="string"?{sha256:A.sha256}:null,verifyArtifact:async()=>(R=await this.findXctestrun(d),R!==null)}))return R;return this.download(c,d,g)}async findXctestrun(c){let d=Ne.join(c,"Build","Products");try{let g=(await this.fileSystem.readdir(d)).filter((A)=>A.includes("appletvsimulator")&&A.endsWith(".xctestrun")&&!A.startsWith(Kf)&&Ne.basename(A)===A),R=[];for(let A of g){let C=Ne.join(d,A);if((await this.fileSystem.stat(C)).isFile())R.push(C)}return R.length===1?R[0]:null}catch(g){if(g instanceof Error&&"code"in g&&g.code==="ENOENT")e.debug("[TVOS_RUNNER] No cached runner products");else e.warn("[TVOS_RUNNER] Unable to inspect runner products",g);return null}}async download(c,d,g){if(this.deps.cacheDir===void 0)hi($c);else await be.mkdir(this.cacheDir,{recursive:!0,mode:448}),await be.chmod(this.cacheDir,448);let R=await be.mkdtemp(Ne.join(this.cacheDir,".staging-")),A=Ne.join(R,AY),C=Ne.join(R,"extracted"),D,T=!1;try{await this.fetch({expected:c,archivePath:A,metadataPath:g,destination:d,extracted:C,staging:R,onDownloaded:()=>{T=!0},onPublished:(k)=>{D=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(!D)throw new t("tvOS runner extraction did not publish an xctestrun.");return Ne.join(d,D)}async fetch(c){let{expected:d,archivePath:g,metadataPath:R,destination:A,extracted:C,staging:D}=c;await this.cache.fetch({label:"[TVOS_RUNNER]",expectedSha256:d,url:this.deps.releaseUrl??qne(this.env),archivePath:g,metadataPath:R,metadataMode:384,downloadTimeoutMs:this.deps.downloadTimeoutMs??120000,afterDownload:async(T)=>{c.onDownloaded(),await be.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??((V,W)=>new y$().extractBundle(V,W)))(T,C);let F=await this.findXctestrun(C);if(!F)throw new t("tvOS runner archive must contain exactly one appletvsimulator xctestrun in Build/Products.");return c.onPublished(Ne.relative(C,F)),await be.chmod(C,448),await be.rm(A,{recursive:!0,force:!0}),await be.rename(C,A),{version:De(this.env),sha256:k,downloadedAt:this.timer.now()}},settle:()=>be.rm(D,{recursive:!0,force:!0})})}}import{access as Wc}from"fs/promises";import{join as jf}from"path";class sn{dependencies;builds=new nt;constructor(c){this.dependencies=c}async resolve(c){c?.throwIfAborted();let d=(this.dependencies.override??(()=>pt(h.TVOS_RUNNER_XCTESTRUN)))();if(d){let D=Se(d);return await(this.dependencies.access??Wc)(D),D}let g=this.dependencies.builder,R=await g.getXctestrunPath("tvSimulator");if(R)return R;let A=await this.dependencies.release?.ensure(c);if(c?.throwIfAborted(),A)return A;let C=g.getConfig();return await this.builds.run(C.derivedDataPath,async(D)=>await H(D,async()=>{let T=async()=>{D?.throwIfAborted();let k=jf(C.projectRoot,"ios","control-proxy","CtrlProxy.xcodeproj");try{await(this.dependencies.access??Wc)(k)}catch(F){throw new t(`Tvos runner project is unavailable; set ${h.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:F})}await(this.dependencies.xcodebuild??new Jn).executeCommand(["build-for-testing","-project",k,"-scheme","AutoMobileTVTest","-destination","generic/platform=tvOS Simulator","-derivedDataPath",C.derivedDataPath,"CODE_SIGNING_ALLOWED=NO"],{signal:D,timeoutMs:120000});let M=await g.getXctestrunPath("tvSimulator");if(!M)throw new t(`No appletvsimulator xctestrun found in ${C.derivedDataPath}/Build/Products after building AutoMobileTVTest; set ${h.TVOS_RUNNER_XCTESTRUN.name} to a prebuilt tvos runner.`);return M};return g.runExclusiveOnDerivedData?await g.runExclusiveOnDerivedData(T):await T()}),c,{cancelWhenAllWaitersAbort:!0})}}class Ze extends t{errorCode;constructor(c,d){super(c);this.errorCode=d}}class cn 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 dn 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 qf from"ws";var LL=["up","down","left","right","select","menu","home","playPause"],Xf="press_button_hold",T3=5000,Yf=(c)=>{let d=new qf(c);return{send:(g)=>d.send(g),close:()=>d.close(),onMessage:(g)=>{d.on("message",(R)=>g(R.toString()))},onFailure:(g)=>{d.on("error",g),d.on("close",()=>g(Error("Tvos runner disconnected; reconnect it.")))}}};function Jf(c){return c==="request_hierarchy"?"hierarchy_update":c==="request_screenshot"?"screenshot":`${c.slice(8)}_result`}class ln{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((g,R)=>{this.resolveReady=g,this.rejectReady=R}),this.ready.then(void 0,()=>{}),this.socket=(d.factory??Yf)(c),this.socket.onMessage((g)=>this.receive(g)),this.socket.onFailure((g)=>{if(!this.failure)this.connectionLost=!0;this.fail(u(g,"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 g=d;if(g.type==="connected")this.connected(g);else this.reply(g)}catch(d){this.fail(u(d,"Invalid tvos runner response")),this.socket.close()}}connected(c){if(c.platform!=="tvos"){this.fail(new Ze("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 Ze(String(c.error??"Tvos command failed"),String(c.errorCode??"command_failed")));else if(c.type===Jf(d.type)&&(c.success===!0||["request_hierarchy","request_screenshot"].includes(d.type)&&c.success===void 0))d.resolve(c.data)}async request(c,d,g){let R=this.options.timer??i,A=(g?.timeoutMs??this.options.timeoutMs??T3)+Math.max(0,this.holdEndsAt-R.now()),C=String(++this.sequence),D=new AbortController,T=d?AbortSignal.any([d,D.signal]):D.signal,k=this.withForegroundHint(c),M=R.now(),F=JSON.stringify({...k,requestId:C}),V=!1,W,G=()=>W??=new dn(c.type,A);try{return await l(async()=>{if(await this.ready,T.throwIfAborted(),this.failure)throw new cn(c.type,this.failure);if(!this.supported.has(c.type))throw new Ze(`The tvos runner does not support ${c.type}.`,"unsupported_on_tvos");if(c.type==="request_press_button"&&c.durationMs!==void 0&&!this.features.has(Xf))throw new Ze("The tvos runner predates remote long presses (durationMs); rebuild or update the tvOS runner.","unsupported_on_tvos");return new Promise((q,X)=>{if(this.pending.set(C,{type:c.type,resolve:q,reject:X}),V=!0,c.type==="request_press_button"&&c.durationMs!==void 0)this.holdEndsAt=Math.max(this.holdEndsAt,R.now()+c.durationMs);this.socket.send(F)})},{timer:R,timeoutMs:A,signal:T,label:`Tvos runner ${c.type}`,timeoutError:()=>V?G():void 0,onTimeout:()=>{if(V)this.connectionLost=!0,this.fail(G()),this.socket.close()}})}catch(q){throw await this.requestError(q,k,{dispatched:V,startedAt:M,signal:d})}finally{D.abort(),this.pending.delete(C)}}async requestError(c,d,g){g.signal?.throwIfAborted();let R="bundleId"in d?d.bundleId:void 0;if(g.dispatched&&R&&this.connectionLost&&c===this.failure){let A=await this.options.appExit?.diagnose(R,d.type,g.startedAt,g.signal);if(A)return A}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(!FL(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 YC=new Dr;import{rm as yh}from"fs/promises";class Mt extends t{bundleId;commandType;crashReport;constructor(c,d,g){let R=g?` (${[g.exceptionType,g.exceptionMessage,g.terminationReason,`crash report ${g.reportPath}`].filter(Boolean).join("; ")})`:"";super(`App ${c} exited during ${d}${R}; relaunch it with launchApp.`);this.bundleId=c;this.commandType=d;this.crashReport=g}}var un="crashApp is not supported on physical iOS devices; AutoMobile will not fall back to normal termination";class xr{kind="physical";listProcesses(c){return Promise.reject(new t(un))}killProcess(c){return Promise.reject(new t(un))}readCrashLog(c){return Promise.reject(new t(un))}}class JC{deviceId;simctl;launchctlDomain;kind="simulator";constructor(c,d,g="user"){this.deviceId=c;this.simctl=d;this.launchctlDomain=g}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 Wte(c,d){return z({deviceId:c})==="simulator"?new JC(c,d.simctl,d.platform==="tvos"||d.platform==="watchos"?"system":"user"):new xr}function fl(c,d){for(let g of c.split(`
|
|
7
|
+
`)){let R=g.trim().match(/^(\d+)\s+\S+\s+(UIKitApplication:(.+?)\[[^\]]+\]\[[^\]]+\])$/);if(R?.[3]===d)return{pid:Number(R[1]),serviceLabel:R[2]}}return null}function XC(c,d){return fl(c,d)?.pid??null}import{homedir as uh}from"os";import{join as zc}from"path";var CW=16;function Vm(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 zte(c){let d=[c.className,c.fileName&&`${c.fileName}:${c.lineNumber??"?"}`].filter(Boolean).join(" ");return d?`${c.methodName} (${d})`:c.methodName}var pn=1000;function DW(c,d){return c.timestampMs===void 0||c.timestampMs>=d-pn}function OW(c,d){return c.appId===d.appId&&(d.processId===void 0||c.processId===d.processId)}var Qf="309",Zf=7;function Gc(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 eh(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 g=(d[3]??"").padEnd(3,"0").slice(0,3),R=Date.parse(`${d[1]}T${d[2]}.${g}${d[4]}${d[5]}:${d[6]}`);return Number.isNaN(R)?void 0:R}function th(c){let d=c.procPath?.match(/\/CoreSimulator\/Devices\/([0-9A-Fa-f-]{36})\//)?.[1],g=c.coalitionName?.match(/^com\.apple\.CoreSimulator\.SimDevice\.([0-9A-Fa-f-]{36})$/)?.[1];return(d??g)?.toUpperCase()}function rh(c){let d=c?.indexOf(".app/")??-1;return d>=0?c.slice(0,d+5):void 0}function ih(c){let d=c.threads??[],g=(c.faultingThread!==void 0?d[c.faultingThread]:void 0)??d.find((A)=>A.triggered),R=rh(c.procPath);return(g?.frames??[]).slice(0,CW).map((A)=>oh(A,c,R))}function nh(c){let d=Vm(c.symbol);if(d)return d;return c.imageOffset!==void 0?`0x${c.imageOffset.toString(16)}`:"???"}function oh(c,d,g){let R=c.imageIndex!==void 0?d.usedImages?.[c.imageIndex]:void 0,A=R?.path??"";return{className:R?.name??"",methodName:nh(c),fileName:c.sourceFile??null,lineNumber:c.sourceLine??null,isAppCode:g!==void 0&&A.startsWith(g)}}function sh(c){let d=Object.values(c.asi??{}).flatMap((g)=>Array.isArray(g)?g.filter((R)=>typeof R==="string"):[]);return Vm(d.join(`
|
|
8
|
+
`))}function ah(c){let d=c.termination;if(!d)return;let R=[[d.namespace,d.code].filter((A)=>A!==void 0).join(" "),d.indicator].filter(Boolean).join(": ");return Vm(d.byProc?`${R} (by ${d.byProc})`:R)}function ch(c){let d=c.exception??{},g=[d.type,d.signal&&`(${d.signal})`].filter(Boolean).join(" ");return{exceptionType:Vm(g)??"unknown",exceptionCode:Vm([d.codes,d.subtype].filter(Boolean).join(" ")),exceptionMessage:sh(c),terminationReason:ah(c)}}function dh(c){let d=c.indexOf(`
|
|
9
|
+
`);if(d<0)return;let g=Gc(c.slice(0,d));if(g?.bug_type!==Qf)return;let R=Gc(c.slice(d+1));return R?{header:g,body:R}:void 0}function Kc(c,d){let g=dh(c),R=g?.body.bundleInfo?.CFBundleIdentifier??g?.header.bundleID;if(!g||!R)return;let{header:A,body:C}=g,D=th(C);return{report:{id:C.incident??A.incident_id??d,platform:"ios",source:"ios_ips",appId:R,appVersion:C.bundleInfo?.CFBundleShortVersionString??A.app_version,processId:C.pid,timestampMs:eh(C.captureTime),...ch(C),frames:ih(C),reportPath:d,...lh(A,C,D)},...D?{simulatorDeviceId:D}:{}}}function lh(c,d,g){return{deviceModel:c.platform===Zf||g!==void 0?"iOS Simulator":d.modelCode,osVersion:Vm(c.os_version)}}var ph=32,mh=4194304,Hw={readdir:async(c)=>Tr(c),stat:async(c)=>Hf(c),readFileBuffer:async(c)=>Uf(c)};class ZC{deviceId;fileSystem;reportsDirectory;constructor(c,d,g=zc(uh(),"Library","Logs","DiagnosticReports")){this.deviceId=c;this.fileSystem=d;this.reportsDirectory=g}async find(c){let d=this.deviceId.toUpperCase();for(let g of await this.freshCandidates(c.notBeforeTimestampMs)){c.signal?.throwIfAborted();let R=(await this.readReport(g))?.parsed;if(R?.simulatorDeviceId===d&&OW(R.report,c)&&DW(R.report,c.notBeforeTimestampMs))return{status:"found",report:R.report}}return{status:"notFound"}}async read(c,d){let g=this.deviceId.toUpperCase();for(let R of await this.freshCandidates(0)){d?.throwIfAborted();let A=await this.readReport(R);if(A?.parsed?.simulatorDeviceId===g&&A.parsed.report.id===c)return{report:A.parsed.report,text:A.text}}return}async freshCandidates(c){let d;try{d=(await this.fileSystem.readdir(this.reportsDirectory)).map((R)=>R.name)}catch(R){return e.debug(`[CrashReports] cannot list ${this.reportsDirectory}: ${R}`),[]}let g=[];for(let R of d.filter((A)=>A.endsWith(".ips"))){let A=zc(this.reportsDirectory,R);try{let C=await this.fileSystem.stat(A),D=C.mtime.getTime();if(C.isFile()&&C.size<=mh&&D>=c-pn)g.push({path:A,mtimeMs:D})}catch(C){e.debug(`[CrashReports] cannot stat ${A}: ${C}`)}}return g.sort((R,A)=>A.mtimeMs-R.mtimeMs).slice(0,ph).map((R)=>R.path)}async readReport(c){try{let d=(await this.fileSystem.readFileBuffer(c)).toString("utf8");return{text:d,parsed:Kc(d,c)}}catch(d){e.warn(`[CrashReports] failed to read ${c}: ${r(d)}`,d);return}}}var fh=4000,hh=6000;function vh(c,d=new L){let g=new JC(c,d,"system");return{async isRunning(R,A){let C=await g.listProcesses({timeoutMs:fh,signal:A});return fl(C.stdout,R)!==null}}}class jc{dependencies;constructor(c){this.dependencies=c}async diagnose(c,d,g,R){let A=new AbortController,C=R?AbortSignal.any([R,A.signal]):A.signal,D=!1;try{return await l(async()=>{let T;try{T=await this.dependencies.liveness.isRunning(c,C)}catch(M){if(!(M instanceof Io))throw M;C.throwIfAborted(),e.warn(`[TvosRunner] App liveness probe timed out for ${c}; retrying`,M),T=await this.dependencies.liveness.isRunning(c,C)}if(T)return;C.throwIfAborted(),D=!0;let k=await this.dependencies.finder.find({appId:c,notBeforeTimestampMs:g,signal:C});return new Mt(c,d,k.status==="found"?k.report:void 0)},{timer:this.dependencies.timer??i,timeoutMs:hh,signal:C,label:"tvOS app-exit diagnosis",onTimeout:()=>A.abort()})}catch(T){return R?.throwIfAborted(),e.warn(`[TvosRunner] App-exit diagnosis failed for ${c}`,T),D?new Mt(c,d):void 0}finally{A.abort()}}}function qc(c,d){return new jc({timer:d,liveness:vh(c),finder:new ZC(c,Hw)})}function gh(c,d,g={}){let R=g.targetApps??YC;return new ln(c,{timer:g.timer,factory:g.factory,foregroundApp:()=>R.get(d),appExit:g.appExit??qc(d,g.timer)})}class mn{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(Ls.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}`),g=!1,R=()=>{if(!g&&d!==c.xctestrun)g=!0,yh(d,{force:!0}).catch((A)=>{e.warn("Failed to remove tvos runner xctestrun copy",A)})};try{return await this.launchPrepared({...c,xctestrun:d},R)}catch(A){throw R(),u(A,"Failed to launch tvos runner")}}async launchPrepared(c,d){let g=this.dependencies.timer??i;c.signal?.throwIfAborted();let R=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}),A={exited:!1,unregister:()=>{}},C=()=>{if(!A.exited)A.client?.runnerExited();else A.client?.close();A.exited=!0,A.unregister(),d()},D=()=>{let T=!A.exited;if(A.exited=!0,C(),T)R.kill("SIGTERM")};R.once("exit",C),R.once("error",C);try{return await l(()=>this.waitForRunner(c,A),{timer:g,timeoutMs:60000,label:"Tvos runner startup",onTimeout:D,signal:c.signal}),{stop:D}}catch(T){throw D(),u(T,"Failed to launch tvos runner")}}async waitForRunner(c,d){let g=this.dependencies.timer??i;while(!d.exited){let R=(this.dependencies.connect??((A)=>gh(A,c.deviceId,{timer:g})))(`ws://127.0.0.1:${c.port}/ws`);d.client=R;try{await R.hierarchy(c.signal)}catch(A){if(R.close(),d.exited||c.signal?.aborted||A instanceof Ze)throw u(A,"Tvos runner exited during startup");e.debug("Tvos runner not ready during startup",A),await g.sleep(100);continue}if(d.exited)break;c.signal?.throwIfAborted(),d.unregister=Ls.register(c.deviceId,R);return}throw new t("Tvos runner exited before becoming ready; check the prebuilt test bundle.")}}class BL extends t{code="timeout";retryable=!0;detail;constructor(c,d){super(c);this.detail=d}}var ct=S(n().min(1)).min(1).optional().describe("Exact case-sensitive AutoMobile tool names to enable for the session this call mints, applied before the response is built so the returned enabledTools/gatedTools reflect discovery. Unknown or hidden names reject the call before device work; always-on names are returned in skipped.");var Xc=s({deviceId:n(),bootId:n().uuid(),userId:a().int().nonnegative(),entries:S(s({resource:p(Object.keys(HK)),target:n(),kind:p(["package","global","secure","backup"]),value:n().nullable()}).strict()).min(1).max(100)}).strict();var Yc=s({description:n(),confidence:p(["verified","inferred"]),evidence:n().optional()}),qw=S(s({resource:n(),labels:S(n()),automobileImpact:S(Yc),appImpact:S(Yc),unsafeWith:S(s({hazardId:n(),appliesTo:S(p(["post_boot","preboot"])),withResources:S(n()),reason:n(),evidence:n()})).optional()})),bh=p(["enabled","disabled"]).optional(),Sh=Object.fromEntries(Object.entries(HK).map(([c,d])=>[c,bh.describe(d)])),kr=Vt(s(Sh).strict().refine((c)=>Object.values(c).some((d)=>d!==void 0),"Specify at least one resource. Omitted resources remain unchanged."),(c)=>{c.minProperties=1}),k3=Vt(se(s({resources:kr.optional(),restore:Xc.optional().describe("Restore exact prior Android overrides from a returned receipt. Requires the same boot and user. Specify resources or restore, never both."),timeoutMs:a().int().positive().max(Do).optional().describe(`Total configuration budget in milliseconds. Defaults to ${xu}.`)}).strict()).refine((c)=>c.resources!==void 0!==(c.restore!==void 0),"Specify exactly one of resources or restore."),(c)=>{c.if={required:["resources"]},c.then={not:{required:["restore"]}},c.else={required:["restore"]}}),E3=se(s({resources:kr.describe("Requested workload profile: the resource map the simulator should match. It has no name; its identity is the returned profileFingerprint."),repair:m().optional().describe("Apply only the drifted requested entries, then re-read and fail closed. Defaults to false (report only)."),releaseOwnedExtras:m().optional().describe("With repair, re-enable services AutoMobile disabled earlier that this profile omits. Never touches overrides AutoMobile did not apply."),timeoutMs:a().int().positive().max(Do).optional().describe(`Total reconciliation budget in milliseconds. Defaults to ${xu}.`)}).strict());var jte=["vendor_documented","cdd_derived","inferred"],UT=["samsung-sleeping","samsung-deep-sleeping","samsung-auto-disable","samsung-foreground-kill","screen-off-stop","xiaomi-autostart-off","oneplus-deep-optimization","recents-swipe-kill","recents-swipe-force-stop","oneplus-sleep-standby","motorola-adaptive","user-restricted","exact-alarm-denied","notifications-off","huawei-powergenie","vivo-autostart","realme-power-saver","meizu-flyme-background","asus-power-master","sony-stamina","tecno-app-halt"];var fn=[{kind:"kill",mode:"hard"},{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"}],yn="Approximated as a force-stop plus RUN_ANY_IN_BACKGROUND ignore: the app is stopped and may not run in the background until reset. The OEM's own trigger and exemption UI are not reproduced.",gn=" Boot-receiver observation predicts default delivery without sending BOOT_COMPLETED: shell is denied this protected broadcast (SecurityException). Root checks on stock API 35 show a force-stopped package receives no default broadcast (no process starts), but does with --include-stopped-packages. A non-stopped package still receives it with RUN_ANY_IN_BACKGROUND=ignore or the restricted bucket; only stopped state blocks delivery on stock Android when a receiver and permission are present.",Wm={"samsung-sleeping":{id:"samsung-sleeping",version:1,description:"Samsung 'Sleeping apps': on battery, app in the restricted standby bucket.",steps:[{kind:"batteryUnplug"},{kind:"standbyBucket",bucket:"restricted"}],evidenceStatus:"vendor_documented",evidenceNote:"Samsung documents sleeping apps as restricted from background work. The restricted bucket needs API 30+; below that the bucket step reports unsupported.",source:"https://developer.samsung.com/mobile/app-management.html"},"samsung-deep-sleeping":{id:"samsung-deep-sleeping",version:2,description:"Samsung 'Deep sleeping apps': stopped and never run in the background.",steps:[...fn,{kind:"appOp",op:"WAKE_LOCK",mode:"ignore"}],evidenceStatus:"inferred",evidenceNote:yn+" WAKE_LOCK ignore simulates Samsung's foreground-service wake-lock denial on Android 11; this is inferred, not a vendor-documented capture.",source:"https://developer.samsung.com/mobile/app-management.html"},"samsung-auto-disable":{id:"samsung-auto-disable",version:2,description:"Samsung auto-disable of unused apps: runtime permissions revoked and app hibernation.",steps:[{kind:"runtimePermissions"},{kind:"hibernation"}],evidenceStatus:"inferred",evidenceNote:"Approximated by explicit runtime permission revocation and AOSP app hibernation. Hibernation alone does not revoke permissions of preinstalled apps. Restores the captured granted permission set and hibernation state read before the first change; the unused-for-N-days trigger is not reproduced.",source:"https://developer.samsung.com/mobile/app-management.html"},"samsung-foreground-kill":{id:"samsung-foreground-kill",version:1,description:"Samsung Game Booster / Good Guardians: force-stop after another app comes to the foreground.",steps:[{kind:"foregroundChange"},{kind:"kill",mode:"hard"}],evidenceStatus:"inferred",evidenceNote:"Opens Settings, verifies another app is foreground, then force-stops. Approximates Game Booster / Good Guardians; OEM trigger and exemption policies are not reproduced.",source:"https://dontkillmyapp.com/samsung"},"screen-off-stop":{id:"screen-off-stop",version:1,description:"Screen-off cleanup: wait one minute with the screen off, then force-stop.",steps:[{kind:"screenOff",minutes:1},{kind:"kill",mode:"hard"}],evidenceStatus:"inferred",evidenceNote:"Approximates Asus Power Master, Meizu Protected apps and realme/Tecno screen-off cleanup with an explicit one-minute wait. Restores an initially awake screen; the N-days-unused trigger remains non-emulatable.",source:"https://dontkillmyapp.com/"},"xiaomi-autostart-off":{id:"xiaomi-autostart-off",version:2,description:"Xiaomi HyperOS/MIUI Autostart off: stopped and not restarted in the background.",steps:[...fn,{kind:"bootReceiverCheck"}],evidenceStatus:"inferred",evidenceNote:yn+gn,source:"https://dontkillmyapp.com/"},"oneplus-deep-optimization":{id:"oneplus-deep-optimization",version:1,description:"OnePlus deep optimization: stopped and restricted from background execution.",steps:fn,evidenceStatus:"inferred",evidenceNote:yn,source:"https://dontkillmyapp.com/"},"recents-swipe-kill":{id:"recents-swipe-kill",version:1,description:"Swipe away from recents, soft: background the app, then kill its processes.",steps:[{kind:"home"},{kind:"kill",mode:"soft"}],evidenceStatus:"inferred",evidenceNote:"Stock Android keeps the app's alarms and jobs after a recents swipe; `am kill` only ends its background processes. Nothing to restore.",source:"https://dontkillmyapp.com/"},"recents-swipe-force-stop":{id:"recents-swipe-force-stop",version:1,description:"Swipe away from recents, hard (several OEMs): background, then force-stop.",steps:[{kind:"home"},{kind:"kill",mode:"hard"}],evidenceStatus:"inferred",evidenceNote:"Several OEMs force-stop on a recents swipe, which also cancels alarms and jobs until the user opens the app again. Nothing to restore.",source:"https://dontkillmyapp.com/"},"oneplus-sleep-standby":{id:"oneplus-sleep-standby",version:1,description:"OnePlus sleep standby optimization: on battery, device forced into deep Doze.",steps:[{kind:"batteryUnplug"},{kind:"forceIdle"}],evidenceStatus:"inferred",evidenceNote:"Approximated with the AOSP Doze test recipe; force-idle needs the device on battery, so the battery is unplugged first. Doze must be enabled on the device.",source:"https://developer.android.com/topic/performance/power/test-power"},"motorola-adaptive":{id:"motorola-adaptive",version:1,description:"Motorola adaptive battery: app in the rare standby bucket.",steps:[{kind:"standbyBucket",bucket:"rare"}],evidenceStatus:"inferred",evidenceNote:"Approximated by the AOSP rare bucket that adaptive battery assigns.",source:"https://developer.android.com/topic/performance/power/test-power"},"user-restricted":{id:"user-restricted",version:1,description:"User-restricted background usage: RUN_ANY_IN_BACKGROUND ignore.",steps:[{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"}],evidenceStatus:"cdd_derived",evidenceNote:"Android 16 CDD 3.5.1: an OEM restriction stricter than the restricted bucket must return true for ActivityManager.isBackgroundRestricted(); this appop produces that signal on stock Android.",source:"https://source.android.com/docs/compatibility/16/android-16-cdd"},"exact-alarm-denied":{id:"exact-alarm-denied",version:1,description:"Exact alarms revoked: SCHEDULE_EXACT_ALARM denied for the app's uid.",steps:[{kind:"appOp",op:"SCHEDULE_EXACT_ALARM",mode:"deny"}],evidenceStatus:"vendor_documented",evidenceNote:"AOSP behaviour when the user turns off 'Alarms & reminders' (API 31+). Apps that declare USE_EXACT_ALARM keep the permission.",source:"https://developer.android.com/develop/background-work/services/alarms/schedule"},"notifications-off":{id:"notifications-off",version:2,description:"Notifications off: POST_NOTIFICATIONS runtime permission revoked (Android 13+).",steps:[{kind:"notificationPermission",mode:"revoke"}],evidenceStatus:"inferred",evidenceNote:"Revokes the POST_NOTIFICATIONS runtime permission, as the Settings notification toggle does on Android 13+. Restored to the grant read before the first change; an already-denied permission stays denied."},"huawei-powergenie":{id:"huawei-powergenie",version:2,description:"Huawei EMUI: Classic battery optimization: Don't allow and background restriction.",steps:[{kind:"standbyBucket",bucket:"restricted"},{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"},{kind:"appOp",op:"WAKE_LOCK",mode:"ignore"},{kind:"bootReceiverCheck"}],evidenceStatus:"inferred",evidenceNote:'Battery > App launch set to "Manage manually" with Auto-launch, Secondary launch and Run in background switched off is approximated by the restricted bucket, RUN_ANY_IN_BACKGROUND ignore and WAKE_LOCK ignore, plus boot receiver observation. Mechanisms from the dontkillmyapp.com Huawei entry (CC-BY-4.0). samsung-foreground-kill gives a foreground-change kill; screen-off-stop gives a screen-off kill. Not emulated: PowerGenie/HwPFWService killing every non-whitelisted app after about 60 minutes in the background, using a Huawei-maintained whitelist; System Manager Smart tune-up cleanup.'+gn,source:"https://dontkillmyapp.com/huawei"},"vivo-autostart":{id:"vivo-autostart",version:2,description:"Vivo Funtouch OS: Per-app background power restriction (Android 13).",steps:[{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"},{kind:"standbyBucket",bucket:"restricted"},{kind:"bootReceiverCheck"}],evidenceStatus:"inferred",evidenceNote:"Android 13 background power restriction is approximated by background restriction and the restricted bucket, plus boot receiver observation. Mechanisms from the dontkillmyapp.com Vivo entry (CC-BY-4.0). Not emulated: the proprietary Autostart permission (stock delivery is only observed); taskbar app lock."+gn,source:"https://dontkillmyapp.com/vivo"},"realme-power-saver":{id:"realme-power-saver",version:2,description:"realme UI: Power saving on battery with App battery management set to Optimize.",steps:[{kind:"batteryUnplug"},{kind:"standbyBucket",bucket:"restricted"},{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"}],evidenceStatus:"inferred",evidenceNote:"Power saving on battery and App battery management Optimize are approximated by battery unplug, the restricted bucket and background restriction. Mechanisms from the dontkillmyapp.com realme entry (CC-BY-4.0). The separate screen-off-stop profile approximates screen-off cleanup. Not emulated: Super power saving mode's 6-app limit; auto power-saving trigger levels; OEM sleep schedules.",source:"https://dontkillmyapp.com/realme"},"meizu-flyme-background":{id:"meizu-flyme-background",version:2,description:'Meizu Flyme: Background processes not allowed and "keep running after screen off" off (wake-lock denial).',steps:[{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"},{kind:"appOp",op:"WAKE_LOCK",mode:"ignore"}],evidenceStatus:"inferred",evidenceNote:"Background processes not allowed is approximated by background restriction. Keep running after screen off off is approximated by WAKE_LOCK ignore. Mechanisms from the dontkillmyapp.com Meizu entry (CC-BY-4.0). screen-off-stop gives a screen-off kill. Not emulated: Protected apps list; Power plan.",source:"https://dontkillmyapp.com/meizu"},"asus-power-master":{id:"asus-power-master",version:2,description:"Asus ZenUI: Power Master's auto-deny of auto-start.",steps:[{kind:"standbyBucket",bucket:"restricted"},{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"}],evidenceStatus:"inferred",evidenceNote:`Power Master auto-deny of auto-start is approximated by the restricted bucket and RUN_ANY_IN_BACKGROUND ignore. Mechanisms from the dontkillmyapp.com Asus entry (CC-BY-4.0). screen-off-stop approximates "Clean up in suspend". Not emulated: Power Master's own whitelist and settings UI; its auto-start denial, which can block a boot receiver from starting an app that targets below API 33 (stock Android still starts it, so a boot receiver check here can differ from a real Asus device).`,source:"https://dontkillmyapp.com/asus"},"sony-stamina":{id:"sony-stamina",version:2,description:"Sony Xperia: STAMINA mode (background processes and alarms restricted).",steps:[{kind:"batteryUnplug"},{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"},{kind:"appOp",op:"SCHEDULE_EXACT_ALARM",mode:"deny"}],evidenceStatus:"inferred",evidenceNote:'STAMINA mode on battery is approximated by battery unplug, background restriction and exact alarm denial. On Android 13 and later an app declaring USE_EXACT_ALARM can keep exact alarm access despite the SCHEDULE_EXACT_ALARM denial. Mechanisms from the dontkillmyapp.com Sony entry (CC-BY-4.0). Not emulated: the time-based "Prefer battery time" STAMINA level limits after screen off; the Power-saving feature Excepted list; Intelligence Engine.',source:"https://dontkillmyapp.com/sony"},"tecno-app-halt":{id:"tecno-app-halt",version:2,description:"Tecno HiOS: Background execution denied and foreground-service wake locks denied.",steps:[{kind:"appOp",op:"RUN_ANY_IN_BACKGROUND",mode:"ignore"},{kind:"appOp",op:"WAKE_LOCK",mode:"ignore"}],evidenceStatus:"inferred",evidenceNote:'Power Saving Management For Apps denial is approximated by background execution and wake-lock denial. Mechanisms from the dontkillmyapp.com Tecno entry (CC-BY-4.0). screen-off-stop approximates Power Marathon screen-off cleanup. Not emulated: app-freeze ("frozen in time") of timers and foreground services; the night-time Sleep Mode airplane-mode schedule; Auto-start management allow-list.',source:"https://dontkillmyapp.com/tecno"}},MW=[{id:"oem-unused-app-triggers",note:"OEM triggers such as 'unused for 3 days' that move an app into a sleeping list."},{id:"firmware-update-exemption-reset",note:"Battery-optimization exemptions that a firmware update resets."},{id:"xiaomi-proprietary-appops",note:"Xiaomi proprietary AppOps 10008/10021 (autostart, background start); community-reported only."}];var $L=2,UL=["focused_trace","vendor_documented","cdd_derived","inferred","experimental"],Kte=["keyboard","kill","display"],I3={keyboard:"functionalityBreak",kill:"functionalityBreak",display:"functionalityBreak"};function bn(c){return MW.find((d)=>d.id===c)?.note??c}var HT={"samsung-dex":"Samsung DeX desktop mode.",knox:"Samsung Knox attestation, containers and enterprise APIs.","flip-cover-screen":"The Galaxy Z Flip cover screen and its launcher.","spen-air-actions":"S Pen Air actions and the S Pen remote.","oem-systemui":"The OEM's own SystemUI (status bar, quick settings, recents); runtime resource overlays cannot overlay code.","oem-unused-app-triggers":bn("oem-unused-app-triggers"),"firmware-update-exemption-reset":bn("firmware-update-exemption-reset"),"xiaomi-proprietary-appops":bn("xiaomi-proprietary-appops")};var cg=CL,wh="https://dontkillmyapp.com/",Jc="The gboard profile matches InputConnection traces captured from real Gboard on API 36; autocorrect and prediction are not claimed.";function Be(c){return{status:"inferred",note:`${c} global builds ship Gboard as the default keyboard. ${Jc}`}}function Oe(c){let d=Wm[c];return{status:d.evidenceStatus,note:d.evidenceNote,...d.source?{source:d.source}:{}}}var Sn={status:"inferred",note:"Current flagship and mid-range phones use a centred punch-hole camera; approximated with the AOSP hole cutout overlay. The OEM's own SystemUI is not reproduced."},Sp={"pixel-baseline":{id:"pixel-baseline",version:1,displayName:"Pixel (stock baseline)",keyboardProfileId:"gboard",nonEmulatable:[],evidence:{keyboard:{status:"focused_trace",note:Jc}}},"samsung-oneui":{id:"samsung-oneui",version:1,displayName:"Samsung One UI",keyboardProfileId:"samsung",killProfile:"samsung-sleeping",displayProfile:{cutout:"hole",navigationMode:"threebutton"},nonEmulatable:["samsung-dex","knox","flip-cover-screen","spen-air-actions","oem-systemui","oem-unused-app-triggers"],evidence:{keyboard:{status:"experimental",note:"The samsung profile is an AutoMobile behaviour model; a Samsung Keyboard trace is pending."},kill:Oe("samsung-sleeping"),display:{status:"inferred",note:"Many One UI releases ship the three-button navigation bar by default and current Galaxy S phones use a centred punch-hole (defaults vary by model and One UI version); approximated with the AOSP overlays. One UI SystemUI is not reproduced."}}},"xiaomi-hyperos":{id:"xiaomi-hyperos",version:1,displayName:"Xiaomi HyperOS",keyboardProfileId:"gboard",killProfile:"xiaomi-autostart-off",displayProfile:{cutout:"hole"},nonEmulatable:["xiaomi-proprietary-appops","oem-systemui","firmware-update-exemption-reset"],evidence:{keyboard:Be("Xiaomi"),kill:Oe("xiaomi-autostart-off"),display:Sn}},"oneplus-oxygenos":{id:"oneplus-oxygenos",version:1,displayName:"OnePlus OxygenOS",keyboardProfileId:"gboard",killProfile:"oneplus-deep-optimization",displayProfile:{cutout:"hole"},nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("OnePlus"),kill:Oe("oneplus-deep-optimization"),display:Sn}},"oppo-coloros":{id:"oppo-coloros",version:1,displayName:"OPPO ColorOS",keyboardProfileId:"gboard",killProfile:"recents-swipe-force-stop",displayProfile:{cutout:"hole"},nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("OPPO"),kill:{...Oe("recents-swipe-force-stop"),note:`ColorOS is reported to force-stop apps swiped from recents. ${Wm["recents-swipe-force-stop"].evidenceNote}`,source:wh},display:Sn}},motorola:{id:"motorola",version:1,displayName:"Motorola",keyboardProfileId:"gboard",killProfile:"motorola-adaptive",nonEmulatable:[],evidence:{keyboard:Be("Motorola"),kill:Oe("motorola-adaptive")}},"huawei-emui":{id:"huawei-emui",version:1,displayName:"Huawei EMUI",keyboardProfileId:"gboard",killProfile:"huawei-powergenie",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Huawei"),kill:Oe("huawei-powergenie")}},"vivo-funtouch":{id:"vivo-funtouch",version:1,displayName:"Vivo Funtouch OS",keyboardProfileId:"gboard",killProfile:"vivo-autostart",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Vivo"),kill:Oe("vivo-autostart")}},"realme-ui":{id:"realme-ui",version:1,displayName:"realme UI",keyboardProfileId:"gboard",killProfile:"realme-power-saver",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("realme"),kill:Oe("realme-power-saver")}},"meizu-flyme":{id:"meizu-flyme",version:1,displayName:"Meizu Flyme",keyboardProfileId:"gboard",killProfile:"meizu-flyme-background",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Meizu"),kill:Oe("meizu-flyme-background")}},"asus-zenui":{id:"asus-zenui",version:1,displayName:"Asus ZenUI",keyboardProfileId:"gboard",killProfile:"asus-power-master",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Asus"),kill:Oe("asus-power-master")}},"sony-xperia":{id:"sony-xperia",version:1,displayName:"Sony Xperia",keyboardProfileId:"gboard",killProfile:"sony-stamina",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Sony"),kill:Oe("sony-stamina")}},"tecno-hios":{id:"tecno-hios",version:1,displayName:"Tecno HiOS",keyboardProfileId:"gboard",killProfile:"tecno-app-halt",nonEmulatable:["oem-systemui"],evidence:{keyboard:Be("Tecno"),kill:Oe("tecno-app-halt")}}};function qT(c){return["keyboard",...c.killProfile?["kill"]:[],...c.displayProfile?["display"]:[]]}var Rh=s({manufacturerProfile:p(cg).describe("Manufacturer profile id, as listed by the manufacturerProfile tool"),requires:S(p(Um)).optional().describe("OEM capabilities the task needs; one the manufacturer profile cannot emulate refuses with requires_real_device before anything is created")}).strict().describe("Android: OEM manufacturer profile applied after automation readiness and reset when the session is released; the kill facet is deferred until an app is known (apply it with killProfile). Not the hardware deviceType. Requires boot=true and readiness=automation."),Ah=s({...Os,deviceProfile:Rh.optional()}).strict().superRefine(ni),Er=s({apkDirectory:n().min(1).describe("Host directory holding the Android Auto split APKs you supplied: base.apk plus its split_*.apk config splits for the emulator's ABI, language and density. AutoMobile never downloads them. Installed only while the phone still runs the image's Android Auto stub."),dhuPath:n().min(1).optional().describe("desktop-head-unit binary; defaults to $ANDROID_HOME/extras/google/auto/desktop-head-unit"),dhuConfig:n().min(1).optional().describe("Head unit config (.ini); defaults to config/default_720p.ini beside the DHU binary"),acceptAndroidAutoTerms:m().optional().describe("Tap Continue on Android Auto's welcome screen, which accepts its terms. Set only on the user's explicit instruction; otherwise a pending welcome screen is reported, not tapped.")}).strict(),Ph=s({headUnit:s({dhuPath:Er.shape.dhuPath,dhuConfig:Er.shape.dhuConfig}).strict().describe("Start a headless Desktop Head Unit projecting this phone. Pass {} for the SDK's DHU and default_720p.ini."),acceptAndroidAutoTerms:Er.shape.acceptAndroidAutoTerms}).strict(),dg=s({platform:bt,minOsVersion:n().optional().describe("Minimum OS version, inclusive (e.g., '14', '17.2')"),maxOsVersion:n().optional().describe("Maximum OS version, inclusive (e.g., '15', '18.0')"),name:n().optional().describe("Device name to match (e.g., 'iPhone 16e', 'Pixel_9_Pro')"),avdName:n().min(1).optional().describe("Exact Android Virtual Device name. Unlike name, this never selects a substring-matching AVD."),cameraPosterPath:n().optional().describe("Host PNG/JPG/JPEG camera poster. Android emulator: back camera wall, cold boot only. iOS Simulator: records for the next launchApp cold launch, including on an already-running simulator. Physical devices are unsupported."),cameraPosterQr:s({text:n().min(1).max(1024).describe("Payload the generated QR code encodes (UTF-8, at most ~213 bytes)")}).strict().optional().describe("Generate a QR PNG camera poster. Android emulator: back camera wall, cold boot only. iOS Simulator: records for the next launchApp cold launch. Physical devices are unsupported. Mutually exclusive with cameraPosterPath."),formFactor:p(["phone","tablet","foldable","tv","watch","automotive","xr-headset","xr-glasses"]).optional().describe("Device form factor"),requires:s({panels:a().int().positive().optional().describe("Minimum number of display panels"),posture:p(["closed","half_opened","opened","rear_display","flipped","tent","unknown"]).optional().describe("Supported device posture"),playStore:m().optional().describe("Android emulators only: true needs Google Play (Play Billing, Play-dependent SDKs). Matches only an emulator built from a Play Store system image, and a new emulator is created from one (google_apis_playstore). Play Store images refuse adb root, so root-dependent features report that they need a non-Play image"),screenRound:m().optional().describe("Wear OS emulators only: true matches only a round Wear profile, false only a square one; a new watch is created round unless this is false"),vehicle:s({motion:_("supported").optional().describe("Android Automotive only: the emulator can simulate driving state (deviceCondition vehicle.motion). Matches only a non-Play android-automotive image, and a new emulator is created from one; Play Store car images are user builds that refuse it")}).strict().optional().describe("Simulated vehicle states the automotive emulator must support")}).strict().optional().describe("Required display capabilities from device inventory, Google Play and vehicle states"),screenSize:s({width:a().positive().finite().describe("Screen width in pixels"),height:a().positive().finite().describe("Screen height in pixels")}).optional().describe("Desired screen dimensions"),pairWithDeviceId:n().min(1).optional().describe("watchOS only: iPhone simulator UDID to pair and activate before boot; does not boot the phone"),deviceId:n().optional(),preferRunning:m().optional().describe("Prefer already-booted device (default true)"),timeoutMs:a().int().positive().max(Do).optional().describe("Total device boot and automation-readiness timeout in ms"),runnerReadinessTimeoutMs:a().int().min(ab).max(gR).optional().describe(`Runner-readiness budget in ms within timeoutMs; overrides the shared timeout (${ab}-${gR})`),createIfMissing:m().optional().describe(`Create a device when nothing matches (CLI: --create-if-missing). Default off; ${Ct}=1 enables it when this flag is not supplied, and the flag wins.`),enableTools:ct,androidAuto:Ph.optional().describe("Android only. After the phone emulator is ready, start a headless Desktop Head Unit projecting it. The phone must already be provisioned for Android Auto (provisionDevice androidAuto); one projecting emulator per host.")});function Au(c){if(!c||typeof c!=="object"||Array.isArray(c))return c;let d=c,g=d.device;if(!g||typeof g!=="object"||Array.isArray(g))return c;return{...g,...d}}function Qc(c,d){if(c.androidAuto!==void 0&&c.platform!=="android")d.addIssue({code:"custom",path:["androidAuto"],message:"androidAuto.headUnit needs an Android phone emulator"});if(c.cameraPosterQr!==void 0&&c.cameraPosterPath!==void 0)d.addIssue({code:"custom",path:["cameraPosterQr"],message:"cameraPosterQr and cameraPosterPath are mutually exclusive"});if(c.avdName!==void 0&&c.platform!=="android")d.addIssue({code:"custom",path:["avdName"],message:"avdName is only supported for Android startDevice requests"});if(c.avdName!==void 0&&c.name!==void 0&&c.avdName!==c.name)d.addIssue({code:"custom",path:["avdName"],message:"avdName and name must identify the same Android device when both are supplied"})}var Gte=EP(Au,dg.superRefine(Qc)),HL=s({platform:_("watchos"),pairWithDeviceId:dg.shape.pairWithDeviceId,deviceId:n().min(1).optional().describe("Apple Watch simulator UDID"),name:n().min(1).optional().describe("Exact Apple Watch simulator name"),timeoutMs:dg.shape.timeoutMs.describe("Total boot timeout in ms"),enableTools:ct,sessionUuid:n().optional()}).strict(),Yte=EP((c)=>{let d=Au(c);if(d===c||!d||typeof d!=="object")return d;let g={...d};return delete g.device,g},HL.superRefine((c,d)=>{if(c.deviceId===void 0&&c.name===void 0)d.addIssue({code:"custom",path:["deviceId"],message:"A watchOS startDevice request needs deviceId or name"})})),Jte=EP(Au,dg.extend({platform:p(["android","ios","watchos","tvos","visionos"])}).superRefine(Qc)),Zc=s({bootTimeoutMs:a().int().positive().max(Do).optional().describe(`Maximum time in ms to find, recover, or boot the device operating system (default ${Ve}). bootTimeoutMs + automationReadyTimeoutMs must be <= ${Do}, including defaults for omitted fields.`),automationReadyTimeoutMs:a().int().min(ab).max(Do).optional().describe(`Maximum time in ms to install, update, start, and verify the automation runner (default ${ga}). bootTimeoutMs + automationReadyTimeoutMs must be <= ${Do}, including defaults for omitted fields; when bootTimeoutMs is omitted, this must be <= ${Do-Ve}.`)}).strict();function ed(c,d){if((c.bootTimeoutMs??Ve)+(c.automationReadyTimeoutMs??ga)>Do)d.addIssue({code:"custom",message:`bootTimeoutMs + automationReadyTimeoutMs must be <= ${Do}`,path:["bootTimeoutMs"]})}var NW=Zc.extend({requires:dg.shape.requires,avdName:n().min(1).optional().describe("Configured Android Virtual Device name (the `name` field of automobile:devices/images/android)"),deviceId:n().min(1).optional().describe("Booted device serial, e.g. emulator-5554 (the `runtime.deviceId` field of automobile:devices/booted/android), or a defined AVD image name, which is cold-booted by name. Prefer avdName to boot or coordinate a named AVD."),enableTools:ct}).superRefine(ed).superRefine((c,d)=>{if(!c.avdName&&!c.deviceId)d.addIssue({code:"custom",message:"Provide avdName (the `name` field of automobile:devices/images/android) or deviceId (the `runtime.deviceId` field of automobile:devices/booted/android)",path:["avdName"]})}),FW=Zc.extend({udid:n().min(1).optional().describe("iOS Simulator UDID (the `runtime.deviceId` field of automobile:devices/booted/ios or the `identity.stableId` field of automobile:devices/images/ios)"),deviceId:n().min(1).optional().describe("Booted device identifier (the `runtime.deviceId` field of automobile:devices/booted/ios); alias for udid"),enableTools:ct}).superRefine(ed).superRefine((c,d)=>{if(!c.udid&&!c.deviceId)d.addIssue({code:"custom",message:"Provide udid or deviceId (the `runtime.deviceId` field of automobile:devices/booted/ios)",path:["udid"]});if(c.udid&&c.deviceId&&c.udid!==c.deviceId)d.addIssue({code:"custom",message:`identifier_conflict: udid '${c.udid}' and deviceId '${c.deviceId}' are different simulator UDIDs. Pass only the identifier you mean.`,path:["deviceId"]})}),td=s({platform:_("android"),name:n().min(1).describe("Exact AVD name"),spec:Ah}).strict(),rd=s({platform:_("ios"),name:n().min(1).describe("Exact simulator name"),deviceId:n().min(1).optional().describe("Exact simulator UDID; prevents same-named simulator selection"),spec:Ms}).strict(),Ih=s({platform:_("watchos"),name:n().min(1).describe("Exact watch simulator name"),deviceId:n().min(1).optional().describe("Exact watch simulator UDID; a UDID that names no watch is refused, not created"),spec:xL}).strict(),Ch=s({platform:_("tvos"),name:n().min(1).describe("Exact Apple TV simulator name"),deviceId:n().min(1).optional().describe("Exact Apple TV simulator UDID; a UDID that names no Apple TV is refused, not created"),spec:_s}).strict(),Dh=s({platform:_("visionos"),name:n().min(1).describe("Exact Apple Vision Pro simulator name"),deviceId:n().min(1).optional().describe("Exact Apple Vision Pro simulator UDID; a UDID that names no Apple Vision Pro is refused, not created"),spec:Ns}).strict(),id=kr.optional().describe("Resource settings applied after boot and before automation readiness. Requires boot=true; omitted resources stay unchanged."),nd={boot:m().default(!0).optional().describe("Boot the resolved device after creation or adoption"),readiness:p(["automation","none"]).default("automation").optional().describe("Whether to wait for the AutoMobile automation runner after device boot"),timeoutMs:a().int().positive().max(yR).optional().describe("Total provision, boot, resource configuration, and readiness timeout in ms"),enableTools:ct.describe(`${ct.description} Requires boot=true.`),androidAuto:Er.optional().describe("Android only. After boot, prepare the phone emulator for Android Auto projection (no Google account) and start a headless Desktop Head Unit. Requires boot=true and a Google Play system image; one projecting emulator per host.")};function od(c,d){if(!c.androidAuto)return;if(c.device.platform!=="android")d.addIssue({code:"custom",path:["androidAuto"],message:"Android Auto projection needs an Android phone emulator."});if(c.boot===!1)d.addIssue({code:"custom",path:["androidAuto"],message:"Android Auto projection requires boot=true."})}function dd(c,d){if(c.resources&&c.boot===!1)d.addIssue({code:"custom",path:["resources"],message:"Resource configuration requires boot=true."});if(c.enableTools&&c.boot===!1)d.addIssue({code:"custom",path:["enableTools"],message:"Capability declaration requires boot=true; boot=false mints no session."});if(c.device.platform==="android"&&Reflect.get(c.device.spec,"deviceProfile")&&(c.boot===!1||c.readiness==="none"))d.addIssue({code:"custom",path:["device","spec","deviceProfile"],message:"A manufacturer profile requires boot=true and readiness=automation."})}var LW=s({resources:id,device:lD(Fo("platform",[td,rd])),...nd}).strict().superRefine(dd).superRefine(od);function Th(c,d){if(c.device.platform!=="watchos")return;for(let g of["resources","enableTools"])if(c[g]!==void 0)d.addIssue({code:"custom",path:[g],message:`${g} is not supported on watchOS.`});if(c.readiness==="automation")d.addIssue({code:"custom",path:["readiness"],message:'watchOS has no automation runner; pass readiness "none" or omit it.'})}function xh(c,d){if(c.device.platform!=="tvos"&&c.device.platform!=="visionos")return;let g=c.device.platform==="visionos"?["resources","enableTools"]:["resources"];for(let R of g)if(c[R]!==void 0)d.addIssue({code:"custom",path:[R],message:`${R} is not supported on ${c.device.platform==="visionos"?"visionOS":"tvOS"}.`});if(c.readiness==="automation"&&c.device.platform==="visionos")d.addIssue({code:"custom",path:["readiness"],message:'visionOS provisioning accepts only readiness "none"; observe, tapOn and sendKeys prepare the window-app runner on demand.'});if(c.readiness==="automation"&&c.device.platform==="tvos"&&c.boot===!1)d.addIssue({code:"custom",path:["readiness"],message:'tvOS readiness "automation" starts the runner and requires boot=true.'})}var zm=s({resources:id,device:lD(Fo("platform",[td,rd,Ih,Ch,Dh])),...nd,readiness:p(["automation","none"]).optional().describe('Whether to wait for the AutoMobile automation runner after device boot (default "automation"); tvOS defaults to "none" and starts its runner with "automation" (or startDevice); watchOS takes only "none" (startDevice prepares its runner); visionOS also takes only "none" and prepares its window-app runner on the first observe, tapOn or sendKeys')}).strict().superRefine(dd).superRefine(od).superRefine(Th).superRefine(xh);function Xte(c){if(c instanceof Ue)return c;if(c instanceof Qu)return new Ue(c.code,c.message,c.retryable,{hazards:c.hazards,howToProceed:c.howToProceed});if(c instanceof gt)return new Ue("identity_conflict",c.message);if(c instanceof ze)return new Ue("discovery_incomplete",c.message,!0,c.retryAfterMs!==void 0?{retryAfterMs:c.retryAfterMs}:{});return}function Zte(c,d,g){if(c==="ios")return d.find((A)=>A.deviceId===g.deviceId);return(g.deviceId?d.find((A)=>!A.foreignOwned&&A.deviceId===g.deviceId):void 0)??ot(d,g.name)}var ld=new WeakMap;function VT(c,d){return ld.set(c,d),c}function _3(c){return typeof c==="object"&&c!==null?ld.get(c):void 0}function Qte(c){if(c.status==="succeeded")return"removed";return c.failure?.code==="mutation_settlement_timeout"?"cleanup_in_progress":"retained"}var kh=["target_identity_unresolved","target_identity_conflict","inventory_incomplete","booted_inventory_incomplete"];function ere(c){return c.status==="failed"&&c.failure?.phase==="precondition"&&kh.some((d)=>d===c.failure?.code)}function tre(c){if(c.status==="succeeded")return"succeeded";return c.failure?.code==="mutation_settlement_timeout"?"in_progress":"failed"}class hl extends Ue{provisionFailure;cleanup;constructor(c,d,g){let R=d.status==="failed"&&!c.diagnostics.failedStepChangedNothing;super(R?"cleanup_failed":c.code,R?`${c.message} Cleanup of the newly created device also failed: ${d.failure?.message??"unknown cleanup failure"}`:c.message,d.status==="failed"&&!g?.retainedDevice?!1:c.retryable,d.status==="failed"&&g?.retainedDevice?{...c.diagnostics,retainedDevice:g.retainedDevice}:c.diagnostics);this.provisionFailure=c;this.cleanup=d;this.name="ProvisionDeviceRollbackError"}}function Vw(c){return"isError"in c&&c.isError===!0}function BW(c){return[`platform=${c.platform}`,c.deviceId?`deviceId=${c.deviceId}`:void 0,c.name?`name=${c.name}`:void 0,c.minOsVersion?`minOsVersion=${c.minOsVersion}`:void 0,c.maxOsVersion?`maxOsVersion=${c.maxOsVersion}`:void 0,c.formFactor?`formFactor=${c.formFactor}`:void 0].filter((d)=>d!==void 0).join(" ")}function rre(c){return c.runnerReadinessTimeoutMs??c.timeoutMs??N.getRunnerReadinessTimeoutMs()}function nre(c,d=Fs()){let g={...c};Hs(g),delete g.rollbackOnRetryableReadiness,delete g.discardSnapshotOnExit,delete g.transportDeadlineMs,delete g.liveDeadlineKey;let R=LW.parse(g);return{...R,...c.rollbackOnRetryableReadiness===!1?{rollbackOnRetryableReadiness:!1}:{},...c.discardSnapshotOnExit===!0?{discardSnapshotOnExit:!0}:{},boot:R.boot??!0,readiness:R.readiness??"automation",...Eh(d)}}function Eh(c){let d=c?.deadlineMs,g=c?.liveDeadlineKey;return{...typeof d==="number"?{transportDeadlineMs:d}:{},...g?{liveDeadlineKey:g}:{}}}function ire(c,d,g){let R=d.now()+(c.timeoutMs??ao),A=c.transportDeadlineMs;if(!g||A===void 0)return R;return Math.min(R,A-Vr-Jo)}function ud(c){return new Ue("timeout",`provisionDevice timeout exhausted while ${c}; remainingBudgetMs=0`)}var ore="device_already_stopped",Bs=30000,QC=5000;async function sre(c,d,g){let R=Error("Provision device settlement wait timed out");try{return await l(c.then(()=>!0,()=>!0),{timer:d,timeoutMs:g,label:"Provision device settlement",timeoutError:()=>R})}catch(A){if(A===R)return!1;throw A}}function lg(c,d,g={}){return{isError:!0,content:[{type:"text",text:JSON.stringify({success:!1,message:d,error:{code:c,message:d},...g})}]}}function x3(c,d,g,{timeoutError:R,timeoutDetail:A}){if(d.now()>=g)throw R(A);throw c}function Pc(c,d,g=Bs,R="to disappear"){return new BL(`Timed out waiting for ${c.platform} device '${c.name}' (${c.deviceId}) ${R} after ${g}ms: ${d}. Verify the platform shutdown state and retry.`,d)}async function Ac(c,d,g,{deadlineMs:R,requestAbortSignal:A,timeoutError:C=(k)=>Pc(d,k),operation:D="start",coordinator:T=Gs()}){try{return await T.reserve({kind:"stable",platform:c.platform,stableId:c.stableId},{operation:D,deadlineMs:R,signal:A})}catch(k){x3(k,g,R,{timeoutError:C,timeoutDetail:"waiting for stable device lifecycle reservation"})}}async function are(c,d,g){let R=Error("Settlement wait timed out");try{await l(c.then(()=>{return},()=>{return}),{timer:d,timeoutMs:g,label:"Settlement wait",timeoutError:()=>R})}catch(A){if(A!==R)throw A}}async function Kt(c,d,g,{detail:R,requestAbortSignal:A,operation:C,timeoutMs:D,phase:T,onOrphan:k}){let M=g-d.now(),F=D??Math.max(0,M);if(M<=0)throw Pc(c,R,F,T);let V=new AbortController,W=A?AbortSignal.any([A,V.signal]):V.signal,G=!1,q=!1,X=Promise.resolve().then(()=>H(W,()=>C(W,M))).then((J)=>(q=!0,J),(J)=>{if(q=!0,G)throw Pc(c,R,F,T);throw J});X.catch(()=>{return});try{return await l(X,{timer:d,timeoutMs:M,signal:A,label:"Device shutdown",relabelDefaultAbort:!1,timeoutError:()=>(G=!0,V.abort(),Pc(c,R,F,T))})}catch(J){if(!q)k?.(X);throw J}}async function eD(c,d,g){if(!g)return await c.sleep(d),!1;if(g.aborted)return!0;let R,A;try{return await new Promise((C)=>{if(A=c.setTimeout(()=>C(!1),d),g.aborted){C(!0);return}R=()=>C(!0),g.addEventListener("abort",R,{once:!0})})}finally{if(A!==void 0)c.clearTimeout(A);if(R)g.removeEventListener("abort",R)}}async function jm(c,d,g,{operation:R,timeoutError:A,onOrphan:C}){let D=Math.floor(d-c.now());if(D<=0)throw A();let T=new AbortController,k=g?AbortSignal.any([g,T.signal]):T.signal,M=!1,F,V,W=(X)=>{F=X},G=async(X,J)=>{try{await Xe(()=>J(X))}catch(Z){e.warn(`Undoing an undelivered operation result failed: ${r(Z)}`,Z)}return M=!0,X},q=H(k,()=>R(k,W,(X)=>{V=X})).then((X)=>{let J=F;if(J&&(g?.aborted||T.signal.aborted))return G(X,J);return M=!0,X},(X)=>{throw M=!0,X});q.catch((X)=>{e.debug(`Provision operation rejection observed: ${r(X)}`)});try{let X=await l(q,{timer:c,timeoutMs:D,signal:g,label:"Provision operation",timeoutError:()=>{let J=A();return T.abort(J),J}});return V?.(),X}catch(X){if(!M)C?.(q);throw X}}async function ug(c,d,g,{operation:R,phase:A,onPendingSettlement:C}){return await jm(c,d,g,{operation:R,timeoutError:()=>ud(A),onOrphan:C})}var Oh=5000,Mh=250;class wn{dependencies;constructor(c){this.dependencies=c}async restore(c,d){let g=this.dependencies.targetApps.get(c);if(g===void 0)return;d?.throwIfAborted();let R=await this.dependencies.activate(c,g,d);if(!R.success)throw d?.throwIfAborted(),new t(`Could not bring ${g} back to the foreground after the tvOS runner started: ${R.error??"simctl launch failed"}. Call launchApp to bring it to the front.`);await this.awaitForeground(c,g,d)}async awaitForeground(c,d,g){let R=this.dependencies.foreground;if(!R)return;let A=this.dependencies.timer??i,C=this.dependencies.settleTimeoutMs??Oh,D=this.dependencies.pollIntervalMs??Mh,T=A.now()+C,k;for(;;){if(g?.throwIfAborted(),k=await this.readForeground(R,c,{timer:A,remainingMs:T-A.now(),signal:g}),k===d)return;let M=T-A.now();if(M<=0)break;await eD(A,Math.min(D,M),g)}throw new t(`${d} was not in front within ${C} ms after the tvOS runner started (in front: ${k??"unknown"}). Call observe again, or launchApp to bring it to the front.`)}async readForeground(c,d,{timer:g,remainingMs:R,signal:A}){let C=new AbortController,D=He(A,C.signal);try{return await l(()=>c(d,D),{timer:g,timeoutMs:Math.max(1,R),signal:A,label:"tvOS foreground probe",onTimeout:()=>C.abort()})}catch(T){A?.throwIfAborted(),e.debug(`[TvosRunner] foreground probe on ${d} failed: ${r(T)}`);return}}}class pd{dependencies;runners=new Map;observedSessions=new WeakSet;restarts=new nt;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(g)=>{if(Ls.get(c)?.isUsable())return{};let R=this.runners.get(c);if(!R){let C=Ls.get(c);if(C)return{unownedRunner:C};return{runnerUnavailable:"the runner is not owned by this lifecycle"}}let A=new AbortController;try{let C=this.startOwned({deviceId:c,signal:He(g,A.signal)},R.ownerSession);return await l(C,{timer:this.dependencies.timer??i,timeoutMs:65000,signal:He(g,this.runners.get(c)?.controller.signal),label:"tvOS runner recovery",onTimeout:()=>A.abort()})}catch(C){throw new t(`tvOS runner recovery failed: ${r(C)}. Call startDevice to restart the runner.`,{cause:C})}finally{A.abort()}},d,{cancelWhenAllWaitersAbort:!0})}async startOwned(c,d){let{deviceId:g,sessions:R}=c;if(R)this.observeSessions(R);if(Ls.get(g)?.isUsable())return{};this.stop(g);let A={controller:new AbortController,ownerSession:d},C=He(c.signal,A.controller.signal);this.runners.set(g,A);let D=()=>{if(this.runners.get(g)===A)this.stop(g)};C.addEventListener("abort",D,{once:!0});try{C.throwIfAborted();let T=await this.dependencies.artifacts.resolve(C);C.throwIfAborted(),A.port=this.dependencies.ports.allocate(g);let k=await this.dependencies.launcher.launch({deviceId:g,xctestrun:T,port:A.port,signal:C});if(A.stop=k.stop,C.aborted||this.runners.get(g)!==A){if(this.runners.get(g)!==A)k.stop();throw new t("the tvos session ended during runner startup")}let M=await this.restoreForeground(g,C);if(C.aborted||this.runners.get(g)!==A)throw new t("the tvos session ended during runner startup");return{...M===void 0?{}:{foregroundRestore:M},stop:()=>{if(this.runners.get(g)===A)this.stop(g)}}}catch(T){if(this.runners.get(g)===A)this.stop(g,T);let k=r(T);return e.warn(`[TvosRunner] Runner unavailable for ${g}: ${k}`,T),{runnerUnavailable:k}}finally{C.removeEventListener("abort",D)}}async restoreForeground(c,d){try{await this.dependencies.foreground?.restore(c,d);return}catch(g){return d.throwIfAborted(),e.warn(`[TvosRunner] App under test not restored to the foreground on ${c}: ${r(g)}`,g),r(g)}}attach({deviceId:c,ownerSession:d,sessions:g}){if(this.observeSessions(g),!g.hasSession(d))return this.stop(c),"the tvos session ended before runner startup";let R=this.runners.get(c);if(R)R.ownerSession=d;return}stop(c,d=new t("Tvos runner lifecycle ended")){let g=this.runners.get(c);if(!g)return;this.runners.delete(c),g.controller.abort(d);try{g.stop?.()}catch(R){e.warn(`[TvosRunner] Failed to stop runner for ${c}`,R)}finally{if(g.port!==void 0)this.dependencies.ports.release(c,g.port)}}stopSession(c){for(let[d,g]of this.runners)if(g.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,g)=>{if(this.runners.get(g)?.ownerSession===d)this.stop(g)})}}var Rn;function cre(c){Rn=c}function Or(){if(!Rn)throw new t("Tvos runner builder has not been registered by the server.");return Rn()}var Nt;function gl(){if(!Nt)Nt=new pd({artifacts:new sn({release:new on,builder:{getXctestrunPath:(c)=>Or().getXctestrunPath(c),getConfig:()=>Or().getConfig(),runExclusiveOnDerivedData:(c)=>{let d=Or();return d.runExclusiveOnDerivedData?d.runExclusiveOnDerivedData(c):c()}}}),foreground:new wn({targetApps:YC,activate:(c,d,g)=>new L().launchApp(d,{signal:g},c),foreground:async(c,d)=>(await Ls.get(c)?.hierarchy(d))?.packageName}),launcher:new mn({writeRunnerEnvironment:(c,d,g)=>Or().writeRunnerEnvironment(c,d,`${g}-${B.next()}`)}),ports:{allocate:(c)=>ke.allocate(`tvos:${c}`,{reservedPorts:Oo}),release:(c,d)=>ke.releaseIfAllocated(`tvos:${c}`,d)}}),process.once("exit",()=>Nt?.stopAll());return Nt}function dre(){Nt?.stopAll()}async function ua(c,d,g){if(d?.throwIfAborted(),!Ls.get(c)?.isUsable()){let R=await(g??gl()).restartOwned(c,d);if(d?.throwIfAborted(),R.unownedRunner)return R.unownedRunner;if(R.runnerUnavailable||!Ls.get(c)?.isUsable())throw new t(`tvOS runner unavailable for ${c}: ${R.runnerUnavailable??"recovery did not connect a usable runner"}. Call startDevice to restart the runner, then retry.`)}return Ls.require(c)}function C3(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((g)=>typeof g==="number"&&Number.isFinite(g)&&g>0)&&(d.bundleId===void 0||d.bundleId===null||typeof d.bundleId==="string")&&md(d.root)}function md(c){if(!c||typeof c!=="object")return!1;let d=c;return typeof d.className==="string"&&_h(d.bounds)&&Fh(d)&&(d.children===void 0||d.children===null||Array.isArray(d.children)&&d.children.every(md))}function _h(c){if(!c||typeof c!=="object")return!1;let d=c;return["left","top","right","bottom"].every((g)=>typeof d[g]==="number"&&Number.isFinite(d[g]))}function Fh(c){let d=c.accessibilityTraits??[];return[c.accessibilityIdentifier,c.accessibilityLabel,c.role].every((g)=>g===void 0||g===null||typeof g==="string")&&[c.isHidden,c.isOccluded,c.isAccessibilityElement,c.isAccessibilityFocused,c.hasTapTarget,c.isUserInteractionEnabled].every((g)=>g===void 0||g===null||typeof g==="boolean")&&Number.isFinite(c.alpha??1)&&Array.isArray(d)&&d.every((g)=>typeof g==="string")}function hd(c){return!c.isHidden&&!c.isOccluded&&(c.alpha??1)>0}var Nh=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]),Bh=new Set([45,49,50,52]),Lh=new Set([26,32,46]);function Hh(c){let d=/^XCUIElementType\((\d+)\)$/.exec(c);return d?Number(d[1]):void 0}function In(c,d){let g=Hh(c.className);return g!==void 0&&d.has(g)}function Vh(c,d){let g=d&&In(c,Nh),R=d&&In(c,Bh);return{clickable:String((c.hasTapTarget??!1)||g),scrollable:In(c,Lh)?"true":void 0,actions:R?["set_text"]:void 0}}function vd(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),...Vh(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(hd).map(vd)}}function $v(c){if(!C3(c))throw new t("The watch runner returned an invalid hierarchy; reconnect the runner.");return zR({updatedAt:c.timestamp,hierarchy:hd(c.root)?vd(c.root):{},packageName:c.bundleId??"",screenWidth:c.screenWidth,screenHeight:c.screenHeight,screenScale:c.screenScale})}class yd{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 To=new yd;var Cn=Ft(Up());var gd=new Map;function tD(c){let d=gd.get(c);if(!d)d=new Yn,gd.set(c,d);return d}var Uh=1500;async function bd(c,{deadline:d,signal:g},R){if(c.deviceId===void 0)return R();o(g);let A=d-c.timer.now();if(A<=0)throw Error("Hierarchy fallback deadline exhausted before the dump lock was free");let C=tD(c.deviceId).acquire(),D;try{D=await l(C,{timer:c.timer,timeoutMs:A,signal:g,label:"Hierarchy fallback dump lock wait"})}catch(T){throw C.then((k)=>k()),T}try{return await R()}finally{D()}}function Sd(c,d){let g=wt(d??c.bounds);return JSON.stringify([c.package,c.class,xl(c,"resource-id")??"",xl(c,"text")??"",xl(c,"content-desc")??"",g?[g.left,g.top,g.right,g.bottom]:null])}function Dn(c,d,g){return c.flatMap((R)=>{let A=Dn(R.node??[],d,g),C=R.$,D=wt(C?.bounds);if(!C||g!==void 0&&C.package!==g||!D||D.right<=D.left||D.bottom<=D.top)return A;let T={...C,"hierarchy-source":"uiautomator"},k={$:T,bounds:D,...A.length?{node:A}:{}};if(delete T["view-id"],delete T["unique-id"],delete T.actions,d.has(Sd(T,k.bounds)))return A;return[k]})}function $h(c,d,g){let R=new K,A=new Set(R.flattenViewHierarchy(c,{includeWindows:!0}).map((T)=>Sd(T.element,T.element.bounds))),C=Dn(d,A,g);if(!C.length)return c;let D={...c,packageName:g,hierarchy:{node:{$:{},node:[...R.extractRootNodes(c),...C]}},sources:[...new Set([...c.sources??["control-proxy"],"uiautomator"])],fresh:!1};return delete D.frameContext,delete D.receivedAt,delete D.updatedAt,D}async function $W(c,d,g,R){if(o(R),d.timer.now()>=g)return c;let A=Rd(d.idGenerator),C=Ad(d,{deadline:g,signal:R});try{let D=await d.adb.getForegroundApp(R,g-d.timer.now());if(!D)return c;if(c.packageName!==void 0&&c.packageName!==D.packageName)return c;e.warn(`[HierarchyFallback] Supplementing incomplete CtrlProxy hierarchy (ctrlProxyIncompleteReason=${c.ctrlProxyIncompleteReason??"unknown"})`);let T=await bd(d,{deadline:g,signal:R},async()=>(await C(["shell","uiautomator","dump",A]),C(["shell","cat",A])));return o(R),await Wh(c,T.stdout,D,{deps:d,bound:{deadline:g,signal:R}})}catch(D){return o(R),e.debug("[HierarchyFallback] Could not supplement incomplete CtrlProxy hierarchy",D),c}finally{await wd(d,A,g,R)}}async function wd(c,d,g,R){let A=c.adb.execute(["shell","rm","-f",d],{timeoutMs:Uh,signal:new AbortController().signal,noRetry:!0}).catch((D)=>{e.debug("[HierarchyFallback] Could not remove temporary dump",D)}),C=g-c.timer.now();if(R?.aborted||C<=0){o(R);return}try{await l(A,{timer:c.timer,timeoutMs:C,signal:R,label:"Hierarchy fallback cleanup wait"})}catch(D){e.debug("[HierarchyFallback] Stopped waiting for temporary dump cleanup",D)}o(R)}function Rd(c=B){return`/data/local/tmp/automobile-hierarchy-${c.next()}.xml`}async function Wh(c,d,g,{deps:R,bound:A}){let{deadline:C,signal:D}=A,k=(await Cn.parseStringPromise(d,{explicitArray:!0})).hierarchy?.node;if(!Array.isArray(k)||R.timer.now()>=C)return c;let M=await R.adb.getForegroundApp(D,C-R.timer.now());if(o(D),M?.packageName!==g.packageName||M?.userId!==g.userId||R.timer.now()>=C)return c;return $h(c,k,g.packageName)}function Ad(c,{deadline:d,signal:g}){return async(R)=>{o(g);let A=d-c.timer.now();if(A<=0)throw Error("Hierarchy fallback deadline exhausted");return c.adb.execute(R,{timeoutMs:A,signal:g,noRetry:!0,maxBuffer:4194304})}}function Gh(c){let d=new Set,g=(R)=>{let A=R.$?.package;if(typeof A==="string"&&A)d.add(A);(R.node??[]).forEach(g)};return c.forEach(g),d.size===1?[...d][0]:void 0}function Pd(c,d){return c.every((g)=>{let R=g.bounds;return(!R||R.left>=0&&R.top>=0&&R.right<=d.width&&R.bottom<=d.height)&&Pd(g.node??[],d)})}function Kh(c){let d=Uk(c,{current:!0});return d.length?d:Jg(c)}async function zh(c,d){let g=Kh((await d(["shell","dumpsys","display"])).stdout),R=g.find((C)=>C.logicalId===String(c));if(R&&Die(R))throw new St(c,{uniqueId:R.uniqueId,ownerPackage:R.ownerPackage});let A=R?.sizePx;if(!A||A.width<=0||A.height<=0)throw new t(`Display ${c} has no readable size in dumpsys display`);return{size:A,defaultSize:g.find((C)=>C.logicalId==="0")?.sizePx}}function jh(c,d,{size:g,defaultSize:R}){let A=`${g.width}x${g.height}`;if(!Pd(c,g))return`UIAutomator dump does not fit display ${d} (${A}); this Android release likely ignores --display`;if(!c.some(({bounds:D})=>D?.left===0&&D.top===0&&D.right===g.width&&D.bottom===g.height))return`UIAutomator dump has no window spanning display ${d} (${A}), so it cannot be shown to come from that display`;if(!R||R.width===g.width&&R.height===g.height)return`Display ${d} (${A}) cannot be told apart from the default display by size, so a UIAutomator dump cannot be shown to come from it`;return}async function Id(c,d,g,R){let A=Rd(d.idGenerator),C=Ad(d,{deadline:g,signal:R});try{let D=await zh(c,C),{size:T}=D,k=await bd(d,{deadline:g,signal:R},async()=>(await C(["shell","uiautomator","dump","--display",String(c),A]),C(["shell","cat",A]))),M=await Cn.parseStringPromise(k.stdout,{explicitArray:!0});o(R);let F=Dn(M.hierarchy?.node??[],new Set);if(!F.length||d.timer.now()>=g)throw new t(`UIAutomator returned no hierarchy for display ${c}`);let V=jh(F,c,D);if(V)throw new t(V);let W=Gh(F);return{hierarchy:{node:F.length===1?F[0]:{$:{},node:F}},displayId:c,screenWidth:T.width,screenHeight:T.height,...W?{packageName:W}:{},sources:["uiautomator"],fresh:!1}}catch(D){if(o(R),D instanceof St)throw D;throw u(D,`Failed to read display ${c} with UIAutomator`)}finally{await wd(d,A,g,R)}}class Tn{hierarchy;sync;visible;settle;constructor(c,d,g,R){this.hierarchy=c;this.sync=d;this.visible=g;this.settle=R}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 Bt extends t{}class xn{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,g){let R,A=!1,C=()=>{if(R!==void 0)c.clearTimeout(R),R=void 0},D=()=>{if(A)return;C(),R=c.setTimeout(()=>{if(R=void 0,this.remainingMs()>0){D();return}A=!0,T(),d()},this.remainingMs()),g?.(R)},T=this.onChange(D);return D(),()=>{A=!0,T(),C()}}}async function qh(c,d,g){let R=v.create(c),[A,C]=await Promise.allSettled([R.execute(["shell","cmd","package","path","android"],{timeoutMs:g,noRetry:!0,signal:d}),R.execute(["shell","settings","get","secure","accessibility_enabled"],{timeoutMs:g,noRetry:!0,signal:d})]);d.throwIfAborted();let D=[],T=[];if(A.status==="rejected"||!A.value.stdout.includes("package:"))D.push("package"),T.push(A.status==="rejected"?`package: ${ue(A.reason)}`:`package: ${ue(A.value.stdout||A.value.stderr)}`);if(C.status==="rejected"||Al(`${C.value.stdout}
|
|
10
|
+
${C.value.stderr}`))D.push("settings"),T.push(C.status==="rejected"?`settings: ${ue(C.reason)}`:`settings: ${ue(C.value.stdout||C.value.stderr)}`);return{ready:D.length===0,...D.length>0?{unavailableResources:D}:{},...T.length>0?{diagnostic:T.join("; ")}:{}}}function Cd(c){return ue(c).replace(/\s+/g," ").trim()||"empty"}async function Xh(c,d){let g=v.create(c),R=v.create(),A={timeoutMs:Pt,noRetry:!0,signal:d},[C,D,T]=await Promise.allSettled([g.execute(["shell","getprop","sys.boot_completed"],A),R.execute(["devices","-l"],A),R.execute(["-s",c.deviceId,"get-state"],A)]),k=(M)=>M.status==="fulfilled"?Cd(M.value.stdout||M.value.stderr):`unavailable (${Cd(r(M.reason))})`;return{sysBootCompleted:k(C),adbDevices:k(D),emulatorQemuHealth:k(T)}}function UW(c=i){return new DL({timer:c,getAndroidFrameworkReadiness:qh,getAndroidManager:(d)=>le.getInstance(d),getAndroidClient:(d)=>E.getInstance(d),getIosManager:(d)=>ve.getInstance(d),getIosClient:(d,g)=>x.getInstance(d,g),checkIosOverride:xb,awaitIosStartupMaintenance:()=>ve.awaitStartupOrphanRunnerReap(),getAndroidRunnerConnectDiagnostic:async(d,g)=>{let R=v.create(d),[A,C]=await Promise.all([R.getDeviceLock(g),R.listUsers(g)]),D=C.find((T)=>T.profileType==="primary"||T.userId===0);return{deviceLock:A,primaryUserStartState:D?.startState}},getAndroidRunnerHealthDiagnostic:Xh})}function En(c){return c.platform==="ios"?x.getExistingInstance(c.deviceId):E.getExistingInstance(c.deviceId)}var Yh={async awaitTransition(c,d){return w.devicePool()?.waitForAssignmentTransition(c.deviceId,d)??!1},canStart(c){let d=w.devicePool();if(!d)return!1;let g=d.getDevice(c.deviceId);return!N$(po(c.platform,c.deviceId))&&g?.platform===c.platform&&g.name===c.name&&Ar(g)&&!O(g)&&d.isSafeForObservationServiceStart(c.deviceId)}},Jh={available:()=>w.devicePoolWrites()!==void 0,isPooled:(c)=>Boolean(w.devicePool()?.getDevice(c.deviceId)),ensurePooled:async(c)=>{await w.devicePoolWrites()?.pickUpRunningDevice(c)}},Qh=1e4,Dd=8,Zh=60000,ev=300000;class xd{options;queueSnapshots=new Map;flights=new nt;pickupFlights=new nt;unpooledPickupAt=new Map;poolPickup;timer;guard;constructor(c={}){this.options=c;this.timer=c.timer??i,this.guard=c.ownershipGuard??Yh,this.poolPickup=c.poolPickup??Jh}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=po(c.device.platform,c.device.deviceId),g=this.queueSnapshotFor(d),R=!1;try{return await l(()=>this.flights.run(d,(A)=>this.setup({request:c,flightSignal:A,snapshot:g}),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:()=>{R=!0}})}catch(A){c.signal?.throwIfAborted(),e.warn(`[observe] Hierarchy service start failed: ${r(A)}`,A);let C=R&&c.device.platform==="ios"&&this.flights.has(d);return this.rethrowStartupFailure(A,c,g,C)}finally{if(!this.flights.has(d))this.clearQueueSnapshot(d,g)}}async admit(c){let d=0;while(!this.guard.canStart(c.device)){let g=c.deadlineMs-this.timer.now();if(!this.guard.awaitTransition||g<=0||d>=Dd)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,g){return l(()=>this.guard.awaitTransition(c,g),{timer:this.timer,timeoutMs:Math.max(0,d-this.timer.now()),signal:g,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,g,R){if(!(c instanceof Ao&&c.deadlineExhausted||c instanceof Error&&c.message.startsWith("Observer hierarchy service start timed out"))||d.device.platform!=="ios")throw c;let C=g.status??this.launchQueueStatus(d.device);throw new UO(d.device.deviceId,C,{cause:c,startWindowExpired:!C&&!R})}launchQueueStatus(c){return c.platform==="ios"?(this.options.launchQueue??f$()).queueStatus(c.deviceId):void 0}async pickupIfUnpooled(c){let{device:d}=c;if(this.poolPickup.isPooled(d))return;let g=c.deadlineMs-this.timer.now();if(g<=0)throw new t("Observer device pool pickup timed out before pickup");let R=po(d.platform,d.deviceId),A=await l(()=>this.pickupFlights.run(R,async()=>{let C=this.unpooledPickupAt.get(R);if(this.poolPickup.isPooled(d)||C!==void 0&&this.timer.now()-C<Qh)return;let D;try{await this.poolPickup.ensurePooled(d)}catch(T){D=r(T),e.warn(`[observe] Device pool pickup failed: ${D}`,T)}if(!this.poolPickup.isPooled(d))this.unpooledPickupAt.set(R,this.timer.now());else this.unpooledPickupAt.delete(R);return D},c.signal),{timer:this.timer,timeoutMs:g,signal:c.signal,label:"Observer device pool pickup"});if(!this.poolPickup.isPooled(d)){if(A!==void 0)throw new t(`Device ${d.deviceId} is running but could not be added to this daemon's device pool: ${A}; 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:g,snapshot:R}=c;if(R.status=void 0,(this.options.isServiceConnected??((M)=>En(M)?.isConnected()===!0))(d.device))return!1;let A=po(d.device.platform,d.device.deviceId);if(jie(A))throw new t("service start declined: device readiness is in progress");let C=d.deadlineMs-this.timer.now();if(C<=0)throw new t("Observer hierarchy service start timed out before setup");let D=d.device.platform==="ios"?Math.max(C,this.options.iosFlightCeilingMs??Zh):C,T=this.startFlightDeadline(d,R,D),k=g?AbortSignal.any([g,T.signal]):T.signal;try{let M=this.options.readiness??UW(this.timer);return await this.ensureReadyWithTransitions(M,{device:d.device,requestedIdentity:d.device.deviceId,operationName:"observe deviceId",totalDeadlineMs:T.totalDeadlineMs,deadline:T.deadline,readinessTimeoutMs:D,signal:k,skipCtrlProxyDownload:(this.options.skipCtrlProxyDownload??(()=>N.isSkipCtrlProxyDownloadEnabled()))(),assertCanSetup:()=>{if(k.throwIfAborted(),!this.guard.canStart(d.device))throw new Bt("service start declined: ownership or pool transition changed while waiting for readiness")}}),!0}finally{T.stop(),this.clearQueueSnapshot(A,R)}}startFlightDeadline(c,d,g){let R=new AbortController,A=()=>{d.status=this.launchQueueStatus(c.device),R.abort(new t("Observer hierarchy service start timed out"))};if(c.device.platform!=="ios"){let k=this.timer.setTimeout(A,g);return{signal:R.signal,totalDeadlineMs:c.deadlineMs,deadline:void 0,stop:()=>this.timer.clearTimeout(k)}}let C=new xn(this.timer,this.timer.now()+g),D=this.followLaunchQueue(c.device,C,g),T=C.whenExpired(this.timer,A);return{signal:R.signal,totalDeadlineMs:C.deadlineMs,deadline:C,stop:()=>{T(),D()}}}followLaunchQueue(c,d,g){let R=Math.max(g,this.options.iosQueueCeilingMs??ev),C=this.timer.now()+R+g,D=(F)=>d.set(Math.min(F,C)),T=()=>D(Math.max(d.deadlineMs,this.timer.now()+R)),k=this.options.launchQueue??f$(),M=k.watchQueue(c.deviceId,{queued:T,admitted:()=>D(this.timer.now()+g),left:()=>D(this.timer.now()+g)});if(k.queueStatus(c.deviceId))T();return M}async ensureReadyWithTransitions(c,d){let g=0;while(!0){let R=Math.max(0,Mr(d)-this.timer.now());try{await l(()=>c.ensureReady({...d,readinessTimeoutMs:Math.min(R,d.readinessTimeoutMs)}),{timer:this.timer,signal:d.signal,...d.deadline?{deadline:d.deadline}:{timeoutMs:R},label:"Observer hierarchy service start"});return}catch(A){await this.awaitSetupTransition(A,d,g),g++}}}async awaitSetupTransition(c,d,g){if(!(c instanceof Bt)||!this.guard.awaitTransition||g>=Dd||d.signal?.aborted||this.timer.now()>=Mr(d))throw c;let R;try{R=await this.awaitTransition(d.device,Mr(d),d.signal)}catch(A){throw e.debug("[observe] Assignment transition wait ended before setup retry",A),c}if(!R||d.signal?.aborted||this.timer.now()>=Mr(d))throw c}}function Mr(c){return c.deadline?.deadlineMs??c.totalDeadlineMs}var Td=new WeakMap;function Ed(c){let d=Td.get(c);if(!d)d=new xd({timer:c}),Td.set(c,d);return d}var ji=15000,tv=gi(100);function rv(c,d,g){let R=d[ts];return{...l2(c.convertToViewHierarchyResult(d.hierarchy)),...R==="device"||R==="client-cache"?{[ts]:R}:{},receivedAt:g.now(),fresh:!0,...d.frameContext!==void 0?{frameContext:d.frameContext}:{}}}async function Fd(c,d,g){let R={},A=[new U,d.searchRaw===!0,d.signal],{timeoutMs:C}=g,D;if(d.observerMode){if(!c.requestHierarchySyncForObserver)throw new t("Observer hierarchy read is unavailable for this client");D=await c.requestHierarchySyncForObserver(...A,{timeoutMs:C,...d.displayId!==void 0&&d.displayId!==0?{diagnostics:R}:{},display:d.preserveDisplayState?{displayId:d.displayId,preserveDisplayState:!0}:d.displayId})}else D=await c.requestHierarchySync(...A,{timeoutMs:C,diagnostics:R,displayId:d.displayId});if(!D)iv(d,g,R);return D}function iv(c,d,g){if(c.displayId!==void 0&&c.displayId!==0&&g.runnerError?.includes("exposes no accessibility windows"))throw new Ef(g.runnerError);let R=g.failureReason??(g.runnerError?`runner error: ${g.runnerError}`:void 0),A=!c.observerMode||d.owned?`Device ${d.deviceId} hierarchy service did not answer`:`Device ${d.deviceId} has no reachable hierarchy service`;throw new t(R?`${A}: ${R}`:A)}function Od(c,d,g=!1,R){let{adbFactory:A}=d,C=d.androidClients??E;if(c.platform==="ios")return g?x.createForObservationRead(c):x.getInstance(c);return g?C.createForObservationRead(c,A,R instanceof E?R:void 0):C.getInstance(c,A)}function nv(c,d,g){if(d.syncClientFactory)return{syncClient:d.syncClientFactory(c),transient:!1,owned:!1};let R=En(c);if(!g)return{syncClient:R??Od(c,d),transient:!1,owned:!1};let A=w.devicePool(),C=A?!!O(A.getDevice(c.deviceId)):!1;if(C&&!R?.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(R?.isConnected())return{syncClient:R,transient:!1,owned:C};return{syncClient:Od(c,d,!0,R),transient:!0,owned:!1}}function Nd(c){let{device:d,dependencies:g,observerMode:R}=c;if(R&&g.observationClientResolver)return g.observationClientResolver(d);return nv(d,g,R)}async function Md(c){let{connection:d,request:g,timer:R,deadline:A,device:C}=c;return await l(()=>d.syncClient.connectForObservationRead?.()??Promise.resolve(!1),{timer:R,timeoutMs:Math.max(0,A-R.now()),signal:g.signal,label:`Observer hierarchy connection for ${C.deviceId}`})}async function ov(c){let{connection:d,request:g,timer:R,deadline:A,device:C,dependencies:D}=c;if(!d.transient||await Md(c))return!1;await d.syncClient.close?.(),d.transient=!1;let T;try{T=await(D.observationServiceStart??Ed(R)).start({device:C,deadlineMs:A,signal:g.signal})}catch(k){throw g.signal?.throwIfAborted(),new t(`Device ${C.deviceId} has no reachable hierarchy service; read tried to start the service: ${r(k)}`,{cause:k})}if(Object.assign(d,Nd({device:C,dependencies:D,observerMode:!0})),d.transient&&!await Md(c))throw new t(`Device ${C.deviceId} has no reachable hierarchy service; read started the service but could not connect`);return T}function _d(c,d,g){let R=c.convertToViewHierarchyResult(d.hierarchy),A=d.hierarchy?.updatedAt;if(typeof A==="number"&&Number.isFinite(A))R.updatedAt=A;if(R.receivedAt=g.now(),R.fresh=!0,d.frameContext!==void 0)R.frameContext=d.frameContext;return R}async function sv(c){let{device:d,dependencies:g,syncClient:R,deadline:A,request:C,timer:D,owned:T}=c,k=c.synced;if(d.platform==="ios")return rv(R,k,D);let M=_d(R,k,D);if(C.observerMode||!lM(M)||D.now()>=A)return M;let F=tv.delayForAttempt(1);if(A-D.now()>F)try{k=await l(async()=>{await D.sleep(F),C.signal?.throwIfAborted();let W=A-D.now();if(W<=0)throw new t(`Device ${d.deviceId} hierarchy retry deadline exhausted`);return Fd(R,C,{timeoutMs:W,deviceId:d.deviceId,owned:T})},{timer:D,timeoutMs:A-D.now(),signal:C.signal,label:`Device ${d.deviceId} incomplete hierarchy retry`}),M=_d(R,k,D)}catch(W){C.signal?.throwIfAborted(),e.warn("[HierarchyCapture] Incomplete CtrlProxy hierarchy retry failed",W)}if(!lM(M)||D.now()>=A)return M;let V=await $W(M,{adb:(g.adbFactory??v).create(d),timer:D,idGenerator:g.ids,deviceId:d.deviceId},A,C.signal);return woe(V,M.updatedAt),V}function av(c,{device:d,request:g,owned:R}){let A=g.displayId;return!(g.observerMode&&R)&&d.platform==="android"&&A!==void 0&&A!==0&&c instanceof Ef&&c.message.includes(`Display ${A} exposes no accessibility windows`)?A:void 0}async function cv(c,d){try{return await sv({...d,synced:await c()})}catch(g){let{device:R,dependencies:A,request:C,timer:D,deadline:T}=d;C.signal?.throwIfAborted();let k=av(g,d);if(k===void 0)throw g;try{return await Id(k,{adb:(A.adbFactory??v).create(R),timer:D,idGenerator:A.ids,deviceId:R.deviceId},T,C.signal)}catch(M){if(C.signal?.throwIfAborted(),M instanceof St)throw M;throw e.warn("[HierarchyCapture] Untracked-display UIAutomator fallback failed",M),g}}}function Pn(c,d={}){if(c.platform==="watchos"||c.platform==="tvos"||c.platform==="visionos"){let A=async(C)=>c.platform==="visionos"?LT(await BT(c.deviceId,C.signal,async()=>(await Bv(c.deviceId,C.signal)).hierarchy(C.signal,C.timeoutMs===void 0?void 0:{timeoutMs:C.timeoutMs}))):c.platform==="tvos"?qm(await(await ua(c.deviceId,C.signal)).hierarchy(C.signal)):$v(await To.require(c.deviceId).hierarchy(C.signal));return new dy("ios",{readCached:A,readFresh:A,projectVisible:(C)=>C},d.timer,d.ids)}let g=re(c.platform,"Observing the view hierarchy"),R=new Tn({getViewHierarchy:(A,C)=>(d.viewHierarchy??new Qi(c,d.adbFactory,null,{timer:d.timer})).getViewHierarchy(A,C),filterOffscreenNodes:_O},async(A)=>{let C=d.timer??i,D=A.timeoutMs??ji,T=C.now()+D;A.signal?.throwIfAborted();let k=Nd({device:c,dependencies:d,observerMode:A.observerMode===!0});try{let M=await ov({device:c,dependencies:d,connection:k,request:A,timer:C,deadline:T}),{syncClient:F,owned:V}=k,W=T-C.now();if(W<=0)throw new t(`Device ${c.deviceId} hierarchy read timed out`);let G=()=>Fd(F,A,{timeoutMs:W,deviceId:c.deviceId,owned:V}),q=await cv(()=>A.observerMode?l(G,{timer:C,timeoutMs:W,signal:A.signal,label:`Device ${c.deviceId} hierarchy read`}):G(),{device:c,dependencies:d,syncClient:F,deadline:T,timer:C,request:A,owned:V});if(!A.observerMode)return q;let X={...q};if(delete X.hierarchyServiceStarted,M)X.hierarchyServiceStarted=!0;return X}finally{if(k.transient)await k.syncClient.close?.()}},(A)=>cy(g,A,g==="ios"&&(c.displays?.panels.length??0)>1),d.settle);return new dy(g,R,d.timer,d.ids)}var dv=[{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 Bd(c,d){if(d.signal?.aborted)return{kind:"aborted",transient:!1};let g=r(c),R=dv.find(({pattern:A})=>A.test(g));return R?{kind:R.kind,transient:R.transient}:{kind:"unknown",transient:!1}}class On extends Zn{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 lv=Q({initialDelayMs:200,multiplier:2,maxDelayMs:1000});function uv(c,d){return c.transient&&!d?.aborted}async function Ld(c){let{timer:d,signal:g}=c,R=c.backoff??lv,A=c.maxAttempts??4,C=d.now()+c.budgetMs,D=0;while(!0){g?.throwIfAborted(),D++;try{return await c.read({number:D,timeoutMs:D===1?c.timeoutMs:C-d.now()})}catch(T){let k=c.classify(T),M={...k,attempts:D,exhausted:!1};if(!uv(k,g))throw c.wrap(T,M);let F=R.delayForAttempt(D),V=()=>c.wrap(T,{...M,exhausted:!0});if(D>=A||C-d.now()<=F)throw V();if(e.warn(`[SelectedDisplayRead] Retrying ${k.kind}; attempt ${D+1}`,T),await l(()=>d.sleep(F),{timer:d,signal:g,label:"Selected display read backoff"}),g?.throwIfAborted(),c.assertFenceCurrent(),C-d.now()<=0)throw V()}}}class Lt extends t{constructor(c,d){super(u(c,`Failed to capture screenshot for device ${d}`).message,{cause:c})}}async function Hd(c,d){let{request:g,panelKey:R,captureStart:A}=d;return(await Ld({...c.selectedDisplayRead,timer:c.timer,budgetMs:g.timeoutMs??ji,timeoutMs:g.timeoutMs,signal:g.signal,read:(D)=>c.hierarchyCapture.capture(D.number===1?g:{...g,timeoutMs:D.timeoutMs}),classify:(D)=>Bd(D,{signal:g.signal}),assertFenceCurrent:()=>{let D=c.deviceId;if(Ce.revision(D)!==A.revision)throw Af(A.identityRevision,Ce.identityRevision(D),Ce.currentObservedPanel(D)?.key)},wrap:(D,T)=>{let k=`Unable to read selected display "${R}": ${String(D)}`;return T.exhausted?new On(k,{cause:D,kind:T.kind,attempts:T.attempts}):new Zn(k,{cause:D})}})).hierarchy}function Vd(c,d,g){if(d instanceof Lt||d instanceof Nl||d instanceof Zn)return!0;if(!(c==="android"&&g.display!==void 0&&g.display!=="active"))return!1;return d instanceof Ef||d instanceof Ee||g.signal?.aborted===!0&&d===g.signal.reason}async function Wd(c,d){try{return(await c.capture(d)).hierarchy}catch(g){if(d.signal?.aborted||g instanceof Ef)throw g;let R=Loe(g),A=R?.message??r(g);return e.warn(`[ObserveScreen] Observer hierarchy unavailable: ${A}`,g),{hierarchy:{error:"Hierarchy service unavailable",unavailableReason:R?"runner_launch_queued":g instanceof Wg?"request_timed_out":"connection_lost",unavailableDetail:A},fresh:!1}}}class Mn{d;constructor(c){this.d=c}captureSingleDisplayData(c){let{result:d,options:g,queryOptions:R,perf:A,skipWaitForFresh:C,minTimestamp:D,signal:T,skipBackStack:k,observerMode:M,preserveDisplayState:F,capturedHierarchy:V,requestedDisplayId:W,observedAndroid:G}=c;return this.d.collectAllData(d,{queryOptions:R,perf:A,skipWaitForFresh:C,minTimestamp:D,signal:T,skipBackStack:k,readOnly:M||F||g?.skipRecompositionTracking===!0,capturedHierarchy:V,readOptions:this.d.device().platform==="android"&&g?.requireFreshExtraction?{timeoutMs:g.timeoutMs,requireFreshExtraction:g.requireFreshExtraction}:g?.timeoutMs,displayId:W??G?.logicalId??0})}resolveSingleDisplayIntent(c){let d=gc(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 gr(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:g,minTimestamp:R,signal:A,preserveDisplayState:C}=c;e.debug(`Executing observe command (skipWaitForFresh=${g}, minTimestamp=${R})`);let D=this.d.timer().now();o(A);let T=this.d.createBaseResult(),k={revision:Ce.revision(this.d.device().deviceId),identityRevision:Ce.identityRevision(this.d.device().deviceId)},M=this.d.displayBinding().resolveTarget({result:T,displayRequest:c.displayRequest,androidDisplayCache:c.androidDisplayCache,signal:A}),F=M instanceof Promise?await M:M,{explicitlyRouted:V,requestedDisplayId:W}=F,G=C&&V&&W!==void 0&&W!==0,q=mo().currentGeneration(this.d.device().deviceId);return d.serial("observe"),{...c,...F,result:T,startTime:D,captureStart:k,routedAggregateSecondary:G,cacheGeneration:q}}async failSingleDisplay(c,d){let{preserveDisplayState:g,observerMode:R,displayRequest:A,signal:C,iosLockState:D}=d;if(g){if(C?.throwIfAborted(),!R&&(A===void 0||A==="active"))return e.error("Critical error in aggregate active observation:",c),this.d.createCriticalFallback(c)}if(R||g)throw u(c,`Unable to observe device ${this.d.device().deviceId}`);if(Vd(this.d.device().platform,c,{display:A,signal:C}))throw Zk(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),Qr().update(this.d.device().deviceId,void 0,`Observation failed: ${T}`);let k=this.d.createBaseResult();if(D)Ir(k,await D);return this.d.createCriticalFallback(c,{fallback:k})}async captureSingleDisplay(c){let{options:d,result:g,perf:R,queryOptions:A,skipWaitForFresh:C,minTimestamp:D,signal:T}=c,k=this.startForegroundProbe(c),M=k.then((V)=>V?.packageName),F=await this.captureRequestedHierarchy(c);if(d?.hierarchyOnly)return await this.d.hierarchyCollector().collect(g,{queryOptions:A,perf:R,skipWaitForFresh:C,minTimestamp:D,signal:T,readOnly:!0,capturedHierarchy:F,readOptions:d.timeoutMs}),o(T),R.end(),{earlyResult:g,foregroundSnapshot:k,foregroundIdentity:M};return await this.captureSingleDisplayData({result:g,options:d,queryOptions:A,perf:R,skipWaitForFresh:C,minTimestamp:D,signal:T,skipBackStack:c.skipBackStack,observerMode:c.observerMode,preserveDisplayState:c.preserveDisplayState,capturedHierarchy:F,requestedDisplayId:c.requestedDisplayId,observedAndroid:c.observedAndroid}),{earlyResult:void 0,foregroundSnapshot:k,foregroundIdentity:M}}startForegroundProbe(c){let{options:d,signal:g,observerMode:R,routedAggregateSecondary:A,requestedDisplayId:C}=c;return!d?.hierarchyOnly&&this.d.device().platform==="android"&&(!R||A)?this.d.deviceStateCollector().collectForegroundSnapshot(g,{displayId:C}):Promise.resolve(null)}buildHierarchyCaptureRequest(c){let{options:d,observerMode:g,preserveDisplayState:R,minTimestamp:A,signal:C}=c;return{freshness:c.requestedDisplayId!==void 0&&d?.freshness==="cached-ok"?"fresh":d?.freshness??"fresh",observerMode:g,...R?{preserveDisplayState:!0}:{},minTimestamp:A>0?A:void 0,signal:C,timeoutMs:d?.timeoutMs,displayId:c.requestedDisplayId}}async captureRequestedHierarchy(c){let{options:d,observerMode:g,requestedDisplayId:R,requestedPanel:A,captureStart:C}=c,D=this.buildHierarchyCaptureRequest(c);if(g)return await Wd(this.d.hierarchyCapture(),D);if(R!==void 0)return await Hd({selectedDisplayRead:this.d.selectedDisplayRead(),timer:this.d.timer(),hierarchyCapture:this.d.hierarchyCapture(),deviceId:this.d.device().deviceId},{request:D,panelKey:A?.key,captureStart:C});if((d?.freshness||d?.hierarchyOnly)&&!(this.d.device().platform==="android"&&d.requireFreshExtraction))try{return(await this.d.hierarchyCapture().capture(D)).hierarchy}catch(T){e.warn(`[ObserveScreen] Freshness capture failed; collecting hierarchy: ${T}`)}return}}function pv(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 mv(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,g=d&&we(d).class;if(typeof g==="string"&&g.startsWith("android."))return!0;return!1}class _n{validate(c,d){let g=pv(d),R=mv(d);if(c==="android"&&g&&!R)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"&&R&&!g)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 fv(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 Gd(c,d,g,R){if(!c.viewHierarchy?.hierarchy)return!0;let A=R.validate(d,c.viewHierarchy);if(A.valid)return!0;return e.error(`[observe] Platform mismatch: device ${g} is ${d} but received hierarchy from other platform. Discarding stale data to prevent cross-platform contamination.`),fv(c),c.error=A.error,!1}var hv="androidx.car.app.activity.CarAppActivity",Kd="com.google.android.apps.automotive.templates.host",qL=`${Kd}:id/`;function vv(c){return c["resource-id"]??c.$?.["resource-id"]}function yv(c){let d=[...ly(c)];for(let g=d.pop();g;g=d.pop()){let R=vv(g);if(typeof R==="string"&&R.startsWith(qL))return!0;d.push(...Ea(g))}return!1}function VL(c){if(yv(c.viewHierarchy?.hierarchy?.node))return{kind:"carAppLibrary",hostPackage:Kd};return c.activeWindow?.activityName===hv?{kind:"carAppLibrary"}:void 0}function zd(c){let d=c.automotive;if(!d)return;let g=VL(c);if(g)d.hostRenderedUi=g;else delete d.hostRenderedUi}class Fn{d;constructor(c){this.d=c}async reconcileSingleDisplay(c,d){let{result:g,signal:R}=c,A=jd(g),C=await d.foregroundSnapshot,D,T=()=>(D??=this.d.isConfirmedFrameworkErrorDialog(g.viewHierarchy,R),D);if(await this.recoverInitialWindowMismatch(c,d,T))D=void 0;this.adoptSampledPrimaryActivity(c,C),this.attributeRoutedAggregateSecondary(c,C);let M=Gd(g,re(this.d.device().platform,"Observing the view hierarchy"),this.d.device().deviceId,this.d.platformValidator()),F=await this.resolvePostCaptureForeground(c);if(await this.verifyCachedHierarchyIfRequested(c,F),g.automotive&&jd(g)!==A)await this.d.deviceStateCollector().refreshAutomotiveForegroundActivity(g,R);else zd(g);let V=await this.bindFinalSingleDisplay(c);return this.attachOtherDisplays(g),{sampledForeground:C,postCaptureForeground:F,hierarchyPlatformValid:M,getConfirmedFrameworkErrorDialog:T,recordProvenance:V}}async recoverInitialWindowMismatch(c,d,g){let{options:R,result:A,startTime:C,minTimestamp:D,signal:T,skipBackStack:k}=c;if(!this.shouldRecoverWrongWindow(c))return!1;let M=await this.d.windowIdentity().resolveWindowIdentityMismatch(A,d.foregroundIdentity,{postCaptureForeground:{sampled:!1,identity:void 0,activityAttributionMismatch:!1},getConfirmedFrameworkErrorDialog:g,minTimestamp:D,signal:T}),F=Math.min(500,(R?.timeoutMs??ji)-(this.d.timer().now()-C));if(!M||F<=0)return!1;return await this.d.staleRecovery().refreshKnownStaleHierarchy(A,M.foreground,R,{remainingMs:F,sideSamples:{skipBackStack:k,displayId:c.requestedDisplayId??c.observedAndroid?.logicalId??0}}),!0}shouldRecoverWrongWindow(c){let{options:d,observerMode:g,preserveDisplayState:R,explicitlyRouted:A}=c;return this.d.device().platform==="android"&&!g&&!R&&!A&&!d?.skipRecompositionTracking&&!d?.requireFreshExtraction&&!d?.skipStaleWindowRecovery}adoptSampledPrimaryActivity(c,d){let{result:g}=c;if(d===null||!yc(c,d))return;if(d.packageName===g.viewHierarchy?.packageName&&d.activityName&&g.activeWindow)g.activeWindow={...g.activeWindow,appId:d.packageName,activityName:d.activityName}}attributeRoutedAggregateSecondary(c,d){if(!c.routedAggregateSecondary)return;let{result:g}=c,R=d?.packageName??g.viewHierarchy?.packageName;g.activeWindow=R?{appId:R,activityName:d?.activityName??"",layoutSeqSum:0}:void 0}async resolvePostCaptureForeground(c){let{result:d,signal:g,observerMode:R,preserveDisplayState:A,explicitlyRouted:C}=c;if(C)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1,displayId:c.requestedDisplayId};if(R)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};return await this.d.reconcileActiveWindowAttribution(d,{signal:g,readOnly:A})}async verifyCachedHierarchyIfRequested(c,d){let{options:g,result:R,signal:A,startTime:C,skipBackStack:D}=c;if(!g?.verifyCachedHierarchy||d.activityAttributionMismatch)return;await this.d.staleRecovery().verifyCachedAndroidHierarchy(R,{signal:A,remainingMs:Math.min(500,(g.timeoutMs??ji)-(this.d.timer().now()-C)),eligible:!c.observerMode&&!c.preserveDisplayState&&!c.explicitlyRouted,sideSamples:{skipBackStack:D,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((g)=>g.key!==c.display.key).map((g)=>gv(g))}}function gv(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 jd(c){return`${c.activeWindow?.appId??""}/${c.activeWindow?.activityName??""}`}import{AsyncLocalStorage as bv}from"async_hooks";var Nn=new bv;function Km(c){return Nn.run(new WeakSet,c)}function qd(c){if(c.viewHierarchy)Nn.getStore()?.add(c.viewHierarchy);return c}function Gm(c){return Nn.getStore()?.has(c)??!1}function Xd(c){return c?.[ts]==="device"}var Sv=5000,wv=1000,Rv=30000;function Yd(){return $e(h.OBSERVE_PERF_SNAPSHOT)}function Jd(){let c=ep(h.OBSERVE_PERF_WINDOW_MS);if(c===void 0)return Sv;return Math.min(Rv,Math.max(wv,Math.round(c)))}async function Qd(c,d,g){if(!Yd())return;let R=c.activeWindow?.appId;if(!R){e.debug("[PerfSnapshot] Skipping snapshot, no active app");return}let A=d.platform;if(!dr(A)){e.debug(`[PerfSnapshot] Skipping snapshot, no perf sampling on ${A}`);return}try{let{getPerformanceMonitor:C,getLastStartupTimingMs:D}=await import("./chunk-bvranw3g.js");C().requestPerfWindow(d.deviceId,R,A);let k=Tj().snapshot(d.deviceId,g.now(),Jd());k.startup=D(d.deviceId,R),c.perfSnapshot=k}catch(C){e.warn(`[PerfSnapshot] Failed to attach performance snapshot: ${C}`)}}var Br="androidx.wear.tiles.action.BIND_TILE_PROVIDER";class Bn 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 ${Br}.`));this.component=c;this.available=d}}var Av=1e4,Pv=/^([A-Za-z0-9_.]+)\/([\p{L}\p{N}\p{M}\p{Pc}\p{Sc}.]+)$/u;function Zd(c){let d=new Set;return c.split(/\r?\n/).map((g)=>Pv.exec(g.trim())).filter((g)=>g!==null).map(([,g,R])=>{let A=R.startsWith(".")?`${g}${R}`:R;return{component:`${g}/${A}`,packageName:g,className:A}}).filter((g)=>{if(d.has(g.component))return!1;return d.add(g.component),!0})}function Iv(c){let d=Zd(c);return d.length===1?d[0].component:c.trim()}class D3{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 ${Br}`,{timeoutMs:Av,signal:c});return Zd(d.stdout)}catch(d){throw u(d,"Failed to list Wear tile providers")}}}async function el(c,d,g){let R=Iv(d),A=await c.list(g),C=A.find((D)=>D.component===R);if(!C)throw new Bn(d,A.map((D)=>D.component));return C}var HW="com.google.android.wearable.app.DEBUG_SURFACE",Cv="com.google.android.wearable.app.DEBUG_SYSUI",tt="com.google.android.clockwork.sysui",Dv=3000,Tv=1e4,lre=["addTile","showTile","removeTile","listTileProviders"],O3=/^[A-Za-z][\w.]*\/\.?[A-Za-z_][\w.]*$/,ure=["added","removed","showRequested","providerNotFound","missingComponent","indexRequired","unrecognizedOperation","unknown"],xv=/^Broadcast completed: result=(-?\d+)(?:, data="(.*)")?\s*$/m,kv=/^Index=\[(\d+)\]$/,Ev=/^Unrecognized operation (.+)$/;function M3(c){let d=xv.exec(c.replace(/\r\n/g,`
|
|
11
|
+
`));if(!d)return{code:null};return{code:Number(d[1]),...d[2]!==void 0?{data:d[2]}:{}}}function Ln(c,d){let{data:g}=d,R=g===void 0?null:Ev.exec(g);if(R)return{...d,outcome:"unrecognizedOperation",operation:R[1]};let A=Mv.find((C)=>g!==void 0&&C.matches(g));if(A)return{...d,outcome:A.outcome};return d.code===1?{...d,..._v[c](g)}:Ov(d)}function Ov(c){return{...c,outcome:"unknown"}}var Mv=[{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")}],_v={"add-tile":(c)=>{let d=c===void 0?null:kv.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"})},Fv={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 Lr(c){return Fv[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 N3{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 g=await this.addTileBroadcast(c,d),R=g.outcome==="added";return{success:R,action:"addTile",requested:{component:c},broadcastResult:g,...g.index!==void 0?{index:g.index}:{},verified:!1,message:R?`The tile is in the carousel at index ${g.index} (add-tile is idempotent: it may already have been there). Not observed; use showTile to confirm it renders.`:"The tile was not added.",...R?{}:{reason:Lr(g)}}}async removeTile(c,d){let g=Ln("remove-tile",await this.broadcast(HW,"remove-tile",`--ecn component ${c}`,d)),R=g.outcome==="removed";return{success:R,action:"removeTile",requested:{component:c},broadcastResult:g,verified:!1,message:R?"The tile was removed or was not present; the broadcast does not say which. Not observed.":"The tile was not removed.",...R?{}:{reason:Lr(g)}}}async showTile(c,d){let g="component"in c?{component:c.component}:{index:c.index},R,A;if("component"in c){if(R=await this.addTileBroadcast(c.component,d),R.outcome!=="added"||R.index===void 0)return{success:!1,action:"showTile",requested:g,broadcastResult:R,indexResolution:R,verified:!1,message:"The tile index could not be resolved, so nothing was shown.",reason:Lr(R)};A=R.index}else A=c.index;let C=Ln("show-tile",await this.broadcast(Cv,"show-tile",`--ei index ${A}`,d)),D={action:"showTile",requested:g,broadcastResult:C,...R?{indexResolution:R}:{},index:A};if(C.outcome!=="showRequested")return{...D,success:!1,verified:!1,message:"The tile was not shown.",reason:Lr(C)};await this.deps.timer.sleep(Dv),d?.throwIfAborted();let T=await this.deps.observe(d),k=Nv(T);return{...D,success:k===void 0,verified:k===void 0,message:k===void 0?`The show-tile broadcast was accepted for index ${A}; 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 ${A}, but the observe did not confirm a tile.`,...k!==void 0?{reason:k}:{}}}async addTileBroadcast(c,d){return await el(this.deps.tileProviders,c,d),Ln("add-tile",await this.broadcast(HW,"add-tile",`--ecn component ${c}`,d))}async broadcast(c,d,g,R){let A=`shell am broadcast -a ${c} --es operation ${d} ${g}`;try{R?.throwIfAborted();let C=await this.deps.adb.executeCommand(A,{timeoutMs:Tv,noRetry:!0,signal:R});return M3(C.stdout)}catch(C){throw u(C,`Failed to run adb ${A}`)}}}function Nv(c){if(c.appId!==tt)return`The foreground after the broadcast is ${c.appId??"unknown"}, not the Wear system UI (${tt}).`;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 tl(c){let{activeWindow:d,viewHierarchy:g}=c;if(!d?.appId||!g)return;if(d.appId!==tt)return"app";if(d.activityName?.startsWith(`${tt}.experiences.globallauncher.`))return"launcher";if(d.activityName!==`${tt}.mainui.activity.SysUiActivity`)return;let R=new js,A=!1,C=!1;for(let D of R.extractRootNodes(g))R.traverseNode(D,(T)=>{let k=we(T)["resource-id"];A||=k===`${tt}:id/carousel_tile_container`,C||=k==="watch_face_fallthrough"||k===`${tt}:id/watchface_overlay`});return A?"tile":C?"watchface":void 0}class Hn{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)this.buildElementsWithPanelSpace(d,d.viewHierarchy)}buildElementsWithPanelSpace(c,d){let g=this.d.device(),R=this.isAndroidXr(),A=XD(c,R),C=wt(A?.bounds);if(A?.id!==void 0&&Number.isInteger(A.id)&&C)c.xrPanelSpace={windowId:A.id,bounds:C};else delete c.xrPanelSpace;c.elements=this.d.elementsBuilder().build(d,re(g.platform,"Observing the view hierarchy"),R,c)}isAndroidXr(){return this.d.device().platform==="android"&&(this.d.isAndroidXr?.()??!1)}refreshXrPanelSpace(c){if(!c.viewHierarchy||!c.elements||!this.isAndroidXr())return;if(!XD(c,!0)&&!c.xrPanelSpace)return;this.buildElementsWithPanelSpace(c,c.viewHierarchy)}async enrichSingleDisplay(c){if(this.enrichSingleDisplayElements({result:c.result}),this.d.device().formFactor==="watch"){let d=tl(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:g,perf:R,signal:A,screenshotMode:C,requestedDisplayId:D}=c;if(C==="none"){g.screenshotCaptureAttempted=!1;return}let T=D,k=Un(d?.screenshotOptions);if(g.screenshotCaptureAttempted=!0,Wn(g,k),C==="settled")g.screenshotOrientation=this.d.platformTraits().settledScreenshotOrientation(),await this.d.captureSettledScreenshot(g,R,A,{strict:d?.screenshot==="settled",displayId:T,screenshotOptions:d?.screenshotOptions});else if(N.getAccessibilityAuditConfig())await this.d.screenshotRecorder().capture(g.observationId,{perf:R,signal:A,displayId:T,capture:k});else this.d.screenshotRecorder().start(g.observationId,{perf:R,signal:A,displayId:T,capture:k})}async runSingleDisplayAudits(c){let{options:d,result:g,perf:R,signal:A,observerMode:C}=c;if(!d?.skipRecompositionTracking&&!C)await this.d.processRecomposition(g,R);if(!d?.skipPerformanceAudit&&!C)await this.d.performanceAuditor().run(g,R);if(!d?.skipAccessibilityAudit&&!C)await this.d.accessibilityAuditor().run(g,R);if(!C)await this.d.accessibilityStateDetector().run(g,R,A);if(!C)await this.attachPredictionsIfEnabled(g)}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:g,startTime:R,skipBackStack:A,observerMode:C}=c;if(g.end(),!C)await Qd(d,this.d.device(),this.d.timer());if(wc(d,g),d.screenshotPath)d.screenshotExpiresAt=await this.d.pathProtection().protect(d.screenshotPath);if(this.d.device().platform==="android"&&!C&&A)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()-R}ms`),this.d.platformTraits().grantsObservationRead(d)?qd(d):d}attachPredictions(c,d){if(d)c.predictions=d}}function Un(c){return c?.hidePrototypes===!0?{hidePrototypes:!0}:void 0}function Wn(c,d){if(d)c.screenshotIncludesPrototype=!1;else delete c.screenshotIncludesPrototype}function pe(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((g)=>g.message).join("; ")}function Tc(c,d){let g=Number.isInteger(c)&&c>=0&&c<=3;if(!d)return g?c:void 0;let R=[d.width,d.height].every((D)=>Number.isFinite(D)&&D>0),A=d.width<d.height;if(g&&!(R&&A&&(c===1||c===3)))return c;return R?A?0:1:void 0}var Re=new Set(["com.android.systemui"]),nl="com.android.systemui",Lv=3;function rl(c){return c.packageName===nl||c.type===Lv}function Vv(c,d){let g=c.bounds;if(!g)return!1;let R=g.bottom-g.top;if(d&&d>0)return R>d/2;return R>400}function il(c){let d=c?.windows;if(!d||d.length===0)return"none";let g=d.find((A)=>A.isFocused===!0);if(g)return rl(g)?"focused":"none";let R=d.reduce((A,C)=>(C.windowLayer??0)>(A.windowLayer??0)?C:A);return rl(R)&&Vv(R,c?.screenHeight)?"topmost-suspect":"none"}function Gn(c){let d=c.split("/")[1]??"";return d.startsWith("android.widget.")||d.startsWith("android.view.")||d.endsWith("DecorView")}function Ht(c){let d=c?.foregroundActivity;return typeof d==="string"&&!Gn(d)}function ol(c,d){if(d===void 0)return!0;if(!Ht(c))return!1;let[g,R=""]=(c.foregroundActivity??"").split("/"),A=R.startsWith(".")?g+R:R;return d.appId===g&&d.activityName===A}function Wv(c,d){return c===d||c.startsWith(`${d}.`)}function Rt(c){let d=c.viewHierarchy?.packageName,g=c.backStack;if(!d||g?.source!=="adb")return;let R=g.currentActivity?.name;if(!R)return;if(Wv(R,d))return{packageName:d,activityName:R};let A=g.currentActivity?.taskId;return g.tasks.some((D)=>D.id===A&&D.packageName===d)===!0?{packageName:d,activityName:R}:void 0}function Kn(c,d,g){return!Ht(c.viewHierarchy)||d.activityName!==g.activityName}function kc(c){return c?.hierarchy!==void 0&&typeof c.hierarchy==="object"&&c.hierarchy!==null&&!("error"in c.hierarchy)}class zn{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 re(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:g,readOnly:R=!1}=d;if(await this.applyFocusedSystemUiOverlay(c,g))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let A=c.activeWindow,C=c.viewHierarchy?.packageName;if(C===void 0||A===void 0||Re.has(C))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let D=Rt(c);if(D){let k=await this.reconcileAgainstBackStack(c,A,D,{signal:g,readOnly:R});if(k)return k}if(A.appId===C)return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let T=await this.deviceStateCollector.collectForegroundIdentity(g);if(T===C)c.activeWindow={...A,appId:C,activityName:""};return{sampled:!0,identity:T,activityAttributionMismatch:!1}}async reconcileAgainstBackStack(c,d,g,R={}){let{signal:A,readOnly:C=!1}=R,D=!Ht(c.viewHierarchy);if(!Kn(c,d,g))return;if(!await this.recaptureHierarchyForBackStackAttribution(c,g,A)){if(D&&d.activityName!=="")c.activeWindow={...d,activityName:""};return{sampled:!1,identity:void 0,activityAttributionMismatch:!0}}let k=await this.refreshRecaptureSideSamples(c,d,g,{bootstrapAttribution:D,signal:A,readOnly:C});if(c.activeWindow=k,await this.applyFocusedSystemUiOverlay(c,A,!0))return{sampled:!1,identity:void 0,activityAttributionMismatch:!1};let M={...k,appId:g.packageName,activityName:g.activityName};if(c.notificationPermissionDetected)M.type="notification_permission_dialog";else delete M.type;return c.activeWindow=M,{sampled:!1,identity:void 0,activityAttributionMismatch:!1}}async applyFocusedSystemUiOverlay(c,d,g=!1){if(this.device.platform!=="android")return!1;let R=c.activeWindow;if(R===void 0)return!1;let A=il(c.viewHierarchy);if(A==="none")return!1;if(A==="focused")return this.mirrorFocusedSystemUiOverlay(c,R),!0;return this.applyFallbackSystemUiOverlay(c,R,g,d)}async applyFallbackSystemUiOverlay(c,d,g,R){if(g)return this.confirmFallbackOverlayFocus(c,d,R);return this.resolveFallbackOverlayWithRecapture(c,d,R)}async confirmFallbackOverlayFocus(c,d,g){if(!await this.deviceStateCollector.collectFocusedSystemUiSurface(g))return!1;return this.mirrorFocusedSystemUiOverlay(c,d),!0}async resolveFallbackOverlayWithRecapture(c,d,g,R=1){if(!await this.recaptureHierarchyForSystemUiOverlay(c,g))return this.confirmFallbackOverlayFocus(c,d,g);let A=c.activeWindow??d,C=il(c.viewHierarchy);if(C==="none")return!1;if(C==="focused")return this.mirrorFocusedSystemUiOverlay(c,A),!0;if(await this.deviceStateCollector.collectFocusedSystemUiSurface(g))return this.mirrorFocusedSystemUiOverlay(c,A),!0;if(R>0)return this.resolveFallbackOverlayWithRecapture(c,A,g,R-1);return!1}mirrorFocusedSystemUiOverlay(c,d){let g={...d,appId:nl,activityName:"",systemOverlay:!0};delete g.type,c.activeWindow=g}async recaptureHierarchyForSystemUiOverlay(c,d){let g=this.resolveObservationTimestampMs(c);if(g===void 0)return e.debug("[OBSERVE] Skipping SystemUI-overlay recapture without a device capture timestamp"),!1;let R=g+1,A;try{A=await this.viewHierarchy.getViewHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:R,signal:d})}catch(C){return e.debug(`[OBSERVE] SystemUI-overlay recapture failed; preserving original hierarchy: ${C}`),!1}if(!A||!kc(A)||A.fresh!==!0||!this.platformValidator.validate(this.hierarchyPlatform,A).valid)return!1;return await this.primeRecapturedHierarchy(c,A,d),this.applyRecapturedHierarchy(c,A),delete c.deviceLock,delete c.deviceLockUnknown,await this.deviceStateCollector.collectDeviceLock(c,d),delete c.backStack,this.recorrelateActiveWindowToRecapture(c,A),!0}recorrelateActiveWindowToRecapture(c,d){if(c.activeWindow===void 0)return;let g=this.deriveActiveWindowFromHierarchy(d);if(g===void 0)return;if(c.notificationPermissionDetected)g.type="notification_permission_dialog";c.activeWindow=g}deriveActiveWindowFromHierarchy(c){let d=c.packageName??c.foregroundActivity?.split("/")[0];if(!d)return;return{appId:d,activityName:"",layoutSeqSum:0}}async recaptureHierarchyForBackStackAttribution(c,d,g){let R=this.resolveObservationTimestampMs(c);if(R===void 0)return e.debug("[OBSERVE] Skipping back-stack recapture without a device capture timestamp"),!1;let A=R+1,C;try{C=await this.viewHierarchy.getViewHierarchy(void 0,{skipWaitForFresh:!0,minTimestamp:A,signal:g})}catch(k){return e.debug(`[OBSERVE] Attribution recapture failed; preserving original hierarchy: ${k}`),!1}if(!this.isUsableAttributionRecapture(C,d))return!1;let D={...c,backStack:void 0,errors:void 0};await this.deviceStateCollector.collectBackStack(D,new U,g);let T=Rt(D);if(!this.matchesExpectedBackStackAttribution(T,d)){for(let k of D.errors??[])pe(c,k);return!1}return await this.primeRecapturedHierarchy(c,C,g),this.applyRecapturedHierarchy(c,C),c.backStack=D.backStack,!0}async refreshRecaptureSideSamples(c,d,g,{bootstrapAttribution:R,...A}){let{signal:C,readOnly:D=!1}=A;delete c.deviceLock,delete c.deviceLockUnknown;let[T]=await Promise.all([R?this.refreshBootstrapLayoutSeqSum(c,d,g,{readOnly:D}):Promise.resolve(d),this.deviceStateCollector.collectDeviceLock(c,C)]);return T}async refreshBootstrapLayoutSeqSum(c,d,g,R={}){let{readOnly:A=!1}=R,C={...c,activeWindow:void 0,errors:void 0};await this.deviceStateCollector.collectActiveWindow(C,A);for(let M of C.errors??[])pe(c,M);let D=C.activeWindow;if(!D?.layoutSeqSum)return d;let T=D.activityName.startsWith(".")?D.appId+D.activityName:D.activityName;return D.appId===g.packageName&&T===g.activityName?{...d,layoutSeqSum:D.layoutSeqSum}:d}isUsableAttributionRecapture(c,d){if(!c)return!1;return kc(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,g){await this.dependencies.xrDisplaySize?.prime(c,d,g)}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=Tc(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 Kv(c,d){let g=c?.packageName;return d!==void 0&&!Re.has(d)&&(g===void 0?c?.ctrlProxyIncomplete===!0:Re.has(g))}function jv(c,d,g,R){return Re.has(d)||Re.has(g)||R&&ZD(c)}function Hr(c){let d=c.systemInsets.top,g=c.viewHierarchy?.hierarchy.node;if(d<=0||!g)return!1;let R=!1,A=Array.isArray(g)?[...g]:[g];while(A.length>0){let C=A.pop();if(!C)continue;if(C.bounds){if(R=!0,C.bounds.bottom>d)return!1}let D=C.node;if(D)A.push(...Array.isArray(D)?D:[D])}return R}function qv(c,d){return{foreground:d,ctrlProxyIncomplete:c?.ctrlProxyIncomplete===!0,sdkInt:c?.sdkInt,accessibilityTool:c?.accessibilityTool}}class Qn{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:g,getConfirmedFrameworkErrorDialog:R,minTimestamp:A,signal:C}){let D=await d,T=c.viewHierarchy?.packageName??c.activeWindow?.appId;if(!D||!T)return;if(jv(c.viewHierarchy,T,D,this.isOwnWindowEvidenceCurrent(c,A)))return;let k=await this.resolvePostCaptureForegroundIdentity(D,T,g,C);if(!k||k!==D||k===T)return;if(await R())return;return{observed:T,foreground:D}}isOwnWindowEvidenceCurrent(c,d){let g=this.resolveObservationTimestampMs(c);if(g===void 0||d>0&&g<d)return!1;let R=this.resolveHostReceivedAtMs(c)??g;return this.timer.now()-R<=Pb()}async attributeFocusedOwnWindowToForeground(c,d,g){let R=c.activeWindow;if(R?.appId!==vt||!ZD(c.viewHierarchy)||!this.isOwnWindowEvidenceCurrent(c,g))return;let A=await d;if(!A||A===vt||Re.has(A))return;c.activeWindow={...R,appId:A,type:R.type??_j}}async resolveStatusBarOnlyHierarchy(c,d,g,R){let A=await d,C=c.viewHierarchy,D=Hr(c);if(!Kv(C,A)&&!D)return;if(A===void 0||Re.has(A))return;let T=D?await this.confirmForegroundIdentity(g,R):await this.resolvePostCaptureForegroundIdentity(A,C?.packageName??"",g,R);if(!T||Re.has(T)||!Hr(c))return;return qv(C,T)}async confirmForegroundIdentity(c,d){if(c.sampled)return c.identity;return this.deviceStateCollector.collectForegroundIdentity(d,{displayId:c.displayId})}async resolvePostCaptureForegroundIdentity(c,d,g,R){if(g.sampled)return g.identity;if(c===d)return;return this.deviceStateCollector.collectForegroundIdentity(R,{displayId:g.displayId})}resolveHostReceivedAtMs(c){let d=c.viewHierarchy?.receivedAt;if(typeof d==="number"&&!Number.isNaN(d))return d;return}}function eo(c,d={}){let g,R=new Map;for(let C of c.split(`
|
|
12
|
+
`)){let D=C.match(/^\s*Display:\s*mDisplayId=(\d+)/);if(D){g=parseInt(D[1],10);continue}let T=C.trim(),M=T.match(/^mRotation=(\d+)/)??(T.startsWith("mDisplayFrozen=")?T.match(/\bmRotation=(\d+)\b/):null);if(!M)continue;let F=parseInt(M[1],10);if(!R.has(g))R.set(g,F)}let A=g===void 0?void 0:d.displayId??0;return R.get(A)??null}function sl(c,d={}){let g,R=new Map,A=new Set;for(let C of c.split(`
|
|
13
|
+
`)){let D=C.match(/^\s*Display:\s*mDisplayId=(\d+)/);if(D){g=Number(D[1]);continue}if(g===void 0||A.has(g))continue;let T=C.match(/\bmDisplayRotation=(?:ROTATION_(0|90|180|270)\b|\S+)/);if(T){if(T[1]!==void 0)R.set(g,Number(T[1])/90);A.add(g)}}return R.get(d.displayId??0)??null}var Xv="shell dumpsys window displays",Yv='shell dumpsys window | grep -i "mRotation="',Jv=5000,al=ie;function Qv(c,d){return sl(c,d)??eo(c,d)}async function yl(c,d={}){let g=d.timeoutMs??Jv,R=(d.displayId??0)===0,A="display 0 rotation is missing",C;try{let{stdout:T}=await c.executeCommand(Xv,{timeoutMs:g,maxBuffer:al,signal:d.signal}),k=Qv(T,d);if(k!==null||!R)return k}catch(T){if(d.signal?.aborted||T instanceof Error&&T.name==="AbortError"||!R)throw T;A="the displays subcommand failed",C=T}o(d.signal),e.debug(`[readWindowManagerRotation] Falling back to legacy WindowManager rotation: ${A}`,C);let{stdout:D}=await c.executeCommand(Yv,{timeoutMs:g,maxBuffer:al,signal:d.signal});return eo(D)}var rD="sdk-capture-identity",nD="web-snapshot-id";function Zv(c,d){if(c===rD||c===nD)return;if(c!==""&&typeof d==="object"&&d!==null&&"resource-id"in d){let g=d["resource-id"];if(typeof g==="string"&&d2.has(g))return}return d}function ty(c){let d=new WeakMap;return(g)=>{if(!g?.hierarchy)return null;let R=d.get(g);if(R!==void 0)return R;let A=null;try{A=c(JSON.stringify(g.hierarchy,Zv))}catch(C){e.warn(`[hierarchyFingerprint] Failed to fingerprint view hierarchy: ${r(C)}`)}return d.set(g,A),A}}var An=ty((c)=>Lc.generateCacheKey(c)),WL=(c,d)=>{let g=An(c),R=An(d);if(g===null||R===null)return null;return g!==R};function $t(c){let d=0;for(let g of c?.windows??[]){let R=g.prototypeMotion?.active;if(typeof R==="number"&&Number.isFinite(R)&&R>0)d+=R}return d}var WT=["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 ry="shell cmd package resolve-activity --brief -c android.intent.category.HOME -a android.intent.action.MAIN",cl=5000,iy=new Set(WT),ny=30000,oy=2000,Ur=new Map;function sy(c){let d=c.split(`
|
|
14
|
+
`).map((A)=>A.trim()).filter((A)=>A.length>0),g=d[d.length-1];if(!g)return null;let R=g.match(/^([^\s/]+)\//);return R?R[1]:null}function ay(c,d,g){if(c===void 0||c.incarnationToken!==g)return;let R=g===void 0?oy:ny;return d-c.resolvedAtMs<R?c.packageName:void 0}async function F3(c,d,g=i,{incarnationToken:R,signal:A,timeoutMs:C}={}){let D=me(A);o(D);let T=g.now(),k=Ur.get(d),M=ay(k,T,R);if(M!==void 0)return M;let F=C===void 0?cl:Math.max(1,Math.min(cl,C));try{let V=await c.executeCommand(ry,{timeoutMs:F,noRetry:!0,signal:D}),W=sy(V.stdout);if(W)Ur.set(d,{packageName:W,resolvedAtMs:g.now(),incarnationToken:R});return W}catch(V){if(D?.aborted)throw V;return e.warn(`[androidLauncherPackages] Failed to resolve configured HOME launcher package: ${r(V)}`,V),null}}function pre(c){if(c===void 0)Ur.clear();else Ur.delete(c)}function uy(c){if(!c)return!1;return iy.has(c)}async function Uv(c,d,g,{timer:R=i,...A}={}){if(!c)return!1;let{incarnationToken:C,signal:D,timeoutMs:T}=A,k=await F3(d,g,R,{incarnationToken:C,signal:D,timeoutMs:T});if(A.formFactor==="automotive"&&c==="com.android.car.mapsplaceholder")return!0;if(k)return c===k;return uy(c)}class to{device;adbFactory;timer;reader;lastUpdatedAt;constructor(c,d,g,R){this.device=c;this.adbFactory=d;this.timer=g;this.reader=R}async wait(c,d){let g=this.timer.now()+Math.max(0,c),R=null;while(this.timer.now()<g&&!d?.aborted){let A=g-this.timer.now();try{let C=await this.readFingerprint(A,d);if(C!==null&&C===R)return;R=C}catch(C){if(R=null,d?.aborted||this.timer.now()>=g){e.debug(`Quiet-tree stability read ended: ${r(C)}`);return}e.warn(`Quiet-tree stability read failed: ${r(C)}`)}if(d?.aborted)return;await this.timer.sleep(Math.min(17,Math.max(0,g-this.timer.now())))}}async readFingerprint(c,d){let g=new AbortController,R=d?AbortSignal.any([d,g.signal]):g.signal,A=this.reader??=new Qi(this.device,this.adbFactory,null,{timer:this.timer}),C=await l(()=>A.getViewHierarchy(void 0,{timeoutMs:c,requireFreshExtraction:!0,skipWaitForFresh:!0,...this.lastUpdatedAt===void 0?{}:{minTimestamp:this.lastUpdatedAt+1},signal:R}),{timer:this.timer,timeoutMs:c,signal:d,label:"Quiet-tree stability read",onTimeout:()=>g.abort()});if(!C.hierarchy.error)this.lastUpdatedAt=hn(C)??this.lastUpdatedAt;if($t(C)>0)return null;return C.fresh===!0&&!C.hierarchy.error?An(C):null}async metrics(c,d,g,R){return await this.wait(d+g-this.timer.now(),R),{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 zL=1000,mre=5000;class zT{adb;timer;quietTree;testHooks={isSystemLauncher:(c)=>this.isSystemLauncher(c)};constructor(c,d=v,g=i,R){this.adb=d.create(c),this.timer=g,this.quietTree=new to(c,d,g,R)}isSystemLauncher(c){if(!c)return!1;let d=["com.android.systemui",...WT];return c==="android"||d.some((g)=>c===g||c.startsWith(`${g}.`))}async waitForQuietTreeStability(c,d,g,R){if(!this.isSystemLauncher(c))return null;return this.quietTree.metrics(c,d,g,R)}getTouchStatus(c,d,g,R){let A=this.timer.now()-c,C=this.timer.now()-d,D=C>=g,T=!D&&A<R;return{isIdle:D,shouldContinue:T,currentElapsed:A,idleTime:C}}async getRotationStatus(c,d,g,{perf:R=new U,signal:A}={}){try{let C=await R.track("adbDumpsysWindowRotation",()=>{A?.throwIfAborted();let D=d+g-this.timer.now();return yl(this.adb,{signal:A,timeoutMs:Math.max(D,zL)})});if(C!==null){if(e.debug(`Current rotation: ${C}, target: ${c}`),C===c)return e.debug(`Rotation to ${c} complete, took ${this.timer.now()-d}ms`),{rotationComplete:!0,currentRotation:C,shouldContinue:!1};return{rotationComplete:!1,currentRotation:C,shouldContinue:this.timer.now()-d<g}}return{rotationComplete:!1,currentRotation:null,shouldContinue:this.timer.now()-d<g}}catch(C){return A?.throwIfAborted(),e.debug(`Rotation idle check failed, treating as not-yet-idle: ${C}`),{rotationComplete:!1,currentRotation:null,shouldContinue:this.timer.now()-d<g}}}async getUiStabilitySnapshot(c,d=200,g=new U){e.info(`[AwaitIdle] Measuring UI idle for ${c} with ${d}ms delay`);try{return await g.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:g})}catch(R){return e.info(`[Idle] Error measuring UI idle: ${R}`),{isStable:!1,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:null,updatedPrevSlowUiThread:null,updatedPrevFrameDeadlineMissed:null,updatedPrevTotalFrames:null,updatedFirstGfxInfoLog:!1}}}async getFrameStats(c,d,g=new U,R={}){try{let{stdout:A}=await g.track("adbGfxinfo",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{timeoutMs:R.timeoutMs,maxBuffer:ie,signal:R.signal}));if(d)e.info(`[AwaitIdle] Initial gfxinfo stdout for ${c}:
|
|
15
|
+
${A}`);return A}catch(A){return R.signal?.throwIfAborted(),e.info(`[AwaitIdle] Failed to get gfxinfo for ${c}: ${A}`),null}}parseMetrics(c){let d=this.extractMetric(c,/50th percentile:\s+(\d+(?:\.\d+)?)ms/),g=this.extractMetric(c,/90th percentile:\s+(\d+(?:\.\d+)?)ms/),R=this.extractMetric(c,/95th percentile:\s+(\d+(?:\.\d+)?)ms/),A=this.extractMetric(c,/99th percentile:\s+(\d+(?:\.\d+)?)ms/),C=this.extractMetric(c,/Total frames rendered:\s+(\d+)/),D=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=${g}ms 95th=${R}ms 99th=${A}ms TotalFrames=${C} MissedVsync=${D} SlowUI=${T} DeadlineMissed=${k}`),{percentile50th:d,percentile90th:g,percentile95th:R,percentile99th:A,totalFrames:C,missedVsync:D,slowUiThread:T,frameDeadlineMissed:k}}validateFrameData(c){return c.percentile50th!==null&&c.missedVsync!==null&&c.slowUiThread!==null}updateStabilityState(c,d){let{missedVsync:g,slowUiThread:R,frameDeadlineMissed:A,totalFrames:C}=c,D=this.calculateDeltas(c,d);return{updatedPrevMissedVsync:g,updatedPrevSlowUiThread:R,updatedPrevFrameDeadlineMissed:A,updatedPrevTotalFrames:C,deltas:D}}processFrameStatsForStability(c,d,g,{prevFrameDeadlineMissed:R,prevTotalFrames:A}){let C=this.parseMetrics(c);if(!this.validateFrameData(C))return e.info(`[AwaitIdle] No valid frame data yet: percentile50th ${C.percentile50th} && missedVsync ${C.missedVsync} && slowUiThread ${C.slowUiThread}`),{isStable:!1,noFrameData:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:d,updatedPrevSlowUiThread:g,updatedPrevFrameDeadlineMissed:R,updatedPrevTotalFrames:A};let D=this.updateStabilityState({missedVsync:C.missedVsync,slowUiThread:C.slowUiThread,frameDeadlineMissed:C.frameDeadlineMissed,totalFrames:C.totalFrames},{missedVsync:d,slowUiThread:g,frameDeadlineMissed:R,totalFrames:A}),T=this.checkStabilityCriteria(D.deltas,{percentile50th:C.percentile50th,percentile90th:C.percentile90th,percentile95th:C.percentile95th},C.totalFrames);return{isStable:T,shouldUpdateLastNonIdleTime:!T,updatedPrevMissedVsync:D.updatedPrevMissedVsync,updatedPrevSlowUiThread:D.updatedPrevSlowUiThread,updatedPrevFrameDeadlineMissed:D.updatedPrevFrameDeadlineMissed,updatedPrevTotalFrames:D.updatedPrevTotalFrames}}calculateDeltas(c,d){let g=d.missedVsync!==null&&c.missedVsync!==null?c.missedVsync-d.missedVsync:0,R=d.slowUiThread!==null&&c.slowUiThread!==null?c.slowUiThread-d.slowUiThread:0,A=d.frameDeadlineMissed!==null&&c.frameDeadlineMissed!==null?c.frameDeadlineMissed-d.frameDeadlineMissed:0,C=d.totalFrames!==null&&c.totalFrames!==null?c.totalFrames>=d.totalFrames?c.totalFrames-d.totalFrames:null:null;return e.debug(`Deltas: MissedVsync=${g} SlowUI=${R} DeadlineMissed=${A} TotalFrames=${C}`),{missedVsyncDelta:g,slowUiThreadDelta:R,frameDeadlineMissedDelta:A,totalFramesDelta:C}}checkStabilityCriteria(c,d,g){let{p50Int:R,p90Int:A,p95Int:C,shouldCheckPercentiles:D,percentilesOk:T}=this.assessPercentiles(c.totalFramesDelta,d,g),k=c.missedVsyncDelta===0&&c.slowUiThreadDelta===0&&c.frameDeadlineMissedDelta===0&&T;if(k)e.info("[AwaitIdle] UI appears stable (criteria met)");else{let M=D?`percentiles (50th=${R}, 90th=${A}, 95th=${C})`:`percentiles skipped (frames=${g??"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"}), ${M}`)}return k}assessPercentiles(c,d,g){let R=d.percentile50th!==null?Math.floor(d.percentile50th):0,A=d.percentile90th!==null?Math.floor(d.percentile90th):0,C=d.percentile95th!==null?Math.floor(d.percentile95th):0,D=5,T=c!==null&&c>0,k=g!==null&&g>=5,M=c===null||T&&k,F=!M||R<100&&A<100&&C<200;return{p50Int:R,p90Int:A,p95Int:C,shouldCheckPercentiles:M,percentilesOk:F}}async getUiStability(c,d,g,{perf:R=new U,...A}={}){let{missedVsync:C,slowUiThread:D,frameDeadlineMissed:T,totalFrames:k}=d;try{if(this.isSystemLauncher(c))return await this.quietTree.wait(A.timeoutMs??1000,A.signal),{isStable:!0,shouldUpdateLastNonIdleTime:!1,updatedPrevMissedVsync:null,updatedPrevSlowUiThread:null,updatedPrevFrameDeadlineMissed:null,updatedPrevTotalFrames:null,updatedFirstGfxInfoLog:!1};let M=await this.getFrameStats(c,g,R,A);if(M===null)return{isStable:!1,frameStatsUnavailable:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:C,updatedPrevSlowUiThread:D,updatedPrevFrameDeadlineMissed:T,updatedPrevTotalFrames:k,updatedFirstGfxInfoLog:!1};if(M.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 F=this.processFrameStatsForStability(M,C,D,{prevFrameDeadlineMissed:T,prevTotalFrames:k});return{isStable:F.isStable,...F.noFrameData?{noFrameData:!0}:{},shouldUpdateLastNonIdleTime:F.shouldUpdateLastNonIdleTime,updatedPrevMissedVsync:F.updatedPrevMissedVsync,updatedPrevSlowUiThread:F.updatedPrevSlowUiThread,updatedPrevFrameDeadlineMissed:F.updatedPrevFrameDeadlineMissed,updatedPrevTotalFrames:F.updatedPrevTotalFrames,updatedFirstGfxInfoLog:!1}}catch(M){return A.signal?.throwIfAborted(),e.info(`[AwaitIdle] Error checking frame stats: ${M}`),{isStable:!1,frameStatsUnavailable:!0,shouldUpdateLastNonIdleTime:!0,updatedPrevMissedVsync:C,updatedPrevSlowUiThread:D,updatedPrevFrameDeadlineMissed:T,updatedPrevTotalFrames:k,updatedFirstGfxInfoLog:!1}}}extractMetric(c,d){let g=c.match(d);if(g&&g[1]){let R=parseFloat(g[1]);return isNaN(R)?null:R}return null}}var py=750,my=2000,$r=new Map;class mt{timer;adb;deviceId;constructor(c,d=v,g=i){this.timer=g;this.adb=d.create(c),this.deviceId=c.deviceId}async detectRefreshRate(){let c=Ni(this.deviceId)??"unknown",d=`${this.deviceId}\x00${c}`,g=$r.get(d);if(g!==void 0)return g;let R=this.timer.now();try{let{stdout:A}=await this.probe("shell dumpsys display | grep mRefreshRate",R),C=A.match(/mRefreshRate[=:]\s*(\d+\.?\d*)/i);if(C&&C[1]){let V=Math.round(parseFloat(C[1]));return e.info(`Detected refresh rate: ${V}Hz`),$r.set(d,V),V}let{stdout:D}=await this.probe("shell dumpsys SurfaceFlinger | grep 'refresh-rate'",R),T=D.match(/refresh-rate[=:]\s*(\d+\.?\d*)/i);if(T&&T[1]){let V=Math.round(parseFloat(T[1]));return e.info(`Detected refresh rate from SurfaceFlinger: ${V}Hz`),$r.set(d,V),V}let{stdout:k}=await this.probe("shell dumpsys display | grep -A 5 'mBaseDisplayInfo'",R),M=k.match(/fps\s*[=:]\s*(\d+\.?\d*)|(\d+\.?\d*)\s*fps/i),F=M?.[1]??M?.[2];if(F){let V=Math.round(parseFloat(F));return e.info(`Detected refresh rate from display modes: ${V}Hz`),$r.set(d,V),V}return e.warn("Could not detect refresh rate, defaulting to 60Hz"),60}catch(A){return e.warn(`Error detecting refresh rate: ${A}; defaulting to 60Hz`,A),60}}async probe(c,d){let g=this.timer.now()-d,R=my-g;if(R<=0)return{stdout:""};return this.adb.executeCommand(c,{timeoutMs:Math.min(py,R),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:g}=c;return{frameTimeThresholdMs:d,p50ThresholdMs:d*0.9,p90ThresholdMs:d*1,p95ThresholdMs:d*1.2,p99ThresholdMs:d*1.5,jankCountThreshold:Math.ceil(g/12),cpuUsageThresholdPercent:80,touchLatencyThresholdMs:d*2}}}var ro={min:0.1,max:2,successMultiplier:1.1,failureMultiplier:0.9};function dl(c,d,g){if(c.length===0)return null;let R=c.reduce((C,D)=>C+g(D),0);if(R===0)return null;return c.reduce((C,D)=>C+d(D)*g(D),0)/R}function ll(c){if(c.length===0)return;let d=new Map,g=0,R=c[0];for(let A of c){let C=(d.get(A)??0)+1;if(d.set(A,C),C>g)g=C,R=A}return R}function ul(c){if(c.length===0)return;let d=[...c].sort((R,A)=>R-A),g=Math.floor(d.length/2);return d.length%2===0?(d[g-1]+d[g])/2:d[g]}function iD(c,d){if(d===0)return c>0?1/0:1;return c/d}function qW(c,d=Date.now()){let g=new Date(d);return g.setDate(g.getDate()-c),g.toISOString()}var oD={thresholdHours:24,baselineDays:30},fre=0.3;var fy=10,hy=100,pl=125;function Wr(c,d){return c!==null&&d!==null&&d>c}function vl(c,d){return Wr(c.totalFrames,d.totalFrames)||Wr(c.missedVsync,d.missedVsync)||Wr(c.slowUiThread,d.slowUiThread)||Wr(c.frameDeadlineMissed,d.frameDeadlineMissed)}class no{adb;device;idle;timer;inertTouchPointResolver;constructor(c,d=v,g=i,R){this.device=c,this.adb=d.create(c),this.idle=new zT(c,d),this.timer=g,this.inertTouchPointResolver=R}selectSafeTouchLocation(c,d,g){if(d)return e.debug(`[TouchLatency] Using caller-provided touch location: (${d.x}, ${d.y})`),d;if(g&&g.right>g.left&&g.bottom>g.top){let C=Math.floor((g.left+g.right)/2),D=Math.floor((g.top+g.bottom)/2);return e.debug(`[TouchLatency] Selected touch location from app window bounds ${JSON.stringify(g)}: (${C}, ${D})`),{x:C,y:D}}let R=Math.floor(c.width*0.5),A=Math.floor(c.height*0.12);return e.debug(`[TouchLatency] Selected safe touch location (no window bounds): (${R}, ${A})`),{x:R,y:A}}async injectTouch(c,d,g){await g.track("adbInputTap",()=>this.adb.executeCommand(`shell input tap ${c} ${d}`))}async measureFrameResponse(c,d,g,R){let A=this.timer.now();while(this.timer.now()-A<g){await this.timer.sleep(fy);try{let{stdout:C}=await R.track("adbGfxinfoCheck",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),D=this.idle.parseMetrics(C);if(vl(d,D)){let T=this.timer.now()-A;return e.debug(`[TouchLatency] Frame activity detected after ${T}ms`),T}}catch(C){e.warn(`[TouchLatency] Error checking frame stats: ${C}`)}}return e.warn(`[TouchLatency] No frame activity detected within ${g}ms`),null}async takeSample(c,d,g,{perf:R,sampleIndex:A}){await R.track("adbGfxinfoReset",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)} reset`,{maxBuffer:ie})),await this.timer.sleep(pl);let{stdout:C}=await R.track("adbGfxinfoBaselineFirst",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),D=this.idle.parseMetrics(C);await this.timer.sleep(pl);let{stdout:T}=await R.track("adbGfxinfoBaselineSecond",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),k=this.idle.parseMetrics(T);if(vl(D,k))return e.warn(`[TouchLatency] Sample ${A+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 M=d,F=k;if(this.inertTouchPointResolver){let W=await R.track("touchLatencyRevalidatePoint",()=>this.inertTouchPointResolver.resolveInertTouchPoint());if(!W)return e.warn(`[TouchLatency] Sample ${A+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};M=W;let{stdout:G}=await R.track("adbGfxinfoBaselinePostRevalidate",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie}));F=this.idle.parseMetrics(G)}return await this.injectTouch(M.x,M.y,R),{latencyMs:await this.measureFrameResponse(c,F,g,R),animating:!1,obstructed:!1,tapPoint:M}}buildResult(c,d,g,{otherFailureCount:R,obstructedCount:A}){let C=g>0;if(d.length===0){let T=C&&R===0&&A===0,k=A>0&&R===0&&!C,M;if(T)M="App renders continuously (animating); touch latency cannot be isolated";else if(k)M="Touch point was no longer inert on a freshly captured hierarchy; aborted touch-latency measurement rather than tapping a possibly-live control";else M="No successful measurements - UI may be frozen or gfxinfo unavailable";return{latencyMs:0,touchCoordinates:c,success:!1,error:M,sampleCount:0,animating:T}}let D=ul(d)??0;return e.info(`[TouchLatency] Measured latency: ${D}ms (from ${d.length} samples)`),{latencyMs:D,touchCoordinates:c,success:!0,sampleCount:d.length,...C?{animating:!0}:{}}}async measureLatency(c,d,g={},R=new U){let A=g.sampleCount||3,C=g.maxWaitMs||200;e.info(`[TouchLatency] Measuring touch latency for ${c} (${A} samples)`);let D=this.selectSafeTouchLocation(d,g.touchPoint,g.windowBounds),T=[],k=0,M=0,F=0,V=D;try{for(let W=0;W<A;W++){e.debug(`[TouchLatency] Taking sample ${W+1}/${A}`);let G=await this.takeSample(c,D,C,{perf:R,sampleIndex:W});if(G.animating)k++;else if(G.obstructed)F++;else if(G.latencyMs!==null)V=G.tapPoint,T.push(G.latencyMs),e.debug(`[TouchLatency] Sample ${W+1}: ${G.latencyMs}ms`);else M++,e.warn(`[TouchLatency] Sample ${W+1} timeout - no response within ${C}ms`);if(W<A-1)await this.timer.sleep(hy)}return this.buildResult(V,T,k,{otherFailureCount:M,obstructedCount:F})}catch(W){return e.warn(`[TouchLatency] Failed to measure touch latency: ${r(W)}`,W),{latencyMs:0,touchCoordinates:D,success:!1,error:r(W),sampleCount:T.length}}}}function bl(){return N.isUiPerfModeEnabled()&&pk()&&!$e(h.DISABLE_PERF_AUDIT)}function Sl(){return $e(h.TOUCH_LATENCY_SAMPLING)}var vy=1e4,yy=24,wl=300000,gy=Ak(),At=null,by=500,Rl=["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 Pl(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 Ym{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(),g={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(g).execute(),await this.cleanupRetention()}catch(d){e.error(`[PerformanceAuditRepository] Failed to store audit result: ${d}`)}}async listResults(c){let d=this.getDb(),g=Math.max(1,c.limit??50),R=Math.max(0,c.offset??0),A=d.selectFrom("performance_audit_results").select(Rl);if(c.deviceId)A=A.where("device_id","=",c.deviceId);if(c.deviceSessionUuid)A=A.where("device_session_uuid","=",c.deviceSessionUuid);if(c.startTime)A=A.where("timestamp",">=",c.startTime);if(c.endTime)A=A.where("timestamp","<=",c.endTime);let C=await A.orderBy("timestamp","desc").orderBy("id","desc").limit(g+1).offset(R).execute(),D=C.length>g;return{results:(D?C.slice(0,g):C).map(Pl),hasMore:D,nextOffset:D?R+g:null}}async listResultsSince(c){let d=this.getDb(),g=Math.min(Math.max(1,c.limit??50),by),R=d.selectFrom("performance_audit_results").select(Rl);if(c.deviceId)R=R.where("device_id","=",c.deviceId);if(c.sessionId)R=R.where("session_id","=",c.sessionId);if(c.packageName)R=R.where("package_name","=",c.packageName);if(c.startTime)R=R.where("timestamp",">=",c.startTime);if(c.endTime)R=R.where("timestamp","<=",c.endTime);if(c.sinceTimestamp){let C=c.sinceTimestamp,D=c.sinceId??0;R=R.where((T)=>T.or([T("timestamp",">",C),T.and([T("timestamp","=",C),T("id",">",D)])]))}return(await R.orderBy("timestamp","asc").orderBy("id","asc").limit(g).execute()).map(Pl)}async cleanupRetention(){await Mu(gy,()=>this.pruneToRowCap())}async pruneToRowCap(c=vy){try{await Ou(this.getDb(),"performance_audit_results",c)}catch(d){e.warn(`[PerformanceAuditRepository] Retention cleanup failed: ${d}`)}}async pruneOldRecords(){try{let c=this.getDb(),g=new Date(this.timer.now()-yy*60*60*1000).toISOString(),R=await c.deleteFrom("performance_audit_results").where("timestamp","<",g).executeTakeFirst(),A=Number(R.numDeletedRows??0);if(A>0)e.info(`[PerformanceAuditRepository] Pruned ${A} old records`);return A}catch(c){return e.warn(`[PerformanceAuditRepository] Pruning failed: ${c}`),0}}startPeriodicPruning(){if(At)return;At=i.setInterval(()=>{this.pruneOldRecords().catch((c)=>{e.warn(`[PerformanceAuditRepository] Periodic pruning error: ${c}`)})},wl),At.unref(),e.info(`[PerformanceAuditRepository] Started periodic pruning (every ${wl/1000}s)`)}stopPeriodicPruning(){if(At)i.clearInterval(At),At=null,e.info("[PerformanceAuditRepository] Stopped periodic pruning")}}function VW(c){if(c.length===0)return[];let d=[...c].sort((R,A)=>A.contributionWeight-R.contributionWeight),g=Math.min(0.5,d[0].contributionWeight);return d.filter((R)=>R.contributionWeight>=g)}var Sy=5000,wy=1048576;async function oo(c){let d=c;if(typeof d.getAndroidApiLevel==="function"){let g=await d.getAndroidApiLevel();if(g!==null&&g>=29)return"ActivityTaskManager"}return"ActivityManager"}function so(c){let d=c.replace("+","").trim(),g=d.match(/^(\d+)s(\d+)ms$/);if(g)return Number.parseInt(g[1],10)*1000+Number.parseInt(g[2],10);let R=d.match(/^(\d+)ms$/);if(R)return Number.parseInt(R[1],10);let A=d.match(/^(\d+)s$/);if(A)return Number.parseInt(A[1],10)*1000;return null}function L3(c){let d=c.match(/^\s*(\d+\.\d+)\s+\d+\s+\d+\s+[VDIWEF]\s+(\w+):\s+(.*)$/);if(!d)return null;let g=Number.parseFloat(d[1]);if(Number.isNaN(g))return null;let R=d[2];if(R!=="ActivityManager"&&R!=="ActivityTaskManager")return null;return{timestampMs:Math.round(g*1000),logcatTag:R,message:d[3]}}function B3(c,d){let g=d==="Displayed"?/Displayed\s+(\S+?)(?:\s+for user \d+)?:/:/Fully drawn\s+(\S+?)(?:\s+for user \d+)?:/,R=c.match(g);return R?R[1]:null}function WW(c){let[d,g]=c.split("/"),R=g??"";if(R.startsWith("."))R=`${d}${R}`;return{packageName:d,activityName:R,componentName:c}}function $3(c){let d=c.match(/\+\s*\d+(?:s\d+ms|ms|s)/);if(!d)return null;return so(d[0])}class U3{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 g=await this.getPreferredLogcatTag();e.info(`[DisplayedTimeMetrics] Using logcat tag: ${g}`);let R=this.buildLogcatCommand(g);e.info(`[DisplayedTimeMetrics] Logcat command: ${R}`);try{let{stdout:A}=await d.track("adbLogcatDisplayed",()=>this.adb.executeCommand(R,{timeoutMs:Sy,maxBuffer:wy}));e.info(`[DisplayedTimeMetrics] Logcat output length: ${A.length} chars`);let C=this.parseDisplayedMetrics(A,c);return e.info(`[DisplayedTimeMetrics] Parsed ${C.length} metrics for package ${c.packageName} (window: ${c.startTimestampMs} - ${c.endTimestampMs})`),C}catch(A){return e.warn(`[DisplayedTimeMetrics] Failed to read logcat: ${A}`),[]}}async getPreferredLogcatTag(){if(this.logcatTagCache)return this.logcatTagCache;return this.logcatTagCache=await oo(this.adb),this.logcatTagCache}buildLogcatCommand(c){return`shell logcat -d -v epoch -s ${c}:I`}parseDisplayedMetrics(c,d){let g=[],R=c.split(`
|
|
16
|
+
`),A=R.filter((C)=>C.includes("Displayed"));if(e.info(`[DisplayedTimeMetrics] Found ${A.length} 'Displayed' lines in logcat`),A.length>0)e.info(`[DisplayedTimeMetrics] Last few Displayed lines: ${A.slice(-3).join(" | ")}`);for(let C of R){let D=L3(C);if(!D)continue;let{timestampMs:T,logcatTag:k,message:M}=D;if(T<d.startTimestampMs||T>d.endTimestampMs){if(M.includes("Displayed")&&M.includes(d.packageName))e.info(`[DisplayedTimeMetrics] Filtered by timestamp: logcatTs=${T}, window=[${d.startTimestampMs}, ${d.endTimestampMs}]`);continue}let F=B3(M,"Displayed");if(!F)continue;let V=WW(F);if(V.packageName!==d.packageName)continue;let W=$3(M);if(W===null)continue;e.info(`[DisplayedTimeMetrics] Found metric: ${V.componentName} = ${W}ms`),g.push({packageName:V.packageName,activityName:V.activityName,componentName:V.componentName,displayedTimeMs:W,timestampMs:T,logcatTag:k})}return g}}var lo=500;function Il(c,d){if(c.startTimeTicks!==d.startTimeTicks)return null;let g=d.processTicks-c.processTicks,R=d.uptimeSeconds-c.uptimeSeconds;if(!Number.isFinite(g)||!Number.isFinite(R))return null;if(g<0||R<=0)return null;return g/(R*100)*100}function zr(c,d){if(c===null||d===null)return null;return d>=c?d-c:d}function Ry(c,d,g){let R=zr(c.jankyFrames,d.jankyFrames);if(R!==null)return R;return g.length>0?Math.max(...g):null}function Cl(c,d,g){if(!(g>0))return null;let R=zr(c.missedVsync,d.missedVsync),A=zr(c.slowUiThread,d.slowUiThread),C=zr(c.frameDeadlineMissed,d.frameDeadlineMissed),D=[R,A,C].filter((M)=>M!==null),T=Ry(c,d,D);if(T===null)return null;let k=T*1000/g;return{jankPerSecond:Math.round(k*100)/100,missedVsync:R,slowUiThread:A,frameDeadlineMissed:C}}function Dl(c){let d=c.match(/^[ \t]*Janky frames:[ \t]*(\d+)/m);return d?parseInt(d[1],10):null}function Tl(c){let d=c.lastIndexOf(")");if(d<0)return null;let g=c.slice(d+1).trim().split(/\s+/),R=parseInt(g[11]??"",10),A=parseInt(g[12]??"",10),C=parseInt(g[19]??"",10);if(![R,A,C].every(Number.isFinite))return null;return{processTicks:R+A,startTimeTicks:C}}var Ay="No frames were rendered in the audit window, so there are no frame times to check.",Py="gfxinfo reported no rendered-frame count, so its frame times cannot be checked.";function Iy(c){if(!c.totalFrames)return{p50Ms:null,p90Ms:null,p95Ms:null,p99Ms:null,frameTimeUnmeasured:c.totalFrames===0?Ay:Py};return{p50Ms:c.percentile50th,p90Ms:c.percentile90th,p95Ms:c.percentile95th,p99Ms:c.percentile99th}}var Cy=200,Dy=100,Ty=500,xy=5000;class fo{adb;device;idle;capabilitiesDetector;touchLatencyTracker;repository=new Ym;timer;constructor(c,d=v,g,R=i){this.timer=R,this.device=c,this.adb=d.create(c),this.idle=new zT(c,d),this.capabilitiesDetector=new mt(c,d),this.touchLatencyTracker=new no(c,d,R,g)}async collectMetrics(c,d,g=new U,R){let A=R??{};e.info(`[PerformanceAudit] Collecting metrics for ${c}`);let[C,D,T,k]=await Promise.all([this.collectGfxMetrics(c,g),this.collectCpuMetrics(c,g),this.checkForAnr(c,g),this.calculateFrameRate(c,g)]),M=await this.measureTouchLatency(c,d,g,{windowBounds:A.windowBounds,touchPoint:A.touchPoint,skipTouchLatency:A.skipTouchLatency}),F=null,V=null;if(A.measureTtff)F=await this.measureTimeToFirstFrame(c,g);if(A.measureTti&&F!==null)V=await this.measureTimeToInteractive(c,F,g);return{...this.normalizeGfxMetrics(C),cpuUsagePercent:D.cpuUsagePercent??null,threadCount:D.threadCount??null,touchLatencyMs:M,anrDetected:T.anrDetected??!1,anrDetails:T.anrDetails??null,timeToFirstFrameMs:F,timeToInteractiveMs:V,frameRateFps:k,gfxinfoRaw:C.gfxinfoRaw??null,cpuStatsRaw:D.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:g}=await d.track("adbGfxinfo",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),R=this.idle.parseMetrics(g);return{stdout:g,counters:{totalFrames:R.totalFrames,jankyFrames:Dl(g),missedVsync:R.missedVsync,slowUiThread:R.slowUiThread,frameDeadlineMissed:R.frameDeadlineMissed}}}async collectGfxMetrics(c,d){try{let g=await this.readGfxSample(c,d),R=this.timer.now();await this.timer.sleep(lo);let A=await this.readGfxSample(c,d),C=this.timer.now()-R,D=this.idle.parseMetrics(A.stdout),T=Cl(g.counters,A.counters,C);return{...Iy(D),jankCount:T?.jankPerSecond??null,missedVsyncCount:T?.missedVsync??null,slowUiThreadCount:T?.slowUiThread??null,frameDeadlineMissedCount:T?.frameDeadlineMissed??null,gfxinfoRaw:A.stdout}}catch(g){return e.warn(`[PerformanceAudit] Failed to collect gfx metrics: ${g}`),{p50Ms:null,p90Ms:null,p95Ms:null,p99Ms:null,jankCount:null,missedVsyncCount:null,slowUiThreadCount:null,frameDeadlineMissedCount:null,gfxinfoRaw:null}}}async readCpuSample(c,d){let{stdout:g}=await d.track("adbCpuStat",()=>this.adb.executeCommand(`shell cat /proc/${b(c)}/stat`)),{stdout:R}=await d.track("adbUptime",()=>this.adb.executeCommand("shell cat /proc/uptime")),A=Tl(g),C=parseFloat(R.trim().split(/\s+/)[0]||"");if(!A||!Number.isFinite(C)||C<=0)return null;return{sample:{...A,uptimeSeconds:C},statRaw:g}}async collectCpuMetrics(c,d){try{let{stdout:g}=await d.track("adbGetPid",()=>this.adb.executeCommand(`shell pidof ${b(c)}`)),R=g.trim().split(/\s+/)[0];if(!R)return e.warn(`[PerformanceAudit] No PID found for ${c}`),{cpuUsagePercent:null,threadCount:null,cpuStatsRaw:null};let{stdout:A}=await d.track("adbThreadCount",()=>this.adb.executeCommand(`shell ps -T -p ${b(R)} | wc -l`)),C=parseInt(A.trim(),10)-1,D=await this.readCpuSample(R,d);await this.timer.sleep(lo);let T=await this.readCpuSample(R,d);return{cpuUsagePercent:D&&T?Il(D.sample,T.sample):null,threadCount:C,cpuStatsRaw:(T??D)?.statRaw??null}}catch(g){return e.warn(`[PerformanceAudit] Failed to collect CPU metrics: ${g}`),{cpuUsagePercent:null,threadCount:null,cpuStatsRaw:null}}}async checkForAnr(c,d){try{let{stdout:g}=await d.track("adbCheckAnr",()=>this.adb.executeCommand(`shell dumpsys activity processes | grep -A 20 ${b(c)}`,{maxBuffer:ie})),R=g.toLowerCase().includes("anr")||g.toLowerCase().includes("not responding");return{anrDetected:R,anrDetails:R?g:null}}catch(g){return e.warn(`[PerformanceAudit] Failed to check for ANR: ${g}`),{anrDetected:!1,anrDetails:null}}}async measureTouchLatency(c,d,g,R={}){let{windowBounds:A,touchPoint:C,skipTouchLatency:D}=R;if(D)return e.info("[PerformanceAudit] Touch latency measurement skipped (no verified-inert touch point available)"),null;if(!N.isUiPerfModeEnabled()||!Sl())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 g.track("touchLatencyMeasurement",()=>this.touchLatencyTracker.measureLatency(c,d,{sampleCount:3,maxWaitMs:Cy,windowBounds:A,touchPoint:C},g));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:g}=await d.track("adbGfxinfoFrameRate",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),R=g.match(/Total frames rendered:\s*(\d+)/);if(!R)return null;let A=parseInt(R[1],10);if(A===0)return null;let D=(await this.capabilitiesDetector.getCapabilities()).refreshRate||60,T=g.match(/Janky frames:\s*(\d+)/),k=T?parseInt(T[1],10):0,M=this.idle.parseMetrics(g);if(M.percentile50th&&M.percentile50th>0){let V=1000/M.percentile50th;return Math.min(V,D)}if(k>0&&A>0){let F=A-k,V=1000/D,W=F*V+k*V*2,G=A*1000/W;return Math.min(G,D)}return D}catch(g){return e.warn(`[PerformanceAudit] Failed to calculate frame rate: ${g}`),null}}async measureTimeToFirstFrame(c,d){try{let g=await oo(this.adb),{stdout:R}=await d.track("adbLogcatTtff",()=>this.adb.executeCommand(`shell "logcat -d -s ${g}:I | grep -E 'Displayed.*'${b(c)} | tail -1"`));if(!R.trim())return e.debug("[PerformanceAudit] No TTFF data found in logcat"),null;let A=R.match(/\+\s*\d+(?:s\d+ms|ms|s)/);return A?so(A[0]):null}catch(g){return e.warn(`[PerformanceAudit] Failed to measure TTFF: ${g}`),null}}async measureTimeToInteractive(c,d,g){try{let R=Dy,A=Ty,C=xy,D=null,T=0;while(T<C){await g.track("adbGfxinfoTtiReset",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)} reset`,{maxBuffer:ie})),await i.sleep(R),T+=R;let{stdout:k}=await g.track("adbGfxinfoTtiAfter",()=>this.adb.executeCommand(`shell dumpsys gfxinfo ${b(c)}`,{maxBuffer:ie})),M=this.idle.parseMetrics(k);if((M.missedVsync||0)>0||(M.slowUiThread||0)>0||(M.frameDeadlineMissed||0)>0){D=null;continue}if(D===null){D=T;continue}if(T-D>=A)return e.info(`[PerformanceAudit] TTI reached: ${d+D}ms`),d+D}return e.warn(`[PerformanceAudit] TTI measurement timed out after ${C}ms`),null}catch(R){return e.warn(`[PerformanceAudit] Failed to measure TTI: ${R}`),null}}validateMetrics(c,d){let g=[];if(this.appendPercentileViolations(g,c,d),c.jankCount!==null&&c.jankCount>d.jankCountThreshold)g.push({metric:"jankCount",threshold:d.jankCountThreshold,actual:c.jankCount,severity:"critical",contributionWeight:0.9});if(c.cpuUsagePercent!==null&&c.cpuUsagePercent>d.cpuUsageThresholdPercent)g.push({metric:"cpuUsage",threshold:d.cpuUsageThresholdPercent,actual:c.cpuUsagePercent,severity:"warning",contributionWeight:0.5});if(c.touchLatencyMs!==null&&c.touchLatencyMs>d.touchLatencyThresholdMs)g.push({metric:"touchLatency",threshold:d.touchLatencyThresholdMs,actual:c.touchLatencyMs,severity:"critical",contributionWeight:0.85});if(c.anrDetected)g.push({metric:"anr",threshold:0,actual:1,severity:"critical",contributionWeight:1});return g}appendPercentileViolations(c,d,g){if(d.p50Ms!==null&&d.p50Ms>g.p50ThresholdMs)c.push({metric:"p50",threshold:g.p50ThresholdMs,actual:d.p50Ms,severity:"warning",contributionWeight:0.6});if(d.p90Ms!==null&&d.p90Ms>g.p90ThresholdMs)c.push({metric:"p90",threshold:g.p90ThresholdMs,actual:d.p90Ms,severity:"warning",contributionWeight:0.7});if(d.p95Ms!==null&&d.p95Ms>g.p95ThresholdMs)c.push({metric:"p95",threshold:g.p95ThresholdMs,actual:d.p95Ms,severity:"critical",contributionWeight:0.8});if(d.p99Ms!==null&&d.p99Ms>g.p99ThresholdMs)c.push({metric:"p99",threshold:g.p99ThresholdMs,actual:d.p99Ms,severity:"warning",contributionWeight:0.4})}generateDiagnostics(c,d){if(d.length===0)return"No performance issues detected";let g=`Performance issues detected:
|
|
17
|
+
|
|
18
|
+
`,R=VW(d);g+=`Top contributors:
|
|
19
|
+
`;for(let D of R)g+=`- ${D.metric}: ${D.actual.toFixed(2)} (threshold: ${D.threshold.toFixed(2)}) [${D.severity}]
|
|
20
|
+
`;if(g+=`
|
|
21
|
+
Diagnostic details:
|
|
22
|
+
`,R.some((D)=>["p50","p90","p95","p99","jankCount"].includes(D.metric))&&c.gfxinfoRaw)g+=`
|
|
23
|
+
--- GFXINFO DUMP ---
|
|
24
|
+
`,g+=c.gfxinfoRaw,g+=`
|
|
25
|
+
--- END GFXINFO ---
|
|
26
|
+
`;if(R.some((D)=>D.metric==="cpuUsage")&&c.cpuStatsRaw)g+=`
|
|
27
|
+
--- CPU STATS ---
|
|
28
|
+
`,g+=`Thread count: ${c.threadCount}
|
|
29
|
+
`,g+=`CPU usage: ${c.cpuUsagePercent?.toFixed(2)}%
|
|
30
|
+
`,g+=c.cpuStatsRaw,g+=`
|
|
31
|
+
--- END CPU STATS ---
|
|
32
|
+
`;if(c.anrDetected&&c.anrDetails)g+=`
|
|
33
|
+
--- ANR DETECTED ---
|
|
34
|
+
`,g+=c.anrDetails,g+=`
|
|
35
|
+
--- END ANR ---
|
|
36
|
+
`;return g}async runAudit(c,d,g={}){let{screenSize:R,perf:A=new U,windowBounds:C,touchPoint:D,skipTouchLatency:T}=g;e.info(`[PerformanceAudit] Running audit for ${c}`);let k=gB(this.device.deviceId),M=await this.capabilitiesDetector.getCapabilities(),F=await this.collectMetrics(c,R,A,{windowBounds:C,touchPoint:D,skipTouchLatency:T}),V=this.validateMetrics(F,d),W=V.length>0?this.generateDiagnostics(F,V):null,G=V.length===0,q=new Date().toISOString().split("T")[0];return await this.repository.recordAudit({deviceId:this.device.deviceId,sessionId:q,packageName:c,timestamp:new Date().toISOString(),passed:G,metrics:{p50Ms:F.p50Ms,p90Ms:F.p90Ms,p95Ms:F.p95Ms,p99Ms:F.p99Ms,jankCount:F.jankCount,missedVsyncCount:F.missedVsyncCount,slowUiThreadCount:F.slowUiThreadCount,frameDeadlineMissedCount:F.frameDeadlineMissedCount,cpuUsagePercent:F.cpuUsagePercent,touchLatencyMs:F.touchLatencyMs},diagnostics:W,deviceSessionUuid:k}),{passed:G,metrics:F,violations:V,diagnostics:W,deviceCapabilities:M}}}var vo=f`datetime(created_at, '+' || ttl_hours || ' hours')`,yo=f`datetime('now')`;class go{table;constructor(c){this.table=f.table(c)}async deleteExpired(c,d){let g=await f`
|
|
37
|
+
delete from ${this.table}
|
|
38
|
+
where ${vo} < ${yo}${this.andWhere(d)}
|
|
39
|
+
`.execute(c);return Number(g.numAffectedRows??0)}async selectValid(c,d){return(await f`
|
|
40
|
+
select * from ${this.table}
|
|
41
|
+
where ${vo} >= ${yo}${this.andWhere(d)}
|
|
42
|
+
order by created_at desc
|
|
43
|
+
`.execute(c)).rows}async insert(c,d){let g=Object.entries(d),R=f.join(g.map(([C])=>f.ref(C))),A=f.join(g.map(([,C])=>f.val(C)));await f`insert into ${this.table} (${R}) values (${A})`.execute(c)}async adjustLatestWeight(c,d,g,R){let A=g?f`min(weight * ${R.successMultiplier}, ${R.max})`:f`max(weight * ${R.failureMultiplier}, ${R.min})`,C=await f`
|
|
44
|
+
update ${this.table}
|
|
45
|
+
set weight = ${A}
|
|
46
|
+
where id = (
|
|
47
|
+
select id from ${this.table}
|
|
48
|
+
where ${vo} >= ${yo}${this.andWhere(d)}
|
|
49
|
+
order by created_at desc
|
|
50
|
+
limit 1
|
|
51
|
+
)
|
|
52
|
+
`.execute(c);return Number(C.numAffectedRows??0)}andWhere(c){return f.join(c.map((d)=>f` and ${f.ref(d.column)} = ${f.val(d.value)}`),f``)}}class jL{injectedDb;descriptor;repository;constructor(c,d){this.descriptor=c,this.repository=new go(c.tableName),this.injectedDb=d??null}get db(){return this.injectedDb??_e()}async cleanupExpiredThresholds(c,d,g=this.db){try{let R=await this.repository.deleteExpired(g,c);if(R>0)e.info(`[${this.descriptor.logPrefix}] Cleaned up ${R} expired thresholds for ${d}`)}catch(R){e.warn(`[${this.descriptor.logPrefix}] Failed to cleanup expired thresholds: ${R}`)}}async getValidThresholds(c,d,g,R=this.db){return await this.cleanupExpiredThresholds(d,g,R),await this.repository.selectValid(R,c)}calculateWeightedAverageThresholds(c){if(c.length===0)return null;let d={weight:ro.max/2,ttl_hours:oD.thresholdHours};for(let g of this.descriptor.modeColumns??[])d[g]=ll(c.map((R)=>Number(R[g])))??60;for(let{column:g,round:R}of this.descriptor.weightedColumns){let A=dl(c,(C)=>Number(C[g]),(C)=>C.weight);if(A===null)return null;d[g]=R?Math.round(A):A}return d}async storeThresholds(c,d,g=this.db){try{await this.repository.insert(g,c),e.info(`[${this.descriptor.logPrefix}] Stored new thresholds for ${d}`)}catch(R){throw e.error(`[${this.descriptor.logPrefix}] Failed to store thresholds: ${R}`),R}}async updateThresholdWeight(c,d,g){try{if(await this.cleanupExpiredThresholds(g.cleanupWhere??c,this.describeWhere(g.cleanupWhere??c)),await this.repository.adjustLatestWeight(this.db,c,d,ro)===0){e.warn(`[${this.descriptor.logPrefix}] ${g.missingMessage}`);return}e.debug(`[${this.descriptor.logPrefix}] ${g.updatedMessage}`)}catch(R){e.warn(`[${this.descriptor.logPrefix}] Failed to update threshold weight: ${R}`)}}describeWhere(c){return c.map((d)=>`${d.column} ${d.value}`).join(", ")}}var ky={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 bo{thresholds;constructor(c){this.thresholds=new jL(ky,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 g=this.db,R=async(D)=>{let T=await this.getValidThresholdsWith(D,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}},A=async(D)=>{let T=await R(D);if(T)return T;e.info(`[ThresholdManager] Creating new thresholds for device ${c}`);let k=mt.calculateDefaultThresholds(d);return await this.storeThresholdsWith(D,c,d,{thresholds:k}),k};if(g.isTransaction)return A(g);return await R(g)??g.transaction().execute(A)}async storeThresholds(c,d,g,{weight:R=1,ttlHours:A=24}={}){await this.storeThresholdsWith(this.db,c,d,{thresholds:g,weight:R,ttlHours:A})}async storeThresholdsWith(c,d,g,{thresholds:R,weight:A=1,ttlHours:C=24}){let D=this.getCurrentSessionId(),T={device_id:d,session_id:D,refresh_rate:g.refreshRate,frame_time_threshold_ms:R.frameTimeThresholdMs,p50_threshold_ms:R.p50ThresholdMs,p90_threshold_ms:R.p90ThresholdMs,p95_threshold_ms:R.p95ThresholdMs,p99_threshold_ms:R.p99ThresholdMs,jank_count_threshold:R.jankCountThreshold,cpu_usage_threshold_percent:R.cpuUsageThresholdPercent,touch_latency_threshold_ms:R.touchLatencyThresholdMs,weight:A,ttl_hours:C};await this.thresholds.storeThresholds(T,`device ${d} session ${D}`,c)}async updateThresholdWeight(c,d,g){await this.thresholds.updateThresholdWeight([...this.deviceWhere(c),{column:"session_id",value:d}],g,{missingMessage:`No threshold found for device ${c} session ${d}`,updatedMessage:`Updated threshold weight (${g?"passed":"failed"})`})}deviceWhere(c){return[{column:"device_id",value:c}]}}var Ww="com.android.systemui",Ey="proud-lock",pg=300,Oy=["NotificationCenter","NCNotification","NotificationList","NotificationShortLookView","NotificationLongLookView","PLPlatterView"],H3=["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"],My=["NotificationPanel","NotificationShade","NotificationStack","QSPanel","QuickSettings","StatusBarExpanded"],et=(c)=>{if(!c||typeof c!=="object")return null;return we(c)},Jm=(c,d)=>{if(!c)return!1;if(d(c))return!0;let g=c.node;if(Array.isArray(g)){for(let R of g)if(Jm(R,d))return!0}else if(g&&typeof g==="object"){if(Jm(g,d))return!0}return!1},_y=new fe,jn=(c)=>{let d=new Set;return[..._y.project(c)].filter((g)=>g.parentIndex===void 0).sort((g,R)=>g.windowRank-R.windowRank||g.index-R.index).filter((g)=>{if(d.has(g.source))return!1;return d.add(g.source),!0}).map((g)=>g.source)},Fy={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"]},sd=(c,d)=>Fy[d].some((g)=>c===g),q3=(c)=>{let d=String(c.packageName??c.package??"");if(d)return d===Ww;return mr(c).startsWith(`${Ww}:id/`)},hre=(c)=>{let d=et(c);if(!d)return!1;let g=mr(d),R=String(d.className??d.class??"");if(!q3(d))return!1;let C=H3.some((T)=>g===`${Ww}:id/${T}`||g===T),D=My.some((T)=>R.includes(T));return C||D},zW=(c)=>jn(c).some((d)=>Jm(d,(g)=>mr(et(g))===Ey)),kl=(c)=>{let d=et(c);if(!d)return!1;return String(d.className??d.class??"")==="UIWindow"&&mr(d,["identifier"])==="SBCoverSheetWindow"&&Jm(c,(g)=>{let R=mr(et(g));return R==="combined-list-view"||R==="lockscreen-date-view"})},jW=(c)=>!zW(c)&&jn(c).some((d)=>Jm(d,kl)),gre=(c)=>{let d=et(c);if(!d)return!1;let g=String(d.className??d.class??""),R=OR(d,["content-desc","ios-accessibility-label"]),A=mr(d,["identifier"]);return kl(c)||Oy.some((C)=>g.includes(C)||R.includes(C)||A.includes(C))},V3=(c)=>mr(et(c)),yre=1500,vre=150,KW=["title","title_big","conversation_text","notification_title"];class So{observeScreen;appId;enclosingUpdatedAt;constructor(c,d,g){this.observeScreen=c;this.appId=d;this.enclosingUpdatedAt=g}async resolveInertTouchPoint(){try{let c=N9(this.enclosingUpdatedAt)+1,d=await this.observeScreen.execute({perf:new U,skipWaitForFresh:!1,minTimestamp:c,skipScreenshot:!0,skipBackStack:!0,skipAccessibilityAudit:!0,skipPerformanceAudit:!0});if(N9(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 g=Wt(d,this.appId),{touchPoint:R,skipTouchLatency:A}=wo(g,d);if(A||!R)return null;return R}catch(c){return e.warn(`[PerformanceAudit] Failed to re-derive inert touch point: ${c}`),null}}}var Ny=1,By="notification_permission_dialog";function Ly(c,d){if(!c.bounds||c.type!==Ny)return!1;return c.packageName===void 0||c.packageName===d}function Wt(c,d){let g=c.viewHierarchy?.windows;if(!g||g.length===0)return;let R=g.filter((C)=>Ly(C,d));return(R.find((C)=>C.isFocused)??R[0])?.bounds}var Hy=[{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}],Vy={x:0.5,y:0.95};function Uy(c){return dt(c.clickable)||dt(c.focusable)||dt(c["long-clickable"])||Rr(c.actions,"click")||Rr(c.actions,"long_click")}function El(c,d,g){return c>=g.left&&c<g.right&&d>=g.top&&d<g.bottom}function $y(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 Wy(c,d,g=[]){let R=d.filter((T)=>T.bounds&&Uy(T)),A=c.right-c.left,C=c.bottom-c.top,D=(T)=>({x:Math.floor(c.left+A*T.x),y:Math.floor(c.top+C*T.y)});for(let T of Hy){let k=D(T),M=R.some((V)=>El(k.x,k.y,V.bounds)),F=g.some((V)=>El(k.x,k.y,V));if(!M&&!F)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:D(Vy),inert:!1}}function Gy(c,d=new K){if(!c.viewHierarchy)return c.elements?.clickable??[];return d.flattenViewHierarchy(c.viewHierarchy,{includeWindows:!0}).map((g)=>g.element)}function Ky(c){return(c.viewHierarchy?.contentHiddenRegions??[]).map((d)=>d.bounds)}var zy=[(c)=>c?null:"no app window bounds were found",(c)=>c&&!$y(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 g=Rb(d.viewHierarchy?.truncationReasons);return g.length>0?`view hierarchy is truncated (${g.join(", ")}) - the obstacle map may be incomplete`:null},(c,d)=>d.activeWindow?.appId===Ww?`a SystemUI overlay owns focus (activeWindow.appId === "${Ww}") - the app window beneath it cannot be safely probed`:null,(c,d)=>d.notificationPermissionDetected||d.activeWindow?.type===By?"a notification-permission dialog owns the window - the underlying app's bounds/gfxinfo don't correspond to the same surface":null];function jy(c,d){for(let g of zy){let R=g(c,d);if(R!==null)return R}return null}function wo(c,d,g=new K){let R=jy(c,d);if(R!==null||!c){if(R!==null)e.warn(`[PerformanceAudit] Skipping touch-latency measurement: ${R}`);return{skipTouchLatency:!0}}let A=Gy(d,g),C=Ky(d),{point:D,inert:T}=Wy(c,A,C);if(!T)return{skipTouchLatency:!0};return{touchPoint:D,skipTouchLatency:!1}}class KL{device;adbFactory;isEnabled;observeScreenProvider;constructor(c){this.device=c.device,this.adbFactory=c.adbFactory??v,this.isEnabled=c.isEnabled??bl,this.observeScreenProvider=c.observeScreenProvider}async run(c,d){if(!this.isEnabled())return;let g=this.device.platform;if(g!=="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 R=new mt(this.device,this.adbFactory),A=new bo,C=this.observeScreenProvider?.(),D=C?new So(C,c.activeWindow.appId,c.updatedAt):void 0,T=new fo(this.device,this.adbFactory,D),k=await R.getCapabilities(),M=await A.getOrCreateThresholds(this.device.deviceId,k),F=Wt(c,c.activeWindow.appId),{touchPoint:V,skipTouchLatency:W}=wo(F,c),G=await T.runAudit(c.activeWindow.appId,M,{screenSize:c.screenSize,perf:d,windowBounds:F,touchPoint:V,skipTouchLatency:W});c.performanceAudit=G;let q=new Date().toISOString().split("T")[0];if(await A.updateThresholdWeight(this.device.deviceId,q,G.passed),!G.passed)e.warn(`[PerformanceAudit] Performance audit FAILED with ${G.violations.length} violations`);else e.info("[PerformanceAudit] Performance audit PASSED");let{getPerformanceMonitor:X}=await import("./chunk-bvranw3g.js");X().startMonitoring(this.device.deviceId,c.activeWindow.appId,g)})}catch(R){e.error(`[PerformanceAudit] Failed to run performance audit: ${R}`)}}}var Ro="android",Ol="android:id/aerr_";function Ml(c){if(!c.activeWindow?.appId||!c.elements)return!1;if(Re.has(c.activeWindow.appId))return!1;let g=Wt(c,c.activeWindow.appId)??{top:0,bottom:1/0,left:-1/0,right:1/0},R=c.systemInsets,A=Math.max(g.top,R.top),C=Math.min(g.bottom,(c.viewHierarchy?.screenHeight??1/0)-R.bottom),D=Math.max(g.left,R.left),T=Math.min(g.right,(c.viewHierarchy?.screenWidth??1/0)-R.right);return Object.values(c.elements).every((k)=>k.every(({bounds:M})=>M.bottom<=A||M.top>=C||M.right<=D||M.left>=T))}function qy(c){return Boolean(c.activeWindow?.appId||c.viewHierarchy?.packageName||Ht(c.viewHierarchy))}function mg(c){if(!c.viewHierarchy?.hierarchy?.node)return;if(Hr(c))return{reason:"status_bar_only"};if(qy(c))return;return{reason:"empty_active_window"}}function _l(c,d,g){if(c?.ctrlProxyIncomplete!==!0)return;if(g&&c.packageName===Ro)return;let{packageName:R,ctrlProxyIncompleteReason:A}=c,C=d!==void 0&&R!==void 0&&R===d;if(C&&!$8(A))return;return{sdkInt:c.sdkInt,reason:A,accessibilityTool:c.accessibilityTool,...C?{foregroundRead:!0}:{}}}function GL(c){let{freshness:d}=c;if(d?.isFresh===!1||d?.verified===!1||c.viewHierarchy?.fallbackToSpringboard===!0||mg(c))return;return Xy(c)}function Xy(c){return c.activeWindow?.appId||c.viewHierarchy?.packageName||c.viewHierarchy?.foregroundActivity?.split("/")[0]||void 0}class Co{d;constructor(c){this.d=c}recordSingleDisplayTransition(c){let{result:d,observerMode:g,preserveDisplayState:R,explicitlyRouted:A,recordProvenance:C}=c;return!g&&!R&&!A&&Ce.record(this.d.device().deviceId,d,this.d.platformTraits().isIosMultiPanel()?"ios":"android",C)}reconcileSingleDisplayFreshness(c){let{result:d,recordProvenance:g}=c,R=Ce.revision(this.d.device().deviceId)!==g.revision,A=this.recordSingleDisplayTransition(c);return d.display.generation=R?g.identityRevision:Ce.identityRevision(this.d.device().deviceId),d.displayRevision=R?g.revision:Ce.revision(this.d.device().deviceId),{staleDisplay:R,geometryTransition:A}}async settleSingleDisplay(c,d,g){let{options:R,result:A,perf:C,signal:D,observerMode:T,preserveDisplayState:k}=c;await this.computeSingleDisplayFreshness(c,d,g);let{staleDisplay:M,geometryTransition:F}=this.reconcileSingleDisplayFreshness({result:A,observerMode:T,preserveDisplayState:k,explicitlyRouted:c.explicitlyRouted,recordProvenance:g.recordProvenance}),V=F?mo().currentGeneration(this.d.device().deviceId):c.cacheGeneration;if(this.d.device().platform==="android"&&(F||Ce.revision(this.d.device().deviceId)!==c.captureStart.revision))await this.resampleDeviceLock(A,D);if(this.d.identifyCapture(A,R?.freshness??"cached-ok"),c.iosLockState)Ir(A,await c.iosLockState);if(!M&&bc(c))await C.track("cacheResult",()=>mo().put(this.d.device().deviceId,A,V))}async resampleDeviceLock(c,d){delete c.deviceLock,delete c.deviceLockUnknown,await this.d.deviceStateCollector().collectDeviceLock(c,d)}async computeSingleDisplayFreshness(c,d,g){let{result:R,minTimestamp:A,signal:C,observerMode:D}=c,{foregroundIdentity:T}=d,{postCaptureForeground:k,getConfirmedFrameworkErrorDialog:M}=g,F=await this.d.windowIdentity().resolveStatusBarOnlyHierarchy(R,T,k,C);await this.d.windowIdentity().attributeFocusedOwnWindowToForeground(R,T,A);let V=await this.d.windowIdentity().resolveWindowIdentityMismatch(R,T,{postCaptureForeground:k,getConfirmedFrameworkErrorDialog:M,minTimestamp:A,signal:C});if(R.freshness=FR({requestedAfter:A>0?A:void 0,actualTimestamp:this.d.resolveObservationTimestampMs(R),hostAgeBasisMs:this.d.windowIdentity().resolveHostReceivedAtMs(R),now:this.d.timer().now(),verified:typeof R.viewHierarchy==="object"&&R.viewHierarchy!==null?R.viewHierarchy.fresh:void 0,...Sc(c,g),missingForegroundWindow:mg(R),statusBarOnlyHierarchy:F,windowIdentityMismatch:V,activityAttributionMismatch:k.activityAttributionMismatch,emptyFocusedWindow:this.d.device().platform==="android"&&Ml(R),incompleteCapture:await this.describeIncompleteSingleDisplay(c,g)}),V)HY(R);if(D&&R.freshness?.unavailableDetail)R.freshness.warning+=` ${R.freshness.unavailableDetail}`}async describeIncompleteSingleDisplay(c,d){let{viewHierarchy:g}=c.result,R=g?.ctrlProxyIncomplete===!0;return _l(g,R?await this.d.windowIdentity().confirmForegroundIdentity(d.postCaptureForeground,c.signal):void 0,R?await d.getConfirmedFrameworkErrorDialog():!1)}}var jT=0.02;function Yy(c,d,g){let{x:R,y:A}=c;switch(g){case 1:return{x:d.height-A,y:R};case 2:return{x:d.width-R,y:d.height-A};case 3:return{x:A,y:d.width-R};default:return c}}function GW(c,d,g){let{x:R,y:A}=c;switch(g){case 1:return{x:A,y:d.height-R};case 2:return{x:d.width-R,y:d.height-A};case 3:return{x:d.width-A,y:R};default:return c}}function YW(c,d){return d===1||d===3?{width:c.height,height:c.width}:c}function Fl(c,d){let g=[{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(...g.map((R)=>R.x)),top:Math.min(...g.map((R)=>R.y)),right:Math.max(...g.map((R)=>R.x)),bottom:Math.max(...g.map((R)=>R.y))}}function YL(c,d,g){return Fl(c,(R)=>Yy(R,d,g))}function W3(c,d,g){return Fl(c,(R)=>GW(R,d,g))}function JL(c,d,g){return{left:Math.max(0,Math.floor(c.left*d.x)),top:Math.max(0,Math.floor(c.top*d.y)),right:Math.min(g.width,Math.ceil(c.right*d.x)),bottom:Math.min(g.height,Math.ceil(c.bottom*d.y))}}function JW(c,d,g="snapshotOf"){let{width:R,height:A}=d.screenSize;if(![R,A].every((X)=>Number.isFinite(X)&&X>0))throw new t(`${g} requires finite, nonempty bounds and screen dimensions`);if([c.width,c.height].some((X)=>X<=0))throw new t(`${g} received an empty screenshot raster`);let D=d.platform==="ios"&&d.rasterOrientation!=="display"?d.rotation:0,T=[1,3].some((X)=>X===D)&&R>A&&c.width<c.height,k=D===2,[M,F]=T?[A,R]:[R,A],V=c.width/M,W=c.height/F;if(Math.abs(V-W)>jT)throw new t(`${g} screenshot and screen geometry have incompatible aspect ratios`);let G=[V,W].every((X)=>Math.abs((d.nativeScale??NaN)-X)<=jT)?"native-scale-confirmed":"raster-dimensions",q=[T,k].includes(!0)?"native":"display";return{pixelsPerNativeUnit:{x:V,y:W},scaleProvenance:G,quarterTurn:T,halfTurn:k,screenshotOrientation:q}}import*as Jy from"fs/promises";import Qy from"path";function Zy(c){let d=Qy.extname(c).toLowerCase(),R={".png":"png",".jpg":"jpeg",".jpeg":"jpeg",".webp":"webp"}[d];if(!R)throw new t("Screenshot file has an unrecognized format.");return R}async function Gt(c,d,g,R={}){let{files:A=Jy,timer:C=i,protection:D=Vn}=R;await D.protect(c);let T=await A.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:C.now(),M=Zy(c),F=await D.protect(c);return{screenshotPath:c,screenshotExpiresAt:F,screenshotSource:d,screenshotCaptureSource:d==="fresh"?"device":"observation-cache",screenshotCapturedAt:new Date(k).toISOString(),screenshotAgeMs:Math.max(0,C.now()-k),screenshotFormat:M,screenshotMimeType:`image/${M}`,...g?{screenshotFreshFailure:{code:"SCREENSHOT_CAPTURE_FAILED",message:g,retryable:!0}}:{}}}class xo{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,g,{strict:R,displayId:A,screenshotOptions:C}){try{if(!this.screenshotRecorder.captureSettled)throw new t("Settled screenshot capture is unavailable");let D=await this.screenshotRecorder.captureSettled(c.observationId,{perf:d,signal:g,displayId:A,options:C}),T=await Gt(D,"fresh",void 0,{files:this.screenshotEvidenceFiles,timer:this.timer,protection:this.pathProtection});Object.assign(c,T);let k=Qr().getImageSizeForObservation(this.device.deviceId,c.observationId,D);await this.attachScreenshotRaster(c,k),this.refineIosPanelOrientation(c),c.screenshotSettled=!0}catch(D){if(g?.throwIfAborted(),R)throw new Lt(D,this.device.deviceId);c.screenshotSettled=!1,c.screenshotSettledError=r(D),e.warn(`[OBSERVE] Settled screenshot unavailable: ${c.screenshotSettledError}`,D)}}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:g,height:R}=c.screenSize;if(this.device.platform!=="ios"||kc(c.viewHierarchy)||(this.device.displays?.panels.length??0)<2||![g,R].every((D)=>Number.isFinite(D)&&D>0))return!0;let A=(D,T)=>Math.abs(d.width/D-d.height/T)<=jT;if(A(g,R))return!0;if(A(R,g))return c.screenSize={...c.screenSize,width:R,height:g},c.rotation=Tc(void 0,c.screenSize),!0;let C=`The ${c.display.role} panel screenshot (${d.width}x${d.height} px) fits neither orientation of its ${g}x${R} 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] ${C}`),pe(c,{phase:"screenshot",message:C}),!1}async attachScreenshotRaster(c,d){delete c.screenshotImageSize,delete c.screenshotPixelsPerNativeUnit,delete c.screenshotScaleProvenance;try{if(!d||![d.width,d.height].every((C)=>Number.isInteger(C)&&C>0)){e.warn("[OBSERVE] Could not read screenshot raster dimensions");return}c.screenshotImageSize={width:d.width,height:d.height};let g=c.viewHierarchy??{},R=re(this.device.platform,"Deriving the screenshot raster scale");if(!this.orientHierarchylessPanelToRaster(c,d))return;let A=JW(d,{platform:R,screenSize:c.screenSize,rotation:g.rotation??c.rotation,nativeScale:g.nativeScale,rasterOrientation:R==="ios"&&!((this.device.displays?.panels.length??0)>1&&d.width>d.height===c.screenSize.width>c.screenSize.height)?"native":"display"},"observe");c.screenshotPixelsPerNativeUnit=A.pixelsPerNativeUnit,c.screenshotScaleProvenance=A.scaleProvenance}catch(g){e.warn(`[OBSERVE] Could not derive screenshot raster scale: ${r(g)}`,g);return}}}function eg(c,d){return c?.key===d.key&&c.generation===d.generation}class Eo{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,g,R={}){let{requireFreshScreenshot:A=!1,display:C=this.requestedDisplay}=R;c.screenshotCaptureAttempted=!0,c.screenshotOrientation=this.device.platform==="ios"?"native":"display";let D=await this.resolveReadDisplayId(c,{signal:d,display:C}),T={format:g?.format??"png",...g,displayId:D},k=this.screenshotService instanceof No?await this.screenshotService.executeObservationRead(T,d):await this.screenshotService.execute(T,d);if(d?.throwIfAborted(),k.success&&k.path){Object.assign(c,await Gt(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",D,A)}async handleDeviceReadScreenshotFailure(c,d,g,R){if(R)throw new t(`observe crop screenshot capture failed for device ${this.device.deviceId}: ${d}. Retry with a fresh settled capture.`);let A=this.eligibleCachedScreenshot(g,c.display);if(A)try{Object.assign(c,await Gt(A.path,"cached",d,{files:this.screenshotEvidenceFiles,timer:this.timer,protection:this.pathProtection})),await this.settledScreenshots().attachScreenshotRaster(c,A.imageSize)}catch(C){e.warn(`[OBSERVE] Cached screenshot unavailable: ${r(C)}`,C)}c.screenshotSettled=!1,c.screenshotSettledError=d}async resolveReadDisplayId(c,d={}){let{signal:g,display:R=this.requestedDisplay}=d;if(this.device.platform!=="android"||!R||R==="active")return;let A=Ei(this.device,R,{}),C=await this.observedAndroidDisplayCache.logicalIdForPanel(this.device,this.adb,A.key,g);return c.display={...c.display,key:A.key,role:A.role},C}eligibleCachedScreenshot(c,d){let g=mo().getRecentInMemoryForDevice(this.device.deviceId);if(!this.cachedScreenshotDisplayMatches(g,c,d))return;if(g?.screenshotPath)return{path:g.screenshotPath,imageSize:g.screenshotImageSize};let R=this.deviceWideScreenshotPath(c);return R?{path:R}:void 0}deviceWideScreenshotPath(c){return!Boolean(this.requestedDisplay&&this.requestedDisplay!=="active")&&c===void 0&&!this.hasMultiplePanels()?Qr().getPath(this.device.deviceId):void 0}hasMultiplePanels(){return(this.device.displays?.panels.length??0)>1}cachedScreenshotDisplayMatches(c,d,g){let R=[void 0,"active",c?.display.key,c?.display.role].includes(this.requestedDisplay),A=[void 0,c?.viewHierarchy?.displayId].includes(d),C=!this.hasMultiplePanels()||eg(c?.display,g);return R&&A&&C}}async function Ll(c,d,g){if(d?.packageName!==Ro)return!1;let R=new K,A=!1,C=!1,D=!1,T=!1,k=!1,M=!1;for(let V of R.extractRootNodes(d))R.traverseNode(V,(W)=>{let G=R.extractNodeProperties(W),q=G["resource-id"]??G.resourceId;A||=typeof q==="string"&&q.startsWith(Ol),C||=q===vi,D||=q===bi,T||=q===yi;let X=G.text??G["content-desc"];k||=typeof X==="string"&&/\b(?:isn't|is not) responding\b/i.test(X),M||=X==="Wait"});if(!(A||k&&M||C&&D&&T))return!1;try{let{stdout:V}=await c.executeCommand('shell "dumpsys window"',{signal:g});return/mCurrentFocus=Window\{[^}\r\n]*Application (?:Error:|Not Responding)/.test(V)}catch(V){return e.debug("Failed to read focused framework window from dumpsys:",V),!1}}class _o{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 re(this.device.platform,"Observing the view hierarchy")}get platformValidator(){return this.deps.platformValidator()}get reconciler(){return this.deps.reconciler()}async refreshKnownStaleHierarchy(c,d,g,{remainingMs:R,sideSamples:A}){let C=this.timer.now(),D=await this.readIndependentHierarchy(c.viewHierarchy?.updatedAt,g?.signal,R,"Known-stale hierarchy refresh");if(D?.fresh===!0&&kc(D)&&D.packageName===d&&this.platformValidator.validate(this.hierarchyPlatform,D).valid)await this.reconciler.primeRecapturedHierarchy?.(c,D,g?.signal),this.reconciler.applyRecapturedHierarchy(c,D),this.reconciler.recorrelateActiveWindowToRecapture(c,D),delete c.backStack,delete c.deviceLock,delete c.deviceLockUnknown,await this.resampleAfterStaleWindowRecovery(c,{...A,signal:g?.signal,budgetMs:R-(this.timer.now()-C)})}async resampleAfterStaleWindowRecovery(c,d){let{skipBackStack:g,displayId:R,signal:A,budgetMs:C}=d;if(C<=0)return;let D={...c,deviceLock:void 0,deviceLockUnknown:void 0,backStack:void 0,errors:void 0},T=new AbortController,k=A?AbortSignal.any([A,T.signal]):T.signal;try{await l(Promise.all([this.deviceStateCollector.collectDeviceLock(D,k),g?Promise.resolve():this.deviceStateCollector.collectBackStack(D,new U,k,R)]),{timer:this.timer,timeoutMs:C,signal:A,label:"Stale-window side-sample refresh",onTimeout:()=>T.abort()})}catch(M){o(A),e.warn(`[StaleHierarchyRecovery] Stale-window side-sample refresh failed: ${r(M)}`,M);return}if(D.deviceLockUnknown)c.deviceLockUnknown=D.deviceLockUnknown;if(D.deviceLock)c.deviceLock=D.deviceLock;if(D.backStack)c.backStack=D.backStack;for(let M of D.errors??[])pe(c,M)}async verifyCachedAndroidHierarchy(c,d){let g=c.viewHierarchy;if(!g||!this.needsCachedVerification(g,d))return;let R=this.timer.now(),A=await this.readIndependentHierarchy(g.updatedAt,d.signal,d.remainingMs,"Cached hierarchy verification");if(!A||!this.isVerifyingReplacement(A,g))return;let C=ol(A,c.activeWindow);if(await this.reconciler.primeRecapturedHierarchy?.(c,A,d.signal),this.reconciler.applyRecapturedHierarchy(c,A),!C)this.reconciler.recorrelateActiveWindowToRecapture(c,A),delete c.backStack,delete c.deviceLock,delete c.deviceLockUnknown,await this.resampleAfterStaleWindowRecovery(c,{...d.sideSamples,signal:d.signal,budgetMs:d.remainingMs-(this.timer.now()-R)})}needsCachedVerification(c,d){return d.eligible&&this.device.platform==="android"&&c.fresh!==!0&&kc(c)&&d.remainingMs>0}isVerifyingReplacement(c,d){return c.fresh===!0&&kc(c)&&c.packageName===d.packageName&&this.platformValidator.validate(this.hierarchyPlatform,c).valid}async readIndependentHierarchy(c,d,g,R){let A=new AbortController,C=d?AbortSignal.any([d,A.signal]):A.signal;try{return await l(()=>this.viewHierarchy.getViewHierarchy({},{perf:new U,skipWaitForFresh:!0,minTimestamp:Math.max(1,c??1),signal:C,timeoutMs:g,requireFreshExtraction:!0}),{timer:this.timer,timeoutMs:g,signal:d,label:R,onTimeout:()=>A.abort()})}catch(D){o(d),e.warn(`[StaleHierarchyRecovery] ${R} failed: ${r(D)}`,D);return}}}async function Hl(c,d,g=rs){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 g(c.path))throw new t(`Screenshot capture succeeded for device ${d} but the file is missing: ${c.path}`);return c.path}var tg=2;class Lo{pathProtection;device;screenshotUtil;store;completionByJob=new Map;observationResultCountByJob=new Map;constructor(c,d,g=Qr(),R=Vn){this.pathProtection=R;this.device=c,this.screenshotUtil=d,this.store=g}start(c,{perf:d=new U,signal:g,displayId:R,capture:A}={}){this.store.beginObservation(this.device.deviceId,c),d.startOperation("screenshot");let C=this.screenshotUtil.startTrackedCapture(Bo(R,A),{parentSignal:g,coalesceWithPending:!0,queueAfterPendingIfRunning:!0,onComplete:async(D)=>{if(this.completionByJob.set(D.jobId,{aborted:D.aborted,isLatest:D.isLatest}),!D.isLatest){this.store.endObservation(this.device.deviceId,c,vE);return}if(D.aborted){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,c,wP);return}try{await this.handleScreenshotResult(D.result,{ignoreCancel:!0})}catch(T){e.warn(`[OBSERVE] Failed to finalize screenshot capture: ${T}`)}}});this.recordObservationResult(C,c),C.promise.finally(()=>{d.endOperation("screenshot")}).catch((D)=>{e.debug(`[OBSERVE] Screenshot completion rejected: ${r(D)}`)})}async capture(c,{perf:d=new U,signal:g,displayId:R,capture:A}={}){this.store.beginObservation(this.device.deviceId,c),await this.captureWithOptions(c,d,g,{trackerOptions:{coalesceWithPending:!0,queueAfterPendingIfRunning:!0},request:Bo(R,A)})}async captureFresh(c,{perf:d=new U,signal:g,displayId:R,capture:A}={}){this.store.beginObservation(this.device.deviceId,c),await this.captureWithOptions(c,d,g,{trackerOptions:{queueAfterPending:!0},request:Bo(R,A)})}async captureSettled(c,{perf:d=new U,signal:g,displayId:R,options:A}={}){this.store.beginObservation(this.device.deviceId,c);try{return await d.track("screenshot",async()=>{for(let C=0;C<tg;C++){let{result:D,cancelled:T}=await this.captureSettledAttempt(g,R,A);if(T&&C===0&&!g?.aborted){e.debug("[OBSERVE] Retrying screenshot cancelled by another capture");continue}if(D.path)await this.pathProtection.protect(D.path);let k=await Hl(T?{success:!1,error:D.error??Ye}:D,this.device.deviceId);return this.store.update(this.device.deviceId,k),this.store.updateForObservation(this.device.deviceId,c,{path:k,imageSize:D.screenshotImageSize}),k}throw new t("Screenshot capture retry exhausted")})}catch(C){let D=r(C);throw this.store.updateForObservation(this.device.deviceId,c,{error:D}),e.warn(`[OBSERVE] Settled screenshot capture failed: ${D}`),u(C,`Failed to capture screenshot for device ${this.device.deviceId}`)}}async captureSettledAttempt(c,d,g){let R=this.screenshotUtil.startTrackedCapture({...g,format:g?.format??"png",displayId:d},{parentSignal:c,queueAfterPending:!0});Pe.registerCompletionReader(R.jobId);try{let A=await R.promise,C=Pe.getCompletion(R.jobId);return{result:A,cancelled:R.signal.aborted||C?.aborted===!0||C?.isLatest===!1||A.error?.includes(Ye)===!0}}finally{Pe.releaseCompletionReader(R.jobId)}}async captureWithOptions(c,d,g,{trackerOptions:R,request:A}){try{await d.track("screenshot",async()=>{let C=this.screenshotUtil.startTrackedCapture(A,{parentSignal:g,...R,onComplete:async(T)=>{if(this.completionByJob.set(T.jobId,{aborted:T.aborted,isLatest:T.isLatest}),!T.isLatest){this.store.endObservation(this.device.deviceId,c,vE);return}if(T.aborted){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,c,wP);return}try{await this.handleScreenshotResult(T.result,{ignoreCancel:!0})}catch(k){e.warn(`[OBSERVE] Failed to finalize screenshot capture: ${k}`)}}}),D=this.recordObservationResult(C,c);await C.promise,await D})}catch(C){let D=r(C);if(D.includes(Ye)){e.debug("[OBSERVE] Screenshot capture cancelled");return}this.store.update(this.device.deviceId,void 0,D),this.store.updateForObservation(this.device.deviceId,c,{error:D}),e.warn(`[OBSERVE] Screenshot capture failed: ${D}`)}}async handleScreenshotResult(c,d={}){let g=(A,C)=>{if(d.updateDeviceWide!==!1)this.store.update(this.device.deviceId,A,C);if(d.observationId)this.store.updateForObservation(this.device.deviceId,d.observationId,{path:A,error:C,imageSize:c.screenshotImageSize})};if(!c.success){let A=c.error||"Failed to capture screenshot";if(d.ignoreCancel&&A.includes(Ye)){if(e.debug("[OBSERVE] Screenshot capture cancelled"),d.observationId)this.store.endObservation(this.device.deviceId,d.observationId,wP);return}g(void 0,A),e.warn(`[OBSERVE] Screenshot capture failed: ${A}`);return}if(!c.path){g(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 rs(c.path)){g(void 0,"Screenshot file missing after capture"),e.warn(`[OBSERVE] Screenshot capture reported success but file missing: ${c.path}`);return}g(c.path)}recordObservationResult(c,d){Pe.registerCompletionReader(c.jobId),this.observationResultCountByJob.set(c.jobId,(this.observationResultCountByJob.get(c.jobId)??0)+1);let g=!1,R=()=>{if(g)return;g=!0,Pe.releaseCompletionReader(c.jobId);let A=(this.observationResultCountByJob.get(c.jobId)??1)-1;if(A<=0){this.observationResultCountByJob.delete(c.jobId),this.completionByJob.delete(c.jobId);return}this.observationResultCountByJob.set(c.jobId,A)};return c.promise.then(async(A)=>{let C=Pe.getCompletion(c.jobId)??this.completionByJob.get(c.jobId);if(R(),!C||C.aborted||!C.isLatest){e.debug("[OBSERVE] Screenshot capture cancelled"),this.store.endObservation(this.device.deviceId,d,C?.isLatest===!1?vE:wP);return}await this.handleScreenshotResult(A,{ignoreCancel:!0,observationId:d,updateDeviceWide:!1})}).catch((A)=>{R();let C=r(A);this.store.updateForObservation(this.device.deviceId,d,{error:C}),e.warn(`[OBSERVE] Failed to record screenshot for observation ${d}: ${C}`)})}}function Bo(c,d){return d?.hidePrototypes===!0?{displayId:c,hidePrototypes:!0}:{displayId:c}}function rg(c){return typeof c==="number"?{timeoutMs:c}:c}class Ho{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(g){e.warn("[HierarchyCollector] Failed to report lost availability:",g)}}async collect(c,d={}){let{queryOptions:g,perf:R=new U,skipWaitForFresh:A=!1,minTimestamp:C=0,signal:D,readOnly:T=!1,capturedHierarchy:k,readOptions:M}=d,{device:F,viewHierarchy:V,adb:W,timer:G}=this.opts;try{if(F.platform==="android"&&!T)await V.configureRecompositionTracking(!0,R,D);let q=G.now(),X=k??await V.getViewHierarchy(g,{perf:R,skipWaitForFresh:A,minTimestamp:C,signal:D,...rg(M)});if(e.debug("Accessibility service availability cached as: true"),X)this.attachHierarchy(c,X,V,F);e.debug(`View hierarchy retrieval took ${G.now()-q}ms`)}catch(q){e.warn("Failed to get view hierarchy:",q);try{le.getInstance(F,{create:()=>W}).clearAvailabilityCache()}catch(X){e.debug(`[HierarchyCollector] Failed to clear availability cache: ${X}`)}this.reportHierarchyError(c,F,q)}}reportHierarchyError(c,d,g){let R=String(g);if(d.platform==="android"&&(R.includes(Mo)||R.includes("Failed to connect to accessibility service")))try{this.opts.onAvailabilityLost?.(`CtrlProxy hierarchy connection lost: ${R}`)}catch(A){e.warn("[HierarchyCollector] Failed to report lost availability:",A)}if(R.includes("null root node returned by UiTestAutomationBridge")||R.includes("cat:")&&R.includes("No such file or directory")||R.includes("screen appears to be off"))pe(c,{phase:"viewHierarchy",message:"Screen appears to be off or device is locked",cause:R});else pe(c,{phase:"viewHierarchy",message:"Failed to retrieve view hierarchy",cause:R})}attachHierarchy(c,d,g,R){if(c.viewHierarchy=d,this.reportTransportFailureIfAny(R.platform,d),d.updatedAt)c.updatedAt=d.updatedAt,e.debug(`Using updatedAt from view hierarchy: ${d.updatedAt}`);this.attachFocusedElements(c,d,g);try{let A=d.intentChooserDetected;if(c.intentChooserDetected=A,A)e.debug("[ObserveScreen] Intent chooser dialog detected in view hierarchy")}catch(A){e.warn(`[ObserveScreen] Failed to detect intent chooser: ${A}`)}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,g){let R=g.findFocusedElement(d);if(R)c.focusedElement=R,e.debug(`Found focused element: ${R.text||R["resource-id"]||"no text/id"}`);let A=g.findAccessibilityFocusedElement(d);if(A)c.accessibilityFocusedElement=A,e.debug(`Found accessibility-focused element: ${A.text||A["resource-id"]||A["content-desc"]||"no text/id/desc"}`)}async collectRaw(c,d,g){let{device:R,adbFactory:A,timer:C}=this.opts;try{if(R.platform==="android"){let D=(this.opts.androidRawClient??((k,M)=>E.getInstance(k,M)))(R,A),T=await D.requestHierarchySync(new U,!0,d,{displayId:g});if(g===void 0||g===0)D.invalidateCache();if(T?.hierarchy)c.rawViewHierarchy={json:JSON.stringify(T.hierarchy,null,2),source:"accessibility-service",timestamp:C.now(),device:{deviceId:R.deviceId,platform:R.platform}}}else{let D=x.getInstance(R),T=await D.requestHierarchySync(new U,!0,d);if(D.invalidateCache(),T?.hierarchy)c.rawViewHierarchy={xcuitest:JSON.stringify(T.hierarchy,null,2),source:"xcuitest",timestamp:C.now(),device:{deviceId:R.deviceId,platform:R.platform}}}}catch(D){e.warn("[ObserveScreen] Failed to collect raw view hierarchy:",D)}}extractScreenSize(c,d=!1){return c?IO(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 Vl(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 Ul(c,d){for(let g of c.matchAll(/^\s*Display id:\s*(\d+)\s+UXR:\s*DO:\s*(true|false)\s+UxR:\s*(\d+)\s+time:/gm))if(Number(g[1])===d&&Number.isSafeInteger(Number(g[3])))return{requiresDistractionOptimization:g[2]==="true",activeRestrictions:Number(g[3])};return}function $l(c,d){let g=c.trim().split(/\r?\n/).map((A)=>A.trim());if(g[0]===`No DO Activities for ${d}`)return new Set;if(g[0]!==`DO Activities for ${d}`)return;let R=g.slice(1).filter((A)=>A.length>0);if(R.some((A)=>!/^[\w$]+(?:\.[\w$]+)+$/.test(A)))return;return new Set(R)}async function pa(c,d,g,{timeoutMs:R,signal:A}={}){let C=await c.executeCommand(`shell pm list packages --user ${g}`,{timeoutMs:R,noRetry:!0,signal:A});return Gi(C.stdout,d)}class Xm extends Error{details;constructor(c,d={kind:"unavailable",users:[]}){super(c);this.details=d}}class _t{adb;constructor(c){this.adb=c}async resolve(c={}){if(c.explicitUserId!==void 0)return{userId:c.explicitUserId,source:"explicit"};if(c.currentUser){let C=await this.adb.executeCommand("shell am get-current-user",{noRetry:!0,signal:c.signal}),D=Number.parseInt(C.stdout.trim(),10);if(Number.isSafeInteger(D)&&D>=0)return{userId:D,source:"currentUser"}}let d=c.packageName?await this.readForeground(c):void 0;if(d?.match)return d.match;let g=await this.adb.listUsers(c.signal),R=await this.installedCandidates(c,g);return{...R!==g&&R.length===1?{userId:R[0].userId,source:"installedUser"}:this.selectDefaultUser(R,g),...d?.extra}}async readForeground(c){let d=await this.adb.getForegroundApp(c.signal),g=c.includeForegroundApp?{foregroundApp:d}:void 0;if(d&&d.packageName===c.packageName)return{match:{userId:d.userId,source:"foregroundPackage",...g}};return{extra:g}}selectDefaultUser(c,d){let g=c.filter((A)=>A.running&&(A.profileType??zl(A.flags))==="managed");if(g.length===1)return{userId:g[0].userId,source:"managedProfile"};if(g.length>1)throw new Xm(`Android target user is ambiguous: ${g.length} managed profiles are running`,{kind:"ambiguous",users:d});let R=c.find((A)=>A.running&&(A.profileType??zl(A.flags))==="primary");if(R)return{userId:R.userId,source:"primary"};throw new Xm("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 g=d.filter((A)=>A.running);if(g.length<=1)return d;let R=[];for(let A of g)if(await pa(this.adb,c.packageName,A.userId,{signal:c.signal}))R.push(A);if(R.length>0)return R;return e.info(`Android app ${c.packageName} is not installed for any running user; checked users: ${g.map((A)=>A.userId).join(", ")}`),d}}async function oe(c,d,g){let R=await c.execute(["shell",...d],{signal:g});if(R.error)throw new t(`adb shell ${d.join(" ")} failed: ${R.error}`);return R.stdout.replace(/\r\n?/g,`
|
|
53
|
+
`).trim()}function Ge(c){throw new t(`unsupported on this image: ${c}`)}function tr(c,d,g){throw new t(`Invalid ${c} value '${d}'. Expected one of: ${g.join(", ")}.`)}async function Fa(c,d,g){let R=await c.execute([...d],{signal:g});if(R.error)throw new t(`adb ${d.join(" ")} failed: ${R.error}`);return`${R.stdout}
|
|
54
|
+
${R.stderr}`.replace(/\r\n?/g,`
|
|
55
|
+
`).trim()}function si(){let c=Promise.resolve();return(d)=>{let g=c.then(d,d);return c=g.catch(()=>{return}),g}}var fg=(c)=>(d,g)=>new _t(c).resolve({packageName:d,installedOnly:!0,signal:g}).then((R)=>R.userId);function XW(c){let d=c?.currentActivity;if(d?.name!=="com.android.systemui.car.activity.ActivityBlockingActivity")return;let g=c?.activities??[],R=g.findIndex((C)=>C.name===d.name&&C.taskId===d.taskId),A=R<0?void 0:g.slice(R+1).find((C)=>C.taskId!==d.taskId);return{blockedBy:d.name,...A?{blockedActivity:A.name}:{}}}class Vo{opts;constructor(c){this.opts=c}async collectAutomotive(c,d,g=0){if(this.opts.device.formFactor!=="automotive")return;let[R,A]=await Promise.all([this.readAutomotive(["dumpsys","car_service","--services","CarDrivingStateService"],d),this.readAutomotive(["dumpsys","car_service","--services","CarUxRestrictionsManagerService"],d)]),C=Vl(R),D=Ul(A,g);c.automotive={...C!==void 0?{drivingState:C}:{},...D?{uxRestrictions:D}:{},blocked:!1},await this.refreshAutomotiveForegroundActivity(c,d)}async refreshAutomotiveForegroundActivity(c,d){let g=c.automotive;if(!g)return;let R=await this.readForegroundDistractionOptimized(c,d),{drivingState:A,uxRestrictions:C}=g,D=VL(c),T=XW(c.backStack);c.automotive={...A!==void 0?{drivingState:A}:{},...C?{uxRestrictions:C}:{},...R!==void 0?{foregroundActivity:{distractionOptimized:R}}:{},blocked:T!==void 0||C?.requiresDistractionOptimization===!0&&R===!1,...T,...D?{hostRenderedUi:D}:{}}}async readForegroundDistractionOptimized(c,d){let{appId:g,activityName:R}=c.activeWindow??{};if(!g||!R)return;return $l(await this.readAutomotive(["cmd","car_service","get-do-activities",g],d),g)?.has(R.replace(/^\./,`${g}.`))}async readAutomotive(c,d){try{return await oe(this.opts.adb,c,d)}catch(g){return e.warn("Failed to read automotive observation state:",g),""}}async collectWakefulness(c,d){let{adb:g}=this.opts;try{let R=await g.getWakefulness(d);if(R)c.wakefulness=R,c.wakefulnessSource="adb"}catch(R){e.warn("Failed to get wakefulness state:",R)}}async collectDeviceLock(c,d){let{adb:g}=this.opts;try{let R=await g.getDeviceLock(d);if(R)c.deviceLock=R}catch(R){e.warn("Failed to get device lock state:",R)}}async collectBackStack(c,d=new U,g,R=0){let{backStack:A,timer:C}=this.opts;try{let D=C.now(),T=await A.execute(d,g,R);c.backStack=T,e.debug(`Back stack retrieval took ${C.now()-D}ms`)}catch(D){e.warn("Failed to get back stack:",D),pe(c,{phase:"backStack",message:"Failed to retrieve back stack information",cause:String(D)})}}async collectForegroundIdentity(c,d={}){return(await this.collectForegroundSnapshot(c,d))?.packageName??void 0}async collectForegroundSnapshot(c,d={}){let{adb:g}=this.opts;try{return await g.getForegroundApp(c,{displayId:d.displayId??0})}catch(R){if(c?.aborted)e.debug("Failed to get ground-truth foreground app:",R);else e.warn("Failed to get ground-truth foreground app:",R);return null}}async collectFocusedSystemUiSurface(c){let{adb:d}=this.opts;try{let{stdout:g}=await d.executeCommand('shell "dumpsys window"',{signal:c});return Soe(g)}catch(g){return e.debug("Failed to read focused window surface from dumpsys:",g),!1}}async collectActiveWindow(c,d=!1){let{window:g,timer:R}=this.opts;try{let A=R.now(),C=d?await g.getActive(!0,void 0,{cacheResult:!1}):await g.getActive(!0);if(e.debug(`Bootstrap active window retrieval took ${R.now()-A}ms`),C)c.activeWindow=C}catch(A){e.warn("Failed to get bootstrap active window:",A),pe(c,{phase:"activeWindow",message:"Failed to retrieve active window information",cause:String(A)})}}}import $g from"crypto";function qr(c){let d=c.textSize;return typeof d==="number"&&Number.isFinite(d)&&d>0?d:null}var Wl=new WeakMap;function Gl(c){let d=Wl.get(c);if(!d){let g=c.width+1;d=new Int32Array(g*(c.height+1));for(let R=0;R<c.height;R++){let A=0;for(let C=0;C<c.width;C++)A+=c.data[(c.width*R+C)*4+3]===255?1:0,d[(R+1)*g+C+1]=d[R*g+C+1]+A}Wl.set(c,d)}return d}function Kl(c,d,{x:g,y:R,radius:A}){let C=Math.round(uo(g-A,0,c.width-1)),D=Math.round(uo(g+A,0,c.width-1)),T=Math.round(uo(R-A,0,c.height-1)),k=Math.round(uo(R+A,0,c.height-1)),M=c.width+1;return d[(k+1)*M+D+1]-d[T*M+D+1]-d[(k+1)*M+C]+d[T*M+C]>0}function Uo(c,d){return d.left>=0&&d.top>=0&&d.right<=c.width&&d.bottom<=c.height}var vg=6,yg=20,gg=2,bg=10,Xr=8,Sg=256,Rg=0.5,Ag=30,Yr=12;function ql(c,d){return We(c,d)<=20}function We(c,d){let g=c.r-d.r,R=c.g-d.g,A=c.b-d.b;return Math.sqrt(g*g+R*R+A*A)}class $o{resolve;constructor(c){this.resolve=c}isGlyphPixel(c,d,g,{color:R,point:A}){let{x:C,y:D}=A,T=We(R,g.textColor)<=Ag;if(!T&&ql(this.resolve(c,C,D),g.textColor)&&this.isFringeNear(c,d,A,{color:R,...g}))return!0;if(!T||We(R,g.textColor)>=We(R,g.backgroundColor))return!1;return[[Yr,0],[-Yr,0],[0,Yr],[0,-Yr]].filter(([M,F])=>ql(this.resolve(c,uo(C+M,d.left,d.right-1),uo(D+F,d.top,d.bottom-1)),g.backgroundColor)).length>=3}isFringeNear(c,d,g,{color:R,textColor:A,backgroundColor:C}){return this.isFringe(c,{left:Math.max(d.left,g.x-Xr),top:Math.max(d.top,g.y-Xr),right:Math.min(d.right,g.x+Xr),bottom:Math.min(d.bottom,g.y+Xr)},R,{text:A,background:C})}*levelPixels(c,d,g){let R=Math.ceil(d.left),A=Math.ceil(d.top),C=Math.ceil(d.right)-1,D=Math.ceil(d.bottom)-1;for(let T=A;T<=D;T++)for(let k=R;k<=C;k++)if(We(this.resolve(c,k,T),g)<=gg)yield{x:k,y:T}}isFringe(c,d,g,{text:R,background:A}){if(!this.isAntiAliasingBlend(g,A,R))return!1;let C=We(g,R),D=We(g,A),T=(G,q)=>G>=0&&q>=0&&G<c.width&&q<c.height?this.resolve(c,G,q):null,k=(G)=>G!==null&&We(G,R)<C-yg,M=(G)=>G!==null&&We(G,A)<D-bg,F=(G,q,X,J)=>[1,2,3].some((Z)=>k(T(G+X*Z,q+J*Z)))&&[1,2,3].some((Z)=>M(T(G-X*Z,q-J*Z))),V=0,W=0;for(let G of this.levelPixels(c,d,g)){if(V++,F(G.x,G.y,1,0)||F(G.x,G.y,-1,0)||F(G.x,G.y,0,1)||F(G.x,G.y,0,-1))W++;if(V>=Sg)break}return V>0&&W>=V*Rg}isAntiAliasingBlend(c,d,g){let R=g.r-d.r,A=g.g-d.g,C=g.b-d.b,D=R*R+A*A+C*C;if(D===0)return!1;let T=((c.r-d.r)*R+(c.g-d.g)*A+(c.b-d.b)*C)/D;if(T<=0||T>=1)return!1;let k={r:d.r+T*R,g:d.g+T*A,b:d.b+T*C};return We(c,k)<=vg}}var Xl=160,Pg=24,Ig=32,Cg=40,Wo=40,Zr=10,Dg=40,Tg=16384,xg=65536,kg=0.6,Yl=3,Eg=65536;class Go{config;getCachedContrast;constructor(c,d){this.config=c;this.getCachedContrast=d}fringe=new $o((c,d,g)=>this.resolvePixelColor(c,d,g));pixelRGBA(c,d,g){let R=Math.round(d),A=Math.round(g);if(R<0)R=0;else if(R>=c.width)R=c.width-1;if(A<0)A=0;else if(A>=c.height)A=c.height-1;let C=(c.width*A+R)*4;return{r:c.data[C],g:c.data[C+1],b:c.data[C+2],a:c.data[C+3]}}colorClusters(c,d=!0){let g=new Map,R=new Map;for(let A of c){let C=A.r<<16|A.g<<8|A.b,D=d?A.r>>3<<10|A.g>>3<<5|A.b>>3:C,T=(R.get(C)??0)+1;R.set(C,T);let k=g.get(D);if(k)k.r+=A.r,k.g+=A.g,k.b+=A.b,k.count++,k.coreCount=Math.max(k.coreCount,T);else g.set(D,{...A,count:1,coreCount:1})}return Array.from(g.values(),(A)=>({color:{r:Math.round(A.r/A.count),g:Math.round(A.g/A.count),b:Math.round(A.b/A.count)},count:A.count,coreCount:A.coreCount})).sort((A,C)=>C.count-A.count)}elementPixels(c,d){let g=Math.ceil(d.right)-Math.ceil(d.left),R=Math.ceil(d.bottom)-Math.ceil(d.top),A=g*R,C=Math.min(A,4096);return Array.from({length:C},(D,T)=>{let k=Math.floor(T*A/C);return this.resolvePixelColor(c,Math.ceil(d.left)+k%g,Math.ceil(d.top)+Math.floor(k/g))})}perimeterPixels(c,d){let g=[];for(let R=0;R<128;R++){let A=d.left+Math.floor((d.right-d.left-1)*R/127),C=d.top+Math.floor((d.bottom-d.top-1)*R/127);g.push(this.resolvePixelColor(c,A,d.top)),g.push(this.resolvePixelColor(c,A,d.bottom-1)),g.push(this.resolvePixelColor(c,d.left,C)),g.push(this.resolvePixelColor(c,d.right-1,C))}return g}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,g){let R=Math.ceil(d.left),A=Math.ceil(d.top),C=Math.ceil(d.right)-R,D=Math.ceil(d.bottom)-A,T=Math.max(1,Math.ceil(Math.sqrt(C*D/Tg))),k=1/0,M=1/0,F=-1/0,V=-1/0,W=0,G=0;for(let Z=0;Z<D;Z+=T)for(let ee=0;ee<C;ee+=T)if(W++,this.colorDistance(this.resolvePixelColor(c,R+ee,A+Z),g)>Wo)G++,k=Math.min(k,ee),M=Math.min(M,Z),F=Math.max(F,ee),V=Math.max(V,Z);if(G===0||G>W*0.5)return null;let q=T+2,X={left:R+Math.max(0,k-q),top:A+Math.max(0,M-q),right:R+Math.min(C,F+q+1),bottom:A+Math.min(D,V+q+1)};return(X.right-X.left)*(X.bottom-X.top)<=C*D*0.5&&X.right-X.left>=2&&X.bottom-X.top>=2?X:null}hasSolidStroke(c,d,g,R=Zr){return!this.solidStrokeSeeds(c,d,g,R).next().done}*solidStrokeSeeds(c,d,g,R=Zr){let A=Math.ceil(d.left),C=Math.ceil(d.top),D=Math.ceil(d.right)-1,T=Math.ceil(d.bottom)-1,k=(D-A+1)*(T-C+1),M=Math.max(1,Math.ceil(Math.sqrt(k/xg))),F=(W,G)=>this.colorDistance(this.resolvePixelColor(c,W,G),g)<=R,V=(W,G)=>F(W,G)&&(W>A&&F(W-1,G)||W<D&&F(W+1,G))&&(G>C&&F(W,G-1)||G<T&&F(W,G+1));for(let W=C;W<=T;W+=M)for(let G=A;G<=D;G+=M)if(V(G,W))yield{x:G,y:W}}hasGlyphStrokes(c,d,g){let R={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)},A=new Set,C={pixels:Eg},D=0;for(let T of this.solidStrokeSeeds(c,R,g)){if(C.pixels<=0||D>=Yl)break;if(A.has(T.y*c.width+T.x))continue;let k=this.strokeRegion(c,R,g,{seed:T,visited:A,budget:C}),M=k.right-k.left+1,F=k.bottom-k.top+1;if(k.count<=M*F*kg)return!0;D+=Math.min(M,F)*3<=Math.max(M,F)?1:0}return D>=Yl}strokeRegion(c,d,g,{seed:R,visited:A,budget:C}){let D=Math.ceil(d.left),T=Math.ceil(d.top),k=Math.ceil(d.right)-1,M=Math.ceil(d.bottom)-1,F={count:0,left:R.x,top:R.y,right:R.x,bottom:R.y},V=[R.y*c.width+R.x];A.add(V[0]);while(V.length>0&&C.pixels>0){let W=V.pop(),G=W%c.width,q=Math.floor(W/c.width);C.pixels--,F.count++,F.left=Math.min(F.left,G),F.top=Math.min(F.top,q),F.right=Math.max(F.right,G),F.bottom=Math.max(F.bottom,q);let X=[G>D?W-1:-1,G<k?W+1:-1,q>T?W-c.width:-1,q<M?W+c.width:-1];for(let J of X)if(J>=0&&!A.has(J)&&this.isStrokePixel(c,J,g))A.add(J),V.push(J)}return F}isStrokePixel(c,d,g){let R=this.resolvePixelColor(c,d%c.width,Math.floor(d/c.width));return this.colorDistance(R,g)<=Zr}sampleElementColors(c,d){let g=this.interiorBounds(d),R=this.elementPixels(c,g),A=this.colorClusters(R),C=A[0].color,D=this.perimeterPixels(c,d),T=this.colorClusters(D),k=T.filter((te)=>this.isSimilarColor(te.color,C)).reduce((te,ce)=>te+ce.count,0),M=A.filter((te)=>!this.isSimilarColor(te.color,C)&&T.some((ce)=>this.isSimilarColor(te.color,ce.color))).reduce((te,ce)=>te+ce.count,0),F=T.filter((te)=>te.count>=51.2),V=this.perimeterPixels(c,this.interiorBounds(d)).filter((te)=>F.some((ce)=>this.colorDistance(te,ce.color)<=40)).length;if(k<51.2&&M>=R.length*0.1&&V>=256)C=this.averageColor(D);let W=this.inkBounds(c,g,C),G=W?this.elementPixels(c,W):R,X=(W?this.colorClusters(G):A).filter((te)=>te.count>=Math.max(2,G.length*0.0025)&&!this.isSimilarColor(te.color,C)&&(!W||this.colorDistance(te.color,C)>Wo)),J=(te)=>this.hasSolidStroke(c,W??g,te,this.colorDistance(te,C)<=Dg?0:Zr),Z=(te,ce)=>this.fringe.isFringe(c,W??g,te,{text:ce,background:C}),ee=this.selectTextColor(X,C,T,{isSolidStroke:J,isFringe:Z});return{textColor:(W?A.filter((te)=>te.count>=Math.max(2,R.length*0.0025)&&!this.isSimilarColor(te.color,C)&&this.colorDistance(te.color,C)<=Wo&&!T.some((ce)=>this.isSimilarColor(te.color,ce.color))&&this.hasGlyphStrokes(c,g,te.color)):[]).reduce((te,ce)=>this.getCachedContrast(ce.color,C)<this.getCachedContrast(te,C)?ce.color:te,ee),backgroundColor:C}}selectTextColor(c,d,g,{isSolidStroke:R,isFringe:A}){let C=c[0]?.count??0,D=c.filter((T)=>T.count>=C*0.25||T.coreCount>=T.count*0.8&&!g.some((k)=>this.isSimilarColor(T.color,k.color))&&!A(T.color,c[0].color)&&R(T.color));return D.reduce((T,k)=>{let M=this.getCachedContrast(k.color,d),F=this.getCachedContrast(T,d);return M<F?k.color:T},D[0]?.color??d)}async sampleBackgroundColors(c,d,g,R){let A=[];for(let C of R){let D=await this.sampleBackgroundAtPoint(c,d,g,{x:C.x,y:C.y});A.push({x:C.x,y:C.y,ratio:0,backgroundColor:D})}return A}backgroundColorsAtRadius(c,d,g,{x:R,y:A,radius:C}){let D=[];for(let T=-C;T<=C;T++)for(let k=-C;k<=C;k++){let M=uo(R+T,d.left,d.right-1),F=uo(A+k,d.top,d.bottom-1),V=this.resolvePixelColor(c,M,F);if(!this.isSimilarColor(V,g))D.push(V)}return D}async sampleBackgroundAtPoint(c,d,g,{x:R,y:A}){let C=[2,4,6,8];for(let D of C){let T=this.backgroundColorsAtRadius(c,d,g.textColor,{x:R,y:A,radius:D}),k=this.colorClusters(T)[0];if(k&&T.length>=(2*D+1)**2*0.2&&k.count>=T.length*0.2){let M=this.colorClusters(T.filter((F)=>this.isSimilarColor(F,k.color)),!1)[0].color;return this.fringe.isGlyphPixel(c,d,g,{color:M,point:{x:R,y:A}})?g.backgroundColor:M}}return g.backgroundColor}resolvePixelColor(c,d,g){let R=this.pixelRGBA(c,d,g);if(!this.config.compositeOverlays||R.a===255)return{r:R.r,g:R.g,b:R.b};let A=this.findUnderlyingColor(c,d,g);if(!A)return{r:R.r,g:R.g,b:R.b};return this.compositeColors(A,R)}underlyingColorAtRadius(c,d,g,R){for(let A=-R;A<=R;A++)for(let C=-R;C<=R;C++){if(R>1&&Math.abs(A)<R&&Math.abs(C)<R)continue;let D=Math.round(uo(d+A,0,c.width-1)),T=Math.round(uo(g+C,0,c.height-1)),k=(c.width*T+D)*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,g){let R=Gl(c);for(let A=1;A<=12;A++)if(Kl(c,R,{x:d,y:g,radius:A}))return this.underlyingColorAtRadius(c,d,g,A);return null}compositeColors(c,d){let g=d.a/255;return{r:Math.round(d.r*g+c.r*(1-g)),g:Math.round(d.g*g+c.g*(1-g)),b:Math.round(d.b*g+c.b*(1-g))}}detectGradient(c){if(c.length<5)return null;let d=c.map((D)=>D.backgroundColor),g=this.calculateColorVariance(d);if(g<250)return null;let A=this.calculateGradientAxes(c),C=A.direction;if(this.colorDistance(A.startColor,A.endColor)<20)return null;return{isGradient:!0,direction:C,variance:g,startColor:A.startColor,endColor:A.endColor}}calculateColorVariance(c){let d=this.averageColor(c);return c.reduce((R,A)=>{let C=A.r-d.r,D=A.g-d.g,T=A.b-d.b;return R+C*C+D*D+T*T},0)/c.length/3}calculateGradientAxes(c){let d=[...c].sort((ne,de)=>ne.x-de.x),g=[...c].sort((ne,de)=>ne.y-de.y),R=this.averageColor(d.slice(0,3).map((ne)=>ne.backgroundColor)),A=this.averageColor(d.slice(-3).map((ne)=>ne.backgroundColor)),C=this.averageColor(g.slice(0,3).map((ne)=>ne.backgroundColor)),D=this.averageColor(g.slice(-3).map((ne)=>ne.backgroundColor)),T=this.colorDistance(R,A),k=this.colorDistance(C,D),M=d[0].x,F=d[d.length-1].x,V=g[0].y,W=g[g.length-1].y,G=this.closestSample(c,M,V).backgroundColor,q=this.closestSample(c,F,V).backgroundColor,X=this.closestSample(c,M,W).backgroundColor,J=this.closestSample(c,F,W).backgroundColor,Z=this.colorDistance(G,J),ee=this.colorDistance(q,X);if(T>=k&&T>=Z&&T>=ee)return{direction:"horizontal",startColor:R,endColor:A};if(k>=T&&k>=Z&&k>=ee)return{direction:"vertical",startColor:C,endColor:D};if(Z>=ee)return{direction:"diagonal-down",startColor:G,endColor:J};return{direction:"diagonal-up",startColor:X,endColor:q}}closestSample(c,d,g){let R=c[0],A=Number.POSITIVE_INFINITY;for(let C of c){let D=C.x-d,T=C.y-g,k=D*D+T*T;if(k<A)A=k,R=C}return R}getGradientSamplingPoints(c,d){let{left:g,top:R,right:A,bottom:C}=c,D=A-g,T=C-R,k=Math.max(1,Math.floor(Math.min(D,T)*0.1)),M=g+k,F=A-k-1,V=R+k,W=C-k-1,G=5,q=[];for(let X=0;X<5;X++){let J=X/4;if(d==="horizontal")q.push({x:Math.round(M+J*(F-M)),y:Math.round((V+W)/2)});else if(d==="vertical")q.push({x:Math.round((M+F)/2),y:Math.round(V+J*(W-V))});else if(d==="diagonal-up")q.push({x:Math.round(M+J*(F-M)),y:Math.round(W-J*(W-V))});else q.push({x:Math.round(M+J*(F-M)),y:Math.round(V+J*(W-V))})}return q}mergeSamples(c,d){let g=new Set,R=[];for(let A of[...c,...d]){let C=`${A.x},${A.y}`;if(g.has(C))continue;g.add(C),R.push(A)}return R}getSamplingPoints(c,d){let{left:g,top:R,right:A,bottom:C}=c,D=A-g,T=C-R,k=Math.max(1,Math.floor(Math.min(D,T)*0.1)),M=g+k,F=A-k-1,V=R+k,W=C-k-1,G=d===5?[0.5,0.1,0.9]:[0.1,0.5,0.9],q=[];if(d===5)return q.push({x:Math.round(M+G[0]*(F-M)),y:Math.round(V+G[0]*(W-V))}),q.push({x:Math.round(M),y:Math.round(V+G[0]*(W-V))}),q.push({x:Math.round(F),y:Math.round(V+G[0]*(W-V))}),q.push({x:Math.round(M+G[0]*(F-M)),y:Math.round(V)}),q.push({x:Math.round(M+G[0]*(F-M)),y:Math.round(W)}),q;for(let X of G)for(let J of G)q.push({x:Math.round(M+X*(F-M)),y:Math.round(V+J*(W-V))});if(d===13)q.push({x:Math.round(M),y:Math.round(V)}),q.push({x:Math.round(F),y:Math.round(V)}),q.push({x:Math.round(M),y:Math.round(W)}),q.push({x:Math.round(F),y:Math.round(W)});return q}detectTextShadow(c,d,g,R){let{left:A,top:C,right:D,bottom:T}=d,k=1,M=[{x:A+1,y:C+1},{x:D-1-1,y:C+1},{x:A+1,y:T-1-1},{x:D-1-1,y:T-1-1},{x:Math.round((A+D)/2),y:C+1},{x:Math.round((A+D)/2),y:T-1-1},{x:A+1,y:Math.round((C+T)/2)},{x:D-1-1,y:Math.round((C+T)/2)}],F=this.relativeLuminance(g),V=this.relativeLuminance(R),W=F>V;return M.reduce((q,X)=>{let J=this.resolvePixelColor(c,X.x,X.y);if(this.isSimilarColor(J,g))return q;let Z=this.relativeLuminance(J);if(W&&Z<V-0.05)return q+1;if(!W&&Z>V+0.05)return q+1;return q},0)>=3}applyShadowAdjustment(c,d,g,R){if(!g||!this.isLargeText(d,R))return c;return Math.max(3,c-0.5)}requiredRatioFor(c,d,g,R){return this.applyShadowAdjustment(this.getRequiredContrastRatio(c,d,R),c,g,R)}isLargeText(c,d){if(!d||d<=0)return!1;let g=qr(c);if(g!==null)return g*Xl/d>=Pg;let A=(c.bounds.bottom-c.bounds.top)*Xl/d;return A>=Ig&&A<Cg}isSimilarColor(c,d){return this.colorDistance(c,d)<=20}colorDistance(c,d){let g=c.r-d.r,R=c.g-d.g,A=c.b-d.b;return Math.sqrt(g*g+R*R+A*A)}averageColor(c){if(c.length===0)return{r:128,g:128,b:128};let d=c.reduce((g,R)=>({r:g.r+R.r,g:g.g+R.g,b:g.b+R.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,g=c.g/255,R=c.b/255,A=d<=0.03928?d/12.92:Math.pow((d+0.055)/1.055,2.4),C=g<=0.03928?g/12.92:Math.pow((g+0.055)/1.055,2.4),D=R<=0.03928?R/12.92:Math.pow((R+0.055)/1.055,2.4);return 0.2126*A+0.7152*C+0.0722*D}calculateContrastRatio(c,d){let g=this.relativeLuminance(c),R=this.relativeLuminance(d),A=Math.max(g,R),C=Math.min(g,R);return(A+0.05)/(C+0.05)}getRequiredContrastRatio(c,d,g){let R=this.isLargeText(c,g);if(d==="AAA")return R?4.5:7;else if(d==="AA")return R?3:4.5;else return R?3:4.5}}import Jl from"fs/promises";function Og(c){return{screenshots:c.maxCacheSize?.screenshots??10,colorPairs:c.maxCacheSize?.colorPairs??1000,elements:c.maxCacheSize?.elements??500,backgrounds:c.maxCacheSize?.backgrounds??200}}function Mg(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:Og(c)}}class ei{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,g=As(),R={readFile:Jl.readFile}){this.deps=R;this.timer=d,this.backend=g,this.config=Mg(c),this.imageAnalysis=new Go(this.config,(A,C)=>this.getCachedContrast(A,C))}async checkContrast(c,d,g,R){try{if(this.config.enableElementCache){let W=this.elementCacheKey(d,g,R),G=await this.getScreenshotFingerprint(c),q=this.elementCache.get(W);if(q&&q.screenshotFingerprint===G)return this.elementHits++,q.result;this.elementMisses++}let{left:A,top:C,right:D,bottom:T}=d.bounds,k=D-A,M=T-C;if(k<2||M<2)return null;let F=await this.getOrLoadScreenshot(c),V=await this.checkContrastWithImage(F,d,g,R);if(V&&this.config.enableElementCache){let W=this.elementCacheKey(d,g,R),G=await this.getScreenshotFingerprint(c);this.elementCache.set(W,{result:V,timestamp:this.timer.now(),screenshotFingerprint:G}),this.cleanupCache(this.elementCache,this.config.maxCacheSize.elements)}return V}catch(A){return e.warn(`Contrast checking error: ${r(A)}`,A),null}}getBatchCachedContrast(c,d,g,R){if(!this.config.enableElementCache)return;let A=this.elementCacheKey(c,d,R),C=this.elementCache.get(A);if(C&&C.screenshotFingerprint===g)return this.elementHits++,C;this.elementMisses++;return}cacheBatchContrast(c,d,g,{result:R,density:A}){if(R&&this.config.enableElementCache){let C=this.elementCacheKey(c,d,A);this.elementCache.set(C,{result:R,timestamp:this.timer.now(),screenshotFingerprint:g})}}async checkContrastBatch(c,d,g,R){return(await this.checkContrastBatchWithCoverage(c,d,g,R)).results}async checkContrastBatchWithCoverage(c,d,g,R){let A=new Map,C=[];try{let D=await this.getOrLoadScreenshot(c),T=await this.getScreenshotFingerprint(c);for(let k of d){if(!Uo(D,k.bounds)){C.push(k);continue}A.set(k,await this.checkBatchElement(D,k,g,{screenshotFingerprint:T,density:R}))}if(this.config.enableElementCache)this.cleanupCache(this.elementCache,this.config.maxCacheSize.elements)}catch(D){e.warn(`Batch contrast checking error: ${r(D)}`,D),C.length=0;for(let T of d)A.set(T,null)}return{results:A,outsideImage:C}}async checkBatchElement(c,d,g,{screenshotFingerprint:R,density:A}){try{let C=this.getBatchCachedContrast(d,g,R,A);if(C)return C.result;let D=await this.checkContrastWithImage(c,d,g,A);return this.cacheBatchContrast(d,g,R,{result:D,density:A}),D}catch(C){return e.warn(`Error checking contrast for element: ${r(C)}`,C),null}}async checkContrastWithImage(c,d,g,R){let{left:A,top:C,right:D,bottom:T}=d.bounds,k=D-A,M=T-C;if(k<2||M<2)return null;if(!Uo(c,d.bounds))return null;let{textColor:F,backgroundColor:V}=this.imageAnalysis.sampleElementColors(c,d.bounds);if(!this.config.useMultiPointSampling){let ge=V,Ae=this.getCachedContrast(F,ge),Jt=this.config.detectTextShadows?this.imageAnalysis.detectTextShadow(c,d.bounds,F,ge):!1,Ss=this.imageAnalysis.getRequiredContrastRatio(d,g,R),fp=this.imageAnalysis.applyShadowAdjustment(Ss,d,Jt,R),hp=Ae>=this.imageAnalysis.requiredRatioFor(d,"AA",Jt,R),vp=Ae>=this.imageAnalysis.requiredRatioFor(d,"AAA",Jt,R);return{ratio:Ae,minRatio:Ae,maxRatio:Ae,avgRatio:Ae,samples:[{x:Math.floor((A+D)/2),y:Math.floor((C+T)/2),ratio:Ae,backgroundColor:ge}],textColor:F,backgroundColor:ge,shadowDetected:Jt,baseRequiredRatio:Ss,meetsAA:hp,meetsAAA:vp,requiredRatio:fp}}let W=this.imageAnalysis.getSamplingPoints(d.bounds,this.config.samplingPoints),G=await this.imageAnalysis.sampleBackgroundColors(c,d.bounds,{textColor:F,backgroundColor:V},W),q=this.config.detectGradients?this.imageAnalysis.detectGradient(G):null,X=G,J;if(q?.isGradient){J=q;let ge=this.imageAnalysis.getGradientSamplingPoints(d.bounds,J.direction),Ae=await this.imageAnalysis.sampleBackgroundColors(c,d.bounds,{textColor:F,backgroundColor:V},ge);X=this.imageAnalysis.mergeSamples(G,Ae)}let Z=X.map((ge)=>{let Ae=this.getCachedContrast(F,ge.backgroundColor);return{...ge,ratio:Ae}}),ee=Z.map((ge)=>ge.ratio),ne=Math.min(...ee),de=Math.max(...ee),te=ee.reduce((ge,Ae)=>ge+Ae,0)/ee.length,ce=this.imageAnalysis.averageColor(Z.map((ge)=>ge.backgroundColor));this.setBackgroundCache(d.bounds,ce);let Yt=this.config.detectTextShadows?this.imageAnalysis.detectTextShadow(c,d.bounds,F,ce):!1,bs=this.imageAnalysis.getRequiredContrastRatio(d,g,R),up=this.imageAnalysis.applyShadowAdjustment(bs,d,Yt,R),pp=ne>=this.imageAnalysis.requiredRatioFor(d,"AA",Yt,R),mp=ne>=this.imageAnalysis.requiredRatioFor(d,"AAA",Yt,R);return{ratio:ne,minRatio:ne,maxRatio:de,avgRatio:te,samples:Z,textColor:F,backgroundColor:ce,gradient:J,shadowDetected:Yt,baseRequiredRatio:bs,meetsAA:pp,meetsAAA:mp,requiredRatio:up}}async getOrLoadScreenshot(c){if(!this.config.enableScreenshotCache)return await this.decodeScreenshot(c);let d=this.screenshotCache.get(c),g=this.timer.now();if(d&&g-d.timestamp<this.config.screenshotCacheTTL){let C=await this.getScreenshotFingerprint(c);if(d.fingerprint===C)return this.screenshotHits++,d.image}this.screenshotMisses++;let R=await this.decodeScreenshot(c),A=await this.getScreenshotFingerprint(c);return this.screenshotCache.set(c,{image:R,timestamp:g,fingerprint:A}),this.cleanupCache(this.screenshotCache,this.config.maxCacheSize.screenshots),R}async decodeScreenshot(c){let d=await this.deps.readFile(c);return this.backend.rawPixels(d)}async getScreenshotFingerprint(c){try{let d=await Jl.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,g){return JSON.stringify({text:c.text,bounds:c.bounds,class:c.class,textSize:qr(c),wcagLevel:d,density:g&&g>0?g:null})}getCachedContrast(c,d){if(!this.config.enableColorPairCache)return this.imageAnalysis.calculateContrastRatio(c,d);let g=this.colorPairKey(c,d),R=this.contrastCache.get(g);if(R!==void 0)return this.colorPairHits++,R;return this.colorPairMisses++,R=this.imageAnalysis.calculateContrastRatio(c,d),this.contrastCache.set(g,R),this.cleanupCache(this.contrastCache,this.config.maxCacheSize.colorPairs),R}colorPairKey(c,d){let g=c.r+c.g+c.b,R=d.r+d.g+d.b,[A,C]=g>R?[c,d]:[d,c];return`${A.r},${A.g},${A.b}:${C.r},${C.g},${C.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 g=Array.from(c.entries()).sort((A,C)=>{if(typeof A[1]==="number"||typeof C[1]==="number")return 0;return A[1].timestamp-C[1].timestamp}),R=c.size-d;for(let A=0;A<R;A++)c.delete(g[A][0])}setBackgroundCache(c,d){if(!this.config.enableBackgroundCache)return;let g=`${c.left},${c.top},${c.right},${c.bottom}`;if(this.bgColorCache.set(g,d),this.bgColorCache.size>this.config.maxCacheSize.backgrounds){let R=this.bgColorCache.keys().next().value;if(R)this.bgColorCache.delete(R)}}}var _g=1,ti=2,Fg=3;function Lg(c){let d=c.occlusionState;return d==="partial"||d==="hidden"}function Hg(c,d){if(c.type===ti)return!(d?.type===ti||d?.windowLayer!==void 0&&c.windowLayer!==void 0&&d.windowLayer>c.windowLayer);if(c.type!==_g&&c.type!==Fg)return!1;return d?.windowLayer!==void 0&&c.windowLayer!==void 0&&c.windowLayer>d.windowLayer}function Vg(c,d,g){let R=d===void 0?void 0:g.find((A)=>A.id===d);return g.some((A)=>{let C=wt(A.bounds);return C!==null&&A!==R&&Hg(A,R)&&Ut(c.bounds,C)!==null})}function Ql(c,d,g=[]){return!Lg(c)&&!Vg(c,d,g)}function Zl(c,d,g=[]){let R=d===void 0?void 0:g.find((C)=>C.id===d);if(R)return R.type===ti;let A=c.package??c["resource-id"]?.split(":id/")[0];return A!==void 0&&g.some((C)=>C.type===ti&&C.packageName===A)}class Ko{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,g){await this.db.insertInto("accessibility_baselines").values({screen_id:c,violations_json:d,updated_at:g}).onConflict((R)=>R.column("screen_id").doUpdateSet({violations_json:d,updated_at:g})).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(f`datetime(updated_at)`,"<",f`datetime(${c})`).executeTakeFirst();return Number(d.numDeletedRows)||0}}var Ug=j(ho((c)=>typeof c==="object"&&c!==null&&("fingerprint"in c)&&typeof c.fingerprint==="string"));class XL{repository;constructor(c){this.repository=new Ko({db:c})}async getBaseline(c){let d=await this.repository.get(c);if(!d)return null;let g=this.parseViolations(d.violations_json,d.screen_id);if(g===null)return null;return{screenId:d.screen_id,violations:g,updatedAt:d.updated_at}}parseViolations(c,d){try{return Ug.parse(JSON.parse(c))}catch(g){return e.warn(`[BaselineManager] Corrupt violations_json for screen "${d}"; ignoring baseline row`,g),null}}async saveBaseline(c,d){let g=new Date().toISOString(),R=JSON.stringify(d);await this.repository.upsert(c,R,g)}async clearBaseline(c){await this.repository.delete(c)}async listBaselines(){let c=await this.repository.list(),d=[];for(let g of c){let R=this.parseViolations(g.violations_json,g.screen_id);if(R===null)continue;d.push({screenId:g.screen_id,violations:R,updatedAt:g.updated_at})}return d}async clearAllBaselines(){await this.repository.deleteAll()}async cleanupOldBaselines(c=oD.baselineDays){let d=qW(c);return this.repository.deleteOlderThan(d)}}var Gg="no screenshot for this observation",Kg="text elements are covered by the keyboard or another window, or partly hidden, so the screenshot does not show them",zg="text elements extend beyond the screenshot";function jg(c){return[{count:c.covered,reason:Kg},{count:c.outsideImage,reason:zg}].filter(({count:d})=>d>0).map(({count:d,reason:g})=>({check:"insufficient-contrast",reason:`${d} ${g}`}))}var hg=50,eu={error:0,warning:1,info:2};function tu(c){let d=c.violations.length;if(d<=hg)return c;let g=[...c.violations].sort((C,D)=>eu[C.severity]-eu[D.severity]),R=g.slice(0,hg),A={};for(let C of g.slice(hg))A[C.type]=(A[C.type]??0)+1;return{...c,violations:R,violationsTruncated:{total:d,omitted:d-R.length,omittedByType:A}}}function qg(c){if(we(c).class||!c.node)return c;let d=Array.isArray(c.node)?c.node:[c.node];return d.find((g)=>we(g)["resource-id"])??d.find((g)=>we(g).class)??c}function Xg(c,d,g){let R=ya(c,g)?.filter((C)=>C.type===1&&(C.packageName===void 0||C.packageName===d)&&C.hierarchy),A=R?.find((C)=>C.isFocused)??R?.find((C)=>C.isActive)??R?.reduce((C,D)=>!C||(D.windowLayer??-1/0)>(C.windowLayer??-1/0)?D:C,void 0);if(!A?.hierarchy)return;return qg(A.hierarchy)}class Zm{contrastChecker;baselineStore;timer;constructor(c=i,d=new XL,g=new ei({},c)){this.contrastChecker=g,this.baselineStore=d,this.timer=c}async audit(c,d,{screenshotPath:g,packageName:R,config:A},C){let{density:D,windows:T,descendantLabelled:k,elementWindowIds:M}=typeof C==="number"?{density:C}:C??{};c=c.filter((Z)=>!Zl(Z,M?.get(Z),T));let F=[];F.push(...this.checkMissingContentDescriptions(c,k));let V;if(g)V=await this.checkContrastRatios(c,g,A,{density:D,coverage:{windows:T??[],elementWindowIds:M}}),F.push(...V.violations);F.push(...this.checkTouchTargetSizes(c,A.level,D)),F.push(...this.checkFormInputLabels(c,d,D));let W=this.generateScreenId(R,d,T),G=F,q=0;if(A.useBaseline){let Z=await this.baselineStore.getBaseline(W);if(Z){let ee=new Set(Z.violations.map((ne)=>ne.fingerprint));G=F.filter((ne)=>!ee.has(ne.fingerprint)),q=F.length-G.length}}let X=this.generateSummary(F,G,q,A),J=V?jg(V):[{check:"insufficient-contrast",reason:Gg}];if(J.length>0)X.notEvaluated=J;return{config:A,summary:X,violations:G,timestamp:this.timer.now(),screenId:W}}async saveBaseline(c){await this.baselineStore.saveBaseline(c.screenId,c.violations)}async clearBaseline(c){await this.baselineStore.clearBaseline(c)}checkMissingContentDescriptions(c,d){let g=[];for(let R of c){if(R.text||R["content-desc"])continue;if(d?.has(R))continue;if(R.clickable||R.focusable||R.checkable)g.push({type:"missing-content-description",severity:"error",criterion:"1.1.1",message:`Interactive element (${R.class||"unknown"}) lacks accessible label`,element:R,details:{explanation:"Clickable, focusable, or checkable elements must have a text label or content-desc for screen readers"},fingerprint:this.generateFingerprint(R,"missing-content-description")})}return g}async checkContrastRatios(c,d,{level:g,contrast:R},{density:A,coverage:C}){let D=[],T=c.filter((G)=>G.text&&G.text.trim().length>0),k=T.filter((G)=>Ql(G,C.elementWindowIds?.get(G),C.windows)),M=T.length-k.length,F=R?new ei(R,this.timer):this.contrastChecker,{results:V,outsideImage:W}=await F.checkContrastBatchWithCoverage(d,k,g,A);for(let[G,q]of V.entries())if(q&&q.minRatio<q.requiredRatio){let X=q.minRatio.toFixed(2),J=q.maxRatio.toFixed(2),Z=q.avgRatio.toFixed(2),ee=q.shadowDetected?" (shadow-enhanced)":"";D.push({type:"insufficient-contrast",severity:g==="AAA"?"warning":"error",criterion:"1.4.3",message:`Text has insufficient contrast ratio: ${X}:1 (required: ${q.requiredRatio}:1)`,element:G,details:{contrastRatio:parseFloat(X),contrastMinRatio:parseFloat(X),contrastMaxRatio:parseFloat(J),contrastAvgRatio:parseFloat(Z),requiredRatio:q.requiredRatio,explanation:`Text color RGB(${q.textColor.r},${q.textColor.g},${q.textColor.b}) on background RGB(${q.backgroundColor.r},${q.backgroundColor.g},${q.backgroundColor.b}). Samples min/avg/max=${X}/${Z}/${J}${ee}.`},fingerprint:this.generateFingerprint(G,"insufficient-contrast")})}return{violations:D,covered:M,outsideImage:W.length}}checkTouchTargetSizes(c,d,g){let R=[];if(!g||g<=0)return R;let A=44,C=g,D=A*(C/Zm.BASELINE_DENSITY_DPI);for(let T of c){if(!T.clickable)continue;let k=T.bounds.right-T.bounds.left,M=T.bounds.bottom-T.bounds.top;if(k<D||M<D){let F=Math.floor(k*Zm.BASELINE_DENSITY_DPI/C),V=Math.floor(M*Zm.BASELINE_DENSITY_DPI/C);R.push({type:"touch-target-too-small",severity:d==="AAA"?"error":"warning",criterion:"2.5.5",message:`Touch target is too small: ${F}x${V}dp (minimum: ${A}x${A}dp)`,element:T,details:{actualSize:{width:F,height:V},requiredSize:{width:A,height:A},explanation:"Touch targets should be at least 44x44 dp to be easily tappable"},fingerprint:this.generateFingerprint(T,"touch-target-too-small")})}}return R}checkFormInputLabels(c,d,g){let R=[],A=c.filter((T)=>T.class?.includes("EditText")||T.class?.includes("Spinner")||T.class?.includes("CheckBox")||T.class?.includes("RadioButton")),C=c.filter((T)=>(!T.class||T.class.includes("TextView"))&&T.text),D=this.labelGapThresholdPx(g);for(let T of A)if(!(T.text||T["content-desc"]||this.hasNearbyLabel(T,C,D)))R.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 R}static LABEL_GAP_DP=50;static BASELINE_DENSITY_DPI=160;static FALLBACK_DENSITY_DPI=320;labelGapThresholdPx(c){let d=c&&c>0?c:Zm.FALLBACK_DENSITY_DPI;return Zm.LABEL_GAP_DP*(d/Zm.BASELINE_DENSITY_DPI)}hasNearbyLabel(c,d,g){let R=1/0;for(let A of d){let C=this.boundingBoxGap(c.bounds,A.bounds);if(C<R)R=C}return R<=g}boundingBoxGap(c,d){let g=Math.max(0,c.left-d.right,d.left-c.right),R=Math.max(0,c.top-d.bottom,d.top-c.bottom);return Math.sqrt(g*g+R*R)}generateFingerprint(c,d){let g=JSON.stringify({type:d,resourceId:c["resource-id"],class:c.class,bounds:c.bounds,text:c.text});return $g.createHash("md5").update(g).digest("hex")}generateScreenId(c,d,g){let R=this.resolveRootNode(d,c,g),A=we(R),C=A.class||"unknown",D=A["resource-id"]||"";return`${c}:${C}:${D}`}resolveRootNode(c,d,g){if(g&&g.length>1){let A=Xg(c,d,g);if(A)return A}let R=c.node;if(Array.isArray(R)&&R.length>0)return R[R.length-1];if(R&&typeof R==="object")return R;return c}generateSummary(c,d,g,R){let A={error:d.filter((k)=>k.severity==="error").length,warning:d.filter((k)=>k.severity==="warning").length,info:d.filter((k)=>k.severity==="info").length},C={"missing-content-description":0,"insufficient-contrast":0,"touch-target-too-small":0,"unlabeled-form-input":0};for(let k of d)C[k.type]++;let D=!0,T;if(R.failureMode==="strict"&&d.length>0)D=!1,T=`Found ${d.length} accessibility violation(s) in strict mode`;else if(R.failureMode==="threshold"){let k=R.minSeverity||"warning",M=d.filter((F)=>{if(k==="error")return F.severity==="error";if(k==="warning")return F.severity==="error"||F.severity==="warning";return!0});if(M.length>0)D=!1,T=`Found ${M.length} violation(s) at or above ${k} severity`}return{totalViolations:c.length,bySeverity:A,byType:C,baselinedViolations:g,passed:D,failureReason:T}}}function ru(c,d){let g=we(c.source).windowId;if(typeof g==="number"&&Number.isInteger(g))return g;return c.parentIndex===void 0?void 0:ru(d[c.parentIndex],d)}var eb=/Image|Icon/i;function ib(c,d,g){if(/\p{L}/u.test(c??""))return!0;return/\p{N}/u.test(c??"")&&nb(d,g)}function nb(c,d){let g=0;for(let R=d.index+1;R<c.length;R++){let A=c[R];if(A.rootGroup!==d.rootGroup||A.depth<=d.depth)break;if(eb.test(A.className??""))return!1;if((A.element?.text??"").trim()||(A.element?.["content-desc"]??"").trim())g+=1}return g===1}function ZL(c,d=new fe){let g=d.project(lt(c)??c),R=[],A=new Set,C=new Map;for(let D of g){if(D.rootGroup!==0||!D.element)continue;R.push(D.element);let T=ru(D,g);if(T!==void 0)C.set(D.element,T);if(!Boolean(D.element.text||D.element["content-desc"])&&D.affordances.includes("tap")&&ib(D.displayedLabel,g,D))A.add(D.element)}return{elements:R,descendantLabelled:A,windowIds:C}}async function ZW(c){if(!c)return;try{return await rs(c)?c:void 0}catch(d){e.warn(`[AccessibilityAudit] Failed to check observation screenshot: ${d}`);return}}class zo{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 g=this.getConfig();if(!g)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 ${g.level} audit for ${c.activeWindow?.appId}`);let R=new Zm(void 0,void 0,this.contrastChecker),{elements:A,descendantLabelled:C,windowIds:D}=ZL(c.viewHierarchy),T=await this.screenshotPathResolver(c.observationId),k=await R.audit(A,c.viewHierarchy.hierarchy,{screenshotPath:T,packageName:c.activeWindow.appId,config:g},{density:c.viewHierarchy.density,windows:c.viewHierarchy.windows,descendantLabelled:C,elementWindowIds:D});if(c.accessibilityAudit=tu(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(R){e.error(`[AccessibilityAudit] Failed to run accessibility audit: ${R}`)}}}class iu{DEFAULT_TTL_MS=60000;cache;timer;constructor(c=new $f){this.timer=c,this.cache=new an(c,{ttlMs:this.DEFAULT_TTL_MS})}async isVoiceOverEnabled(c,d,{featureFlags:g,timeoutMs:R,signal:A}={}){return await this.resolveVoiceOverState(c,d,{featureFlags:g,timeoutMs:R,signal:A})===!0}async isVoiceOverActiveOrUnknown(c,d,{featureFlags:g,timeoutMs:R,signal:A}={}){let C=await this.resolveVoiceOverState(c,d,{featureFlags:g,timeoutMs:R,signal:A});if(C===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 C}async resolveState(c,d,{featureFlags:g,timeoutMs:R,signal:A}={}){return this.resolveVoiceOverState(c,d,{featureFlags:g,timeoutMs:R,signal:A})}async resolveVoiceOverState(c,d,{featureFlags:g,timeoutMs:R,signal:A}={}){if(g?.isEnabled("force-accessibility-mode"))return e.debug(`[IosVoiceOverDetector] Force-enabled via feature flag for device ${c}`),!0;if(g&&!g.isEnabled("accessibility-auto-detect"))return e.debug(`[IosVoiceOverDetector] Auto-detection disabled via feature flag for device ${c}`),!1;let C=this.cache.get(c);if(C!==void 0)return e.debug(`[IosVoiceOverDetector] Using cached result for device ${c}: enabled=${C}`),C;e.debug(`[IosVoiceOverDetector] Detecting VoiceOver state for device ${c}`);let D=this.timer.now(),T=await this.detectVoiceOverState(c,d,R,A),k=this.timer.now()-D;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,g,R){try{let A=await d.requestVoiceOverState(g,void 0,R);if(!A.success)return e.warn(`[IosVoiceOverDetector] VoiceOver detection failed for ${c}: ${A.error}`),null;return e.debug(`[IosVoiceOverDetector] VoiceOver state for device ${c}: enabled=${A.enabled}`),A.enabled}catch(A){return e.error(`[IosVoiceOverDetector] Failed to detect VoiceOver state for device ${c}:`,A),null}}}var ko=new iu;class jo{device;adb;featureFlags;detector;iosDetector;iosClient;constructor(c){this.device=c.device,this.adb=c.adb,this.featureFlags=c.featureFlags,this.detector=c.accessibilityDetector??li,this.iosDetector=c.iosVoiceOverDetector??ko,this.iosClient=c.iosClient}async run(c,d,g){try{await d.track("accessibilityDetection",async()=>{o(g);let R=this.featureFlags??ar.getInstance();if(this.device.platform==="android"){let A=await this.detector.resolveState(this.device.deviceId,this.adb,R);if(A===null){delete c.accessibilityState;return}let{enabled:C,service:D}=A,T=!R.isEnabled("force-accessibility-mode")&&!R.isEnabled("accessibility-auto-detect");c.accessibilityState={enabled:C,service:D,detectionSkipped:T},e.debug(`[AccessibilityDetector] Android accessibility state: enabled=${C}, service=${D}`)}else if(this.device.platform==="ios"){let A=this.iosClient??x.getInstance(this.device),C=await this.iosDetector.resolveState(this.device.deviceId,A,{featureFlags:R});if(C===null){delete c.accessibilityState;return}c.accessibilityState={enabled:C,service:C?"voiceover":"unknown"},e.debug(`[IosVoiceOverDetector] iOS VoiceOver state: enabled=${C}`)}})}catch(R){e.error(`[detectAccessibilityState] Failed to detect accessibility state: ${R}`)}}}function rt(c){return c.timeoutMs+Math.max(0,c.budgetExtensionMs?.()??0)}var sb=100,zt=Symbol("observe-poll-budget-expired"),qo=Symbol("observe-poll-reconciliation-unconfirmed");async function ou(c,{timer:d,remainingMs:g,signal:R,label:A}){if(g<0)return zt;let C=new AbortController,D=Error(`${A} exceeded the remaining ${g}ms budget`);try{return await l(()=>c(He(R,C.signal)),{timer:d,timeoutMs:g+1,signal:R,label:A,timeoutError:()=>D})}catch(T){if(T!==D)throw T;return C.abort(new DOMException(D.message,"TimeoutError")),e.debug(`[ObservePoll] ${D.message}; aborted the read`),zt}}function cb(c,d,g){return g!==void 0&&(d<=0||c.hardBudget===!0&&d<sb)}function Yo(c){return c.wakefulness==="Asleep"}function db(c){return Yo(c)&&c.wakefulnessSource==="adb"}function su(c){let d=c.viewHierarchy;if(!d||typeof d.hierarchy!=="object"||d.hierarchy===null||"error"in d.hierarchy)return;return hn(d)}function au(c,d,g){if(c)return d!==void 0&&d>0?d:0;return g!==void 0&&g>0?g+1:0}async function lb(c,d,g,R){let A=Error("Observe poll finalization deadline reached"),C;try{await l(c,{timer:d,timeoutMs:Math.max(0,g),signal:R,label:"Observe poll finalization",timeoutError:()=>A}),C="settled"}catch(D){if(R?.aborted)C="aborted";else if(D===A)C="deadline";else throw D}if(C==="settled")return;c.then(()=>{e.debug("[ObservePoll] Background terminal finalization settled after poll completion")}).catch((D)=>{e.debug(`[ObservePoll] Background terminal finalization failed: ${D}`)})}function ub(c){return su(c)!==void 0&&c.freshness?.isFresh!==!1&&c.freshness?.verified!==!1}function pb(c){return c.freshness?.isFresh===!1||c.freshness?.verified===!1}function mb(c,d){return{capture:d??c,canProcessRecomposition:d!==void 0}}function fb(c,d,g){return c!==void 0&&(d===void 0||c>=d)&&!g}function cu(c,d){let g=su(c),R=pb(c);if(d.enteringReference===void 0&&g!==void 0)d.enteringReference=g;let A=fb(g,d.deviceFloor,R);if(A&&g!==void 0)d.deviceFloor=d.deviceFloor===void 0?g:Math.max(d.deviceFloor,g);let C=g!==void 0&&d.enteringReference!==void 0&&g>d.enteringReference&&A;if(C)d.hasPostInvocationEvidence=!0;return{isAdmissibleEvidence:A,isPostInvocation:C}}function hb(c,d,g){let R=Yo(c)&&c.wakefulnessSource==="hierarchy";return db(c)||Yo(c)&&d&&(!R||g)}function vb(c,d,g){if(c.isAdmissibleEvidence)return{previous:c.capture.observation,newestTrustworthyCapture:c.capture};return{previous:d,newestTrustworthyCapture:g}}function yb(c,d,g,{original:R,capture:A}){if(!g.stopped)return;let{options:C,timer:D,start:T,onObservation:k}=c,M=C.resumeOnTerminalMismatch?cu(A.observation,d):{isAdmissibleEvidence:!0,isPostInvocation:!0};if(M.isAdmissibleEvidence&&M.isPostInvocation&&k(A.observation,R,g.polls))return;if(g.stopped=!1,g.terminalReason="timeout",C.resumeOnTerminalMismatch&&D.now()-T<rt(C))return{kind:"resume",outcome:g,capture:A,isAdmissibleEvidence:M.isAdmissibleEvidence};return}function gb(c,d){let{observeScreen:g,timer:R,options:A,start:C}=c;return async(D,T=!0,k,M)=>{let F=await bb(g,R,A,{start:C,observation:D.observation,minTimestamp:au(d.hasPostInvocationEvidence,d.deviceFloor,d.enteringReference)});if(D.waitMs=R.now()-C,F===qo){if(D.stopped)D.stopped=!1,D.terminalReason="timeout"}else if(F){let V=D.observation;D.observation=F.observation,D.polls++,k=F.generation,M=F.cachedAt,T=ub(F.observation);let W=yb(c,d,D,{original:V,capture:F});if(W)return W}if(o(A.signal),A.skipRecompositionTracking&&T&&g.processRecomposition){let V=(async()=>{await g.processRecomposition(D.observation),await g.cacheObserveResult?.(D.observation,k,M)})();await lb(V,R,rt(A)-(R.now()-C),A.signal)}else await g.cacheObserveResult?.(D.observation,k,M);return{kind:"terminal",outcome:D}}}async function Qo(c,d,g,{minTimestamp:R,timeoutMs:A,readBackStackEachPoll:C=g.readBackStackEachPoll,signal:D=g.signal}){let T=c.captureCacheGeneration?.(),k=d.now();return{observation:await c.execute({display:g.display,freshness:g.display===void 0?void 0:"fresh",minTimestamp:R,timeoutMs:A,skipWaitForFresh:g.skipWaitForFresh??!1,requireFreshExtraction:g.requireFreshExtraction,signal:D,skipScreenshot:!0,skipStaleWindowRecovery:!0,skipCache:!0,skipBackStack:C===!0?void 0:!0,skipAccessibilityAudit:!0,skipPerformanceAudit:g.skipPerformanceAudit,skipRecompositionTracking:g.skipRecompositionTracking}),generation:T,cachedAt:k}}function nu(c,d,g,{start:R,label:A}){if(g.hardBudget)return ou(c,{timer:d,remainingMs:rt(g)-(d.now()-R),signal:g.signal,label:A});return l(()=>c(g.signal),{timer:d,signal:g.signal,label:A})}async function bb(c,d,g,{start:R,observation:A,minTimestamp:C}){if(g.readBackStackEachPoll||!c.collectDeferredBackStack)return;let D=await nu((T)=>c.collectDeferredBackStack(A,{signal:T}),d,g,{start:R,label:"Observe poll terminal back stack"});if(o(g.signal),D===zt)return qo;if(!D)return;try{let T=await nu((k)=>Qo(c,d,g,{minTimestamp:C,readBackStackEachPoll:!0,signal:k}),d,g,{start:R,label:"Observe poll attribution reconciliation"});return o(g.signal),T===zt?qo:T}catch(T){o(g.signal),e.warn("[ObservePoll] Terminal attribution poll failed; returning original observation",T);return}}async function Sb(c,d,g,{start:R,minTimestamp:A,lastCapture:C}){let D=rt(g)-(d.now()-R),T=Math.max(1,D);if(!g.hardBudget)return{capture:await Qo(c,d,g,{minTimestamp:A,timeoutMs:T})};let k=await ou((M)=>Qo(c,d,g,{minTimestamp:A,timeoutMs:T,signal:M}),{timer:d,remainingMs:D,signal:g.signal,label:"Observe poll read"});if(o(g.signal),k!==zt)return{capture:k};if(!C)throw new t(`Observe poll read did not finish within its ${rt(g)}ms budget`);return{expired:C}}async function KT(c,d,g,R){let A=d.now(),C,D,T=0,k={enteringReference:g.initialMinTimestampMs,deviceFloor:g.initialMinTimestampMs,hasPostInvocationEvidence:!1},M,F=gb({observeScreen:c,timer:d,options:g,start:A,onObservation:R},k),V=async(G)=>{let{capture:q,canProcessRecomposition:X}=mb(G,M);return(await F({observation:q.observation,polls:T,waitMs:d.now()-A,stopped:!1,terminalReason:"timeout"},X,q.generation,q.cachedAt)).outcome},W=()=>rt(g)-(d.now()-A);while(!0){if(o(g.signal),cb(g,W(),D))return V(D);let G=au(k.hasPostInvocationEvidence,k.deviceFloor,k.enteringReference),q=await Sb(c,d,g,{start:A,minTimestamp:G,lastCapture:D});if(o(g.signal),"expired"in q)return V(q.expired);let{capture:X}=q,{observation:J,generation:Z,cachedAt:ee}=X;T++,D=X;let{isAdmissibleEvidence:ne,isPostInvocation:de}=cu(J,k);if(ne)M=X;if(hb(J,ne,de))return(await F({observation:J,polls:T,waitMs:d.now()-A,stopped:!1,terminalReason:"screen_off"},ne,Z,ee)).outcome;if(ne&&R(J,C,T)&&de){let ce=await F({observation:J,polls:T,waitMs:d.now()-A,stopped:!0,terminalReason:"matched"},!0,Z,ee);if(ce.kind==="terminal")return ce.outcome;T=ce.outcome.polls,D=ce.capture,{previous:C,newestTrustworthyCapture:M}=vb(ce,J,M),await P(d.sleep(Math.min(Math.max(1,g.pollMs),Math.max(0,rt(g)-(d.now()-A)))),g.signal);continue}if(ne)C=J;if(W()<=0)return V(X);await P(d.sleep(Math.min(g.pollMs,Math.max(0,rt(g)-(d.now()-A)))),g.signal)}}var wb=new Set(["text","view-id","visible-to-user"]),Ab=["text","visible-to-user"];function jt(c){let d=c.split("\x00");if(d.length!==4)return;return[d[0],d[1],d[3]].join("\x00")}function Ib(c,d){return uu(Object.keys(NO(c.attributes,d.attributes)))}function uu(c){return Ab.some((d)=>c.includes(d))&&c.every((d)=>wb.has(d))}function du(c){let d=new Map;for(let g of iU(c)){let R=jt(g.key);if(R===void 0)continue;let A=g.pathKey.split(h2).map((C)=>jt(C)??C).join(h2);d.set(R,d.has(R)?null:A)}return d}function Zo(c,d){let g=du(c),R=du(d),A=new Set;for(let C of new Set([...g.keys(),...R.keys()])){let D=g.get(C);if(D===void 0||D===null||D!==R.get(C))A.add(C)}return A}function lu(c){let d=new Map;for(let g of c){let R=jt(g.key);if(R!==void 0)d.set(R,[...d.get(R)??[],g])}return d}function pu(c){return uu(Object.keys(c.changes))}function mu(c,d){let g=new Set,R=lu(c.added);for(let[A,C]of lu(c.removed)){let D=R.get(A);if(C.length===1&&D?.length===1&&Ib(C[0],D[0]))g.add(A)}for(let A of c.changed){let C=jt(A.key);if(C!==void 0&&pu(A))g.add(C)}for(let A of d)g.delete(A);return g}class es{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 g=mu(c,d),R=new Set([...g].filter((A)=>this.volatile.has(A)));for(let A of g)if(this.previousChanges.has(A))this.volatile.add(A);return this.previousChanges=g,fu(c,R)}}function fu(c,d){let g=(R)=>{let A=jt(R);return A!==void 0&&d.has(A)};return{...c,added:c.added.filter((R)=>!g(R.key)),removed:c.removed.filter((R)=>!g(R.key)),changed:c.changed.filter((R)=>!pu(R)||!g(R.key))}}function hu(c,d=new Set){let g=mu(c,d);return{ticks:g.size,rest:fu(c,g)}}var Cb=2500,Db=150,Tb=2;function QL(c){return c.added.length===0&&c.removed.length===0&&c.changed.length===0&&c.fields===void 0}function kb(c,d,g){if(d===void 0||$t(d.viewHierarchy)>0||!Df(d,g))return;c.mask(jp(d,g),Zo(d,g))}class Qm{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??Cb,g=c.pollMs??Db,R=c.stableReads??Tb,A=0,C=!1,D=new es,T=!1,k=Math.max(0,c.volatileExtensionMs??0),M=await KT(this.observeScreen,this.timer,{display:c.display,timeoutMs:d,pollMs:g,signal:c.signal,initialMinTimestampMs:c.initialMinTimestampMs,skipWaitForFresh:c.skipWaitForFresh,get requireFreshExtraction(){return C||c.requireFreshExtraction},resumeOnTerminalMismatch:c.resumeOnTerminalMismatch,hardBudget:c.hardBudget,budgetExtensionMs:()=>T?k:0,skipPerformanceAudit:c.skipPerformanceAudit,skipRecompositionTracking:c.skipRecompositionTracking},(F,V)=>{if(C=$t(F.viewHierarchy)>0,C)return T=!1,A=0,D.reset(),!1;if(V===void 0)return kb(D,c.referenceObservation,F),A=1,A>=R;if(!Df(V,F))return T=!1,D.reset(),A=1,A>=R;let W=jp(V,F),G=Zo(V,F),q=hu(W,G);return T=QL(q.rest)&&(q.ticks>0||T),A=QL(D.mask(W,G))?A+1:1,A>=R});return{observation:M.observation,settled:M.stopped,polls:M.polls,waitMs:M.waitMs,terminalReason:M.terminalReason==="matched"?"settled":M.terminalReason}}}function vu(c){if(c?.cacheStore)Ioe(c.cacheStore);if(c?.screenshotStateStore)_oe(c.screenshotStateStore)}function yu(c){let{device:d,identity:g}=c;return{createHierarchyCapture(R,A){return Pn(d,{viewHierarchy:g.viewHierarchy(),settle:new Qm(c.observeScreenProvider(),R),timer:R,ids:A})},createScreenshotRecorder(R,A){return new Lo(d,R,Qr(),A)},createHierarchyCollector(R){return new Ho({device:d,viewHierarchy:g.viewHierarchy(),adb:c.adb(),adbFactory:c.adbFactory(),timer:g.timer(),onAvailabilityLost:R?.onAvailabilityLost??(d.platform==="android"?(A)=>{let C=R?.daemonState;(C?C.isInitialized()?C.getSessionManager():void 0:w.sessionManager())?.invalidateAutomationReadinessForDevice(d.deviceId,A)}:void 0)})},createDeviceStateCollector(R,A){return new Vo({device:d,window:R,backStack:A,adb:c.adb(),timer:g.timer()})},createPerformanceAuditor(){return new KL({device:d,adbFactory:c.adbFactory(),observeScreenProvider:c.observeScreenProvider})},createAccessibilityAuditor(){return new zo({device:d,screenshotPathResolver:(R)=>ZW(Qr().getPathForObservation(g.device().deviceId,R))})},createAccessibilityStateDetector(){return new jo({device:d,adb:c.adb()})},createWindowIdentity(){return new Qn({deviceStateCollector:g.deviceStateCollector,timer:g.timer,resolveObservationTimestampMs:g.resolveObservationTimestampMs})},createReconciler(){return new zn({xrDisplaySize:c.xrDisplaySize,viewHierarchy:g.viewHierarchy,deviceStateCollector:g.deviceStateCollector,device:g.device,platformValidator:g.platformValidator,resolveObservationTimestampMs:g.resolveObservationTimestampMs,extractScreenSizeFromHierarchy:g.extractScreenSizeFromHierarchy})}}}var ri=/^\s*(?:Task\s+id\s+#(\d+)\b|\*?\s*TaskRecord\{\S+\s+#(\d+)\b(.*))$/,ii=/^\s*\*\s*Task\{\S+\s+#(\d+)\b(.*)$/;var Eb=/^\s*(?:Stack|RootTask)\s+#\d+:(.*)$/,gu=/(?:^|\s)mode=([^\s}]+)/,Ob=/^\s*mBounds=Rect\((-?\d+), (-?\d+) - (-?\d+), (-?\d+)\)/,Mb=/^\s*bounds=\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/,_b=/^\s*CurrentConfiguration=.*?winConfig=\{\s*mBounds=Rect\((-?\d+), (-?\d+) - (-?\d+), (-?\d+)\)/,Fb=/^\s*CurrentConfiguration=.*?\smWindowingMode=([^\s}]+)/,Nb=/^\s*\*\s/;function is(c){if(!c)return;let[d,g,R,A]=c.slice(1,5).map((C)=>Number.parseInt(C,10));return R>d&&A>g?{left:d,top:g,right:R,bottom:A}:void 0}function Bb(c){let d=c.match(ii);if(d)return{id:Number.parseInt(d[1],10),tail:d[2]};let g=c.match(ri);if(g)return{id:Number.parseInt(g[1]??g[2],10),tail:g[3]??""};return}class bu{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(Eb);if(d){this.rootTask={mode:d[1].match(gu)?.[1]},this.current=void 0;return}let g=Bb(c);if(g){this.startTask(g.id,g.tail);return}if(Nb.test(c))this.ownFields=!1;this.fields(c)}startTask(c,d){let g=this.evidence.get(c)??{};this.evidence.set(c,g),g.headerMode??=d.match(gu)?.[1],g.rootTaskMode??=this.rootTask?.mode,g.rootTaskBounds??=this.rootTask?.bounds,this.current=g,this.ownFields=!0}fields(c){let d=c.match(Ob);if(d){this.overrideBounds(is(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 g=d.match(Mb);if(g&&this.ownFields){c.resolved??=is(g);return}let R=d.match(_b);if(R)c.activityBounds??=is(R),c.activityMode??=d.match(Fb)?.[1]}}function Su(c){let d=new bu;for(let R of c.split(/\r?\n/))d.line(R);let g=new Map;for(let[R,A]of d.evidence){let C=A.headerMode??A.rootTaskMode??A.activityMode,D=A.resolved??A.override??A.rootTaskBounds??A.activityBounds;g.set(R,{...C===void 0?{}:{windowingMode:C},...D===void 0?{}:{bounds:D}})}return g}function wu(c,d){for(let g of c){let R=d.get(g.id);if(R?.windowingMode!==void 0)g.windowingMode=R.windowingMode;if(R?.bounds!==void 0)g.bounds=R.bounds}}var Lb=/(?:^|\s)A=([^\s}]+)/,Hb=/(?:^|\s)a?I=([^\s}]+)/,Ub=/(?:^|\s)U=(\d+)(?=\s|})/,$b=/Hist\s+#(\d+):\s+ActivityRecord\{\S+\s+u(\d+)\s+([^\s}]+)([^\n]*\})/;function Du(c){let d=c.match($b);if(!d)return;let g=d[4].match(/(?:^|[\s}])t(\d+)(?=[\s}]|$)/);return{histIndex:parseInt(d[1],10),userId:parseInt(d[2],10),component:d[3],taskId:g?parseInt(g[1],10):void 0}}var Eu=/\bHist\s+#\d+:/,_u=/^\s*rootOfTask=(true|false)\b/;function Ru(c){let d=c.match(ii);if(d)return Cu(parseInt(d[1],10),d[2]);let g=c.match(ri);if(g)return g[1]!==void 0?{id:parseInt(g[1],10)}:Cu(parseInt(g[2],10),g[3]);return}function Cu(c,d){let g=d.match(Lb),R=d.match(Hb),A=d.match(Ub);return{id:c,userId:A?parseInt(A[1],10):void 0,affinity:g?g[1]:void 0,component:R?R[1]:void 0}}function ns(c,d){let g=c.get(d);if(g===void 0)g={},c.set(d,g);return g}function Gb(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 Kb(c,d,g,{histRoots:R,openHist:A}){let C=Du(c);if(C){let D=C.taskId??d;if(g.set(D,(g.get(D)??0)+1),C.histIndex===0)ns(R,D).firstHist0??=C.component;A={owner:D,component:C.component,histIndex:C.histIndex}}else if(Eu.test(c))g.set(d,(g.get(d)??0)+1),A=void 0;return A}function zb(c,d,g){let R=c.match(/launchedFromPackage=([^\s]+)/);if(R&&g){if(g.launchedFromPackage=R[1]==="null"?void 0:R[1],g.histIndex===0&&g.launchedFromPackage!==void 0)ns(d,g.owner).firstHist0LaunchedFromPackage??=g.launchedFromPackage}let A=c.match(_u);if(A&&g){if(A[1]==="true"){let C=ns(d,g.owner);if(C.authoritative===void 0)C.authoritative=g.component,C.authoritativeLaunchedFromPackage=g.launchedFromPackage}g=void 0}return g}function jb(c,d){let g=d.match(/affinity=([^\s]+)/);if(g)c.affinity=g[1];let R=d.match(/realActivity=([^\s]+)/);if(R){let C=R[1];if(c.packageName=C.split("/")[0],!c.rootActivity)c.rootActivity=C}let A=d.match(/numActivities=(\d+)/);if(A)c.numActivities=parseInt(A[1],10)}function qb(c,d,g){if(c.numActivities===void 0)c.numActivities=d.get(c.id)??0;let R=g.get(c.id),A=R?.authoritative!==void 0?R.authoritativeLaunchedFromPackage:R?.firstHist0LaunchedFromPackage;if(A!==void 0)c.launchedFromPackage=A;if(R===void 0||R.firstHist0===void 0)return;let C=R.authoritative??R.firstHist0;if(c.rootActivity===void 0)c.rootActivity=C;if(c.packageName===void 0)c.packageName=C.split("/")[0]}class eB{adb;timer;constructor(c,d=v,g=i){this.adb=d.create(c),this.timer=g}parseActivities(c){let d=[],g=c.split(/\r?\n/),R=-1,A,C;for(let D=0;D<g.length;D++){let T=g[D],k=Ru(T);if(k)R=k.id,A=k.affinity,C=void 0,e.debug(`[BACK_STACK] Found task ID: ${R}`);let M=T.match(/affinity=([^\s]+)/);if(M)A=M[1],e.debug(`[BACK_STACK] Found task affinity: ${A}`);let F=Du(T);if(F){let{histIndex:W,component:G}=F,q=F.taskId??R,X=G.split("/"),J=X[0],Z=X[1]||"";if(Z.startsWith("."))Z=J+Z;let ee={name:Z,taskId:q,userId:F.userId,taskAffinity:A,isTaskRoot:W===0};d.push(ee),C=ee,e.debug(`[BACK_STACK] Found activity: ${Z} (task: ${q})`);continue}if(Eu.test(T)){C=void 0;continue}let V=T.match(_u);if(V&&C)C.isTaskRoot=V[1]==="true",C=void 0}return d}parseTasks(c){let d=new Map,g=c.split(/\r?\n/),R=-1,A={id:-1},C=new Map,D=new Map,T,k=()=>{if(R===-1||A.id===void 0)return;d.set(R,A)};for(let M=0;M<g.length;M++){let F=g[M],V=Ru(F);if(V)k(),R=V.id,A=d.get(R)??{id:R},Gb(A,V),T=void 0,e.debug(`[BACK_STACK] Parsing task: ${R}`);if(R===-1)continue;T=Kb(F,R,C,{histRoots:D,openHist:T}),T=zb(F,D,T),jb(A,F)}k();for(let M of d.values())qb(M,C,D);return Array.from(d.values())}getCurrentActivity(c,d){let g=lR(c,d);if(g.displayCount>0)return g.activity?{name:g.activity.activityName,taskId:g.activity.taskId,userId:g.activity.userId}:void 0;let R=c.split(/\r?\n/);for(let A of R){let C=A.match(/(mResumedActivity|mFocusedActivity|topResumedActivity)\s*[:=].*?u(\d+)\s+([^\s]+)(?:\s+t(\d+))?/);if(C){let D=parseInt(C[2],10),T=C[3],k=C[4]?parseInt(C[4],10):-1,M=T.split("/"),F=M[0],V=M[1]||"";if(V.startsWith("."))V=F+V;return e.debug(`[BACK_STACK] Current activity: ${V} (task: ${k})`),{name:V,taskId:k,userId:D}}}return}async execute(c=new U,d,g=0){let R=this.timer.now();try{e.info("[BACK_STACK] Fetching back stack information via dumpsys");let A=await c.track("dumpsysActivities",()=>this.adb.executeCommand("shell dumpsys activity activities",{maxBuffer:ie,signal:d})),[C,D,T]=await c.track("parseBackStack",()=>Promise.all([Promise.resolve(this.parseActivities(A.stdout)),Promise.resolve(this.parseTasks(A.stdout)),Promise.resolve(this.getCurrentActivity(A.stdout,g))]));wu(D,Su(A.stdout));let k=T?.taskId||-1,M=C.filter((G)=>G.taskId===k),F=Math.max(0,M.length-1),V={depth:F,activities:C,tasks:D,currentActivity:T,displayCount:lR(A.stdout).displayCount,currentTaskId:k,capturedAt:this.timer.now(),source:"adb"},W=this.timer.now()-R;return e.info(`[BACK_STACK] Back stack retrieved in ${W}ms: depth=${F}, activities=${C.length}, tasks=${D.length}, currentActivity=${T?.name||"unknown"}`),V}catch(A){let C=this.timer.now()-R;return e.warn(`[BACK_STACK] Failed to get back stack after ${C}ms: ${A}`),{depth:0,activities:[],tasks:[],capturedAt:this.timer.now(),partial:!0,source:"adb"}}}}var Xb=(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 Yb(c=Xb){return(d)=>{let g=d?c(d):null;return g?he.getInstanceForSession(g):he.getInstance()}}var QW=Yb();function GT(c){if(!c||Object.keys(c).length===0)return"";return Fr(Jb(c))}function io(c){let d=c?.trim();return d?d.toLowerCase():void 0}function Jb(c){let d={...c};return delete d.deviceId,delete d.sessionUuid,d}class tB{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(),g=jr(this.timer),R=GT(c.toolArgs??void 0),A={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:R,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:g};await d.insertInto("prediction_outcomes").values(A).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,g){let R=this.getDb(),A=jr(this.timer),C=GT(c.toolArgs??void 0),D=Math.pow(d-(g?1:0),2),T=g?1:0,k={app_id:c.appId,from_screen:c.fromScreen,to_screen:c.toScreen,tool_name:c.toolName,tool_args:C,attempts:1,successes:T,total_confidence:d,brier_score_sum:D,updated_at:A,created_at:A};return await R.insertInto("prediction_transition_stats").values(k).onConflict((F)=>F.columns(["app_id","from_screen","to_screen","tool_name","tool_args"]).doUpdateSet((V)=>({attempts:V("prediction_transition_stats.attempts","+",1),successes:V("prediction_transition_stats.successes","+",T),total_confidence:V("prediction_transition_stats.total_confidence","+",d),brier_score_sum:V("prediction_transition_stats.brier_score_sum","+",D),updated_at:A}))).returningAll().executeTakeFirstOrThrow()}async getTransitionStatsForScreen(c,d){return this.getDb().selectFrom("prediction_transition_stats").selectAll().where("app_id","=",c).where("from_screen","=",d).execute()}}class os{tapByText=new Map;tapById=new Map;swipeByText=new Map;swipeById=new Map;swipeByDesc=new Map;constructor(c){c.forEach((d,g)=>{let R=d.interaction?.toolName;if(R==="tapOn")this.indexTapEdge(d,g);else if(R==="swipeOn")this.indexSwipeEdge(d,g)})}indexTapEdge(c,d){let g=c.interaction?.args;this.addKey(this.tapByText,io(g?.text),c,d),this.addKey(this.tapById,io(g?.elementId??g?.id),c,d)}indexSwipeEdge(c,d){let R=c.interaction?.args?.container||c.interaction?.uiState?.scrollPosition?.container;if(!R)return;this.addKey(this.swipeByText,io(R.text),c,d),this.addKey(this.swipeById,io(R.elementId||R.resourceId),c,d),this.addKey(this.swipeByDesc,io(R.contentDesc),c,d)}addKey(c,d,g,R){if(!d||c.has(d))return;c.set(d,{edge:g,index:R})}findMatch(c){let d=io(c.text),g=io(c.contentDesc),R=io(c.resourceId),A,C=(D)=>{if(D&&(!A||D.index<A.index))A=D};if(c.clickable){if(d)C(this.tapByText.get(d));if(g)C(this.tapByText.get(g));if(R)C(this.tapById.get(R))}if(c.scrollable){if(d)C(this.swipeByText.get(d));if(g)C(this.swipeByText.get(g)),C(this.swipeByDesc.get(g));if(R)C(this.swipeById.get(R))}return A?.edge}}class ss{resolveNavigationGraph;elementParser;historyRepository;DEFAULT_CONFIDENCE=0.5;constructor(c=QW,d={}){this.resolveNavigationGraph=c;this.elementParser=d.elementParser??new K,this.historyRepository=d.historyRepository??new tB}async generate(c,d){if(!c.viewHierarchy)return;let g=this.resolveNavigationGraph(d),R=g.getCurrentScreen();if(!R)return;let A=g.getCurrentAppId();if(A&&c.activeWindow?.appId&&A!==c.activeWindow.appId)return;let D=(await g.getEdgesFrom(R)).filter((k)=>k.interaction?.toolName==="tapOn"||k.interaction?.toolName==="swipeOn");if(D.length===0)return;let T=this.extractInteractables(c.viewHierarchy);if(T.length===0)return;return this.buildPredictions(T,D,g,{currentScreen:R,appId:A})}async buildPredictions(c,d,g,{currentScreen:R,appId:A}){let C=[],D=[],T=new Set,k=new Map,M=A?await this.historyRepository.getTransitionStatsForScreen(A,R):[],F=new Map;for(let W of M){let G=this.buildTransitionKey(W.from_screen,W.to_screen,W.tool_name,W.tool_args);F.set(G,W)}let V=new os(d);for(let W of c){let G=V.findMatch(W);if(!G||!G.interaction)continue;let q=Qb(G,W);if(!q)continue;let X=this.buildEdgeKey(G);if(!T.has(X)){let J=await this.getPredictedElements(g,G.to,k),Z=this.getAdjustedConfidence(F.get(this.buildTransitionKey(R,G.to,G.interaction.toolName,GT(G.interaction.args))));C.push({action:G.interaction.toolName,target:q,predictedScreen:G.to,predictedElements:J.length>0?J:void 0,confidence:Z}),T.add(X)}D.push({elementId:W.resourceId,elementText:W.text,elementContentDesc:W.contentDesc,predictedOutcome:{screenName:G.to,basedOn:"navigation_graph"}})}if(C.length===0&&D.length===0)return;return{likelyActions:C,interactableElements:D}}extractInteractables(c){if(!c)return[];let d=this.elementParser.flattenViewHierarchy(c),g=[];for(let{element:R}of d){let A=R.clickable===!0||R.clickable==="true",C=R.scrollable===!0||R.scrollable==="true";if(!A&&!C)continue;g.push({element:R,text:R.text,contentDesc:R["content-desc"],resourceId:R["resource-id"],clickable:A,scrollable:C})}return g}buildEdgeKey(c){let d=c.interaction?.args??{};return`${c.from}:${c.to}:${c.interaction?.toolName}:${JSON.stringify(d)}`}buildTransitionKey(c,d,g,R){return`${c}:${d}:${g}:${R}`}getAdjustedConfidence(c){if(!c)return this.DEFAULT_CONFIDENCE;let d=c.attempts,g=d>0?c.successes/d:this.DEFAULT_CONFIDENCE;return this.adjustConfidence(this.DEFAULT_CONFIDENCE,g,d)}adjustConfidence(c,d,g){let R=Math.min(g/100,0.8),A=1-R,C=c*A+d*R;return Math.max(0,Math.min(1,C))}async getPredictedElements(c,d,g){if(g.has(d))return g.get(d)??[];let R=await c.getEdgesFrom(d),A=new Set;for(let D of R){let T=D.interaction?.uiState?.selectedElements;if(!T)continue;for(let k of T){let M=k.text||k.resourceId||k.contentDesc;if(M)A.add(M)}}let C=Array.from(A);return g.set(d,C),C}}function Qb(c,d){let g=c.interaction?.args,R=c.interaction?.uiState,A=c.interaction?.toolName;if(A==="tapOn")return Zb(g,d);if(A==="swipeOn")return eS(g,R);return null}function Zb(c,d){let g=c?.text??d.text,R=c?.elementId??c?.id??d.resourceId,A=d.contentDesc;if(!g&&!R&&!A)return null;return{text:g,elementId:R,contentDesc:A}}function eS(c,d){let{container:g,lookFor:R}=tS(c,d),A={};if(g)A.container=Fu(g);if(R)A.lookFor=Fu(R);if(!A.container&&!A.lookFor)return null;return A}function tS(c,d){let g=c?.container||d?.scrollPosition?.container,R=c?.lookFor||d?.scrollPosition?.targetElement;return{container:g,lookFor:R}}function Fu(c){return{text:c.text,elementId:c.elementId||c.resourceId,contentDesc:c.contentDesc}}class as{inner;timer;observeBudgetMs;constructor(c,d,g=750){this.inner=c;this.timer=d;this.observeBudgetMs=g}async read(c,d){let g=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:()=>g})}catch(R){if(d?.aborted)return e.debug("[iOS] Lock-state caller aborted"),{kind:"unknown",reason:"pending",message:"caller aborted"};if(R===g)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(R)}`,R),{kind:"unknown",reason:"error",message:r(R)}}}}class cs{inner;timer;options;entries=new Map;settling=new Set;epochs=new Map;lockTransitions=new Map;constructor(c,d,g={}){this.inner=c;this.timer=d;this.options=g}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(g){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(g)}`,g),{kind:"unknown",reason:"error",message:r(g)}}}sharedRead(c){let d=this.entries.get(c);if(d?.reading){if(this.timer.now()<d.expiresAt){let R=d.reading.kind==="known"?void 0:this.staleReading(d);return Promise.resolve(R??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 g=this.staleReading(d);return g?Promise.resolve(g):d.flight}staleReading(c){let d=c.lastKnown;if(!d)return;let g=d.lock.locked?this.options.staleLockedMs??1e4:this.options.staleUnlockedMs??120000;return this.timer.now()-d.staleSince<g?{kind:"known",lock:d.lock}:void 0}async readInner(c){try{return await Xe(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,g){let R=this.lockTransitions.get(c);return R!==void 0&&this.isCurrent(c,d)&&g.kind==="known"&&!g.lock.locked&&this.timer.now()<R}async awaitLockTransition(c,d,g){let R=g;while(this.awaitingLock(c,d,R))await this.timer.sleep(this.options.lockTransitionPollMs??250),R=await this.readInner(c);return R}async fill(c,d){let g;try{g=await Xe(async()=>this.inner.read(c))}catch(R){g=this.probeFailure(R)}if(this.awaitingLock(c,d,g))g=await this.awaitLockTransition(c,d,g);if(this.isCurrent(c,d)){let R=this.options.failureTtlMs??5000;if(g.kind==="known"){if(this.lockTransitions.delete(c),R=g.lock.locked?this.options.lockedTtlMs??2000:this.options.knownTtlMs??30000,this.settling.delete(c))R=Math.min(R,this.options.settleTtlMs??2000)}if(d.reading=g,d.expiresAt=this.timer.now()+R,g.kind==="known")d.lastKnown={lock:g.lock,staleSince:d.expiresAt};d.flight=void 0}return g}}var rS;function Tu(){return rS??=new cs(new FT(new L,{timeoutMs:4000}),i)}var iS={getViewHierarchy:async()=>({hierarchy:{error:"Hierarchy connection unavailable",unavailableReason:"connection_lost"}}),configureRecompositionTracking:async()=>{},findFocusedElement:()=>null,findAccessibilityFocusedElement:()=>null,filterOffscreenNodes:(c)=>c};function ye(c,d){return c??d()}function Nu(c,d,g){return c?d():g()}function Bu(c){let{device:d,adbFactory:g,dependencies:R}=c;return ye(R?.viewHierarchy,()=>Nu(R?.deviceReadOnly,()=>iS,()=>new Qi(d,g)))}function nS(c){let{device:d,adbFactory:g,timer:R,idGenerator:A,wiring:C,dependencies:D}=c,T=D?.deviceReadOnly;return{hierarchyCapture:ye(D?.hierarchyCapture,()=>C.createHierarchyCapture(R,A)),screenshotService:ye(D?.screenshot,()=>Nu(T,()=>No.forObservationRead(d),()=>new No(d,{adbFactory:g}))),window:ye(D?.window,()=>new Bl(d,g)),backStack:ye(D?.backStack,()=>new eB(d,g)),predictiveUIState:ye(D?.predictiveUIState,()=>new ss)}}function oS(c,d){let{wiring:g,dependencies:R}=c,A=R?.screenshotPathProtection??Vn;return{pathProtection:A,screenshotRecorder:ye(R?.screenshotRecorder,()=>g.createScreenshotRecorder(d.screenshotService,A)),screenshotEvidenceFiles:R?.screenshotEvidenceFiles}}function sS(c,d){let{wiring:g,dependencies:R}=c;return{hierarchyCollector:ye(R?.hierarchyCollector,()=>g.createHierarchyCollector(R)),deviceStateCollector:ye(R?.deviceStateCollector,()=>g.createDeviceStateCollector(d.window,d.backStack)),iosLockStateProbe:ye(R?.iosLockStateProbe,()=>new as(Tu(),c.timer)),performanceAuditor:ye(R?.performanceAuditor,()=>g.createPerformanceAuditor()),accessibilityAuditor:ye(R?.accessibilityAuditor,()=>g.createAccessibilityAuditor()),accessibilityStateDetector:ye(R?.accessibilityStateDetector,()=>g.createAccessibilityStateDetector()),platformValidator:ye(R?.platformValidator,()=>new _n),windowIdentity:ye(R?.windowIdentityFreshnessResolver,()=>g.createWindowIdentity()),reconciler:ye(R?.activeWindowAttributionReconciler,()=>g.createReconciler())}}function aS(c,d){return vu(c.dependencies),{...oS(c,d),...sS(c,d)}}function Lu(c){let d=nS(c);return{sources:d,services:aS(c,d)}}var Uu={screenSizeUnits:()=>"physical-pixels",settledScreenshotOrientation:()=>"display",isIosMultiPanel:()=>!1,grantsObservationRead:(c)=>c.viewHierarchy?.fresh===!0},cS={...Uu,grantsObservationRead:()=>!0};function dS(c){return{screenSizeUnits:()=>"points",settledScreenshotOrientation:()=>"native",isIosMultiPanel:()=>(c().displays?.panels.length??0)>1,grantsObservationRead:(d)=>Xd(d.viewHierarchy)}}function $u(c,d){if(c==="ios")return dS(d);return c==="android"?Uu:cS}function ds(c,d,g){let{result:R,displayRequest:A}=d,C=A!==void 0&&A!=="active",D=C?Ei(c,A,{activePanelKey:g?.display.key,posture:R.display.posture}):void 0;return{explicitlyRouted:C,requestedPanel:D}}function Wu(c,d,g,R){if(g)return;if(Ce.checkIdentity(c,d.display,"ios"),R)Ce.checkIosGeometry(c,d.screenSize,d.observationId,d.display)}function lS(c){return Boolean(c.viewHierarchy?.hierarchy?.error||c.viewHierarchy?.hierarchy?.unavailableReason||c.viewHierarchy?.ctrlProxyIncomplete&&!c.viewHierarchy.hierarchy?.node)}function uS(c,d){let g=c.viewHierarchy?.hierarchy;if(d!==0&&(g?.error||g?.unavailableReason))return new Zn(g.unavailableDetail??g.error??"Selected display hierarchy is unavailable");return new Zn("CtrlProxy APK too old for display routing; update it and retry the observation.")}function pS({result:c,requestedPanel:d,requestedDisplayId:g,preserveDisplayState:R},A,C){if(g!==void 0&&typeof A!=="number"&&!C&&!(R&&lS(c)))throw uS(c,g);if(g!==void 0&&typeof A==="number"&&A!==g)throw new Zn(`Selected display "${d?.key}" returned hierarchy for display ${A}; retry the observation.`)}function mS(c,d){if(c&&d&&c.key!==d.key)throw new Zn(`Selected display "${c.key}" returned content from "${d.key}"; retry the observation.`)}class ls{deps;constructor(c){this.deps=c}resolveTarget(c){return this.resolveTargetAsync(c)}async resolveTargetAsync(c){let{result:d,androidDisplayCache:g,signal:R}=c,A=this.deps.device(),C=this.deps.adb(),D=await g.resolve(A,C,R);if(D)d.display=D.display;let{explicitlyRouted:T,requestedPanel:k}=ds(A,c,D),M=k?await g.logicalIdForPanel(A,C,k.key,R):void 0;if(k)d.display={...d.display,key:k.key,role:k.role};return{observedAndroid:D,explicitlyRouted:T,requestedPanel:k,requestedDisplayId:M}}bindFinalDisplay(c){if(!this.deps.device().displays?.panels.length)return{recordProvenance:c.recordProvenance};return this.bindFinalDisplayAsync(c)}async bindFinalDisplayAsync(c){let{result:d,androidDisplayCache:g,observedAndroid:R,requestedPanel:A,explicitlyRouted:C,signal:D}=c,T=c.recordProvenance,k=this.deps.device(),M=this.deps.adb(),F=d.viewHierarchy?.displayId,V=d.viewHierarchy?.panelUniqueId;pS(c,F,V);let W=typeof F==="number"||V?await g.panelForLogicalId(k,M,F,{signal:D,identity:{panelUniqueId:V,panelFingerprint:d.viewHierarchy?.panelFingerprint},allowProbe:C}):void 0;mS(A,W);let G=Ce.geometryChanged(k.deviceId,d.screenSize),q=G&&!C?await g.resolve(k,M,D,!0):R;return d.display.posture=await g.posture(k,M,D,G&&!C),this.applyBoundPanel(c,k,W?.key,q?.display.key),T=this.recordFinalIdentity(c,k,T),{recordProvenance:T}}applyBoundPanel({result:c,displayRequest:d,requestedPanel:g},R,A,C){let D=g??Ei(R,d,{focusedPanelKey:A,activePanelKey:C,posture:c.display.posture});c.display={...c.display,key:D.key,role:D.role}}recordFinalIdentity({result:c,explicitlyRouted:d,preserveDisplayState:g,observerMode:R},A,C){if(!d&&!g&&!R&&Ce.revision(A.deviceId)===C.revision)Ce.checkIdentity(A.deviceId,c.display),C={revision:Ce.revision(A.deviceId),identityRevision:Ce.identityRevision(A.deviceId)};return C}}class us{deps;constructor(c){this.deps=c}resolveTarget(c){let{explicitlyRouted:d,requestedPanel:g}=ds(this.deps.device(),c,void 0);return{observedAndroid:void 0,explicitlyRouted:d,requestedPanel:g,requestedDisplayId:void 0}}bindFinalDisplay(c){let{result:d,displayRequest:g,explicitlyRouted:R,preserveDisplayState:A,observerMode:C}=c,D=c.recordProvenance,T=this.deps.device();if(d.display=RO(T,d.viewHierarchy,n2(d)),!C&&!A&&Ce.revision(T.deviceId)===D.revision)Wu(T.deviceId,d,R,(T.displays?.panels.length??0)>1),D={revision:Ce.revision(T.deviceId),identityRevision:Ce.identityRevision(T.deviceId)};let k=Ei(T,g,{focusedPanelKey:d.display.key,activePanelKey:d.display.key,posture:d.display.posture});if(R&&k.key!==d.display.key)throw new Zn(`Display "${k.key}" is not the active panel on iOS. Active panel: ${d.display.key}`);return{recordProvenance:D}}}var Gu=new Set(["com.android.permissioncontroller","com.google.android.permissioncontroller"]),Ku="android.permission.POST_NOTIFICATIONS";function ps(c){return c!==void 0&&Gu.has(c)}function z3(c){return ps(c)||c!==void 0&&/permissioncontroller/i.test(c)}function fS(c,d){return c===d||c.startsWith(`${d}.`)}function ez(c){if(!c||!ps(c.appId)||c.activityName==="")return c;return[...Gu].some((g)=>fS(c.activityName,g))?c:{...c,activityName:""}}function hS(c){let d=c.text??c["content-desc"];return typeof d==="string"&&d.trim()!==""?d.trim():void 0}function vS(c,d){if(c.enabled!==void 0&&!ut(c.enabled))return!1;if(c.package!==void 0&&c.package!==d)return!1;let g=c["resource-id"]??"",R=typeof c.class==="string"?c.class:"";return/button/i.test(g)||/Button$/.test(R)}function yS(c,d){let g=(c.elements?.clickable??[]).filter((R)=>vS(R,d)).map(hS).filter((R)=>R!==void 0);return[...new Set(g)]}function bre(c,d){let g=gS(d);if(!d||!g||g===c)return;let R=bS(d);if(!(R?z3(g):ps(g)))return;return{kind:"permission_dialog",packageName:g,...R?{permission:Ku}:{},actions:yS(d,g)}}function gS(c){return c?.activeWindow?.appId||c?.viewHierarchy?.packageName}function bS(c){return c.notificationPermissionDetected===!0||c.activeWindow?.type==="notification_permission_dialog"}function Sre(c){let d=c.permission===Ku?"a notification permission dialog":"a permission dialog",g=c.actions.length>0?`tap ${c.actions.map((R)=>`"${R}"`).join(" or ")}`:"answer it with tapOn";return`blocked by ${d} (${c.packageName}); ${g}, or pre-grant with setAppPermissions`}var SS=1;function zu(c){if(typeof c!=="string")return;let d=c.trim();return d.length>0?d:void 0}function wS(c,d){let g=new Set(t9(c).map((C)=>C.id)),R=(ya(c.hierarchy,c.windows)??[]).filter((C)=>C.type===SS&&C.hierarchy!==void 0&&(C.packageName===void 0||C.packageName===d)&&!g.has(C.id)),A=R.toSorted((C,D)=>(D.windowLayer??0)-(C.windowLayer??0))[0];return(R.find((C)=>C.isFocused)??R.find((C)=>C.isActive)??A)?.hierarchy}function RS(c){let d=[c];while(d.length>0){let g=d.shift(),R=zu(we(g)["pane-title"]);if(R)return R;let A=g.node;if(A)d.unshift(...Array.isArray(A)?A:[A])}return}function tz(c,d){let g=zu(c?.packageName);if(!c||!g)return;if(d?.platform==="android"&&d.source==="sdk"&&d.components.bundleId===g)return d;let R=wS(c,g),A=R?RS(R):void 0;if(!A)return;return{platform:"android",source:"heuristic",confidence:"medium",key:JSON.stringify([["package",g],["paneTitle",A]]),components:{bundleId:g,navigationTitle:A}}}function ms(c){if((c.backStack?.displayCount??0)>1&&c.activeWindow){let d=Rt(c);if(d)c.activeWindow={...c.activeWindow,appId:d.packageName,activityName:d.activityName}}}function AS(c){let d=c.viewHierarchy,g=d?.packageName,R=c.activeWindow?.appId,A=d?.sources?.length===1&&d.sources[0]==="uiautomator";if(!g||!R||!A||!c.activeWindow)return!1;return c.activeWindow={...c.activeWindow,appId:g,activityName:""},!0}class fs{deps;xrDisplaySize;constructor(c){this.deps=c;this.xrDisplaySize=c.xrDisplaySize??new Ot(c)}async collect(c){let{result:d,queryOptions:g,perf:R,skipWaitForFresh:A,minTimestamp:C,signal:D,readOnly:T,capturedHierarchy:k,readOptions:M}=c;R.serial("phase1_hierarchy"),await this.deps.hierarchyCollector().collect(d,{queryOptions:g,perf:R,skipWaitForFresh:A,minTimestamp:C,signal:D,readOnly:T,capturedHierarchy:k,readOptions:M}),R.end();let F=d.viewHierarchy;if(F?.screenWidth&&F?.screenHeight){d.screenSize={width:F.screenWidth,height:F.screenHeight},await this.xrDisplaySize.prime(d,F,D,c.displayId),this.xrDisplaySize.applyCached(d,F,c.displayId),this.applyHierarchyDeviceMetadata(d,F);let V=this.startDeviceStateTasks(c,!F.wakefulness);if(V.length>0)await Promise.all(V);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),ms(d),await this.applyAndroidScreenIdentity(d),d.activeWindow=ez(d.activeWindow),this.deps.device().formFactor==="automotive")await this.deps.deviceStateCollector().collectAutomotive(d,D,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&&!Gn(d.foregroundActivity))this.applyAndroidForegroundActivity(c,d.foregroundActivity)}startDeviceStateTasks({result:c,perf:d,signal:g,skipBackStack:R,displayId:A},C){let D=[];if(C)D.push(d.track("wakefulness",()=>this.deps.deviceStateCollector().collectWakefulness(c,g)));else c.wakefulness=c.viewHierarchy?.wakefulness,c.wakefulnessSource="hierarchy";if(D.push(d.track("deviceLock",()=>this.deps.deviceStateCollector().collectDeviceLock(c,g))),!R)D.push(d.track("backStack",()=>this.deps.deviceStateCollector().collectBackStack(c,d.fork(),g,A)));return D}backfillActiveWindowPackage(c){if(AS(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 g;try{g=await this.deps.viewHierarchy().getScreenIdentity?.(d)}catch(A){e.debug(`[Android] SDK screen identity read failed; using hierarchy identity: ${r(A)}`)}let R=tz(c.viewHierarchy,g);if(R)c.screenIdentity=R}applyAndroidForegroundActivity(c,d){let g=d.split("/"),R=g[0],A=g[1]?.startsWith(".")?R+g[1]:g[1]||"";c.activeWindow={appId:R,activityName:A,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(),g=c.display?.key,R=g?d.displays?.panels.find((A)=>A.key===g):dO(d.displays,"active",{focusedPanelKey:Ce.observedPanel(d.deviceId)?.key});if(!R){e.warn(`[OBSERVE] Display ${g} is not in the display inventory; leaving screen size unknown`);return}if(R.sizePx.width>0&&R.sizePx.height>0)c.screenSize={...R.sizePx}}}var PS="sdkBridge",ju="sdk-element-id";function Hv(c){let d=c[ju],g=Number(c[rD]);if(typeof d!=="string"||d.length===0||!Number.isSafeInteger(g))return null;return{elementId:d,observationIdentity:g}}function sD(c,d){let g=c?.hierarchy?.node,R=Array.isArray(g)?[...g]:g&&typeof g==="object"?[g]:[];for(let A=R.pop();A;A=R.pop()){let C=Hv(we(A));if(C&&(d===void 0||C.elementId===d))return C;R.push(...Ea(A))}return null}function Xu(c,d){if(!c.visible)return null;let g=c.enabled,R=c.role.toLowerCase()==="textfield",A={"resource-id":c.id,"test-tag":c.id,class:c.role,role:R?"textfield":c.role,...R?{focusable:"true","input-type":"text",actions:["set_text"]}:{},bounds:{...c.bounds},enabled:String(c.enabled),[ju]:c.id,[rD]:String(d),...c.label!==void 0?{"content-desc":c.label}:{},...c.value!==void 0?{text:c.value}:{},...g?{clickable:"true"}:{},...c.focused?{focused:"true"}:{}},C=c.children.map((D)=>Xu(D,d)).filter((D)=>D!==null);return{$:A,extras:{"sdk.source":PS},...C.length>0?{node:C}:{}}}function Xt(c){if(c===null||typeof c!=="object")return null;let{left:d,top:g,right:R,bottom:A}=c;if([d,g,R,A].some((C)=>typeof C!=="number"))return null;return`${d},${g},${R},${A}`}function Yu(c,d){if(!c.visible)return;let g=Xt(c.bounds);if(g){for(let R of[c.id,c.label,c.value])if(R)d.add(`${g}|${R}`)}for(let R of c.children)Yu(R,d)}function IS(c,d){if(Ea(c).length>0)return!1;let g=Xt(qt(c));if(!g)return!1;let R=we(c);return["resource-id","content-desc","text"].some((A)=>{let C=R[A];return typeof C==="string"&&C.length>0&&d.has(`${g}|${C}`)})}function Ju(c,d){let g=Ea(c);if(g.length===0)return 0;let R=g.filter((C)=>!IS(C,d)),A=g.length-R.length;c.node=R;for(let C of R)A+=Ju(C,d);return A}function Zu(c){return 1+Ea(c).reduce((d,g)=>d+Zu(g),0)}function tp(c,d){let g=c.hierarchy?.node;if(!g||!d.root||d.coordinateSpace!=="screen")return null;let R=Xu(d.root,d.captureIdentity);if(!R)return null;let A=new Set;Yu(d.root,A);let C=Ju(g,A);return g.node=[...Ea(g),R],{attached:Zu(R),deduplicated:C}}var hs=2000;function CS(c){let d=c.enabled??(()=>N.isIosSdkObservationBridgeEnabled()),g=c.timer??i,R=(A)=>A.failure??A.error??"no observation";return{async observe(A,C,D=1/0){let T=g.now()+Math.max(0,D),k=()=>Math.max(0,Math.min(hs,T-g.now())),M=d()?c.client():null;if(!M||k()<=0)return{kind:"none"};let F;try{F=await M.getObservationBridgeStateForIos(A,k())}catch(G){return e.debug(`[iOS] SDK bridge discovery failed; observing with XCTest: ${r(G)}`),{kind:"none"}}if(F.status!=="available")return e.debug(`[iOS] SDK bridge unavailable for ${A}: ${F.reason}`),{kind:"none"};if(k()<=0)return{kind:"unavailable",detail:"search budget exhausted"};let V;try{V=await M.requestSdkObservationForIos({timeoutMs:k(),signal:C})}catch(G){return e.warn(`[iOS] SDK bridge snapshot failed for ${A}: ${r(G)}`,G),{kind:"unavailable",detail:r(G)}}if(jk(V),V.success&&V.observation)return{kind:"observation",observation:V.observation};let W=R(V);return e.warn(`[iOS] SDK bridge snapshot unavailable for ${A}: ${W}`),{kind:"unavailable",detail:W}}}}function rz(c,d){return CS({client:()=>x.getExistingInstance(c.deviceId),timer:d})}async function nz(c,d,g,R){let A=c.packageName;if(!A)return{};let C=await d.observe(A,g,R);if(C.kind==="none")return{};if(C.kind==="observation"&&C.observation.bundleId!==void 0&&C.observation.bundleId!==A)return e.debug(`[iOS] SDK snapshot app ${C.observation.bundleId} differs from hierarchy app ${A}; skipping merge`),{backend:"xctest",fallbackReason:"unavailable"};let D=C.kind==="observation"?tp(c,C.observation):null;if(D)return u2(c),e.debug(`[iOS] Merged ${D.attached} SDK bridge nodes (${D.deduplicated} XCTest duplicates removed)`),{backend:"sdk"};return{backend:"xctest",fallbackReason:"unavailable"}}var DS="sdkWebBridge",rp="web-view-id";var ip="web-element-id",TS="web-origin",np="web-document-id",op="web-role",xS=new Set(["input","textarea"]);function wre(c){let d=c[op],g=typeof d==="string"&&xS.has(d)?iz(c):null;return g?.documentId?g:null}var kS=new Set(["input","textarea","textbox","searchbox","combobox"]),ES=new Set(["text","search","email","url","tel","password","number"]);function OS(c,d){if(d!=="input")return kS.has(d);return ES.has((c.inputType??"text").toLowerCase())}var MS="[REDACTED]",_S="WKWebView";function iz(c){let d=c[rp],g=c[nD],R=c[ip];if(typeof d!=="string"||typeof g!=="string"||typeof R!=="string"||!d||!g||!R)return null;let A=c[np];return typeof A==="string"&&A?{webViewId:d,snapshotId:g,elementId:R,documentId:A}:{webViewId:d,snapshotId:g,elementId:R}}function Rre(c,d,g){let R=c?.hierarchy?.node,A=Array.isArray(R)?[...R]:R&&typeof R==="object"?[R]:[];for(let C=A.pop();C;C=A.pop()){let D=iz(we(C));if(D&&D.webViewId===d&&D.elementId===g)return D;A.push(...Ea(C))}return null}function FS(c){if(c===null||typeof c!=="object")return null;let{left:d,top:g,right:R,bottom:A}=c;if(typeof d!=="number"||typeof g!=="number"||typeof R!=="number"||typeof A!=="number")return null;return{left:d,top:g,right:R,bottom:A}}function NS(c){let d=we(c);return(d.class??d.className)===_S}function rB(c){let d=[],g=(C)=>{if(NS(C)){d.push(C);return}Ea(C).forEach(g)},R=c?.hierarchy?.node;return(Array.isArray(R)?R:R&&typeof R==="object"?[R]:[]).forEach(g),d}function BS(c){if(!c||!URL.canParse(c))return;let d=new URL(c).origin;return d==="null"?void 0:d}function LS(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 HS(c,d,g){let[R,A,C,D]=c.bounds;if([R,A,C,D].some((G)=>G===void 0||!Number.isFinite(G)))return null;let T=d.left+(R-g.offsetLeft)*g.pointsPerPixel,k=d.top+(A-g.offsetTop)*g.pointsPerPixel,M=Math.trunc(Math.max(d.left,T)),F=Math.trunc(Math.max(d.top,k)),V=Math.trunc(Math.min(d.right,T+C*g.pointsPerPixel)),W=Math.trunc(Math.min(d.bottom,k+D*g.pointsPerPixel));return V>M&&W>F?{left:M,top:F,right:V,bottom:W}:null}function VS(c){let d=new Set,g=new Set;for(let{id:R}of c)(d.has(R)?g:d).add(R);return g}function US(c,d){if(c.value!==MS)return c.value?{text:c.value}:{};return typeof d?.value==="string"?{}:{[OE]:"true"}}function $S(c,d,g,{origin:R,native:A}={}){let C=c.role??"element",D=OS(c,C);return{$:{class:C,role:D?"textfield":C,...D?{focusable:"true","input-type":"text"}:{},enabled:String(c.enabled),...c.label?{"content-desc":c.label}:{},...US(c,A),...c.enabled?{clickable:"true"}:{},...c.focused&&!A?{focused:"true"}:{},...A,bounds:d,[rp]:g.webViewId,[nD]:g.snapshotId,...g.documentId?{[np]:g.documentId}:{},[ip]:c.id,[op]:C,...R?{[TS]:R}:{}},extras:{"sdk.source":DS}}}function WS(c,d){let g=Xt(d);return g?[c.label,c.value].flatMap((R)=>R?[`${g}|${R}`]:[]):[]}function sp(c,d,g,R){let A=Ea(c);if(A.length===0)return 0;let C=0,D=A.flatMap((T)=>{let k=Ea(T).length===0?GS(T,d):void 0;if(k===void 0)return C+=sp(T,d,g,R),[T];if(C+=1,R.has(k))return[];R.add(k);let M=Object.fromEntries(Object.entries(we(T)).filter(([F])=>F!=="bounds"));return[g(k,M)]});return c.node=D,C}function GS(c,d){let g=Xt(qt(c));if(!g)return;let R=we(c),A=new Set(["resource-id","content-desc","text"].flatMap((C)=>{let D=R[C],T=typeof D==="string"&&D?d.get(`${g}|${D}`):void 0;return T===void 0?[]:[T]}));return A.size===1?[...A][0]:void 0}function ap(c,d){let g=rB(c);if(d.length!==1||g.length!==1)return null;let R={webViews:0,attached:0,deduplicated:0};return g.forEach((A,C)=>{let{webViewId:D,snapshot:T}=d[C],k=FS(qt(A));if(!T||!k)return;let M=BS(T.url),F=VS(T.elements),V=LS(T.viewport,k),W=T.elements.flatMap((ee)=>{let ne=ee.id!==""&&!F.has(ee.id),de=ee.visible&&ne?HS(ee,k,V):null;return de?[{element:ee,bounds:de}]:[]});if(W.length===0)return;let G=new Map,q=new Set;W.forEach(({element:ee,bounds:ne},de)=>{for(let te of new Set(WS(ee,ne)))if(G.has(te))q.add(te);else G.set(te,de)}),q.forEach((ee)=>G.delete(ee));let X=(ee,ne)=>{let{element:de,bounds:te}=W[ee],ce={webViewId:D,snapshotId:T.snapshotId,documentId:T.documentId};return $S(de,te,ce,{origin:M,native:ne})},J=new Set;R.deduplicated+=sp(A,G,X,J);let Z=W.flatMap((ee,ne)=>J.has(ne)?[]:[X(ne)]);A.node=[...Ea(A),...Z],R.webViews+=1,R.attached+=W.length}),R.webViews>0?R:null}async function KS(c,d){try{return await c.requestSdkWebSnapshotForIos(d)}catch(g){return e.warn(`[iOS] SDK web-view snapshot failed: ${r(g)}`,g),null}}function zS(c){let d=c.enabled??(()=>N.isIosSdkObservationBridgeEnabled()),g=c.timer??i;return{async snapshots(R,A=1/0){let C=g.now()+Math.max(0,A),D=()=>Math.max(0,Math.min(hs,C-g.now())),T=d()?c.client():null;if(!T)return[];let k=D();if(k===0)return e.debug("[iOS] SDK web-view snapshot skipped: time budget exhausted"),[];let M=await KS(T,{signal:R,timeoutMs:k});if(M&&!M.success&&M.failure==="bad_reply")e.warn(`[iOS] SDK web-view snapshot failed: ${M.error??M.failure}`);let F=M?.webViews??[];if(F.length>1)return F.map(({webViewId:V})=>({webViewId:V}));return F.map(({webViewId:V})=>({webViewId:V,...M?.success&&M.snapshot&&M.webViewId===V?{snapshot:M.snapshot}:{}}))}}}function YT(c,d){return zS({client:()=>x.getExistingInstance(c.deviceId),timer:d})}async function oz(c,d,g,R){if(rB(c).length!==1)return null;let A=await d.snapshots(g,R),C=ap(c,A);if(C)u2(c),e.debug(`[iOS] Merged ${C.attached} DOM elements from ${C.webViews} web view(s) (${C.deduplicated} XCTest duplicates removed)`);else if(A.length>0)e.debug(`[iOS] ${A.length} registered web view(s) not merged: no snapshot, or no one-to-one WKWebView match`);return C}var jS="com.apple.springboard";class vs{deps;constructor(c){this.deps=c}async collect({result:c,queryOptions:d,perf:g,skipWaitForFresh:R,minTimestamp:A,signal:C,readOnly:D,capturedHierarchy:T,readOptions:k}){g.serial("ios_collect"),await this.deps.hierarchyCollector().collect(c,{queryOptions:d,perf:g,skipWaitForFresh:R,minTimestamp:A,signal:C,readOnly:D,capturedHierarchy:T,readOptions:k});let M=await this.readLiveIosPanel(C);uoe(c,M),this.dropHomeScreenOfOtherPanel(c,M),this.applyIosScreenMetadata(c),this.applyLiveIosPanelSize(c),this.applyIosInsetsAndRotation(c),this.projectIosObservationHierarchy(c),await this.mergeSdkBridgeObservation(c,C),await this.mergeSdkWebSnapshots(c,C);let F;try{F=await this.deps.viewHierarchy().getScreenIdentity?.(c.viewHierarchy?.packageName,c.viewHierarchy?.updatedAt)}catch(W){e.debug(`[iOS] SDK screen identity refresh failed; using hierarchy identity: ${W}`)}let V=qR(c.viewHierarchy,c.screenSize);c.screenIdentity=V?.components.modalClass?V:F??V,g.end()}async mergeSdkBridgeObservation(c,d){if(!c.viewHierarchy)return;let g=this.deps.sdkBridge?.()??rz(this.deps.device()),R=await nz(c.viewHierarchy,g,d);if(R.backend)c.backend=R.backend;if(R.fallbackReason)c.fallbackReason=R.fallbackReason}async mergeSdkWebSnapshots(c,d){if(!c.viewHierarchy)return;let g=this.deps.sdkWeb?.()??YT(this.deps.device());if(await oz(c.viewHierarchy,g,d)&&!c.backend)c.backend="sdk"}dropHomeScreenOfOtherPanel(c,d){let g=c.viewHierarchy;if(!d||g?.packageName!==jS)return;let R=loe(this.deps.device().displays?.panels??[],g);if(R&&R.key!==d.key)c.viewHierarchy=void 0,pe(c,{phase:"viewHierarchy",message:`The home screen is not observable on the ${d.role} panel: the runner only sees the ${R.role} panel's SpringBoard. Launch an app, or setPosture closed to return to the ${R.role} panel.`})}async readLiveIosPanel(c){let d=this.deps.device(),g=d.displays?.panels??[];if(g.length<2)return;if(!this.deps.iosDisplayInfoSource){e.debug("[iOS] Live panel source unavailable; using runner size");return}try{let R=await this.deps.iosDisplayInfoSource.readDisplays({deviceId:d.deviceId,signal:c});c?.throwIfAborted();let A=G$(R,g);if(!A)e.debug("[iOS] No unique active CoreDevice panel; using runner size");return A}catch(R){if(c?.aborted)throw R;e.warn(`[iOS] Live panel read failed; using runner size: ${r(R)}`,R);return}}applyLiveIosPanelSize(c){let d=n2(c);if(!d?.scale||d.scale<=0)return;let g=d.sizePx.width/d.scale,R=d.sizePx.height/d.scale,A=c.screenSize;if(A.width===g&&A.height===R||A.width===R&&A.height===g)return;let C=c.viewHierarchy?.rotation===1||c.viewHierarchy?.rotation===3;c.screenSize=C?{width:R,height:g}:{width:g,height:R}}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=Tc(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,g=(this.deps.device().displays?.panels.length??0)>1;c.viewHierarchy=cy("ios",d,g),Roe(d,c.viewHierarchy,g)}if(c.viewHierarchy?.packageName&&!c.activeWindow)c.activeWindow={appId:c.viewHierarchy.packageName,activityName:"",layoutSeqSum:0}}}var qS=/\bFLAG_ROUND\b/,XS=/DisplayInfo\{[^\n]*\bdisplayId 0\b/,YS=/DisplayDeviceInfo\{[^\n]*\btype INTERNAL\b/;function JS(c){let d=c.split(/\r?\n/),g=d.find((R)=>XS.test(R))??d.find((R)=>YS.test(R));return g===void 0?void 0:qS.test(g)}class nB{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:JS(d.stdout)},this.cached.value}catch(d){c?.throwIfAborted(),e.debug(`isScreenRound unavailable: ${r(d)}`);return}}}import*as QS from"fs/promises";async function cp(c,d,{files:g=QS,store:R=Qr()}={}){let A=c.observationId?R.getPathForObservation(d,c.observationId):void 0;if(!A)return;try{let{mtimeMs:C}=await g.stat(A);if(Number.isFinite(C))c.screenshotCapturedAt=new Date(C).toISOString()}catch(C){e.debug(`[OBSERVE] screenshot capture time unavailable: ${r(C)}`)}}function dp(c){if(!c?.layoutWarnings)return c;let d=Vb(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=mo().getRecentInMemoryEntry();if(!c)return;let d=dp(c.result);return d?{deviceId:c.deviceId,result:d}:void 0}static getRecentCachedResult(){return xe.getRecentCachedObservation()?.result}static getRecentCachedResultForDevice(c){return dp(mo().getRecentInMemoryForDevice(c))}static getRecentCachedScreenshotPathForDevice(c){return Qr().getPath(c)}static getRecentCachedScreenshotErrorForDevice(c){return Qr().getError(c)}static getRecentCachedScreenshotPathForObservation(c,d){return Qr().getPathForObservation(c,d)}static getRecentCachedScreenshotErrorForObservation(c,d){return Qr().getErrorForObservation(c,d)}static clearCache(c){if(mo().clear(c),Qr().clear(c),c)Pe.cancelJob(c);else Pe.clear()}static defaultObserveScreenCache={clearForDevice(c){xe.clearCache(c)}};constructor(c,d=v,g,{timer:R=i,idGenerator:A=B}={}){this.device=c,this.adbFactory=d,this.adb=d.create(c),this.timer=R,this.observedAndroidDisplayCache=new gr(R),this.requestedDisplay=g?.display,this.selectedDisplayRead=g?.selectedDisplayRead??{},this.idGenerator=A,this.screenRound=new nB(this.adb);let C=this.xrDisplaySize=new Ot({device:()=>this.device,adb:()=>this.adb,xrDetector:Bw,readDisplaySize:()=>jC(this.adb,{timeoutMs:1000}),hierarchyCollector:()=>this.hierarchyCollector}),D=yu({xrDisplaySize:C,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:(V)=>this.resolveObservationTimestampMs(V),extractScreenSizeFromHierarchy:(V)=>this.extractScreenSizeFromHierarchy(V)}}),T={device:c,adbFactory:this.adbFactory,timer:R,idGenerator:A,wiring:D,dependencies:g};this.viewHierarchy=Bu(T);let{sources:k,services:M}=Lu(T);this.hierarchyCapture=k.hierarchyCapture,this.screenshotService=k.screenshotService,this.predictiveUIState=k.predictiveUIState,this.pathProtection=M.pathProtection,this.screenshotRecorder=M.screenshotRecorder,this.screenshotEvidenceFiles=M.screenshotEvidenceFiles,this.hierarchyCollector=M.hierarchyCollector,this.deviceStateCollector=M.deviceStateCollector,this.iosLockStateProbe=M.iosLockStateProbe,this.performanceAuditor=M.performanceAuditor,this.accessibilityAuditor=M.accessibilityAuditor,this.accessibilityStateDetector=M.accessibilityStateDetector,this.elementsBuilder=new Yg,this.platformValidator=M.platformValidator,this.safeAreaAuditor=new L9,this.windowIdentity=M.windowIdentity,this.reconciler=M.reconciler,this.settledScreenshots=new xo({device:()=>this.device,timer:()=>this.timer,screenshotRecorder:()=>this.screenshotRecorder,screenshotEvidenceFiles:()=>this.screenshotEvidenceFiles,pathProtection:()=>this.pathProtection}),this.deviceReadScreenshot=new Eo({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 _o({timer:()=>this.timer,device:()=>this.device,viewHierarchy:()=>this.viewHierarchy,deviceStateCollector:()=>this.deviceStateCollector,platformValidator:()=>this.platformValidator,reconciler:()=>this.reconciler}),this.androidCollector=new fs({xrDisplaySize:C,hierarchyCollector:()=>this.hierarchyCollector,deviceStateCollector:()=>this.deviceStateCollector,viewHierarchy:()=>this.viewHierarchy,device:()=>this.device}),this.platformTraits=$u(c.platform,()=>this.device);let F={device:()=>this.device,adb:()=>this.adb};this.displayBinding=c.platform==="ios"?new us(F):new ls(F),this.iosCollector=new vs({iosDisplayInfoSource:g?.iosDisplayInfoSource,hierarchyCollector:()=>this.hierarchyCollector,sdkBridge:g?.sdkBridge,viewHierarchy:()=>this.viewHierarchy,device:()=>this.device}),this.createStages()}createStages(){this.allDisplays=new Wi({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 Mn({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 Fn({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 Hn({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 Co({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",g,R={}){let{requireFreshScreenshot:A=!1,timeoutMs:C}=R;if(this.requestedDisplay==="all")return this.allDisplays.execute({observerMode:!0,skipCache:!0,skipRecompositionTracking:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,screenshot:"none",signal:c,timeoutMs:C,deviceReadScreenshot:d==="none"?void 0:g??{}});let D=await this.execute({observerMode:!0,skipCache:!0,skipRecompositionTracking:!0,skipPerformanceAudit:!0,skipAccessibilityAudit:!0,screenshot:"none",signal:c});if(D.viewHierarchy?.hierarchyServiceStarted)D.hierarchyServiceStarted=!0,delete D.viewHierarchy.hierarchyServiceStarted;if(d==="none")return D.screenshotCaptureAttempted=!1,D;if(await this.captureDeviceReadScreenshot(D,c,g,{requireFreshScreenshot:A}),D.screenshotPath)D.screenshotExpiresAt=await this.pathProtection.protect(D.screenshotPath);return D}captureDeviceReadScreenshot(...c){return this.deviceReadScreenshot.captureDeviceReadScreenshot(...c)}async appendRawViewHierarchy(c,d){if(!c.viewHierarchy)return;let g=await this.deviceReadScreenshot.resolveReadDisplayId(c,{signal:d});await this.hierarchyCollector.collectRaw(c,d,g)}async readCachedObservationForTarget(){let c=await mo().getMostRecent(this.device.deviceId);if(!c||(this.device.displays?.panels.length??0)<=1)return c;let d=Ce.currentObservedPanel(this.device.deviceId),g=![void 0,"active"].includes(this.requestedDisplay),R=d||g?void 0:this.device.platform==="android"?(await this.observedAndroidDisplayCache.resolve(this.device,this.adb)).display:RO(this.device,c.viewHierarchy),{key:A,posture:C}=R??{},D=Ei(this.device,this.requestedDisplay,{focusedPanelKey:d?.key,activePanelKey:A,posture:C,displayPin:qu()});return c.display?.key===D.key?c:void 0}async getMostRecentCachedObserveResult(){rP(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(),g=d&&this.device.platform==="ios"?{...d,rotation:Tc(d.viewHierarchy?.rotation,d.screenSize)}:d,R=this.timer.now()-c;if(g){await Wb(g,this.pathProtection),e.debug(`[OBSERVE_CACHE] Found recent result in cache (${R}ms)`),this.identifyCapture(g,"cached-ok");let A=FR({actualTimestamp:this.resolveObservationTimestampMs(g),hostAgeBasisMs:this.windowIdentity.resolveHostReceivedAtMs(g),now:this.timer.now()});A.requestedAfter=g.freshness?.requestedAfter;let C=g.displayRevision!==void 0&&g.displayRevision!==Ce.revision(this.device.deviceId)||Ce.geometryChanged(this.device.deviceId,g.screenSize);if(g.freshness?.isFresh===!1)return Sj(g,{...g,freshness:{...g.freshness,ageMs:A.ageMs}});return{...g,freshness:C?{...A,isFresh:!1,category:"cache_age",warning:"Display changed since this observation was captured; observe again."}:A}}return e.debug(`[OBSERVE_CACHE] No cached observe result available (${R}ms)`),{...this.createBaseResult(),error:"No cached observe result available"}}catch(d){let g=this.timer.now()-c;return e.warn(`[OBSERVE_CACHE] Error getting cached observe result after ${g}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 g=await this.captureStage.beginSingleDisplay(d),R=await this.captureStage.captureSingleDisplay(g);if(R.earlyResult)return R.earlyResult;let A=await this.reconcileStage.reconcileSingleDisplay(g,R);return await this.enrichStage.enrichSingleDisplay(g),await this.settleStage.settleSingleDisplay(g,R,A),await this.enrichStage.publishSingleDisplay(g)}catch(g){if(g instanceof Mj)throw g;return await this.captureStage.failSingleDisplay(g,d)}}createCriticalFallback(c,d={}){let{fallback:g=this.createBaseResult()}=d,R=c instanceof Error?c.stack||c.message:String(c);return this.stampScreenSizeUnits(g),pe(g,{phase:"critical",message:"Observation failed due to device access error",cause:R}),g.freshness=FR({now:this.timer.now(),unavailable:!0,unavailableReason:"unknown",unavailableDetail:R}),g}identifyCapture(c,d){if(c.viewHierarchy&&typeof c.viewHierarchy==="object"&&!c.viewHierarchy.hierarchy?.error)kd(re(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 qn.getInstance().processObservation(c,this.device)}async screenshotDisplayId(c,d){if(this.device.platform!=="android"||this.requestedDisplay==="active")return;let g=this.requestedDisplay||d?.display?.key;if(!g)return;try{let R=Ei(this.device,g,{}),A=await this.observedAndroidDisplayCache.logicalIdForPanel(this.device,this.adb,R.key,c);return!this.requestedDisplay&&A===0?void 0:A}catch(R){if(this.requestedDisplay)throw R;e.debug(`Screenshot panel "${g}" could not be mapped; using default display: ${r(R).replace(/\s+/g," ")}`);return}}async captureScreenshot(c=new U,{signal:d,observation:g,screenshot:R,screenshotOptions:A}={}){let C=g??this.createBaseResult(),D=await this.screenshotDisplayId(d,g),T=Hm(R),k=Un(A);if(g){if(g.screenshotCaptureAttempted=!0,Wn(g,k),T==="settled")g.screenshotOrientation=this.platformTraits.settledScreenshotOrientation()}if(T==="settled")await this.captureSettledScreenshot(C,c,d,{strict:R==="settled",displayId:D,screenshotOptions:A});else if(await this.screenshotRecorder.captureFresh(C.observationId,{perf:c,signal:d,displayId:D,capture:k}),g)await cp(g,this.device.deviceId,{files:this.screenshotEvidenceFiles});if(g)await this.runAccessibilityAudit(g,c)}captureSettledScreenshot(...c){return this.settledScreenshots.captureSettledScreenshot(...c)}async runAccessibilityAudit(c,d=new U){await this.accessibilityAuditor.run(c,d)}appendError(c,d){pe(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 mo().currentGeneration(this.device.deviceId)}async cacheObserveResult(c,d,g){if(c.displayRevision!==void 0&&c.displayRevision!==Ce.revision(this.device.deviceId))return;let R=mo(),A=g??this.timer.now(),C=R.getRecentInMemoryForDevice(this.device.deviceId),D=R.getRecentCachedAtForDevice(this.device.deviceId);if(C!==void 0&&C.observationId!==c.observationId&&D!==void 0&&D>A){e.debug(`[OBSERVE_CACHE] Skipping deferred observe result for device ${this.device.deviceId}: a more recently cached observation already exists`);return}await R.put(this.device.deviceId,c,d,A)}async collectDeferredBackStack(c,d={}){let g=this.deferredBackStackDisplays.get(c);if(g===void 0||this.device.platform!=="android"||c.backStack)return!1;await this.deviceStateCollector.collectBackStack(c,new U,d.signal,g);let R=Rt(c),A=c.activeWindow,C=Boolean(R&&A&&!Re.has(c.viewHierarchy?.packageName??"")&&!Re.has(A.appId)&&Kn(c,A,R));if(ms(c),await this.deviceStateCollector.refreshAutomotiveForegroundActivity(c,d.signal),!C)this.enrichStage.refreshXrPanelSpace(c);return C}collectAllData(c,d={}){let g={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({...g,skipBackStack:d.skipBackStack??!1,displayId:d.displayId??0});case"ios":return this.iosCollector.collect(g);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,g){return this.reconciler.recaptureHierarchyForBackStackAttribution(c,d,g)}isConfirmedFrameworkErrorDialog(c,d){return Ll(this.adb,c,d)}resolveObservationTimestampMs(c){return c.viewHierarchy?.updatedAt}}function iB(c,d){return new xe(c,d,c.platform==="ios"?{iosDisplayInfoSource:Vu()}:void 0)}class ai{invalidate(c,d){if(c.platform==="android")E.getExistingInstance(c.deviceId)?.invalidateCache();else{let g=x.getExistingInstance(c.deviceId);if(d)g?.invalidateCache();else g?.clearCache()}if(xe.clearCache(c.deviceId),c.platform==="android")Eoe(c.deviceId)}retireAppProcess(c,d){if(c.platform==="android")E.getExistingInstance(c.deviceId)?.clearSdkScreenIdentity(d)}}async function Kr(c,d,g={}){await w.devicePoolWrites()?.reconcileDiscoveryObservation(c,d,g)}class La extends t{errorCode;constructor(c,d){super(c);this.errorCode=d}}function ad(c,d,g={}){let R=g.clock??i,A=g.log??e,C,D,T=async()=>{let k=R.now();try{let M=await d();return C=M,A.info(`[lazy-feature] ${c} module loaded in ${R.now()-k} ms`),M}catch(M){throw D=void 0,A.warn(`[lazy-feature] ${c} module failed to load`,M),u(M,`Failed to load the ${c} module`)}};return{load:()=>{if(C!==void 0)return Promise.resolve(C);return D??=T(),D},loaded:()=>C}}function ku(c){return x.getInstance(c)}class lp{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 g of[...c])try{g(d)}catch(R){e.warn(`[StreamDeviceLifecycle] listener failed for ${d}: ${r(R)}`,R)}}}var gs=null;function ma(){if(!gs){let c=new lp;gs=c,Zt({name:"stream-device-lifecycle",prepareForIncarnationChange:(d)=>c.deviceRestored(d),onDeviceIncarnationChanged:(d)=>c.deviceRestored(d)})}return gs}import*as Ie from"fs";import*as ft from"path";class aD{filePath;constructor(c=ZS()){this.filePath=c}read(){try{return Ie.existsSync(this.filePath)?Ie.readFileSync(this.filePath,"utf8"):null}catch(c){return e.debug(`Failed to read startup failure tracker file: ${c}`),null}}write(c){let d=ft.dirname(this.filePath);Ie.mkdirSync(d,{recursive:!0});let g=ft.join(d,`.${ft.basename(this.filePath)}.${process.pid}.tmp`);Ie.writeFileSync(g,c,{mode:384}),Ie.renameSync(g,this.filePath)}clear(){try{if(Ie.existsSync(this.filePath))Ie.rmSync(this.filePath,{force:!0})}catch(c){e.debug(`Failed to clear startup failure tracker file: ${c}`)}}}function ZS(){return ft.join(Je(vn.STATE),"daemon-startup-failures.json")}
|
|
56
|
+
export{oi,$n,Ow,Po,Cte,Dte,xL,RW,CL,Um,Ao,OT,DL,MT,qC,OL,PW,VC,Mw,Ue,ng,WC,zC,Rc,Nw,Fw,Ote,R3,AW,TW,kW,EW,P3,Mte,NT,Lw,Nte,IW,Bw,da,Fte,jC,Lte,_W,FT,$w,Pu,KC,Uw,A3,Bte,_r,ar,ML,$te,Hm,LT,ml,Fe,lr,la,Ute,ig,og,Fs,xW,sg,ag,NL,GC,Hte,qte,Bv,BT,Vte,$T,FL,qm,Ls,LL,T3,YC,JC,Wte,fl,XC,CW,Vm,zte,DW,OW,Hw,ZC,BL,qw,k3,E3,jte,UT,Wm,MW,$L,UL,Kte,I3,HT,cg,Sp,qT,dg,Au,Gte,HL,Yte,Jte,NW,FW,LW,zm,Xte,Zte,VT,_3,Qte,ere,tre,hl,Vw,BW,rre,nre,ire,ore,Bs,QC,sre,lg,x3,Pc,Ac,are,Kt,eD,jm,ug,cre,gl,dre,ua,C3,$v,To,tD,$W,UW,ji,Pn,qL,VL,Km,Gm,D3,HW,lre,O3,ure,M3,N3,Tc,kc,yl,rD,nD,An,WL,WT,F3,pre,Uv,zL,mre,zT,iD,qW,oD,fre,Ym,VW,L3,B3,WW,$3,U3,jL,Ww,pg,H3,et,Jm,jn,sd,q3,hre,zW,jW,gre,V3,yre,vre,KW,KL,mg,GL,jT,GW,YW,YL,W3,JL,JW,pa,Xm,_t,oe,Ge,tr,Fa,si,fg,XW,XL,hg,Zm,ZL,ZW,ko,KT,QL,Qm,eB,QW,GT,io,tB,Tu,z3,ez,bre,Sre,tz,Hv,sD,rz,nz,wre,iz,Rre,rB,YT,oz,nB,xe,iB,ai,Kr,La,ad,ku,ma,aD};
|
|
57
|
+
|
|
58
|
+
//# debugId=62248B333C10F92B64756E2164756E21
|