@kaeawc/auto-mobile 0.0.92 → 0.0.93
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/{chunk-jhnbfj19.js → chunk-00167wan.js} +5 -5
- package/dist/src/chunk-0jrrsnc9.js +6 -0
- package/dist/src/chunk-0n6swkwg.js +5 -0
- package/dist/src/chunk-0qsy1qsx.js +57 -0
- package/dist/src/chunk-11m8wj8j.js +237 -0
- package/dist/src/{chunk-4pfftt07.js → chunk-1p7xf5kb.js} +3 -3
- package/dist/src/chunk-23p5f095.js +4 -0
- package/dist/src/{chunk-a4k9rt7z.js → chunk-26k317v5.js} +3 -3
- package/dist/src/chunk-284ptqa4.js +7 -0
- package/dist/src/chunk-28re4xrg.js +4 -0
- package/dist/src/chunk-2f9rkmhx.js +5 -0
- package/dist/src/chunk-2fxdh48t.js +4 -0
- package/dist/src/chunk-2tbdrbt6.js +4 -0
- package/dist/src/chunk-2tqzq5qh.js +971 -0
- package/dist/src/chunk-32gvv9b4.js +21 -0
- package/dist/src/chunk-3f3t1x97.js +8 -0
- package/dist/src/chunk-3fspkbc7.js +4 -0
- package/dist/src/chunk-3qwrzxh0.js +11 -0
- package/dist/src/chunk-3sy6ahhz.js +26 -0
- package/dist/src/chunk-3vg455e6.js +4 -0
- package/dist/src/chunk-3xkpk44w.js +5 -0
- package/dist/src/chunk-3y6eykz9.js +4 -0
- package/dist/src/chunk-49bsqdx3.js +4 -0
- package/dist/src/chunk-4hw3665t.js +42 -0
- package/dist/src/chunk-58wzr3mt.js +5 -0
- package/dist/src/chunk-5d2hft6c.js +5 -0
- package/dist/src/chunk-5snsn9cf.js +4 -0
- package/dist/src/chunk-5tm9mn47.js +54 -0
- package/dist/src/chunk-5zc77a5t.js +4 -0
- package/dist/src/chunk-64j0majr.js +19 -0
- package/dist/src/chunk-65y8v4td.js +17 -0
- package/dist/src/chunk-6awz7vhq.js +5 -0
- package/dist/src/{chunk-stfzjr9y.js → chunk-6bznss4t.js} +5 -5
- package/dist/src/chunk-6ep7f5ge.js +4 -0
- package/dist/src/{chunk-0dfnyfkh.js → chunk-6wt9rgjf.js} +3 -3
- package/dist/src/chunk-6xmss8er.js +8 -0
- package/dist/src/chunk-710rxz9y.js +5 -0
- package/dist/src/chunk-7cs2da62.js +5 -0
- package/dist/src/chunk-7g103b54.js +4 -0
- package/dist/src/chunk-7j5vj4pa.js +4 -0
- package/dist/src/chunk-7rz9898k.js +5 -0
- package/dist/src/chunk-7tw8x05v.js +4 -0
- package/dist/src/chunk-7zy586cb.js +4 -0
- package/dist/src/{chunk-r0f1q783.js → chunk-8037tzzj.js} +3 -3
- package/dist/src/chunk-84nanf8s.js +5 -0
- package/dist/src/{chunk-950qcq1e.js → chunk-8g1922rp.js} +4 -4
- package/dist/src/chunk-8gvwcv2p.js +4 -0
- package/dist/src/{chunk-sz1a7p43.js → chunk-8ph29g99.js} +1 -1
- package/dist/src/chunk-8thrmfat.js +4 -0
- package/dist/src/chunk-8zgzzs7k.js +78 -0
- package/dist/src/chunk-97b1zmaq.js +4 -0
- package/dist/src/chunk-9fth9ayh.js +4 -0
- package/dist/src/chunk-9j6anhjr.js +4 -0
- package/dist/src/{chunk-w7zsh13a.js → chunk-aabchzxk.js} +4 -4
- package/dist/src/{chunk-wry6skrm.js → chunk-ayp07wbb.js} +1 -1
- package/dist/src/chunk-bfjwqk8q.js +4 -0
- package/dist/src/{chunk-jdqvcq0a.js → chunk-bfw6125s.js} +3 -3
- package/dist/src/chunk-bnhscm2n.js +4 -0
- package/dist/src/chunk-bxmsax22.js +5 -0
- package/dist/src/chunk-c1vs4g1n.js +4 -0
- package/dist/src/chunk-ct3e7yng.js +4 -0
- package/dist/src/{chunk-8en08r7q.js → chunk-cyy71ggq.js} +3 -3
- package/dist/src/chunk-ddzkz92z.js +4 -0
- package/dist/src/chunk-dgrbdpb7.js +9 -0
- package/dist/src/chunk-drdz8hee.js +5 -0
- package/dist/src/chunk-e98dqnc9.js +145 -0
- package/dist/src/chunk-eersndy7.js +5 -0
- package/dist/src/chunk-eggq53ks.js +4 -0
- package/dist/src/chunk-f2dya7cs.js +4 -0
- package/dist/src/chunk-fbakd6cw.js +4 -0
- package/dist/src/chunk-fgb98zjj.js +5 -0
- package/dist/src/chunk-fmpad823.js +5 -0
- package/dist/src/{chunk-v90es00d.js → chunk-g04bwyj3.js} +2 -2
- package/dist/src/chunk-g0xr8zw0.js +4 -0
- package/dist/src/chunk-g3rjs80x.js +4 -0
- package/dist/src/chunk-g78rtrfv.js +4 -0
- package/dist/src/{chunk-r20pe1nv.js → chunk-g7tmjbkt.js} +3 -3
- package/dist/src/chunk-gabgv3y5.js +4 -0
- package/dist/src/chunk-gmr45m8f.js +4 -0
- package/dist/src/chunk-gsyfebqj.js +4 -0
- package/dist/src/chunk-h5rpn9wr.js +247 -0
- package/dist/src/chunk-hb1x7v55.js +4 -0
- package/dist/src/chunk-hrfytkxh.js +168 -0
- package/dist/src/chunk-j4yjzbak.js +4 -0
- package/dist/src/chunk-jd6a5v6p.js +5 -0
- package/dist/src/chunk-jh6vhqzx.js +5 -0
- package/dist/src/chunk-kn5spq15.js +4 -0
- package/dist/src/{chunk-w2mwa0jk.js → chunk-m94qs0f0.js} +2 -2
- package/dist/src/chunk-mjrps0ac.js +7 -0
- package/dist/src/chunk-n03dmn5q.js +5 -0
- package/dist/src/chunk-n72qhwd9.js +4 -0
- package/dist/src/{chunk-km0dy5vc.js → chunk-ndt1ccxm.js} +9 -9
- package/dist/src/chunk-nr6y0n4y.js +5 -0
- package/dist/src/chunk-pcsen2vs.js +4 -0
- package/dist/src/chunk-ppfr0b8h.js +4 -0
- package/dist/src/chunk-q10bdnat.js +4 -0
- package/dist/src/chunk-q9xmq595.js +4 -0
- package/dist/src/{chunk-2v7tw1nj.js → chunk-qcxzr2my.js} +3 -3
- package/dist/src/chunk-qf6nynk6.js +7 -0
- package/dist/src/chunk-qyqypn28.js +5 -0
- package/dist/src/chunk-r2epb56s.js +4 -0
- package/dist/src/chunk-r5bxavdx.js +311 -0
- package/dist/src/{chunk-r14wwk37.js → chunk-r6z1eztj.js} +12 -12
- package/dist/src/{chunk-d57432wq.js → chunk-r7bpkgff.js} +2 -2
- package/dist/src/chunk-r8jf3d92.js +4 -0
- package/dist/src/{chunk-9rkfyt6q.js → chunk-rbpdk7m0.js} +3 -3
- package/dist/src/chunk-rc0dbypm.js +4 -0
- package/dist/src/chunk-rhcty4ms.js +4 -0
- package/dist/src/chunk-rpvckv3p.js +4 -0
- package/dist/src/{chunk-s1zq65ny.js → chunk-rqc9ap3x.js} +2 -2
- package/dist/src/chunk-rvvy1bte.js +7 -0
- package/dist/src/chunk-ry0mz41y.js +4 -0
- package/dist/src/{chunk-34zxqcmq.js → chunk-s3jc6cwp.js} +3 -3
- package/dist/src/chunk-sfv61xjb.js +6 -0
- package/dist/src/chunk-t6bfvfkg.js +4 -0
- package/dist/src/chunk-t6c8akcm.js +5 -0
- package/dist/src/chunk-t7w8rctc.js +4 -0
- package/dist/src/chunk-thbh3jew.js +5 -0
- package/dist/src/chunk-v2wd4n3e.js +5 -0
- package/dist/src/{chunk-zg67wjkh.js → chunk-v6pya0dm.js} +3 -3
- package/dist/src/chunk-vy3bwm1d.js +17 -0
- package/dist/src/chunk-w3vs79ex.js +27 -0
- package/dist/src/chunk-w4zga19f.js +4 -0
- package/dist/src/chunk-w5b2jwk3.js +14 -0
- package/dist/src/chunk-w7hkv422.js +5 -0
- package/dist/src/{chunk-qv2918jt.js → chunk-waqwcjyn.js} +2 -2
- package/dist/src/{chunk-b4cxdzwy.js → chunk-wbh8spm5.js} +7 -7
- package/dist/src/{chunk-ajsrz473.js → chunk-wyrkw6hw.js} +3 -3
- package/dist/src/chunk-xa73x2cx.js +5 -0
- package/dist/src/{chunk-eka89q3k.js → chunk-xgan0qqp.js} +1 -1
- package/dist/src/chunk-y2vs6jwg.js +4 -0
- package/dist/src/chunk-yattm52s.js +4 -0
- package/dist/src/{chunk-9y5bcy28.js → chunk-yb97j25b.js} +4 -4
- package/dist/src/{chunk-c9nk1r78.js → chunk-ybbtagbt.js} +3 -3
- package/dist/src/chunk-ycaj2sgf.js +9 -0
- package/dist/src/chunk-yf7ympyz.js +325 -0
- package/dist/src/chunk-yjawdzk8.js +4 -0
- package/dist/src/chunk-z637nqg8.js +11 -0
- package/dist/src/{chunk-0w1spptt.js → chunk-zgja5f3p.js} +4 -4
- package/dist/src/chunk-zs1sghs9.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 +3 -2
- 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-2e6s75qv.js +0 -78
- 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-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
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{i,Xe,si,dn,te,xo,gd,pb,l,nt,e}from"./chunk-z8t0v07j.js";import{g,E,$e,wu}from"./chunk-mf9spd4g.js";import{L,oo,la}from"./chunk-32jpxz2y.js";import{Ge,Je,Zi,ne,B,yL,gn,le,v,yn,dW,F,ls,Aw,S,Vo,pt,Ce,w5,Wee,k5,tn,fi,ko,Pv,wW,Qi,tp,rp,MT,Jc,Hn,NT,TW,nte,W,M,na,ni,rB,ZC,ez,sn,fr,_,xe,k}from"./chunk-h3n4adc6.js";import{n,a,h,b,s,Ko,I}from"./chunk-79q5xsdc.js";import{l6,Ty,m6,_c}from"./chunk-nwm2pq5v.js";import{CP,Ub,Hb}from"./chunk-f9s1kkhx.js";import{hf,FU,SE,LU}from"./chunk-r20pe1nv.js";import{Bn,Ai,tT,IQ,$c,Zl,pm}from"./chunk-6d3mmqxt.js";import{KF}from"./chunk-zg67wjkh.js";import{fd}from"./chunk-0dfnyfkh.js";import{r,t,u}from"./chunk-9rkfyt6q.js";import{Lt}from"./chunk-2v7tw1nj.js";var Gn={invalid_type:"invalid_type",too_big:"too_big",too_small:"too_small",invalid_format:"invalid_format",not_multiple_of:"not_multiple_of",unrecognized_keys:"unrecognized_keys",invalid_union:"invalid_union",invalid_key:"invalid_key",invalid_element:"invalid_element",invalid_value:"invalid_value",custom:"custom"};function _e(o){return o==="ios"||o==="tvos"}function lK(o){return o==="android"||_e(o)}function FO(o,d){if(lK(o))return o;throw new t(`${d} is not supported on ${pb[o]} yet. Target an Android, iOS or Apple TV device instead.`)}import{promises as Qo}from"fs";var Zo=new Set(["moov","trak","mdia","minf","stbl"]),en={avc1:"h264",avc3:"h264",hvc1:"hevc",hev1:"hevc"},he=8,Ke=16,rn=8;function We(o,d,c,p){if(c<he)return;let m=o.readUInt32BE(d),f=o.toString("latin1",d+4,d+8),w=he;if(m===1){if(c<Ke)return;let R=o.readUInt32BE(d+8),y=o.readUInt32BE(d+12);m=R*4294967296+y,w=Ke}else if(m===0)m=p;if(m<w)return;return{size:m,type:f,headerSize:w}}function Cr(o,d,c){let p=d;while(p+he<=c){let m=We(o,p,c-p,c-p);if(!m||p+m.size>c)return;let f=p+m.headerSize,w=p+m.size;if(Zo.has(m.type)){let R=Cr(o,f,w);if(R)return R}else if(m.type==="stsd"){let R=on(o,f,w);if(R)return R}p+=m.size}return}function on(o,d,c){let p=d+rn;while(p+he<=c){let m=We(o,p,c-p,c-p);if(!m||p+m.size>c)return;let f=en[m.type.toLowerCase()];if(f)return f;p+=m.size}return}async function xr(o){let d=await Qo.open(o,"r");try{let{size:c}=await d.stat(),p=Buffer.alloc(Ke),m=0;while(m+he<=c){let{bytesRead:f}=await d.read(p,0,Ke,m),w=We(p,0,f,c-m);if(!w)return;if(w.type==="moov"){let R=Math.min(w.size,c-m),y=Buffer.alloc(R);return await d.read(y,0,R,m),{moov:y,headerSize:w.headerSize}}m+=w.size}return}finally{await d.close()}}async function nn(o){let d=await xr(o);return d&&Cr(d.moov,d.headerSize,d.moov.length)}var an=4;function cn(o,d,c){let p=o[d],m=p===1?16:8,f=d+an+m,w=f+4;if(w+(p===1?8:4)>c)return;let y=o.readUInt32BE(f),P=p===1?o.readUInt32BE(w)*4294967296+o.readUInt32BE(w+4):o.readUInt32BE(w);if(y===0)return;return Math.round(P/y*1000)}function kr(o,d,c){let p=d;while(p+he<=c){let m=We(o,p,c-p,c-p);if(!m||p+m.size>c)return;let f=p+m.headerSize,w=p+m.size;if(m.type==="moov"){let R=kr(o,f,w);if(R!==void 0)return R}else if(m.type==="mvhd")return cn(o,f,w);p+=m.size}return}async function ln(o){let d=await xr(o);return d&&kr(d.moov,d.headerSize,d.moov.length)}function we(o,d){return o.durationMs?.(d)??Promise.resolve(void 0)}var ae={async codec(o){try{return await nn(o)}catch(d){e.warn(`[RecordingCodec] Failed to probe codec for ${o}: ${d}`,d);return}},async durationMs(o){try{return await ln(o)}catch(d){e.warn(`[RecordingCodec] Failed to probe duration for ${o}: ${d}`,d);return}}};import{promises as To}from"fs";import br from"path";import{promises as Tr}from"fs";import ye from"path";class J extends t{retainOwnership;retainedCapturePath;constructor(o,d){super(o,d);this.name="VideoCaptureFinalizationError",this.retainOwnership=d?.retainOwnership??!1,this.retainedCapturePath=d?.retainedCapturePath}}class X extends Error{handle;constructor(o,d,c){super(o,c);this.handle=d;this.name="VideoCaptureStartCleanupError"}}function pn(o){let d={qualityPreset:o.qualityPreset,targetBitrateKbps:o.targetBitrateKbps,maxThroughputMbps:o.maxThroughputMbps,fps:o.fps,maxArchiveSizeMb:o.maxArchiveSizeMb,format:o.format};if(o.resolution)d.resolution=o.resolution;return d}function mn(o,d){return o.transitions??(d?[]:void 0)}function fn(o,d){if(o.physicalDisplayId=d.warning?void 0:d.physicalDisplayId??o.physicalDisplayId,o.warning=d.warning,o.recordedPanel=d.recordedPanel??o.recordedPanel,d.warning?.includes("rejected --display-id"))o.recordedPanel=void 0}function hn(o,d){let c=[...o.warning?[o.warning]:[],...d?.warnings??[]];return c.length>0?c:void 0}class qe{backend;archiveRoot;log;idGenerator;now;securePermissions;fileSystem;activeRecordings=new Map;stoppingRecordings=new Map;forceStoppingRecordings=new Map;constructor(o){this.backend=o.backend,this.archiveRoot=o.archiveRoot??Xe(dn.VIDEO_ARCHIVE),this.log=o.logger??e,this.idGenerator=wn(o.idGenerator),this.now=o.now??(()=>new Date),this.securePermissions=o.securePermissions??nte,this.fileSystem=o.fileSystem??Tr}async startRecording(o={}){let d=hf(o.config),c=this.idGenerator.next(),p=this.now().toISOString(),m=Rn(o.outputName),f=m?`${m}-${c}`:c,w=this.getRecordingDir(f);await this.securePermissions.ensureSecureDir(w);let R=vn(f,p,d.format),y=ye.join(w,R),P=new AbortController,A={recordingId:c,outputDirectory:w,outputPath:y,fileName:R,startedAt:p,device:o.device,maxDurationSeconds:o.maxDurationSeconds,abortSignal:Ge(o.abortSignal,P.signal),display:o.display,recordingPanel:o.recordingPanel,physicalDisplayId:o.physicalDisplayId,audio:o.audio,...d},x=Promise.resolve().then(async()=>await this.backend.start(A)),C={recordingId:c,outputPath:y,fileName:R,startedAt:p,config:d,outputName:o.outputName,recordedPanel:o.recordingPanel,physicalDisplayId:o.physicalDisplayId,deviceId:o.device?.deviceId,startPromise:x,startAbortController:P,forceStopRequested:!1};this.activeRecordings.set(c,C);try{let T=await x;if(C.handle=T,C.outputPath=T.outputPath||y,C.fileName=ye.basename(C.outputPath),C.liveCapturePath=T.liveCapturePath,C.inProgressSidecarPaths=T.inProgressSidecarPaths,C.startedAt=T.startedAt||p,C.config=pn(T.effectiveConfig??d),fn(C,T),C.forceStopRequested||this.activeRecordings.get(c)!==C)throw Error(`Recording ${c} was force-stopped while it was starting.`);return{recordingId:c,outputPath:C.outputPath,fileName:C.fileName,startedAt:C.startedAt,config:C.config,outputName:C.outputName,recordedPanel:C.recordedPanel,physicalDisplayId:C.physicalDisplayId,warning:C.warning,liveCapturePath:C.liveCapturePath}}catch(T){return await this.handleStartFailure(T,C)}}listActiveRecordingIds(){return Array.from(this.activeRecordings.keys())}getCaptureTeardown(o){let d=this.activeRecordings.get(o)?.handle;return d?this.backend.describeCaptureTeardown?.(d):void 0}getInProgressFiles(o){let d=this.activeRecordings.get(o);return d?[d.liveCapturePath??d.outputPath,...d.inProgressSidecarPaths??[]]:[]}hasActiveRecordingForDevice(o){return Array.from(this.activeRecordings.values()).some((d)=>d.deviceId===o)}async stopRecording(o){let d=this.stoppingRecordings.get(o);if(d)return d;let c=this.activeRecordings.get(o);if(!c)throw Error(`No active recording found for id ${o}`);let p=this.stopActiveRecording(c);this.stoppingRecordings.set(o,p);try{return await p}finally{this.stoppingRecordings.delete(o)}}async stopActiveRecording(o){let d=o.recordingId,c=o.handle??await o.startPromise,p;try{p=await this.backend.stop(c)}catch(x){throw await this.handleStopFailure(o,x)}this.assertGracefulStopOwnership(o);let m=p.endedAt??this.now().toISOString(),f=p.outputPath||o.outputPath,w=ye.basename(f);await this.securePermissions.secureFile(f);let R=await this.safeStat(f);this.assertGracefulStopOwnership(o);let y=p.sizeBytes??R?.size??0,P=p.durationMs??Pn(o.startedAt,m),A={recordingId:o.recordingId,fileName:w,filePath:f,format:bn(f,o.config.format),sizeBytes:y,durationMs:P,videoDurationMs:p.videoDurationMs,codec:p.codec,outputName:o.outputName,createdAt:o.startedAt,startedAt:o.startedAt,endedAt:m,lastAccessedAt:m,config:o.config,recordedPanel:p.recordedPanel??o.recordedPanel,transitions:mn(p,o.recordedPanel),warnings:hn(o,p),...p.hasAudioTrack===void 0?{}:{hasAudioTrack:p.hasAudioTrack}};return this.activeRecordings.delete(d),A}assertGracefulStopOwnership(o){if(this.activeRecordings.get(o.recordingId)!==o||o.forceStopRequested)throw Error(`Recording ${o.recordingId} was force-stopped while it was stopping.`)}async handleStopFailure(o,d){let c=o.recordingId;if(d instanceof rp)return u(d,`Recording ${c} could not be confirmed stopped; the capture process may still be running on the device`);if(d instanceof J){if(d.retainOwnership)return new J(`Recording ${c} ownership retained; stop again to finalize its device artifact: ${d.message}`,{cause:d,retainOwnership:!0});this.activeRecordings.delete(c);try{if(d.retainedCapturePath)await this.fileSystem.rm(o.outputPath,{force:!0});else await this.removeRecordingArtifacts(c,o.outputPath)}catch(p){this.log.warn(`[VideoRecorderService] Failed to remove unusable recording artifacts for ${c}: ${r(p)}`,p)}return d}return d}async forceStopRecording(o,d){await this.forceStopOrDiscardRecording(o,!1,d)}async discardRecording(o,d){await this.forceStopOrDiscardRecording(o,!0,d)}async forceStopOrDiscardRecording(o,d,c){let p=this.activeRecordings.get(o)?.outputPath,m=this.forceStoppingRecordings.get(o);if(m){if(await m,d)await this.removeRecordingArtifacts(o,p);return}let f=this.activeRecordings.get(o);if(!f)throw Error(`No active recording found for id ${o}`);let w=this.backend.forceStop;if(!w&&f.handle)throw Error("Video capture backend does not support force stopping recordings.");f.forceStopRequested=!0;let R=this.forceStopActiveRecording(f,w,d,c);this.forceStoppingRecordings.set(o,R);try{await R}finally{this.forceStoppingRecordings.delete(o)}}async forceStopActiveRecording(o,d,c,p){o.startAbortController.abort();let m=await this.resolveForceStopHandle(o,c);if(!m)return;if(!d)throw o.forceStopRequested=!1,Error("Video capture backend does not support force stopping recordings.");try{if(await d.call(this.backend,m,p),this.activeRecordings.delete(o.recordingId),c)await this.removeRecordingArtifacts(o.recordingId,o.outputPath)}catch(f){if(this.activeRecordings.get(o.recordingId)===o)o.forceStopRequested=!1;throw f}}retainStartCleanupHandle(o,d){if(!(o instanceof X))return!1;return d.handle=o.handle,!0}async handleStartFailure(o,d){if(this.retainStartCleanupHandle(o,d)){try{if(!d.forceStopRequested)await this.forceStopOrDiscardRecording(d.recordingId,!0)}catch(c){this.log.warn(`[VideoRecorderService] Failed to retry cleanup for ${d.recordingId}: ${String(c)}`,c)}throw o}if(this.activeRecordings.get(d.recordingId)===d&&!d.forceStopRequested)this.activeRecordings.delete(d.recordingId);if(!d.forceStopRequested)try{await this.removeRecordingArtifacts(d.recordingId,d.outputPath)}catch(c){this.log.warn(`[VideoRecorderService] Failed to remove aborted recording directory for ${d.recordingId}: ${String(c)}`)}throw o}async resolveForceStopHandle(o,d){try{return o.handle??await o.startPromise}catch(c){if(this.retainStartCleanupHandle(c,o))return c.handle;if(this.log.debug(`[VideoRecorderService] Starting recording ${o.recordingId} ended during force stop: ${c}`),this.activeRecordings.delete(o.recordingId),d)await this.removeRecordingArtifacts(o.recordingId,o.outputPath);return}}async removeRecordingArtifacts(o,d){let c=this.activeRecordings.get(o),p=d??c?.outputPath;if(!p)return;await this.fileSystem.rm(ye.dirname(p),{recursive:!0,force:!0})}getRecordingDir(o){return ye.join(this.archiveRoot,o)}async safeStat(o){try{return await Tr.stat(o)}catch(d){return this.log.warn(`[VideoRecorderService] Missing recording file at ${o}: ${r(d)}`,d),null}}}var wn=(o)=>{if(o===void 0)return L;if(typeof o==="function")return{next:o};return o};function bn(o,d){let c=ye.extname(o).slice(1).toLowerCase();return c==="mp4"||c==="mov"?c:d}function vn(o,d,c){let p=Sn(d);return`${o}-${p}.${c}`}function Rn(o){if(!o)return"";return o.replace(/[^A-Za-z0-9._-]+/g,"-").slice(0,64).replace(/^-+|-+$/g,"")}function Sn(o){return o.replace(/[-:]/g,"").replace(/\.\d{3}Z$/,"Z")}function Pn(o,d){let c=Date.parse(o),p=Date.parse(d);if(Number.isNaN(c)||Number.isNaN(p))return;return Math.max(0,p-c)}import{createWriteStream as Es}from"fs";import{rm as Cs}from"fs/promises";import{constants as Pi}from"fs";import{open as Fa,stat as _a}from"fs/promises";var Ir=-120,uK=-50,Mr=1,An=3,En=65534;function se(o){return new t(`Unsupported audio file: ${o}. Provide an uncompressed PCM WAV file (8/16/24/32-bit integer or 32-bit float).`)}function vt(o,d){return String.fromCharCode(o.getUint8(d),o.getUint8(d+1),o.getUint8(d+2),o.getUint8(d+3))}function Cn(o,d,c){if(c<16)throw se("fmt chunk is too short");let p=o.getUint16(d,!0);if(p===En&&c>=26)p=o.getUint16(d+24,!0);return{formatTag:p,channels:o.getUint16(d+2,!0),sampleRate:o.getUint32(d+4,!0),bitsPerSample:o.getUint16(d+14,!0)}}function xn(o){let{formatTag:d,bitsPerSample:c}=o;if(d===An&&c===32)return(p,m)=>Math.round(Math.max(-1,Math.min(1,p.getFloat32(m,!0)))*32767);if(d!==Mr)throw se(`format tag ${d} is compressed or unknown`);switch(c){case 8:return(p,m)=>p.getUint8(m)-128<<8;case 16:return(p,m)=>p.getInt16(m,!0);case 24:return(p,m)=>p.getInt16(m+1,!0);case 32:return(p,m)=>p.getInt32(m,!0)>>16;default:throw se(`${c}-bit samples are not supported`)}}function kn(o,d,c,p){let m=p.bitsPerSample/8,f=Math.floor(Math.min(c,o.byteLength-d)/m),w=xn(p),R=new Int16Array(f);for(let y=0;y<f;y++)R[y]=w(o,d+y*m);return R}function Fr(o){let d=new DataView(o.buffer,o.byteOffset,o.byteLength);if(o.byteLength<12||vt(d,0)!=="RIFF"||vt(d,8)!=="WAVE")throw se("missing RIFF/WAVE header");let c,p=12;while(p+8<=o.byteLength){let m=vt(d,p),f=d.getUint32(p+4,!0),w=p+8;if(m==="fmt ")c=Cn(d,w,f);else if(m==="data"){if(!c)throw se("data chunk precedes the fmt chunk");if(c.channels<1||c.sampleRate<1)throw se("fmt chunk declares no channels or no sample rate");let R=kn(d,w,f,c);return{sampleRate:c.sampleRate,channels:c.channels,samples:R}}p=w+f+f%2}throw se("no data chunk")}function cJ(o){let d=o.samples.length*2,c=new Uint8Array(44+d),p=new DataView(c.buffer),m=(f,w)=>{for(let R=0;R<w.length;R++)p.setUint8(f+R,w.charCodeAt(R))};m(0,"RIFF"),p.setUint32(4,36+d,!0),m(8,"WAVE"),m(12,"fmt "),p.setUint32(16,16,!0),p.setUint16(20,Mr,!0),p.setUint16(22,o.channels,!0),p.setUint32(24,o.sampleRate,!0),p.setUint32(28,o.sampleRate*o.channels*2,!0),p.setUint16(32,o.channels*2,!0),p.setUint16(34,16,!0),m(36,"data"),p.setUint32(40,d,!0);for(let f=0;f<o.samples.length;f++)p.setInt16(44+f*2,o.samples[f],!0);return c}function Ye(o){if(o.channels===1)return o;let d=Math.floor(o.samples.length/o.channels),c=new Int16Array(d);for(let p=0;p<d;p++){let m=0;for(let f=0;f<o.channels;f++)m+=o.samples[p*o.channels+f];c[p]=Math.round(m/o.channels)}return{sampleRate:o.sampleRate,channels:1,samples:c}}function Qe(o,d){if(o.channels!==1)throw Error("resampleMono expects mono PCM");if(o.sampleRate===d||o.samples.length===0)return{...o,sampleRate:d};let c=o.sampleRate/d,p=Math.max(1,Math.floor(o.samples.length/c)),m=new Int16Array(p),f=o.samples.length-1;for(let w=0;w<p;w++){let R=w*c,y=Math.min(Math.floor(R),f),P=Math.min(y+1,f),A=R-y;m[w]=Math.round(o.samples[y]*(1-A)+o.samples[P]*A)}return{sampleRate:d,channels:1,samples:m}}function _r(o){return Math.max(-32768,Math.min(32767,Math.round(o)))}function Or(o,d){if(d===0)return o;let c=10**(d/20);return{...o,samples:o.samples.map((p)=>_r(p*c))}}function Oe(o){let d=o.samples.length/o.channels;return Math.round(d/o.sampleRate*1000)}function Rt(o){if(o<=0)return Ir;return Math.max(Ir,Math.round(20*Math.log10(o/32768)*10)/10)}function Dr(o,d,c){if(c<=d)return 0;let p=0;for(let m=d;m<c;m++)p+=o[m]*o[m];return Math.sqrt(p/(c-d))}function Tn(o){let d=0;for(let c of o)d=Math.max(d,Math.abs(c));return d}function Vr(o,d={}){let c=d.silenceThresholdDbfs??uK,p=Math.max(o.channels,Math.round((d.windowMs??20)/1000*o.sampleRate)*o.channels),{samples:m}=o,f=0,w=0;for(let R=0;R<m.length;R+=p)if(f++,Rt(Dr(m,R,Math.min(R+p,m.length)))>=c)w++;return{durationMs:Oe(o),rmsDbfs:Rt(Dr(m,0,m.length)),peakDbfs:Rt(Tn(m)),activeRatio:f===0?0:Math.round(w/f*1000)/1000,silent:w===0}}function Hr(o){let d=o.sampleRate??48000,c=o.frequencyHz??1000,p=32767*10**((o.amplitudeDbfs??-6)/20),m=Math.round(o.durationMs/1000*d),f=new Int16Array(m);for(let w=0;w<m;w++)f[w]=_r(p*Math.sin(2*Math.PI*c*w/d));return{sampleRate:d,channels:1,samples:f}}function Ze(o){if(!Number.isSafeInteger(o)||o<0)throw RangeError(`varint must be a non-negative safe integer, got ${o}`);let d=[],c=o;while(c>=128)d.push(c%128|128),c=Math.floor(c/128);return d.push(c),d}class et{chunks=[];varint(o,d){if(d!==0)this.chunks.push(Uint8Array.from([...Ze(o*8+0),...Ze(d)]));return this}bytes(o,d){if(d.byteLength>0){let c=[...Ze(o*8+2),...Ze(d.byteLength)];this.chunks.push(Uint8Array.from(c),d)}return this}finish(){let o=new Uint8Array(this.chunks.reduce((c,p)=>c+p.byteLength,0)),d=0;for(let c of this.chunks)o.set(c,d),d+=c.byteLength;return o}}function Pt(o){let d=0,c=1;for(;;){if(o.offset>=o.bytes.byteLength)throw RangeError("truncated varint");let p=o.bytes[o.offset++];if(d+=(p&127)*c,p<128)return d;c*=128}}function St(o,d){if(o.offset+d>o.bytes.byteLength)throw RangeError("truncated field");let c=o.bytes.subarray(o.offset,o.offset+d);return o.offset+=d,c}function In(o,d){switch(d){case 0:return{kind:"varint",value:Pt(o)};case 2:return{kind:"bytes",value:St(o,Pt(o))};case 1:St(o,8);return;case 5:St(o,4);return;default:throw RangeError(`unsupported wire type ${d}`)}}function At(o){let d={bytes:o,offset:0},c=[];while(d.offset<o.byteLength){let p=Pt(d),m=In(d,p%8);if(m)c.push({field:Math.floor(p/8),value:m})}return c}var de=48000,ie={samplingRate:1,channels:2,format:3,mode:4},be={format:1,timestamp:2,audio:3};function tt(o){return new et().varint(ie.samplingRate,o.samplingRate).varint(ie.channels,o.channels==="stereo"?1:0).varint(ie.format,o.format==="s16"?1:0).varint(ie.mode,o.mode==="realtime"?1:0).finish()}function $r(o){let d=new et;if(o.format)d.bytes(be.format,tt(o.format));return d.varint(be.timestamp,o.timestampUs??0).bytes(be.audio,o.audio).finish()}function Dn(o){let d={samplingRate:44100,channels:"mono",format:"u8",mode:"unspecified"};for(let{field:c,value:p}of At(o)){if(p.kind!=="varint")continue;if(c===ie.samplingRate)d.samplingRate=p.value;else if(c===ie.channels)d.channels=p.value===1?"stereo":"mono";else if(c===ie.format)d.format=p.value===1?"s16":"u8";else if(c===ie.mode)d.mode=p.value===1?"realtime":"unspecified"}return d}function Et(o){let d={audio:new Uint8Array(0)};for(let{field:c,value:p}of At(o))if(c===be.format&&p.kind==="bytes")d.format=Dn(p.value);else if(c===be.timestamp&&p.kind==="varint")d.timestampUs=p.value;else if(c===be.audio&&p.kind==="bytes")d.audio=p.value;return d}var ce=5;function Lr(o){let d=new Uint8Array(ce+o.byteLength);return new DataView(d.buffer).setUint32(1,o.byteLength,!1),d.set(o,ce),d}class Ct{maxMessageBytes;buffer=new Uint8Array(0);constructor(o=16777216){this.maxMessageBytes=o}push(o){this.buffer=Mn(this.buffer,o);let d=[];while(this.buffer.byteLength>=ce){let c=new DataView(this.buffer.buffer,this.buffer.byteOffset,this.buffer.byteLength);if(c.getUint8(0)!==0)throw Error("received a compressed gRPC message; compression was not negotiated");let p=c.getUint32(1,!1);if(p>this.maxMessageBytes)throw Error(`gRPC message of ${p} bytes exceeds the ${this.maxMessageBytes}-byte limit`);if(this.buffer.byteLength<ce+p)break;d.push(this.buffer.slice(ce,ce+p)),this.buffer=this.buffer.subarray(ce+p)}return d}get pendingBytes(){return this.buffer.byteLength}}function Mn(o,d){if(o.byteLength===0)return d;let c=new Uint8Array(o.byteLength+d.byteLength);return c.set(o,0),c.set(d,o.byteLength),c}var H={OK:0,CANCELLED:1,UNKNOWN:2,INVALID_ARGUMENT:3,DEADLINE_EXCEEDED:4,NOT_FOUND:5,PERMISSION_DENIED:7,FAILED_PRECONDITION:9,UNIMPLEMENTED:12,UNAVAILABLE:14,UNAUTHENTICATED:16};function Fn(o){try{return decodeURIComponent(o)}catch(d){return e.debug(`grpc-message was not valid percent-encoding: ${r(d)}`),o}}function Br(o){if(o===void 0)return;return Array.isArray(o)?o[0]:String(o)}function xt(...o){for(let d of o){let c=Br(d?.["grpc-status"]);if(c!==void 0){let p=Number.parseInt(c,10);return{code:Number.isNaN(p)?H.UNKNOWN:p,message:Fn(Br(d?.["grpc-message"])??"")}}}return}class O extends t{code;grpcStatus;constructor(o,d,c,p){super(`[${o}] ${d}`);this.code=o;this.grpcStatus=c;this.retryable=p?.retryable,this.remedy=p?.remedy}retryable;remedy}var rt="Grant macOS Microphone permission to the host app that runs the emulator in System Settings > Privacy and Security > Microphone, or restart the emulator.";function Ur(o){return new O("audio_host_microphone_unavailable",`Emulator ${o} reported a host microphone voice failure. ${rt}`,void 0,{retryable:!1,remedy:rt})}function Gr(o){return new O("audio_repeat_injection_unsafe",`An injection has already been started on emulator ${o} in this boot; another may crash it. Stop any earlier injection before restarting. ${rt}`,void 0,{retryable:!1,remedy:rt})}var Nr="Relaunch the emulator with -grpc-use-token, or with -grpc <port> and no JWT, then retry.";function jr(o){return o.code===H.UNAUTHENTICATED||o.code===H.PERMISSION_DENIED||o.code===H.INVALID_ARGUMENT&&/\bJWT\b/i.test(o.message)}function zr(o,d){return new O("audio_grpc_auth_rejected",`The emulator refused AutoMobile's gRPC credentials for audio ${o} (gRPC status ${d.code}: ${d.message||"no detail"}). ${Nr}`,d,{retryable:!1,remedy:Nr})}function kt(o){if(jr(o))return zr("injection",o);switch(o.code){case H.FAILED_PRECONDITION:return new O("audio_injection_busy","Another audio injection is already active on this emulator. Stop it before starting a new one.",o);case H.UNIMPLEMENTED:case H.UNAVAILABLE:return new O("audio_injection_unsupported",`The emulator's gRPC audio injection is unavailable (${o.message||"no detail"}). Use an emulator build with gRPC enabled and do not launch it with -no-audio.`,o);default:return new O("audio_grpc_failed",`Emulator audio injection failed with gRPC status ${o.code}: ${o.message||"no detail"}`,o)}}function Tt(o){if(jr(o))return zr("capture",o);let d=o.code===H.UNIMPLEMENTED||o.code===H.UNAVAILABLE;return new O(d?"audio_capture_unsupported":"audio_grpc_failed",`Emulator audio capture failed with gRPC status ${o.code}: ${o.message||"no detail"}`,o)}function Kr(o){return new O("audio_emulator_exited",`Emulator ${o} exited during audio injection. Restart the emulator and start a new injection.`)}class It{sampleRate;nowUs;nextUs;constructor(o,d){this.sampleRate=o;this.nowUs=d;this.nextUs=d()}before(o){let d=this.nowUs(),c=o.timestampUs??0,m=c>0&&(Math.abs(c-d)<1e7||Math.abs(c-this.nextUs)<1e7)?c:d,f=Math.min(m-this.nextUs,300000000);if(this.nextUs=Math.max(this.nextUs,m)+o.audio.byteLength/2/this.sampleRate*1e6,f<50000)return;return new Uint8Array(Math.round(f*this.sampleRate/1e6)*2)}}var qr="/android.emulation.control.EmulatorController",_n=`${qr}/injectAudio`,Wr=`${qr}/streamAudio`,On=20,Vn=200,$n=2000;function Ln(o){let d=Ye(o);return d.sampleRate>de?Qe(d,de):d}function Nn(o){let d=new Uint8Array(o.length*2),c=new DataView(d.buffer);for(let p=0;p<o.length;p++)c.setInt16(p*2,o[p],!0);return d}function Un(o){let d=new DataView(o.buffer,o.byteOffset,o.byteLength),c=new Int16Array(Math.floor(o.byteLength/2));for(let p=0;p<c.length;p++)c[p]=d.getInt16(p*2,!0);return c}function jn(o){let d,c,p=new Promise((m)=>{c=m});return{get endReason(){return d},ended:p,end(m){if(d)return;d=m,o.cancel(),c()}}}class Dt{transport;authorizer;timer;constructor(o,d,c=i){this.transport=o;this.authorizer=d;this.timer=c}async injectAudio(o,d={}){let c=Ln(o),p=await this.open(_n,d.beforeStreamOpen),m,f=new Promise((y)=>{m=this.timer.setTimeout(()=>y(void 0),Vn)});try{let y=await l([p.status(),p.responseHeaders(),f],{timer:this.timer,label:"Audio injection acceptance"});if(y&&y.code!==H.OK&&y.code!==H.CANCELLED)throw kt(y)}finally{this.timer.clearTimeout(m)}let w=jn(p),R=this.streamInjection(p,c,d,w);return R.catch((y)=>e.debug(`audio injection ended with ${r(y)}`)),{durationMs:Oe(c),sampleRate:c.sampleRate,done:R,stop:()=>(w.end("stopped"),R)}}async captureAudio(o){let d=Math.min(o.sampleRate??de,de),c={samplingRate:d,channels:"mono",format:"s16"},p=await this.open(Wr);await p.write(tt(c)),p.end();let m=Math.round(o.durationMs/1000*d),f=!1,w=this.timer.setTimeout(()=>{f=!0,p.cancel()},o.durationMs+$n),R=[],y=0;try{for await(let C of p.messages()){let T=Un(Et(C).audio);if(R.push(T),y+=T.length,y>=m){p.cancel();break}}}finally{this.timer.clearTimeout(w)}let P=await p.status();if(y===0&&!f&&P.code!==H.OK&&P.code!==H.CANCELLED)throw Tt(P);let A=new Int16Array(Math.min(y,m)),x=0;for(let C of R){let T=C.subarray(0,A.length-x);A.set(T,x),x+=T.length}return{pcm:{sampleRate:d,channels:1,samples:A},timedOut:f&&y<m}}async streamCapture(o,d={}){let c=Math.min(d.sampleRate??de,de),p=await this.open(Wr);await p.write(tt({samplingRate:c,channels:"mono",format:"s16"})),p.end();let m=new It(c,()=>this.timer.now()*1000),f=(async()=>{try{for await(let y of p.messages()){let P=Et(y),A=m.before(P);if(A)await o(A);await o(P.audio)}}catch(y){e.debug(`audio stream ended: ${r(y)}`)}})(),w,R=async()=>{p.cancel(),await f;let y=await p.status();if(y.code!==H.OK&&y.code!==H.CANCELLED)throw Tt(y)};return{sampleRate:c,stop:()=>(w??=R(),w)}}async close(){this.transport.close(),await this.authorizer.dispose()}async open(o,d){let c=await this.authorizer.authorization(o);return d?.(),this.transport.open(o,c?{authorization:c}:{})}async streamInjection(o,d,c,p){let m={call:o,pcm:d,options:c,control:p,framesQueued:0},f=c.maxDurationMs===void 0?void 0:this.timer.setTimeout(()=>p.end("max_duration"),c.maxDurationMs);try{if(c.startDelayMs)await this.delayUnlessEnded(c.startDelayMs,p);await this.sendAll(m)}finally{if(f)this.timer.clearTimeout(f)}o.end();let w=await o.status();if(w.code!==H.OK&&w.code!==H.CANCELLED)throw kt(w);return{framesQueued:m.framesQueued,framesPlayed:this.framesPlayed(m),reason:p.endReason??"completed"}}async sendAll(o){try{let d=!1;do d=await this.sendPass(o);while(d&&o.options.loop&&o.pcm.samples.length>0)}catch(d){e.debug(`audio injection write ended: ${r(d)}`)}}delayUnlessEnded(o,d){return new Promise((c)=>{let p=this.timer.setTimeout(c,o);d.ended.then(()=>{this.timer.clearTimeout(p),c()})})}playbackNowMs(){return this.timer.monotonicNow?.()??this.timer.now()}framesPlayed(o){if(o.playbackStartMs===void 0)return 0;let d=Math.max(0,this.playbackNowMs()-o.playbackStartMs),c=Math.floor(d*o.pcm.sampleRate/1000);return Math.min(o.framesQueued,c)}async sendPass(o){let{pcm:d}=o,c={samplingRate:d.sampleRate,channels:"mono",format:"s16"},p=Math.max(1,Math.round(On/1000*d.sampleRate));for(let m=0;m<d.samples.length;m+=p){if(o.control.endReason)return!1;let f=Nn(d.samples.subarray(m,m+p));o.playbackStartMs??=this.playbackNowMs(),await o.call.write($r({format:o.framesQueued===0?c:void 0,timestampUs:this.timer.now()*1000,audio:f})),o.framesQueued+=f.byteLength/2}return!0}}import{generateKeyPairSync as zn,sign as Kn}from"crypto";import Wn from"path";var qn="android-studio",Jn=900,Jr=10,Xr=100;function Mt(o){return Buffer.from(o).toString("base64url")}class Yr{jwksDir;activeJwksFile;fs;registration;keyFile;ids;timer;constructor(o,d,c,{ids:p=L,timer:m=i}={}){this.jwksDir=o;this.activeJwksFile=d;this.fs=c;this.ids=p,this.timer=m}async authorization(o){this.registration??=this.register();let{kid:d,privateKey:c}=await this.registration,p=Math.floor(this.timer.now()/1000),m=Mt(JSON.stringify({alg:"ES512",kid:d})),f=Mt(JSON.stringify({iss:qn,aud:[o],iat:p,exp:p+Jn})),w=Kn("sha512",Buffer.from(`${m}.${f}`),{key:c,dsaEncoding:"ieee-p1363"});return`Bearer ${m}.${f}.${Mt(w)}`}async dispose(){let o=this.keyFile;if(this.keyFile=void 0,this.registration=void 0,!o)return;try{await this.fs.unlink(o)}catch(d){e.debug(`emulator JWK ${o} already gone: ${r(d)}`)}}async register(){let{publicKey:o,privateKey:d}=zn("ec",{namedCurve:"P-521"}),c=this.ids.next(),p={...o.export({format:"jwk"}),use:"sig",alg:"ES512",key_ops:["verify"],kid:c};this.keyFile=Wn.join(this.jwksDir,`${c}.jwk`),await this.fs.writeFile(this.keyFile,JSON.stringify({keys:[p]}));for(let m=0;m<Jr;m++){if(await this.activeSetHas(c))return{kid:c,privateKey:d};await this.timer.sleep(Xr)}throw await this.dispose(),new t(`The emulator did not load AutoMobile's gRPC key from ${this.jwksDir} within ${Jr*Xr}ms. Restart the emulator, or launch it with -grpc-use-token.`)}async activeSetHas(o){try{return JSON.parse(await this.fs.readFile(this.activeJwksFile)).keys?.some((c)=>c.kid===o)??!1}catch(d){return e.debug(`emulator active JWKS not readable yet: ${r(d)}`),!1}}}function Qr(o,d){switch(o.kind){case"token":return{authorization:async()=>`Bearer ${o.token}`,dispose:async()=>{}};case"jwt":return new Yr(o.jwksDir,o.activeJwksFile,d);case"none":return{authorization:async()=>{return},dispose:async()=>{}}}}import Xn from"http2";import Zr from"http2";class Ft{flow;highWater;lowWater;messages=[];paused=!1;constructor(o,d=64,c=16){this.flow=o;this.highWater=d;this.lowWater=c}push(o){if(this.messages.push(...o),!this.paused&&this.messages.length>=this.highWater)this.paused=!0,this.flow.pause()}shift(){let o=this.messages.shift();if(this.paused&&this.messages.length<=this.lowWater)this.paused=!1,this.flow.resume();return o}}class _t{stream;decoder=new Ct;queue;wake;finished=!1;headers;finalStatus;initialStatus;constructor(o){this.stream=o;this.queue=new Ft({pause:()=>o.pause(),resume:()=>o.resume()}),this.initialStatus=new Promise((d)=>{o.on("response",(c)=>{this.headers=c,d(xt(c))})}),o.on("data",(d)=>this.onData(d)),this.finalStatus=new Promise((d)=>{let c;o.on("trailers",(p)=>{c=p}),o.on("error",(p)=>{d({code:H.UNAVAILABLE,message:r(p)})}),o.on("close",()=>{this.finish(),d(this.statusAtClose(c))})})}write(o){return new Promise((d,c)=>{if(this.stream.destroyed||this.stream.writableEnded){c(Error("gRPC stream is closed"));return}let p=()=>c(Error("gRPC stream closed before the write completed"));this.stream.once("close",p),this.stream.write(Lr(o),(m)=>{if(this.stream.off("close",p),m)c(m);else d()})})}end(){if(!this.stream.writableEnded)this.stream.end()}async*messages(){for(;;){let o=this.queue.shift();if(o)yield o;else if(this.finished)return;else await new Promise((d)=>{this.wake=d})}}status(){return this.finalStatus}responseHeaders(){return this.initialStatus}cancel(){if(!this.stream.destroyed)this.stream.close(Zr.constants.NGHTTP2_CANCEL)}onData(o){try{this.queue.push(this.decoder.push(o))}catch(d){this.stream.destroy(d instanceof Error?d:Error(r(d)))}this.notify()}finish(){this.finished=!0,this.notify()}notify(){let o=this.wake;this.wake=void 0,o?.()}statusAtClose(o){let d=xt(o,this.headers);if(d)return d;if(this.stream.rstCode===Zr.constants.NGHTTP2_CANCEL)return{code:H.CANCELLED,message:"cancelled"};return{code:H.UNKNOWN,message:`stream closed without a gRPC status (HTTP ${this.headers?.[":status"]??"none"})`}}}class Ot{address;session;constructor(o){this.address=o}open(o,d){let p=this.connect().request({":method":"POST",":path":o,"content-type":"application/grpc",te:"trailers",...d});return new _t(p)}close(){this.session?.close(),this.session=void 0}connect(){if(!this.session||this.session.closed||this.session.destroyed){let o=Xn.connect(`http://${this.address}`);o.on("error",(d)=>{e.debug(`emulator gRPC session error: ${r(d)}`)}),this.session=o}return this.session}}var ue=n().min(1).max(256),Yn=Ko("type",[s({key:ue,type:I("string"),value:n()}).strict(),s({key:ue,type:I("int"),value:a().int()}).strict(),s({key:ue,type:I("long"),value:a().int()}).strict(),s({key:ue,type:I("float"),value:a().finite()}).strict(),s({key:ue,type:I("boolean"),value:h()}).strict(),s({key:ue,type:I("stringArray"),value:b(n())}).strict(),s({key:ue,type:I("uri"),value:n()}).strict()]),dJ={component:n().min(1).optional().describe('A class inside appId: ".Receiver", "com.app.Receiver", or "com.app/.Receiver"'),action:n().min(1).optional().describe("Intent action, e.g. com.app.DEBUG_TOGGLE"),data:n().min(1).optional().describe("Data URI"),mimeType:n().min(1).optional(),categories:b(n().min(1)).max(16).optional(),extras:b(Yn).max(64).optional().describe("Typed extras")},Qn={string:"--es",int:"--ei",long:"--el",float:"--ef",boolean:"--ez",stringArray:"--esa",uri:"--eu"};function Zn(o){return o.map((d)=>d.replace(/\\/g,"\\\\").replace(/,/g,"\\,")).join(",")}function ea(o){let d=o.type==="stringArray"?Zn(o.value):String(o.value);return[Qn[o.type],S(o.key),S(d)]}function ta(o,d){let c=d.indexOf("/");if(c>=0){let p=d.slice(0,c),m=d.slice(c+1);if(p!==o||m.length===0)throw new t(`Component "${d}" is outside ${o}; name a class inside the app under test.`);return`${o}/${m}`}return`${o}/${d}`}function Vt(o,d){return[...d.action?["-a",S(d.action)]:[],...d.data?["-d",S(d.data)]:[],...d.mimeType?["-t",S(d.mimeType)]:[],...(d.categories??[]).flatMap((c)=>["-c",S(c)]),...d.component?["-n",S(ta(o,d.component))]:["-p",S(o)],...(d.extras??[]).flatMap(ea)]}var ra=30000;function ia(o){return["am","broadcast",...o.userId===void 0?[]:["--user",String(o.userId)],...Vt(o.appId,o.intent)].join(" ")}var oa=/Broadcast completed: result=(-?\d+)(?:, data="([\s\S]*?)")?\s*$/m,aa=/not allowed to send broadcast ([^\s]+?)(?: from|\s|$)/;function it(o){let d=oa.exec(o);if(d)return{delivered:!0,resultCode:Number(d[1]),...d[2]===void 0?{}:{resultData:d[2]},output:o};let c=aa.exec(o);if(c)return{delivered:!1,errorCode:"protected_broadcast",error:`${c[1]} is a protected system broadcast; only the system can send it, not the adb shell. Use an app-defined action the receiver also accepts.`,output:o};if(/SecurityException|Permission Denial/.test(o))return{delivered:!1,errorCode:"permission_denied",error:"The broadcast was refused: the shell lacks a permission it requires.",output:o};return{delivered:!1,errorCode:"broadcast_failed",error:"am broadcast did not report completion.",output:o}}var sa=1e4;function da(o){return["cmd","package","query-receivers","--components",...o.userId===void 0?[]:["--user",String(o.userId)],...Vt(o.appId,o.intent)].join(" ")}class LO{adb;constructor(o){this.adb=o}async send(o,d){let c=await this.precheck(o,d);if(c)return c;let p=ia(o);try{let m=await this.adb.execute(["shell",p],{timeoutMs:ra,noRetry:!0,signal:d});return it(`${m.stdout}
|
|
3
|
-
${m.stderr}`.trim())}catch(m){if(d?.aborted)throw m;return e.warn(`[sendBroadcast] am broadcast failed: ${r(m)}`,m),it(r(m))}}async precheck(o,d){let c=await this.probe(`pm list packages${o.userId===void 0?"":` --user ${o.userId}`}`,d);if(c!==null&&!ko(c,o.appId))return{delivered:!1,errorCode:"package_not_installed",error:`${o.appId} is not installed, so nothing can receive the broadcast.`,output:c};if(!o.intent.component)return null;let p=await this.probe(da(o),d);if(p!==null&&!p.includes(`${o.appId}/`))return{delivered:!1,errorCode:"no_matching_receiver",error:`${o.appId} declares no receiver ${o.intent.component} for ${o.intent.action??"this intent"}; the broadcast was not sent.`,output:p};return null}async probe(o,d){try{return(await this.adb.execute(["shell",o],{timeoutMs:sa,noRetry:!0,signal:d})).stdout}catch(c){if(d?.aborted)throw c;return e.warn(`[sendBroadcast] precheck "${o}" failed: ${r(c)}`,c),null}}}var ti=60000,$t=3720000;function G(o,d){return new O("audio_guest_capture_unavailable",`Cannot verify an open guest microphone capture on ${o}: ${d}. Injection was refused to protect the emulator. The guest microphone capture is provided by the CtrlProxy app. Stop competing recordings and retry. AutoMobile does not enable adb root.`)}var ca=`${pt}/.GuestAudioCaptureReceiver`,ua="dev.jasonpearson.automobile.GUEST_AUDIO_CAPTURE",Ht=2000;class Bt{adbFor;discovery;ids;now;timeoutMs;pollMs;settleMs;timer;options;constructor(o,d,c,{timer:p=i,...m}={}){this.adbFor=o;this.discovery=d;this.ids=c;if(this.timer=p,this.options=m,this.now=p.monotonicNow?.bind(p)??p.now.bind(p),this.timeoutMs=m.timeoutMs??8000,this.pollMs=m.pollMs??100,this.settleMs=m.settleMs??3000,![this.timeoutMs,this.pollMs,this.settleMs].every(Number.isFinite)||Math.min(this.timeoutMs,this.pollMs)<=0||this.settleMs<0||this.settleMs>=this.timeoutMs)throw new O("audio_guest_capture_unavailable","Invalid guest capture polling or settle deadline.")}async open(o,{leaseMs:d}){let c=this.now()+this.timeoutMs,p,m,f=!1,w=!1,R;try{R=this.adbFor(o)}catch(A){throw G(o,r(A))}let y=async(A,x)=>{let C=x-this.now();if(C<=0)throw G(o,"capture verification deadline expired");let T=await R.execute(["shell","am","broadcast","-n",ca,"-a",ua,"--es","op",A,"--es","lease",Vo(m??""),...A==="start"?["--el","leaseTimeoutMs",String(d)]:[]],{timeoutMs:Math.min(Ht,C),noRetry:!0,signal:new AbortController().signal});if(this.now()>=x)throw G(o,"capture verification deadline expired");if(T.error)throw G(o,T.error);let D=it(`${T.stdout}
|
|
4
|
-
${T.stderr}`),N="the CtrlProxy on the device has no guest capture receiver; reinstall the CtrlProxy APK";if(!D.delivered){let V=D.output.trim().slice(0,2048);switch(D.errorCode){case"permission_denied":throw G(o,`the adb shell was refused the CtrlProxy receiver, which needs android.permission.DUMP (held by the adb shell): ${V}`);case"no_matching_receiver":throw G(o,N);case"protected_broadcast":throw G(o,`the guest capture broadcast is protected: ${V}`);default:if(D.output.trimStart().startsWith("Error: receiver not found"))throw G(o,N);throw G(o,`the guest capture broadcast failed: ${V}`)}}if(!D.resultData)throw G(o,N);return D.resultData.slice(0,2048)},P=async()=>{if(w||!f)return;w=!0;try{if(p===void 0||await this.emulatorPidFor(o)!==p){e.debug(`Skipping guest capture cleanup on ${o}: emulator identity changed`);return}}catch(A){e.debug(`Skipping guest capture cleanup on ${o}: ${r(A)}`);return}try{let A=await y("stop",this.now()+Ht),x=A.split(" ",1)[0];if(x!=="stopped"&&x!=="absent")throw new t(`Guest capture stop refused: ${A}`)}catch(A){throw u(A,`Failed to close guest audio capture on ${o}`)}};try{if(p=await this.emulatorPidFor(o),await this.ensureRecordAudioPermission(R,o,c),m=this.ids.next(),!m||/[\r\n\0]/.test(m))throw G(o,"the capture lease is invalid");f=!0;let A=await y("start",c);if(A.split(" ",1)[0]!=="running")throw G(o,A);let x=this.now();while(this.now()<c){let C=this.now();if(C-x>=this.settleMs)return{close:P};await this.timer.sleep(Math.min(this.pollMs,c-C));let T=await y("status",c);if(T.split(" ",1)[0]!=="running")throw G(o,T)}throw G(o,"capture verification deadline expired")}catch(A){throw await P().catch((x)=>{e.warn(`Failed guest capture start cleanup on ${o}: ${r(x)}`)}),A instanceof O?A:G(o,r(A))}}async ensureRecordAudioPermission(o,d,c){let p=()=>{let P=c-this.now();if(P<=0)throw G(d,"capture verification deadline expired");return Math.min(Ht,P)},m=(P,A)=>{if(P instanceof O)return P;return p(),G(d,`the RECORD_AUDIO check could not ${A}: ${r(P)}`)},f;try{p();let P=this.options.resolveSetupUser;if(P)f=await l(()=>P(d),{timer:this.timer,timeoutMs:c-this.now(),label:"CtrlProxy setup user resolution",timeoutError:()=>G(d,"capture verification deadline expired")});p()}catch(P){throw m(P,"read")}let w=(P)=>new O("audio_record_permission_not_granted",`${Pv} is not granted to ${pt}: ${P}. Run: adb shell pm grant ${pt} ${Pv}`),R=async()=>{let P;try{P=await o.execute(["shell","dumpsys","package",pt],{noRetry:!0,timeoutMs:p()})}catch(x){throw m(x,"read")}if(p(),P.error)throw m(P.error,"read");let A=Bn(P.stdout,pt,f)?.runtimePermissions.get(Pv);if(!A)throw w("the runtime permission row is absent");return A.state==="granted"};if(await R())return;let y=await wW(o,f,p(),p);if(!y.granted&&y.transportError instanceof O)throw y.transportError;if(p(),!y.granted){if("transportError"in y)throw m(y.transportError,"grant");throw w(y.reason)}if(!await R())throw w("the runtime permission remains ungranted after pm grant")}async emulatorPidFor(o){let d=le(o)?await this.discovery.findByConsolePort(Number(o.slice(9))):void 0;if(!d||!Number.isSafeInteger(d.pid)||d.pid<1)throw G(o,"the emulator incarnation could not be identified");return d.pid}}var pa=52428800,ma=2000,fa=600000,ri=64,ga=128;function ii(o,d,c){if(c!==void 0&&d!==c)throw new t(`Audio injection '${o}' is on ${d}, not ${c}. Stop it on ${d}.`)}function Nt(o,d){return new t(`Audio file ${o} is larger than the ${d}-byte limit. Use a shorter clip.`)}function oi(o,d){return new O(o,d)}class Ut{deps;injectionStarts=new Map;reservedDevices=new Set;active=new Map;hostLoopbackStarting=!1;finished=new Map;constructor(o){this.deps=o}async startInjection(o,d){if(this.reservedDevices.has(o))throw new O("audio_injection_busy",`An audio injection is starting or active on ${o}. Stop it before starting another.`);this.reservedDevices.add(o);try{return await this.startReservedInjection(o,d)}catch(c){throw this.reservedDevices.delete(o),u(c,`Cannot start audio injection on ${o}`)}}async startReservedInjection(o,d){let c=await this.routeFor(o,"audio_injection_unsupported");this.assertInjectionSafe(o,c.endpoint);let p=this.reserveHostLoopback(c.route),m;try{m=await this.openInjection(o,c,d)}finally{p()}let{injection:f,injectionId:w}=m,R=this.settle(o,c.endpoint,m);this.active.set(w,{deviceId:o,route:c.route,owner:d.sessionId,injection:f,result:R});let y=()=>{this.active.delete(w),this.reservedDevices.delete(o),this.finished.set(w,{deviceId:o,result:R});while(this.finished.size>ri)this.finished.delete(this.finished.keys().next().value)};return R.then(y,(P)=>{e.warn(`Audio injection ${w} on ${o} failed: ${r(P)}`),y()}),{injectionId:w,deviceId:o,durationMs:f.durationMs,sampleRate:f.sampleRate,route:c.route}}async stopInjection(o,d){let c=this.finished.get(o);if(c)return ii(o,c.deviceId,d),c.result;let p=this.active.get(o);if(!p)throw new t(`No audio injection '${o}' on this server. Only the last ${ri} ended injections are kept, and a server restart forgets them all; start a new injection.`);return ii(o,p.deviceId,d),await p.injection.stop().catch((m)=>{e.debug(`audio injection ${o} stop: ${r(m)}`)}),p.result}stopDevice(o){return this.stopMatching((d)=>d.deviceId===o)}stopOwnedBy(o,d){let c=(p)=>p.deviceId===o&&p.owner===d;return[...this.active.values()].some(c)?this.stopMatching(c):void 0}stopOwnerless(o){let d=(c)=>c.deviceId===o&&c.owner===void 0;return[...this.active.values()].some(d)?this.stopMatching(d):void 0}async stopMatching(o){let d=[...this.active].filter(([,c])=>o(c)).map(([c])=>c);return await Promise.all(d.map((c)=>this.stopInjection(c).catch((p)=>{e.warn(`Failed to stop audio injection ${c}: ${r(p)}`)}))),d.length}activeInjectionIds(o){return[...this.active].filter(([,d])=>d.deviceId===o).map(([d])=>d)}async capture(o,d){let c=await this.routeFor(o,"audio_capture_unsupported"),p=c.open();try{let{pcm:m,timedOut:f}=await p.captureAudio({durationMs:d.durationMs,sampleRate:d.sampleRate});return{...Vr(m,{silenceThresholdDbfs:d.silenceThresholdDbfs}),pcm:m,timedOut:f,route:c.route}}finally{await p.close()}}async startStream(o,d,c={}){let m=(await this.routeFor(o,"audio_capture_unsupported")).open(),f;try{f=await m.streamCapture(d,c)}catch(y){throw await m.close(),y}let w,R=async()=>{try{await f.stop()}finally{await m.close()}};return{sampleRate:f.sampleRate,stop:()=>(w??=R(),w)}}async settle(o,d,c){let{injectionId:p,injection:m,session:f,guestCapture:w}=c;try{return{injectionId:p,...await m.done}}catch(R){throw d?await this.classifyInjectionError(o,d,R):u(R,`Audio injection on ${o} failed`)}finally{await this.closeInjectionResources(w,f)}}async closeInjectionResources(o,d){let c=!0;for(let p of[o,d])try{await p?.close()}catch(m){e.warn(`Failed to close audio injection resource: ${r(m)}`),c=!1}return c}async classifyInjectionError(o,d,c){if(c instanceof O&&c.code==="audio_host_microphone_unavailable")return c;try{let p=await this.deps.discovery.findByConsolePort(d.consolePort);if(!p||p.pid!==d.pid)return Kr(o)}catch(p){e.warn(`Cannot check emulator ${o} after audio injection failure: ${r(p)}`)}return u(c,`Audio injection on ${o} failed`)}async openInjection(o,d,c){let p=Or(await this.loadSource(c.source),c.gainDb??0);this.assertInjectionSafe(o,d.endpoint);let m=Math.ceil(p.samples.length/p.channels/p.sampleRate*1000),f=c.maxDurationMs??(c.loop?fa:void 0),w=f??m,R=(c.startDelayMs??0)+w+ti;if(d.endpoint&&R>$t)throw new t(`Guest microphone capture lease exceeds the ${$t} ms (62 minute) limit. Reduce startDelayMs or maxDurationMs, or use a shorter clip.`);let y=d.endpoint?await this.deps.guestCapture.open(o,{leaseMs:R}):void 0,P;try{this.assertInjectionSafe(o,d.endpoint),P=d.open();let A=this.deps.ids.next();if(d.endpoint)this.recordInjectionStart(o,d.endpoint);let x=await P.injectAudio(p,{loop:c.loop,startDelayMs:c.startDelayMs,maxDurationMs:f,beforeStreamOpen:()=>this.assertInjectionSafe(o,d.endpoint,1)});return{session:P,injection:x,injectionId:A,guestCapture:y}}catch(A){throw await this.closeInjectionResources(y,P),d.endpoint?await this.classifyInjectionError(o,d.endpoint,A):u(A,`Audio injection on ${o} failed`)}}recordInjectionStart(o,d){this.pruneInjectionHistory(o,d.pid);let c=`${o}:${d.pid}`;this.injectionStarts.set(c,(this.injectionStarts.get(c)??0)+1);while(this.injectionStarts.size>ga){let p=this.injectionStarts.keys().next().value;if(p!==void 0)this.injectionStarts.delete(p)}}pruneInjectionHistory(o,d){let c=`${o}:`,p=`${c}${d}`;for(let m of this.injectionStarts.keys())if(m.startsWith(c)&&m!==p)this.injectionStarts.delete(m)}assertInjectionSafe(o,d,c=0){if(!d)return;if(this.pruneInjectionHistory(o,d.pid),this.deps.outputTail?.hostMicrophoneFailed(o,d.pid))throw Ur(o);if((this.injectionStarts.get(`${o}:${d.pid}`)??0)>c)throw Gr(o)}reserveHostLoopback(o){if(o!=="host-loopback")return()=>{};let d=[...this.active].find(([,c])=>c.route==="host-loopback");if(this.hostLoopbackStarting||d){let c=d?`Audio injection '${d[0]}' on ${d[1].deviceId} is`:"Another injection is starting and";throw new O("audio_injection_busy",`${c} using the host loopback device, which every iOS Simulator on this host records from. Stop it before starting another.`)}return this.hostLoopbackStarting=!0,()=>{this.hostLoopbackStarting=!1}}async routeFor(o,d){let c=this.deps.createHostLoopbackSession;if(c&&W({deviceId:o})==="simulator")return{route:"host-loopback",open:c};let p=await this.endpointFor(o,d);return{route:"emulator-grpc",endpoint:p,open:()=>this.deps.createSession(p)}}async endpointFor(o,d){if(!le(o))throw oi(d,`Audio injection and capture support local Android emulators and iOS Simulators; '${o}' is neither.`);let c=Number.parseInt(o.slice(9),10),p=await this.deps.discovery.findByConsolePort(c);if(!p)throw oi(d,`Emulator ${o} does not advertise a gRPC endpoint. Use an emulator build with gRPC enabled (the default on recent builds) running on this host.`);return p}async loadSource(o){if(o.kind==="tone")return Hr({frequencyHz:o.frequencyHz,durationMs:o.durationMs??ma});let d=this.deps.maxSourceBytes??pa,c=await this.deps.readFile(o.path,d);if(c.byteLength>d)throw Nt(o.path,d);return Fr(c)}}var ha="audio-loopback-ready:",di="audio-loopback-error:",ai=5000;function wa(o){let d=o.slice(di.length).trim(),c=d.indexOf(" ");return c<0?{code:d,message:""}:{code:d.slice(0,c),message:d.slice(c+1)}}function ci(o,d,c){let p={inject:["no_loopback_input","audio_injection_unsupported"],capture:["no_loopback_output","audio_capture_unsupported"]},[m,f]=p[o];if(d?.code===m)return new O(f,d.message);let w=d?`${d.code}: ${d.message}`:`the helper exited with code ${c??"none"} and reported no error`;return new O("audio_loopback_failed",`The host audio loopback ${o==="inject"?"playback":"capture"} failed (${w}).`)}async function li(o){let d=o.launch(),c=null,p,m=()=>{},f=new Promise((C)=>{m=C}),w="";d.stderr.on("data",(C)=>{w+=C.toString();let T=w.split(`
|
|
5
|
-
`);w=T.pop()??"";for(let D of T)if(D.startsWith(ha))m();else if(D.startsWith(di))p=wa(D);else if(D.trim())e.debug(`audio-loopback-helper: ${D}`)});let{onStdout:R}=o,y=!1;if(R)d.stdout.on("data",(C)=>{let T=R(C);if(T instanceof Promise){y=!0,d.stdout.pause();let D=()=>{y=!1,d.stdout.resume()};T.then(D,D)}});d.stdin.on("error",(C)=>{e.debug(`audio-loopback-helper stdin closed: ${C.message}`)});let P=new Promise((C)=>{d.once("exit",(T)=>{c=T,C(T)}),d.once("error",(T)=>{p??={code:"spawn_failed",message:T.message},C(null)})}),A=new Promise((C)=>{d.stdout.once("end",C),d.stdout.once("close",C),d.stdout.once("error",()=>C())}),x={process:d,exited:P,outputEnded:A,sinkBusy:()=>y,failure:()=>ci(o.operation,p,c)};return await ya(x,f,o,()=>p),x}async function ya(o,d,c,p){let m=await new Promise((f)=>{let w=c.timer.setTimeout(()=>f("timeout"),ai),R=(y)=>{c.timer.clearTimeout(w),f(y)};d.then(()=>R("ready")),o.exited.then((y)=>R({code:y}))});if(m==="ready")return;if(m==="timeout")throw o.process.kill("SIGKILL"),new O("audio_loopback_failed",`The audio loopback helper did not open its device within ${ai} ms.`);throw ci(c.operation,p(),m.code)}var ba=8000,ui=48000,pi=48000,va=100,Ra=5000,Sa=2000,mi=1000;function Pa(o,d){return new O(o,`iOS Simulator audio needs the released audio-loopback helper on a macOS host. Check release asset availability, or set ${d} to the path of an audio-loopback-helper executable.`)}function ot(o){return o<ba||o>ui?ui:o}function Aa(o,d){let c=[];for(let p=0;p<o.length;p+=d){let m=o.subarray(p,p+d);c.push(new Uint8Array(m.buffer,m.byteOffset,m.byteLength))}return c}function Ea(o,d,c){return new Promise((p)=>{if(c.then(p),o.write(d))p();else o.once("drain",()=>p())})}class Gt{deps;envName;timer;live=new Set;constructor(o,d){this.deps=o;this.envName=d;this.timer=o.timer??i}async injectAudio(o,d={}){let c=Ye(o),p=ot(c.sampleRate)===c.sampleRate?c:Qe(c,ot(c.sampleRate)),m=await this.start("inject",["play","--sample-rate",String(p.sampleRate)]),f,w=!1,R=()=>{},y=new Promise((V)=>{R=V}),P=()=>{w=!0,R()},A=(V)=>{if(f===void 0)f=V,P(),m.process.kill("SIGTERM")},x=d.maxDurationMs===void 0?void 0:this.timer.setTimeout(()=>A("max_duration"),d.maxDurationMs),C=0,T,D=this.feed(m,p,d,{ended:y,isEnded:()=>w,progress:{started:()=>{T??=this.timer.monotonicNow?.()??this.timer.now()},queued:(V)=>{C+=V}}}),N=(async()=>{let V=await m.exited;if(P(),x)this.timer.clearTimeout(x);await D;let j=this.framesPlayed(T,C,p.sampleRate);if(f)return{framesQueued:C,framesPlayed:j,reason:f};if(V===0)return{framesQueued:C,framesPlayed:j,reason:"completed"};throw m.failure()})();return{durationMs:Oe(p),sampleRate:p.sampleRate,done:N,stop:async()=>(A("stopped"),N)}}framesPlayed(o,d,c){if(o===void 0)return 0;let p=this.timer.monotonicNow?.()??this.timer.now(),m=Math.max(0,p-o),f=Math.floor(m*c/1000);return Math.min(d,f)}async captureAudio(o){let d=ot(o.sampleRate??pi),c=[],p=await this.start("capture",["capture","--duration-ms",String(o.durationMs),"--sample-rate",String(d)],(A)=>{c.push(A)}),m=!1,f=this.timer.setTimeout(()=>{m=!0,p.process.kill("SIGTERM")},o.durationMs+Ra),w=await p.exited;if(this.timer.clearTimeout(f),!m&&w!==0)throw p.failure();await this.untilOutputEnded(p);let R=Buffer.concat(c),y=new Int16Array(R.buffer.slice(R.byteOffset,R.byteOffset+(R.byteLength&-2))),P=Math.floor(o.durationMs*d/1000);return{pcm:{sampleRate:d,channels:1,samples:y},timedOut:m||y.length<P}}async streamCapture(o,d={}){let c=ot(d.sampleRate??pi),p=await this.start("capture",["capture","--until-stopped","--sample-rate",String(c)],o),m=async()=>{p.process.stdin.end();let w=this.idleDeadline(p,Sa,()=>p.process.kill("SIGTERM")),R=await p.exited;w();let y=await this.untilOutputEnded(p);if(R!==0)throw p.failure();if(!y)throw new O("audio_loopback_failed",`The audio-loopback helper's output did not finish within ${mi} ms of its exit, so the end of the capture may be missing.`)},f;return{sampleRate:c,stop:()=>(f??=m(),f)}}untilOutputEnded(o){return new Promise((d)=>{let c=this.idleDeadline(o,mi,()=>d(!1));o.outputEnded.then(()=>{c(),d(!0)})})}idleDeadline(o,d,c){let p,m=()=>{p=this.timer.setTimeout(()=>o.sinkBusy()?m():c(),d)};return m(),()=>this.timer.clearTimeout(p)}async close(){for(let o of this.live)o.kill("SIGTERM");this.live.clear()}async start(o,d,c){let p=await this.deps.helperPath();if(!p)throw Pa(o==="inject"?"audio_injection_unsupported":"audio_capture_unsupported",this.envName);let m=await li({launch:()=>this.deps.launchHelper(p,d),operation:o,timer:this.timer,onStdout:c});return this.live.add(m.process),m.exited.then(()=>this.live.delete(m.process)),m}async feed(o,d,c,p){let{ended:m,isEnded:f,progress:w}=p,R=c.startDelayMs;if(R)await new Promise((x)=>{let C=this.timer.setTimeout(x,R);m.then(()=>{this.timer.clearTimeout(C),x()})});let y=Math.max(1,Math.round(d.sampleRate*va/1000)),P=Aa(d.samples,y),A=o.process.stdin;if(P.length===0){A.end();return}do for(let x of P){if(f())return;w.started(),await Ea(A,x,m),w.queued(x.byteLength/2)}while(c.loop&&!f());if(!f())A.end()}}import{existsSync as Da}from"fs";var bi=Lt(fd());import*as z from"fs/promises";import Ve from"path";var gi="audio-loopback-helper",hi=448,wi=384,yi=448,Ca=30000,xa=w5,at="audio-loopback-helper",ka="audio-loopback-helper.json";class jt{downloader;checksumCalculator;cacheDir;usesDefaultCacheDir;timer;cache;env;expectedChecksumOverride;releaseUrlOverride;downloadTimeoutMs;platform;inFlight=null;constructor(o={}){this.downloader=o.downloader??new fi,this.checksumCalculator=o.checksumCalculator??new tn,this.cacheDir=o.cacheDir??Xe(gi),this.usesDefaultCacheDir=o.cacheDir===void 0,this.timer=o.timer??i,this.cache=new Qi({downloader:this.downloader,checksumCalculator:this.checksumCalculator,timer:this.timer}),this.env=o.env??process.env,this.expectedChecksumOverride=o.expectedChecksum,this.releaseUrlOverride=o.releaseUrl,this.downloadTimeoutMs=o.downloadTimeoutMs??Ca,this.platform=o.platform??process.platform}async ensure(){if(this.platform!=="darwin")return;if(this.inFlight)return this.inFlight;return this.inFlight=this.doEnsure().catch((o)=>{throw u(o,"Unable to resolve the released audio-loopback helper")}).finally(()=>{this.inFlight=null}),this.inFlight}async doEnsure(){let o=this.expectedChecksumOverride??k5(this.env);if(o.length===0)return e.info("[AUDIO_LOOPBACK_HELPER] Expected checksum unknown for the pinned version; no release helper can be trusted."),null;let d=await this.tryCache(o);if(d)return e.info("[AUDIO_LOOPBACK_HELPER] Reusing verified release helper",{path:d}),d;return this.download(o)}get helperPath(){return Ve.join(this.cacheDir,at)}get metadataPath(){return Ve.join(this.cacheDir,ka)}async tryCache(o){return await this.cache.isCached({label:"[AUDIO_LOOPBACK_HELPER]",subject:"helper",expectedSha256:o,metadataPath:this.metadataPath,parseMetadata:(c)=>Ta(c)?c:null,verifyArtifact:(c)=>this.isHelperExecutable(c.size)})?this.helperPath:null}async isHelperExecutable(o){try{let d=await z.stat(this.helperPath);return!(!d.isFile()||d.size!==o||process.platform!=="win32"&&(d.mode&73)===0)}catch(d){if(d instanceof Error&&"code"in d&&d.code==="ENOENT")e.debug("[AUDIO_LOOPBACK_HELPER] No cached helper executable");else e.warn("[AUDIO_LOOPBACK_HELPER] Unable to inspect cached helper",d);return!1}}async ensureSecureCacheDir(){if(this.usesDefaultCacheDir)return si(gi);return await z.mkdir(this.cacheDir,{recursive:!0,mode:hi}),await z.chmod(this.cacheDir,hi),this.cacheDir}async download(o){let d=await this.ensureSecureCacheDir(),c=Ve.join(d,`${xa}.download`),p=Ve.join(d,`${at}.download`);return await this.cache.fetch({label:"[AUDIO_LOOPBACK_HELPER]",expectedSha256:o,url:this.releaseUrlOverride??Wee(this.env),archivePath:c,metadataPath:this.metadataPath,metadataMode:wi,downloadTimeoutMs:this.downloadTimeoutMs,afterDownload:(m)=>z.chmod(m,wi),mismatchError:(m,f)=>new t(`audio-loopback-helper checksum verification failed. Expected: ${m}, Got: ${f}. The downloaded release asset is corrupted or tampered.`),timeoutError:()=>new t(`Timed out downloading audio-loopback-helper after ${this.downloadTimeoutMs}ms. Check GitHub Release asset availability or set AUTOMOBILE_IOS_AUDIO_LOOPBACK_HELPER for local development.`),publish:async(m,f)=>{await z.writeFile(p,Ia(m),{mode:yi}),await z.chmod(p,yi);let{size:w}=await z.stat(p);return await z.rename(p,this.helperPath),e.info("[AUDIO_LOOPBACK_HELPER] Downloaded and verified release helper",{path:this.helperPath,sha256:f}),{version:Ce(this.env),sha256:f??o,size:w,downloadedAt:this.timer.now()}},discard:()=>z.rm(p,{force:!0})}),this.helperPath}}function Ta(o){return typeof o==="object"&&o!==null&&"sha256"in o&&typeof o.sha256==="string"&&"size"in o&&typeof o.size==="number"}function Ia(o){let d;try{d=new bi.default(o)}catch(p){throw new t(`audio-loopback-helper release asset is not a valid zip archive: ${r(p)}`)}let c=d.getEntries().filter((p)=>!p.isDirectory&&Ve.posix.basename(p.entryName)===at);if(c.length!==1)throw new t(`audio-loopback-helper release asset must contain exactly one ${at}.`);try{return c[0].getData()}catch(p){if(p instanceof t)throw p;throw new t(`Unable to extract audio-loopback-helper release asset: ${r(p)}`)}}var vi;function Ma(){return vi??=new jt,vi}async function Ri(o=process.env,d={}){let c=E(g.IOS_AUDIO_LOOPBACK_HELPER,o);if(c!==void 0)return c&&(d.exists??Da)(c)?c:void 0;if((d.platform??process.platform)!=="darwin")return;try{return await(d.provider??Ma()).ensure()??void 0}catch(p){e.warn("Unable to resolve the released audio-loopback helper",p);return}}function Si(o,d){return new ne().spawn(o,d,{stdio:["pipe","pipe","pipe"]})}var Oa=65536;function Ei(o){return new t(`Audio file ${o} is not a regular file.`)}async function Va(o,d){if(!(await _a(o)).isFile())throw Ei(o);let c=await Fa(o,Pi.O_RDONLY|(Pi.O_NONBLOCK??0));try{if(!(await c.stat()).isFile())throw Ei(o);let p=[],m=0;for(;;){let f=new Uint8Array(Oa),{bytesRead:w}=await c.read(f,0,f.byteLength,null);if(w===0)break;if(m+=w,m>d)throw Nt(o,d);p.push(f.subarray(0,w))}return Buffer.concat(p,m)}finally{await c.close()}}function Ha(){let o=new ni,d=new rB(o);return new Ut({discovery:d,outputTail:ez,guestCapture:new Bt((c)=>v.create({deviceId:c,platform:"android",name:c}),d,L,{resolveSetupUser:async(c)=>{let p=v.create({deviceId:c,name:c,platform:"android"}),m=await gn.read(p,c);return Aw(p,{formFactor:yL(m)?"automotive":void 0})}}),createSession:(c)=>new Dt(new Ot(c.address),Qr(c.auth,o)),createHostLoopbackSession:()=>new Gt({helperPath:()=>Ri(),launchHelper:Si},g.IOS_AUDIO_LOOPBACK_HELPER.name),readFile:Va,ids:L})}var pf=Ha();function $a(o={}){if(o.explicitPath)return o.explicitPath;let d=o.env??process.env;for(let c of o.environmentKeys??[g.FFMPEG.name]){let p=d[c];if(p)return p}return"ffmpeg"}var Ba=new ne,La=(o,d,c)=>Ba.spawn(o,d,c);class pe{binaryPath;spawnProcess;timer;constructor(o={}){this.binaryPath=$a({explicitPath:o.binaryPath??o.explicitPath,environmentKeys:o.environmentKeys,env:o.env}),this.spawnProcess=o.spawn??La,this.timer=o.timer??i}start(o){let d=this.spawnProcess(this.binaryPath,o.args,{stdio:o.stdio??["ignore","pipe","pipe"]}),c=Jc(d);return c.exitPromise.catch(()=>{return}),{process:d,tracker:c}}async run(o){let d=this.start(o),c=[];d.process.stdout?.on("data",(m)=>{c.push(m.toString())});let p=this.abortOnSignal(d.process,o.signal);try{await Hn(d.process,d.tracker.exitPromise,{timeoutMs:o.timeoutMs,forceKillTimeoutMs:o.forceKillTimeoutMs,timer:this.timer,signal:null})}catch(m){throw this.commandError(o,d.tracker,m)}finally{p()}if(d.tracker.exitState.exitCode!==0||d.tracker.exitState.signal)throw this.commandError(o,d.tracker);return{stdout:c.join(""),stderr:d.tracker.stderr.join(""),exitCode:d.tracker.exitState.exitCode,signal:d.tracker.exitState.signal}}async probe(o={}){let d=o.timeoutMs===void 0?void 0:this.timer.now()+o.timeoutMs,c=async(y,P)=>await this.run({args:y,context:P,timeoutMs:d===void 0?void 0:Math.max(0,d-this.timer.now()),forceKillTimeoutMs:d===void 0?void 0:0,signal:o.signal}),p=await c(["-version"],"FFmpeg version probe"),m=/ffmpeg version (\S+)/.exec(p.stdout)?.[1];if(!m)throw new t("FFmpeg version probe returned invalid version output.");let w=(await c(["-hide_banner","-encoders"],"FFmpeg encoder probe")).stdout.split(`
|
|
6
|
-
`).filter((y)=>y.trim().startsWith("V")).map((y)=>y.trim().split(/\s+/)[1]).filter((y)=>Boolean(y)),R=(o.requiredEncoders??[]).filter((y)=>!w.includes(y));if(R.length>0)throw new t(`FFmpeg is missing required encoder(s): ${R.join(", ")}.`);return{version:m,encoders:w}}pipe(o){if(!o.source||!o.destination)throw new t(`Cannot pipe ${o.context}: source or destination stream is unavailable.`);let d=!1,c=(p)=>{if(d)return;d=!0,e.warn(`[FfmpegClient] ${o.context} pipe failed: ${p.message}; stopping both processes.`);for(let m of o.processes)m.kill("SIGKILL")};o.source.on("error",c),o.destination.on("error",c),o.source.pipe(o.destination)}abortOnSignal(o,d){if(!d)return()=>{return};let c=()=>{if(o.exitCode===null&&!o.killed)o.kill("SIGKILL")};if(d.aborted)return c(),()=>{return};return d.addEventListener("abort",c,{once:!0}),()=>d.removeEventListener("abort",c)}commandError(o,d,c){let p=[`FFmpeg ${o.context} failed.`,`command: ${this.binaryPath} ${o.args.join(" ")}`,`exitCode: ${d.exitState.exitCode??"null"}`,`signal: ${d.exitState.signal??"null"}`,`stderr: ${d.stderr.join("").trim()||"(empty)"}`,c instanceof Error?`cause: ${c.message}`:void 0].filter((m)=>Boolean(m));return new t(p.join(`
|
|
7
|
-
`))}}function Na(o){return`${o}.audio.pcm`}function pK(o,d,c){if(c&&o==="android"&&(d??0)>Ai)throw new t(`audio is supported for Android recordings up to ${Ai} s; set maxDuration to that or less, or record without audio.`)}var Ua="The recording has no audio track: an earlier stop failed and its audio was discarded.";class zt{inner;deps;tracks=new Map;lostTracks=new Set;constructor(o,d){this.inner=o;this.deps=d;if(o.describeCaptureTeardown)this.describeCaptureTeardown=o.describeCaptureTeardown.bind(o);if(o.forceStopOrphanedCapture)this.forceStopOrphanedCapture=o.forceStopOrphanedCapture.bind(o)}describeCaptureTeardown;forceStopOrphanedCapture;async start(o){if(!o.audio)return this.inner.start(o);let d=o.device?.deviceId;if(!d)throw new t("A recording with audio needs a target device.");pK(o.device?.platform,o.maxDurationSeconds,o.audio),await this.deps.muxer.ensureAvailable();let c=Na(o.outputPath),p=this.deps.openPcmFile(c),m=Ga(p),f;try{f=await this.deps.source.startStream(d,m.sink)}catch(A){throw await this.discardFile(p,c),A}let w=this.deps.now(),R,y=this.deps.now();try{R=await this.inner.start(o)}catch(A){throw await this.discard({stream:f,abandon:m.abandon,file:p,pcmPath:c,leadMs:0}),A}let P=Math.max(0,y-w);return this.tracks.set(R.recordingId,{stream:f,abandon:m.abandon,file:p,pcmPath:c,leadMs:P}),{...R,inProgressSidecarPaths:[...R.inProgressSidecarPaths??[],c]}}async stop(o){let d=this.tracks.get(o.recordingId);if(!d){if(!this.lostTracks.has(o.recordingId))return this.inner.stop(o);let c=await this.inner.stop(o);return this.lostTracks.delete(o.recordingId),Ci(c,Ua)}try{return await this.stopWithTrack(o,d)}finally{this.tracks.delete(o.recordingId)}}async forceStop(o,d){this.lostTracks.delete(o.recordingId);let c=this.tracks.get(o.recordingId);if(c)this.tracks.delete(o.recordingId),this.discardOnce(c);await this.inner.forceStop?.(o,d)}async stopWithTrack(o,d){let c;try{c=await this.inner.stop(o)}catch(m){if(await this.discardOnce(d),this.tracks.has(o.recordingId))this.lostTracks.add(o.recordingId);throw m}let p=d.discarded?"The recording has no audio track: it was force-stopped while stopping.":await this.addTrack(d,c.outputPath);return Ci(c,p)}async addTrack(o,d){let c;try{await o.stream.stop(),c=o.file.close();let p=await c;await this.deps.muxer.mux({videoPath:d,pcmPath:o.pcmPath,pcmBytes:p,sampleRate:o.stream.sampleRate,leadMs:o.leadMs});return}catch(p){return e.warn(`Recording audio track for ${d} failed: ${r(p)}`),`The recording has no audio track: ${r(p)}`}finally{if(c)await this.removeQuietly(o.pcmPath);else await this.discardFile(o.file,o.pcmPath)}}discardOnce(o){return o.discarded??=this.discard(o),o.discarded}async discard(o){o.abandon(),await o.stream.stop().catch((d)=>{e.debug(`audio track stop during discard: ${r(d)}`)}),await this.discardFile(o.file,o.pcmPath)}async discardFile(o,d){await o.close().catch((c)=>{e.debug(`audio track file close during discard: ${r(c)}`)}),await this.removeQuietly(d)}async removeQuietly(o){await this.deps.removeFile(o).catch((d)=>{e.warn(`Failed to remove temporary audio ${o}: ${r(d)}`)})}}function Ci(o,d){let c=[...o.warnings??[],...d?[d]:[]];return{...o,...d?{}:{sizeBytes:void 0},hasAudioTrack:d===void 0,warnings:c.length>0?c:void 0}}function Ga(o){let d=!1,c;return{sink:(p)=>{if(d)return;let m=o.write(p);if(!(m instanceof Promise))return;return new Promise((f)=>{let w=()=>{if(c===w)c=void 0;f()};c=w,m.then(w,w)})},abandon:()=>{d=!0,c?.()}}}import{platform as os}from"os";import ns from"path";function xi(o,d){if(o.warning=d?.warning??o.warning,o.warning?.includes("rejected --display-id"))o.recordedPanel=void 0}function ja(o,d){return o!==void 0&&o!==null&&o!==0&&/usage|unknown (?:option|argument)|unrecognized (?:option|argument)/i.test(d.join(""))}async function He(o,d,c=20){let p=Error("screenrecord display flag probe timed out");try{await l(o.exitPromise,{timer:d,timeoutMs:c,label:"screenrecord display flag probe",timeoutError:()=>p})}catch(m){if(m!==p)throw u(m,"Android screenrecord startup failed");e.debug("[VideoCapture] screenrecord display flag probe found a live capture")}return ja(o.exitState.exitCode,o.stderr)}function za(o,d){if(d!==void 0&&d!=="active")throw new t("Recording a selected Android panel requires API 34 or newer.");let c=sn(o.displays,"active",{}),p={key:c.key,role:c.role};return{panel:p,activePanel:p,warning:"Android API below 34: recording the default display without a pinned panel."}}function Wa(o,d){if(!o.displays?.panels.length){if(d!==void 0&&d!=="active")sn(o.displays,d,{});return}let c=sn(o.displays,d,{}),p={key:c.key,role:c.role};return{panel:p,activePanel:p}}async function st(o,d,{request:c,signal:p,timer:m=i}={}){if((o.displays?.panels.length??0)<2)return Wa(o,c);if(o.apiLevel!==void 0&&o.apiLevel<34)return za(o,c);let f=await new fr(m).resolve(o,d,p,!0),w=xe.observedPanel(o.deviceId),R=w&&o.displays?.panels.some((P)=>P.key===w.key)?w:f.display,y=sn(o.displays,c,{focusedPanelKey:R.key,activePanelKey:f.display.key,posture:f.display.posture});if(!/^(0|[1-9]\d*)$/.test(y.key))throw new t(`Display panel "${y.key}" has no physical Android display ID.`);return{panel:{key:y.key,role:y.role},physicalId:y.key,activePanel:{key:R.key,role:R.role}}}var Ti={key:"unknown",role:"unknown"};function Ii(o,d){let c=(o.displays?.panels??[]).filter(gd);if(c.length<2)return;let p=c.find((f)=>f.key===d?.key),m=p?{key:p.key,role:p.role}:Ti;return{panel:m,activePanel:m}}function Di(o,d,c){if(!d)return;if(!c)return Ti;let p=o?.displays?.panels.find((m)=>m.key===c);return{key:c,role:p?.role??"unknown"}}function Mi(o,d,c){if(o.platform!=="ios")return d;let p=c??d.panel;return{...d,panel:p,activePanel:p}}function Fi(o,d,c,p){return o.platform==="ios"&&p!==void 0&&p.key!=="unknown"&&d.key==="unknown"&&c.length===0}function ki(o){return o.key==="unknown"?"the starting panel":`panel "${o.key}" (${o.role})`}function qa(o,d){return d.map((c)=>`iOS recording kept capturing ${ki(o)} after the active display changed to ${ki(c.to)} at ${c.atMs}ms; frames after that point may show an inactive panel.`)}function _i(o){return[...o.warning?[o.warning]:[],...o.device.platform==="ios"?qa(o.recordedPanel,o.transitions):[]]}async function Be(o,d,c,{callerSignal:p,timeoutMessage:m}){p?.throwIfAborted();let f=new AbortController,w=p?AbortSignal.any([p,f.signal]):f.signal,R=Error(m),y=Math.max(0,d-c.now()),P=o(w),A=c.setTimeout(()=>f.abort(R),y);try{return await l(P,{timer:c,signal:w,label:"FFmpeg operation"})}finally{c.clearTimeout(A)}}function ee(o,d){if(o?.aborted)throw new t(`${d} recording start was cancelled during shutdown.`)}class Kt{ffmpegClient;platformProvider;timer;startTimeoutMs;hwAccelCache=new Map;ffmpegProbeResult;constructor(o,d,c,p){this.ffmpegClient=o;this.platformProvider=d;this.timer=c;this.startTimeoutMs=p}async detectHardwareAccel(){let o=this.platformProvider(),d=o;if(this.hwAccelCache.has(d))return this.hwAccelCache.get(d);let c;if(o==="darwin")c=await this.detectVideoToolbox();else if(o==="linux")c=await this.detectLinuxHwAccel();else c={encoder:"libx264",available:!1,description:`Unsupported platform: ${o}`};return this.hwAccelCache.set(d,c),c}async detectVideoToolbox(){try{if((await this.listEncoders()).some((c)=>c.includes("h264_videotoolbox")))return{encoder:"h264_videotoolbox",available:!0,description:"macOS VideoToolbox (hardware acceleration)"};return{encoder:"libx264",available:!1,description:"VideoToolbox not available"}}catch(o){return e.warn(`[FfmpegVideo] Failed to detect VideoToolbox: ${o}`),{encoder:"libx264",available:!1,description:"VideoToolbox detection failed"}}}async detectLinuxHwAccel(){try{let o=await this.listEncoders();if(o.some((p)=>p.includes("h264_nvenc")))return{encoder:"h264_nvenc",available:!0,description:"NVIDIA NVENC (hardware acceleration)"};if(o.some((p)=>p.includes("h264_vaapi")))return{encoder:"h264_vaapi",available:!0,description:"VAAPI (hardware acceleration)"};return{encoder:"libx264",available:!1,description:"No hardware acceleration available (VAAPI/NVENC not found)"}}catch(o){return e.warn(`[FfmpegVideo] Failed to detect Linux HW accel: ${o}`),{encoder:"libx264",available:!1,description:"Hardware acceleration detection failed"}}}async listEncoders(){return(await this.probeFfmpeg()).encoders}async ensureFfmpegAvailable(o,d){try{await this.checkFfmpegVersion(o,d)}catch(c){throw ee(d,"iOS"),new t(`FFmpeg is not available. Please install FFmpeg to use video recording.
|
|
8
|
-
macOS: brew install ffmpeg
|
|
9
|
-
Linux: apt-get install ffmpeg or yum install ffmpeg
|
|
10
|
-
Error: ${c}`)}}async checkFfmpegVersion(o,d){let{version:c}=await this.probeFfmpeg(o,d);e.debug(`[FfmpegVideo] Found FFmpeg ${c}`)}async probeFfmpeg(o,d){if(this.ffmpegProbeResult)return this.ffmpegProbeResult;let p=await(o===void 0?this.ffmpegClient.probe():Be(async(m)=>await this.ffmpegClient.probe({timeoutMs:Math.max(0,o-this.timer.now()),signal:m}),o,this.timer,{callerSignal:d,timeoutMessage:`Timed out checking FFmpeg availability within ${this.startTimeoutMs()}ms`}));return this.ffmpegProbeResult=p,p}}class Le extends t{}function Oi(o){return o!==void 0&&o!==0}function Vi(o){return Oi(o.exitCode)||o.signal!==void 0&&o.signal!==null}function ve(o,d,c,{tracker:p,outputPath:m}){return[d,m?`output: ${m}`:void 0,`command: ${o} ${c.join(" ")}`,`exitCode: ${p.exitState.exitCode??"null"}`,`signal: ${p.exitState.signal??"null"}`,`stderr:
|
|
11
|
-
${p.stderr.join("").trim()||"(empty)"}`].filter((w)=>Boolean(w)).join(`
|
|
12
|
-
`)}function Ne(o,d,c,{tracker:p,outputPath:m}){return[o,m?`output: ${m}`:void 0,`command: ${d} ${c.join(" ")}`,`exitCode: ${p.exitState.exitCode??"null"}`,`signal: ${p.exitState.signal??"null"}`,`stderr:
|
|
13
|
-
${p.stderr.join("").trim()||"(empty)"}`].filter((w)=>Boolean(w)).join(`
|
|
14
|
-
`)}function Wt(o,d){if(Oi(d.exitState.exitCode))e.warn(`[FfmpegVideo] ${o} exited with code ${d.exitState.exitCode}: ${d.stderr.join("")}`);if(d.stderr.length>0)e.info(`[FfmpegVideo] ${o} stderr: ${d.stderr.join("")}`)}async function Hi(o,d,c,{recordingFileProbe:p,binaryPath:m}){let f=await p.size(o);if(f===null)throw new t(ve(m,"FFmpeg output file missing",d,{tracker:c,outputPath:o}));if(!f)throw new t(ve(m,"FFmpeg output file is empty",d,{tracker:c,outputPath:o}))}var $i=60000,Ja=500,qt=1800000,Bi=600000;function Li(o){return!o.resolution}function Ni(o,d,c=qt){if(Li(o))return $i;if(d===void 0||!Number.isFinite(d))return c;let p=o.maxDurationSeconds&&o.maxDurationSeconds>0?Math.min(d,o.maxDurationSeconds):d;return Math.min(c,Math.max($i,Math.ceil(Math.max(0,p)*Ja)))}var Xa=5000;function Ui(o,d){if(d===void 0)return o;let c=d-Xa;return c<=0?void 0:Math.min(o,c)}function dt(o,d,c){let p=[];if(c.type==="pipe")p.push("-f","mp4","-i","pipe:0");else if(p.push("-i",c.path),Li(o)){if(p.push("-c","copy"),p.push("-movflags","+faststart"),o.maxDurationSeconds&&o.maxDurationSeconds>0)p.push("-t",String(o.maxDurationSeconds));return p.push("-y"),p.push(o.outputPath),p}if(p.push("-r",String(o.fps)),o.resolution)p.push("-vf",`scale=${o.resolution.width}:${o.resolution.height}`);if(d.available)p.push("-c:v",d.encoder),e.info(`[FfmpegVideo] Using hardware acceleration: ${d.description}`);else p.push("-c:v","libx264"),p.push("-preset","ultrafast"),e.warn("[FfmpegVideo] Hardware acceleration unavailable, falling back to software encoding");if(p.push("-b:v",`${o.targetBitrateKbps}k`),p.push("-maxrate",`${o.targetBitrateKbps}k`),p.push("-bufsize",`${o.targetBitrateKbps*2}k`),p.push("-profile:v","baseline"),p.push("-level","3.0"),p.push("-pix_fmt","yuv420p"),p.push("-movflags","+faststart"),o.maxDurationSeconds&&o.maxDurationSeconds>0)p.push("-t",String(o.maxDurationSeconds));return p.push("-y"),p.push(o.outputPath),p}import{promises as Gi}from"fs";var Ya=15000,Qa=100,Za=1000,Jt={async size(o){try{return(await Gi.stat(o)).size}catch(d){if(d.code!=="ENOENT")throw u(d,`Failed to stat recording ${o}`);return e.debug(`src/features/video/FfmpegVideoProcessingBackend.ts recording file stat failed: ${d}`,d),null}}},ji={async remove(o){await Gi.rm(o,{force:!0})}};async function zi(o,d={}){let c=d.probe??Jt,p=d.timer??i,m=d.timeoutMs??Ya,f=xo(d.backoff??te({initialDelayMs:Qa,maxDelayMs:Za})),w=p.now()+m,R=0,y=!1,P=null;for(;;){R++;let A=await c.size(o);if(A!==null){if(y=!0,A>0&&A===P)return A}if(P=A,p.now()>=w){let x=es(y,P);throw Error(`iOS recording file not ready at ${o} after ${m}ms (${R} probes): ${x}`)}await p.sleep(f.delayForAttempt(R))}}function es(o,d){return!o?"never appeared":d===null?"disappeared after appearing":d===0?"stayed empty (0 bytes)":`stopped at ${d} bytes but never stabilized`}class Xt{ffmpegClient;timer;recordingFileProbe;captureFileRemover;codecProbe;detectHardwareAccel;constructor(o){this.ffmpegClient=o.ffmpegClient,this.timer=o.timer,this.recordingFileProbe=o.recordingFileProbe,this.captureFileRemover=o.captureFileRemover,this.codecProbe=o.codecProbe,this.detectHardwareAccel=o.detectHardwareAccel}async postProcessRecording(o){let d=o.capturePath;if(!d)throw new t("Missing iOS capture path for FFmpeg processing.");try{await zi(d,{timer:this.timer,probe:this.recordingFileProbe})}catch(c){let p=r(c);throw new t(Ne(`iOS recording file missing at ${d}: ${p}`,"xcrun simctl",o.captureArgs??["io",o.config.device?.deviceId??"(unknown-device)","recordVideo",d],{tracker:o.captureTracker,outputPath:d}))}try{return await this.runFfmpegPostProcess(o,d),{kind:"processed"}}catch(c){if(c instanceof rp)throw c;return this.keepRawCaptureAfterPostProcessFailure(o,d,c)}}async keepRawCaptureAfterPostProcessFailure(o,d,c){if(await this.removePartialPostProcessOutput(o.config.outputPath),!await this.isRawCaptureUsable(o,d))throw e.warn(`[FfmpegVideo] iOS post-processing failed and the raw capture is not playable: ${r(c)}`,c),c;e.warn(`[FfmpegVideo] iOS post-processing did not finish; keeping the unprocessed capture: ${r(c)}`,c);let p=r(c).split(`
|
|
15
|
-
`)[0];return{kind:"kept-raw",warning:`iOS ${c instanceof Le?"post-processing ran out of time":"post-processing failed"} (${p}); returning the unprocessed simulator capture, which has not been remuxed or scaled to the requested resolution.`}}async removePartialPostProcessOutput(o){try{await this.captureFileRemover.remove(o)}catch(d){e.warn(`[FfmpegVideo] Failed to remove the partial post-processed output: ${r(d)}`,d)}}async isRawCaptureUsable(o,d){if(o.captureTracker.exitState.signal==="SIGKILL")return!1;try{return await this.codecProbe.codec(d)!==void 0}catch(c){return e.warn(`[FfmpegVideo] Could not probe the raw capture ${d}: ${r(c)}`,c),!1}}async runFfmpegPostProcess(o,d){let c=this.requestBoundedPostProcessBudgetMs(o.config),p=await this.detectHardwareAccel(),m=dt(o.config,p,{type:"file",path:d});e.info(`[FfmpegVideo] Starting ffmpeg post-process: ${this.ffmpegClient.binaryPath} ${m.join(" ")}`);let{process:f}=this.ffmpegClient.start({args:m,context:"iOS recording post-processing",stdio:["ignore","pipe","pipe"]});try{await NT(f)}catch(R){throw u(R,"Failed to start FFmpeg post-processing")}let w=Jc(f);if(o.ffmpegTracker=w,await Hn(f,w.exitPromise,{timeoutMs:c,signal:null,timer:this.timer}),Vi(w.exitState)){let{exitCode:R,signal:y}=w.exitState;if(y==="SIGKILL")throw new Le(ve(this.ffmpegClient.binaryPath,`FFmpeg post-processing timed out after ${c}ms`,m,{tracker:w}));throw new t(ve(this.ffmpegClient.binaryPath,`FFmpeg post-processing failed (exit ${R??`signal ${y}`})`,m,{tracker:w}))}await Hi(o.config.outputPath,m,w,{recordingFileProbe:this.recordingFileProbe,binaryPath:this.ffmpegClient.binaryPath})}requestBoundedPostProcessBudgetMs(o){let d=Zi(),c=Ni(o,this.recordedSeconds(o),d?qt:Bi),p=d?.getDeadlineMs?.(),m=Ui(c,p===void 0?void 0:p-this.timer.now());if(m===void 0)throw new Le("the stop request has no time left for post-processing");return m}recordedSeconds(o){let d=Date.parse(o.startedAt);return Number.isNaN(d)?void 0:(this.timer.now()-d)/1000}}var Ki=async(o,d)=>{let c=_.getInstance(o);if(!await c.ensureConnected())return null;let m=await c.requestHierarchySyncWithoutObservationStreamPush(void 0,!1,void 0,d)?c.getScreenScaleMetadata():null;return m?{width:m.pixelWidth,height:m.pixelHeight}:null};var Wi=(o)=>new F(o);var qi=["Recording started"];function Ji(o){return Array.isArray(o)?o:[o]}function Yt(o,d){let c=o.stderr.join("");return Ji(d).some((p)=>c.includes(p))}async function Xi(o,d,c,p={}){let m=Ji(d),f=m.join(" or "),w=p.timer??i;if(Yt(o,m))return;if(o.exitState.endedAt!==void 0||o.process.exitCode!==null&&o.process.exitCode!==void 0||o.process.signalCode!==null&&o.process.signalCode!==void 0)throw Error(`Process exited before ${f}`);p.signal?.throwIfAborted();let R=o.process.stderr;if(!R)throw Error(`Cannot wait for ${f}: process stderr is not captured`);let y;await new Promise((P,A)=>{let x=!1,C=()=>{if(R.off("data",D),o.process.off("exit",N),o.process.off("error",V),p.signal?.removeEventListener("abort",j),y)w.clearTimeout(y)},T=(q)=>{if(x)return;x=!0,C(),q()},D=()=>{if(Yt(o,m))T(P)},N=()=>{T(()=>A(Error(`Process exited before ${f}`)))},V=(q)=>{T(()=>A(q))},j=()=>{T(()=>A(p.signal?.reason??Error("Recording start was cancelled.")))};R.on("data",D),o.process.once("exit",N),o.process.once("error",V),p.signal?.addEventListener("abort",j,{once:!0}),D(),y=w.setTimeout(()=>{if(Yt(o,m)){T(P);return}T(()=>A(Error(`Timed out waiting for ${f}`)))},c)})}async function Yi(o,d,c,p){let m=Math.max(0,d-c.now()),f=new AbortController,w=c.setTimeout(()=>f.abort(Error(p)),m);try{return await l(o,{timer:c,signal:f.signal,label:"FFmpeg operation"})}finally{if(w)c.clearTimeout(w)}}function Qt(o){if(o&&o.exitCode===null&&!o.killed)o.kill("SIGKILL")}function eo(o,d){throw ee(d,"Android"),e.error(`[FfmpegVideo] Failed to start Android recording: ${o}`),u(o,"Failed to start Android recording")}var to=15000,ro=2;var Zt={readStartToken:la,isRunning:(o)=>nt(o,{debugLog:e.debug}),signal:(o,d)=>{process.kill(o,d)}},ts=30000,rs=4000,is=1000,io=100;async function no(o,d={control:Zt,timer:i},c={mode:"user"}){let{control:p,timer:m}=d,f=o.hostPid,w=()=>{if(!p.isRunning(f))return!1;let y=p.readStartToken(f);if(y===void 0){if(!p.isRunning(f))return!1;throw new t(`Cannot prove orphan host recorder identity for pid ${f}; retry teardown when its start token can be read.`)}return y===o.hostStartToken},R=async(y)=>{for(let P=0;P<y;P+=io){if(!p.isRunning(f))return!0;await m.sleep(io)}return!p.isRunning(f)};try{if(!w())return;p.signal(f,"SIGINT");let y=c.mode==="background";if(await R(y?rs:ts))return;if(y)throw new t(`Orphan host recorder pid ${f} teardown is unconfirmed; retry after MOV finalization completes.`);if(!w())return;if(p.signal(f,"SIGKILL"),await R(is))return;if(!w())return;throw new t(`Cannot confirm orphan host recorder pid ${f} stopped; retry teardown before starting another recording.`)}catch(y){throw e.warn(`[HostRecorderTeardown] Teardown unconfirmed for pid ${f}`,y),u(y,`Failed to stop orphan host recorder pid ${f}`)}}var as=30000,ao=2000,so=500,co=3000,ss=250;function ds(o,d,c,p){return{kind:"ffmpeg",platform:"ios",captureTracker:o,capturePath:d,captureArgs:c,config:p}}class ct{adbFactory;iosRecordingStartTimeoutMs=to;iosRecordingStartMaxAttempts=ro;simctlFactory;ffmpegClient;codecProbe;timer;captureFileRemover;liveScreenPixels;recordingFileProbe;readHostStartToken;hostRecorderControl;constructor(o=v,d={}){this.adbFactory=o;this.simctlFactory=d.simctlFactory??Wi,this.ffmpegClient=d.ffmpegClient??new pe,this.timer=d.timer??i,this.liveScreenPixels=d.liveScreenPixels??Ki;let c=ct.resolveHostSeams(d);this.capabilities=new Kt(this.ffmpegClient,c.platformProvider,this.timer,()=>this.iosRecordingStartTimeoutMs),this.codecProbe=c.codecProbe,this.captureFileRemover=c.captureFileRemover,this.recordingFileProbe=c.recordingFileProbe,this.readHostStartToken=c.readHostStartToken,this.hostRecorderControl=c.hostRecorderControl}static resolveHostSeams(o){return{platformProvider:o.platformProvider??os,codecProbe:o.codecProbe??ae,captureFileRemover:o.captureFileRemover??ji,recordingFileProbe:o.recordingFileProbe??Jt,readHostStartToken:o.readHostStartToken??la,hostRecorderControl:o.hostRecorderControl??Zt}}describeCaptureTeardown(o){let d=o.backendHandle;if(d?.kind!=="ffmpeg"||d.platform!=="ios")return;if(d.captureTeardown)return d.captureTeardown;let c=d.captureTracker.process.pid,p=d.config.device?.deviceId;try{let m=c===void 0?void 0:this.readHostStartToken(c);if(!c||!m||!p){e.warn("[FfmpegVideo] Cannot persist iOS host recorder teardown identity: pid, start token or udid unreadable");return}return d.captureTeardown={kind:"ios-host-recorder",hostPid:c,hostStartToken:m,udid:p,capturePath:d.capturePath},d.captureTeardown}catch(m){e.warn("[FfmpegVideo] Cannot read iOS host recorder start token",m);return}}async forceStopOrphanedCapture(o,d,c){if(d.kind!=="ios-host-recorder")throw new t("FFmpeg orphan teardown requires an iOS host recorder identity.");await no(d,{control:this.hostRecorderControl,timer:this.timer},c)}async start(o){let d=o.device;if(!d)throw new t("Device is required to start video recording.");let c=_e(d.platform),p=c?this.timer.now()+this.iosRecordingStartTimeoutMs:void 0;if(await this.ensureFfmpegAvailable(p,c?o.abortSignal:void 0),d.platform==="android")return this.startAndroid(d,o);if(c)return this.startIos(d,o,p);throw new t(`Unsupported platform for video recording: ${d.platform}`)}async stop(o){let d=o.backendHandle;if(!d)throw Error("Missing backend handle for FFmpeg video recording.");await Hn(d.captureTracker.process,d.captureTracker.exitPromise,{timeoutMs:d.platform==="ios"?as:tp,timer:this.timer});try{let{outputPath:c,warnings:p}=await this.finalizeCaptureOutput(d,o),m=await this.recordingFileProbe.size(c);if(!m)throw new t("The finalized recording is missing or contains zero bytes.");let f=await this.codecProbe.codec(c),w=await we(this.codecProbe,c);if(c!==d.capturePath)await this.removeRawCapture(d.capturePath);if(Wt("capture",d.captureTracker),d.ffmpegTracker)Wt("ffmpeg",d.ffmpegTracker);return{recordingId:o.recordingId,outputPath:c,startedAt:o.startedAt,endedAt:d.captureTracker.exitState.endedAt??new Date().toISOString(),sizeBytes:m,codec:f,videoDurationMs:w,...p.length>0&&{warnings:p}}}catch(c){throw await this.buildFinalizationError(d,c)}}async finalizeCaptureOutput(o,d){if(o.platform==="ios"){let c=await this.postProcessRecording(o);return c.kind==="kept-raw"?{outputPath:o.capturePath??d.outputPath,warnings:[c.warning]}:{outputPath:d.outputPath,warnings:[]}}if(o.ffmpegTracker)await Hn(o.ffmpegTracker.process,o.ffmpegTracker.exitPromise,{timer:this.timer});return{outputPath:d.outputPath,warnings:[]}}postProcessRecording(o){return new Xt({ffmpegClient:this.ffmpegClient,timer:this.timer,recordingFileProbe:this.recordingFileProbe,captureFileRemover:this.captureFileRemover,codecProbe:this.codecProbe,detectHardwareAccel:()=>this.detectHardwareAccel()}).postProcessRecording(o)}async removeRawCapture(o){if(!o)return;try{await this.captureFileRemover.remove(o)}catch(d){e.warn(`[FfmpegVideo] Failed to remove raw recording: ${r(d)}`,d)}}async buildFinalizationError(o,d){let c=await this.cleanupStartingTrackers([o.ffmpegTracker].filter((m)=>m!==void 0));if(c)e.warn(`[FfmpegVideo] Failed to clean up recording encoder: ${r(c)}`,c);let p=o.capturePath;if(p)try{let m=await this.recordingFileProbe.size(p);if(m===null||m===0)await this.captureFileRemover.remove(p),p=void 0}catch(m){e.warn(`[FfmpegVideo] Could not inspect or remove raw recording; retaining ${p}: ${r(m)}`,m)}return new J(p?`Capture exited but finalization failed. Raw capture retained at ${p}. ${r(d)}`:`Capture exited but the recording produced no usable video (zero bytes / finalization failed). Start a new recording. ${r(d)}`,{cause:d,retainedCapturePath:p})}async forceStop(o){let d=o.backendHandle;if(!d)throw Error("Missing backend handle for FFmpeg video recording.");let c=[d.ffmpegTracker,d.captureTracker].filter((f)=>f!==void 0),m=(await Promise.allSettled(c.map(async(f)=>{await Hn(f.process,f.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer})}))).find((f)=>f.status==="rejected");if(m)throw m.reason}async startAndroid(o,d){let c=this.adbFactory.create(o),p=["exec-out","screenrecord"];if(d.physicalDisplayId!==void 0)p.push("--display-id",d.physicalDisplayId);p.push("-"),e.info(`[FfmpegVideo] Starting screenrecord: ${p.join(" ")}`);let m=await c.spawn(p),f=Jc(m),w;if(d.physicalDisplayId!==void 0&&o.apiLevel===void 0){if(await He(f,this.timer))w="Android screenrecord rejected --display-id; recording the default display.",e.warn(`[FfmpegVideo] ${w}`),m=await c.spawn(["exec-out","screenrecord","-"]),f=Jc(m)}let R,y,P=()=>{Qt(m),Qt(R)},A=()=>P();d.abortSignal?.addEventListener("abort",A,{once:!0});try{ee(d.abortSignal,"Android"),m.stderr.on("data",(V)=>{let j=V.toString();e.info(`[FfmpegVideo] screenrecord stderr: ${j.trim()}`)});let x=0;m.stdout.on("data",(V)=>{if(x+=V.length,x%102400===0)e.info(`[FfmpegVideo] Received ${x} bytes from screenrecord`)}),e.info("[FfmpegVideo] screenrecord process spawned");let C=await this.detectHardwareAccel();ee(d.abortSignal,"Android");let T=dt(d,C,{type:"pipe"});ee(d.abortSignal,"Android"),e.info(`[FfmpegVideo] Starting ffmpeg: ${this.ffmpegClient.binaryPath} ${T.join(" ")}`);let D=this.ffmpegClient.start({args:T,context:"Android screen recording encoder",stdio:["pipe","pipe","pipe"]});R=D.process,y=D.tracker,ee(d.abortSignal,"Android"),this.ffmpegClient.pipe({source:m.stdout,destination:R.stdin,context:"Android screen recording",processes:[m,R]}),e.info("[FfmpegVideo] Piped screenrecord stdout to ffmpeg stdin"),await NT(R),e.info("[FfmpegVideo] ffmpeg process spawned");let N={kind:"ffmpeg",platform:"android",captureTracker:f,ffmpegTracker:y,config:d};return{recordingId:d.recordingId,outputPath:d.outputPath,startedAt:d.startedAt,warning:w,physicalDisplayId:w?void 0:d.physicalDisplayId,backendHandle:N}}catch(x){P();let C=await this.cleanupStartingTrackers([f,...y?[y]:[]]);if(C)throw new X(`Failed to clean up Android recording after startup failed: ${r(C)}`,{recordingId:d.recordingId,outputPath:d.outputPath,startedAt:d.startedAt,backendHandle:{kind:"ffmpeg",platform:"android",captureTracker:f,ffmpegTracker:y,config:d}},{cause:x});return eo(x,d.abortSignal)}finally{d.abortSignal?.removeEventListener("abort",A)}}async cleanupStartingTrackers(o){let c=(await Promise.allSettled(o.map((p)=>Hn(p.process,p.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer})))).map((p,m)=>({result:p,tracker:o[m]})).filter((p)=>p.result.status==="rejected"&&p.tracker.process.pid!==void 0).map((p)=>p.result.reason);return c.length>0?AggregateError(c,"Failed to reap recording startup processes"):void 0}async recordingDisplayArg(o,d,c){let p=c-this.timer.now();if(p<=0||d.platform==="tvos")return;let m;try{let f=Math.min(p,ao);m=await Be((w)=>o.enumerateDisplays(d.deviceId,f,w),this.timer.now()+f,this.timer,{timeoutMessage:"Timed out enumerating iOS simulator recording displays"})}catch(f){e.warn(`Unable to enumerate iOS simulator recording displays: ${r(f)}`);return}if(m.length===0){e.warn(`Unable to select the live recording display for ${d.name}: no Integrated screens found`);return}if(m.length===1)return;try{let f=Math.min(c-this.timer.now(),ao);if(f<=0){e.warn(`Unable to select the live recording display for ${d.name}: start deadline expired`);return}let w=await Be(()=>this.liveScreenPixels(d,f),this.timer.now()+f,this.timer,{timeoutMessage:"Timed out probing the live iOS simulator display"}),R=w?dW(m,w.width,w.height):null;if(R?.name)return R.name;e.warn(`Unable to select the live recording display for ${d.name}: no uniquely matching Integrated screen with a Device Name`);return}catch(f){e.warn(`Unable to select the live recording display for ${d.name}: ${r(f)}`);return}}recordingCommandArgs(o,d,c){return["io",o,"recordVideo",...d?[`--display=${d}`]:[],c]}async startIos(o,d,c){if(ee(d.abortSignal,"iOS"),this.timer.now()>=c)throw new t(`Failed to start iOS recording within ${this.iosRecordingStartTimeoutMs}ms.`);let p=this.simctlFactory(o),m=await Be(async(A)=>await p.isAvailable({timeoutMs:Math.max(0,c-this.timer.now()),signal:A}),c,this.timer,{callerSignal:d.abortSignal,timeoutMessage:`Timed out checking simctl availability within ${this.iosRecordingStartTimeoutMs}ms`});if(ee(d.abortSignal,"iOS"),this.timer.now()>=c)throw new t(`Failed to start iOS recording within ${this.iosRecordingStartTimeoutMs}ms.`);if(!m)throw new t("simctl is not available. Install Xcode command line tools.");let f=await this.recordingDisplayArg(p,o,c),w=`${d.recordingId}-raw`,R=Math.max(1,this.iosRecordingStartMaxAttempts),y=[],P;for(let A=1;A<=R;A++){if(ee(d.abortSignal,"iOS"),c-this.timer.now()<=0)break;let C=ns.join(d.outputDirectory,A===1?`${w}.mov`:`${w}-attempt${A}.mov`),T=this.recordingCommandArgs(o.deviceId,f,C);if(P!==void 0)await this.removeStaleCapture(P);P=C;let D=await p.startCommandArgs(T,{stdio:["ignore","ignore","pipe"]}),N=Jc(D),V=!1;try{ee(d.abortSignal,"iOS"),await Yi(NT(D),c,this.timer,`Timed out waiting for simctl to spawn within ${this.iosRecordingStartTimeoutMs}ms`),V=!0;let j=R-A+1,q=Math.max(0,c-this.timer.now()),Fe=Math.min(so,q)*j,Xo=Math.max(0,Math.floor((q-Fe)/j));await Xi(N,qi,Xo,{signal:d.abortSignal,timer:this.timer});let Yo=ds(N,C,T,d);return{recordingId:d.recordingId,outputPath:d.outputPath,startedAt:d.startedAt,liveCapturePath:C,recordedPanel:Di(o,d.recordingPanel,f),backendHandle:Yo}}catch(j){let q=await this.describeFailedIosStartAttempt({attempt:A,captureTracker:N,config:d,device:o,error:j,maxAttempts:R,simctl:p,spawned:V,startDeadlineMs:c});if(y.push(q.description),q.cleanupError){let Fe=Ne(`Failed to clean up iOS recording after startup failed: ${q.description}`,"xcrun simctl",T,{tracker:N});throw new X(Fe,{recordingId:d.recordingId,outputPath:d.outputPath,startedAt:d.startedAt,backendHandle:{kind:"ffmpeg",platform:"ios",captureTracker:N,capturePath:C,config:d}},{cause:q.cleanupError})}if(A>=R)throw new t(Ne(`Failed to start iOS recording after ${R} attempt(s): ${y.join(" | ")}`,"xcrun simctl",T,{tracker:N}))}}throw new t(`Failed to start iOS recording within ${this.iosRecordingStartTimeoutMs}ms`+(y.length>0?`: ${y.join(" | ")}`:"."))}async removeStaleCapture(o){try{await this.captureFileRemover.remove(o)}catch(d){e.warn(`[FfmpegVideo] Failed to remove stale iOS capture ${o}: ${r(d)}`,d)}}async describeFailedIosStartAttempt(o){let d=await this.cleanupFailedIosStart(o.captureTracker,o.startDeadlineMs),c=`attempt ${o.attempt}/${o.maxAttempts}: ${o.error}`;if(!o.spawned&&o.captureTracker.process.pid===void 0)throw new t(`Failed to start iOS recording: ${o.error}`);if(d)return{description:`${c}; cleanup failed: ${r(d)}`,cleanupError:d};if(o.config.abortSignal?.aborted)throw new t("iOS recording start was cancelled during shutdown.");if(!o.spawned)throw new t(`Failed to start iOS recording: ${o.error}`);let p=await this.diagnoseFailedIosStart(o.simctl,o.device,o.startDeadlineMs,{isFinalAttempt:o.attempt>=o.maxAttempts,abortSignal:o.config.abortSignal});return e.warn(`[FfmpegVideo] iOS recording start attempt ${o.attempt}/${o.maxAttempts} failed: ${o.error} (${p})`),{description:`${c}; ${p}`}}async cleanupFailedIosStart(o,d){let c=Math.max(0,Math.min(so,d-this.timer.now()));try{await Hn(o.process,o.exitPromise,{timeoutMs:c,forceKillTimeoutMs:0,timer:this.timer,signal:"SIGKILL"});return}catch(p){return p}}async diagnoseFailedIosStart(o,d,c,{isFinalAttempt:p,abortSignal:m}){if(p)return await this.captureSimulatorDiagnostics(o,d,co,m);let f=Math.max(0,Math.min(ss,c-this.timer.now()));return f>0?await this.captureSimulatorDiagnostics(o,d,f,m):"simulator state unknown: start budget reserved for the pending retry"}async captureSimulatorDiagnostics(o,d,c,p){let m=Math.min(co,c),f=this.timer.now();try{let w=await ls(f+m,this.timer,p,async(y,P)=>await o.executeCommandArgs(["list","devices",d.deviceId],P,y)),R=(w.stdout||w.stderr||"").replace(/\s+/g," ").trim();return R?`simulator state: ${R.slice(0,500)}`:"simulator state: (empty)"}catch(w){if(p?.aborted)return e.debug("[FfmpegVideo] Simulator state probe cancelled by shutdown"),"simulator state probe cancelled by shutdown";let R=r(w);if(e.debug(`[FfmpegVideo] Simulator state probe failed: ${R}`),this.timer.now()-f>=m)return`simulator state unknown: state probe exceeded its ${m}ms budget (host may be loaded): ${R}`;return`simulator state unavailable: ${R}`}}capabilities;detectHardwareAccel(){return this.capabilities.detectHardwareAccel()}ensureFfmpegAvailable(o,d){return this.capabilities.ensureFfmpegAvailable(o,d)}}class er{executor;timeoutMs;constructor(o=new ne,d=15000){this.executor=o;this.timeoutMs=d}async list(o,d){let c=await this.executor.executeCommand(o,["--list-devices"],{timeoutMs:this.timeoutMs,signal:d});return lo(c.stdout)}}function lo(o){let d;try{d=JSON.parse(o)}catch(p){throw new t(`screen-capture-helper --list-devices returned unparseable output: ${r(p)}`)}let c=d?.devices;if(!Array.isArray(c))throw new t("screen-capture-helper --list-devices returned no `devices` array; the helper may be out of date.");return c.map((p)=>p).filter((p)=>typeof p?.uniqueID==="string"&&p.uniqueID.length>0).map((p)=>({uniqueID:p.uniqueID,localizedName:p.localizedName??p.uniqueID,modelID:p.modelID??"",manufacturer:p.manufacturer??""}))}var uo=30000,tr=20,po=8388608;function rr(o){return o.replace(/-/g,"").toLowerCase()}function ir(o){let{resolution:d}=o;return{codec:"h264",bitrate:{kind:"explicitBps",bps:o.targetBitrateKbps*1000},...d?{maxLongSide:Math.max(2,Math.max(d.width,d.height)&-2)}:{}}}function or(o){let d=["-use_wallclock_as_timestamps","1","-f","h264","-i","pipe:0","-c:v","copy","-fps_mode","passthrough","-movflags","+faststart"];if(o.maxDurationSeconds&&o.maxDurationSeconds>0)d.push("-t",String(o.maxDurationSeconds));return d.push("-y",o.outputPath),d}class nr{ffmpegClient;helperProvider;deviceLister;createHelper;platformProvider;fileSize;encoderFinalizeTimeoutMs;now;timer;env;helperPathExists;constructor(o={}){this.ffmpegClient=o.ffmpegClient??new pe,this.helperProvider=o.helperProvider??_c.getInstance(),this.deviceLister=o.deviceLister??new er,this.createHelper=o.createHelper??((d)=>new Ty(d)),this.platformProvider=o.platformProvider??(()=>process.platform),this.fileSize=o.fileSize??TW,this.encoderFinalizeTimeoutMs=o.encoderFinalizeTimeoutMs??uo,this.now=o.now??Date.now,this.timer=o.timer??i,this.env=o.env??process.env,this.helperPathExists=o.helperPathExists}async start(o){let d=o.device;if(!d)throw new t("Device is required to start video recording.");if(this.platformProvider()!=="darwin")throw new t("Physical iOS video recording requires macOS: the capture path uses CoreMediaIO/AVFoundation through the screen-capture-helper, which only exists on macOS.");let{abortSignal:c}=o;me(c),await this.ensureFfmpegAvailable(c),me(c);let p=await this.resolveHelperBinary(c);me(c);let m=await this.resolveCaptureUniqueId(p,d,c);me(c);let f={framesWritten:0,framesDropped:0,stopRequested:!1,helperExitWasRequested:!1,helperStderr:[]},w=this.createHelper({binaryPath:p,target:{kind:"device",deviceId:m,encode:ir(o)}});w.on("stderr",(y)=>{if(f.helperStderr.push(y),f.helperStderr.length>tr)f.helperStderr.shift()}),w.on("malformed",(y)=>{if(f.helperStderr.push(`malformed record from the helper (${y.reason})
|
|
16
|
-
`),f.helperStderr.length>tr)f.helperStderr.shift()}),w.on("exit",(y)=>{f.helperExit=y,f.helperExitWasRequested=f.stopRequested}),w.on("error",(y)=>{f.helperError??=y instanceof Error?y:Error(String(y));let P=y;if(P.syscall?.startsWith("spawn ")&&["ENOENT","EACCES","EAGAIN","EMFILE","ENFILE"].includes(P.code??"")&&!f.encoder&&!f.helperExit)f.helperSpawnError??=y;e.warn(`[IosPhysicalVideo] capture helper error: ${r(y)}`)}),w.on("encodedVideo",(y)=>this.onEncodedVideo(y,f,o));let R={recordingId:o.recordingId,outputPath:o.outputPath,startedAt:o.startedAt,effectiveConfig:o,backendHandle:{kind:"ios-physical",helper:w,state:f,config:o}};try{await lt(Promise.resolve(w.start()),c)}catch(y){try{await this.abandonStartedCapture(w,f)}catch(P){throw new X(`Failed to clean up physical iOS recording after startup failed: ${r(P)}`,R,{cause:y})}throw y}if(c?.aborted){try{await this.abandonStartedCapture(w,f)}catch(y){throw new X(`Failed to clean up physical iOS recording after startup was cancelled: ${r(y)}`,R)}me(c)}return R}async stop(o){let d=o.backendHandle;if(!d||d.kind!=="ios-physical")throw Error("Missing backend handle for physical iOS video recording.");let{helper:c,state:p}=d;p.stopRequested=!0;let m=this.now();try{if(await c.stop(),p.helperSpawnError)throw new t(this.buildNoFramesMessage(p),{cause:p.helperSpawnError});if(!p.helperExit)throw new rp("Physical iOS capture helper exit was not observed; it may still be running.");return await this.finalizeStoppedRecording(o,d,m)}catch(f){if(!p.helperExit&&!p.helperSpawnError)throw f;throw await this.buildFinalizationError(p,f)}}async buildFinalizationError(o,d){try{if(o.encoder&&o.encoderTracker)await Hn(o.encoder,o.encoderTracker.exitPromise,{timeoutMs:0,signal:"SIGKILL",timer:this.timer})}catch(c){e.warn(`[IosPhysicalVideo] Failed to clean up recording encoder: ${r(c)}`,c)}return new J(o.helperSpawnError?`Physical iOS capture never started. Start a new recording. ${this.buildNoFramesMessage(o)}`:`Physical iOS capture exited but the recording produced no usable video (zero bytes / finalization failed). Start a new recording. ${r(d)}`,{cause:o.helperSpawnError??d})}async finalizeStoppedRecording(o,d,c){let{state:p}=d,m=p.encoder;if(!m)throw new t(this.buildNoFramesMessage(p));if(m.stdin?.end(),p.encoderTracker)await Hn(m,p.encoderTracker.exitPromise,{timeoutMs:this.encoderFinalizeTimeoutMs,signal:null,timer:this.timer});this.assertEncoderSucceeded(p,o.outputPath),this.assertHelperSucceeded(p,o.outputPath);let f=await this.fileSize(o.outputPath);if(!f)throw new t("The finalized physical iOS recording is missing or contains zero bytes.");return this.logCaptureAccounting(p,o),{recordingId:o.recordingId,outputPath:o.outputPath,startedAt:o.startedAt,endedAt:new Date(c).toISOString(),sizeBytes:f,codec:"h264"}}async forceStop(o){let d=o.backendHandle;if(!d||d.kind!=="ios-physical")throw Error("Missing backend handle for physical iOS video recording.");d.state.stopRequested=!0;let c=[d.helper.stop()],p=d.state.encoder;if(p&&d.state.encoderTracker)c.push(Hn(p,d.state.encoderTracker.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer}));else if(p&&p.exitCode===null)p.kill("SIGKILL");let f=(await Promise.allSettled(c)).filter((w)=>w.status==="rejected").map((w)=>w.reason);if(f.length>0)throw AggregateError(f,`Failed to fully stop physical iOS recording: ${f.map(r).join("; ")}`)}onEncodedVideo(o,d,c){if(d.stopRequested&&!d.encoder)return;if(!d.encoder){if(!o.keyframe){d.framesDropped+=1;return}this.startEncoder(d,c)}let p=d.encoder?.stdin;if(!p||p.writableEnded){d.framesDropped+=1;return}if(p.writableLength>po)d.awaitingKeyframe=!0;if(d.awaitingKeyframe){if(!o.keyframe||p.writableNeedDrain){d.framesDropped+=1;return}d.awaitingKeyframe=!1}p.write(o.payload),d.framesWritten+=1}startEncoder(o,d){let c=or(d);e.info(`[IosPhysicalVideo] starting muxer: ${this.ffmpegClient.binaryPath} ${c.join(" ")}`);let p=this.ffmpegClient.start({args:c,context:"physical iOS screen recording muxer",stdio:["pipe","pipe","pipe"]});o.encoder=p.process,o.encoderTracker=p.tracker,p.process.stdin?.on("error",(m)=>{e.debug(`[IosPhysicalVideo] muxer stdin error (expected on muxer exit): ${m}`)})}logCaptureAccounting(o,d){if(e.info(`[IosPhysicalVideo] recording ${d.recordingId} wrote ${o.framesWritten} encoded record(s) to ${d.outputPath}.`),o.framesDropped>0)e.debug(`[IosPhysicalVideo] dropped ${o.framesDropped} encoded record(s) that arrived before the first keyframe or while the muxer stalled.`)}async ensureFfmpegAvailable(o){try{await lt(this.ffmpegClient.probe({signal:o}),o)}catch(d){throw me(o),new t(`FFmpeg is not available. Please install FFmpeg to use video recording.
|
|
17
|
-
macOS: brew install ffmpeg
|
|
18
|
-
Error: ${r(d)}`)}}assertEncoderSucceeded(o,d){let c=o.encoderTracker?.exitState;if(!c)return;if(!(c.exitCode!==void 0&&c.exitCode!==null&&c.exitCode!==0||Boolean(c.signal)))return;let m=o.encoderTracker?.stderr.join("").trim();throw new t(`FFmpeg failed to finalize the physical iOS recording at ${d} (exitCode: ${c.exitCode??"null"}, signal: ${c.signal??"null"}).`+(m?`
|
|
19
|
-
ffmpeg: ${m}`:""))}assertHelperSucceeded(o,d){let c=o.helperStderr.join("").trim(),p=c?`
|
|
20
|
-
screen-capture-helper: ${c}`:"";if(o.helperError)throw new t(`The iOS capture helper failed during the recording, so ${d} is truncated: ${r(o.helperError)}.${p}`);let m=o.helperExit;if(!m||o.helperExitWasRequested)return;let f=m.signal!==null?`signal ${m.signal}`:`exit code ${m.code??"null"}`;throw new t(`The iOS capture helper terminated with ${f} before the recording was stopped, so ${d} is truncated. The device was most likely unplugged or lost its capture session.${p}`)}async abandonStartedCapture(o,d){d.stopRequested=!0,await o.stop();let c=[],p=d.encoder;if(p&&d.encoderTracker)c.push(Hn(p,d.encoderTracker.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer}));else if(p&&p.exitCode===null)p.kill("SIGKILL");let f=(await Promise.allSettled(c)).filter((w)=>w.status==="rejected").map((w)=>w.reason);if(f.length>0)throw AggregateError(f,`Failed to abandon physical iOS recording start: ${f.map(r).join("; ")}`)}buildNoFramesMessage(o){let d=o.helperStderr.join("").trim();if(o.helperError)return`The iOS capture helper could not be run, so no recording was produced: ${r(o.helperError)}.`+(d?`
|
|
21
|
-
screen-capture-helper: ${d}`:"");return`No frames were captured from the physical iOS device${o.helperExit?` (helper exited code=${o.helperExit.code??"null"} signal=${o.helperExit.signal??"null"})`:""}, so no recording was produced. Connect the device over USB and accept the Trust This Computer prompt, then retry.`+(d?`
|
|
22
|
-
screen-capture-helper: ${d}`:"")}async resolveHelperBinary(o){let d=Ub(this.env);if(d)return Hb(d,{env:this.env,exists:this.helperPathExists});let c=await lt(this.helperProvider.ensure(o),o);if(!c)throw new t(`Physical iOS video recording requires the signed screen-capture-helper from the matching GitHub Release, which could not be resolved. For local development, build it with \`bash scripts/ios/swift-build.sh\` and set ${CP} to the resulting absolute path.`);return c}async resolveCaptureUniqueId(o,d,c){let p=await lt(this.deviceLister.list(o,c),c);if(p.length===0)throw new t(`No muxed external capture devices found for ${d.deviceId}. Connect the iPhone/iPad over USB, accept the Trust This Computer prompt, and make sure it is not already being captured by QuickTime.`);let m=p.find((y)=>y.uniqueID===d.deviceId);if(m)return m.uniqueID;let f=rr(d.deviceId),w=p.find((y)=>rr(y.uniqueID)===f);if(w)return w.uniqueID;if(p.length===1)return e.warn(`[IosPhysicalVideo] capture device uniqueID ${p[0].uniqueID} does not match ${d.deviceId}; using the only attached device.`),p[0].uniqueID;let R=p.map((y)=>`${y.uniqueID} (${y.localizedName})`).join(", ");throw new t(`Could not match device ${d.deviceId} to an AVFoundation capture device. Attached: ${R}. Disconnect the other devices, or record the matching UDID.`)}}function me(o){if(o?.aborted)throw new t("Physical iOS recording start was cancelled during shutdown.")}async function lt(o,d){if(me(d),!d)return o;let c=new AbortController,p=()=>c.abort(new t("Physical iOS recording start was cancelled during shutdown."));d.addEventListener("abort",p,{once:!0});try{return await l(o,{timer:i,signal:c.signal,label:"Physical iOS recording start"})}finally{if(p)d.removeEventListener("abort",p)}}function mo(o){return new t(`Unsupported platform for video recording: ${o}`)}function ar(o){return["shell",`echo $$; exec ${o.join(" ")}`]}function cs(o){let d=o.trim();if(!/^\d+$/.test(d))return;let c=Number(d);return Number.isSafeInteger(c)&&c>0?c:void 0}function sr(o){let d={pid:void 0},c="",p=!1;return o.on("data",(m)=>{if(p)return;c+=m.toString();let f=c.indexOf(`
|
|
23
|
-
`);if(f===-1&&c.length<=32)return;p=!0,d.pid=cs(f===-1?c:c.slice(0,f))}),d}function dr(o,d){let c=o.split(/[\0\s]+/).filter((p)=>p.length>0);return c.length>0&&(c[0]==="screenrecord"||c[0].endsWith("/screenrecord"))&&c.includes(d)}var us=1000,fo=Error("Video capture graceful exit deadline elapsed"),cr=5,ps=300,ut=3,ms=500,go=4000,fs=1e4,lr=300,gs=8192,hs=1000,ws=/\/sdcard\/auto-mobile-[^\s'":]+\.mp4/g,ho={maxStderrChars:gs};function mt(o,d){let c=o.exitCode;if(!(c!==void 0&&c!==null&&c!==0)&&!o.signal)return;let m=o.signal?`signal ${o.signal}`:`code ${c}`,f=o.endedAt?` at ${o.endedAt}`:"",w=d.join("").replace(ws,"<device recording file>").trim().slice(-hs);return`exited${f} with ${m}${w?`: ${w}`:""}`}async function ys(o,d,c,{device:p,physicalDisplayId:m,timer:f,cleanupFailedStart:w}){let R=await o.spawn(ar(d),{signal:c.abortSignal,abortSignalScope:"startup"}),y=sr(R.stdout),P=()=>R.kill("SIGTERM");c.abortSignal?.addEventListener("abort",P,{once:!0});try{if(c.abortSignal?.aborted)P();let A=[],{exitState:x,exitPromise:C}=MT(R,A,ho),T,D=m;if(await He({exitPromise:C,exitState:x,stderr:A},f,lr)&&m!==void 0&&p.apiLevel===void 0)T="Android screenrecord rejected --display-id; recording the default display.",e.warn(`[VideoCapture] ${T}`),R=await o.spawn(ar(d.filter((V,j)=>V!=="--display-id"&&d[j-1]!=="--display-id")),{signal:c.abortSignal,abortSignalScope:"startup"}),y=sr(R.stdout),A=[],{exitState:x,exitPromise:C}=MT(R,A,ho),D=void 0,await He({exitPromise:C,exitState:x,stderr:A},f,lr);if(mt(x,A))throw c.abortSignal?.throwIfAborted(),await IQ(R.stderr,f),new t(`Android screenrecord ${mt(x,A)} within ${lr} ms of launch, so no recording was started.`);return{process:R,exitState:x,exitPromise:C,stderr:A,devicePid:y,warning:T,physicalDisplayId:D}}catch(A){throw await w(y),A}finally{c.abortSignal?.removeEventListener("abort",P)}}function bs(o){return FU(o.targetBitrateKbps,o.maxThroughputMbps)}class ur{adbFactory;timer;codecProbe;constructor(o=v,d=i,c=ae){this.adbFactory=o;this.timer=d;this.codecProbe=c}async start(o){let d=o.device;if(!d)throw new t("Device is required to start video recording.");if(d.platform==="android")return this.startAndroid(d,o);if(d.platform==="ios")throw new t("iOS video recording is not handled by PlatformVideoCaptureBackend. Route iOS devices through FfmpegVideoProcessingBackend (HybridVideoCaptureBackend does this automatically).");throw mo(d.platform)}describeCaptureTeardown(o){let d=o.backendHandle;if(d?.kind!=="android")return;return{kind:"android-screenrecord",devicePid:d.devicePid?.pid,deviceTempPath:d.deviceTempPath}}async forceStopOrphanedCapture(o,d){let c=d.devicePid;if(c===void 0)throw new t(`Cannot identify orphan recorder on ${o.deviceId} without a pid.`);let p=this.adbFactory.create(o);try{if(await this.signalDeviceRecorder(p,d,c,{signal:9,orphan:!0})==="not-ours")return;if(!await this.confirmDeviceRecorderPidExited(p,d,c))throw new t(`Cannot confirm orphan recorder pid ${c} stopped on ${o.deviceId}.`)}catch(m){throw u(m,`Failed to stop orphan recorder pid ${c} on ${o.deviceId}`)}}async stop(o){let d=o.backendHandle;if(!d||d.kind!=="android")throw Error("Missing backend handle for video recording.");if(e.info(`[VideoCapture] Stopping recording ${o.recordingId}`),!d.stopRequested)d.stopRequested=!0,d.exitedBeforeStop=mt(d.exitState,d.stderr)!==void 0;let c=this.adbFactory.create(d.device);await this.requestDeviceRecorderStop(c,d);try{await l(d.exitPromise,{timer:this.timer,timeoutMs:tT.gracefulExit,label:"Video capture graceful exit",timeoutError:()=>fo,onTimeout:()=>{if(d.process.exitCode===null&&!d.process.killed)e.info("[VideoCapture] Sending SIGINT to host adb after pkill wait"),d.process.kill("SIGINT")}})}catch(f){if(f!==fo)throw f}if(d.process.exitCode===null)e.warn("[VideoCapture] screenrecord still running after SIGINT; sending SIGKILL"),d.process.kill("SIGKILL"),await d.exitPromise;else await d.exitPromise;e.info(`[VideoCapture] Process exited with code: ${d.exitState.exitCode}, signal: ${d.exitState.signal}`);let p=this.adbFactory.create(d.device),m=!1;try{try{if(e.info("[VideoCapture] Waiting 1 second for file to finalize on device"),await this.timer.sleep(us),m=!await this.waitForDeviceFileToFinalize(p,d),m)throw new t(`Device recording ${o.recordingId} did not finish writing before the finalization deadline. The device copy was retained; try stopping the recording again before retrying the pull.`);e.info(`[VideoCapture] Pulling file from device: ${d.deviceTempPath} -> ${o.outputPath}`),await this.pullRecordingFileWithRetry(p,["pull",d.deviceTempPath,o.outputPath],o.recordingId)}finally{await this.cleanupDeviceRecording(p,d,m)}let f=await TW(o.outputPath);if(!f)throw new t("The pulled recording is missing or contains zero bytes.");e.info(`[VideoCapture] Final file size: ${f} bytes`),e.debug(`[VideoCapture] Output file at ${o.outputPath}`);let w=await this.codecProbe.codec(o.outputPath),R=await we(this.codecProbe,o.outputPath);this.logRecordingExit(d);let y=this.earlyExitDescription(d);return{recordingId:o.recordingId,outputPath:o.outputPath,startedAt:o.startedAt,endedAt:d.exitState.endedAt??new Date().toISOString(),sizeBytes:f,codec:w,videoDurationMs:R,...y&&{warnings:[`The Android recorder ${y} before the stop was requested; the recording may end sooner than requested.`]}}}catch(f){throw this.finalizationError(d,m,f)}}earlyExitDescription(o){return o.exitedBeforeStop?mt(o.exitState,o.stderr):void 0}finalizationError(o,d,c){let p=this.earlyExitDescription(o);if(p&&!d)return e.warn(`[VideoCapture] No usable recording after the recorder exited early: ${r(c)}`,c),new J(`Android recorder ${p}, before the stop was requested, so the recording produced no usable video. Start a new recording.`,{cause:c,retainOwnership:!1});return new J(d?`Android capture exited but finalization failed: ${r(c)}`:`Android capture exited but the recording produced no usable video (zero bytes / finalization failed). Start a new recording. ${r(c)}`,{cause:c,retainOwnership:d})}async requestDeviceRecorderStop(o,d){let c=d.devicePid?.pid;try{if(c!==void 0){let m=await this.signalDeviceRecorder(o,d,c,{signal:2});e.info(`[VideoCapture] Device recorder pid ${c} SIGINT: ${m}`);return}let p=await o.executeCommand("shell pkill -2 screenrecord",tT.pkillOpts);e.info(`[VideoCapture] Device pkill -2 screenrecord completed (out=${p.stdout.trim().slice(0,120)} err=${p.stderr.trim().slice(0,160)})`)}catch(p){e.warn(`[VideoCapture] Device-side SIGINT of screenrecord failed; will rely on host SIGINT: ${r(p)}`)}}async signalDeviceRecorder(o,d,c,{signal:p,orphan:m=!1}){let f;try{f=await this.readDeviceRecorderCmdline(o,c)}catch(R){if(!m)throw R;throw new $c(`Cannot reach device to inspect orphan recorder pid ${c}; retry when the device answers.`,{cause:R})}if(f.error){if(!m)throw u(f.error,`Could not inspect recorder pid ${c}`);throw new $c(`Cannot reach device to inspect orphan recorder pid ${c}; retry when the device answers.`,{cause:f.error})}if(!dr(f.stdout,d.deviceTempPath))return e.warn(`[VideoCapture] Device pid ${c} is no longer this recording's screenrecord; not signalling it`),"not-ours";let w=await o.executeCommand(`shell kill -${p} ${c}`,{timeoutMs:go});if(w.error)throw u(w.error,`Could not signal recorder pid ${c}`);return"signalled"}readDeviceRecorderCmdline(o,d){return o.executeCommand(`shell 'cat /proc/${d}/cmdline 2>/dev/null; true'`,{timeoutMs:go,noRetry:!0})}async forceKillDeviceRecorder(o,d,c,p){let m=d.devicePid?.pid;if(m===void 0&&p?.deviceWide===!1){e.warn(`[VideoCapture] Skipping device-wide screenrecord kill for ${c}; its device pid is unknown so the device-side recorder may run until its own time limit`);return}try{if(m===void 0)await o.executeCommand("shell pkill -9 screenrecord",tT.pkillOpts);else await this.signalDeviceRecorder(o,d,m,{signal:9});return}catch(f){return e.warn(`[VideoCapture] Device-side force-stop failed: ${r(f)}`),`screenrecord force-stop failed: ${r(f)}`}}async cleanupDeviceRecording(o,d,c){if(c)e.warn(`[VideoCapture] Retaining unstable device file ${d.deviceTempPath} for recovery`);else{e.info("[VideoCapture] Cleaning up temp file on device");let p=["shell","rm",d.deviceTempPath];try{let m=await o.spawn(p);await new Promise((f)=>{m.once("exit",(w)=>{if(w===0)e.info("[VideoCapture] Temp file cleaned up");else e.warn(`[VideoCapture] Failed to clean up temp file: rm exited with code ${w}`);f()}),m.once("error",(w)=>{e.warn(`[VideoCapture] Failed to clean up temp file: ${w}`),f()})})}catch(m){e.warn(`[VideoCapture] Failed to clean up temp file: ${m}`)}}}logRecordingExit(o){if(o.exitState.exitCode&&o.exitState.exitCode!==0)e.warn(`[VideoCapture] Recording exited with code ${o.exitState.exitCode}: ${o.stderr.join("")}`);if(o.stderr.length>0)e.info(`[VideoCapture] Stderr output: ${o.stderr.join("")}`)}async readDeviceFileSizeBytes(o,d){try{let c=await o.executeCommand(`shell stat -c %s ${d}`,{timeoutMs:tT.probe,noRetry:!0}),p=Number.parseInt(c.stdout.trim(),10);return Number.isFinite(p)?p:null}catch(c){return e.debug(`[VideoCapture] Failed to stat device file ${d}: ${r(c)}`),null}}async waitForDeviceFileToFinalize(o,d){let c=d.deviceTempPath,p=-1,m=!1,f=!1;for(let w=0;w<cr;w++){let R=await this.readDeviceFileSizeBytes(o,c);if(m||=R!==null,f||=R!==null&&R>0,R!==null&&R>0&&R===p)return e.info(`[VideoCapture] Device file finalized at ${R} bytes`),!0;p=R??-1,await this.timer.sleep(ps)}if(f)return e.warn(`[VideoCapture] Device file ${c} did not visibly stabilize after ${cr} checks`),!1;if(m){if(!await this.confirmDeviceScreenrecordExited(o,d))return!1;throw new t(`Device recording remained empty (zero bytes) after ${cr} checks with capture exit confirmed.`)}return e.warn(`[VideoCapture] Could not observe device file ${c}; attempting bounded pull recovery`),!0}async confirmDeviceScreenrecordExited(o,d){let c=d.devicePid?.pid;if(c!==void 0)return this.confirmDeviceRecorderPidExited(o,d,c);try{let p=await o.executeCommand(`shell 'pidof screenrecord; printf "pidof-status:%s\\n" "$?"'`,{timeoutMs:tT.probe,noRetry:!0});return!p.error&&p.stderr.trim()===""&&p.stdout.trim()==="pidof-status:1"}catch(p){return e.warn("[VideoCapture] Could not confirm device screenrecord exit",p),!1}}async confirmDeviceRecorderPidExited(o,d,c){try{let p=await this.readDeviceRecorderCmdline(o,c);if(p.error)return!1;return!dr(p.stdout,d.deviceTempPath)}catch(p){return e.warn(`[VideoCapture] Could not confirm device recorder pid ${c} exit`,p),!1}}async pullRecordingFile(o,d){let c=await o.spawn(d);await new Promise((p,m)=>{c.once("exit",(f)=>{if(f===0)e.info("[VideoCapture] File pulled successfully"),p();else m(Error(`adb pull failed with exit code ${f}`))}),c.once("error",(f)=>m(f))})}async pullRecordingFileWithRetry(o,d,c){let p;for(let m=1;m<=ut;m++)try{await this.pullRecordingFile(o,d);return}catch(f){if(p=f,e.warn(`[VideoCapture] adb pull attempt ${m}/${ut} failed for recording ${c}: ${r(f)}`),m<ut)await this.timer.sleep(ms)}throw new t(`Failed to pull video recording ${c} from device after ${ut} attempts: ${r(p)}`,{cause:p})}async forceStop(o,d){let c=o.backendHandle;if(!c||c.kind!=="android")throw Error("Missing backend handle for video recording.");if(d?.hostOnly){try{await Hn(c.process,c.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer})}catch(y){throw new t(`Failed to fully stop Android recording ${o.recordingId}: host adb process cleanup failed: ${r(y)}`,{cause:y})}return}let p=Hn(c.process,c.exitPromise,{timeoutMs:0,forceKillTimeoutMs:tp,signal:"SIGKILL",timer:this.timer}).then(()=>{return},(y)=>y),m=this.adbFactory.create(c.device),f=[],w=await this.forceKillDeviceRecorder(m,c,o.recordingId,d);if(w)f.push(w);try{await m.execute(["shell","rm","-f",c.deviceTempPath],{timeoutMs:tT.tempFileRemove})}catch(y){e.warn(`[VideoCapture] Device temp-file cleanup failed: ${y}`),f.push(`device temp-file cleanup failed: ${r(y)}`)}let R=await p;if(R)f.push(`host adb process cleanup failed: ${r(R)}`);if(f.length>0)throw new t(`Failed to fully discard Android recording ${o.recordingId}: ${f.join("; ")}`)}async startAndroid(o,d){let c=this.adbFactory.create(o),p=d.physicalDisplayId===void 0?await st(o,c,{request:d.display,signal:d.abortSignal,timer:this.timer}):void 0,m=d.physicalDisplayId??p?.physicalId,f=bs(d),w=Math.max(1,Math.round(f*1000)),R=this.resolveAndroidTimeLimit(d.maxDurationSeconds);if(d.maxDurationSeconds&&d.maxDurationSeconds>Ai)e.warn(`[VideoCapture] Android screenrecord caps at ${Ai}s; requested ${d.maxDurationSeconds}s.`);let y=`/sdcard/auto-mobile-${d.recordingId}.mp4`,P=["screenrecord","--bit-rate",String(w),"--time-limit",String(R)];if(m!==void 0)P.push("--display-id",m);if(d.resolution)P.push("--size",`${d.resolution.width}x${d.resolution.height}`);P.push(y),e.info("[VideoCapture] Starting Android recording"),e.debug(`[VideoCapture] Screenrecord argv: ${P.join(" ")}`),e.debug(`[VideoCapture] Device temp path: ${y}`),e.debug(`[VideoCapture] Output path: ${d.outputPath}`),e.info(`[VideoCapture] Bitrate: ${f}kbps (${w}bps), Time limit: ${R}s`);let A={device:o,physicalDisplayId:m,timer:this.timer,cleanupFailedStart:(Fe)=>this.cleanupFailedAndroidStartDetached(c,y,Fe)},{process:x,exitState:C,exitPromise:T,stderr:D,devicePid:N,warning:V,physicalDisplayId:j}=await ys(c,P,d,A),q={kind:"android",process:x,exitState:C,exitPromise:T,stderr:D,device:o,deviceTempPath:y,devicePid:N};return{recordingId:d.recordingId,outputPath:d.outputPath,startedAt:d.startedAt,warning:V,physicalDisplayId:j,backendHandle:q}}async cleanupFailedAndroidStartDetached(o,d,c){try{await Je(()=>l(this.cleanupFailedAndroidStart(o,d,c),{timer:this.timer,timeoutMs:fs,label:"Failed video start cleanup"}))}catch(p){e.warn(`[VideoCapture] Failed-start cleanup did not finish: ${r(p)}`,p)}}async cleanupFailedAndroidStart(o,d,c){let p=c.pid;try{if(p===void 0)e.warn("[VideoCapture] Failed start left no known device pid; not signalling screenrecord by name");else{let m=await this.signalDeviceRecorder(o,{deviceTempPath:d},p,{signal:9});e.info(`[VideoCapture] Failed-start device recorder pid ${p} SIGKILL: ${m}`)}}catch(m){e.warn(`[VideoCapture] Could not stop the device recorder after a failed start: ${r(m)}`,m)}await this.cleanupDeviceRecording(o,{deviceTempPath:d},!1)}resolveAndroidTimeLimit(o){if(o&&o>0)return Math.min(o,Ai);return Ai}}class BO{ffmpegBackend;platformBackend;physicalIosBackend;constructor(o=new ct,d=new ur,c=new nr){this.ffmpegBackend=o,this.platformBackend=d,this.physicalIosBackend=c}async start(o){let d=o.device;if(!d)throw new t("Device is required to start video recording.");let c=this.selectBackend(d),p;try{p=await c.start(o)}catch(m){if(m instanceof X)throw new X(m.message,this.wrapHandle(m.handle,c),{cause:m});throw m}return this.wrapHandle(p,c)}wrapHandle(o,d){return{...o,backendHandle:{kind:"hybrid",backend:this.backendKind(d),handle:o}}}describeCaptureTeardown(o){let d=o.backendHandle;if(!d||d.kind!=="hybrid")return;return this.backendFor(d.backend).describeCaptureTeardown?.(d.handle)}async forceStopOrphanedCapture(o,d,c){let p=d.kind==="ios-host-recorder"?this.ffmpegBackend:this.platformBackend;if(d.kind==="android-screenrecord"&&!o)throw new t("Device is required to stop an orphan Android recorder.");if(!p.forceStopOrphanedCapture)throw new t("Selected backend does not support orphan capture teardown.");if(c)await p.forceStopOrphanedCapture(o,d,c);else await p.forceStopOrphanedCapture(o,d)}async stop(o){let d=o.backendHandle;if(!d||d.kind!=="hybrid")throw Error("Missing backend handle for hybrid video recording.");return this.backendFor(d.backend).stop(d.handle)}async forceStop(o,d){let c=o.backendHandle;if(!c||c.kind!=="hybrid")throw Error("Missing backend handle for hybrid video recording.");let p=this.backendFor(c.backend);if(!p.forceStop)throw Error("Selected video capture backend does not support force stopping recordings.");await p.forceStop(c.handle,d)}backendKind(o){if(o===this.ffmpegBackend)return"ffmpeg";return o===this.physicalIosBackend?"ios-physical":"platform"}backendFor(o){if(o==="ffmpeg")return this.ffmpegBackend;return o==="ios-physical"?this.physicalIosBackend:this.platformBackend}selectBackend(o){if(o.platform==="ios")return yn(o.deviceId)?this.physicalIosBackend:this.ffmpegBackend;if(o.platform==="tvos")return this.ffmpegBackend;if(o.platform==="android"){if($e(g.ANDROID_VIDEO_USE_FFMPEG_PIPE))return e.info("[VideoCapture] Android: using exec-out screenrecord \u2192 ffmpeg (AUTOMOBILE_ANDROID_VIDEO_USE_FFMPEG_PIPE)"),this.ffmpegBackend}return this.platformBackend}}import{rename as vs,rm as Rs}from"fs/promises";var Ss=120000,Ps=1e4;function As(o,d){let c=o.pcmBytes>0?[...o.leadMs>0?["-ss",(o.leadMs/1000).toFixed(3)]:[],"-f","s16le","-ar",String(o.sampleRate),"-ac","1","-i",o.pcmPath]:["-f","lavfi","-i",`anullsrc=r=${o.sampleRate}:cl=mono`];return["-y","-hide_banner","-loglevel","error","-i",o.videoPath,...c,"-map","0:v:0","-map","1:a:0","-c:v","copy","-c:a","aac","-b:a","128k","-af","apad","-shortest","-movflags","+faststart",d]}class pr{client;files;constructor(o,d={rename:vs,remove:(c)=>Rs(c,{force:!0})}){this.client=o;this.files=d}async ensureAvailable(){try{await this.client.probe({timeoutMs:Ps})}catch(o){throw new t(`A recording with audio needs FFmpeg to add the audio track (${r(o)}). Install FFmpeg (brew install ffmpeg, or apt-get install ffmpeg) or record without audio.`)}}async mux(o){let d=`${o.videoPath}.with-audio.mp4`;try{let c=await this.client.run({args:As(o,d),context:"recording audio track mux",timeoutMs:Ss});if(c.exitCode!==0)throw Error(`ffmpeg exited with ${c.exitCode??c.signal}: ${c.stderr.trim().slice(-400)}`);await this.files.rename(d,o.videoPath)}catch(c){throw await this.files.remove(d).catch((p)=>{e.warn(`Failed to remove partial mux output ${d}: ${r(p)}`)}),c}}}function xs(o){let d=Es(o,{mode:384}),c=0,p;d.on("error",(f)=>{p??=f});let m;return{write:(f)=>{if(p)return;if(c+=f.byteLength,d.write(f))return;return new Promise((w)=>{let R=()=>{d.off("drain",R),d.off("close",R),w()};d.on("drain",R),d.on("close",R)})},close:()=>(m??=new Promise((f,w)=>{let R=()=>p?w(p):f(c);if(d.destroyed){R();return}d.once("close",R),d.end()}),m)}}function ks(){return{source:pf,muxer:new pr(new pe),openPcmFile:xs,removeFile:(o)=>Cs(o,{force:!0}),now:()=>i.now()}}function mr(){return e.debug("[VideoRecording] Using HybridVideoCaptureBackend (iOS FFmpeg, Android platform)"),new zt(new BO,ks())}function oe(o){return{recordingId:o.recordingId,fileName:o.fileName,filePath:o.filePath,format:o.format,sizeBytes:o.sizeBytes,durationMs:o.durationMs,videoDurationMs:o.videoDurationMs,codec:o.codec,outputName:o.outputName,createdAt:o.createdAt,startedAt:o.startedAt,endedAt:o.endedAt,lastAccessedAt:o.lastAccessedAt,config:o.config,highlights:o.highlights,recordedPanel:o.recordedPanel,transitions:o.transitions,...o.warnings?{warnings:o.warnings}:{},...o.hasAudioTrack===void 0?{}:{hasAudioTrack:o.hasAudioTrack}}}function wo(o,d){return{status:"completed",captureTeardown:void 0,ownerSessionUuid:d,outputName:o.outputName,fileName:o.fileName,filePath:o.filePath,format:o.format,sizeBytes:o.sizeBytes,durationMs:o.durationMs,codec:o.codec,endedAt:o.endedAt,lastAccessedAt:o.lastAccessedAt,config:o.config,highlights:o.highlights,recordedPanel:o.recordedPanel,transitions:o.transitions,warnings:o.warnings,hasAudioTrack:o.hasAudioTrack}}var Rd={LATEST:"automobile:video/latest",ARCHIVE:"automobile:video/archive",ARCHIVE_ITEM:"automobile:video/archive/{recordingId}"};function $O(o){return`automobile:video/archive/${o}`}var yo=1,bo=(o,d,c,p)=>[[c,p],[p,c]].some(([m,f])=>Math.abs(o-m)<=yo&&Math.abs(d-f)<=yo);function Ts(o,d){if(d)return d.screenScale??(()=>null);return()=>Zl(o).getScreenScaleMetadata()}function Is(o,d){let{sourceWidth:c,sourceHeight:p}=o;if(!d||typeof c!=="number"||typeof p!=="number"||typeof o.sourceScale==="number"&&o.sourceScale>0)return;let{nativeScale:m,pixelWidth:f,pixelHeight:w}=d;if(bo(c,p,f/m,w/m))return 1;if(bo(c,p,f,w))return m;return}var vo=Error("Simulator highlight deadline elapsed"),Ds=new Map,Ms=0,Fs=s({requestId:n(),success:h(),error:n().optional()});class gr{device;executor;timer;resolveHelper;screenScale;hosts;supportedHelpers=new Map;fallback;constructor(o,d){this.device=o;this.fallback=d?.fallback??(()=>Zl(o)),this.executor=d?.executor??new ne,this.timer=d?.timer??i,this.screenScale=Ts(o,d),this.hosts=d?new Map:Ds,this.resolveHelper=d?.resolveHelper??(async()=>{if(Ub())return Hb();return _c.getInstance().ensure()})}async requestAddHighlight(o,d,c=5000){let p=new AbortController;try{return await l(this.sendHighlight(o,d,p.signal,c),{timer:this.timer,timeoutMs:c,label:"Simulator highlight",timeoutError:()=>vo,onTimeout:()=>p.abort()})}catch(m){if(m===vo)return e.warn(`[SimulatorHighlights] highlight request timed out after ${c}ms`),{success:!1,error:"Simulator highlight timed out"};throw m}}async sendHighlight(o,d,c,p){try{let m=await this.resolveHelper();if(c.throwIfAborted(),!m)return await this.fallback().requestAddHighlight(o,d,p);let f=this.supportedHelpers.get(m);if(f===void 0){let A=await this.executor.executeCommand(m,["--help"],{timeoutMs:p,signal:c});c.throwIfAborted(),f=A.stderr.split(/\r?\n/).some((x)=>m6(x)==="simulator-highlights"),this.supportedHelpers.set(m,f)}if(!f)return await this.fallback().requestAddHighlight(o,d,p);let w=`${m}:${this.device.deviceId}`,R=String(++Ms),y=JSON.stringify({requestId:R,id:o,shape:this.withSourceScale(d)}),P=this.hosts.get(w);if(!P)P={child:this.executor.spawn(m,["--highlight-simulator",this.device.name,"--highlight-json",y],{stdio:["pipe","pipe","pipe"]}),pending:new Map},this.hosts.set(w,P),this.watchHost(w,P);else{let A=this.waitForReply(P,R,c);return P.child.stdin?.write(`${y}
|
|
24
|
-
`),await A}return await this.waitForReply(P,R,c)}catch(m){return e.warn(`[SimulatorHighlights] Failed to send highlight: ${r(m)}`,m),{success:!1,error:String(m)}}}withSourceScale(o){let d=Is(o.bounds,this.screenScale());return d===void 0?o:{...o,bounds:{...o.bounds,sourceScale:d}}}waitForReply(o,d,c){return new Promise((p)=>{let m=(w)=>{c.removeEventListener("abort",f),o.pending.delete(d),p(w)},f=()=>m({success:!1,error:"Simulator highlight timed out"});if(o.pending.set(d,m),c.addEventListener("abort",f,{once:!0}),c.aborted)f()})}watchHost(o,d){let c="",p="",m=!1,f=(w)=>{if(m)return;if(m=!0,this.hosts.get(o)===d)this.hosts.delete(o);for(let R of d.pending.values())R({success:!1,error:w});d.child.kill()};d.child.stdout?.on("data",(w)=>{if(m)return;if(c+=w.toString(),c.length>65536){f("Invalid highlight acknowledgement");return}let R;while((R=c.indexOf(`
|
|
25
|
-
`))>=0){let y=c.slice(0,R);c=c.slice(R+1);try{let P=Fs.parse(JSON.parse(y));d.pending.get(P.requestId)?.({success:P.success,...P.error?{error:P.error}:{}})}catch(P){f(`Invalid highlight acknowledgement: ${P}`);return}}}),d.child.stderr?.on("data",(w)=>{p=(p+w.toString()).slice(-4096)}),d.child.stdin?.on("error",(w)=>f(String(w))),d.child.once("error",(w)=>f(String(w))),d.child.once("exit",()=>f(p.trim()||"Highlight helper exited before drawing"))}}var _s=5000,hr=(o)=>o===null?void 0:o,Ro={x:a().int(),y:a().int(),width:a().int().positive("bounds.width must be a positive integer"),height:a().int().positive("bounds.height must be a positive integer"),sourceWidth:a().int().positive().nullable().optional(),sourceHeight:a().int().positive().nullable().optional()},So=(o,d)=>{let c=hr(o.sourceWidth)!==void 0,p=hr(o.sourceHeight)!==void 0;if(c!==p)d.addIssue({code:Gn.custom,message:"bounds.sourceWidth and bounds.sourceHeight must be provided together"});if(hr(o.sourceScale)!==void 0&&!c)d.addIssue({code:Gn.custom,message:"bounds.sourceScale requires bounds.sourceWidth and bounds.sourceHeight"})},Po=(o)=>s({type:I("circle"),bounds:o}).strict(),_U=Po(s(Ro).strict().superRefine(So)),Os=Po(s({...Ro,sourceScale:a().finite().positive().nullable().optional()}).strict().superRefine(So)),Vs=s({success:h(),error:n().nullable().optional(),requestId:n().optional(),timestamp:a().optional()}).passthrough();class wr{device;adbFactory;highlightClient;constructor(o,d=v,c){if(this.device=o,o.platform==="ios")this.adbFactory=v;else if(d&&typeof d.create==="function")this.adbFactory=d;else if(d){let p=d;this.adbFactory={create:()=>p}}else this.adbFactory=v;this.highlightClient=c||this.createDefaultHighlightClient(o)}async addHighlight(o,d,c={}){let p=this.parseHighlightId(o),m=this.parseHighlightShape(d),f=c.timeoutMs??_s,w=await this.highlightClient.requestAddHighlight(p,m,f,new B);return this.parseHighlightResponse(w)}parseHighlightId(o){let d=n().min(1,"Highlight id must be a non-empty string").safeParse(o);if(!d.success)throw new t(d.error.issues.map((c)=>c.message).join("; "));return d.data}parseHighlightShape(o){let d=Os.safeParse(o);if(!d.success){let c=d.error.issues.map((p)=>p.message).join("; ");throw new t(c)}return d.data}parseHighlightResponse(o){let d=Vs.safeParse(o);if(!d.success){let c=d.error.issues.map((p)=>p.message).join("; ");throw new t(`Invalid highlight response: ${c}`)}return d.data}createDefaultHighlightClient(o){if(o.platform==="android")return k.getInstance(o,this.adbFactory);if(o.platform==="ios"){if(W({deviceId:o.deviceId})==="simulator")return new gr(o);return _.getInstance(o)}throw new t(`Visual highlights are not supported on ${o.platform} devices.`)}}class fE{deviceReadiness;visualHighlightFactory;constructor(o,d=(c)=>new wr(c)){this.deviceReadiness=o,this.visualHighlightFactory=d}async addHighlight(o,d,c){let m=await(await this.resolveHighlight(c)).addHighlight(o,d,{timeoutMs:c.timeoutMs});if(!m.success)throw new t(m.error||"Failed to add highlight");return m}async resolveHighlight(o){if(o.device){if(o.device.platform!==o.platform)throw new t(`Highlight platform mismatch: requested ${o.platform}, device is ${o.device.platform}.`);return this.visualHighlightFactory(o.device)}if(o.platform!=="android"&&o.platform!=="ios")throw new t(`Visual highlights are not supported on ${o.platform} devices.`);if(!this.deviceReadiness)throw new t("Supply a resolved device or inject device readiness for visual highlights.");let d=await this.deviceReadiness.ensureDeviceReady(o.platform,o.deviceId);return this.visualHighlightFactory(d)}}var Hs=30,$s=300,mK=3600,Bs=1200,Ls=86400000,Ns=7,Us=60,Gs=15,js=5000;function yr(o,d,c){return wu(o,d,(p)=>e.warn(`[VideoRecording] Ignoring invalid retention env value "${p}"; using ${c}`))??c}function Io(o=process.env){let d=yr(g.VIDEO_RETENTION_DAYS,o,Ns),c=yr(g.VIDEO_RETENTION_SWEEP_MINUTES,o,Us),p=yr(g.VIDEO_INPROGRESS_CHECK_SECONDS,o,Gs);return{ttlMs:Math.max(0,Math.floor(d*Ls)),sweepIntervalMs:Math.max(1000,Math.floor(c*60000)),inProgressCheckIntervalMs:Math.max(1000,Math.floor(p*1000))}}var Tl=5000;async function Do(o,d,c){return st(o,v.create(o),{request:d,signal:c})}var K=null,Re,Rr=!0,Ue=0,fe=null,ze=new Set,je=new Map,zs=600000,Ee=new Map;function UO(o){let d=Ee.get(o);if(d)d.timer.clearTimeout(d.handle),Ee.delete(o)}function lJ(o,d={}){UO(o);let c=d.timer??i,p={timer:c,handle:c.setTimeout(()=>{if(Ee.get(o)===p)UO(o)},d.expiryMs??zs)};Ee.set(o,p)}var ke=new Map,Te=new Map,wt=new Map,ft;function uJ(o){ft=o}function xU(){return ft}var Q=new Map,Se=new Map,Pe=new Map,Y=new Set,re=new Map;function Ks(o,d){if(!d)return{key:"unknown",role:"unknown"};return{key:d.key,role:o.displays?.panels.find((c)=>c.key===d.key)?.role??d.role}}function Ws(o,d,c,{startedAt:p,timer:m}){let f=Date.parse(p),w={recordedPanel:c.panel,currentPanel:c.activePanel,transitions:[],unsubscribe:()=>{return},device:d,warning:c.warning};if(c.activePanel.key!==c.panel.key)w.transitions.push({atMs:0,from:c.panel,to:c.activePanel});w.unsubscribe=xe.subscribe(d.deviceId,(R)=>{let y=w.transitions.at(-1),P=Ks(d,R);if(y?.to.key==="unknown"&&R){if(y.from.key===P.key&&y.from.role===P.role){w.transitions.pop();return}y.to=P,w.currentPanel=P;return}if(R&&R.key===w.currentPanel.key)return;if(Fi(d,w.currentPanel,w.transitions,R)){w.currentPanel=P;return}if(w.transitions.push({atMs:Math.max(0,Math.round(m.now()-f)),from:w.currentPanel,to:P}),R)w.currentPanel=P}),re.set(o,w)}async function qs(o,d,c){if(d.device.platform==="android"){if(d.physicalDisplayId!==void 0){let p=d.device.displays?.panels.find((f)=>f.key===d.physicalDisplayId),m={key:d.physicalDisplayId,role:p?.role??"unknown"};return{panel:m,physicalId:d.physicalDisplayId,activePanel:d.activePanel??m}}return o.resolveAndroidDisplay(d.device,d.display,c)}if(d.display!==void 0)throw new t("display selection for videoRecording is supported on Android only.");if(d.device.platform==="ios")return Ii(d.device,xe.observedPanel(d.device.deviceId));return}async function Mo(o,d,c,p){let m=re.get(o);if(!m)return;m.unsubscribe(),re.delete(o);let f=m.transitions.at(-1),R=!(p?.hostOnly||Y.has(o))&&m.device.platform!=="ios";if(f?.to.key==="unknown"&&R)try{let P=await c.resolveAndroidDisplay(m.device,"active");if(P)f.to=P.activePanel}catch(P){e.warn(`[VideoRecording] Could not resolve display after transition: ${r(P)}`)}m.transitions=m.transitions.filter((P)=>P.from.key!==P.to.key||P.from.role!==P.to.role),d.recordedPanel=m.recordedPanel,d.transitions=m.transitions;let y=_i(m);d.warnings=y.length>0?[...d.warnings??[],...y]:d.warnings}var Ie=new Map,Ae=null;async function Js(){return mr()}async function Fo(){let o=await Js();return new qe({backend:o})}async function Xs(o){if(!Re){let c=Ys(o).catch((p)=>{if(Re===c)Re=void 0;throw p});Re=c}await Re}async function HO(){return U()}function _o(o,d,c){return Q.has(o)||d.videoRecorderService.listActiveRecordingIds().includes(o)||d.daemonSessionId!==void 0&&c===d.daemonSessionId}async function Z(o,d){try{if(!_o(o,d)){let p=await d.recordingRepository.getRecording(o);if(!d.daemonSessionId||p?.recorderDaemonSessionId!==d.daemonSessionId)return}let c=d.videoRecorderService.getCaptureTeardown(o);await d.recordingRepository.updateRecording(o,{captureTeardown:Y.has(o)&&c?.kind!=="ios-host-recorder"?void 0:c})}catch(c){e.warn(`[VideoRecording] Failed to refresh capture teardown descriptor for ${o}`,c)}}async function Ys(o){let d=await o.recordingRepository.listRecordings({status:"recording",excludeLiveDaemonSessionIds:o.liveDaemonSessionIds,ownDaemonSessionId:o.daemonSessionId});if(K===o)od(o);if(d.length===0)return;let c=o.now().toISOString();for(let p of d){let m=await o.statFileSize(p.filePath),f=Sr(p.startedAt,c);await o.recordingRepository.updateRecording(p.recordingId,{status:"interrupted",endedAt:c,lastAccessedAt:c,sizeBytes:m,durationMs:f})}e.info(`[VideoRecording] Marked ${d.length} recording(s) as interrupted after restart`)}async function U(){if(!K)K={videoRecorderService:await Fo(),recordingRepository:new LU,configRepository:l6(),highlightClient:new fE,timer:i,now:()=>new Date,liveDaemonSessionIds:new Set,daemonSessionId:void 0,retentionPolicy:Io(),statFileSize:ht,codecProbe:ae,resolveAndroidDisplay:Do};let o=K;return await Xs(o),o}async function pJ(o){let d=K??await Qs(o);o={daemonSessionId:d.daemonSessionId,...o},K={videoRecorderService:o.videoRecorderService??d.videoRecorderService,recordingRepository:o.recordingRepository??d.recordingRepository,configRepository:o.configRepository??d.configRepository,highlightClient:o.highlightClient??d.highlightClient,timer:o.timer??d.timer,now:o.now??d.now,liveDaemonSessionIds:o.liveDaemonSessionIds??d.liveDaemonSessionIds,daemonSessionId:o.daemonSessionId,retentionPolicy:o.retentionPolicy??d.retentionPolicy,...Oo(o,d),resolveAndroidDisplay:o.resolveAndroidDisplay??d.resolveAndroidDisplay},Zs()}function Oo(o,d={statFileSize:ht,codecProbe:ae}){return{statFileSize:o.statFileSize??d.statFileSize,codecProbe:o.codecProbe??d.codecProbe}}async function Qs(o){return{videoRecorderService:o.videoRecorderService??await Fo(),recordingRepository:o.recordingRepository??new LU,configRepository:o.configRepository??l6(),highlightClient:o.highlightClient??new fE,timer:o.timer??i,now:o.now??(()=>new Date),liveDaemonSessionIds:o.liveDaemonSessionIds??new Set,daemonSessionId:o.daemonSessionId,retentionPolicy:o.retentionPolicy??Io(),...Oo(o),resolveAndroidDisplay:o.resolveAndroidDisplay??Do}}function Zs(){for(let o of Ee.keys())UO(o);for(let{timer:o,handle:d}of ke.values())o.clearTimeout(d);ke.clear(),Q.clear();for(let{timer:o,handle:d}of Ie.values())o.clearInterval(d);if(Ie.clear(),Ae)Ae.timer.clearInterval(Ae.handle),Ae=null;for(let o of Te.values())for(let d of o.timers)o.timer.clearTimeout(d);Te.clear(),wt.clear(),Se.clear(),Y.clear(),Pe.clear();for(let o of re.values())o.unsubscribe();re.clear(),Rr=!0,Ue=0;for(let o of ze)o.abort();ze.clear(),fe?.resolve(),fe=null,je.clear(),Re=void 0}function ed(o){let d=o.device.deviceId,c=o.abortSignal;if(c?.throwIfAborted(),!Rr)throw new t("Video recording is unavailable while the daemon shuts down.");if(Ee.has(d))throw new t(`VM snapshot restore is in progress on device ${d}. Retry video recording after it completes.`);if(je.has(d))throw new t(`Video recording start already in progress for device ${d}.`);je.set(d,o),Ue++;let p=new AbortController;return ze.add(p),{abortSignal:Ge(c,p.signal),complete:()=>{if(je.delete(d),Ue--,ze.delete(p),Ue===0)fe?.resolve(),fe=null}}}async function mJ(){Rr=!1;for(let o of ze)o.abort();if(Ue===0)return;if(!fe){let o;fe={promise:new Promise((c)=>{o=c}),resolve:o}}await fe.promise}function Ho(o,d){return{qualityPreset:d.qualityPreset??o.qualityPreset,targetBitrateKbps:d.targetBitrateKbps??o.targetBitrateKbps,maxThroughputMbps:d.maxThroughputMbps??o.maxThroughputMbps,fps:d.fps??o.fps,maxArchiveSizeMb:d.maxArchiveSizeMb??o.maxArchiveSizeMb,format:d.format??o.format,resolution:d.resolution??o.resolution}}function $o(o){return{qualityPreset:o.qualityPreset,targetBitrateKbps:o.targetBitrateKbps,maxThroughputMbps:o.maxThroughputMbps,fps:o.fps,maxArchiveSizeMb:o.maxArchiveSizeMb,format:o.format,resolution:o.resolution}}function td(o,d){if(o===void 0)return Hs;if(!Number.isFinite(o)||o<=0)throw new t("maxDuration must be a positive number of seconds.");let c=_e(d)?mK:$s;if(o>c)throw new t(`maxDuration must be <= ${c} seconds.`);return Math.round(o)}async function rd(o,d){if(d)return d;let{recordingRepository:c}=o,p=new Set(o.videoRecorderService.listActiveRecordingIds()),m=(await c.listRecordings({status:"recording"})).filter((f)=>p.has(f.recordingId));if(m.length===0)throw new t("No active video recording found. Provide recordingId.");if(m.length>1)throw new t("Multiple active video recordings found. Provide recordingId.");return m[0].recordingId}function id(o,d,c){if(!Number.isFinite(d)||d<=0)return;let{timer:p}=c,m=Math.max(1,Math.round(d*1000)),f=p.setTimeout(()=>{if(K!==c)return;bt(c,o).catch((w)=>{e.warn(`[VideoRecording] Failed to auto-stop recording ${o}: ${w}`)})},m);ke.set(o,{timer:p,handle:f})}function De(o){let d=ke.get(o);if(d)d.timer.clearTimeout(d.handle),ke.delete(o)}function od(o){if(Ae)return;let{retentionPolicy:d,timer:c}=o;if(d.ttlMs<=0)return;let p=c.setInterval(()=>{if(K!==o)return;nd(o).catch((m)=>{e.warn(`[VideoRecording] TTL retention sweep failed: ${m}`)})},d.sweepIntervalMs);Ae={timer:c,handle:p}}async function nd(o){let{recordingRepository:d,retentionPolicy:c,now:p}=o;if(c.ttlMs<=0)return[];let m=p().getTime()-c.ttlMs,f=await d.listRecordings({status:SE}),w=[];for(let R of f){let y=Date.parse(R.createdAt);if(Number.isNaN(y)||y>m)continue;try{if(await qo(R.recordingId,o))w.push(R.recordingId)}catch(P){e.warn(`[VideoRecording] Failed to prune expired recording ${R.recordingId}: ${P}`)}}if(w.length>0)e.info(`[VideoRecording] TTL sweep pruned ${w.length} recording(s) older than ${c.ttlMs} ms`);return w}function Bo(o,d,c,p){if(!Number.isFinite(c)||c<=0)return;let{timer:m,retentionPolicy:f}=p,w=m.setInterval(()=>{ad(o,d,c,p).catch((R)=>{e.warn(`[VideoRecording] In-progress size check failed for ${o}: ${R}`)})},f.inProgressCheckIntervalMs);Ie.set(o,{timer:m,handle:w})}function ge(o){let d=Ie.get(o);if(d)d.timer.clearInterval(d.handle),Ie.delete(o)}async function yt(o,d){if(K!==d)return;if(!d.videoRecorderService.listActiveRecordingIds().includes(o))return;let c=await d.recordingRepository.getRecording(o);if(!c||c.status!=="recording")return;if(K!==d)return;if(!d.videoRecorderService.listActiveRecordingIds().includes(o))return;De(o);let p=d.timer.setTimeout(()=>{if(K!==d)return;bt(d,o).catch((f)=>{e.warn(`[VideoRecording] Retained safety stop failed for ${o}: ${f}`)})},js);ke.set(o,{timer:d.timer,handle:p});let m=Math.floor((c.config.maxArchiveSizeMb??0)*1024*1024);ge(o),Bo(o,d.videoRecorderService.getInProgressFiles(o),m,d)}async function ad(o,d,c,p){if(K!==p||!Ie.has(o))return;let{statFileSize:m}=p,f=(y)=>m===ht?ht(y,!0):m(y),R=(await Promise.all(d.map(f))).reduce((y,P)=>y+P,0);if(K!==p||R<c)return;e.warn(`[VideoRecording] In-progress recording ${o} reached size cap (${R} >= ${c} bytes); stopping to protect disk.`),ge(o),await bt(p,o)}function sd(o){let d=wt.get(o);if(!d)return null;return Te.get(d)??null}function Lo(o,d){if(!Number.isFinite(d))return 0;return Math.max(0,Math.round(d-o.startedAtMs))}function Ao(o){let d=Math.max(0,Math.round(o));return Number((d/1000).toFixed(3))}function No(o,d,c){let p=Lo(o,c);o.highlights.push({description:d.description,shape:d.shape,appearedAtMs:p,disappearedAtMs:p+Bs})}function fK(o=i){return oo("highlight",o)}function Uo(o,d){if(o.highlights.length===0)return;let c=Date.parse(d),p=Lo(o,c);return o.highlights.map((m)=>{let f=Math.min(m.disappearedAtMs,p);return{description:m.description,shape:m.shape,timeline:{appearedAtSeconds:Ao(m.appearedAtMs),disappearedAtSeconds:Ao(f)}}}).sort((m,f)=>m.timeline.appearedAtSeconds-f.timeline.appearedAtSeconds)}function dd(o,d,c,p){let m=Date.parse(c);return{recordingId:o,deviceId:d.deviceId,platform:d.platform,startedAtMs:Number.isNaN(m)?p.now():m,highlights:[],timer:p,timers:new Set}}function gt(o){let d=Te.get(o);if(!d)return null;for(let c of d.timers)d.timer.clearTimeout(c);return d.timers.clear(),Te.delete(o),wt.delete(d.deviceId),d}function Go(o){let d=o.timing?.startTimeMs??0;if(!Number.isFinite(d)||d<0)throw new t("highlight.timing.startTimeMs must be >= 0.");return{startMs:d}}async function cd(o,d,c,p){let m={device:d,deviceId:d.deviceId,platform:d.platform},f=[],w=(y,P)=>{let A=Math.max(0,Math.round(y));if(A===0){f.push(P());return}let x=o.timer.setTimeout(()=>{P()},A);o.timers.add(x)},R=async(y)=>{try{let P=fK();await p.highlightClient.addHighlight(P,y.shape,m),No(o,y,p.now().getTime())}catch(P){e.warn(`[VideoRecording] Failed to add highlight: ${P}`)}};for(let y of c){let{startMs:P}=Go(y);w(P,()=>R(y))}if(f.length>0)await Promise.all(f)}async function ld(o){let{configRepository:d}=await U(),c=await d.getConfig(),p=c?$o(c):M.getVideoRecordingDefaults();return Ho(p,o)}async function ht(o,d=!1){try{return(await To.stat(o)).size}catch(c){if(d&&c instanceof Error&&"code"in c&&c.code==="ENOENT")e.debug(`[VideoRecording] Missing recording file at ${ZC(o)} during capture; the host file may be unavailable until finalization (Android adb pull).`);else e.warn(`[VideoRecording] Missing recording file at ${ZC(o)}`,c);return 0}}function Sr(o,d){let c=Date.parse(o),p=Date.parse(d);if(Number.isNaN(c)||Number.isNaN(p))return;return Math.max(0,p-c)}async function Me(o){let d=new Set([Rd.LATEST,Rd.ARCHIVE]);for(let c of o)d.add($O(c));await KF(Array.from(d))}async function hK(){let{configRepository:o}=await U(),d=await o.getConfig();if(d)return d;return hf(M.getVideoRecordingDefaults())}async function fJ(o){let d=await U(),{configRepository:c}=d;if(o===null){await c.clearConfig();let R=hf(M.getVideoRecordingDefaults()),y=await vr(d,R.maxArchiveSizeMb);return{config:R,evictedRecordingIds:y.evictedRecordingIds}}let p=await hK(),m=Ho($o(p),o),f=hf(m);await c.setConfig(f);let w=await vr(d,f.maxArchiveSizeMb);return{config:f,evictedRecordingIds:w.evictedRecordingIds}}async function ud(o,d,c){let{videoRecorderService:p,recordingRepository:m}=o,f=ft?.list(d.deviceId)??[];if(f.length>0)try{await ft.stop(d.deviceId)}catch(y){throw new pm(d.deviceId,f.map((P)=>P.recordingId),y)}if(c.throwIfAborted(),p.hasActiveRecordingForDevice(d.deviceId))throw new t(`Video recording already active for device ${d.deviceId}.`);let w=await m.listRecordings({status:"recording",deviceId:d.deviceId});c.throwIfAborted();let R=new Set(p.listActiveRecordingIds());if(w.some((y)=>R.has(y.recordingId)))throw new t(`Video recording already active for device ${d.deviceId}.`);if(w.length>0)await Promise.all(w.map((y)=>El(y.recordingId)))}function pd(o,d,c,{abortSignal:p,recordingDisplay:m}){return{outputName:o.outputName,config:d,device:o.device,maxDurationSeconds:c,abortSignal:p,display:o.display,recordingPanel:m?.panel,physicalDisplayId:m?.physicalId,audio:o.audio}}async function md(o,d,c,p){Er();let m={ownerSessionUuid:d.ownerSessionUuid,deviceId:d.device.deviceId};Q.set(c.recordingId,m);let{recordingRepository:f,videoRecorderService:w}=o,R=m.ownerSessionUuid;if(await f.insertRecording({recordingId:c.recordingId,captureTeardown:w.getCaptureTeardown(c.recordingId),deviceId:d.device.deviceId,platform:FO(d.device.platform,"Video recording"),status:"recording",outputName:c.outputName,fileName:c.fileName,filePath:c.outputPath,format:c.config.format,sizeBytes:0,durationMs:void 0,codec:void 0,createdAt:c.startedAt,startedAt:c.startedAt,endedAt:void 0,lastAccessedAt:c.startedAt,config:c.config,recordedPanel:c.recordedPanel,transitions:c.recordedPanel?[]:void 0,ownerSessionUuid:R,recorderDaemonSessionId:o.daemonSessionId}),p.throwIfAborted(),m.ownerSessionUuid!==R)await f.updateRecording(c.recordingId,{ownerSessionUuid:m.ownerSessionUuid})}function hd(o){if(FO(o.device.platform,"Video recording"),o.audio&&o.device.platform==="tvos")throw new t("audio is not supported for Apple TV recordings; record without audio.")}async function hE(o){hd(o),o={...o};let d=ed(o),c;try{let p=await U();d.abortSignal.throwIfAborted();let{videoRecorderService:m,timer:f}=p;await ud(p,o.device,d.abortSignal);let w=o.configOverrides??{},R=await ld(w),y=td(o.maxDurationSeconds,o.device.platform),P=o.highlights??[],A=await qs(p,o,d.abortSignal);for(let T of P)Go(T);if(c=await m.startRecording(pd(o,R,y,{abortSignal:d.abortSignal,recordingDisplay:A})),d.abortSignal.throwIfAborted(),xi(c,A),await md(p,o,c,d.abortSignal),A&&c.recordedPanel){let T=Mi(o.device,A,c.recordedPanel);Ws(c.recordingId,o.device,T,{startedAt:c.startedAt,timer:f})}let x=dd(c.recordingId,o.device,c.startedAt,f);if(Te.set(c.recordingId,x),wt.set(o.device.deviceId,c.recordingId),P.length>0)await cd(x,o.device,P,p);id(c.recordingId,y,p);let C=Math.floor((c.config.maxArchiveSizeMb??0)*1024*1024);return Bo(c.recordingId,m.getInProgressFiles(c.recordingId),C,p),d.abortSignal.throwIfAborted(),c}catch(p){if(c)try{await nP(c.recordingId,o.rollbackOptions?.())}catch(m){throw e.warn(`[VideoRecording] Failed to roll back recording ${c.recordingId}: ${m}`,m),AggregateError([p,m],`${r(p)}; recording rollback failed: ${r(m)}`)}throw p}finally{d.complete()}}async function wd(o,d,c){if(c?.hostOnly)Y.add(o),await yt(o,d).catch((p)=>{e.warn(`[VideoRecording] Failed to re-arm retained host-only rollback safety for ${o}: ${r(p)}`,p)});await Z(o,d)}async function nP(o,d){re.get(o)?.unsubscribe(),re.delete(o);let c=await U(),{videoRecorderService:p,recordingRepository:m}=c,f=p.listActiveRecordingIds().includes(o);if(f)try{await p.discardRecording(o,d)}catch(y){if(p.listActiveRecordingIds().includes(o))throw await wd(o,c,d),y;if(await Z(o,c),De(o),ge(o),(await m.getRecording(o))?.status==="recording")await El(o);throw y}await Z(o,c),De(o),ge(o);let w=await m.getRecording(o);if(w?.status==="recording")await El(o);if(gt(o),!f&&w)await Jo(w.filePath);if(await m.deleteRecording(o))await Me([o])}async function kl(o){let d=await U();return jo(d,o)}async function CU(o){let d=await U();return bt(d,o)}function bt(o,d){return Je(()=>jo(o,d))}async function jo(o,d){let c=await rd(o,d);if(Y.has(c))return zo(c,o);let p=Se.get(c);if(p)return p;let m=bd(c,o);Se.set(c,m);try{return await m}finally{if(Se.get(c)===m)Se.delete(c);if(Y.has(c)&&!o.videoRecorderService.listActiveRecordingIds().includes(c))Y.delete(c)}}async function yd(o,d){let c=Pe.get(o);if(c)throw await c,u(d,`Failed to stop video recording ${o}`)}async function bd(o,d){let{videoRecorderService:c,recordingRepository:p,now:m}=d,f=Q.get(o),w;try{w=await c.stopRecording(o)}catch(P){if(await yd(o,P),c.listActiveRecordingIds().includes(o)){await Z(o,d),e.warn(`[VideoRecording] Stop of ${o} could not confirm teardown; the service retained ownership, so its recording row stays active: ${P}`);try{await yt(o,d)}catch(x){e.warn(`[VideoRecording] Failed to re-arm retained safety enforcement for ${o}: ${x}`,x)}}else try{await Pr(o,d)}catch(x){e.warn(`[VideoRecording] Failed to clean up orphaned recording ${o} after a failed stop: ${x}`,x)}throw u(P,`Failed to stop video recording ${o}`)}await Z(o,d),await Mo(o,w,d),De(o),ge(o);let R=gt(o);if(R){let P=Uo(R,w.endedAt??m().toISOString());if(P)w.highlights=P}await p.updateRecording(o,wo(w,f?.ownerSessionUuid));let y=await vr(d,w.config.maxArchiveSizeMb,o);if(y.maxSizeBytes>0&&y.currentSizeBytes>y.maxSizeBytes)w.warnings=[...w.warnings??[],`Archive size ${y.currentSizeBytes} bytes exceeds limit ${y.maxSizeBytes} bytes after eviction; just-finished recording ${o} was kept.`];return await Me([w.recordingId]),{metadata:w,evictedRecordingIds:y.evictedRecordingIds}}async function El(o){let d=await U();await Pr(o,d)}async function hJ(o,d){let c=await U(),p=await c.recordingRepository.getRecording(o);if(!p||await c.statFileSize(p.filePath)>0)return;let m=await c.statFileSize(d);if(m<=0)return;let f=br.extname(d).slice(1).toLowerCase();if(f!=="mov"&&f!=="mp4"){e.warn(`[VideoRecording] Unsupported orphan capture container: ${f}`);return}let w=await c.codecProbe.codec(d);if(w===void 0){e.warn(`[VideoRecording] Could not probe the raw orphan capture at ${ZC(d)}`);return}let R=await we(c.codecProbe,d),y={filePath:d,fileName:br.basename(d),format:f,sizeBytes:m,codec:w,videoDurationMs:R};return await c.recordingRepository.updateRecording(o,y),await Me([o]),{...oe(p),...y}}async function Pr(o,d,c){let{recordingRepository:p,now:m,statFileSize:f}=d,w=Q.get(o);De(o),ge(o);let R=await p.getRecording(o);if(!R||R.status!=="recording"){await Z(o,d),re.get(o)?.unsubscribe(),re.delete(o),gt(o);return}await Mo(o,R,d,c);let y=m().toISOString(),P=gt(o),A=P?Uo(P,y):R.highlights;await p.updateRecording(o,{status:"interrupted",..._o(o,d,R.recorderDaemonSessionId)?{captureTeardown:c?.hostOnly||Y.has(o)?void 0:d.videoRecorderService.getCaptureTeardown(o)}:{},ownerSessionUuid:w?.ownerSessionUuid??R.ownerSessionUuid,endedAt:y,lastAccessedAt:y,sizeBytes:await f(R.filePath),durationMs:Sr(R.startedAt,y),highlights:A,recordedPanel:R.recordedPanel,transitions:R.transitions}),await Me([o])}async function gJ(o){let d=await U();await zo(o,d)}async function zo(o,d){let c=Pe.get(o);if(c)return c;Y.add(o);let p=Se.get(o);if(p&&!d.videoRecorderService.listActiveRecordingIds().includes(o))try{await Z(o,d);let f=await d.recordingRepository.getRecording(o);if(f&&f.status!=="recording")return{metadata:oe(f),evictedRecordingIds:[]};return await vd(o,p,d)}finally{Y.delete(o)}let m=Wo(o,d);Pe.set(o,m);try{return await m}finally{if(Pe.get(o)===m)Pe.delete(o);if(!d.videoRecorderService.listActiveRecordingIds().includes(o))Y.delete(o)}}async function vd(o,d,c){let p=!1;try{return await l(d,{timer:c.timer,timeoutMs:Tl,label:`Stop of replaced-device recording ${o}`,onTimeout:()=>{p=!0}})}catch(m){if(!p)throw m;return e.warn(`[VideoRecording] Settling replaced-device recording on the host: ${r(m)}`,m),Wo(o,c)}}async function Wo(o,d){let c=Q.get(o);if(await Z(o,d),d.videoRecorderService.listActiveRecordingIds().includes(o))try{await d.videoRecorderService.forceStopRecording(o,{hostOnly:!0})}catch(m){if(d.videoRecorderService.listActiveRecordingIds().includes(o))throw await Z(o,d),await yt(o,d).catch((f)=>{e.warn(`[VideoRecording] Failed to re-arm retained safety enforcement for ${o}: ${r(f)}`,f)}),new Ar(o,c?.deviceId,m);e.warn(`[VideoRecording] Host-only force-stop of ${o} failed: ${r(m)}`,m)}await Pr(o,d,{hostOnly:!0});let p=await d.recordingRepository.getRecording(o);if(!p)throw new t(`No video recording found for id ${o}`);return{metadata:oe(p),evictedRecordingIds:[]}}async function qO(o){let d=await U();try{await d.videoRecorderService.forceStopRecording(o,Y.has(o)?{hostOnly:!0}:void 0)}catch(c){throw await Z(o,d),u(c,`Failed to force-stop video recording ${o}`)}await Z(o,d)}class Ar extends t{recordingId;deviceId;constructor(o,d,c){super(`Teardown of video recording ${o}${d?` on ${d}`:""} is unconfirmed; the capture process may still be running on the device. Retry stopping the original recording or recover the device.`,{cause:c});this.recordingId=o;this.deviceId=d;this.name="VideoRecordingTeardownUnconfirmedError"}}async function yJ(o){let d=Q.get(o),c=await U();try{await c.videoRecorderService.forceStopRecording(o,Y.has(o)?{hostOnly:!0}:void 0)}catch(f){if(e.warn(`[VideoRecording] Force-stop of ${o} failed: ${r(f)}`,f),c.videoRecorderService.listActiveRecordingIds().includes(o)){await Z(o,c);try{await yt(o,c)}catch(w){e.warn(`[VideoRecording] Failed to re-arm retained safety enforcement for ${o}: ${r(w)}`,w)}throw new Ar(o,d?.deviceId,f)}}De(o),ge(o);let p=await c.recordingRepository.getRecording(o);if(!p||p.status!=="recording"){await Z(o,c);return}let m=c.now().toISOString();await c.recordingRepository.updateRecording(o,{status:"incomplete",captureTeardown:void 0,ownerSessionUuid:d?.ownerSessionUuid,endedAt:m,lastAccessedAt:m,sizeBytes:await c.statFileSize(p.filePath),durationMs:Sr(p.startedAt,m)}),await Me([o])}async function vJ(o,d){let c=sd(o.deviceId);if(!c)return;let{now:p}=await U();No(c,d,p().getTime())}async function Ka(o={}){let{recordingRepository:d}=await U();return(await d.listRecordings({status:"recording",deviceId:o.deviceId,platform:o.platform})).map((p)=>{let m=Q.get(p.recordingId);return m?{...p,ownerSessionUuid:m.ownerSessionUuid}:p})}function iP(){return K?.videoRecorderService.listActiveRecordingIds()??[]}function Er(){let o=new Set(iP());for(let d of Q.keys())if(!o.has(d))Q.delete(d)}function bJ(o,d){let c=je.get(o);if(c&&c.ownerSessionUuid===void 0)c.ownerSessionUuid=d;Er();let p=[];for(let[m,f]of Q)if(f.deviceId===o&&f.ownerSessionUuid===void 0){f.ownerSessionUuid=d;let{recordingRepository:w}=K;p.push(w.updateRecording(m,{ownerSessionUuid:d}).catch(()=>w.updateRecording(m,{ownerSessionUuid:d})))}return p.length>0?Promise.all(p).then(()=>{return}):void 0}function DU(o,d){return Er(),[...Q].filter(([,c])=>c.ownerSessionUuid===o&&c.deviceId===d).map(([c])=>c)}function VO(o){return iP().includes(o)?Q.get(o)??{}:void 0}async function SJ(o={}){let{recordingRepository:d}=await U();return(await d.listRecordings({status:SE,orderByLastAccessed:"desc",ownerSessionUuid:o.ownerSessionUuid})).map(oe)}async function Au(o,d){let{recordingRepository:c,now:p}=await U(),m=await c.getRecording(o,{ownerSessionUuid:d?.ownerSessionUuid,ownerBaseSessionUuid:d?.ownerBaseSessionUuid});if(!m||m.status==="recording")return null;let f=oe(m);if(d?.touch!==!1){let w=p().toISOString();await c.touchRecording(o,w),f.lastAccessedAt=w}return f}async function Sd(o,{statFileSize:d}){return o.sizeBytes>0&&await d(o.filePath)>0}var Eo=20;async function Co(o,d){for(let c of o)if(await Sd(c,d))return c;return}async function wJ(o={}){let d=await U(),c={status:SE,orderByStartedAt:"desc",ownerSessionUuid:o.ownerSessionUuid},p=await d.recordingRepository.listRecordings({...c,limit:Eo}),m=await Co(p,d);if(m)return{recording:oe(m)};if(p.length===Eo){let w=new Set(p.map((y)=>y.recordingId));p=await d.recordingRepository.listRecordings(c);let R=await Co(p.filter((y)=>!w.has(y.recordingId)),d);if(R)return{recording:oe(R)}}let f=p[0];return{recording:null,newestWithoutFile:f&&{recordingId:f.recordingId,status:f.status}}}async function qo(o,d){let{recordingRepository:c}=d,p=await c.getRecording(o);if(!p)return!1;if(p.status==="recording")throw Error(`Cannot delete active recording ${o}`);await Jo(p.filePath);let m=await c.deleteRecording(o);if(m)await Me([o]);return m}async function Jo(o){let d=br.dirname(o);if(!await na(d))return;await To.rm(d,{recursive:!0,force:!0})}async function vr(o,d,c){let p=Math.max(0,Math.floor(d*1024*1024)),{recordingRepository:m}=o,f=await m.listRecordings({status:SE,orderByLastAccessed:"asc"}),w=f.reduce((y,P)=>y+(P.sizeBytes??0),0);if(p===0||w<=p)return{evictedRecordingIds:[],currentSizeBytes:w,maxSizeBytes:p};let R=[];for(let y of f){if(y.recordingId===c)continue;if(w<=p)break;try{if(await qo(y.recordingId,o))R.push(y.recordingId),w-=y.sizeBytes??0}catch(P){e.warn(`[VideoRecording] Failed to evict recording ${y.recordingId}: ${P}`)}}if(w>p)e.warn(`[VideoRecording] Archive size ${w} bytes still exceeds limit ${p} bytes after eviction`);return{evictedRecordingIds:R,currentSizeBytes:w,maxSizeBytes:p}}async function gK(o){let{recordingRepository:d}=await U(),c=await d.getRecording(o);return c?{deviceId:c.deviceId,ownerSessionUuid:c.ownerSessionUuid}:null}async function OU(o,d){let{recordingRepository:c}=await U();return(await c.getRecording(o,{ownerSessionUuid:d?.ownerSessionUuid}))?.status}
|
|
26
|
-
export{Gn,lK,FO,uK,cJ,dJ,LO,pf,pK,BO,Rd,$O,_U,fE,mK,Tl,UO,lJ,uJ,xU,HO,pJ,mJ,fK,hK,fJ,hE,nP,kl,CU,El,hJ,gJ,qO,yJ,vJ,Ka,iP,bJ,DU,VO,SJ,Au,wJ,gK,OU};
|
|
27
|
-
|
|
28
|
-
//# debugId=1574FB5603090D4E64756E2164756E21
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{N7,F7,r4}from"./chunk-tyazf3sk.js";import{PassThrough as u}from"stream";var i=Symbol("swallowsErrorsAfterClose"),a=class{_readBuffer;_started=!1;_closed=!1;constructor(e=r4.stdin,r=r4.stdout,s){this._stdin=e,this._stdout=r,this._readBuffer=new N7({maxBufferSize:s?.maxBufferSize})}onclose;onerror;onmessage;_ondata=(e)=>{try{this._readBuffer.append(e),this.processReadBuffer()}catch(r){this.onerror?.(r),this.close().catch(()=>{})}};_onerror=(e)=>{this.onerror?.(e)};_onstdouterror=(e)=>{if(this._closed)return;this.onerror?.(e),this.close().catch(()=>{})};_onstdinclose=()=>{this.close().catch(()=>{})};async start(){if(this._started)throw Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0;for(let e of this._stdout.listeners("error"))if(e[i])this._stdout.off("error",e);if(this._stdin.readableEnded||this._stdin.destroyed)setImmediate(this._onstdinclose);this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror),this._stdin.on("end",this._onstdinclose),this._stdin.on("close",this._onstdinclose),this._stdout.on("error",this._onstdouterror)}processReadBuffer(){while(!0)try{let e=this._readBuffer.readMessage();if(e===null)break;this.onmessage?.(e)}catch(e){this.onerror?.(e)}}async close(){if(this._closed)return;if(this._closed=!0,this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.off("end",this._onstdinclose),this._stdin.off("close",this._onstdinclose),this._onstdouterror[i]=!0,this._stdin.listenerCount("data")===0)this._stdin.pause();this._readBuffer.clear(),this.onclose?.()}send(e){if(this._closed)return Promise.reject(Error("StdioServerTransport is closed"));return new Promise((r,s)=>{let d=F7(e),t=!1,o=(l)=>{if(t)return;t=!0,this._stdout.off("error",o),this._stdout.off("drain",n),s(l)},n=()=>{if(t)return;t=!0,this._stdout.off("error",o),this._stdout.off("drain",n),r()};if(this._stdout.once("error",o),this._stdout.write(d)){if(t)return;t=!0,this._stdout.off("error",o),r()}else if(!t)this._stdout.once("drain",n)})}};class c extends a{source;feed;constructor(e,r,s){super(r,s);this.source=e;this.feed=r}forwardSourceError=(e)=>{this.onerror?.(e)};async start(){await super.start(),this.source.on("error",this.forwardSourceError),this.source.pipe(this.feed,{end:!1})}async close(){this.source.off("error",this.forwardSourceError),this.source.unpipe(this.feed),await super.close()}}function z(e=process.stdin,r=process.stdout){return new c(e,new u,r)}export{z as createStdioServerTransport};
|
|
3
|
-
|
|
4
|
-
//# debugId=65CB929C27C4272564756E2164756E21
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{n,h,Ag,p,Dk}from"./chunk-79q5xsdc.js";var St=p(["android","ios","tvos","visionos"]),Gi=()=>p(["android","ios","watchos","tvos","visionos"]).optional().describe('Device platform. Name "watchos" to target an Apple Watch simulator, unless sessionUuid is a watch session. Name "tvos" for an Apple TV simulator; tools without tvOS support refuse it'),l4="Device label",u4=h().optional().describe("Opt in to raw accessibility extras metadata in structuredContent only (default off). Only meaningful with project:'full' or raw:true; text content always omits extras."),qx=()=>h().optional().describe("Return the complete result as an automobile:tool-output resource and a resource_link block instead of inline (default off). Only the headline fields stay inline; read the link to get the rest."),Tr={includeExtras:u4,raw:h().optional().describe("Return the raw view hierarchy instead of the compact skeleton"),project:p(["full","skeleton"]).optional().describe("Observation projection. 'skeleton' (default) returns a flat, actionable-only list (elementId/label/bounds/affordances) under `skeleton` in place of `viewHierarchy`; 'full' returns the raw view hierarchy under `viewHierarchy`. Each skeleton elementId/label is directly usable as a tapOn selector, except the collapsed keyboard row `<ime>` (drive it with sendKeys); re-request with raw/project:'full' to disambiguate.")},Vx=["packageId","package","packageName","appPackage","appPackageId","bundle","bundleId","bundleID","bundleIdentifier","application","applicationId","applicationIdentifier","app","appIdentifier","package_id","package_name","bundle_id","application_id"],p4=/^[A-Za-z0-9._-]+$/,m4=256,T=n().trim().refine((e)=>e.length>0&&e.length<=m4&&p4.test(e),{error:(e)=>`appId must be a reverse-DNS identifier such as com.example.app; got: ${e.input}`}),A=new WeakMap,k=new WeakMap,b=new WeakSet;function $t(e,t){return A.set(e,t),e}function rF(e,t){return k.set(e,t),e}function nF(e,t){let r=t?e.describe(t):e;return $t(r,(o)=>{if(t)o.description=t})}function iF(e){if(x(e),Object.hasOwn(e,"allOf")){let t=e.allOf;if(Array.isArray(t))z(e,t);delete e.allOf}for(let t of["anyOf","oneOf","not","if","then","else"])if(Object.hasOwn(e,t))throw Error(`Anthropic input schema has unsupported root ${t}`);if(e.type!=="object")throw Error("Anthropic input schema root must have type object")}function x(e){delete e.if,delete e.then,delete e.else,delete e.not;let t=e.oneOf;if(Array.isArray(t)){let r=e.anyOf;e.anyOf=Array.isArray(r)?[...r,...t]:t}delete e.oneOf,l(e.properties),l(e.$defs),l(e.definitions),P(e.items),u(e.prefixItems),c(e.additionalProperties),u(e.anyOf),u(e.allOf),c(e.contains),l(e.patternProperties),g(e,"anyOf"),g(e,"allOf")}function l(e){if(!d(e))return;Object.values(e).forEach(c)}function c(e){if(d(e))x(e)}function P(e){if(Array.isArray(e))e.forEach(c);else c(e)}function u(e){if(Array.isArray(e))e.forEach(c)}function g(e,t){let r=e[t];if(!Array.isArray(r))return;let o=r.filter((i)=>!d(i)||Object.keys(i).length>0);if(o.length===0)delete e[t];else e[t]=o}function z(e,t){let r=O(e.properties)??{},o=w(e);for(let i of t){if(!d(i))continue;let s=O(i.properties);if(s)Object.assign(r,s);o.push(...w(i))}if(Object.keys(r).length>0)e.properties=r;if(o.length>0)e.required=[...new Set(o)]}function w(e){let t=e.required;return Array.isArray(t)&&t.every((r)=>typeof r==="string")?t:[]}function O(e){return d(e)?e:void 0}function d(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function j7(e,t){A.get(e)?.(t)}function K7(e,t){k.get(e)?.(t)}function f4(e){if(b.has(e))return!0;return e instanceof Ag&&e.shape.deviceId===j.deviceId}function E(e){let t={},r=[],o=!0;for(let i of e){let s=i;if(s?.type!=="object"||typeof s.properties!=="object"||!Array.isArray(s.required)||s.required.length!==1||Object.keys(s.properties).length!==1){o=!1;break}let a=s.required[0];if(!(a in s.properties)){o=!1;break}t[a]=s.properties[a],r.push({required:[a]})}if(!o)return null;return{compact:{type:"object",additionalProperties:!1,properties:t},anyOf:r}}function LA(e,t){let r=e.properties;if(!r)return;for(let o of t){let i=r[o],s=i?.anyOf??i?.oneOf;if(!Array.isArray(s)||s.length<2)continue;let a=E(s);if(!a)continue;let{compact:f,anyOf:R}=a;if(typeof i.description==="string")f.description=i.description;f.anyOf=R,r[o]=f}}function Z(e,t){let r=Dk((o)=>m(o,t),e);if(f4(e))b.add(r);return r}function Ut(e){return Z(e,{appId:Vx}).superRefine((r,o)=>{y(r,o)})}function y(e,t,r=[]){if(Array.isArray(e)){e.forEach((o,i)=>y(o,t,[...r,i]));return}if(!v(e))return;for(let[o,i]of Object.entries(e)){let s=[...r,o];if(o==="appId"&&typeof i==="string"){let a=T.safeParse(i);if(!a.success)t.addIssue({code:"custom",path:s,message:a.error.issues[0]?.message??"appId must be a valid application ID"})}y(i,t,s)}}function m(e,t){if(Array.isArray(e))return e.map((o)=>m(o,t));if(!v(e))return e;let r={};for(let[o,i]of Object.entries(e))r[o]=m(i,t);for(let[o,i]of Object.entries(t)){if(r[o]===void 0){let s=i.find((a)=>r[a]!==void 0);if(s)r[o]=r[s]}for(let s of i)delete r[s]}if(typeof r.appId==="string")r.appId=r.appId.trim();return r}function v(e){if(typeof e!=="object"||e===null||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var S={sessionUuid:n().optional().describe("Session"),keepScreenAwake:h().optional()},j={platform:St.optional(),...S,device:n().optional().describe(l4),deviceId:n().optional()};function I(e,t){return e.extend({...t,...e.shape})}function tm(e){return I(e,S)}function ie(e){let t=I(e,j);if(!("deviceId"in e.shape))b.add(t);return t}
|
|
3
|
-
export{St,Gi,l4,u4,qx,Tr,Vx,p4,m4,$t,rF,nF,iF,j7,K7,f4,LA,Ut,tm,ie};
|
|
4
|
-
|
|
5
|
-
//# debugId=E77EF83F4D159B5764756E2164756E21
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{loe,Z9}from"./chunk-z916af47.js";import"./chunk-zd9vmkzn.js";import"./chunk-vs9r72ta.js";import"./chunk-mqc1d0eb.js";import"./chunk-nwm2pq5v.js";import"./chunk-a4k9rt7z.js";import"./chunk-8cghfzb2.js";import"./chunk-44bt78m9.js";import"./chunk-a2sc4jm0.js";import"./chunk-jhnbfj19.js";import"./chunk-9y5bcy28.js";import"./chunk-sjn0nj4p.js";import"./chunk-tyazf3sk.js";import"./chunk-bn64x5z5.js";import"./chunk-0e4gm1kj.js";import"./chunk-4fgdhcwx.js";import"./chunk-6d3mmqxt.js";import"./chunk-sns0c35v.js";import"./chunk-h3n4adc6.js";import"./chunk-32jpxz2y.js";import"./chunk-79q5xsdc.js";import"./chunk-ggtd5x5a.js";import"./chunk-z8t0v07j.js";import"./chunk-mf9spd4g.js";export{loe as formatConsoleOutput,Z9 as runDoctor};
|
|
3
|
-
|
|
4
|
-
//# debugId=A2C50B64FCEAFDAC64756E2164756E21
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{g,K,E,ft}from"./chunk-mf9spd4g.js";import{t,u}from"./chunk-9rkfyt6q.js";import{Pl,coe}from"./chunk-2v7tw1nj.js";var ke;function Jie(r){ke=r}function Le(){return ke?.()}import{setTimeout as st}from"timers/promises";class qR{timer;offsetMs;leadHighWaterMs=0;wallReportOffsetMs;constructor(r){this.timer=r}now(){let r=this.timer.now(),n=this.timer.monotonicNow?.();if(n===void 0)return r;let o=r-n;if(this.offsetMs===void 0)this.offsetMs=o,this.leadHighWaterMs=o;else if(o>this.leadHighWaterMs){if(this.timer.monotonicIncludesHostSleep!==!0)this.offsetMs+=o-this.leadHighWaterMs;this.leadHighWaterMs=o}else if(o<this.leadHighWaterMs-1000)this.leadHighWaterMs=o;return Math.round(n+this.offsetMs)}toWall(r){let n=this.timer.now()-this.now();if(this.wallReportOffsetMs===void 0||Math.abs(n-this.wallReportOffsetMs)>50)this.wallReportOffsetMs=n;return r+this.wallReportOffsetMs}}var Nr=2147483647;function at(r){return r!=="darwin"&&r!=="linux"}var Oe="1.4";function OY(r){if(r===void 0)return;if(r.split(".").slice(0,2).join(".")===Oe)return;return`Bun ${r} is not the release line (${Oe}.x) whose monotonic clock semantics were verified; whether performance.now() runs through host sleep may have changed, so host sleep and daemon stalls may be judged wrongly (#10962)`}class Zm{monotonicIncludesHostSleep;constructor(r=process.platform){this.monotonicIncludesHostSleep=at(r)}async sleep(r){return st(r)}setTimeout(r,n){return global.setTimeout(r,n)}clearTimeout(r){global.clearTimeout(r)}setInterval(r,n){return global.setInterval(r,n)}clearInterval(r){global.clearInterval(r)}now(){return Date.now()}monotonicNow(){return performance.now()}}var i=new Zm;var j=5000;function q(r,n=i,o=j){if(r.closed)return Promise.resolve();return new Promise((s,a)=>{let c=!1,d,y=n.setTimeout(()=>{b(()=>{r.destroy?.(),a(u(d??Error("Log stream close stalled"),`Log stream did not emit 'close' within ${o}ms \u2014 the file descriptor may still be held`))})},o),b=(p)=>{if(c)return;c=!0,r.off("error",v),r.off("close",S),n.clearTimeout(y),p()},v=(p)=>{d=p,queueMicrotask(()=>{if(!c)r.destroy?.(p)})},S=()=>b(()=>d?a(d):s());r.once("error",v),r.once("close",S),r.end()})}var{setTimeout:lt,clearTimeout:ct}=globalThis,ut=Date.now,Me={setTimeout:(r,n)=>lt(r,n),clearTimeout:(r)=>ct(r),now:()=>ut()};var qa={DEBUG:0,INFO:1,WARN:2,ERROR:3,NONE:4};function pe(r){if(r===void 0)return null;let n=r.trim().toLowerCase();if(n.length===0)return null;switch(n){case"debug":return qa.DEBUG;case"info":return qa.INFO;case"warn":case"warning":return qa.WARN;case"error":return qa.ERROR;case"none":case"silent":return qa.NONE;default:return null}}function me(r,n){return r.includes("--daemon-mode")?"daemon":`stdio-${n}`}var _e=new Set(["PASSWORD","TOKEN","SECRET","KEY","CREDENTIAL","AUTH","API_KEY","PRIVATE_KEY","ACCESS_TOKEN","REFRESH_TOKEN","CLIENT_SECRET","DATABASE_URL","DB_PASSWORD","GITHUB_TOKEN","NPM_TOKEN","AWS_SECRET_ACCESS_KEY"]),Ce=(r)=>{if(typeof r!=="object"||r===null)return String(r);let n=[];try{return JSON.stringify(r,function(o,s){if(typeof s==="object"&&s!==null){while(n.length>0&&n[n.length-1].holder!==this)n.pop();if(n.some((c)=>c.original===s))return"[circular]";let a={};for(let[c,d]of Object.entries(s))if(!_e.has(c.toUpperCase()))a[c]=d;return n.push({holder:a,original:s}),a}if(typeof s==="number"&&!Number.isFinite(s))return String(s);return s})}catch(o){return"[unserializable]"}},B=(r)=>r.replace(/[\r\n\t]/g," "),ge=(r,n,o,{message:s,args:a})=>{let c=new Date().toISOString(),d=B(s),y=a.length>0?` ${a.map((S)=>B(typeof S==="object"?Ce(S):String(S))).join(" ")}`:"",b=`${d}${y}`,v=b.length>1000?`${b.substring(0,1000)}... (truncated)`:b;if(r==="json")return JSON.stringify({timestamp:c,level:o.toLowerCase(),component:n,event:"log",message:v});return`${c} [${o}] ${v}`};var cn={hostLoad:void 0,gitMetadataClient:void 0,hostPortAvailabilityChecker:void 0,emulatorGrpcPortRegistry:void 0,deviceReadinessProxyDriverProvider:null,telemetryNoOpDefault:!1,auxSocketDir:void 0,bootAdmissionGatesDisabled:!1,processGenerationCaptureDisabled:void 0,logSinksDisabled:void 0};import oe from"fs";import Qe from"path";import{promises as H,readdirSync as Ne}from"fs";var Qm=H.readFile,Xie=H.writeFile,ef=H.stat,Jj=H.unlink;function KD(r,n){if(r===n)return 0;return r<n?-1:1}async function nr(r){return(await H.readdir(r)).sort(KD)}async function wr(r){return(await H.readdir(r,{withFileTypes:!0})).sort((n,o)=>KD(n.name,o.name))}function xi(r){return Ne(r).sort(KD)}function h$(r){return Ne(r,{withFileTypes:!0}).sort((n,o)=>KD(n.name,o.name))}import be from"fs";import k from"os";import h from"path";import{existsSync as dt}from"fs";import{homedir as pt}from"os";import fe from"path";var lb=g.DAEMON_LAUNCH_CWD.name,Xj="CORESIMULATOR_DEVICE_SET_PATH";function GD(r="/"){return Pl(()=>process.cwd(),()=>r)}function g$(r=pt()){if(r.length>0&&dt(r))return r;return"/"}function hd(r=GD(),n=process.env){let o=n[lb]?.trim();return o&&fe.isAbsolute(o)?o:r}function Ae(r,n=process.env){if(fe.isAbsolute(r))return r;return fe.resolve(hd(void 0,n),r)}function Zie(r=process.env){let n=r[Xj]?.trim();if(n)r[Xj]=Ae(n,r)}var Fe=448;function yp(r=process.env,n=k.homedir(),o=hd(void 0,r)){let s=ft(g.DATA_DIR,r);if(s&&s.length>0)return h.resolve(o,s);if(n&&n.length>0)return h.resolve(o,n,".auto-mobile");return h.join(k.tmpdir(),"auto-mobile")}function Zj(r=process.env,n=k.homedir(),o=hd(void 0,r)){let s=ft(g.LOG_DIR,r);if(s&&s.length>0)return h.resolve(o,s);return h.join(yp(r,n,o),dn.LOGS)}function Qie(r=process.env){if(E(K.NODE_ENV,r)!=="test")return;if([E(g.LOG_DIR,r),E(g.DATA_DIR,r)].some((o)=>o!==void 0&&o.trim().length>0))return;throw new t(`Unit test is about to write to the real AutoMobile logs directory (${Zj(r)}). Unit tests must never touch the user's ~/.auto-mobile: point AUTOMOBILE_DATA_DIR (or AUTOMOBILE_LOG_DIR) at a temp directory the test removes.`)}function Xe(r){return h.join(yp(),r)}function VR(r,n=k.userInfo().homedir,o=process.env){let s=ft(g.COORDINATION_DIR,o);if(s&&s.length>0){if(!h.isAbsolute(s))throw Error("AUTOMOBILE_COORDINATION_DIR must be an absolute path so all agents share one coordination directory.");return h.join(s,r)}if(n.length===0)throw Error("Unable to resolve a shared AutoMobile directory without a home directory. Set AUTOMOBILE_COORDINATION_DIR to a writable shared directory.");return h.join(h.resolve(n),".auto-mobile",r)}function Qj(r,n=k.userInfo().homedir){if(n.length===0)throw Error("Unable to resolve a host-global AutoMobile directory without an OS account home directory.");return h.join(h.resolve(n),".auto-mobile",r)}function bu(r,n,o=process.env,s=k.userInfo().homedir){let a=ft(g.ADB_SERVER_COORDINATION_DIR,o);if(a&&a.length>0){if(!h.isAbsolute(a))throw Error("AUTOMOBILE_ADB_SERVER_COORDINATION_DIR must be an absolute path so every daemon on one ADB server shares it.");return h.join(a,r,n)}if(s.length===0)throw Error("Unable to resolve the ADB-server coordination directory without an OS account home directory. Set AUTOMOBILE_ADB_SERVER_COORDINATION_DIR to a writable shared directory.");return h.join(h.resolve(s),".auto-mobile","adb-servers",r,n)}function Va(r){if(be.mkdirSync(r,{recursive:!0,mode:Fe}),be.lstatSync(r).isSymbolicLink())throw Error(`Refusing to use symbolic-link directory: ${r}`);if(process.platform!=="win32")be.chmodSync(r,Fe);return r}function si(r,n=process.env){return Va(h.join(yp(n),r))}function eoe(r){return Va(VR(r))}function e2(r=process.env,n=k.homedir()){try{return Va(Zj(r,n))}catch(o){if(o instanceof Error&&o.message.includes("symbolic-link directory"))throw u(o,"Refusing to use symbolic-link directory for AutoMobile logs");throw u(o,"Unable to initialize the AutoMobile log directory. Set AUTOMOBILE_LOG_DIR to a writable directory.")}}var dn={LOGS:"logs",TOOL_LOGS:"tool_logs",SCREENSHOTS:"screenshots",SNAPSHOTS:"snapshots",VIDEO_ARCHIVE:"video-archive",PERFORMANCE_TRACES:"performance-traces",NAVIGATION_SCREENSHOTS:"navigation-screenshots",VIEW_HIERARCHY:"view_hierarchy",OBSERVE_RESULTS:"observe_results",TOOL_OUTPUTS:"tool_outputs",WINDOW:"window",CACHE:"cache",STATE:"state"};import Y from"path";var ai=(r)=>{let n=U(r);return{delayForAttempt(o){return J(o),n}}},Bt=(r)=>{if(r.length===0)throw Error("sequenceBackoff requires at least one delay");let n=r.map(U);return{delayForAttempt(o){return J(o),n[Math.min(o-1,n.length-1)]}}},te=(r)=>{let n=U(r.initialDelayMs),o=r.multiplier??2,s=r.maxDelayMs===void 0?Number.POSITIVE_INFINITY:U(r.maxDelayMs);if(!Number.isFinite(o)||o<1)throw Error(`exponentialBackoff multiplier must be >= 1, got ${o}`);return{delayForAttempt(a){return J(a),U(Math.min(n*o**(a-1),s))}}},xo=(r)=>{if(typeof r==="number")return ai(r);if(mt(r))return Bt(r);if(typeof r==="function")return{delayForAttempt(n){return J(n),U(r(n))}};return r},mt=(r)=>Array.isArray(r),WR=(r,n)=>xo(r).delayForAttempt(n),J=(r)=>{if(!Number.isInteger(r)||r<1)throw Error(`Backoff attempt must be a positive integer, got ${r}`)},U=(r)=>{if(!Number.isFinite(r))throw Error(`Backoff delay must be finite, got ${r}`);return Math.max(0,Math.floor(r))};var bt=new Set(["EBUSY","EPERM"]),ye=4,yt=Bt([10,25,50]);async function ht(r,n){try{return await r.unlink(n),"removed"}catch(o){let s=o?.code;if(s==="ENOENT")return"removed";if(s!==void 0&&bt.has(s))return"transient";return r.logger?.debug(`log pruning could not remove ${n}: ${o}`,o),"failed"}}async function he(r,n){for(let o=1;o<=ye;o++){let s=await ht(r,n);if(s==="removed")return!0;if(s==="failed")return!1;if(o===ye)return r.logger?.debug(`log pruning gave up on ${n} after ${ye} transient unlink failures`),!1;await r.sleep(yt.delayForAttempt(o))}return!1}function vt(r){try{return process.kill(r,0),!0}catch(n){return n?.code!=="ESRCH"}}function Be(r,n){if(r===`${n}.log`)return!0;if(!r.startsWith(`${n}-`))return!1;let o=r.slice(n.length+1);return!/^launch-\d+\.log$/.test(o)}function St(r){let n=/^(?:stdio|server|daemon-launch)-(\d+)(?:-.*)?\.log$/.exec(r);return n?Number(n[1]):void 0}function He(r){return/^daemon-launch-\d+(?:-.*)?\.log$/.test(r)}function xt(r){return{unlink:r.unlink??Jj,sleep:r.sleep??((n)=>i.sleep(n)),logger:r.logger}}async function Rt(r,n){await he(r,`${n}.owner`)}async function At(r,n,o,{now:s,abandonedMaxAgeMs:a}){await coe(async()=>{let c=await ef(n);if(s-c.mtimeMs<=a)return;if(await he(r,n)&&He(o))await Rt(r,n)},()=>{return})}async function Ue(r){let n=r.now??Date.now(),o=r.isProcessAlive??vt,s=r.isDaemonRunning??(()=>!1),a=xt(r),c,d=()=>{if(c!==void 0)return c;let{daemonPidFiles:p,readDaemonOwner:x}=r;if(p&&x){try{let{pidFiles:R,uncertain:I}=p();c={owners:R.flatMap((A)=>{let f=x(A);return f===void 0?[]:[f]}),uncertain:I}}catch(R){r.logger?.debug(`daemon pidfile enumeration for log pruning failed: ${R}`,R),c={owners:[],uncertain:!0}}return c}return c={owners:[],uncertain:s()},c},y=(p)=>{let{owners:x,uncertain:R}=d(),I=Y.resolve(r.dir,p),A=x.filter((f)=>typeof f.launchLogPath==="string"&&Y.resolve(f.launchLogPath)===I);try{let f=r.readDaemonLaunchLogOwnerTombstone?.(I);if(f!==void 0&&!R)A.push(f)}catch(f){return r.logger?.debug(`launch-log ownership tombstone read failed: ${f}`,f),"unknown"}if(A.length>0)return A.some((f)=>Number.isInteger(f.pid)&&f.pid>0&&o(f.pid))?"alive":"dead";if(R)return"unknown";return x.some((f)=>f.launchLogPath===void 0)?"unknown":"dead"},b;try{b=await nr(r.dir)}catch(p){r.logger?.debug(`log pruning skipped because the log directory could not be read: ${p}`,p);return}let v=b.filter((p)=>p.endsWith(".log")),S=v.filter((p)=>Be(p,r.ownPrefix)).sort();if(S.length>r.maxOwnFiles)for(let p of S.slice(0,S.length-r.maxOwnFiles))await he(a,Y.join(r.dir,p));for(let p of v){if(!Pt(p,r.ownPrefix,o,y))continue;await At(a,Y.join(r.dir,p),p,{now:n,abandonedMaxAgeMs:r.abandonedMaxAgeMs})}}function Pt(r,n,o,s){if(Be(r,n))return!1;let a=St(r);if(a===void 0)return!1;if(o(a))return!1;if(He(r)){if(s(r)!=="dead")return!1}return!0}import wt from"fs";var Ve={create(r,n){return wt.createWriteStream(r,n)}};function We(r){let n=r?.trim().toLowerCase();return n==="text"||n==="json"?n:null}function Ge(r){let n=r?.trim().toLowerCase();return n==="file"||n==="stderr"||n==="both"?n:null}function Uk(r=process.env){return We(E(g.LOG_FORMAT,r))??"text"}function tf(r=process.env){return Ge(E(g.LOG_SINK,r))??"file"}function Tt(r,n){if(n===void 0)return r;try{return`${r}: ${n instanceof Error?n.stack??n.message:String(n)}`}catch(o){return r}}function Wi(r,n){let o=Tt(r,n);if(Uk()==="json"){process.stderr.write(`${JSON.stringify({timestamp:new Date().toISOString(),level:"error",component:"process",event:"log.emergency",message:o})}
|
|
3
|
-
`);return}process.stderr.write(`${o}
|
|
4
|
-
`)}class zR extends t{}function Sl(r){if((r&32)!==0)return"managed";if((r&16384)!==0||(r&1)!==0)return"primary";if((r&1024)!==0)return"secondary";return"unknown"}var t2=["RUNNING_MODERATE","RUNNING_LOW","RUNNING_CRITICAL","UI_HIDDEN","BACKGROUND","MODERATE","COMPLETE"];var r2={wallpaperRendering:"Home and Lock Screen wallpaper rendering; excludes widgets and Live Activities.",widgets:"Widget refresh, including app widgets; excludes wallpaper and Live Activities.",liveActivities:"Live Activities and Dynamic Island updates; excludes wallpaper and widgets.",healthServices:"HealthKit data and Health app background work. Health integrations become unavailable.",homeServices:"HomeKit accessories and automations. Home integrations become unavailable.",fitnessServices:"Apple Fitness, coaching, activity awards, and activity sharing.",familyServices:"Family Sharing, family approvals, and parental controls. Changes restriction behavior.",screenTime:"Screen Time limits and usage tracking. Changes restriction behavior.",newsServices:"Apple News background content.",weatherServices:"Apple Weather background forecasts.",tipsServices:"Apple Tips background content.",gameServices:"Game Center and saved-game synchronization; excludes controller input.",mapsSync:"Maps favorites, history, background updates, and suggested destinations; excludes MapKit rendering and location services.",advertising:"Promoted Apple content; excludes advertising privacy preferences and app integrity services.",diagnosticReporting:"Diagnostic collectors, feedback, location analytics, and call-quality reporting; reduces diagnostic evidence, not call transport.",siriAndAppIntents:"iOS Simulator Siri requests, Shortcuts actions, and App Intents; excludes speech services and proactive suggestions.",speechServices:"iOS Simulator speech recognition, dictation, and Siri speech synthesis; excludes Siri requests and App Intents orchestration.",mediaTranscoding:"iOS Simulator Photos image and video conversion; media imports and photo-picker conversions may fail.",photoAnalysis:"Background Photos analysis; may reduce photo search and recognition. Preserves library access, cloud transfers, and shared media-analysis infrastructure.",assistantSuggestions:"Siri inference, knowledge, and proactive suggestions; preserves speech, system voices, and shared language/model infrastructure.",appleIntelligence:"Apple Intelligence orchestration and generative experiences; system writing tools and intelligence integrations may become unavailable. Preserves shared model and speech services.",searchIndexing:"Spotlight and Settings search, including app-provided system indexes; excludes an app's own search service.",appStoreServices:"App Store installation/update services; excludes push and StoreKit payment services.",appleMediaSync:"Apple Music and subscribed/purchased media background services; excludes generic audio/video playback and StoreKit payments.",mailServices:"Apple Mail background services. Mail-based sign-in email workflows may be unavailable.",calendarServices:"Local Calendar database access; excludes server-side calendar integrations in apps.",reminderServices:"Apple Reminders database and background work; excludes reminders maintained by other apps.",personalDataSync:"Exchange, CalDAV, and CardDAV synchronization; preserves local Contacts database access.",safariSync:"Safari bookmark/history synchronization; preserves associated domains, shared credentials, browsing protections, and WebKit.",icloudSettingsSync:"iCloud system-settings synchronization and storage-plan recommendations; preserves accounts, credentials, CloudKit data, Drive, and Photos transfers.",messagingMaintenance:"Apple Messages history cleanup, attachment transfer, and FaceTime message storage; preserves identity, message database XPC helpers, and system calling services.",watchConnectivity:"Paired Watch and companion-device communication.",carPlay:"CarPlay vehicle connectivity.",tvRemote:"Apple TV discovery and remote control.",findMy:"Find My device-location services; excludes general location APIs.",continuity:"Nearby-device Continuity discovery; cross-device workflows may stop working. Preserves system share sheets.",walletServices:"Wallet, Apple Pay, digital identity, and merchant services. Payment sheets, including dependent StoreKit workflows, may fail.",businessServices:"Apple business messaging services; excludes ordinary app messaging.",backgroundSync:"General OS background app scheduling. Control is unsupported to preserve application behavior.",animations:"Android system animation scales: disabled sets all three to zero; enabled sets them to one. Excludes app-owned animation.",screensavers:"Android dream/screensaver activation; excludes wallpaper and widgets.",backup:"Android Backup Manager scheduling for the current user; disables backup and restore test behavior.",mailApp:"Android optional mail apps, including Gmail. Removes mail intent handlers; preserves other apps' messaging.",calendarApp:"Android Calendar app availability; preserves CalendarProvider.",contactsApp:"Android Contacts app availability; preserves ContactsProvider.",mapsApp:"Android Google Maps app; external navigation intents become unavailable.",videoApp:"Android YouTube app; native video links become unavailable.",musicApp:"Android YouTube Music app; preserves shared audio playback.",photosApp:"Android Google Photos app; changes cloud photo sources and choosers. Preserves MediaProvider and DocumentsUI.",assistantApp:"Android Google Search/Assistant app, including voice and home-search integrations.",digitalWellbeing:"Android Digital Wellbeing usage tracking, focus, and app limits.",printing:"Android print spooler and print recommendations; printing becomes unavailable.",accessibilityApps:"Optional Android accessibility apps. Active accessibility services are protected.",textToSpeech:"Android Google speech synthesis; speech-dependent functionality becomes unavailable.",storeApp:"Android Play Store app; installation, updates, billing and licensing may fail.",healthConnect:"Android Health Connect controller and backup app; health integrations become unavailable.",adServices:"Android AdServices API package; advertising/privacy APIs may fail. Does not remove mainline/APEX infrastructure.",onDevicePersonalization:"Android on-device personalization service package; dependent APIs may fail.",wallpaperApps:"Android wallpaper picker and optional live-wallpaper apps; changes wallpaper selection. Does not disable the shared wallpaper framework or widgets.",dialerApp:"Optional Android dialer apps. Default role holders remain protected.",messagesApp:"Optional Android SMS/Messages apps. Default role holders remain protected; excludes other apps' messaging.",googleServicesFramework:"Android Google Services Framework; aggressive control that can break Google account and push integrations.",googlePlayServices:"Android Google Play services; aggressive control that breaks dependent push, authentication, location and other integrations. Keep enabled for workflows that depend on those services.",icloudSync:"Broad iCloud/account synchronization. Control is unsupported; use the narrower icloudSettingsSync setting."};var Hk="value-redacted";function gt(r){return r===!0||r==="true"}function jR(r){return r===!1||r==="false"}var toe=["first","random","unique"];var Wa=Symbol("displayInventoryOutcome");var ub=[["closed","cover"],["opened","inner"],["rear_display","inner"]];function gd(r){return r.role!=="overlay"&&r.role!=="virtual"}function vp(r){return r?.panels?.length?r.panels:[{key:"0",role:"unknown",sizePx:{width:0,height:0}}]}function KR(r,n,o,s){let{hasPostures:a,pinned:c}=s,d=o.map(({key:p,role:x})=>x?`${p} (${x})`:p).join(", "),y=ub.find(([,p])=>p===n)?.[0],b=a&&n!=="cluster"?`; to make this panel available, change the device posture with ${y?`setPosture {posture: "${y}"}`:"setPosture using a supported posture"}`:"";return`Display "${r}" (${n}) ${n==="cluster"?"is not currently connected":"is not connected in the current posture"}. Connected panels: ${d}. Target a connected panel, omit display, or use display: "active"${b}.${c?" Clear the pin with setActiveDevice {display: null} (include deviceId and sessionUuid), or select another display explicitly.":""}`}function y$(r){if(typeof r!=="object"||r===null)return;let n=r;if(typeof n.width!=="number"||typeof n.height!=="number"||!Number.isInteger(n.width)||n.width<=0||!Number.isInteger(n.height)||n.height<=0)return;return{width:n.width,height:n.height}}function n2(r,n){if(!n)return;let o=r?.filter((s)=>s.sizePx.width===n.width&&s.sizePx.height===n.height);return o?.length===1?o[0].key:void 0}var ze=["tv","watch","automotive","xr-headset","xr-glasses"],X={tv:{systemImageTags:["android-tv","google-tv","google-tv-ps16k"],profileIdPattern:/^tv_/i,defaultProfileId:"tv_1080p"},watch:{systemImageTags:["android-wear-signed","android-wear","android-wear-cn"],profileIdPattern:/^wear(?:os)?_/i,defaultProfileId:"wearos_small_round"},automotive:{systemImageTags:["android-automotive-playstore","android-automotive"],profileIdPattern:/^automotive_/i,defaultProfileId:"automotive_1024p_landscape"},"xr-headset":{systemImageTags:["google-xr","android-xr-v3-playstore","android-xr-preview-playstore"],profileIdPattern:/^xr_headset/i,defaultProfileId:"xr_headset_device"},"xr-glasses":{systemImageTags:["ai-glasses"],profileIdPattern:/^(?:xr_glasses|ai_glasses)_/i,defaultProfileId:"ai_glasses_device"}},$e=ze.map((r)=>({formFactor:r,...X[r]}));function roe(r){return ze.includes(r)}function yd(r){return X[r].systemImageTags}function wl(r,n){if(r==="watch"&&n===!1)return"wearos_square";return X[r].defaultProfileId}function noe(r){let n=r?.trim()??"";if(!X.watch.profileIdPattern.test(n))return;if(/round/i.test(n))return!0;return/square|rect/i.test(n)?!1:void 0}function It(r){let n=r.systemImageTag?.trim().toLowerCase(),o=r.profileId?.trim(),s=$e.find((a)=>n?a.systemImageTags.includes(n):!1);if(s)return s.formFactor;return $e.find((a)=>o?a.profileIdPattern.test(o):!1)?.formFactor}function rf(r){let n=/pixel[_ ]tablet|nexus (?:9|10)/i.test(r.profileId??"")?"tablet":void 0;return YD({...r,hint:n,deviceType:r.profileId})}function ve(r){return typeof r==="number"&&Number.isFinite(r)&&r>0}function YD(r){let n=It({systemImageTag:r.systemImageTag,profileId:r.deviceType});if(n)return n;let o=`${r.deviceType??""} ${r.hint??""}`;if(/fold|flip/i.test(o))return"foldable";let s=r.hint?.trim().toLowerCase();if(s!==void 0&&Dt.has(s))return s;return Et(r)}var Dt=new Set(["phone","tablet","tv","watch","automotive","xr-headset","xr-glasses"]);function Et(r){let{width:n,height:o,density:s}=r;if(!ve(n)||!ve(o)||!ve(s))return"unknown";return Math.hypot(n,o)/s>=7?"tablet":"phone"}var co={watchos:"watchOS",tvos:"tvOS",visionos:"visionOS"},pb={android:"Android",ios:"iOS",...co};function dr(r){return r==="android"||r==="ios"}function bp(r,n){return n===void 0?dr(r):r===n}function Q(r,n){if(dr(r))return r;throw kt(n,r)}function MY(r,n){return r==="either"?r:Q(r,n)}function kt(r,n){return new t(`${r} is not supported on ${co[n]} yet. Target an Android or iOS device instead.`)}var JD=1,XD=1798000,ZD=1,QD=1000;function qk(r){return r!==void 0&&(r.toolType==="eraser"||r.pressure!==void 0&&r.pressure!==1||r.tilt!==void 0||r.orientation!==void 0||(r.buttons?.length??0)>0)}function ioe(r){return(r??[]).reduce((n,o)=>n|(o==="primary"?32:64),0)}function Se(r){return r.$??r}function Rl(r){let n=r.node;if(Array.isArray(n))return n;return n&&typeof n==="object"?[n]:[]}function Ft(r){return r.bounds??Se(r).bounds}function Ke(r){return r!==null&&typeof r==="object"&&!Array.isArray(r)}function ooe(r){return Ke(r)&&"hierarchy"in r&&Ke(r.hierarchy)}function Su(r){if(!r)return null;let{nativeScale:n,pixelWidth:o,pixelHeight:s}=r;if(typeof n!=="number"||!Number.isFinite(n)||n<=0||typeof o!=="number"||!Number.isFinite(o)||o<=0||typeof s!=="number"||!Number.isFinite(s)||s<=0)return null;return{nativeScale:n,pixelWidth:o,pixelHeight:s}}function v$(r){return Su(r)??{}}var NY="immediate";var Lt="device_service_disabled";class eO extends t{code=Lt;retryable=!1;tool;resource;labels;disabledLabels;unavailable;howToEnable;deviceId;constructor(r){let n=`Call setDeviceResources with {resources:{${r.resource}:"enabled"}} (enable this default-disabled tool with setToolEnabled or --enable-tool setDeviceResources), or provision/start the simulator without {resources:{${r.resource}:"disabled"}}.`;super(`${r.tool} requires resource ${r.resource} (${r.labels.join(", ")}); disabled labels: ${r.disabledLabels.join(", ")}. Unavailable: ${r.unavailable}. ${n}`);this.name="DeviceServiceDisabledError",this.tool=r.tool,this.resource=r.resource,this.labels=[...r.labels],this.disabledLabels=[...r.disabledLabels],this.unavailable=r.unavailable,this.howToEnable=n,this.deviceId=r.deviceId}toPayload(){return{code:this.code,tool:this.tool,resource:this.resource,labels:this.labels,disabledLabels:this.disabledLabels,unavailable:this.unavailable,howToEnable:this.howToEnable,retryable:this.retryable,deviceId:this.deviceId}}}var Ot="unsafe_device_resource_combination";class Sp extends t{code=Ot;retryable=!1;hazards;howToProceed;constructor(r){super(`Unsafe iOS device resource combination: ${r.map((o)=>`${o.id} (${o.resources.join(", ")}): ${o.reason}`).join("; ")}. Drop or re-enable at least one of the listed resources in each unsafe combination before retrying.`);this.name="UnsafeDeviceResourceCombinationError",this.hazards=r.map((o)=>({...o,resources:[...o.resources],appliesTo:[...o.appliesTo]})),this.howToProceed="Drop or re-enable at least one of the listed resources in each unsafe combination before retrying."}toPayload(){return{code:this.code,retryable:this.retryable,hazards:this.hazards,howToProceed:this.howToProceed}}}function Mt(r){return typeof r==="object"&&r!==null&&"unref"in r&&typeof r.unref==="function"}function _t(r){let{timer:n,timeoutMs:o,deadline:s,unref:a,label:c,timeoutError:d,onTimeout:y}=r;if(s===void 0&&o===void 0)return;let b=o??0,v=()=>{};return{promise:new Promise((p,x)=>{let R=(f)=>{x(d?.()??new t(f)),y?.()},I=(f)=>{if(a&&Mt(f))f.unref()};if(s){v=s.whenExpired(n,()=>R(`${c} timed out`),I);return}let A=n.setTimeout(()=>R(`${c} timed out after ${b}ms`),b);I(A),v=()=>n.clearTimeout(A)}),cancel:()=>v()}}function je(r,n,o){let s=r.reason;if(o&&(s===void 0||s instanceof DOMException&&s.name==="AbortError"))return new t(`${n} cancelled`);return s===void 0?new DOMException("The operation was aborted.","AbortError"):s}function Ct(r){return Array.isArray(r)}function Je(r){return Ct(r)?r:[r]}function Nt(r){return typeof r==="function"?[r()]:Je(r)}function qe(r){for(let n of r)n.then(void 0,()=>{})}async function l(r,{timer:n,timeoutMs:o,deadline:s,unref:a=!1,signal:c,label:d,relabelDefaultAbort:y=!1,timeoutError:b,onTimeout:v}){if(typeof r!=="function")qe(Je(r));if(c?.aborted)throw je(c,d,y);let S,p=c?new Promise((R,I)=>{let A=()=>I(je(c,d,y));if(c.addEventListener("abort",A,{once:!0}),S=()=>c.removeEventListener("abort",A),c.aborted)A()}):void 0,x=_t({timer:n,timeoutMs:o,deadline:s,unref:a,label:d,timeoutError:b,onTimeout:v});try{let R=Nt(r);return qe(R),await Promise.race([...R,...p?[p]:[],...x?[x.promise]:[]])}finally{x?.cancel(),S?.()}}import{readFileSync as Ht}from"fs";function xe(r,n,o){try{r?.(n,o)}catch(s){}}var Ut=50;function Vt(r,n){let o=`${r} (`,s=n.lastIndexOf(")");if(!n.startsWith(o)||s<o.length)return;let a=n.slice(s+1);if(!/^\s/.test(a))return;let c=a.trim().split(/\s+/),[d,...y]=c;if(c.length<Ut||d?.length!==1||y.some((b)=>!/^-?\d+$/.test(b)))return;return d}function Wt(r){return r?.code==="ESRCH"}function nt(r,n={}){if(!Number.isInteger(r)||r<=0)return!1;let o=n.signalProcess??((c)=>{process.kill(c,0)});try{o(r)}catch(c){return xe(n.debugLog,`src/daemon/daemonFiles.ts liveness check failed: ${c}`,c),!Wt(c)}if((n.platform??process.platform)!=="linux")return!0;let s;try{s=(n.readProcStat??((d)=>Ht(`/proc/${d}/stat`,"utf-8")))(r)}catch(c){return xe(n.debugLog,`src/daemon/daemonFiles.ts procfs liveness check failed: ${c}`,c),!0}let a=Vt(r,s);if(a===void 0)return xe(n.debugLog,`src/daemon/daemonFiles.ts could not parse /proc/${r}/stat`,s),!0;return a!=="Z"&&a!=="X"}class Z{policy;pending=new Set;timeout;episode;observing=!0;constructor(r){this.policy=r}get stalled(){return this.episode!==void 0}divert(){if(this.episode)this.episode.diverted++}track(r){return new Promise((n,o)=>{let s={issuedAt:this.policy.timer.now(),settle:n,fail:o};this.pending.add(s),this.armOldest();try{r((a)=>this.complete(s,a))}catch(a){this.complete(s,a)}})}suspend(){this.observing=!1,this.clearTimeout()}retire(r){this.suspend();for(let n of this.pending)if(r)n.fail(r);else n.settle(!1);this.pending.clear(),this.episode=void 0}complete(r,n){if(!this.pending.delete(r))return;if(n){if(this.episode)this.episode.failed++;r.fail(n)}else r.settle(!0);if(!this.observing)return;if(this.episode&&!n&&!this.oldestExpired())this.resume();if(this.pending.size===0&&!this.episode)this.clearTimeout();this.armOldest()}oldest(){return this.pending.values().next().value}oldestExpired(){let r=this.oldest();return r!==void 0&&this.policy.timer.now()-r.issuedAt>=this.policy.timeoutMs}resume(){let r=this.episode;if(this.episode=void 0,this.clearTimeout(),r)this.policy.resumed(this.policy.timer.now()-r.detectedAt,r.diverted)}armOldest(){let r=this.oldest();if(!this.observing||this.timeout!==void 0||this.episode||!r)return;this.arm(Math.max(0,this.policy.timeoutMs-(this.policy.timer.now()-r.issuedAt)))}arm(r){if(this.timeout=this.policy.timer.setTimeout(()=>{this.timeout=void 0,this.onDeadline()},r),typeof this.timeout==="object"&&typeof this.timeout.unref==="function")this.timeout.unref()}onDeadline(){if(this.episode){let r=this.policy.timer.now()-this.episode.detectedAt,n=this.pending.size+this.episode.failed;this.retire(),this.policy.abandoned?.(r,n);return}if(!this.oldestExpired()){this.armOldest();return}this.episode={detectedAt:this.policy.timer.now(),diverted:0,failed:0},this.policy.stalled(this.pending.size);for(let r of this.pending)r.settle(!1);if(this.policy.abandonMs!==void 0)this.arm(this.policy.abandonMs)}clearTimeout(){if(this.timeout!==void 0)this.policy.timer.clearTimeout(this.timeout);this.timeout=void 0}}function FY(){return N==="json"}var V=pe(E(g.LOG_LEVEL))??qa.INFO,N=Uk(),M=tf(),Re=!1,z=Promise.resolve(),W=(r)=>{z=z.then(()=>r)},_=M==="stderr"?void 0:e2(),F=me(process.argv,process.pid),T=_?Qe.join(_,`${F}.log`):void 0,Gt=(r,n)=>{r.on("error",(o)=>{try{Wi(`Log stream error on ${n}`,o)}catch(s){}if(m===r)m=void 0;w.get(r)?.retire(o),C(r),queueMicrotask(()=>r.destroy?.())})},L=new Map,C=(r,n=i)=>{if(r.closed)return;let o=L.get(r);if(o)o.timer.clearTimeout(o.timeoutHandle),r.off("close",o.onClose);let s=o&&n===i?o.timer:n,a=()=>{let d=L.get(r);if(d?.onClose===a)d.timer.clearTimeout(d.timeoutHandle),r.off("close",a),L.delete(r)},c=s.setTimeout(a,j);L.set(r,{timer:s,timeoutHandle:c,onClose:a}),r.once("close",a)},ue=(r)=>{for(let[n,o]of L)if(n.closed)o.onClose();if(L.size>0)return;try{let n=Ve.create(r,{flags:"a"});return Gt(n,r),n}catch(n){Wi(`Failed to open log stream ${r}`,n);return}},m=T?ue(T):void 0;function Te(){if(!_||!T)return;return{dir:_,path:T}}var Ye=20000,ie=5000,$t=30000,Ie=Me,w=new WeakMap,se=0,P;var zt=10485760,Kt=10,jt=86400000,ae;function LY(r){if(ae=r,re&&!re.registeredSweepStarted)et(re)}function de(){if(!ae)throw Error("Log retention namespace source is not registered");return ae}var qt=()=>{try{let r=de(),{pidFiles:n,uncertain:o}=r.listDaemonPidFilesSync();if(o)return!0;return n.some((s)=>{let a=r.readPidFileDataSync(s);return a?nt(a.pid):!1})}catch(r){return e.debug(`daemon liveness probe for log pruning failed: ${r}`,r),!0}},Jt=()=>{try{return de().listDaemonPidFilesSync()}catch(r){return e.debug(`daemon pidfile enumeration for log pruning failed: ${r}`,r),{pidFiles:[],uncertain:!0}}},Yt=(r)=>de().readDaemonOwnerForRetentionSync(r),Xt=(r)=>de().readDaemonLaunchLogOwnerTombstoneSync(r),Qt={daemonPidFiles:Jt,readDaemonOwner:Yt,readDaemonLaunchLogOwnerTombstone:Xt,isDaemonRunning:qt},Ze=()=>{if(!_)return Promise.resolve();return Ue({dir:_,ownPrefix:F,maxOwnFiles:Kt,abandonedMaxAgeMs:jt,...Qt})};function et(r){if(r.timeout!==void 0)return;r.timeout=r.timer.setTimeout(()=>{r.timeout=void 0,r.pending=r.pending.then(async()=>{if(r!==re||r.registeredSweepStarted)return;let n=ae!==void 0;if(r.fallbackStarted&&!n)return;r.fallbackStarted=!0,r.registeredSweepStarted=n;try{await r.prune()}catch(o){e.warn("Startup log pruning failed",o)}})},0)}function Zt(r,n){let o={timer:r,prune:n,pending:Promise.resolve(),fallbackStarted:!1,registeredSweepStarted:!1};return et(o),o}var re=_?Zt(i,Ze):void 0,er=async(r)=>{w.get(r)?.suspend();try{return await q(r),!0}catch(n){let o=r.closed===!0;if(!o)C(r);return await D("Failed to close log stream before rotation",n),o}},tr=async(r)=>{let n=m;if(m=void 0,n){if(!await er(n)){ne=Number.POSITIVE_INFINITY;return}}let o=new Date().toISOString().replace(/:/g,"-"),s=Qe.join(r.dir,`${F}-${o}.log`);if(oe.existsSync(r.path))await oe.promises.rename(r.path,s);m=ue(r.path),await Ze()},O,rr=async(r)=>{if(!oe.existsSync(r.path))return;if((await ef(r.path)).size>=zt)await tr(r)},or=(r)=>{if(!O)O=rr(r).finally(()=>{O=void 0});return O},De=async(r,n)=>{if(L.size===0&&(m?.destroyed||!m?.writable))m=ue(r.path);await D("Log rotation failed",n)},ne=Number.POSITIVE_INFINITY,ir=32768,sr=async(r)=>{if(ne+=r,ne<ir)return!0;ne=0;let n=Te();if(!n||!m)return!0;try{return await ot(or(n))}catch(o){return await De(n,o),!0}};var le=(r)=>new Promise((n,o)=>{process.stderr.write(`${r}
|
|
5
|
-
`,(s)=>{if(s)o(s);else n()})}),D=async(r,n)=>{if(M==="file")return;let o=`${r}: ${B(String(n))}`,s=N==="json"?JSON.stringify({timestamp:new Date().toISOString(),level:"error",component:F,event:"log.write_failed",message:o}):o;try{await le(s)}catch(a){}},tt=(r)=>{try{oe.writeSync(process.stderr.fd,`${r}
|
|
6
|
-
`)}catch(n){}},Ee=(r,n,o)=>{we=r.now(),tt(N==="json"?JSON.stringify({timestamp:new Date(r.now()).toISOString(),level:"error",component:F,event:n,message:B(o)}):B(o))},rt=(r,n)=>{W(it(ge(N,F,"WARN",{message:`Log sink ${T} resumed after ${r}ms; ${n} line(s) were diverted while it was stalled`,args:[]})).catch((o)=>D("Failed to write log sink recovery",o)))},ar=(r,n,o,s)=>{if(Ee(n,"log.sink_abandoned",`Log sink ${T} abandoned after ${o}ms stalled; ${s} line(s) dropped`),m===r)m=void 0;C(r,n);try{r.destroy?.()}catch(a){}},lr=(r)=>{let n=w.get(r);if(!n){let o=Ie;if(n=new Z({timer:o,timeoutMs:ie,abandonMs:$t,stalled:(s)=>Ee(o,"log.sink_stalled",`Logging to ${T} stalled: no write completed within ${ie}ms; ${s} line(s) pending`),resumed:rt,abandoned:(s,a)=>ar(r,o,s,a)}),se>0)n.suspend();w.set(r,n)}return n},ot=(r)=>{if(P?.operation===r)return P.completion;let n=Ie,o=new Z({timer:n,timeoutMs:ie,stalled:()=>Ee(n,"log.sink_stalled",`Logging to ${T} stalled: log rotation did not finish within ${ie}ms`),resumed:rt});if(se>0)o.suspend();let s=o.track((a)=>{let c=(d)=>{if(a(d),P?.guard===o)P=void 0};r.then(()=>c(),async(d)=>{let y=o.stalled;c(d);let b=Te();if(y&&b)await De(b,d)}).catch((d)=>D("Failed to recover log rotation",d))});return P={operation:r,guard:o,completion:s},s},Pe=(r=!1)=>{if(r)P?.guard.retire();else P?.guard.suspend();P=void 0},G=(r)=>{if(P?.guard.divert(),m)w.get(m)?.divert();if(M==="file")tt(r)},ce=()=>P?.guard.stalled===!0||m!==void 0&&w.get(m)?.stalled===!0,we,BY=(r)=>ce()||we!==void 0&&Ie.now()-we<=r,cr=async()=>{while(O)try{if(!await ot(O))return!1}catch(r){let n=Te();if(n)await De(n,r)}return!0},ur=async(r)=>{if(!T)return!1;if(ce())return G(r),!1;if(O&&!await cr())return G(r),!1;if(!m)m=ue(T);if(m&&!await sr(Buffer.byteLength(r)+1))return G(r),!1;if(ce())return G(r),!1;return!0},it=async(r)=>{if(!await ur(r))return;if(ce()){G(r);return}let n=m;if(!n){if(M==="file")await le(r);return}try{await lr(n).track((o)=>{n.write(r+`
|
|
7
|
-
`,o)})}catch(o){if(M==="file"){await le(r);return}throw o}},pr=async(r)=>{if(M==="stderr"||M==="both")await le(r)},mr=(r)=>{if(Re&&N==="text")try{process.stdout.write(`${r}
|
|
8
|
-
`)}catch(n){}},ee=async(r,n,o)=>{if(cn.logSinksDisabled?.())return;try{let s=Le(),a=s?`trace=${s.traceId} ${n}`:n,c=ge(N,F,r,{message:a,args:o}).replace(/[\r\n\t]/g," ");mr(c),await Promise.all([it(c),pr(c)])}catch(s){await D("Failed to write log",s)}},gr=async(r=i)=>{if(Pe(),m){let n=m;w.get(n)?.suspend(),m=void 0,C(n,r);try{await q(n,r)}finally{C(n,r)}}},e={setLogLevel(r){V=r},getLogLevel(){return V},enableStdoutLogging(){Re=N==="text"},disableStdoutLogging(){Re=!1},debug(r,...n){if(V<=qa.DEBUG)W(ee("DEBUG",r,n).catch((o)=>D("Failed to write debug log",o)))},info(r,...n){if(V<=qa.INFO)W(ee("INFO",r,n).catch((o)=>D("Failed to write info log",o)))},warn(r,...n){if(V<=qa.WARN)W(ee("WARN",r,n).catch((o)=>D("Failed to write warn log",o)))},error(r,...n){if(V<=qa.ERROR)W(ee("ERROR",r,n).catch((o)=>D("Failed to write error log",o)))},async flush(){await z},close(){Pe();let r=m;if(m=void 0,r)w.get(r)?.suspend(),C(r),r.end()},async closeAfterFlush(r=i){if(se++,P?.guard.suspend(),m)w.get(m)?.suspend();let n,o=new AbortController;try{n=r.setTimeout(()=>{Pe(!0);let s=m;if(s)w.get(s)?.retire(),m=void 0,C(s,r),s.destroy?.();z=Promise.resolve(),o.abort(u(Error("Pending log writes stalled"),`Log writes did not flush within ${Ye}ms`))},Ye),await l(z,{timer:r,signal:o.signal,label:"Log writes"})}finally{if(se--,n!==void 0)r.clearTimeout(n)}await gr(r)}};
|
|
9
|
-
export{cn,Jie,qR,Nr,OY,Zm,i,qa,Qm,Xie,ef,Jj,KD,nr,wr,xi,h$,lb,Xj,GD,g$,hd,Ae,Zie,yp,Zj,Qie,Xe,VR,Qj,bu,Va,si,eoe,e2,dn,ai,Bt,te,xo,WR,Uk,tf,Wi,zR,Sl,t2,r2,Hk,gt,jR,toe,Wa,ub,gd,vp,KR,y$,n2,roe,yd,wl,noe,rf,YD,co,pb,dr,bp,Q,MY,JD,XD,ZD,QD,qk,ioe,Se,Rl,Ft,ooe,Su,v$,NY,eO,Sp,l,nt,FY,LY,BY,e};
|
|
10
|
-
|
|
11
|
-
//# debugId=52BA9380D29B656164756E2164756E21
|