agent-device 0.21.19 → 0.21.20
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/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.19.apk → agent-device-android-ime-helper-0.21.20.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.20.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.19.manifest.json → agent-device-android-ime-helper-0.21.20.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.19.apk → agent-device-android-snapshot-helper-0.21.20.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.19.manifest.json → agent-device-android-snapshot-helper-0.21.20.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +14 -16
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +40 -14
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +20 -5
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +2 -15
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +10 -25
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -18
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/alert.js +1 -0
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/app-launch.js +2 -2
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/archive.js +2 -2
- package/dist/src/browser-launch.js +1 -1
- package/dist/src/cache.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +287 -301
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +14 -2
- package/dist/src/{scroll-command.d.ts → cloud-artifacts.d.ts} +242 -238
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-tools.js +2 -2
- package/dist/src/command.js +1 -1
- package/dist/src/config.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-transport.js +1 -1
- package/dist/src/daemon-registration.js +1 -1
- package/dist/src/debug-symbols-facade.js +3 -3
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/display-inventory.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/interactor.js +5 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/launch-confirmation.js +1 -0
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +50 -42
- package/dist/src/mechanics.js +16 -16
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +2 -2
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/provider-session-ownership.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/registry.js +20 -4
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/runner-cache-metadata.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +1 -1
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-session-types.js +1 -1
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner-startup-transport.js +1 -1
- package/dist/src/runner-xctestrun.js +1 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/runtime10.js +1 -1
- package/dist/src/runtime2.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/screenshot-result.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/sdk-contracts.d.ts +2 -0
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-selectors.d.ts +4 -4
- package/dist/src/session2.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/toolchain-probe.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/video.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.19.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.19.apk.sha256 +0 -1
package/dist/src/mechanics.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{N as t,P as n,Q as r,R as i,_ as a,et as o,q as s,y as c,z as l}from"./sdk-contracts.js";import"./capture.js";import{O as u}from"./sdk-batch-runner.js";import{a as d,d as f,i as p,l as
|
|
2
|
-
`).map(e=>e.trim()).filter(Boolean)}const
|
|
3
|
-
`):void 0}function Sn(e,t){let n=t[0];if(!n)return;let r=Cn(e,n.index);for(let n of t.slice(1)){let t=new Set(Cn(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r.at(-1)}function Cn(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function wn(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function Tn(e){let t=e.bundleId??``;return Qt.has(t)||rn.test(e.identifier??``)}function En(e){let t=e.bundleId??``;return en.has(t)&&an.test(D(e))}function Dn(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||nn.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function D(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function On(e){return e.find(e=>e.bundleId)?.bundleId}function kn(e,n,r){if(typeof e!=`number`||!Number.isInteger(e))throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} must be an integer.`);return e}function O(e,n,r,i){if(e!==r)throw new t(`INVALID_ARGS`,`Android ${i} manifest ${n} must be "${r}".`);return r}function An(e,n,r){if(typeof e!=`string`||e.length===0)throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} is required.`);return e}function jn(e,n){let r=An(e,`sha256`,n).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new t(`INVALID_ARGS`,`Android ${n} manifest sha256 must be a 64-character hex string.`);return r}function Mn(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))Nn(n,t);return Pn(t),{status:t.status,results:t.results}}function Nn(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},Ln(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){Fn(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},Ln(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&In(t)}function Pn(e){Fn(e),In(e)}function Fn(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function In(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function Ln(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function k(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function Rn(e){if(e===`true`)return!0;if(e===`false`)return!1}function zn(e){if(!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return e}const Bn=1e4;async function Vn(e,t){try{return await qe(e,t)}catch(e){throw at(e)}}async function Hn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await Yn(a,o,u);let f=await Un({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let p=await Vn(a,{provider:n,replace:!0,allowFailure:!0,timeoutMs:l});if(p.exitCode!==0)throw w(`Failed to install ${u}`,p,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Un(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await Kn(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await qn(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Wn(e){let n=x().files,r=Pe(),i=E.join(Fe(),`android`,e.helperDirName,`dist`),a=E.join(i,e.manifestFileName(r));try{let t=e.parseManifest(JSON.parse(await n.readText(a))),r=E.join(i,t.assetName);return await n.access(r),{apkPath:r,manifest:t}}catch(n){throw new t(`UNSUPPORTED_OPERATION`,e.unavailableMessage,{manifestPath:a,error:s(n).message},n)}}function Gn(e){return async t=>await Hn({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function Kn(e,t,n){let r=await b(e,[`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Zn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function qn(e,n,r,i){let a=await b(e,[`pm`,`path`,r],{allowFailure:!0,timeoutMs:Bn,signal:i}),o=Jn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new t(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=x().files,c=await s.makeTempDirectory(`agent-device-helper-`),l=E.join(c,`base.apk`);try{let e=await Ue(o,l,{provider:n,allowFailure:!0,timeoutMs:Bn,signal:i});if(e.exitCode!==0)throw w(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Xn(l)}finally{await s.remove(c,{recursive:!0,force:!0})}}function Jn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function Yn(e,n,r){let i=await Xn(e);if(i!==n)throw new t(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:n,actualSha256:i})}async function Xn(e){let t=x().files;return t.sha256(await t.readBytes(e))}function Zn(e){return e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`)}const Qn=`android-snapshot-helper-v1`,$n=`uiautomator-xml`,er=5e3,tr=3e4;function nr(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let n=e;return{name:ir(n.name,`name`,`android-snapshot-helper`),version:A(n.version,`version`),releaseTag:or(n.releaseTag),assetName:or(n.assetName),apkUrl:sr(n.apkUrl,`apkUrl`),sha256:ar(n.sha256),checksumName:or(n.checksumName),packageName:A(n.packageName,`packageName`),versionCode:rr(n.versionCode,`versionCode`),instrumentationRunner:A(n.instrumentationRunner,`instrumentationRunner`),minSdk:rr(n.minSdk,`minSdk`),targetSdk:n.targetSdk===void 0?void 0:rr(n.targetSdk,`targetSdk`),outputFormat:ir(n.outputFormat,`outputFormat`,$n),statusProtocol:ir(n.statusProtocol,`statusProtocol`,Qn)}}function rr(e,t){return kn(e,t,`snapshot helper`)}function ir(e,t,n){return O(e,t,n,`snapshot helper`)}function ar(e){let n=A(e,`sha256`).trim().toLowerCase();if(n.length!==64||!cr(n))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return n}function A(e,n){if(typeof e!=`string`||e.trim().length===0)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest ${n} is required.`);return e}function or(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function sr(e,t){return e===null?null:A(e,t)}function cr(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const j=new Map;function lr(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of j.keys())e.startsWith(t)&&hr(e)}const ur=`android-snapshot-helper-not-current`;function dr(e){return n(e).details?.reason===ur}function fr(){j.clear()}function pr(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function mr(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of j.keys())t!==e&&t.startsWith(i)&&j.delete(t);j.set(e,t)}function hr(e){e&&j.delete(e)}async function gr(e){let{adb:n,artifact:r}=e,i=e.installPolicy??`missing-or-outdated`,a=r.manifest.packageName,o=r.manifest.versionCode,s=r.manifest.sha256;if(i===`never`)return{packageName:a,versionCode:o,installed:!1,reason:`skipped`};let c=pr(e.deviceKey,a,o,s),l=c?j.get(c):void 0;if(c&&i!==`always`&&l!==void 0)return{packageName:a,versionCode:o,installedVersionCode:l,installedSha256:s,installed:!1,reason:`current`};await Yn(r.apkPath,s,`Android snapshot helper`);let u=i===`always`?{installedVersionCode:await yr(n,a,e.timeoutMs,e.signal),reason:`forced`}:await Un({adb:n,adbProvider:vr(e.adbProvider,n),packageName:a,versionCode:o,sha256:s,signal:e.signal}),{installedVersionCode:d}=u,f=`installedSha256`in u?u.installedSha256:void 0,p=u.reason;if(p===`current`){if(d===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return mr(c,d),{packageName:a,versionCode:o,installedVersionCode:d,installedSha256:f,installed:!1,reason:p}}if(i===`current-only`)throw new t(`COMMAND_FAILED`,`Android snapshot helper is not installed at the current version`,{reason:ur,packageName:a,versionCode:o,installedVersionCode:d});let m;try{m=await br(n,e.adbProvider??n,r.apkPath,{packageName:a,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw hr(c),_r(e,{packageName:a,versionCode:o})}if(m.exitCode!==0)throw hr(c),_r(w(`Failed to install Android snapshot helper`,m,{packageName:a,versionCode:o}));return mr(c,o),{packageName:a,versionCode:o,installedVersionCode:d,installedSha256:f,installed:!0,reason:p}}function _r(e,t){let r=n(e,`COMMAND_FAILED`);return r.details={...t,...r.details,androidSnapshotHelperInstallFailure:!0},r}function vr(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function yr(e,t,n,r){let i=await b(e,[`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return xr(`${i.stdout}\n${i.stderr}`,t)}async function br(e,t,n,r){let i=async()=>await Vn(n,{allowFailure:!0,provider:t,replace:!0,timeoutMs:r.timeoutMs,signal:r.signal}),a=await i();if(a.exitCode===0||!Sr(a))return a;let o=await e([`uninstall`,r.packageName],{allowFailure:!0,timeoutMs:r.timeoutMs,signal:r.signal}),s=await i();return s.exitCode===0?s:{...s,stderr:[s.stderr,o.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${o.stderr}`:``].filter(Boolean).join(`
|
|
4
|
-
`)}}function
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{N as t,P as n,Q as r,R as i,_ as a,et as o,q as s,y as c,z as l}from"./sdk-contracts.js";import"./capture.js";import{O as u}from"./sdk-batch-runner.js";import{a as d,d as f,i as p,l as ee,o as te,r as ne,t as re,u as ie}from"./android-input-ownership.js";import{Hr as ae,Kr as oe,Ur as se,Wr as ce,Yr as le,Zr as ue,qr as de}from"./sdk-batch.js";import{_ as fe,d as pe,p as me}from"./scroll-gesture.js";import{r as he}from"./success-text.js";import{n as ge}from"./alert-contract.js";import{C as _e,_ as ve,b as ye,d as be,v as xe,x as Se,y as Ce}from"./settings.js";import{n as we}from"./location-coordinates.js";import{r as Te}from"./mobile-snapshot-semantics.js";import"./device.js";import{n as Ee,s as De}from"./device-rotation.js";import{c as m,r as h}from"./diagnostics.js";import{c as Oe,g as ke,l as Ae,o as je,r as Me}from"./exec.js";import{t as g}from"./timeouts.js";import{i as Ne}from"./tv-remote.js";import"./diagnostics2.js";import"./command.js";import{a as _,n as Pe,o as v}from"./device-shell.js";import"./retry.js";import{a as Fe,r as Ie}from"./version.js";import{n as Le,r as Re}from"./install-source2.js";import{_ as ze,a as y,c as Be,d as b,f as Ve,g as x,h as S,i as He,l as Ue,n as We,o as C,p as Ge,r as Ke,s as qe,t as Je,u as Ye,v as Xe}from"./adb-executor.js";import{c as Ze,h as Qe,i as $e,o as et,r as tt,u as nt}from"./adb-transport.js";import{c as rt,i as it,l as at,n as w,o as ot,s as st}from"./adb-failure.js";import{a as ct,i as lt,n as ut,o as T}from"./adb.js";import{i as dt,n as ft,r as pt}from"./gesture-plan.js";import{n as mt}from"./android-snapshot-quality.js";import{a as ht,c as gt,i as _t,l as vt,n as yt,o as bt,r as xt,s as St,u as Ct}from"./app-lifecycle.js";import{a as wt,i as Tt,n as Et,o as Dt,r as Ot,t as kt}from"./app-deployment-resolution.js";import{a as At,i as jt,n as Mt,o as Nt,t as Pt}from"./app-parsers.js";import{i as Ft,n as It,r as Lt,t as Rt}from"./window-state.js";import{n as zt}from"./toolchain-probe.js";import{t as Bt}from"./keyed-lock.js";import{n as Vt,r as Ht}from"./android-system-chrome.js";import{t as Ut}from"./bounds.js";import{t as Wt}from"./entities.js";import{n as Gt}from"./startup-recovery-fence.js";import{n as Kt}from"./numeric.js";import E from"node:path";import qt from"node:net";import{TextDecoder as Jt}from"node:util";const Yt=new Map;async function Xt(e){let t=Yt.get(e.deviceKey);if(t!==void 0)return t;let n;try{let t=await e.adb([`features`],{allowFailure:!0,timeoutMs:2e3,...e.signal?{signal:e.signal}:{}});if(t.exitCode!==0)return!1;n=t.stdout}catch{return!1}let r=Qt(n).includes(`shell_v2`);return Yt.set(e.deviceKey,r),r}function Zt(){Yt.clear()}function Qt(e){return e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(Boolean)}const $t=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function en(e){return $t.has(e)}const tn=new Set([`android`,`com.android.systemui`]),nn=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,rn=/^android:id\/button[123]$/i,an=/(?:^|:)id\/permission_/i,on=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,sn=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,cn=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function ln(e){if(e!==null){if(rn.test(e))return`button`;if(nn.test(e))return`content`}}function un(e){let t=pn(e.filter(dn)),n=t.nodes;if(n.length===0)return null;let r=vn(n),i=n.filter(e=>D(e)&&!On(e)),a=xn(i),o=Sn(i,a);if(!a&&!o&&r.length===0)return null;let s=kn(n);return{alert:{...a?{title:a}:{},...o?{message:o}:{},buttons:r.map(e=>e.label),platform:`android`,source:t.source,...s?{packageName:s}:{}},buttons:r}}function dn(e){return!ee(e)}function fn(e,t){let n=t===`accept`?`accept`:`dismiss`;return e.find(e=>e.role===n)||(t===`dismiss`?e.find(e=>e.role===`neutral`)??null:e.length===1?e[0]??null:null)}function pn(e){let t=e.filter(e=>En(e));if(t.length)return{nodes:t,source:`permission`};let n=_n(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:mn(e),source:`native-dialog`}}function mn(e){let t=e.filter(e=>hn(e.type??``)),n=e.filter(e=>nn.test(e.identifier??``)),r=t.length?[...t,...n]:gn(n);if(r.length===0)return[];let i=Cn(e,r);return i===void 0?r:Tn(e,i)}function hn(e){let t=Math.max(e.lastIndexOf(`.`),e.lastIndexOf(`$`));return e.slice(t+1).toLowerCase().endsWith(`dialog`)}function gn(e){let t=e.some(e=>rn.test(e.identifier??``)),n=e.some(e=>!rn.test(e.identifier??``));return t&&n?e:[]}function _n(e){let t=e.filter(e=>Dn(e));if(t.length===0)return[];let n=Cn(e,t);return n===void 0?t:Tn(e,n).filter(e=>e.bundleId&&tn.has(e.bundleId))}function vn(e){let t=new Set,n=[];for(let r of e){let e=D(r);if(!e||!r.rect||!On(r))continue;let i=e.trim().toLowerCase();if(!i||t.has(i))continue;t.add(i);let a=c(r.rect);n.push({label:e,x:a.x,y:a.y,role:yn(r,e)})}return n}function yn(e,t){return bn(e.identifier??``)||(sn.test(t.trim())?`accept`:cn.test(t.trim())?`dismiss`:`neutral`)}function bn(e){return/(?:^|:)id\/button1$/i.test(e)?`accept`:/(?:^|:)id\/button2$/i.test(e)?`dismiss`:/(?:^|:)id\/button3$/i.test(e)?`neutral`:/(?:^|:)id\/permission_allow/i.test(e)?`accept`:/(?:^|:)id\/permission_deny/i.test(e)?`dismiss`:null}function xn(e){return D(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||D(e[0])}function Sn(e,t){let n=e.map(e=>D(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
3
|
+
`):void 0}function Cn(e,t){let n=t[0];if(!n)return;let r=wn(e,n.index);for(let n of t.slice(1)){let t=new Set(wn(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r.at(-1)}function wn(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function Tn(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function En(e){let t=e.bundleId??``;return $t.has(t)||an.test(e.identifier??``)}function Dn(e){let t=e.bundleId??``;return tn.has(t)&&on.test(D(e))}function On(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||rn.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function D(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function kn(e){return e.find(e=>e.bundleId)?.bundleId}function An(e,n,r){if(typeof e!=`number`||!Number.isInteger(e))throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} must be an integer.`);return e}function O(e,n,r,i){if(e!==r)throw new t(`INVALID_ARGS`,`Android ${i} manifest ${n} must be "${r}".`);return r}function jn(e,n,r){if(typeof e!=`string`||e.length===0)throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} is required.`);return e}function Mn(e,n){let r=jn(e,`sha256`,n).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new t(`INVALID_ARGS`,`Android ${n} manifest sha256 must be a 64-character hex string.`);return r}function Nn(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))Pn(n,t);return Fn(t),{status:t.status,results:t.results}}function Pn(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},Rn(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){In(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},Rn(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&Ln(t)}function Fn(e){In(e),Ln(e)}function In(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function Ln(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function Rn(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function k(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function zn(e){if(e===`true`)return!0;if(e===`false`)return!1}function Bn(e){if(!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return e}const Vn=1e4;async function Hn(e,t){try{return await Je(e,t)}catch(e){throw ot(e)}}async function Un(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await Xn(a,o,u);let f=await Wn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let p=await Hn(a,{provider:n,replace:!0,allowFailure:!0,timeoutMs:l});if(p.exitCode!==0)throw w(`Failed to install ${u}`,p,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Wn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await qn(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await Jn(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Gn(e){let n=x().files,r=Fe(),i=E.join(Ie(),`android`,e.helperDirName,`dist`),a=E.join(i,e.manifestFileName(r));try{let t=e.parseManifest(JSON.parse(await n.readText(a))),r=E.join(i,t.assetName);return await n.access(r),{apkPath:r,manifest:t}}catch(n){throw new t(`UNSUPPORTED_OPERATION`,e.unavailableMessage,{manifestPath:a,error:s(n).message},n)}}function Kn(e){return async t=>await Un({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function qn(e,t,n){let r=await b(e,[`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Qn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Jn(e,n,r,i){let a=await b(e,[`pm`,`path`,r],{allowFailure:!0,timeoutMs:Vn,signal:i}),o=Yn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new t(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=x().files,c=await s.makeTempDirectory(`agent-device-helper-`),l=E.join(c,`base.apk`);try{let e=await We(o,l,{provider:n,allowFailure:!0,timeoutMs:Vn,signal:i});if(e.exitCode!==0)throw w(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Zn(l)}finally{await s.remove(c,{recursive:!0,force:!0})}}function Yn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function Xn(e,n,r){let i=await Zn(e);if(i!==n)throw new t(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:n,actualSha256:i})}async function Zn(e){let t=x().files;return t.sha256(await t.readBytes(e))}function Qn(e){return e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`)}const $n=`android-snapshot-helper-v1`,er=`uiautomator-xml`,tr=5e3,nr=3e4;function rr(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let n=e;return{name:ar(n.name,`name`,`android-snapshot-helper`),version:A(n.version,`version`),releaseTag:sr(n.releaseTag),assetName:sr(n.assetName),apkUrl:cr(n.apkUrl,`apkUrl`),sha256:or(n.sha256),checksumName:sr(n.checksumName),packageName:A(n.packageName,`packageName`),versionCode:ir(n.versionCode,`versionCode`),instrumentationRunner:A(n.instrumentationRunner,`instrumentationRunner`),minSdk:ir(n.minSdk,`minSdk`),targetSdk:n.targetSdk===void 0?void 0:ir(n.targetSdk,`targetSdk`),outputFormat:ar(n.outputFormat,`outputFormat`,er),statusProtocol:ar(n.statusProtocol,`statusProtocol`,$n)}}function ir(e,t){return An(e,t,`snapshot helper`)}function ar(e,t,n){return O(e,t,n,`snapshot helper`)}function or(e){let n=A(e,`sha256`).trim().toLowerCase();if(n.length!==64||!lr(n))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return n}function A(e,n){if(typeof e!=`string`||e.trim().length===0)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest ${n} is required.`);return e}function sr(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function cr(e,t){return e===null?null:A(e,t)}function lr(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const j=new Map;function ur(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of j.keys())e.startsWith(t)&&gr(e)}const dr=`android-snapshot-helper-not-current`;function fr(e){return n(e).details?.reason===dr}function pr(){j.clear()}function mr(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function hr(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of j.keys())t!==e&&t.startsWith(i)&&j.delete(t);j.set(e,t)}function gr(e){e&&j.delete(e)}async function _r(e){let{adb:n,artifact:r}=e,i=e.installPolicy??`missing-or-outdated`,a=r.manifest.packageName,o=r.manifest.versionCode,s=r.manifest.sha256;if(i===`never`)return{packageName:a,versionCode:o,installed:!1,reason:`skipped`};let c=mr(e.deviceKey,a,o,s),l=c?j.get(c):void 0;if(c&&i!==`always`&&l!==void 0)return{packageName:a,versionCode:o,installedVersionCode:l,installedSha256:s,installed:!1,reason:`current`};await Xn(r.apkPath,s,`Android snapshot helper`);let u=i===`always`?{installedVersionCode:await br(n,a,e.timeoutMs,e.signal),reason:`forced`}:await Wn({adb:n,adbProvider:yr(e.adbProvider,n),packageName:a,versionCode:o,sha256:s,signal:e.signal}),{installedVersionCode:d}=u,f=`installedSha256`in u?u.installedSha256:void 0,p=u.reason;if(p===`current`){if(d===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return hr(c,d),{packageName:a,versionCode:o,installedVersionCode:d,installedSha256:f,installed:!1,reason:p}}if(i===`current-only`)throw new t(`COMMAND_FAILED`,`Android snapshot helper is not installed at the current version`,{reason:dr,packageName:a,versionCode:o,installedVersionCode:d});let ee;try{ee=await xr(n,e.adbProvider??n,r.apkPath,{packageName:a,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw gr(c),vr(e,{packageName:a,versionCode:o})}if(ee.exitCode!==0)throw gr(c),vr(w(`Failed to install Android snapshot helper`,ee,{packageName:a,versionCode:o}));return hr(c,o),{packageName:a,versionCode:o,installedVersionCode:d,installedSha256:f,installed:!0,reason:p}}function vr(e,t){let r=n(e,`COMMAND_FAILED`);return r.details={...t,...r.details,androidSnapshotHelperInstallFailure:!0},r}function yr(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function br(e,t,n,r){let i=await b(e,[`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Sr(`${i.stdout}\n${i.stderr}`,t)}async function xr(e,t,n,r){let i=async()=>await Hn(n,{allowFailure:!0,provider:t,replace:!0,timeoutMs:r.timeoutMs,signal:r.signal}),a=await i();if(a.exitCode===0||!Cr(a))return a;let o=await e([`uninstall`,r.packageName],{allowFailure:!0,timeoutMs:r.timeoutMs,signal:r.signal}),s=await i();return s.exitCode===0?s:{...s,stderr:[s.stderr,o.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${o.stderr}`:``].filter(Boolean).join(`
|
|
4
|
+
`)}}function Sr(e,t){let n=`package:${t}`;for(let t of e.split(/\r?\n/)){if(!t.startsWith(n)||t.length>n.length&&!/\s/.test(t[n.length]??``))continue;let e=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(e)return Number(e[1])}}function Cr(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}function wr(e){return e.errorType===`java.util.concurrent.TimeoutException`?`accessibility-timeout`:void 0}function Tr(e){return e===137?`accessibility-timeout`:void 0}function Er(e){return e?{androidCaptureFailureReason:e}:{}}function Dr(){return new Promise((e,t)=>{let n=qt.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function Or(e,n,r,i){return new Promise((a,o)=>{let s=qt.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new t(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:n,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${n}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function kr(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return Fr(await Or(e.port,`snapshot ${t}`,Ar(e),e.signal),t)}function Ar(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function jr(e,n,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new t(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:n,reason:`android_snapshot_helper_session_ready_timeout`}))},n),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,n)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new t(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:n,reason:`android_snapshot_helper_session_exited_before_ready`}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function Mr(e){let t=e.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);return
|
|
6
|
+
`);return Rr(e.slice(0,t<0?e.length:t))}function Nr(e,n){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new t(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==n)throw new t(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:n})}function Pr(e,t){let n=Mr(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function Fr(e,n){let r=e.indexOf(`
|
|
7
7
|
|
|
8
|
-
`);if(r<0)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=Lr(e.slice(0,r)),a=e.slice(r+2);return Fr(i,n),Ir(i,a),{xml:a,metadata:Rr(i)}}function Fr(e,n){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==n)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:n});if(e.ok!==`true`)throw new t(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e,...Tr(Cr(e))})}function Ir(e,n){let r=k(e.byteLength);if(r!==void 0&&Buffer.byteLength(n,`utf8`)!==r)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(n,`utf8`)});if(!n.includes(`<hierarchy`)||!n.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:n})}function Lr(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function Rr(e){return{helperApiVersion:e.helperApiVersion,outputFormat:$n,waitForIdleTimeoutMs:k(e.waitForIdleTimeoutMs),waitForIdleQuietMs:k(e.waitForIdleQuietMs),timeoutMs:k(e.timeoutMs),maxDepth:k(e.maxDepth),maxNodes:k(e.maxNodes),rootPresent:Rn(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:k(e.windowCount),nodeCount:k(e.nodeCount),truncated:Rn(e.truncated),elapsedMs:k(e.elapsedMs),pixelDensity:k(e.pixelDensity)}}function M(e,n,r,i){if(i instanceof t){let a=i.details??{};return new t(i.code,i.message,{...a,action:e,package:r,tool:n,hint:typeof a.hint==`string`?a.hint:Vr(n,a)},i)}return new t(`COMMAND_FAILED`,`Failed to ${e} Android ${n} for ${r}`,{action:e,package:r,tool:n,hint:zr(n)},i)}function zr(e){return e===`simpleperf`?`Verify simpleperf is available, the app process is running, and the app/device permits native CPU profiling.`:`Verify perfetto is available, the app process is running, and the device permits trace capture.`}function Br(e){return e===`simpleperf`?`Use an emulator/system image with simpleperf available, or install the Android NDK simpleperf binary for this device.`:`Use Android 10+ or a system image that exposes the perfetto command-line binary.`}function Vr(e,t){let n=(typeof t.stderr==`string`?t.stderr:``).toLowerCase();return e===`simpleperf`?Hr(n):Wr(n)?`Use a device image that permits perfetto trace capture for shell, keep the app running, then retry perf trace start.`:zr(e)}function Hr(e){return Ur(e)?`Use a debuggable/profileable Android app or a device image that permits simpleperf for the target process, then retry perf cpu profile start.`:e.includes(`not supported`)||e.includes(`failed to open perf event`)?`This device image does not expose the requested simpleperf event for the app process. Try a different emulator/system image or a profileable app.`:zr(`simpleperf`)}function Ur(e){return e.includes(`permission denied`)||e.includes(`not profileable`)||e.includes(`profileable`)}function Wr(e){return e.includes(`permission denied`)||e.includes(`not allowed`)}const Gr=`adb-shell-simpleperf`,Kr=`adb-shell-perfetto`,qr=15e3,N=3e4,Jr=`/data/local/tmp`;async function Yr(e,n){try{let t=await b(e,[`pidof`,n],{allowFailure:!0,timeoutMs:qr}),r=Zr(t.stdout);if(t.exitCode===0&&r)return r}catch{}throw new t(`COMMAND_FAILED`,`No active Android app process found for ${n}`,{package:n,hint:`Run open <app> for this session again, wait for the app UI to appear, then retry perf.`})}async function Xr(e,n,r){let i=await b(e,[Me(`command -v ${v(n)} || which ${v(n)}`)],{allowFailure:!0,timeoutMs:qr});if(!(i.exitCode===0&&i.stdout.trim()))throw new t(`UNSUPPORTED_OPERATION`,`Android device does not expose ${n}`,{package:r,tool:n,hint:Br(n)})}function Zr(e){return e.trim().split(/\s+/).find(e=>/^\d+$/.test(e))}const Qr=2e3,$r=`android_snapshot_helper_runtime_occupied`,P=new Map;function ei(e){return`${e.platform}:${e.id}`}async function ti(e){await mi({adb:e.adb,packageName:e.packageName}),await ri({deviceKey:e.deviceKey,packageName:e.packageName,adb:e.adb,cause:e.cause})}async function ni(e){let t=P.get(e.deviceKey);if(!t)return;await mi({adb:e.adb,packageName:t.packageName,timeoutMs:5e3,...e.signal?{signal:e.signal}:{}}),e.signal?.throwIfAborted();let n=await oi({adb:e.adb,packageName:t.packageName});if(n===`occupied`&&(await _(250),n=await oi({adb:e.adb,packageName:t.packageName})),n===`occupied`)throw ai({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause});n!==`unknown`&&P.delete(e.deviceKey)}async function ri(e){let t=e.release??await oi({adb:e.adb,packageName:e.packageName});if(t===`released`)return P.delete(e.deviceKey),t;let n=e.cause instanceof Error?e.cause.message:String(e.cause);return P.set(e.deviceKey,{packageName:e.packageName,cause:n}),g({level:`warn`,phase:`android_snapshot_helper_retirement_pending`,data:{deviceKey:e.deviceKey,packageName:e.packageName,release:t}}),t}function ii(e){return e instanceof t&&e.details?.reason===$r}function ai(e){let n=e.cause instanceof Error?e.cause.message:String(e.cause);return new t(`COMMAND_FAILED`,`Android automation helper is still holding device automation ownership`,{reason:$r,deviceKey:e.deviceKey,packageName:e.packageName,cause:n,hint:`Retry after the helper process exits, or restart the device if Android keeps reporting the helper as running.`})}async function oi(e){try{let t=await b(e.adb,[`pidof`,e.packageName,Me(`|| echo AGENT_DEVICE_NO_HELPER`)],{allowFailure:!0,timeoutMs:Qr}),n=t.stdout.trim();return Zr(n)?`occupied`:n===`AGENT_DEVICE_NO_HELPER`&&t.stderr.trim().length===0?`released`:`unknown`}catch{return`unknown`}}async function si(e){let t=AbortSignal.timeout(e.timeoutMs);return await Promise.all([...e.forceStopRuntime?[mi({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t})]:[],hi({...e,signal:t})]),{timedOut:t.aborted}}function ci(e){let t=li(e);return{ended:t?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())}),hasEnded:()=>li(e),completedCleanly:()=>!t&&e.exitCode===0&&e.signalCode==null}}function li(e){return e.exitCode!=null||e.signalCode!=null}async function ui(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function di(e){if(e.processExit.hasEnded())return!0;try{e.process.kill(`SIGTERM`)}catch{}return await ui(e.processExit.ended,e.timeoutMs)}function fi(e){P.delete(e)}function pi(){P.clear()}async function mi(e){await b(e.adb,[`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs??2e3,...e.signal?{signal:e.signal}:{}}).catch(()=>{})}async function hi(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function gi(e){let n=vi(e),r=e.deviceKey??`android:default`;await ni({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(yi(n),{allowFailure:!0,timeoutMs:n.commandTimeoutMs,signal:e.signal})}catch(t){throw e.signal?.aborted?(await ti({deviceKey:r,packageName:n.packageName,adb:e.adb,cause:t}),e.signal.throwIfAborted(),t):t}e.signal?.aborted&&(await ti({deviceKey:r,packageName:n.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await bi(e,n,i);if(n.outputPath&&!o&&await Di(e.adb,n.outputPath),i.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android snapshot helper failed`,ke(i,{helper:a.metadata}));return a}function _i(e){return{adb:e.adb,adbProvider:e.adbProvider,deviceKey:e.deviceKey,helperVersion:e.artifact.manifest.version,helperVersionCode:e.artifact.manifest.versionCode,helperSha256:e.artifact.manifest.sha256,packageName:e.artifact.manifest.packageName,instrumentationRunner:e.artifact.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:er,commandTimeoutMs:tr,...e.signal?{signal:e.signal}:{}}}function vi(e){let t=F(e.timeoutMs,8e3),n=F(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:F(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:F(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:F(e.commandTimeoutMs,t+5e3),maxDepth:F(e.maxDepth,128),maxNodes:F(e.maxNodes,5e3),packageName:n,runner:F(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function F(e,t){return e===void 0?t:e}function yi(e,t={}){return Ne(`adb`,`shell`,[`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],...t.sessionPort===void 0?[]:[`-e`,`sessionPort`,t.sessionPort],e.runner])}async function bi(e,t,n){try{return{output:Oi(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await xi(e,t,n,r)}}async function xi(e,n,r,i){if(i instanceof t&&r.exitCode!==0&&i.details?.helper)throw i;let a=await Si(e,n,r);if(a)return{output:a,cleanupDone:!0};throw new t(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,...Tr(wr(r.exitCode))},i)}async function Si(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await wi(e.adb,t.outputPath,Ei(`${n.stdout}\n${n.stderr}`)??Ci(t))}function Ci(e){return{outputFormat:$n,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function wi(e,t,n){let r;try{r=await b(e,Ti(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Ti(e){return[`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ei(e){try{return Ii(Ai(Mn(e).results))}catch{return null}}async function Di(e,t){try{await b(e,[`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Oi(e){let t=Mn(e),n=Ai(t.results);return{xml:Mi(ki(t.status),n),metadata:{...Ii(n),transport:`instrumentation`}}}function ki(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:I(n.chunkIndex),count:I(n.chunkCount),payloadBase64:e})}return t}function Ai(e){let n=e.find(e=>e.agentDeviceProtocol===Qn);if(!n)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(n.ok!==`true`)throw new t(`COMMAND_FAILED`,ji(n),{errorType:n.errorType,helper:n,...Tr(Cr(n))});return n}function ji(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Mi(e,n){if(e.length===0)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:n});let r=Ni(e),i=Buffer.concat(Fi(Pi(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Ni(e){let n=e[0]?.count??e.length;if(n<1||e.length!==n||e.some(e=>e.count!==n))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:n,actualChunks:e.length});return n}function Pi(e,n){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=n)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:n});if(r.has(i.index))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Fi(e,n){let r=[];for(let i=0;i<n;i+=1){let a=e.get(i);if(a===void 0)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:n});r.push(Buffer.from(a,`base64`))}return r}function Ii(e){return{helperApiVersion:e.helperApiVersion,outputFormat:$n,waitForIdleTimeoutMs:I(e.waitForIdleTimeoutMs),waitForIdleQuietMs:I(e.waitForIdleQuietMs),timeoutMs:I(e.timeoutMs),maxDepth:I(e.maxDepth),maxNodes:I(e.maxNodes),rootPresent:Ri(e.rootPresent),captureMode:Li(e.captureMode),windowCount:I(e.windowCount),nodeCount:I(e.nodeCount),truncated:Ri(e.truncated),elapsedMs:I(e.elapsedMs),pixelDensity:I(e.pixelDensity)}}function Li(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const I=k,Ri=Rn,zi=5e3,L=new Map,R=new Map;async function Bi(e){return await Vi(e)!==void 0}async function Vi(e){let t=e.deviceKey??`android:default`;if(await ni({deviceKey:t,adb:e.adb,signal:e.signal}),!$i()||!e.adbProvider?.spawn)return;let n=vi(e),r=Zi(n),i=await Ui({deviceKey:t,identity:Xi(t,r,e),options:e,resolved:r,startBudgetMs:Qi(n.commandTimeoutMs)});return i?{session:i,resolved:r,deviceKey:t}:void 0}function Hi(e){return L.get(e)}async function Ui(e){if(!Ki(e.identity))return await Wi(e.deviceKey,e.identity),L.get(e.deviceKey)??await Gi(e)}async function Wi(e,t){let n=L.get(e);!n||Ji(n,t)||await z(e,{force:li(n.process)})}async function Gi(e){let n=Date.now();try{return await Yi(e)}catch(r){e.options.signal?.throwIfAborted(),R.set(e.identity,Date.now()+qi(Date.now()-n)),g({level:`warn`,phase:`android_snapshot_helper_session_start_failed`,data:{deviceKey:e.deviceKey,reason:r instanceof t?r.details?.reason:void 0,detail:r instanceof Error?r.message:String(r)}});return}}function Ki(e){let t=R.get(e);return t===void 0?!1:t>Date.now()||(R.delete(e),!1)}function qi(e){return Math.min(Math.max(e,1e4),6e4)}function Ji(e,t){return e.identity===t&&!li(e.process)}async function Yi(e){let t=await Er();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:zi,signal:e.options.signal});let n=yi({...e.resolved,outputPath:void 0,emitChunks:!1},{sessionPort:t}),r=e.options.adbProvider.spawn(n,{allowFailure:!0,captureOutput:!1}),i={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:r,startedAtMs:Date.now(),capturedCount:0};try{return await Ar(r,e.startBudgetMs,e.options.signal),L.set(e.deviceKey,i),R.delete(e.identity),fi(e.deviceKey),g({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),i}catch(t){let n=ci(r);try{r.kill(`SIGTERM`)}catch{}throw await Promise.all([ui(n.ended,250),si({adb:i.adb,process:i.process,port:i.port,packageName:i.helper.packageName,timeoutMs:Qr,forceStopRuntime:!0})]),await ri({deviceKey:e.deviceKey,packageName:i.helper.packageName,adb:i.adb,cause:t}),t}}function Xi(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function Zi(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function Qi(e){return Math.min(e,Math.max(Math.floor(e/2),5e3))}function $i(){let e=x().environment.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}async function z(e,t={}){let n=L.get(e);if(!n)return!1;L.delete(e);let r=ci(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await ea(n,r,i,t.signal),o=r.hasEnded(),s=a.acknowledged&&a.exited,c=s&&await Yt({adb:n.adb,deviceKey:e,signal:t.signal}),l=i?t.signal?.aborted===!0?250:Qr:zi,u=i?250:2e3,[d,f]=await Promise.all([di({process:n.process,processExit:r,timeoutMs:u}),si({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:l,forceStopRuntime:t.resetRuntime===!0||!c})]),p=await ri({deviceKey:e,packageName:n.helper.packageName,adb:n.adb,cause:t.cause,...c?{release:`released`}:{}});return g({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,quitExitObserved:s,releaseProvenByQuit:c,release:p,forceKilled:!o&&d,forced:i||t.signal?.aborted===!0,externalCleanupTimedOut:f.timedOut}}),!0}async function ea(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=Nr(await Dr(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await ui(t.ended,11e3,r)&&t.completedCleanly()}}catch{return{acknowledged:!1,exited:!1}}}async function ta(e){await z(ei(e))}async function na(){try{await Promise.allSettled([...L.keys()].map(async e=>{await z(e)}))}finally{L.clear(),R.clear(),pi(),Xt()}}async function ra(e){let t=await Vi(e);if(t)return await ia({session:t.session,deviceKey:t.deviceKey,options:e,resolved:t.resolved})}async function ia(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await Or({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await z(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),g({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:pt(e)===`accessibility-timeout`}});return}}function B(e,n){return e!==`gesture`||!(n instanceof t)?n:i(n,it(n)?`no`:`unknown`)}async function aa(e){let n=Hi(e.deviceKey);if(!n)return;if(!oa(n.helper,e.helper)){g({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:n.helper,requestedHelper:e.helper}}),await z(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=jr(await Dr(n.port,i,e.timeoutMs)),Mr(a,r)}catch(t){throw await z(e.deviceKey),B(e.action,t)}if(a.ok!==`true`)throw B(e.action,new t(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a}));return a}function oa(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&sa(e.helperVersion,t.helperVersion)&&sa(e.helperVersionCode,t.helperVersionCode)&&sa(e.sha256,t.sha256)}function sa(e,t){return e===void 0||t===void 0||e===t}const ca=`android-touch-plan-v1`,la=45e3,ua=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,da=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function fa(e,t){let n=await ha(e),r=_a(t),i=Math.max(45e3,r.durationMs+15e3),a=Buffer.from(JSON.stringify({protocol:ca,...r})).toString(`base64`),o=await h(`android_touch_helper_gesture`,async()=>{let e=await aa({deviceKey:n.deviceKey,action:`gesture`,helper:ma(n.artifact),payloadBase64:a,timeoutMs:i});return e?{...xa(e),helperTransport:`persistent-session`}:{...await ya({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,action:`gesture`,extraArgs:[`-e`,`payloadBase64`,a],timeoutMs:i,readResult:xa}),helperTransport:`instrumentation`}},{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version});return{backend:`android-helper`,helperVersion:n.artifact.manifest.version,installReason:n.install.reason,...o}}async function pa(e,t={}){let n=await ha(e);t.helperSessionScope===`daemon-session`&&await Bi(_i({adb:n.adb,adbProvider:n.adbProvider,artifact:n.artifact,deviceKey:n.deviceKey}));try{let e=await aa({deviceKey:n.deviceKey,action:`viewport`,helper:ma(n.artifact),timeoutMs:la});if(e)return Sa(e)}catch(e){await z(n.deviceKey),g({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await ya({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,action:`viewport`,extraArgs:[],timeoutMs:la,readResult:Sa})}function ma(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function ha(e){let t=C(e),n=t.snapshotHelperArtifact??await ga(),r=ei(e);await ni({deviceKey:r,adb:t.exec});let i=await h(`android_touch_helper_install`,async()=>await gr({adb:t.exec,adbProvider:t,artifact:n,deviceKey:r,timeoutMs:3e4}),{packageName:n.manifest.packageName,versionCode:n.manifest.versionCode});return g({phase:`android_touch_helper_install_decision`,data:i}),i.installed&&await z(r),{adb:t.exec,adbProvider:t,artifact:n,install:i,deviceKey:r}}async function ga(){return await Wn({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=nr(e);return{...t,assetName:t.assetName??`agent-device-android-snapshot-helper-${t.version}.apk`}},unavailableMessage:`Android touch gestures require the bundled Android automation helper artifact, but it was not found or could not be read`})}function _a(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(va)}}function va(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function ya(e){let n=await b(e.adb,[`am`,`instrument`,`-w`,`-e`,`mode`,e.action,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=ba(`${n.stdout}\n${n.stderr}`)}catch(r){if(r instanceof t){if(r.code===da)throw B(e.action,new t(`COMMAND_FAILED`,r.message,r.details,r));if(r.code!==ua)throw r}let i=new t(`COMMAND_FAILED`,n.exitCode===0?`Android automation helper output could not be parsed`:`Android automation helper failed before returning parseable output`,ke(n),r);throw B(e.action,n.exitCode===0?i:rt(i))}if(n.exitCode!==0)throw B(e.action,rt(new t(`COMMAND_FAILED`,`Android automation helper failed`,ke(n,{helper:r}))));return e.readResult(r)}function ba(e){let n=Mn(e).results.find(e=>e.agentDeviceProtocol===Qn);if(!n)throw new t(ua,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(da,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function xa(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:k(e.injectedEvents),elapsedMs:k(e.elapsedMs)}}function Sa(e){let n=k(e.x),r=k(e.y),i=k(e.width),a=k(e.height);if(n===void 0||r===void 0||i===void 0||a===void 0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);let o=Ca(e);return{viewport:zn({x:n,y:r,width:i,height:a}),...o?{keyboard:o}:{}}}function Ca(e){let t=k(e.keyboardX),n=k(e.keyboardY),r=k(e.keyboardWidth),i=k(e.keyboardHeight);if(t!==void 0&&n!==void 0&&r!==void 0&&i!==void 0)return{x:t,y:n,width:r,height:i}}function wa(e){if(e.topology===`two`||e.intent===`longPress`)return e;let{releaseBehavior:t,...n}=e,[{pointerId:r,samples:i}]=n.pointers,a=[...new Set([...ut(e.durationMs,`android`),...i.map(({offsetMs:e})=>e)])].sort((e,t)=>e-t),o=0,s=a.map(e=>{for(;o<i.length-2&&e>i[o+1].offsetMs;)o+=1;let n=i[o],r=i[o+1],a=r.offsetMs-n.offsetMs,s=(e-n.offsetMs)/a;return{offsetMs:e,point:e===r.offsetMs||a===0?r.point:ft(n.point,r.point,t===`controlled`?Ta(s,a):s)}}),c=[s[0],s[1],s[2],...s.slice(3)];return{...n,pointers:[{pointerId:r,samples:c}]}}function Ta(e,t){let n=Math.min(16/t,.5);return e<n?e**2/n:1-(1-e)**2/(1-n)}async function Ea(e,t){let n=wa(t),r=ze(e);if(r){let e=n.intent===`longPress`?{...n,viewport:zn(await r.gestureViewport())}:n;return{backend:`provider-native-touch`,...await r.touch(e)??{}}}return await fa(e,n)}async function Da(e,t={}){return(await Oa(e,t)).viewport}async function Oa(e,t={}){let n=ze(e);return n?{viewport:zn(await n.gestureViewport())}:await pa(e,t)}async function V(e,t,n){try{await T(e,[`input`,`tap`,t,n])}catch(e){throw nt(e)}}async function ka(e,t,n){await V(e,t,n);try{await V(e,t,n)}catch(e){throw l(e,1)}}async function Aa(e,t,n){let r=je(t);await T(e,[`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function ja(e){await T(e,[`input`,`keyevent`,`4`])}async function Ma(e){await T(e,[`input`,`keyevent`,`3`])}async function Na(e){await T(e,[`input`,`keyevent`,`ENTER`])}async function Pa(e,t){let n=Wa(t);await T(e,[`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await T(e,[`settings`,`put`,`system`,`user_rotation`,n]),await Ia(e,t,n)}const Fa=15e3;async function Ia(e,n,r){let i=Date.now()+Fa,a=await La(e,n,i);for(;a!==void 0&&a!==r&&Date.now()<i;)await _(Math.min(500,Ra(i))),a=await La(e,n,i);if(a!==void 0&&a!==r)throw new t(`COMMAND_FAILED`,`orientation ${n} did not take effect: the display still reports rotation ${a} after ${Fa}ms`,{requestedRotation:Number(r),observedRotation:Number(a),hint:"The foreground app may pin its orientation, or the device may ignore user_rotation. Check `adb shell dumpsys display | grep mCurrentOrientation` and the app manifest."})}async function La(e,n,r){try{let t=await T(e,[`dumpsys`,`display`],{timeoutMs:Ra(r)});return/mCurrentOrientation=(\d)/.exec(t.stdout)?.[1]}catch(e){throw new t(`COMMAND_FAILED`,`orientation ${n} could not confirm the display rotation: ${e instanceof Error?e.message:String(e)}`,{hint:"The device did not answer `dumpsys display` within the orientation budget."})}}function Ra(e){return Math.max(1,e-Date.now())}async function za(e){await T(e,[`input`,`keyevent`,`187`])}async function Ba(e,t,n,r=800){let i={x:t,y:n};return await Ea(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function Va(e,t,n){await V(e,t,n)}async function Ha(e,t,n){let{viewport:r,keyboard:i}=await Oa(e,{helperSessionScope:n?.helperSessionScope}),a=Ua(t,r,i),o=fe({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:a.viewport.width,referenceHeight:a.viewport.height}),s={...o,referenceWidth:a.viewport.x+a.viewport.width,referenceHeight:a.viewport.y+a.viewport.height,x1:a.viewport.x+o.x1,y1:a.viewport.y+o.y1,x2:a.viewport.x+o.x2,y2:a.viewport.y+o.y2},c=Math.max(n?.durationMs??300,16),l=await Ea(e,{...dt({intent:`pan`,origin:{x:s.x1,y:s.y1},delta:{x:s.x2-s.x1,y:s.y2-s.y1},durationMs:c},a.viewport,`android`),releaseBehavior:n?.releaseBehavior??`controlled`});return{...s,...a.evidence,...n?.durationMs===void 0?{}:{durationMs:c},...l}}function Ua(e,t,n){if(n===void 0)return{viewport:t,evidence:{}};let r=pe(t,n);if(r.kind===`occluded`)throw de(e,{keyboardMinY:r.keyboardMinY,visibleHeight:r.visibleHeight,viewportHeight:t.height});return r.kind===`avoided`?{viewport:r.viewport,evidence:{keyboardAvoided:!0,keyboardMinY:r.keyboardMinY}}:{viewport:t,evidence:{}}}function Wa(e){let n=Te[e];if(n===void 0)throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`);return String(n)}async function Ga(e){let n=(await T(e,[`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}async function Ka(e,t,n){return t===`wait`?await qa(n.captureNodes,n.timeoutMs??1e4):t===`get`?$a((await Qa(n.captureNodes))?.alert??null):await Ja(e,t,n.captureNodes)}async function qa(e,n){let r=Date.now(),i=await Za(e,n);if(!i)throw new t(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:i.alert,waitedMs:Date.now()-r,...me(`Alert visible`)}}async function Ja(e,n,r){let i=await Za(r,he);if(!i)throw new t(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let a=dn(i.buttons,n);if(a)return await V(e,a.x,a.y),await Ya(i.alert,n,r),eo(n,i.alert,a.label,{x:a.x,y:a.y});if(n===`dismiss`)return await ja(e),await Ya(i.alert,n,r),eo(n,i.alert,`Back`);throw new t(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:i.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function Ya(e,n,r){let i=Date.now();for(;;){let a=await Qa(r);if(!a||!Xa(a.alert,e))return;if(Date.now()-i>=2e3)throw new t(`COMMAND_FAILED`,`alert ${n} did not dismiss the visible alert`,{alert:e,hint:`The alert button was pressed but the dialog is still visible. Inspect alert get --json, then press the visible button by label/ref or retry.`});await _(300)}}function Xa(e,t){return e.title===t.title&&e.buttons.join(`\0`)===t.buttons.join(`\0`)}async function Za(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await Qa(e);if(t)return t;await _(300)}return null}async function Qa(e){return ln(await h(`snapshot_capture`,e,{backend:`android`,purpose:`alert`}))}function $a(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...me(e?`Alert visible`:`No alert visible`)}}function eo(e,t,n,r){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:n,...r?{coordinates:r}:{},...me(`Alert ${e}ed`)}}const to=`android.intent.category.LAUNCHER`,no=`android.intent.category.DEFAULT`;async function ro(e,t){await b(e,[`am`,`force-stop`,t])}async function io(e,t,n=[to]){for(let r of n){let n=await b(e,[`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=yt(n.stdout);if(i)return i}return null}async function ao(e,n,r={}){let i=r.category??to;if(r.activity){await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,no,`-c`,i,`-n`,oo(n,r.activity)]);return}let a=await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,no,`-c`,i,`-p`,n],{allowFailure:!0});if(a.exitCode===0&&!bt(a.stdout,a.stderr))return;let o=await io(e,n,[i]);if(!o)throw new t(`COMMAND_FAILED`,`Failed to resolve Android launch component for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,no,`-c`,i,`-n`,o])}function oo(e,t){return t.includes(`/`)?t:`${e}/${t.startsWith(`.`)?t:`.${t}`}`}let so=null;function co(e){return`${e.PATH??``}::${e.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function lo(e){let n=co(e);if(so?.key===n)return so.invocation;if(await Oe(`bundletool`)){let e={cmd:`bundletool`,prefixArgs:[]};return so={key:n,invocation:e},e}let r=await Ae(e.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return so={key:n,invocation:i},i}async function uo(e,t,n){let r=await lo(n);await De(r.cmd,[...r.prefixArgs,...e],{signal:t})}function fo(e){return E.extname(e).toLowerCase()===`.aab`}async function po(e,t,n={}){let r=C(e),i=`universal`;if(r.installBundle){await r.installBundle(t,{mode:i,signal:n.signal});return}let a=x().files,o=await a.makeTempDirectory(`agent-device-aab-`),s=E.join(o,`bundle.apks`);try{await uo([`build-apks`,`--bundle`,t,`--output`,s,`--mode`,i],n.signal,n.environment??x().environment),await uo([`install-apks`,`--apks`,s,`--device-id`,e.id],n.signal,n.environment??x().environment)}finally{await a.remove(o,{recursive:!0,force:!0})}}async function mo(e,t,n={}){if(fo(t)){await po(e,t,n);return}await qe(t,{device:e,replace:!0,signal:n.signal})}async function ho(e,t,n={}){await wt(e,async()=>{e.booted||await ht(e.id,void 0,n.signal),await mo(e,t,n)})}const go=[`mInputShown`,`mIsInputViewShown`,`isInputViewShown`,`mDecorViewVisible`,`mWindowVisible`,`mInShowWindow`],_o=new Map([[2,`number`],[3,`phone`],[4,`datetime`]]),vo=new Set([32,208]),yo=new Set([128,224,144]);async function bo(e){return await H(y(e))}async function H(e){let t=await b(e,[`dumpsys`,`input_method`],{allowFailure:!0});if(t.exitCode!==0)throw w(`Failed to query Android keyboard state`,t);return Co(t.stdout)}async function xo(e){return await So(y(e))}async function So(e){let n=await H(e),r=n,i=0;try{for(;r.visible&&i<2;)await b(e,[`input`,`keyevent`,`111`]),i+=1,await _(120),r=await H(e)}catch(e){throw l(e,i)}if(n.visible&&r.visible)throw new t(`UNSUPPORTED_OPERATION`,`Android keyboard dismiss is unavailable for the current IME without back navigation.`,{attempts:i,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner});return{attempts:i,wasVisible:n.visible,dismissed:n.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}function Co(e){let t=Oo(e)??wo(e),n=To(e),r=Eo(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),i=Eo(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),a=ee(e),o=ne(r,i,a);return Do(r,i,a),{visible:t??!1,inputType:n,type:n?Mo(n):void 0,inputMethodPackage:a,focusedPackage:r,focusedResourceId:i,inputOwner:o}}function wo(e){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/)?.[1];if(!t)return null;let n=Number.parseInt(t,16);return Number.isNaN(n)?null:!!(n&1)}function To(e){let t=Eo(e,/\binputType=0x([0-9a-fA-F]+)\b/gi);return t?`0x${t.toLowerCase()}`:void 0}function Eo(e,t){let n;for(let r of e.matchAll(t))n=r[1];return n}function Do(e,t,n){n||!p(e)&&!d(t)||g({level:`warn`,phase:`android_input_ownership_fallback`,data:{focusedPackage:e,focusedResourceId:t}})}function Oo(e){return Ao(ko(e,go))}function ko(e,t){let n=new Map,r=RegExp(`\\b(${t.join(`|`)})=([a-zA-Z]+)\\b`,`g`);for(let t of e.matchAll(r)){let e=t[1],r=t[2]?.toLowerCase();!e||r!==`true`&&r!==`false`||n.set(e,r===`true`)}return n}function Ao(e){if(e.size===0)return null;let t=jo(e,[`mWindowVisible`,`mDecorViewVisible`,`mInShowWindow`]);if(t!==void 0)return t;let n=e.get(`mInputShown`);return n===void 0?jo(e,[`mIsInputViewShown`,`isInputViewShown`])??null:n}function jo(e,t){for(let n of t){let t=e.get(n);if(t!==void 0)return t}}function Mo(e){let t=Number.parseInt(e.replace(/^0x/i,``),16);if(Number.isNaN(t))return`unknown`;let n=t&15,r=_o.get(n);if(r)return r;if(n!==1)return`unknown`;let i=t&4080;return vo.has(i)?`email`:yo.has(i)?`password`:`text`}async function No(e){return await Po(y(e))}async function Po(e){return Ro(await Lo(e,[`cmd`,`clipboard`,`get`,`text`],`read`))}async function Fo(e,t){await Io(y(e),t)}async function Io(e,t){await Lo(e,[`cmd`,`clipboard`,`set`,`text`,t],`write`)}async function Lo(e,t,n){let{androidClipboardShellCommandUnavailableError:r,classifyAndroidClipboardShellResponse:i}=await import(`./clipboard-shell-response.js`),a=await b(e,t,{allowFailure:!0}),o=i(a);if(o===`no-shell-command`)throw r(n);if(o===`call-failed`)throw w(`Failed to ${n} Android clipboard text`,a);return a.stdout}function Ro(e){let t=e.replaceAll(`\r
|
|
8
|
+
`);if(r<0)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=Rr(e.slice(0,r)),a=e.slice(r+2);return Ir(i,n),Lr(i,a),{xml:a,metadata:zr(i)}}function Ir(e,n){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==n)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:n});if(e.ok!==`true`)throw new t(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e,...Er(wr(e))})}function Lr(e,n){let r=k(e.byteLength);if(r!==void 0&&Buffer.byteLength(n,`utf8`)!==r)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(n,`utf8`)});if(!n.includes(`<hierarchy`)||!n.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:n})}function Rr(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function zr(e){return{helperApiVersion:e.helperApiVersion,outputFormat:er,waitForIdleTimeoutMs:k(e.waitForIdleTimeoutMs),waitForIdleQuietMs:k(e.waitForIdleQuietMs),timeoutMs:k(e.timeoutMs),maxDepth:k(e.maxDepth),maxNodes:k(e.maxNodes),rootPresent:zn(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:k(e.windowCount),nodeCount:k(e.nodeCount),truncated:zn(e.truncated),elapsedMs:k(e.elapsedMs),pixelDensity:k(e.pixelDensity)}}function M(e,n,r,i){if(i instanceof t){let a=i.details??{};return new t(i.code,i.message,{...a,action:e,package:r,tool:n,hint:typeof a.hint==`string`?a.hint:Hr(n,a)},i)}return new t(`COMMAND_FAILED`,`Failed to ${e} Android ${n} for ${r}`,{action:e,package:r,tool:n,hint:Br(n)},i)}function Br(e){return e===`simpleperf`?`Verify simpleperf is available, the app process is running, and the app/device permits native CPU profiling.`:`Verify perfetto is available, the app process is running, and the device permits trace capture.`}function Vr(e){return e===`simpleperf`?`Use an emulator/system image with simpleperf available, or install the Android NDK simpleperf binary for this device.`:`Use Android 10+ or a system image that exposes the perfetto command-line binary.`}function Hr(e,t){let n=(typeof t.stderr==`string`?t.stderr:``).toLowerCase();return e===`simpleperf`?Ur(n):Gr(n)?`Use a device image that permits perfetto trace capture for shell, keep the app running, then retry perf trace start.`:Br(e)}function Ur(e){return Wr(e)?`Use a debuggable/profileable Android app or a device image that permits simpleperf for the target process, then retry perf cpu profile start.`:e.includes(`not supported`)||e.includes(`failed to open perf event`)?`This device image does not expose the requested simpleperf event for the app process. Try a different emulator/system image or a profileable app.`:Br(`simpleperf`)}function Wr(e){return e.includes(`permission denied`)||e.includes(`not profileable`)||e.includes(`profileable`)}function Gr(e){return e.includes(`permission denied`)||e.includes(`not allowed`)}const Kr=`adb-shell-simpleperf`,qr=`adb-shell-perfetto`,Jr=15e3,N=3e4,Yr=`/data/local/tmp`;async function Xr(e,n){try{let t=await b(e,[`pidof`,n],{allowFailure:!0,timeoutMs:Jr}),r=Qr(t.stdout);if(t.exitCode===0&&r)return r}catch{}throw new t(`COMMAND_FAILED`,`No active Android app process found for ${n}`,{package:n,hint:`Run open <app> for this session again, wait for the app UI to appear, then retry perf.`})}async function Zr(e,n,r){let i=await b(e,[_(`command -v ${v(n)} || which ${v(n)}`)],{allowFailure:!0,timeoutMs:Jr});if(!(i.exitCode===0&&i.stdout.trim()))throw new t(`UNSUPPORTED_OPERATION`,`Android device does not expose ${n}`,{package:r,tool:n,hint:Vr(n)})}function Qr(e){return e.trim().split(/\s+/).find(e=>/^\d+$/.test(e))}const $r=2e3,ei=`android_snapshot_helper_runtime_occupied`,P=new Map;function ti(e){return`${e.platform}:${e.id}`}async function ni(e){await hi({adb:e.adb,packageName:e.packageName}),await ii({deviceKey:e.deviceKey,packageName:e.packageName,adb:e.adb,cause:e.cause})}async function ri(e){let t=P.get(e.deviceKey);if(!t)return;await hi({adb:e.adb,packageName:t.packageName,timeoutMs:5e3,...e.signal?{signal:e.signal}:{}}),e.signal?.throwIfAborted();let n=await si({adb:e.adb,packageName:t.packageName});if(n===`occupied`&&(await g(250),n=await si({adb:e.adb,packageName:t.packageName})),n===`occupied`)throw oi({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause});n!==`unknown`&&P.delete(e.deviceKey)}async function ii(e){let t=e.release??await si({adb:e.adb,packageName:e.packageName});if(t===`released`)return P.delete(e.deviceKey),t;let n=e.cause instanceof Error?e.cause.message:String(e.cause);return P.set(e.deviceKey,{packageName:e.packageName,cause:n}),h({level:`warn`,phase:`android_snapshot_helper_retirement_pending`,data:{deviceKey:e.deviceKey,packageName:e.packageName,release:t}}),t}function ai(e){return e instanceof t&&e.details?.reason===ei}function oi(e){let n=e.cause instanceof Error?e.cause.message:String(e.cause);return new t(`COMMAND_FAILED`,`Android automation helper is still holding device automation ownership`,{reason:ei,deviceKey:e.deviceKey,packageName:e.packageName,cause:n,hint:`Retry after the helper process exits, or restart the device if Android keeps reporting the helper as running.`})}async function si(e){try{let t=await b(e.adb,[`pidof`,e.packageName,_(`|| echo AGENT_DEVICE_NO_HELPER`)],{allowFailure:!0,timeoutMs:$r}),n=t.stdout.trim();return Qr(n)?`occupied`:n===`AGENT_DEVICE_NO_HELPER`&&t.stderr.trim().length===0?`released`:`unknown`}catch{return`unknown`}}async function ci(e){let t=AbortSignal.timeout(e.timeoutMs);return await Promise.all([...e.forceStopRuntime?[hi({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t})]:[],gi({...e,signal:t})]),{timedOut:t.aborted}}function li(e){let t=ui(e);return{ended:t?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())}),hasEnded:()=>ui(e),completedCleanly:()=>!t&&e.exitCode===0&&e.signalCode==null}}function ui(e){return e.exitCode!=null||e.signalCode!=null}async function di(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function fi(e){if(e.processExit.hasEnded())return!0;try{e.process.kill(`SIGTERM`)}catch{}return await di(e.processExit.ended,e.timeoutMs)}function pi(e){P.delete(e)}function mi(){P.clear()}async function hi(e){await b(e.adb,[`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs??2e3,...e.signal?{signal:e.signal}:{}}).catch(()=>{})}async function gi(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function _i(e){let n=yi(e),r=e.deviceKey??`android:default`;await ri({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(bi(n),{allowFailure:!0,timeoutMs:n.commandTimeoutMs,signal:e.signal})}catch(t){throw e.signal?.aborted?(await ni({deviceKey:r,packageName:n.packageName,adb:e.adb,cause:t}),e.signal.throwIfAborted(),t):t}e.signal?.aborted&&(await ni({deviceKey:r,packageName:n.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await xi(e,n,i);if(n.outputPath&&!o&&await Oi(e.adb,n.outputPath),i.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android snapshot helper failed`,Me(i,{helper:a.metadata}));return a}function vi(e){return{adb:e.adb,adbProvider:e.adbProvider,deviceKey:e.deviceKey,helperVersion:e.artifact.manifest.version,helperVersionCode:e.artifact.manifest.versionCode,helperSha256:e.artifact.manifest.sha256,packageName:e.artifact.manifest.packageName,instrumentationRunner:e.artifact.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:tr,commandTimeoutMs:nr,...e.signal?{signal:e.signal}:{}}}function yi(e){let t=F(e.timeoutMs,8e3),n=F(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:F(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:F(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:F(e.commandTimeoutMs,t+5e3),maxDepth:F(e.maxDepth,128),maxNodes:F(e.maxNodes,5e3),packageName:n,runner:F(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function F(e,t){return e===void 0?t:e}function bi(e,t={}){return Pe(`adb`,`shell`,[`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],...t.sessionPort===void 0?[]:[`-e`,`sessionPort`,t.sessionPort],e.runner])}async function xi(e,t,n){try{return{output:ki(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Si(e,t,n,r)}}async function Si(e,n,r,i){if(i instanceof t&&r.exitCode!==0&&i.details?.helper)throw i;let a=await Ci(e,n,r);if(a)return{output:a,cleanupDone:!0};throw new t(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,...Er(Tr(r.exitCode))},i)}async function Ci(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Ti(e.adb,t.outputPath,Di(`${n.stdout}\n${n.stderr}`)??wi(t))}function wi(e){return{outputFormat:er,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Ti(e,t,n){let r;try{r=await b(e,Ei(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Ei(e){return[`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Di(e){try{return Li(ji(Nn(e).results))}catch{return null}}async function Oi(e,t){try{await b(e,[`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function ki(e){let t=Nn(e),n=ji(t.results);return{xml:Ni(Ai(t.status),n),metadata:{...Li(n),transport:`instrumentation`}}}function Ai(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:I(n.chunkIndex),count:I(n.chunkCount),payloadBase64:e})}return t}function ji(e){let n=e.find(e=>e.agentDeviceProtocol===$n);if(!n)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(n.ok!==`true`)throw new t(`COMMAND_FAILED`,Mi(n),{errorType:n.errorType,helper:n,...Er(wr(n))});return n}function Mi(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Ni(e,n){if(e.length===0)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:n});let r=Pi(e),i=Buffer.concat(Ii(Fi(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Pi(e){let n=e[0]?.count??e.length;if(n<1||e.length!==n||e.some(e=>e.count!==n))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:n,actualChunks:e.length});return n}function Fi(e,n){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=n)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:n});if(r.has(i.index))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Ii(e,n){let r=[];for(let i=0;i<n;i+=1){let a=e.get(i);if(a===void 0)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:n});r.push(Buffer.from(a,`base64`))}return r}function Li(e){return{helperApiVersion:e.helperApiVersion,outputFormat:er,waitForIdleTimeoutMs:I(e.waitForIdleTimeoutMs),waitForIdleQuietMs:I(e.waitForIdleQuietMs),timeoutMs:I(e.timeoutMs),maxDepth:I(e.maxDepth),maxNodes:I(e.maxNodes),rootPresent:zi(e.rootPresent),captureMode:Ri(e.captureMode),windowCount:I(e.windowCount),nodeCount:I(e.nodeCount),truncated:zi(e.truncated),elapsedMs:I(e.elapsedMs),pixelDensity:I(e.pixelDensity)}}function Ri(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const I=k,zi=zn,Bi=5e3,L=new Map,R=new Map;async function Vi(e){return await Hi(e)!==void 0}async function Hi(e){let t=e.deviceKey??`android:default`;if(await ri({deviceKey:t,adb:e.adb,signal:e.signal}),!ea()||!e.adbProvider?.spawn)return;let n=yi(e),r=Qi(n),i=await Wi({deviceKey:t,identity:Zi(t,r,e),options:e,resolved:r,startBudgetMs:$i(n.commandTimeoutMs)});return i?{session:i,resolved:r,deviceKey:t}:void 0}function Ui(e){return L.get(e)}async function Wi(e){if(!qi(e.identity))return await Gi(e.deviceKey,e.identity),L.get(e.deviceKey)??await Ki(e)}async function Gi(e,t){let n=L.get(e);!n||Yi(n,t)||await z(e,{force:ui(n.process)})}async function Ki(e){let n=Date.now();try{return await Xi(e)}catch(r){e.options.signal?.throwIfAborted(),R.set(e.identity,Date.now()+Ji(Date.now()-n)),h({level:`warn`,phase:`android_snapshot_helper_session_start_failed`,data:{deviceKey:e.deviceKey,reason:r instanceof t?r.details?.reason:void 0,detail:r instanceof Error?r.message:String(r)}});return}}function qi(e){let t=R.get(e);return t===void 0?!1:t>Date.now()||(R.delete(e),!1)}function Ji(e){return Math.min(Math.max(e,1e4),6e4)}function Yi(e,t){return e.identity===t&&!ui(e.process)}async function Xi(e){let t=await Dr();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:Bi,signal:e.options.signal});let n=bi({...e.resolved,outputPath:void 0,emitChunks:!1},{sessionPort:t}),r=e.options.adbProvider.spawn(n,{allowFailure:!0,captureOutput:!1}),i={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:r,startedAtMs:Date.now(),capturedCount:0};try{return await jr(r,e.startBudgetMs,e.options.signal),L.set(e.deviceKey,i),R.delete(e.identity),pi(e.deviceKey),h({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),i}catch(t){let n=li(r);try{r.kill(`SIGTERM`)}catch{}throw await Promise.all([di(n.ended,250),ci({adb:i.adb,process:i.process,port:i.port,packageName:i.helper.packageName,timeoutMs:$r,forceStopRuntime:!0})]),await ii({deviceKey:e.deviceKey,packageName:i.helper.packageName,adb:i.adb,cause:t}),t}}function Zi(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function Qi(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function $i(e){return Math.min(e,Math.max(Math.floor(e/2),5e3))}function ea(){let e=x().environment.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}async function z(e,t={}){let n=L.get(e);if(!n)return!1;L.delete(e);let r=li(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await ta(n,r,i,t.signal),o=r.hasEnded(),s=a.acknowledged&&a.exited,c=s&&await Xt({adb:n.adb,deviceKey:e,signal:t.signal}),l=i?t.signal?.aborted===!0?250:$r:Bi,u=i?250:2e3,[d,f]=await Promise.all([fi({process:n.process,processExit:r,timeoutMs:u}),ci({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:l,forceStopRuntime:t.resetRuntime===!0||!c})]),p=await ii({deviceKey:e,packageName:n.helper.packageName,adb:n.adb,cause:t.cause,...c?{release:`released`}:{}});return h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,quitExitObserved:s,releaseProvenByQuit:c,release:p,forceKilled:!o&&d,forced:i||t.signal?.aborted===!0,externalCleanupTimedOut:f.timedOut}}),!0}async function ta(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=Pr(await Or(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await di(t.ended,11e3,r)&&t.completedCleanly()}}catch{return{acknowledged:!1,exited:!1}}}async function na(e){await z(ti(e))}async function ra(){try{await Promise.allSettled([...L.keys()].map(async e=>{await z(e)}))}finally{L.clear(),R.clear(),mi(),Zt()}}async function ia(e){let t=await Hi(e);if(t)return await aa({session:t.session,deviceKey:t.deviceKey,options:e,resolved:t.resolved})}async function aa(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await kr({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await z(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:mt(e)===`accessibility-timeout`}});return}}function B(e,n){return e!==`gesture`||!(n instanceof t)?n:i(n,at(n)?`no`:`unknown`)}async function oa(e){let n=Ui(e.deviceKey);if(!n)return;if(!sa(n.helper,e.helper)){h({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:n.helper,requestedHelper:e.helper}}),await z(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=Mr(await Or(n.port,i,e.timeoutMs)),Nr(a,r)}catch(t){throw await z(e.deviceKey),B(e.action,t)}if(a.ok!==`true`)throw B(e.action,new t(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a}));return a}function sa(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&ca(e.helperVersion,t.helperVersion)&&ca(e.helperVersionCode,t.helperVersionCode)&&ca(e.sha256,t.sha256)}function ca(e,t){return e===void 0||t===void 0||e===t}const la=`android-touch-plan-v1`,ua=45e3,da=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,fa=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function pa(e,t){let n=await ga(e),r=va(t),i=Math.max(45e3,r.durationMs+15e3),a=Buffer.from(JSON.stringify({protocol:la,...r})).toString(`base64`),o=await m(`android_touch_helper_gesture`,async()=>{let e=await oa({deviceKey:n.deviceKey,action:`gesture`,helper:ha(n.artifact),payloadBase64:a,timeoutMs:i});return e?{...Sa(e),helperTransport:`persistent-session`}:{...await ba({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,action:`gesture`,extraArgs:[`-e`,`payloadBase64`,a],timeoutMs:i,readResult:Sa}),helperTransport:`instrumentation`}},{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version});return{backend:`android-helper`,helperVersion:n.artifact.manifest.version,installReason:n.install.reason,...o}}async function ma(e,t={}){let n=await ga(e);t.helperSessionScope===`daemon-session`&&await Vi(vi({adb:n.adb,adbProvider:n.adbProvider,artifact:n.artifact,deviceKey:n.deviceKey}));try{let e=await oa({deviceKey:n.deviceKey,action:`viewport`,helper:ha(n.artifact),timeoutMs:ua});if(e)return Ca(e)}catch(e){await z(n.deviceKey),h({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await ba({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,action:`viewport`,extraArgs:[],timeoutMs:ua,readResult:Ca})}function ha(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function ga(e){let t=C(e),n=t.snapshotHelperArtifact??await _a(),r=ti(e);await ri({deviceKey:r,adb:t.exec});let i=await m(`android_touch_helper_install`,async()=>await _r({adb:t.exec,adbProvider:t,artifact:n,deviceKey:r,timeoutMs:3e4}),{packageName:n.manifest.packageName,versionCode:n.manifest.versionCode});return h({phase:`android_touch_helper_install_decision`,data:i}),i.installed&&await z(r),{adb:t.exec,adbProvider:t,artifact:n,install:i,deviceKey:r}}async function _a(){return await Gn({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=rr(e);return{...t,assetName:t.assetName??`agent-device-android-snapshot-helper-${t.version}.apk`}},unavailableMessage:`Android touch gestures require the bundled Android automation helper artifact, but it was not found or could not be read`})}function va(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(ya)}}function ya(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function ba(e){let n=await b(e.adb,[`am`,`instrument`,`-w`,`-e`,`mode`,e.action,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=xa(`${n.stdout}\n${n.stderr}`)}catch(r){if(r instanceof t){if(r.code===fa)throw B(e.action,new t(`COMMAND_FAILED`,r.message,r.details,r));if(r.code!==da)throw r}let i=new t(`COMMAND_FAILED`,n.exitCode===0?`Android automation helper output could not be parsed`:`Android automation helper failed before returning parseable output`,Me(n),r);throw B(e.action,n.exitCode===0?i:it(i))}if(n.exitCode!==0)throw B(e.action,it(new t(`COMMAND_FAILED`,`Android automation helper failed`,Me(n,{helper:r}))));return e.readResult(r)}function xa(e){let n=Nn(e).results.find(e=>e.agentDeviceProtocol===$n);if(!n)throw new t(da,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(fa,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function Sa(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:k(e.injectedEvents),elapsedMs:k(e.elapsedMs)}}function Ca(e){let n=k(e.x),r=k(e.y),i=k(e.width),a=k(e.height);if(n===void 0||r===void 0||i===void 0||a===void 0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);let o=wa(e);return{viewport:Bn({x:n,y:r,width:i,height:a}),...o?{keyboard:o}:{}}}function wa(e){let t=k(e.keyboardX),n=k(e.keyboardY),r=k(e.keyboardWidth),i=k(e.keyboardHeight);if(t!==void 0&&n!==void 0&&r!==void 0&&i!==void 0)return{x:t,y:n,width:r,height:i}}function Ta(e){if(e.topology===`two`||e.intent===`longPress`)return e;let{releaseBehavior:t,...n}=e,[{pointerId:r,samples:i}]=n.pointers,a=[...new Set([...dt(e.durationMs,`android`),...i.map(({offsetMs:e})=>e)])].sort((e,t)=>e-t),o=0,s=a.map(e=>{for(;o<i.length-2&&e>i[o+1].offsetMs;)o+=1;let n=i[o],r=i[o+1],a=r.offsetMs-n.offsetMs,s=(e-n.offsetMs)/a;return{offsetMs:e,point:e===r.offsetMs||a===0?r.point:pt(n.point,r.point,t===`controlled`?Ea(s,a):s)}}),c=[s[0],s[1],s[2],...s.slice(3)];return{...n,pointers:[{pointerId:r,samples:c}]}}function Ea(e,t){let n=Math.min(16/t,.5);return e<n?e**2/n:1-(1-e)**2/(1-n)}async function Da(e,t){let n=Ta(t),r=Be(e);if(r){let e=n.intent===`longPress`?{...n,viewport:Bn(await r.gestureViewport())}:n;return{backend:`provider-native-touch`,...await r.touch(e)??{}}}return await pa(e,n)}async function Oa(e,t={}){return(await ka(e,t)).viewport}async function ka(e,t={}){let n=Be(e);return n?{viewport:Bn(await n.gestureViewport())}:await ma(e,t)}async function V(e,t,n){try{await T(e,[`input`,`tap`,t,n])}catch(e){throw rt(e)}}async function Aa(e,t,n){await V(e,t,n);try{await V(e,t,n)}catch(e){throw l(e,1)}}async function ja(e,t,n){let r=Ne(t);await T(e,[`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function Ma(e){await T(e,[`input`,`keyevent`,`4`])}async function Na(e){await T(e,[`input`,`keyevent`,`3`])}async function Pa(e){await T(e,[`input`,`keyevent`,`ENTER`])}async function Fa(e,t){let n=qa(t);await T(e,[`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await T(e,[`settings`,`put`,`system`,`user_rotation`,n]),await La(e,t,n)}const Ia=15e3;async function La(e,n,r){let i=Date.now()+Ia,a=await Ra(e,n,i);for(;a!==void 0&&a!==r&&Date.now()<i;)await g(Math.min(500,za(i))),a=await Ra(e,n,i);if(a!==void 0&&a!==r)throw new t(`COMMAND_FAILED`,`orientation ${n} did not take effect: the display still reports rotation ${a} after ${Ia}ms`,{requestedRotation:Number(r),observedRotation:Number(a),hint:"The foreground app may pin its orientation, or the device may ignore user_rotation. Check `adb shell dumpsys display | grep mCurrentOrientation` and the app manifest."})}async function Ra(e,n,r){try{return(await Ba(e,{timeoutMs:za(r)}))[0]}catch(e){throw new t(`COMMAND_FAILED`,`orientation ${n} could not confirm the display rotation: ${e instanceof Error?e.message:String(e)}`,{hint:"The device did not answer `dumpsys display` within the orientation budget."})}}function za(e){return Math.max(1,e-Date.now())}async function Ba(e,t){let n=await T(e,[`dumpsys`,`display`],{...t,allowFailure:!0});if(n.exitCode!==0)throw w(`adb shell dumpsys display exited with code ${n.exitCode}`,n);return[...n.stdout.matchAll(/mCurrentOrientation=(\d)/g)].map(e=>e[1])}async function Va(e,t){try{let n=await Ba(e,t);return n.length===1?De(Number(n[0])):void 0}catch{return}}async function Ha(e){await T(e,[`input`,`keyevent`,`187`])}async function Ua(e,t,n,r=800){let i={x:t,y:n};return await Da(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function Wa(e,t,n){await V(e,t,n)}async function Ga(e,t,n){let{viewport:r,keyboard:i}=await ka(e,{helperSessionScope:n?.helperSessionScope}),a=Ka(t,r,i),o=pe({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:a.viewport.width,referenceHeight:a.viewport.height}),s={...o,referenceWidth:a.viewport.x+a.viewport.width,referenceHeight:a.viewport.y+a.viewport.height,x1:a.viewport.x+o.x1,y1:a.viewport.y+o.y1,x2:a.viewport.x+o.x2,y2:a.viewport.y+o.y2},c=Math.max(n?.durationMs??300,16),l=await Da(e,{...ft({intent:`pan`,origin:{x:s.x1,y:s.y1},delta:{x:s.x2-s.x1,y:s.y2-s.y1},durationMs:c},a.viewport,`android`),releaseBehavior:n?.releaseBehavior??`controlled`});return{...s,...a.evidence,...n?.durationMs===void 0?{}:{durationMs:c},...l}}function Ka(e,t,n){if(n===void 0)return{viewport:t,evidence:{}};let r=me(t,n);if(r.kind===`occluded`)throw fe(e,{keyboardMinY:r.keyboardMinY,visibleHeight:r.visibleHeight,viewportHeight:t.height});return r.kind===`avoided`?{viewport:r.viewport,evidence:{keyboardAvoided:!0,keyboardMinY:r.keyboardMinY}}:{viewport:t,evidence:{}}}function qa(e){let n=Ee[e];if(n===void 0)throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`);return String(n)}async function Ja(e){let n=(await T(e,[`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}async function Ya(e,t,n){return t===`wait`?await Xa(n.captureNodes,n.timeoutMs??1e4):t===`get`?no((await to(n.captureNodes))?.alert??null):await Za(e,t,n.captureNodes)}async function Xa(e,n){let r=Date.now(),i=await eo(e,n);if(!i)throw new t(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:i.alert,waitedMs:Date.now()-r,...he(`Alert visible`)}}async function Za(e,n,r){let i=await eo(r,ge);if(!i)throw new t(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let a=fn(i.buttons,n);if(a)return await V(e,a.x,a.y),await Qa(i.alert,n,r),ro(n,i.alert,a.label,{x:a.x,y:a.y});if(n===`dismiss`)return await Ma(e),await Qa(i.alert,n,r),ro(n,i.alert,`Back`);throw new t(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:i.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function Qa(e,n,r){let i=Date.now();for(;;){let a=await to(r);if(!a||!$a(a.alert,e))return;if(Date.now()-i>=2e3)throw new t(`COMMAND_FAILED`,`alert ${n} did not dismiss the visible alert`,{alert:e,hint:`The alert button was pressed but the dialog is still visible. Inspect alert get --json, then press the visible button by label/ref or retry.`});await g(300)}}function $a(e,t){return e.title===t.title&&e.buttons.join(`\0`)===t.buttons.join(`\0`)}async function eo(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await to(e);if(t)return t;await g(300)}return null}async function to(e){return un(await m(`snapshot_capture`,e,{backend:`android`,purpose:`alert`}))}function no(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...he(e?`Alert visible`:`No alert visible`)}}function ro(e,t,n,r){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:n,...r?{coordinates:r}:{},...he(`Alert ${e}ed`)}}const io=`android.intent.category.LAUNCHER`,ao=`android.intent.category.DEFAULT`;async function oo(e,t){await b(e,[`am`,`force-stop`,t])}async function so(e,t,n=[io]){for(let r of n){let n=await b(e,[`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=bt(n.stdout);if(i)return i}return null}async function co(e,n,r={}){let i=r.category??io;if(r.activity){await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,ao,`-c`,i,`-n`,lo(n,r.activity)]);return}let a=await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,ao,`-c`,i,`-p`,n],{allowFailure:!0});if(a.exitCode===0&&!xt(a.stdout,a.stderr))return;let o=await so(e,n,[i]);if(!o)throw new t(`COMMAND_FAILED`,`Failed to resolve Android launch component for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});await b(e,[`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,ao,`-c`,i,`-n`,o])}function lo(e,t){return t.includes(`/`)?t:`${e}/${t.startsWith(`.`)?t:`.${t}`}`}let uo=null;function fo(e){return`${e.PATH??``}::${e.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function po(e){let n=fo(e);if(uo?.key===n)return uo.invocation;if(await ke(`bundletool`)){let e={cmd:`bundletool`,prefixArgs:[]};return uo={key:n,invocation:e},e}let r=await Oe(e.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return uo={key:n,invocation:i},i}async function mo(e,t,n){let r=await po(n);await Ae(r.cmd,[...r.prefixArgs,...e],{signal:t})}function ho(e){return E.extname(e).toLowerCase()===`.aab`}async function go(e,t,n={}){let r=C(e),i=`universal`;if(r.installBundle){await r.installBundle(t,{mode:i,signal:n.signal});return}let a=x().files,o=await a.makeTempDirectory(`agent-device-aab-`),s=E.join(o,`bundle.apks`);try{await mo([`build-apks`,`--bundle`,t,`--output`,s,`--mode`,i],n.signal,n.environment??x().environment),await mo([`install-apks`,`--apks`,s,`--device-id`,e.id],n.signal,n.environment??x().environment)}finally{await a.remove(o,{recursive:!0,force:!0})}}async function _o(e,t,n={}){if(ho(t)){await go(e,t,n);return}await Je(t,{device:e,replace:!0,signal:n.signal})}async function vo(e,t,n={}){await Tt(e,async()=>{e.booted||await gt(e.id,void 0,n.signal),await _o(e,t,n)})}const yo=[`mInputShown`,`mIsInputViewShown`,`isInputViewShown`,`mDecorViewVisible`,`mWindowVisible`,`mInShowWindow`],bo=new Map([[2,`number`],[3,`phone`],[4,`datetime`]]),xo=new Set([32,208]),So=new Set([128,224,144]);async function Co(e){return await H(y(e))}async function H(e){let t=await b(e,[`dumpsys`,`input_method`],{allowFailure:!0});if(t.exitCode!==0)throw w(`Failed to query Android keyboard state`,t);return Eo(t.stdout)}async function wo(e){return await To(y(e))}async function To(e){let n=await H(e),r=n,i=0;try{for(;r.visible&&i<2;)await b(e,[`input`,`keyevent`,`111`]),i+=1,await g(120),r=await H(e)}catch(e){throw l(e,i)}if(n.visible&&r.visible)throw new t(`UNSUPPORTED_OPERATION`,`Android keyboard dismiss is unavailable for the current IME without back navigation.`,{attempts:i,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner});return{attempts:i,wasVisible:n.visible,dismissed:n.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}function Eo(e){let t=jo(e)??Do(e),n=Oo(e),r=ko(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),i=ko(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),a=te(e),o=re(r,i,a);return Ao(r,i,a),{visible:t??!1,inputType:n,type:n?Fo(n):void 0,inputMethodPackage:a,focusedPackage:r,focusedResourceId:i,inputOwner:o}}function Do(e){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/)?.[1];if(!t)return null;let n=Number.parseInt(t,16);return Number.isNaN(n)?null:!!(n&1)}function Oo(e){let t=ko(e,/\binputType=0x([0-9a-fA-F]+)\b/gi);return t?`0x${t.toLowerCase()}`:void 0}function ko(e,t){let n;for(let r of e.matchAll(t))n=r[1];return n}function Ao(e,t,n){n||!p(e)&&!d(t)||h({level:`warn`,phase:`android_input_ownership_fallback`,data:{focusedPackage:e,focusedResourceId:t}})}function jo(e){return No(Mo(e,yo))}function Mo(e,t){let n=new Map,r=RegExp(`\\b(${t.join(`|`)})=([a-zA-Z]+)\\b`,`g`);for(let t of e.matchAll(r)){let e=t[1],r=t[2]?.toLowerCase();!e||r!==`true`&&r!==`false`||n.set(e,r===`true`)}return n}function No(e){if(e.size===0)return null;let t=Po(e,[`mWindowVisible`,`mDecorViewVisible`,`mInShowWindow`]);if(t!==void 0)return t;let n=e.get(`mInputShown`);return n===void 0?Po(e,[`mIsInputViewShown`,`isInputViewShown`])??null:n}function Po(e,t){for(let n of t){let t=e.get(n);if(t!==void 0)return t}}function Fo(e){let t=Number.parseInt(e.replace(/^0x/i,``),16);if(Number.isNaN(t))return`unknown`;let n=t&15,r=bo.get(n);if(r)return r;if(n!==1)return`unknown`;let i=t&4080;return xo.has(i)?`email`:So.has(i)?`password`:`text`}async function Io(e){return await Lo(y(e))}async function Lo(e){return Vo(await Bo(e,[`cmd`,`clipboard`,`get`,`text`],`read`))}async function Ro(e,t){await zo(y(e),t)}async function zo(e,t){await Bo(e,[`cmd`,`clipboard`,`set`,`text`,t],`write`)}async function Bo(e,t,n){let{androidClipboardShellCommandUnavailableError:r,classifyAndroidClipboardShellResponse:i}=await import(`./clipboard-shell-response.js`),a=await b(e,t,{allowFailure:!0}),o=i(a);if(o===`no-shell-command`)throw r(n);if(o===`call-failed`)throw w(`Failed to ${n} Android clipboard text`,a);return a.stdout}function Vo(e){let t=e.replaceAll(`\r
|
|
9
9
|
`,`
|
|
10
|
-
`).replace(/\n$/,``),n=t.match(/^clipboard text:\s*(.*)$/i);return n?n[1]??``:t.trim().toLowerCase()===`null`?``:t}const
|
|
11
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const gs=2e3;async function _s(e=x().environment,t=x().files){let n=e.ANDROID_HOME||e.ANDROID_SDK_ROOT,r=await ks(n,t),i=await Rt(`adb`,[`version`]);return i?Ts({license:r,sdkRoot:n,versionLine:i}):Os(n,r)}async function vs(e,t){if(e.platform!==`android`)return[];let n=y(e,t.transportOverrides.androidAdb),r=[];return t.shouldProbeMetro&&r.push(await ws(n,e.id,t.metroPort)),r.push(await ys(n,e)),r}async function ys(e,t){try{let n=await G(e),r=ss(t);return n===await bs()&&!r?await xs(e,t,n):Ss(t,n,r)}catch(e){return Cs(e)}}async function bs(){try{return(await Ho()).manifest.serviceComponent}catch{return}}async function xs(e,t,n){let r=(await b(e,[`settings`,`get`,`secure`,es.previousIme],{allowFailure:!0,timeoutMs:gs})).stdout.trim(),i=r&&r!==`null`?r:void 0;return{id:`android-test-ime`,status:`fail`,summary:`Android test IME helper is the active input method on ${t.id}, but no active session owns it -- likely left over from a crashed session.`,hint:`A stuck test IME leaves the real keyboard unavailable on this device until restored.`,command:i?`adb -s ${t.id} shell ime set ${i}`:`adb -s ${t.id} shell ime list -s`,evidence:{currentIme:n,previousIme:i}}}function Ss(e,t,n){return{id:`android-test-ime`,status:`pass`,summary:n?`Android test IME helper is active for this session on ${e.id}.`:`Android test IME helper is not active on ${e.id}; the device's normal IME is in use.`,evidence:{currentIme:t}}}function Cs(e){let t=s(e);return{id:`android-test-ime`,status:`warn`,summary:`Could not inspect the Android test IME helper state.`,hint:t.message,evidence:{code:t.code}}}async function ws(e,t,n){try{let r=await e([`reverse`,`--list`],{allowFailure:!0,timeoutMs:gs}),i=`tcp:${n} tcp:${n}`,a=r.stdout.includes(i);return{id:`android-reverse`,status:a?`pass`:`warn`,summary:a?`Android adb reverse exists for Metro port ${n}.`:`Android adb reverse is missing for Metro port ${n}.`,command:a?void 0:`adb -s ${t} reverse tcp:${n} tcp:${n}`,evidence:{stdout:r.stdout.trim()}}}catch(e){let t=s(e);return{id:`android-reverse`,status:`warn`,summary:`Could not inspect Android adb reverse mappings.`,hint:t.message,evidence:{code:t.code}}}}function Ts(e){return{id:`toolchain`,status:Es(e),summary:e.versionLine?`Android toolchain: ${e.versionLine}; ${Ds(e.sdkRoot)}.`:`Android toolchain: adb is present but version check failed.`,hint:e.license===`missing`?`Accept Android SDK licenses before installing/building apps.`:void 0,command:e.license===`missing`?`sdkmanager --licenses`:void 0,evidence:{adbVersion:e.versionLine??null,androidHome:e.sdkRoot??null,license:e.license}}}function Es(e){return e.versionLine&&e.sdkRoot&&e.license!==`missing`?`pass`:`info`}function Ds(e){return e?`ANDROID_HOME/ANDROID_SDK_ROOT set`:`ANDROID_HOME unset`}function Os(e,t){return{id:`toolchain`,status:`info`,summary:`Android toolchain: adb not found on PATH.`,hint:`Install Android platform-tools or add adb to PATH.`,evidence:{androidHome:e??null,license:t}}}async function ks(e,t){if(!e)return`unknown`;try{return await t.access(E.join(e,`licenses`,`android-sdk-license`)),`accepted`}catch{return`missing`}}function As(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=Ps(t),r={failureReason:t.reason??`text_mismatch`,targetInput:Ms(t.targetInput),actualInput:Ms(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function J(e){return e?e.password?!0:js(e.text):!1}function js(e){return e?Array.from(e).every(Ns):!1}function Ms(e){if(!e)return null;let t=J(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function Ns(e){return e===`•`||e===`*`||e===`●`}function Ps(e){return e.masked===!0||J(e.targetInput)||J(e.actualInput)}const Fs=new WeakMap;function Is(e,t){return t&&Fs.set(e,t),e}function Ls(e){return Fs.get(e)}function Rs(e){return e.clickable}function zs(e){return e.focusable||e.focused===!0}function Y(e){return Rs(e)||zs(e)}function Bs(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function Vs(e,t){return{raw:e,...t?{effectiveRect:t}:{}}}function Hs(e,t,n){if(!e)return;let r=Gs(e);return t&&(r=Ws(r,t)),n&&(r=Ws(r,n)),r}function Us(e){return{...e.raw,...e.effectiveRect?{rect:e.effectiveRect}:{rect:void 0},hittable:e.raw.hittable===!0&&ce(e.effectiveRect)?!0:void 0}}function Ws(e,t){let n=Math.max(e.x,t.x),r=Math.max(e.y,t.y),i=Math.min(e.x+e.width,t.x+t.width),a=Math.min(e.y+e.height,t.y+t.height),o=i>n&&a>r;return{x:o?n:e.x,y:o?r:e.y,width:o?i-n:0,height:o?a-r:0}}function Gs(e){return{x:e.x,y:e.y,width:Math.max(0,e.width),height:Math.max(0,e.height)}}function Ks(e,t){let n=new Set;return qs(e,n,t),Ys(e,n,t),n}function qs(e,t,n){for(let r of e.children){if(n?.check(`work`),r.visibleToUser===!1){t.add(r);continue}qs(r,t,n)}}function Js(e,t,n){return n?.check(`work`),e.children.filter(e=>!t.has(e)&&e.visibleToUser!==!1)}function Ys(e,t,n){let r=Js(e,t,n).filter(Zs);if(r.length<2)return;let i=r.filter(e=>Qs(e)&&$s(e));if(i.length===0)return;let a=Xs(i);for(let r of Js(e,t,n))n?.check(`work`),Qs(r)&&($s(r)&&(a===void 0||r.windowLayer===a)||t.add(r))}function Xs(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function Zs(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Qs(e){return e.windowType===1}function $s(e){return e.windowActive===!0||e.windowFocused===!0}function ec(e,t,n,r,i){let a=new Set(e.sourceNodes),o=nc(t,i),s=tc(o,n,rc(o,a,i),i);if(!s)return{nodes:[],sourceNodes:[]};let c=new Set(nc([s],i)),l=[];for(let[t,n]of e.sourceNodes.entries())i.check(`work`),c.has(n)&&l.push(t);if(l.length===0)return{nodes:[],sourceNodes:[]};let u=1/0;for(let t of l)i.check(`work`),u=Math.min(u,e.nodes[t]?.depth??0);let d=[];for(let t of l)i.check(`work`),(e.nodes[t]?.depth??0)-u<=r&&d.push(t);return i.consume(d.length),{nodes:se(d.map(t=>e.nodes[t]),u),sourceNodes:d.map(t=>e.sourceNodes[t])}}function tc(e,t,n,r){for(let i of e)if(r.check(`work`),ie(i,t)&&n.has(i))return i;return null}function nc(e,t){let n=[],r=[...e].reverse();for(;r.length>0;){t.check(`work`);let e=r.pop();n.push(e);for(let n=e.children.length-1;n>=0;--n)t.check(`work`),r.push(e.children[n])}return n}function rc(e,t,n){let r=new Set;for(let i=e.length-1;i>=0;--i){n.check(`work`);let a=e[i];if(t.has(a)){r.add(a);continue}for(let e of a.children)if(n.check(`work`),r.has(e)){r.add(a);break}}return r}function ic(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=ac(e);return t.interactiveOnly?oc(e,a,n,r,i):a.isStructural||a.isVisual?lc(e,a,r):!0}function ac(e){let t=dc(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!Bs(e.label??``),hasMeaningfulId:r&&!Bs(e.identifier??``),isStructural:fc(t),isVisual:t===`imageview`||t===`imagebutton`}}function oc(e,t,n,r,i){return cc(e)?!1:Y(e)||ae(t.type)&&r?!0:sc(t,n,r,i)}function sc(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r&&!t?!1:t||n||r}function cc(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function lc(e,t,n){return Y(e)||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function uc(e){if(!e)return!1;let t=dc(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function dc(e){return e?e.toLowerCase():``}function fc(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function pc(e,t,n,r){return{...Vs(e,t),...n?{clipsDescendants:!0}:{},...r?{windowRect:r}:{}}}const mc=`ANDROID_SNAPSHOT_PRESENTATION_FAILED`;var X=class extends Error{code=mc;qualityReasonCode=`presentation-failed`;details;analysis;constructor(e,t,n){super(e),this.name=`AndroidSnapshotPresentationFailure`,this.details=t,this.analysis=n}};function hc(e){return e instanceof X?e.code===mc:!!(e&&typeof e==`object`&&e.code===mc)}var gc=class{workUnits=0;options;defaultMaxWorkUnits;deadlineAtMs;constructor(e,t){this.options=e,this.defaultMaxWorkUnits=t;let n=e.now??Date.now;this.deadlineAtMs=e.deadlineAtMs??n()+xc()}get workUnitCount(){return this.workUnits}check(e){this.consume(1)}consume(e){this.workUnits+=e;let t=this.options.maxWorkUnits??this.defaultMaxWorkUnits;if(this.workUnits>t)throw new X(`Android snapshot presentation exceeded its linear work budget`,{phase:`complexity`,workUnits:this.workUnits,maxWorkUnits:t});if((this.options.now??Date.now)()>=this.deadlineAtMs)throw new X(`Android snapshot presentation exceeded its cooperative deadline`,{phase:`deadline`,workUnits:this.workUnits,deadlineAtMs:this.deadlineAtMs,maxWorkUnits:t})}};function _c(e,t){return new gc(e??{},t)}function vc(e,t,n){let r=new Map;for(let i of e){n.check(`regular-invariant`);let e=yc(i,r,t),a=i.effectiveRect;if(!a||!ce(a)){if(Us(i).hittable===!0)throw new X(`Android regular snapshot node ${i.raw.index} with degenerate effective geometry was marked hittable`,{phase:`regular-invariant`,workUnits:n.workUnitCount,nodeIndex:i.raw.index,frame:a});r.set(i.raw.index,e);continue}if(e&&!bc(a,e))throw new X(`Android regular snapshot node ${i.raw.index} escaped its cumulative clip`,{phase:`regular-invariant`,workUnits:n.workUnitCount,nodeIndex:i.raw.index,frame:a,clip:e});r.set(i.raw.index,i.clipsDescendants?a:e)}}function yc(e,t,n){let r=e.raw.parentIndex;return r===void 0?e.windowRect??n:t.get(r)??e.windowRect??n}function bc(e,t){let n=1e-4;return e.x>=t.x-n&&e.y>=t.y-n&&e.x+e.width<=t.x+t.width+n&&e.y+e.height<=t.y+t.height+n}function xc(){return 250}function Sc(e,t,n){let r=n.depth??1/0,i=oe(n.scope),a=Bc(e),o=_c(n.androidPresentation,Math.max(1024,a.rawNodeCount*128)),s={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:i?1/0:r,options:n,analysis:a,interactiveDescendantMemo:new Map,hidden:new Set,presentationBudget:o,presentationNodes:[],truncated:!1};try{o.check(`work`),s.viewport=Nc(e,o),s.hidden=n.raw?new Set:Ks(e,o);for(let t of e.children)if(wc(s,t,0),s.truncated)break;n.raw||vc(s.presentationNodes,s.viewport,o);let t=s.nodes,a=new Map(s.sourceNodes.map((e,t)=>[e,t])),{nodes:c,sourceNodes:l}=i?ec(s,e.children,i,r,o):s,u={nodes:c,sourceNodes:l,occlusionContext:{nodes:t,sourceIndexByNodeIndex:new Map(l.flatMap((e,t)=>{let n=a.get(e),r=c[t]?.index;return n===void 0||r===void 0?[]:[[r,n]]})),androidSiblingOrderByNodeIndex:Cc(s.sourceNodes)},analysis:s.analysis};return s.truncated?{...u,truncated:!0}:u}catch(e){throw hc(e)&&(e.analysis??=s.analysis),e}}function Cc(e){let t=new Map,n=new Map;for(let[r,i]of e.entries()){let e=Ls(i);if(!e)continue;let a=t.get(e.parent);a===void 0&&(a=t.size,t.set(e.parent,a)),n.set(r,{group:a,order:e.order})}return n}function wc(e,t,n,r,i=!1,a=!1,o=!1,s,c){if(e.presentationBudget.check(`work`),Tc(e,t,n))return;let l=t.windowRect??s??e.viewport,u=Ec(e,t,c,l),d=Dc(e,t,r,i,a,o,u,l),f=i||Y(t),p=a||uc(t.type),m=Oc(e,t,u,c);kc(e,t,n,d,f,p,o||Vt(t.identifier),l,m)}function Tc(e,t,n){return e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes?(e.truncated=!0,!0):n>e.maxDepth||e.hidden.has(t)}function Ec(e,t,n,r){return e.options.raw?t.rect:Hs(t.rect,r,n)}function Dc(e,t,n,r,i,a,o,s){return!e.options.raw&&!ic(t,e.options,r,Ic(e,t),i)?n:Ac(e,t,n,a||Vt(t.identifier),o,s)}function Oc(e,t,n,r){return e.options.raw||!Pc(t)?r:n}function kc(e,t,n,r,i,a,o,s,c){for(let l of t.children)if(wc(e,l,n+1,r,i,a,o,s,c),e.truncated)return}function Ac(e,t,n,r,i,a){let o=e.nodes.length;return e.sourceNodes.push(t),Mc(e,t,jc(e,t,n,r),i,a),o}function jc(e,t,n,r){return{index:e.nodes.length,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,contentDescription:t.contentDescription,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,focused:t.focused,selected:t.selected,heading:t.heading,roleDescription:t.roleDescription,checked:t.checked,editable:t.editable,password:t.password,hintShowing:t.hintShowing,placeholder:t.placeholder,selectionStart:t.selectionStart,selectionEnd:t.selectionEnd,visibleToUser:t.visibleToUser,hittable:Y(t)||void 0,depth:Fc(e.nodes,n),parentIndex:n,...Lc(t,e.hidden),...r?{systemChrome:!0}:{}}}function Mc(e,t,n,r,i){let a=pc(n,r,!e.options.raw&&Pc(t),i);e.presentationNodes.push(a),e.nodes.push(e.options.raw?a.raw:Us(a))}function Nc(e,t){let n=[],r=[...e.children];for(;r.length>0;){t.check(`work`);let e=r.pop();ce(e.windowRect)&&n.push(e.windowRect),r.push(...e.children)}return le(n)??void 0}function Pc(e){return e.scrollable===!0&&ae(e.type)}function Fc(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function Ic(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(!e.hidden.has(n)&&n.visibleToUser!==!1&&(Y(n)||Ic(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function Lc(e,t){return Rc(e,t)?{...e.canScrollBackward?{hiddenContentAbove:!0}:{},...e.canScrollForward?{hiddenContentBelow:!0}:{}}:{}}function Rc(e,t){if(!e.scrollable||!ae(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let n=zc(e,t);return!(n&&n.horizontal>n.vertical&&n.horizontal>16)}function zc(e,t){let n=e.children.filter(e=>!t.has(e)&&e.visibleToUser!==!1);if(!e.rect||n.length===0)return null;let r=n.map(e=>e.rect).filter(e=>e!==void 0);if(r.length===0)return null;let i=Math.min(...r.map(e=>e.x)),a=Math.max(...r.map(e=>e.x+e.width)),o=Math.min(...r.map(e=>e.y)),s=Math.max(...r.map(e=>e.y+e.height));return{horizontal:Math.max(0,a-i-e.rect.width),vertical:Math.max(0,s-o-e.rect.height)}}function Bc(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}function Vc(){let e=[],t=()=>e.at(-1)===!0;return{open(n,r){let i=t()||Vt(n);return r||e.push(i),i},close(){e.pop()}}}function*Hc(e){let t=/<node\b[^>]*>|<\/node>/g,n=Vc(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=Uc(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function Uc(e){let t=Wc(e),n=Ht(t.bounds);return{...t,...n?{rect:n}:{}}}function Wc(e){let t=Gc(e),n=e=>$c(t,e),r=e=>{let t=n(e);if(t!==null)return t===`true`},i=e=>{let t=n(e);if(t===null||t.trim()===``)return;let r=Number(t);return Number.isFinite(r)?r:void 0},a=(e,t)=>{let n=i(t);return n===void 0?{}:{[e]:n}},o=(e,t)=>{let r=Ht(n(t));return r===void 0?{}:{[e]:r}},s=(e,t)=>{let r=n(t);return r===null||r===``?{}:{[e]:r}},c=(e,t)=>{let n=r(t);return n===void 0?{}:{[e]:n}};return{text:n(`text`),desc:n(`content-desc`),resourceId:n(`resource-id`),packageName:n(`package`),className:n(`class`),bounds:n(`bounds`),clickable:r(`clickable`),enabled:r(`enabled`),focusable:r(`focusable`),focused:r(`focused`),password:r(`password`),...c(`editable`,`editable`),...a(`selectionStart`,`selection-start`),...a(`selectionEnd`,`selection-end`),...c(`hintShowing`,`hint-showing`),...s(`hint`,`hint`),...c(`visibleToUser`,`visible-to-user`),...c(`selected`,`selected`),...c(`heading`,`heading`),...s(`roleDescription`,`role-description`),...c(`checked`,`checked`),...a(`drawingOrder`,`drawing-order`),...c(`scrollable`,`scrollable`),...c(`canScrollForward`,`can-scroll-forward`),...c(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...c(`windowActive`,`window-active`),...c(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function Gc(e){let t=new Map,n=e.indexOf(` `),r=e.lastIndexOf(`>`);if(n<0||r<=n)return t;let i=n;for(;i<r;){let n=Kc(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Kc(e,t,n){if(t=Jc(e,t,n),t>=n||Yc(e[t]))return;let r=t;t=qc(e,t,n);let i=e.slice(r,t);if(t=Jc(e,t,n),!i||e[t]!==`=`)return;t=Jc(e,t+1,n);let a=e[t];if(!Xc(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:Ut(e.slice(o,s)),nextCursor:s+1}}function qc(e,t,n){for(;t<n&&!Qc(e[t]??``);)t+=1;return t}function Jc(e,t,n){for(;t<n&&Zc(e[t]??``);)t+=1;return t}function Yc(e){return e===`/`||e===`>`}function Xc(e){return e===`"`||e===`'`}function Zc(e){return e===` `||e===`
|
|
12
|
-
`||e===`\r`||e===` `}function Qc(e){return e===`=`||e===`/`||e===`>`||Zc(e)}function $c(e,t){return e.get(t)??null}function el(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,clickable:!1,focusable:!1,depth:-1,children:[]},n=[t],r=/<node\b[^>]*>|<\/node>/g,i=r.exec(e);for(;i;){let t=i[0];if(t.startsWith(`</node`)){n.length>1&&n.pop(),i=r.exec(e);continue}let a=Uc(t),o=n.at(-1),s=tl(a,o.depth+1,o);o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return t}function tl(e,t,n){let r=e.text||e.desc;return Is({type:e.className,label:r,value:e.text,...e.desc&&e.desc!==r?{contentDescription:e.desc}:{},identifier:e.resourceId,packageName:e.packageName,rect:e.rect,enabled:e.enabled,focused:e.focused,selected:e.selected,heading:e.heading,roleDescription:e.roleDescription,checked:e.checked,editable:e.editable,password:e.password,hintShowing:e.hintShowing,placeholder:e.hint,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd,visibleToUser:e.visibleToUser,clickable:e.clickable===!0,focusable:e.focusable===!0,scrollable:e.scrollable,canScrollForward:e.canScrollForward,canScrollBackward:e.canScrollBackward,windowIndex:e.windowIndex,windowType:e.windowType,windowLayer:e.windowLayer,windowActive:e.windowActive,windowFocused:e.windowFocused,windowRect:e.windowRect,depth:t,parentIndex:void 0,children:[]},e.drawingOrder===void 0?void 0:{parent:n,order:e.drawingOrder})}function nl(e){let t=new Map;return e.nodes.forEach((n,r)=>{t.set(n.index,e.sourceNodes[r]?.clickable)}),{kind:`exact`,provider:`android-helper`,clickableByNodeIndex:t}}const rl=new Set([`android`,`com.android.systemui`]);function il(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=hl(e,n.foregroundAppPackage);return sl(r,t)?al(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):pl(r)?{outcome:`ok`}:ol(r)?{outcome:`system-surface-only`}:cl(r)?{outcome:`ok`}:ll(r)?al(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):ul(r)||dl(r,t)?al(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):fl(r)?al(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function al(e,t,n,r){return{outcome:`unusable`,decision:ml(e,t,n,r)}}function ol(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function sl(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function cl(e){return ll(e)&&e.inputMethodMeaningfulNodeCount>=2}function ll(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function ul(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function dl(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function fl(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function pl(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function ml(e,t,n,r){return{reason:n,failureReason:r,diagnostics:kl(e,t)}}function hl(e,t){let n=gl(t);for(let t of Hc(e))_l(n,t);return wl(n)}function gl(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function _l(e,t){e.nodeCount+=1,Ol(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&vl(e,t.resourceId),yl(e,t),bl(e,t)}function vl(e,t){let n=cn(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function yl(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function bl(e,t){Tl(t)&&(e.meaningfulNodeCount+=1,xl(e,t),Cl(e,t))}function xl(e,t){e.currentWindowType===1&&!Dl(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Sl(e)&&!Bt(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Sl(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Cl(e,t){Dl(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),te({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function wl(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Tl(e){return e.visibleToUser===!1?!1:El(e.text)||El(e.desc)||El(e.resourceId)}function El(e){return e!==null&&e.trim()!==``}function Dl(e){return e===null||rl.has(e)}function Ol(e){return e!==null&&rl.has(e)}function kl(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function Al(e){let t=await z(e.deviceKey,{resetRuntime:!0,signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await jl(e.adb,e.packageName)}async function jl(e,t){await mi({adb:e,packageName:t}),await _(150),g({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:t}})}const Ml=Symbol(`androidSnapshotCaptureEvidence`);function Nl(e,t){return Object.defineProperty(e,Ml,{value:t}),e}function Pl(e){let t={...e,backend:`android`,producer:`android-uiautomator`},n=e[Ml];return re(t,n.clickability),n.occlusionContext&&f(t,n.occlusionContext),t}async function Fl(e,t={}){let n=C(e,t.helperAdb).exec;return(await Ul(e,t,n)).xml}async function Il(e,t={}){let n=C(e,t.helperAdb).exec,r=await Ul(e,t,n),i=r.xml,a=el(i),o=zl(r.metadata,a),s={...t,androidPresentation:{...t.androidPresentation,deadlineAtMs:t.androidPresentation?.deadlineAtMs??Date.now()+250}};try{let e=Sc(a,void 0,s),n=Rl(e.truncated,r.metadata);t.interactiveOnly&&t.includeHiddenContentHints!==!1&&Hl({options:s,tree:a,xml:i,interactiveSnapshot:e});let{sourceNodes:c,occlusionContext:l,...u}=e;return Nl({...u,...Vl(n),androidSnapshot:o,quality:{state:`healthy`,backend:`android-helper`}},{clickability:nl(e),occlusionContext:l})}catch(e){if(!hc(e))throw e;return Ll({failure:e,androidSnapshot:o})}}function Ll(e){return Nl({nodes:[],truncated:!0,analysis:e.failure.analysis??{rawNodeCount:0,maxDepth:0},androidSnapshot:{...e.androidSnapshot,presentationFailure:{phase:e.failure.details.phase,workUnits:e.failure.details.workUnits,...e.failure.details.maxWorkUnits===void 0?{}:{maxWorkUnits:e.failure.details.maxWorkUnits}}},quality:{state:`sparse`,backend:`android-helper`,reason:e.failure.message,reasonCode:e.failure.qualityReasonCode}},{clickability:{kind:`exact`,provider:`android-helper`,clickableByNodeIndex:new Map}})}function Rl(e,t){return e===!0||t.helperTruncated===!0||e}function zl(e,t){return Bl(t)===!1?{...e,occlusionScanUnavailable:!0}:e}function Bl(e){let t=[...e.children];if(t.length!==0){for(;t.length>0;){let e=t.pop();if(Ls(e)!==void 0)return!0;t.push(...e.children)}return!1}}function Vl(e){return e===!0?{truncated:!0}:{}}function Hl(e){if(uu(e.interactiveSnapshot.nodes).size>0||lu(e.xml))return;let t=Sc(e.tree,void 0,{...e.options,interactiveOnly:!1});du(we(a(t.nodes)),t,e.interactiveSnapshot)}async function Ul(e,t,n){let r=C(e,t.helperAdb),i=await h(`android_snapshot_helper_artifact_resolution`,async()=>await su(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await Wl(e,t,n,i.artifact);throw g({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),cu(i.errorReason)}async function Wl(e,t,n,r){let i=ei(e),a=C(e,t.helperAdb),o=Gl(t,i);try{let e;for(let o=0;;o+=1){o>0&&await Zl(t.signal);let s=await Xl({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3||t.transient!==void 0&&Date.now()>=t.transient.settleBy)return await Ql({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal,retireHelper:t.transient===void 0});e=s.decision.reason}}finally{o&&await z(i)}}function Gl(e,t){return e.transient?Hi(t)===void 0:e.helperSessionScope!==`daemon-session`}function Kl(e){return e.transient?`current-only`:e.helperInstallPolicy??`missing-or-outdated`}async function ql(e,t,n,r,i){let a=await h(`android_snapshot_helper_install`,async()=>await gr({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:Kl(e),timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:Kl(e)});return g({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function Jl(e){let{signal:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}=e,o=_i({adb:n,adbProvider:r,artifact:i,deviceKey:a,signal:t});try{let e=await h(`android_snapshot_helper_session_capture`,async()=>await ra(o),{packageName:i.manifest.packageName,version:i.manifest.version,timeoutMs:er});if(e)return e}catch(e){if(t?.throwIfAborted(),ii(e))throw e;g({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:s(e).message}}),await jl(n,i.manifest.packageName)}return await h(`android_snapshot_helper_capture`,async()=>await gi(o),{packageName:i.manifest.packageName,version:i.manifest.version,timeoutMs:er,commandTimeoutMs:tr})}function Yl(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,pixelDensity:e.metadata.pixelDensity,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function Xl(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await ql(t,n,r,i,a);e.installed&&await z(a),s=Yl(await Jl({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){if(t.signal?.throwIfAborted(),dr(e))throw e;return{outcome:`captured`,capture:await eu({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=il(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});if(c.outcome===`unusable`)return{outcome:`unusable`,decision:c.decision};let l=c.outcome===`system-surface-only`;return!l&&o>0&&g({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:{xml:s.xml,metadata:l?{...s.metadata,systemSurfaceOnly:!0}:s.metadata}}}async function Zl(e){e?.throwIfAborted(),await _(250),e?.throwIfAborted()}async function Ql(e){throw g({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),e.retireHelper&&await Al({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),$l(e.contentRecovery,e.attempts)}function $l(e,n){return new t(`COMMAND_FAILED`,e.failureReason,{...e.diagnostics,androidSnapshotHelperFailureReason:e.reason,attempts:n,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function eu(e){let t=tu(e.error);throw g({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await z(e.helperDeviceKey),await jl(e.adb,e.artifact.manifest.packageName),lr({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),nu(e.error,t)}function tu(e){let t=s(e),n=ou(t.details?.helper);if(n&&n!==t.message)return`${t.message}: ${n}`;if(n)return n;let r=(typeof t.details?.stderr==`string`?t.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return r?`${t.message}: ${r}`:t.message}function nu(e,n){let r=s(e),i=ru(r);return new t(o(r.code),`Android snapshot helper failed: ${n}`,{...r.details,...au(r),androidSnapshotHelperFailureReason:n,...i?{androidCaptureFailureReason:i}:{},hint:iu(r,i)},e)}function ru(e){return pt(e)}function iu(e,t){return t===`accessibility-timeout`?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function au(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function ou(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}async function su(e){if(e)return{artifact:e};let t=Pe(),n=E.join(Fe(),`android`,`snapshot-helper`,`dist`),r=E.join(n,`agent-device-android-snapshot-helper-${t}.manifest.json`);try{await x().files.access(r)}catch{return{}}try{let e=nr(JSON.parse(await x().files.readText(r))),t=E.join(n,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await x().files.access(t),{artifact:{apkPath:t,manifest:e}}}catch(e){return{errorReason:s(e).message}}}function cu(e){let n=e??`the bundled helper artifact was not found`;return new t(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${n}`,{androidSnapshotHelperFailureReason:n,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function lu(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function uu(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function du(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const fu=Object.freeze({now:()=>Date.now(),sleep:_});async function pu(e,t,n,r,i={},a=fu){let o=await Mu(e),s=a.now()+1500,c=null;for(;;){let l=await Su(e,t,n,r,o,i);if(l.reason===`ime_capture`)return l;let u=s-a.now();if(l.ok&&c?.ok||u<=0)return l;c=l,await a.sleep(Math.min(150,u))}}async function mu(e,t,n,r={}){return yu(await Fl(e,r),t,n)}async function hu(e,t,n,r){let i=await Mu(e);return Cu(await Fl(e,r),t,n,i).targetInput}async function gu(e,t,n,r={}){try{return await hu(e,t,n,r)}catch(e){return g({level:`warn`,phase:`android_fill_pre_action_target_capture_failed`,data:{error:e instanceof Error?e.message:String(e)}}),null}}function Z(e,n,r){if(r?.ok)return;let a=r?_u(e,n,r):null;if(a)return a;throw i(new t(`COMMAND_FAILED`,bu(r),xu(e,r)),`unknown`)}function _u(e,t,n){let r=n.targetInput,i=n.actualInput;if(e.length===0||n.reason===`ime_capture`||!t||!r||!i||J(t)||J(r)||J(i)||!Ru(t,r)||!Ru(t,i)||t.text===n.actual)return null;let a=zu(t);return g({level:`warn`,phase:`android_fill_verification_unconfirmed`,data:{target:a}}),{verification:`unconfirmed`,requested:e,before:t.text,after:n.actual,target:a}}function vu(e,t,n,r,i={}){let a=Cu(e,t,n,i);return wu(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:Tu(a,r)??Eu(a,r)}function yu(e,t,n){return Cu(e,t,n).targetInput?.text??null}function bu(e){return e?.reason===`ime_capture`?`Android fill input was captured by the active keyboard instead of the app field`:e?.reason===`masked_unverified`?`Android fill verification could not confirm masked text value`:`Android fill verification failed`}function xu(e,t){let n=As(e,t);return t?.reason===`ime_capture`&&(n.hint=`The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill.`),n}async function Su(e,t,n,r,i,a){return vu(await Fl(e,a),t,n,r,i)}function Cu(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of Hc(e)){let e=ju(a,r);e&&Nu(i,e,t,n)}return Fu(i)}function wu(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function Tu(e,t){let n=e.actualInput;if(!n||!Lu(n))return null;let r=n.text??null,i=Array.from(Du(n)).length,a=Array.from(t).length,o=a===0?i===0:i>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function Eu(e,t){let n=e.actualInput;return{ok:n!==null&&Ou(Du(n),t),actual:n?.text??null,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:n}}function Du(e){return e.hintShowing?``:e.text??``}function Ou(e,t){if(e===t)return!0;if(t.length===0)return!1;let n=ku(e),r=ku(t);return!n||!r?!1:!!(n===r||Au(n,r))}function ku(e){return e.replaceAll(/\s+/g,` `).trim()}function Au(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function ju(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:te({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Iu(e.className??``),hintShowing:e.hintShowing===!0,placeholder:e.hint??null}}async function Mu(e){try{return{activeInputMethodPackage:(await bo(e)).inputMethodPackage}}catch(e){return g({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function Nu(e,t,n,r){let i=ue(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=Pu(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=Pu(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=Pu(e.anyAtPoint,t))}function Pu(e,t){return e&&e.area<t.area?e:t}function Fu(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Iu(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function Lu(e){return J(e)}function Ru(e,t){return e.resourceId||t.resourceId?e.resourceId===t.resourceId&&e.packageName===t.packageName:e.className===t.className&&e.packageName===t.packageName&&e.rect.x===t.rect.x&&e.rect.y===t.rect.y&&e.rect.width===t.rect.width&&e.rect.height===t.rect.height}function zu(e){return{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:e.rect}}async function Bu(e,t){return await Wt(t.stateDir),await cs(t.stateDir,e.id,async()=>await Hu(e,t))}function Vu(e){let t=n(e).details?.hint;return{outcome:`helper-unavailable`,reason:s(e).message,...typeof t==`string`?{hint:t}:{}}}async function Hu(e,t){let n=x().imeRecoveryMarkers,r=y(e),i=C(e),a=W(e),o;try{o=await Vo(i),await Go({adb:r,adbProvider:i,artifact:o,deviceKey:a})}catch(e){return Vu(e)}let{manifest:s}=o,c=await G(r);if(c===s.serviceComponent){let i=await n.write(t.stateDir,e.id),o=await K(r);return i&&q.add(a),{outcome:`settled`,activated:!1,alreadyActive:!0,...i?{}:{persistFailed:!0},previousIme:o,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName}}let l=await K(r);if(!await ts(r,c))return await rs(r,l,e.id),S({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName};let u=(await n.read(t.stateDir)).includes(e.id);if(!await n.write(t.stateDir,e.id))return await rs(r,l,e.id),S({level:`warn`,phase:`android_test_ime_marker_persist_failed`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName};await b(r,[`ime`,`enable`,s.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let d=await b(r,[`ime`,`set`,s.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),f=await G(r);return f===s.serviceComponent?(q.add(a),S({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!0,alreadyActive:!1,previousIme:c,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName}):(q.delete(a),await rs(r,l,e.id),u||await n.clear(t.stateDir,e.id),S({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:f,stderr:d.stderr.trim()}}),{outcome:`settled`,activated:!1,alreadyActive:!1,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName})}function Uu(e){return E.join(e,`android-test-ime-pending`)}function Wu(e,t){return E.join(Uu(e),encodeURIComponent(t))}async function Gu(e,t){let n=x().files,r,i=!1;try{let a=Uu(e);if(r=Wu(e,t),await n.ensureDirectory(a),(await Ju(r))?.serial===t)return!0;let o={version:1,serial:t};if(await n.writeAtomicText(r,`${JSON.stringify(o)}\n`,384),i=!0,(await Ju(r))?.serial!==t)throw Error(`Android test IME marker read-back did not match the requested device.`);return!0}catch(a){return i&&r&&await n.remove(r,{force:!0}).catch(()=>{}),g({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:e,serial:t,error:s(a).message}}),!1}}async function Ku(e,t){await x().files.remove(Wu(e,t),{force:!0}).catch(()=>{})}async function qu(e){let t=x().files,n;try{n=await t.readDirectory(Uu(e))}catch{return[]}let r=[];for(let t of n)try{let n=E.join(Uu(e),t),i=await Ju(n);i&&Wu(e,i.serial)===n&&r.push(i.serial)}catch{}return[...new Set(r)].sort()}async function Ju(e){try{return Yu(await x().files.readText(e))}catch{return}}function Yu(e){try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))return;let n=t;return n.version===1&&typeof n.serial==`string`&&n.serial.length>0?{version:1,serial:n.serial}:void 0}catch{return}}const Xu=new qt(`utf-16le`);let Zu;async function Qu(e,t){for(let n of[`AndroidManifest.xml`,`base/manifest/AndroidManifest.xml`]){let r=await $u(e,n,t);if(!r)continue;let i=ed(r);if(i)return i}return await ld(e,t)}async function $u(e,t,n){try{let r=await De(`unzip`,[`-p`,e,t],{allowFailure:!0,binaryStdout:!0,signal:n});return r.exitCode!==0||!r.stdoutBuffer||r.stdoutBuffer.length===0?void 0:r.stdoutBuffer}catch{n?.throwIfAborted();return}}function ed(e){return e.subarray(0,Math.min(e.length,128)).toString(`utf8`).trimStart().startsWith(`<`)?td(e.toString(`utf8`)):nd(e)}function td(e){return e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i)?.[1]}function nd(e){if(e.length<8||e.readUInt16LE(0)!==3)return;let t;for(let n=e.readUInt16LE(2);n+8<=e.length;){let r=e.readUInt16LE(n),i=e.readUInt16LE(n+2),a=e.readUInt32LE(n+4);if(a<=0||n+a>e.length)return;if(r===1)t=id(e.subarray(n,n+a));else if(r===258&&t){let r=rd(e,n,i,t);if(r)return r}n+=a}}function rd(e,t,n,r){if(n<36||t+n>e.length||r[e.readUInt32LE(t+20)]!==`manifest`)return;let i=e.readUInt16LE(t+24),a=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let n=s+t*a;if(n+20>e.length)return;if(r[e.readUInt32LE(n+4)]!==`package`)continue;let i=e.readUInt32LE(n+8);if(i!==4294967295)return r[i];let o=e.readUInt8(n+15),c=e.readUInt32LE(n+16);return o===3?r[c]:void 0}}function id(e){if(e.length<28)return[];let t=e.readUInt32LE(8),n=e.readUInt32LE(16),r=e.readUInt32LE(20),i=!!(n&256),a=[];for(let n=0;n<t;n+=1){let t=28+n*4;if(t+4>e.length)return a;let o=r+e.readUInt32LE(t);a.push(i?ad(e,o):od(e,o))}return a}function ad(e,t){let[,n]=sd(e,t),[r,i]=sd(e,t+n),a=t+n+i;return e.subarray(a,a+r).toString(`utf8`)}function od(e,t){let[n,r]=cd(e,t),i=t+r;return Xu.decode(e.subarray(i,i+n*2))}function sd(e,t){let n=e.readUInt8(t);if(!(n&128))return[n,1];let r=e.readUInt8(t+1);return[(n&127)<<8|r,2]}function cd(e,t){let n=e.readUInt16LE(t);if(!(n&32768))return[n,2];let r=e.readUInt16LE(t+2);return[(n&32767)<<16|r,4]}async function ld(e,t){t?.throwIfAborted();let n=await ud();if(!n)return;let r=await De(n,[`dump`,`badging`,e],{allowFailure:!0,signal:t});if(r.exitCode===0)return r.stdout.match(/package:\s+name='([^']+)'/)?.[1]}async function ud(){if(Zu!==void 0)return Zu??void 0;try{let e=x().files;for(let t of St()){let n=E.join(t,`build-tools`);try{let t=(await e.readDirectory(n)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(let r of t){let t=E.join(n,r,`aapt`);if(E.isAbsolute(t)&&await e.isExecutable(t))return Zu=t,t}}catch{}}}catch{}Zu=null}async function dd(e,t){let n=e.kind===`url`&&Ie(e.url),r=await Le({source:e,isInstallablePath:(e,t)=>t.isFile()&&fd(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await pd(r.installablePath,t?.signal);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function fd(e){let t=E.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function pd(e,t){let n=E.extname(e).toLowerCase();return n!==`.apk`&&n!==`.aab`?{}:{packageName:await Qu(e,t)}}async function md(e,n,r,i={}){let a=typeof r.action==`string`&&r.action.trim()?r.action.trim():`${n}.TEST_PUSH`,o=[`am`,`broadcast`,`-a`,a,`-p`,n],s=typeof r.receiver==`string`?r.receiver.trim():``;s&&o.push(`-n`,s);let c=r.extras;if(c!==void 0&&(typeof c!=`object`||!c||Array.isArray(c)))throw new t(`INVALID_ARGS`,`Android push payload extras must be an object`);let l=c??{},u=0;for(let[e,t]of Object.entries(l))e&&(hd(o,e,t),u+=1);return await T(e,o,{signal:i.signal}),{action:a,extrasCount:u}}function hd(e,n,r){if(typeof r==`string`){e.push(`--es`,n,r);return}if(typeof r==`boolean`){e.push(`--ez`,n,r?`true`:`false`);return}if(typeof r==`number`&&Number.isFinite(r)){if(Number.isInteger(r)){e.push(`--ei`,n,String(r));return}e.push(`--ef`,n,String(r));return}throw new t(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}function Q(e){let t=e.replaceAll(`,`,``).match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let n=Number(t[0]);return Number.isFinite(n)?n:null}function gd(e){let t=xd(e.map(e=>e.intendedVsyncNs)),n=[];for(let e=1;e<t.length;e+=1){let r=t[e]-t[e-1];r>=4e6&&r<=5e7&&n.push(r)}if(n.length!==0)return Sd(n)}function _d(e){let{frames:t,frameDeadlineNs:n,summaryDroppedFrameCount:r}=e;return r===void 0?n===void 0?[]:t.filter(e=>e.durationNs>n):r<=0?[]:[...t].sort((e,t)=>t.durationNs-e.durationNs).slice(0,r).sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}function vd(e){let{frames:t,windowStartNs:n,measuredAtMs:r,uptimeMs:i}=e;if(t.length===0||n===void 0)return[];let a=[],o=[];for(let e of t){let t=o.at(-1);if(!t||e.intendedVsyncNs-t.frameCompletedNs<=5e8){o.push(e);continue}a.push(o),o=[e]}return o.length>0&&a.push(o),a.map(e=>bd({frames:e,windowStartNs:n,measuredAtMs:r,uptimeMs:i})).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}function yd(e){return Math.round(e*10)/10}function bd(e){let{frames:t,windowStartNs:n,measuredAtMs:r,uptimeMs:i}=e,a=Math.min(...t.map(e=>e.intendedVsyncNs)),o=Math.max(...t.map(e=>e.frameCompletedNs)),s=Math.max(0,Math.round((a-n)/1e6)),c=Math.max(s,Math.round((o-n)/1e6)),l=i!==void 0&&Number.isFinite(r)?r-i:void 0;return{startOffsetMs:s,endOffsetMs:c,startAt:l===void 0?void 0:new Date(l+a/1e6).toISOString(),endAt:l===void 0?void 0:new Date(l+o/1e6).toISOString(),missedDeadlineFrameCount:t.length,worstFrameMs:yd(Math.max(...t.map(e=>e.durationNs))/1e6)}}function xd(e){return[...new Set(e.filter(e=>Number.isFinite(e)))].sort((e,t)=>e-t)}function Sd(e){let t=[...e].sort((e,t)=>e-t),n=Math.floor(t.length/2);return t.length%2==1?t[n]:(t[n-1]+t[n])/2}function Cd(e,t,n){wd(e,t);let r=Pd(e),i=Ad(e),a=Ed(i,r,t),o=Date.parse(n),s=Id({frames:i,measuredAtMs:o,summary:r}),c=_d({frames:i,frameDeadlineNs:a,summaryDroppedFrameCount:r?.droppedFrameCount}),l=r?.sampleWindowMs??s.sampleWindowMs??Bd(i),u=Dd(r,i,c),d=kd({droppedFrames:c,timing:s,measuredAtMs:o,summary:r});return{...u,sampleWindowMs:l,...Od(a),windowStartedAt:s.windowStartedAt,windowEndedAt:s.windowEndedAt,timestampSource:s.timestampSource,measuredAt:n,method:`adb-shell-dumpsys-gfxinfo-framestats`,source:r?`android-gfxinfo-summary`:`framestats-rows`,worstWindows:d&&d.length>0?d:void 0}}function wd(e,n){if(/no process found for:/i.test(e))throw new t(`COMMAND_FAILED`,`Android gfxinfo did not find a running process for ${n}`,{metric:`fps`,package:n,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf after the interaction you want to inspect.`})}function Td(e){throw new t(`COMMAND_FAILED`,`Failed to parse Android framestats output for ${e}`,{metric:`fps`,package:e,hint:`Retry perf after exercising the app screen. If the problem persists, capture adb shell dumpsys gfxinfo <package> framestats output for debugging.`})}function Ed(e,n,r){let i=gd(e);if(!n&&e.length===0&&Td(r),n||i!==void 0)return i;throw new t(`COMMAND_FAILED`,`Failed to infer Android frame deadline from framestats output for ${r}`,{metric:`fps`,package:r,hint:`Retry perf after a longer interaction window so consecutive Android frame timestamps are available.`})}function Dd(e,t,n){let r=e?.totalFrameCount??t.length,i=e?.droppedFrameCount??n.length;return{totalFrameCount:r,droppedFrameCount:i,droppedFramePercent:e?.droppedFramePercent??(r>0?Gt(i/r*100):0)}}function Od(e){return{frameDeadlineMs:e===void 0?void 0:yd(e/1e6),refreshRateHz:e===void 0?void 0:yd(1e9/e)}}function kd(e){let{droppedFrames:t,timing:n,measuredAtMs:r,summary:i}=e;if(t.length===0)return;let a=vd({frames:t,windowStartNs:n.windowStartNs,measuredAtMs:r,uptimeMs:i?.uptimeMs});return a.length>0?a:void 0}function Ad(e){let t=[],n=null;for(let r of e.split(`
|
|
13
|
-
`)){let e=r.trim();if(e.length===0||e===`---PROFILEDATA---`)continue;let i=e.split(`,`).map(e=>e.trim());if(jd(i)){n=new Map(i.map((e,t)=>[e,t]));continue}let a=Md(i,n);a&&t.push(a)}return t.sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}function jd(e){return e.includes(`IntendedVsync`)&&e.includes(`FrameCompleted`)}function Md(e,t){if(!t||e.length<t.size)return;let n=Nd(e,t,`Flags`),r=Nd(e,t,`IntendedVsync`),i=Nd(e,t,`FrameCompleted`);if(!(n!==0||r===null||i===null||r<=0||i<=r))return{intendedVsyncNs:r,frameCompletedNs:i,durationNs:i-r}}function Nd(e,t,n){let r=t.get(n);if(r===void 0)return null;let i=Number(e[r]);return Number.isFinite(i)?i:null}function Pd(e){let t=e.split(/\nProfile data in ms:\n/i)[0]??``,n=Vd(t,`Total frames rendered`),r=t.match(/^\s*Janky frames:\s*([0-9][0-9,]*)\s*\(([0-9.]+)%\)/im);if(n===void 0||!r)return;let i=r[1],a=r[2];if(i===void 0||a===void 0)return;let o=Q(i)??void 0,s=Number(a);if(o===void 0||!Number.isFinite(s)||n<0)return;let c=Vd(t,`Uptime`),l=Vd(t,`Stats since`);return{droppedFramePercent:Gt(s),droppedFrameCount:o,totalFrameCount:n,sampleWindowMs:Fd({uptimeMs:c,statsSinceNs:l}),uptimeMs:c,statsSinceNs:l}}function Fd(e){let{uptimeMs:t,statsSinceNs:n}=e;if(t===void 0||n===void 0)return;let r=t-Math.round(n/1e6);return r>=0?r:void 0}function Id(e){let{frames:t,measuredAtMs:n,summary:r}=e,i=Ld(t),a=r?.statsSinceNs,o=a??i.firstFrameNs,s=Rd(o,i.lastFrameNs),c=r?.sampleWindowMs??s;if(!Number.isFinite(n)||r?.uptimeMs===void 0||o===void 0)return{sampleWindowMs:c,windowStartNs:o};let l=n-r.uptimeMs;return{sampleWindowMs:c,windowStartNs:o,windowStartedAt:new Date(l+o/1e6).toISOString(),windowEndedAt:zd({deviceBootWallClockMs:l,measuredAtMs:n,summaryStartNs:a,lastFrameNs:i.lastFrameNs}),timestampSource:`estimated-from-device-uptime`}}function Ld(e){return e.length===0?{}:{firstFrameNs:Math.min(...e.map(e=>e.intendedVsyncNs)),lastFrameNs:Math.max(...e.map(e=>e.frameCompletedNs))}}function Rd(e,t){if(e!==void 0&&t!==void 0)return Math.max(0,Math.round((t-e)/1e6))}function zd(e){let{deviceBootWallClockMs:t,measuredAtMs:n,summaryStartNs:r,lastFrameNs:i}=e;return r===void 0?i===void 0?void 0:new Date(t+i/1e6).toISOString():new Date(n).toISOString()}function Bd(e){if(e.length===0)return;let t=Ld(e);return Rd(t.firstFrameNs,t.lastFrameNs)}function Vd(e,t){let n=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),r=e.match(RegExp(`^\\s*${n}:\\s*([0-9][0-9,]*)`,`im`));if(!r)return;let i=r[1];return i===void 0?void 0:Q(i)??void 0}async function Hd(e,t,n={}){let r=y(e,n.adb);try{let i=Cd((await b(r,[`dumpsys`,`gfxinfo`,t,`framestats`],{timeoutMs:15e3})).stdout,t,new Date().toISOString());return await Ud(e,t,n),i}catch(e){throw Wd(t,e)}}async function Ud(e,t,n={}){let r=y(e,n.adb);try{await b(r,[`dumpsys`,`gfxinfo`,t,`reset`],{allowFailure:!0,timeoutMs:3e3})}catch{}}function Wd(e,n){return n instanceof t?new t(n.code,n.message,{...n.details??{},metric:`fps`,package:e},n):new t(`COMMAND_FAILED`,`Failed to sample Android fps for ${e}`,{metric:`fps`,package:e},n)}async function Gd(e,t,n,r,i){return{capture:{durationMs:r,packageName:t.packageName,appPid:t.appPid,artifactPath:t.outPath,sizeBytes:n},frameHealth:t.kind===`perfetto`?await Kd(e,t.packageName,i):void 0,notes:[t.kind===`perfetto`?`Frame health is sampled from Android gfxinfo around the trace window; open the Perfetto artifact for timeline root cause.`:`Open the Simpleperf report artifact for symbol-level CPU attribution.`]}}async function Kd(e,t,n){try{let r=await Hd(e,t,n);return{available:!0,droppedFramePercent:r.droppedFramePercent,droppedFrameCount:r.droppedFrameCount,totalFrameCount:r.totalFrameCount,method:r.method,worstWindows:r.worstWindows?.slice(0,3).map(e=>({startOffsetMs:e.startOffsetMs,endOffsetMs:e.endOffsetMs,missedDeadlineFrameCount:e.missedDeadlineFrameCount,worstFrameMs:e.worstFrameMs}))}}catch(e){return{available:!1,reason:e instanceof Error?e.message:`Android frame health was not available`}}}async function qd(e,t,n){let r=y(e,n.adb);await $d(r,t),await nf(r,t),await tf(r,t,n.files);let i=await Qd(t.outPath,n.files);await Xd(r,t.remotePath);let a=Date.now(),o=Math.max(0,a-t.startedAt),s=await Gd(e,t,i,o,{adb:r});return{...t,action:`stop`,platform:`android`,state:`stopped`,stoppedAt:a,durationMs:o,sizeBytes:i,method:t.kind===`simpleperf`?Gr:Kr,artifact:{path:t.outPath,sizeBytes:i},summary:s,message:`Stopped Android ${t.kind} ${t.type} for ${t.packageName}`}}async function Jd(e,t,n={}){let r=y(e,n.adb);try{t.state===`running`&&(await $d(r,t),await nf(r,t).catch(()=>{}))}finally{await Xd(r,t.remotePath)}}function Yd(e,t,n=Jr){return`${n}/agent-device-${e.replaceAll(/[^A-Za-z0-9_.-]/g,`_`)}-${Date.now()}-${t}`}async function Xd(e,t){try{await b(e,[`rm`,`-f`,t],{allowFailure:!0,timeoutMs:qr})}catch{}}async function Zd(e,t,n=x().files){await n.ensureDirectory(E.dirname(e)),await n.writeBytes(e,Buffer.from(`${JSON.stringify(t,null,2)}\n`))}async function Qd(e,n=x().files){try{return(await n.stat(e)).size}catch(n){throw new t(`COMMAND_FAILED`,`Profiler artifact was not written: ${e}`,{outPath:e,hint:`Retry the profiling command and check daemon logs if the artifact path is still missing.`},n)}}async function $d(e,t){try{await b(e,[Me(ef(t.profilerPid))],{timeoutMs:N})}catch(e){throw M(`stop`,t.kind,t.packageName,e)}}function ef(e){return[`pid=${v(e)}`,`kill -INT "$pid" 2>/dev/null || true`,`for i in 1 2 3 4 5 6 7 8 9 10; do kill -0 "$pid" 2>/dev/null || exit 0; sleep 0.2; done`,`kill -TERM "$pid" 2>/dev/null || true`,`for i in 1 2 3 4 5 6 7 8 9 10; do kill -0 "$pid" 2>/dev/null || exit 0; sleep 0.2; done`,`echo "profiler process did not stop after SIGTERM" >&2`,`exit 1`].join(`; `)}async function tf(e,n,r){await(r??x().files).ensureDirectory(E.dirname(n.outPath));try{await e([`pull`,n.remotePath,n.outPath],{timeoutMs:N})}catch(e){throw new t(`COMMAND_FAILED`,`Failed to pull Android ${n.kind} artifact for ${n.packageName}`,{package:n.packageName,tool:n.kind,remotePath:n.remotePath,outPath:n.outPath,hint:`Check that the profiling command ran long enough to create an artifact, then retry stop with the same session.`},e)}}async function nf(e,n){let r;for(let t=0;t<12;t+=1){let t=await rf(e,n.remotePath);if(t!==void 0&&t>0&&t===r)return;r=t,await _(250)}throw new t(`COMMAND_FAILED`,`Android ${n.kind} artifact is not ready to pull`,{package:n.packageName,tool:n.kind,remotePath:n.remotePath,hint:`The profiler stopped, but the remote artifact was missing, empty, or still changing. Retry stop with the same session or inspect the device-side artifact.`})}async function rf(e,t){let n=v(t),r=await b(e,[Me(`if [ -f ${n} ]; then stat -c %s ${n} 2>/dev/null || wc -c < ${n}; fi`)],{allowFailure:!0,timeoutMs:qr});if(r.exitCode!==0)return;let i=Number(r.stdout.trim().split(/\s+/)[0]);return Number.isFinite(i)?i:void 0}async function af(e,t,n,r={}){let i=y(e,r.adb),a=await Yr(i,t);await Xr(i,`perfetto`,t);let o=Yd(t,`app.perfetto-trace`,`/data/misc/perfetto-traces`),s;try{await Ud(e,t,{adb:i}),s=await sf(i,o,t)}catch(e){throw await Xd(i,o),e}return{type:`trace`,kind:`perfetto`,packageName:t,appPid:a,profilerPid:s,remotePath:o,outPath:n,startedAt:Date.now(),state:`running`,action:`start`,platform:`android`,method:Kr,message:`Started Android Perfetto trace for ${t}`}}async function of(e,t,n,r={}){return await qd(e,{...t,outPath:n},r)}async function sf(e,n,r){try{let i=Zr((await b(e,[`perfetto`,`--background-wait`,`-o`,n,`-t`,`3600s`,`sched`,`freq`,`idle`,`am`,`wm`,`gfx`,`view`,`binder_driver`,`hal`,`dalvik`],{timeoutMs:N})).stdout);if(i)return i;throw new t(`COMMAND_FAILED`,`Android perfetto did not return a profiler pid`,{package:r,tool:`perfetto`,hint:`Retry perf trace start. If perfetto exits immediately, verify the device permits trace capture.`})}catch(e){throw M(`start`,`perfetto`,r,e)}}function cf(e){let t=[];for(let n of u(e)){let e=n.match(/^([0-9]+(?:\.[0-9]+)?)%\s+(.+)$/);if(!e)continue;let r=Number(e[1]),i=e[2]?.trim();if(!Number.isFinite(r)||!i)continue;let a=i.split(/\s{2,}/).filter(Boolean);if(t.push({percentage:Gt(r),command:a[0],dso:a[1],symbol:a.slice(2).join(` `)||void 0}),t.length>=50)break}return t}async function lf(e,t,n,r={}){let i=y(e,r.adb),a=await Yr(i,t);await Xr(i,`simpleperf`,t);let o=Yd(t,`cpu.perf.data`),s;try{s=await ff(i,a,o,t)}catch(e){throw await Xd(i,o),e}return{type:`cpu-profile`,kind:`simpleperf`,packageName:t,appPid:a,profilerPid:s,remotePath:o,outPath:n,startedAt:Date.now(),state:`running`,action:`start`,platform:`android`,method:Gr,message:`Started Android Simpleperf CPU profile for ${t}`}}async function uf(e,t,n,r={}){return await qd(e,{...t,outPath:n},r)}async function df(e,t,n,r={}){let i=y(e,r.adb);await Xr(i,`simpleperf`,t.packageName);let a=await hf(i,t),o=new Date().toISOString(),s=cf(a.stdout),c=s.slice(0,10).map(e=>({symbol:e.symbol??`<unknown>`,binary:e.dso,selfSamplePercent:e.percentage}));await Zd(n,{kind:`simpleperf-report`,generatedAt:o,packageName:t.packageName,appPid:t.appPid,sourceProfilePath:t.outPath,sourceRemotePath:t.remotePath,entryCount:s.length,summary:{topFunctions:c},entries:s},r.files);let l=await Qd(n,r.files);return{action:`report`,platform:`android`,type:`cpu-profile-report`,kind:`simpleperf`,packageName:t.packageName,appPid:t.appPid,sourceProfilePath:t.outPath,outPath:n,sizeBytes:l,generatedAt:o,entryCount:s.length,summary:{topFunctions:c},method:Gr,message:`Wrote Android Simpleperf report for ${t.packageName}`}}async function ff(e,n,r,i){try{let a=Zr((await b(e,[Me(pf(n,r))],{timeoutMs:N})).stdout);if(a)return a;throw new t(`COMMAND_FAILED`,`Android simpleperf did not return a profiler pid`,{package:i,tool:`simpleperf`,hint:`Retry perf. If simpleperf exits immediately, verify the app is profileable and the device permits native profiling.`})}catch(e){throw M(`start`,`simpleperf`,i,e)}}function pf(e,t){return mf([`simpleperf`,`record`,`-e`,`cpu-clock:u`,`-p`,e,`-o`,t,`--duration`,`3600`],`simpleperf`)}function mf(e,t){let n=e.map(v).join(` `),r=`${Jr}/agent-device-${t}-${Date.now()}.err`;return[`err=${v(r)}`,`(${n}) >/dev/null 2>"$err" & pid=$!`,`sleep 1`,`if kill -0 "$pid" 2>/dev/null; then rm -f "$err"; echo "$pid"; exit 0; fi`,`cat "$err" >&2`,`rm -f "$err"`,`exit 1`].join(`; `)}async function hf(e,t){try{return await b(e,[`simpleperf`,`report`,`-i`,t.remotePath,`--stdio`,`--sort`,`comm,dso,symbol`],{timeoutMs:N})}catch(e){throw M(`report`,`simpleperf`,t.packageName,e)}}const gf=15e3,_f=12e4;async function vf(e,t,n={}){let r=y(e,n.adb);try{return Sf((await b(r,[`dumpsys`,`meminfo`,t],{timeoutMs:gf})).stdout,t,new Date().toISOString())}catch(e){throw Af(`memory`,t,e)}}async function yf(e,n,r,i={}){let a=y(e,i.adb),o=i.files??x().files,s=await Cf(a,n),c=wf(n);await o.ensureDirectory(E.dirname(r));let l=await bf(o,r);try{Ee(await b(a,[`am`,`dumpheap`,n,c],{allowFailure:!0,timeoutMs:_f}),`Failed to capture Android heap dump for ${n}`,e=>({kind:`android-hprof`,package:n,pid:s,remotePath:c,hint:Tf(e.stdout,e.stderr)}));let e=await a([`pull`,c,r],{allowFailure:!0,timeoutMs:_f});if(e.exitCode!==0)throw await xf(o,r,l),w(`Failed to pull Android heap dump for ${n}`,e,{kind:`android-hprof`,package:n,pid:s,remotePath:c,path:r,hint:`Verify the daemon can write the requested --out path and retry. The heap dump stays on-device only until cleanup runs.`});let i=await o.stat(r).catch(()=>null);if(!i?.isFile||i.size<=0)throw await xf(o,r,l),new t(`COMMAND_FAILED`,`Android heap dump artifact is missing or empty`,{kind:`android-hprof`,package:n,pid:s,path:r,remotePath:c,hint:`Retry with a writable --out path. If the file is still empty, inspect adb pull output with --debug.`});return{available:!0,kind:`android-hprof`,path:r,sizeBytes:i.size,measuredAt:new Date().toISOString(),method:`adb-shell-am-dumpheap`,packageName:n,pid:s,remotePath:c}}finally{await b(a,[`rm`,`-f`,c],{allowFailure:!0,timeoutMs:gf}).catch(()=>{})}}async function bf(e,t){return await e.stat(t).then(e=>e.isFile).catch(()=>!1)}async function xf(e,t,n){n||await e.remove(t,{force:!0}).catch(()=>{})}function Sf(e,n,r){if(/no process found for:/i.test(e))throw new t(`COMMAND_FAILED`,`Android meminfo did not find a running process for ${n}`,{metric:`memory`,package:n,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf.`});let i=jf(e,`TOTAL PSS`)??Mf(e);if(i===void 0)throw new t(`COMMAND_FAILED`,`Failed to parse Android meminfo output for ${n}`,{metric:`memory`,package:n,hint:`Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging.`});return{totalPssKb:i,totalRssKb:jf(e,`TOTAL RSS`),measuredAt:r,method:`adb-shell-dumpsys-meminfo`,topConsumers:Ef(e)}}async function Cf(e,n){let r=await b(e,[`pidof`,n],{allowFailure:!0,timeoutMs:gf}),i=r.stdout.trim().split(/\s+/).map(Number).find(e=>Number.isInteger(e)&&e>0);if(r.exitCode===0&&i!==void 0)return i;throw new t(`COMMAND_FAILED`,`No running Android process found for ${n}`,{kind:`android-hprof`,package:n,stdout:r.stdout,stderr:r.stderr,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf memory snapshot.`})}function wf(e){return`/data/local/tmp/agent-device-${e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)}-${Date.now()}.hprof`}function Tf(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`profileable`)||n.includes(`debuggable`)||n.includes(`not allowed`)?`Android heap dumps require a debuggable/profileable app process on many devices. Use a debug/profileable build, reopen the app, then retry.`:n.includes(`permission`)||n.includes(`denied`)?`The device denied heap dump access. Use a debug/profileable build or a device image that permits app heap dumping.`:`Reopen the app to refresh the process, then retry perf memory snapshot. If it still fails, run with --debug and inspect adb am dumpheap output.`}function Ef(e){let t=e.split(`
|
|
14
|
-
`).flatMap(e=>
|
|
15
|
-
`)){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let n=e.split(/\s+/).slice(1).find(e=>
|
|
16
|
-
`).filter(e=>e.trim().length>0).map(e=>({text:e,indent:e.length-e.trimStart().length}))}function
|
|
17
|
-
`).map(e=>e.trim()).filter(e=>e.length>0),n=t[0]??`unknown device error`;return(n.endsWith(`:`)&&t[1]?`${n} ${t[1]}`:n).slice(0,200)}async function mp(e,t,n,r,i){if(n.kind===`notifications`)return await Cp(e,t,`grant`,n,i),[n.permission];if(n.kind===`photos`)return[await Sp(e,t,`grant`,i)];if(n.kind===`pm`){let a=[...await _p(e,t,n.values,r)];for(let n of a)await T(e,[`pm`,`grant`,...i,t,n]);return a}throw n.kind===`all`?Error(`Unhandled Android permission target: all is resolved by the caller.`):Error(`Unhandled Android permission target: ${JSON.stringify(n)}`)}async function hp(e,t,n,r,i){if(r.kind===`notifications`)return await Cp(e,t,n,r,i),[r.permission];if(r.kind===`photos`){let r=await Sp(e,t,`revoke`,i);return n===`reset`&&await wp(e,t,r,i),[r]}throw r.kind===`pm`?Error(`Unhandled Android permission target: pm is resolved by the caller.`):r.kind===`all`?Error(`Unhandled Android permission target: all is resolved by the caller.`):Error(`Unhandled Android permission target: ${JSON.stringify(r)}`)}function gp(e,n){let r=Se(e);if(n?.trim())throw new t(`INVALID_ARGS`,`Android does not support permission modes. Received: ${n}.`);if(r===`all`)return{kind:`all`};if(r===`photos`)return{kind:`photos`};if(r===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};let i=r in qf?qf[r]:void 0;if(i)return{kind:`pm`,name:r,values:i};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use ${Kf.join(`|`)}.`,{hint:`Android custom permission ids are attempted through all, not individually.`})}async function _p(e,t,n,r){let{requested:i}=await Nf(e,t,r);return vp(i,n,t)}function vp(e,n,r){if(e===void 0)return n;let i=n.filter(t=>e.includes(t));if(i.length===0)throw new t(`COMMAND_FAILED`,`Package ${r} has not requested permission ${n.join(`, `)}, so no permission was changed.`,{appPackage:r,permissions:n});return i}async function yp(e,t,n,r,i,a){let{requested:o,grants:s}=await Nf(e,t,i),c=vp(o,r.values,t);await bp(e,t,c,n,a);let{priorGrantState:l,warnings:u}=xp(t,c,c.map(e=>s?.get(e)??`unknown`));return Zf(r.name,c,{priorGrantState:l,warnings:u})}async function bp(e,t,n,r,i){for(let r of n)await T(e,[`pm`,`revoke`,...i,t,r]);if(r===`reset`)for(let r of n)await wp(e,t,r,i)}function xp(e,t,n){return{priorGrantState:n.includes(`granted`)?`granted`:n.includes(`unknown`)?`unknown`:`not_granted`,warnings:t.flatMap((t,r)=>{let i=Gf(e,t,n[r]);return i?[i]:[]})}}async function Sp(e,n,r,i){let a=await Tp(e),o=a!==null&&a>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],s=[];for(let t of o){let a=await T(e,[`pm`,r,...i,n,t],{allowFailure:!0});if(a.exitCode===0)return t;s.push({permission:t,reason:cp(a.stderr),detail:pp(a.stderr)})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:a,attempts:s})}async function Cp(e,t,n,r,i){let a=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await T(e,[`pm`,`grant`,...i,t,r.permission],{allowFailure:!0}):(await T(e,[`pm`,`revoke`,...i,t,r.permission],{allowFailure:!0}),n===`reset`&&await wp(e,t,r.permission,i)),await T(e,[`appops`,`set`,...i,t,r.appOps,a])}async function wp(e,t,n,r){for(let i of[`user-set`,`user-fixed`])await T(e,[`pm`,`clear-permission-flags`,...r,t,n,i],{allowFailure:!0})}async function Tp(e){let t=await T(e,[`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const Ep=[`cmd`,`connectivity`,`airplane-mode`];async function Dp(e,n){let r=n?`enabled`:`disabled`;await Op(e),await T(e,[...Ep,n?`enable`:`disable`]);let i=await kp(e);if(i!==r)throw new t(`COMMAND_FAILED`,`Android airplane mode reads ${i} after requesting ${r}.`,{deviceId:e.id,requested:r,airplaneMode:i});return{airplaneMode:i}}async function Op(e){let{state:n,result:r}=await Ap(e);if(!n)throw r.exitCode!==0&<(r.stdout,r.stderr)?new t(`UNSUPPORTED_OPERATION`,`The connectivity service on this Android build has no airplane-mode command, so nothing was changed.`,{deviceId:e.id,hint:`settings airplane needs cmd connectivity airplane-mode, which requires Android 11 (API 30) or newer. Use a newer device or emulator image.`,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}):w(`Failed to read Android airplane mode`,r,{deviceId:e.id})}async function kp(e){let{state:t,result:n}=await Ap(e);if(t)return t;throw w(`Failed to read Android airplane mode after changing it`,n,{deviceId:e.id})}async function Ap(e){let t=await T(e,[...Ep],{allowFailure:!0});return{state:t.exitCode===0?jp(t.stdout):void 0,result:t}}function jp(e){let t=e.trim().toLowerCase();if(t===`enabled`)return`enabled`;if(t===`disabled`)return`disabled`}const Mp=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`],Np={"extra-small":`0.82`,small:`0.88`,medium:`0.94`,large:`1.0`,"extra-large":`1.12`,"extra-extra-large":`1.24`,"extra-extra-extra-large":`1.35`,"accessibility-medium":`1.5`,"accessibility-large":`1.75`,"accessibility-extra-large":`2.0`,"accessibility-extra-extra-large":`2.5`,"accessibility-extra-extra-extra-large":`3.2`},Pp=Np.large;async function Fp(e,n,r,i,a){switch(n.toLowerCase()){case`wifi`:{let t=ve(r);await T(e,[`svc`,`wifi`,t?`enable`:`disable`]);return}case`airplane`:return await Dp(e,ve(r));case`location`:{if(r.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:r}=Ce(a);return await ct(e,[`emu`,`geo`,`fix`,String(r),String(n)]),{latitude:n,longitude:r}}let n=ve(r)?`3`:`0`;await T(e,[`settings`,`put`,`secure`,`location_mode`,n]);return}case`animations`:{let t=ve(r)?`1`:`0`;for(let n of Mp)await T(e,[`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...Mp]}}case`appearance`:{let t=await Gp(e,r);await T(e,[`cmd`,`uimode`,`night`,t===`dark`?`yes`:`no`]);return}case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await Dt(e,i);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await T(e,[`am`,`force-stop`,n.value],{allowFailure:!0});let a=await T(e,[`pm`,`clear`,n.value],{allowFailure:!0});if(a.exitCode!==0||!/\bSuccess\b/i.test(a.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await Hp(e,Vp(r));return;case`permission`:if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);return await Yf(e,i,r,a);case`text-size`:return await Rp(e,r);default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}const Ip={"text-size":zp};async function Lp(e,t){return await Ip[t](e)}async function Rp(e,t){let n=xe(t),r=Np[n];return await T(e,[`settings`,`put`,`system`,`font_scale`,r]),ge(n,r)}async function zp(e){let n=(await T(e,[`settings`,`get`,`system`,`font_scale`])).stdout.trim(),r=n===`null`?Pp:n,i=/^(\d+(\.\d+)?)$/.test(r)?Number(r):NaN;if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Android reported an unusable font scale: ${n||`(empty)`}`,{deviceId:e.id,fontScale:n,hint:"Run `adb shell settings get system font_scale` to see what the device holds."});return ge(Bp(i),r)}function Bp(e){let t=ye[0],n=1/0;for(let r of ye){let i=Math.abs(Number.parseFloat(Np[r])-e);i>=n||(t=r,n=i)}return t}function Vp(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function Hp(e,n){let i=Up(e,n),a=[];for(let t of i){let n=await ct(e,t,{allowFailure:!0});if(n.exitCode===0)return;a.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let o=r(a);throw a.length>0&&a.every(e=>Wp(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:o})}function Up(e,t){let n=t===`match`?`1`:`9999`,r=[Ne(`adb`,`shell`,[`cmd`,`fingerprint`,`touch`,n]),Ne(`adb`,`shell`,[`cmd`,`fingerprint`,`finger`,n])];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function Wp(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function Gp(e,n){let r=_e(n);if(r!==`toggle`)return r;let i=await T(e,[`cmd`,`uimode`,`night`],{allowFailure:!0});if(i.exitCode!==0)throw w(`Failed to read current Android appearance`,i);let a=Kp(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`auto`?`dark`:a===`dark`?`light`:`dark`}function Kp(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}const qp=Buffer.from([137,80,78,71,13,10,26,10]);async function Jp(e,t,n={}){if(n.stabilize===!1){await Zp(e,t);return}await Yp(e);try{await _(1e3),await Zp(e,t)}finally{await Xp(e).catch(()=>{})}}async function Yp(e){let t=t=>T(e,t,{allowFailure:!0});await t([`settings`,`put`,`global`,`sysui_demo_allowed`,`1`]);let n=e=>t([`am`,`broadcast`,`-a`,`com.android.systemui.demo`,`-e`,`command`,...e]);await n([`clock`,`-e`,`hhmm`,`0941`]),await n([`notifications`,`-e`,`visible`,`false`])}async function Xp(e){await T(e,[`am`,`broadcast`,`-a`,`com.android.systemui.demo`,`-e`,`command`,`exit`],{allowFailure:!0})}async function Zp(e,n){let r=await st(e,[`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(qp);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=Qp(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await x().files.writeBytes(n,r.stdoutBuffer.subarray(i,a))}function Qp(e,t){let n=t+qp.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}async function $p(e,t,n=0){let r=Ke(e);if(r){await r({action:`type`,text:t,delayMs:n}),xm(`type`,`provider-native`,t);return}let i=await im(e,`type`,t);if(i.backend===`test-ime`){await am(e,i.packageName,t,n);return}if(n>0&&Array.from(t).length>1){await sm(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await sm(e,{action:`type`,text:t,chunkSize:8,delayMs:0})}async function em(e,t,n,r,i=0,a={}){let o=await gu(e,t,n,a),s=Ke(e);if(s)return await s({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),xm(`fill`,`provider-native`,r),Z(r,o,await pu(e,t,n,r,a));let c=null,u=0;try{for(let s of tm(i)){await Va(e,t,n),u+=1;let i=await im(e,`fill`,r);if(i.backend===`test-ime`)return Z(r,o,await om(e,i.packageName,t,n,r,o,a));let l=await nm(e,{x:t,y:n,text:r,beforeTarget:o,attempt:s},a);if(c=l,l.ok)return;if(l.reason===`ime_capture`)return Z(r,o,l);let d=_u(r,o,l);if(d)return d}}catch(e){throw l(e,u)}return Z(r,o,c)}function tm(e){return[{clearPadding:12,minClear:8,maxClear:48,chunkSize:e>0?1:8,inputDelayMs:e},{clearPadding:24,minClear:16,maxClear:96,chunkSize:e>0?1:4,inputDelayMs:e>0?e:15}]}async function nm(e,t,n){let{x:r,y:i,text:a,beforeTarget:o,attempt:s}=t;return await fm(e,rm(a,o,s)),await sm(e,{action:`fill`,text:a,chunkSize:s.chunkSize,delayMs:s.inputDelayMs}),pu(e,r,i,a,n)}function rm(e,t,n){let r=Array.from(e).length;return Sm(r>0?r+n.clearPadding:t?.text?Array.from(t.text).length+n.clearPadding:n.maxClear,n.minClear,n.maxClear)}async function im(e,t,n){if(ss(e))return{backend:`test-ime`,packageName:(await Vo(C(e))).manifest.packageName};let r=await pm(e,t),i=r?.inputMethodPackage;return qo(i)?{backend:`test-ime`,packageName:i}:(hm(n),mm(r,t),{backend:`adb-shell`})}async function am(e,t,n,r){let i=y(e);await lm(e,cm(n,r>0?1:1/0,r),{delayMs:r,sendChunk:async e=>await Jo(i,t,e)}),xm(`type`,`test-ime`,n)}async function om(e,t,n,r,i,a,o){let s=y(e),c=null,u=0;try{for(let l=0;l<2;l+=1){l>0&&(await Va(e,n,r),u+=1),await Yo(s,t),u+=1,i&&(await Jo(s,t,i),u+=1);let d=await pu(e,n,r,i,o);if(c=d,d.ok||_u(i,a,d))break}}catch(e){throw l(e,u)}return xm(`fill`,`test-ime`,i),c}async function sm(e,t){await lm(e,cm(t.text,t.chunkSize,t.delayMs),{delayMs:t.delayMs,sendChunk:async t=>{try{await dm(e,t)}catch(e){throw nt(e)}}}),xm(t.action,`adb-shell`,t.text)}function cm(e,t,n){let r=e.split(`
|
|
18
|
-
`);return r.flatMap((e,i)=>{let a=
|
|
19
|
-
`&&(e<32||e>126))return!1}return!0}function
|
|
10
|
+
`).replace(/\n$/,``),n=t.match(/^clipboard text:\s*(.*)$/i);return n?n[1]??``:t.trim().toLowerCase()===`null`?``:t}const Ho=`com.callstack.agentdevice.imehelper`,Uo=`android-ime-helper-v1`;async function Wo(e){return e.imeHelperArtifact??await Go()}async function Go(){return await x().resolveHelperArtifact({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Ko,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}const U=`IME helper`;function Ko(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let n=e;return{name:O(n.name,`name`,`android-ime-helper`,U),version:jn(n.version,`version`,U),assetName:jn(n.assetName,`assetName`,U),sha256:Mn(n.sha256,U),packageName:O(n.packageName,`packageName`,Ho,U),versionCode:An(n.versionCode,`versionCode`,U),serviceComponent:O(n.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,U),broadcastProtocol:O(n.broadcastProtocol,`broadcastProtocol`,Uo,U)}}const qo=new Set;async function Jo(e){return await x().ensureHelperInstalled({cache:qo,installTimeoutMs:3e4,helperLabel:`Android IME helper`},e)}function Yo(){qo.clear()}function W(e){return`${e.platform}:${e.id}`}function Xo(e){return e===Ho}async function Zo(e,t,n){await $o(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Qo(e,t){await $o(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function $o(e,t,n,r){let i=[`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Uo);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);try{let r=await b(e,i,{allowFailure:!0,timeoutMs:1e4});if(r.exitCode!==0)throw w(`Android IME helper broadcast failed`,r,{action:n,packageName:t})}catch(e){throw rt(e)}}const es=`agent_device_ime_helper_previous_ime`,ts=`secure`,ns=`default_input_method`,rs={previousIme:es,defaultInputMethod:ns};async function G(e){let t=await b(e,[`settings`,`get`,ts,ns],{allowFailure:!0,timeoutMs:5e3});return cs(t.exitCode===0?t.stdout:``)}async function K(e){let t=await b(e,[`settings`,`get`,ts,es],{allowFailure:!0,timeoutMs:5e3});return cs(t.exitCode===0?t.stdout:``)||void 0}async function is(e,t){return(await b(e,[`settings`,`put`,ts,es,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0&&await K(e)===t}async function as(e){await b(e,[`settings`,`delete`,ts,es],{allowFailure:!0,timeoutMs:5e3})}async function os(e,t,n){try{(t?await is(e,t):await ss(e))||S({level:`warn`,phase:`android_test_ime_record_rollback_failed`,data:{device:n,hadPriorRecord:t!==void 0}})}catch(e){S({level:`warn`,phase:`android_test_ime_record_rollback_failed`,data:{device:n,hadPriorRecord:t!==void 0,error:s(e).message}})}}async function ss(e){return await as(e),await K(e)===void 0}function cs(e){let t=e.trim();return!t||t===`null`?``:t}const q=new Set,ls=new Map;function us(e){return q.has(W(e))}function ds(e,t,n){return Bt(ls,`${e}:${t}`,n)}function fs(){q.clear()}function ps(e,t){let n=W(e);t?q.add(n):q.delete(n)}async function ms(e,t){return await ds(t.stateDir,e.id,async()=>{let n=W(e);if(!q.has(n))return{restored:!1,reason:`no-record`};q.delete(n);let r=await gs(y(e),e);return hs(r.reason)&&await x().imeRecoveryMarkers.clear(t.stateDir,e.id),r})}function hs(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function gs(e,t){let n=t.id;if(q.has(W(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await K(e);if(!r)return{restored:!1,reason:`no-record`};let i=await G(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return S({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await b(e,[`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await G(e);return a===r?(await as(e).catch(()=>{}),S({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(S({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function _s(e){let t=x().imeRecoveryMarkers,n=await t.read(e.stateDir);if(n.length===0)return;let r;try{r=new Set(await e.listSerials())}catch(e){S({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:s(e).message}});return}for(let i of n){if(!r.has(i))continue;let n={platform:`android`,id:i,name:i,kind:i.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{await ds(e.stateDir,i,async()=>{let r=await gs(y(n),n);r.restored&&S({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:r.previousIme}}),hs(r.reason)&&await t.clear(e.stateDir,i)})}catch(e){S({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:s(e).message}})}}}async function vs(){x();try{return(await ze(nt([`devices`]),{timeoutMs:5e3})).stdout.split(`
|
|
11
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const ys=2e3;async function bs(e=x().environment,t=x().files){let n=e.ANDROID_HOME||e.ANDROID_SDK_ROOT,r=await Ms(n,t),i=await zt(`adb`,[`version`]);return i?Os({license:r,sdkRoot:n,versionLine:i}):js(n,r)}async function xs(e,t){if(e.platform!==`android`)return[];let n=y(e,t.transportOverrides.androidAdb),r=[];return t.shouldProbeMetro&&r.push(await Ds(n,e.id,t.metroPort)),r.push(await Ss(n,e)),r}async function Ss(e,t){try{let n=await G(e),r=us(t);return n===await Cs()&&!r?await ws(e,t,n):Ts(t,n,r)}catch(e){return Es(e)}}async function Cs(){try{return(await Go()).manifest.serviceComponent}catch{return}}async function ws(e,t,n){let r=(await b(e,[`settings`,`get`,`secure`,rs.previousIme],{allowFailure:!0,timeoutMs:ys})).stdout.trim(),i=r&&r!==`null`?r:void 0;return{id:`android-test-ime`,status:`fail`,summary:`Android test IME helper is the active input method on ${t.id}, but no active session owns it -- likely left over from a crashed session.`,hint:`A stuck test IME leaves the real keyboard unavailable on this device until restored.`,command:i?`adb -s ${t.id} shell ime set ${i}`:`adb -s ${t.id} shell ime list -s`,evidence:{currentIme:n,previousIme:i}}}function Ts(e,t,n){return{id:`android-test-ime`,status:`pass`,summary:n?`Android test IME helper is active for this session on ${e.id}.`:`Android test IME helper is not active on ${e.id}; the device's normal IME is in use.`,evidence:{currentIme:t}}}function Es(e){let t=s(e);return{id:`android-test-ime`,status:`warn`,summary:`Could not inspect the Android test IME helper state.`,hint:t.message,evidence:{code:t.code}}}async function Ds(e,t,n){try{let r=await e([`reverse`,`--list`],{allowFailure:!0,timeoutMs:ys}),i=`tcp:${n} tcp:${n}`,a=r.stdout.includes(i);return{id:`android-reverse`,status:a?`pass`:`warn`,summary:a?`Android adb reverse exists for Metro port ${n}.`:`Android adb reverse is missing for Metro port ${n}.`,command:a?void 0:`adb -s ${t} reverse tcp:${n} tcp:${n}`,evidence:{stdout:r.stdout.trim()}}}catch(e){let t=s(e);return{id:`android-reverse`,status:`warn`,summary:`Could not inspect Android adb reverse mappings.`,hint:t.message,evidence:{code:t.code}}}}function Os(e){return{id:`toolchain`,status:ks(e),summary:e.versionLine?`Android toolchain: ${e.versionLine}; ${As(e.sdkRoot)}.`:`Android toolchain: adb is present but version check failed.`,hint:e.license===`missing`?`Accept Android SDK licenses before installing/building apps.`:void 0,command:e.license===`missing`?`sdkmanager --licenses`:void 0,evidence:{adbVersion:e.versionLine??null,androidHome:e.sdkRoot??null,license:e.license}}}function ks(e){return e.versionLine&&e.sdkRoot&&e.license!==`missing`?`pass`:`info`}function As(e){return e?`ANDROID_HOME/ANDROID_SDK_ROOT set`:`ANDROID_HOME unset`}function js(e,t){return{id:`toolchain`,status:`info`,summary:`Android toolchain: adb not found on PATH.`,hint:`Install Android platform-tools or add adb to PATH.`,evidence:{androidHome:e??null,license:t}}}async function Ms(e,t){if(!e)return`unknown`;try{return await t.access(E.join(e,`licenses`,`android-sdk-license`)),`accepted`}catch{return`missing`}}function Ns(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=Ls(t),r={failureReason:t.reason??`text_mismatch`,targetInput:Fs(t.targetInput),actualInput:Fs(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function J(e){return e?e.password?!0:Ps(e.text):!1}function Ps(e){return e?Array.from(e).every(Is):!1}function Fs(e){if(!e)return null;let t=J(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function Is(e){return e===`•`||e===`*`||e===`●`}function Ls(e){return e.masked===!0||J(e.targetInput)||J(e.actualInput)}const Rs=new WeakMap;function zs(e,t){return t&&Rs.set(e,t),e}function Bs(e){return Rs.get(e)}function Vs(e){return e.clickable}function Hs(e){return e.focusable||e.focused===!0}function Y(e){return Vs(e)||Hs(e)}function Us(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function Ws(e,t){return{raw:e,...t?{effectiveRect:t}:{}}}function Gs(e,t,n){if(!e)return;let r=Js(e);return t&&(r=qs(r,t)),n&&(r=qs(r,n)),r}function Ks(e){return{...e.raw,...e.effectiveRect?{rect:e.effectiveRect}:{rect:void 0},hittable:e.raw.hittable===!0&&le(e.effectiveRect)?!0:void 0}}function qs(e,t){let n=Math.max(e.x,t.x),r=Math.max(e.y,t.y),i=Math.min(e.x+e.width,t.x+t.width),a=Math.min(e.y+e.height,t.y+t.height),o=i>n&&a>r;return{x:o?n:e.x,y:o?r:e.y,width:o?i-n:0,height:o?a-r:0}}function Js(e){return{x:e.x,y:e.y,width:Math.max(0,e.width),height:Math.max(0,e.height)}}function Ys(e,t){let n=new Set;return Xs(e,n,t),Qs(e,n,t),n}function Xs(e,t,n){for(let r of e.children){if(n?.check(`work`),r.visibleToUser===!1){t.add(r);continue}Xs(r,t,n)}}function Zs(e,t,n){return n?.check(`work`),e.children.filter(e=>!t.has(e)&&e.visibleToUser!==!1)}function Qs(e,t,n){let r=Zs(e,t,n).filter(ec);if(r.length<2)return;let i=r.filter(e=>tc(e)&&nc(e));if(i.length===0)return;let a=$s(i);for(let r of Zs(e,t,n))n?.check(`work`),tc(r)&&(nc(r)&&(a===void 0||r.windowLayer===a)||t.add(r))}function $s(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function ec(e){return e.windowIndex!==void 0||e.windowType!==void 0}function tc(e){return e.windowType===1}function nc(e){return e.windowActive===!0||e.windowFocused===!0}function rc(e,t,n,r,i){let a=new Set(e.sourceNodes),o=ac(t,i),s=ic(o,n,oc(o,a,i),i);if(!s)return{nodes:[],sourceNodes:[]};let c=new Set(ac([s],i)),l=[];for(let[t,n]of e.sourceNodes.entries())i.check(`work`),c.has(n)&&l.push(t);if(l.length===0)return{nodes:[],sourceNodes:[]};let u=1/0;for(let t of l)i.check(`work`),u=Math.min(u,e.nodes[t]?.depth??0);let d=[];for(let t of l)i.check(`work`),(e.nodes[t]?.depth??0)-u<=r&&d.push(t);return i.consume(d.length),{nodes:ce(d.map(t=>e.nodes[t]),u),sourceNodes:d.map(t=>e.sourceNodes[t])}}function ic(e,t,n,r){for(let i of e)if(r.check(`work`),ae(i,t)&&n.has(i))return i;return null}function ac(e,t){let n=[],r=[...e].reverse();for(;r.length>0;){t.check(`work`);let e=r.pop();n.push(e);for(let n=e.children.length-1;n>=0;--n)t.check(`work`),r.push(e.children[n])}return n}function oc(e,t,n){let r=new Set;for(let i=e.length-1;i>=0;--i){n.check(`work`);let a=e[i];if(t.has(a)){r.add(a);continue}for(let e of a.children)if(n.check(`work`),r.has(e)){r.add(a);break}}return r}function sc(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=cc(e);return t.interactiveOnly?lc(e,a,n,r,i):a.isStructural||a.isVisual?fc(e,a,r):!0}function cc(e){let t=mc(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!Us(e.label??``),hasMeaningfulId:r&&!Us(e.identifier??``),isStructural:hc(t),isVisual:t===`imageview`||t===`imagebutton`}}function lc(e,t,n,r,i){return dc(e)?!1:Y(e)||oe(t.type)&&r?!0:uc(t,n,r,i)}function uc(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r&&!t?!1:t||n||r}function dc(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function fc(e,t,n){return Y(e)||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function pc(e){if(!e)return!1;let t=mc(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function mc(e){return e?e.toLowerCase():``}function hc(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function gc(e,t,n,r){return{...Ws(e,t),...n?{clipsDescendants:!0}:{},...r?{windowRect:r}:{}}}const _c=`ANDROID_SNAPSHOT_PRESENTATION_FAILED`;var X=class extends Error{code=_c;qualityReasonCode=`presentation-failed`;details;analysis;constructor(e,t,n){super(e),this.name=`AndroidSnapshotPresentationFailure`,this.details=t,this.analysis=n}};function vc(e){return e instanceof X?e.code===_c:!!(e&&typeof e==`object`&&e.code===_c)}var yc=class{workUnits=0;options;defaultMaxWorkUnits;deadlineAtMs;constructor(e,t){this.options=e,this.defaultMaxWorkUnits=t;let n=e.now??Date.now;this.deadlineAtMs=e.deadlineAtMs??n()+wc()}get workUnitCount(){return this.workUnits}check(e){this.consume(1)}consume(e){this.workUnits+=e;let t=this.options.maxWorkUnits??this.defaultMaxWorkUnits;if(this.workUnits>t)throw new X(`Android snapshot presentation exceeded its linear work budget`,{phase:`complexity`,workUnits:this.workUnits,maxWorkUnits:t});if((this.options.now??Date.now)()>=this.deadlineAtMs)throw new X(`Android snapshot presentation exceeded its cooperative deadline`,{phase:`deadline`,workUnits:this.workUnits,deadlineAtMs:this.deadlineAtMs,maxWorkUnits:t})}};function bc(e,t){return new yc(e??{},t)}function xc(e,t,n){let r=new Map;for(let i of e){n.check(`regular-invariant`);let e=Sc(i,r,t),a=i.effectiveRect;if(!a||!le(a)){if(Ks(i).hittable===!0)throw new X(`Android regular snapshot node ${i.raw.index} with degenerate effective geometry was marked hittable`,{phase:`regular-invariant`,workUnits:n.workUnitCount,nodeIndex:i.raw.index,frame:a});r.set(i.raw.index,e);continue}if(e&&!Cc(a,e))throw new X(`Android regular snapshot node ${i.raw.index} escaped its cumulative clip`,{phase:`regular-invariant`,workUnits:n.workUnitCount,nodeIndex:i.raw.index,frame:a,clip:e});r.set(i.raw.index,i.clipsDescendants?a:e)}}function Sc(e,t,n){let r=e.raw.parentIndex;return r===void 0?e.windowRect??n:t.get(r)??e.windowRect??n}function Cc(e,t){let n=1e-4;return e.x>=t.x-n&&e.y>=t.y-n&&e.x+e.width<=t.x+t.width+n&&e.y+e.height<=t.y+t.height+n}function wc(){return 250}function Tc(e,t,n){let r=n.depth??1/0,i=se(n.scope),a=Uc(e),o=bc(n.androidPresentation,Math.max(1024,a.rawNodeCount*128)),s={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:i?1/0:r,options:n,analysis:a,interactiveDescendantMemo:new Map,hidden:new Set,presentationBudget:o,presentationNodes:[],truncated:!1};try{o.check(`work`),s.viewport=Ic(e,o),s.hidden=n.raw?new Set:Ys(e,o);for(let t of e.children)if(Dc(s,t,0),s.truncated)break;n.raw||xc(s.presentationNodes,s.viewport,o);let t=s.nodes,a=new Map(s.sourceNodes.map((e,t)=>[e,t])),{nodes:c,sourceNodes:l}=i?rc(s,e.children,i,r,o):s,u={nodes:c,sourceNodes:l,occlusionContext:{nodes:t,sourceIndexByNodeIndex:new Map(l.flatMap((e,t)=>{let n=a.get(e),r=c[t]?.index;return n===void 0||r===void 0?[]:[[r,n]]})),androidSiblingOrderByNodeIndex:Ec(s.sourceNodes)},analysis:s.analysis};return s.truncated?{...u,truncated:!0}:u}catch(e){throw vc(e)&&(e.analysis??=s.analysis),e}}function Ec(e){let t=new Map,n=new Map;for(let[r,i]of e.entries()){let e=Bs(i);if(!e)continue;let a=t.get(e.parent);a===void 0&&(a=t.size,t.set(e.parent,a)),n.set(r,{group:a,order:e.order})}return n}function Dc(e,t,n,r,i=!1,a=!1,o=!1,s,c){if(e.presentationBudget.check(`work`),Oc(e,t,n))return;let l=t.windowRect??s??e.viewport,u=kc(e,t,c,l),d=Ac(e,t,r,i,a,o,u,l),f=i||Y(t),p=a||pc(t.type),ee=jc(e,t,u,c);Mc(e,t,n,d,f,p,o||Ht(t.identifier),l,ee)}function Oc(e,t,n){return e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes?(e.truncated=!0,!0):n>e.maxDepth||e.hidden.has(t)}function kc(e,t,n,r){return e.options.raw?t.rect:Gs(t.rect,r,n)}function Ac(e,t,n,r,i,a,o,s){return!e.options.raw&&!sc(t,e.options,r,zc(e,t),i)?n:Nc(e,t,n,a||Ht(t.identifier),o,s)}function jc(e,t,n,r){return e.options.raw||!Lc(t)?r:n}function Mc(e,t,n,r,i,a,o,s,c){for(let l of t.children)if(Dc(e,l,n+1,r,i,a,o,s,c),e.truncated)return}function Nc(e,t,n,r,i,a){let o=e.nodes.length;return e.sourceNodes.push(t),Fc(e,t,Pc(e,t,n,r),i,a),o}function Pc(e,t,n,r){return{index:e.nodes.length,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,...t.passiveFacts,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,focused:t.focused,visibleToUser:t.visibleToUser,hittable:Y(t)||void 0,depth:Rc(e.nodes,n),parentIndex:n,...Bc(t,e.hidden),...r?{systemChrome:!0}:{}}}function Fc(e,t,n,r,i){let a=gc(n,r,!e.options.raw&&Lc(t),i);e.presentationNodes.push(a),e.nodes.push(e.options.raw?a.raw:Ks(a))}function Ic(e,t){let n=[],r=[...e.children];for(;r.length>0;){t.check(`work`);let e=r.pop();le(e.windowRect)&&n.push(e.windowRect),r.push(...e.children)}return ue(n)??void 0}function Lc(e){return e.scrollable===!0&&oe(e.type)}function Rc(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function zc(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(!e.hidden.has(n)&&n.visibleToUser!==!1&&(Y(n)||zc(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function Bc(e,t){return Vc(e,t)?{...e.canScrollBackward?{hiddenContentAbove:!0}:{},...e.canScrollForward?{hiddenContentBelow:!0}:{}}:{}}function Vc(e,t){if(!e.scrollable||!oe(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let n=Hc(e,t);return!(n&&n.horizontal>n.vertical&&n.horizontal>16)}function Hc(e,t){let n=e.children.filter(e=>!t.has(e)&&e.visibleToUser!==!1);if(!e.rect||n.length===0)return null;let r=n.map(e=>e.rect).filter(e=>e!==void 0);if(r.length===0)return null;let i=Math.min(...r.map(e=>e.x)),a=Math.max(...r.map(e=>e.x+e.width)),o=Math.min(...r.map(e=>e.y)),s=Math.max(...r.map(e=>e.y+e.height));return{horizontal:Math.max(0,a-i-e.rect.width),vertical:Math.max(0,s-o-e.rect.height)}}function Uc(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}function Wc(){let e=[],t=()=>e.at(-1)===!0;return{open(n,r){let i=t()||Ht(n);return r||e.push(i),i},close(){e.pop()}}}function*Gc(e){let t=/<node\b[^>]*>|<\/node>/g,n=Wc(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=Kc(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function Kc(e){let t=qc(e),n=Ut(t.bounds);return{...t,...n?{rect:n}:{}}}function qc(e){let t=Jc(e),n=e=>nl(t,e),r=e=>{let t=n(e);if(t!==null)return t===`true`},i=e=>{let t=n(e);if(t===null||t.trim()===``)return;let r=Number(t);return Number.isFinite(r)?r:void 0},a=(e,t)=>{let n=i(t);return n===void 0?{}:{[e]:n}},o=(e,t)=>{let r=Ut(n(t));return r===void 0?{}:{[e]:r}},s=(e,t)=>{let r=n(t);return r===null||r===``?{}:{[e]:r}},c=(e,t)=>{let n=r(t);return n===void 0?{}:{[e]:n}};return{text:n(`text`),desc:n(`content-desc`),resourceId:n(`resource-id`),packageName:n(`package`),className:n(`class`),bounds:n(`bounds`),clickable:r(`clickable`),enabled:r(`enabled`),focusable:r(`focusable`),focused:r(`focused`),password:r(`password`),...c(`editable`,`editable`),...a(`selectionStart`,`selection-start`),...a(`selectionEnd`,`selection-end`),...c(`hintShowing`,`hint-showing`),...s(`hint`,`hint`),...c(`visibleToUser`,`visible-to-user`),...c(`selected`,`selected`),...c(`heading`,`heading`),...s(`roleDescription`,`role-description`),...c(`checked`,`checked`),...a(`drawingOrder`,`drawing-order`),...c(`scrollable`,`scrollable`),...c(`canScrollForward`,`can-scroll-forward`),...c(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...c(`windowActive`,`window-active`),...c(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function Jc(e){let t=new Map,n=e.indexOf(` `),r=e.lastIndexOf(`>`);if(n<0||r<=n)return t;let i=n;for(;i<r;){let n=Yc(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Yc(e,t,n){if(t=Zc(e,t,n),t>=n||Qc(e[t]))return;let r=t;t=Xc(e,t,n);let i=e.slice(r,t);if(t=Zc(e,t,n),!i||e[t]!==`=`)return;t=Zc(e,t+1,n);let a=e[t];if(!$c(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:Wt(e.slice(o,s)),nextCursor:s+1}}function Xc(e,t,n){for(;t<n&&!tl(e[t]??``);)t+=1;return t}function Zc(e,t,n){for(;t<n&&el(e[t]??``);)t+=1;return t}function Qc(e){return e===`/`||e===`>`}function $c(e){return e===`"`||e===`'`}function el(e){return e===` `||e===`
|
|
12
|
+
`||e===`\r`||e===` `}function tl(e){return e===`=`||e===`/`||e===`>`||el(e)}function nl(e,t){return e.get(t)??null}function rl(e){let t={type:null,label:null,value:null,passiveFacts:{},identifier:null,packageName:null,clickable:!1,focusable:!1,depth:-1,children:[]},n=[t],r=/<node\b[^>]*>|<\/node>/g,i=r.exec(e);for(;i;){let t=i[0];if(t.startsWith(`</node`)){n.length>1&&n.pop(),i=r.exec(e);continue}let a=Kc(t),o=n.at(-1),s=il(a,o.depth+1,o);o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return t}function il(e,t,n){let r=e.text||e.desc;return zs({type:e.className,label:r,value:e.text,passiveFacts:{contentDescription:e.desc&&e.desc!==r?e.desc:void 0,enabled:e.enabled,selected:e.selected,heading:e.heading,roleDescription:e.roleDescription,checked:e.checked,editable:e.editable,password:e.password,hintShowing:e.hintShowing,placeholder:e.hint,selectionStart:e.selectionStart,selectionEnd:e.selectionEnd},identifier:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused,visibleToUser:e.visibleToUser,clickable:e.clickable===!0,focusable:e.focusable===!0,scrollable:e.scrollable,canScrollForward:e.canScrollForward,canScrollBackward:e.canScrollBackward,windowIndex:e.windowIndex,windowType:e.windowType,windowLayer:e.windowLayer,windowActive:e.windowActive,windowFocused:e.windowFocused,windowRect:e.windowRect,depth:t,parentIndex:void 0,children:[]},e.drawingOrder===void 0?void 0:{parent:n,order:e.drawingOrder})}function al(e){let t=new Map;return e.nodes.forEach((n,r)=>{t.set(n.index,e.sourceNodes[r]?.clickable)}),{kind:`exact`,provider:`android-helper`,clickableByNodeIndex:t}}const ol=new Set([`android`,`com.android.systemui`]);function sl(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=vl(e,n.foregroundAppPackage);return ul(r,t)?cl(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):gl(r)?{outcome:`ok`}:ll(r)?{outcome:`system-surface-only`}:dl(r)?{outcome:`ok`}:fl(r)?cl(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):pl(r)||ml(r,t)?cl(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):hl(r)?cl(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function cl(e,t,n,r){return{outcome:`unusable`,decision:_l(e,t,n,r)}}function ll(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function ul(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function dl(e){return fl(e)&&e.inputMethodMeaningfulNodeCount>=2}function fl(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function pl(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function ml(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function hl(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function gl(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function _l(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Ml(e,t)}}function vl(e,t){let n=yl(t);for(let t of Gc(e))bl(n,t);return Dl(n)}function yl(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function bl(e,t){e.nodeCount+=1,jl(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&xl(e,t.resourceId),Sl(e,t),Cl(e,t)}function xl(e,t){let n=ln(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Sl(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Cl(e,t){Ol(t)&&(e.meaningfulNodeCount+=1,wl(e,t),El(e,t))}function wl(e,t){e.currentWindowType===1&&!Al(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Tl(e)&&!Vt(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Tl(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function El(e,t){Al(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),ne({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Dl(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Ol(e){return e.visibleToUser===!1?!1:kl(e.text)||kl(e.desc)||kl(e.resourceId)}function kl(e){return e!==null&&e.trim()!==``}function Al(e){return e===null||ol.has(e)}function jl(e){return e!==null&&ol.has(e)}function Ml(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function Nl(e){let t=await z(e.deviceKey,{resetRuntime:!0,signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await Pl(e.adb,e.packageName)}async function Pl(e,t){await hi({adb:e,packageName:t}),await g(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:t}})}const Fl=Symbol(`androidSnapshotCaptureEvidence`);function Il(e,t){return Object.defineProperty(e,Fl,{value:t}),e}function Ll(e){let t={...e,backend:`android`,producer:`android-uiautomator`},n=e[Fl];return ie(t,n.clickability),n.occlusionContext&&f(t,n.occlusionContext),t}async function Rl(e,t={}){let n=C(e,t.helperAdb).exec;return(await Kl(e,t,n)).xml}async function zl(e,t={}){let n=C(e,t.helperAdb).exec,r=await Kl(e,t,n),i=r.xml,a=rl(i),o=Hl(r.metadata,a),s={...t,androidPresentation:{...t.androidPresentation,deadlineAtMs:t.androidPresentation?.deadlineAtMs??Date.now()+250}};try{let e=Tc(a,void 0,s),n=Vl(e.truncated,r.metadata);t.interactiveOnly&&t.includeHiddenContentHints!==!1&&Gl({options:s,tree:a,xml:i,interactiveSnapshot:e});let{sourceNodes:c,occlusionContext:l,...u}=e;return Il({...u,...Wl(n),androidSnapshot:o,quality:{state:`healthy`,backend:`android-helper`}},{clickability:al(e),occlusionContext:l})}catch(e){if(!vc(e))throw e;return Bl({failure:e,androidSnapshot:o})}}function Bl(e){return Il({nodes:[],truncated:!0,analysis:e.failure.analysis??{rawNodeCount:0,maxDepth:0},androidSnapshot:{...e.androidSnapshot,presentationFailure:{phase:e.failure.details.phase,workUnits:e.failure.details.workUnits,...e.failure.details.maxWorkUnits===void 0?{}:{maxWorkUnits:e.failure.details.maxWorkUnits}}},quality:{state:`sparse`,backend:`android-helper`,reason:e.failure.message,reasonCode:e.failure.qualityReasonCode}},{clickability:{kind:`exact`,provider:`android-helper`,clickableByNodeIndex:new Map}})}function Vl(e,t){return e===!0||t.helperTruncated===!0||e}function Hl(e,t){return Ul(t)===!1?{...e,occlusionScanUnavailable:!0}:e}function Ul(e){let t=[...e.children];if(t.length!==0){for(;t.length>0;){let e=t.pop();if(Bs(e)!==void 0)return!0;t.push(...e.children)}return!1}}function Wl(e){return e===!0?{truncated:!0}:{}}function Gl(e){if(pu(e.interactiveSnapshot.nodes).size>0||fu(e.xml))return;let t=Tc(e.tree,void 0,{...e.options,interactiveOnly:!1});mu(Te(a(t.nodes)),t,e.interactiveSnapshot)}async function Kl(e,t,n){let r=C(e,t.helperAdb),i=await m(`android_snapshot_helper_artifact_resolution`,async()=>await uu(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await ql(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),du(i.errorReason)}async function ql(e,t,n,r){let i=ti(e),a=C(e,t.helperAdb),o=Jl(t,i);try{let e;for(let o=0;;o+=1){o>0&&await eu(t.signal);let s=await $l({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3||t.transient!==void 0&&Date.now()>=t.transient.settleBy)return await tu({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal,retireHelper:t.transient===void 0});e=s.decision.reason}}finally{o&&await z(i)}}function Jl(e,t){return e.transient?Ui(t)===void 0:e.helperSessionScope!==`daemon-session`}function Yl(e){return e.transient?`current-only`:e.helperInstallPolicy??`missing-or-outdated`}async function Xl(e,t,n,r,i){let a=await m(`android_snapshot_helper_install`,async()=>await _r({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:Yl(e),timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:Yl(e)});return h({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function Zl(e){let{signal:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}=e,o=vi({adb:n,adbProvider:r,artifact:i,deviceKey:a,signal:t});try{let e=await m(`android_snapshot_helper_session_capture`,async()=>await ia(o),{packageName:i.manifest.packageName,version:i.manifest.version,timeoutMs:tr});if(e)return e}catch(e){if(t?.throwIfAborted(),ai(e))throw e;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:s(e).message}}),await Pl(n,i.manifest.packageName)}return await m(`android_snapshot_helper_capture`,async()=>await _i(o),{packageName:i.manifest.packageName,version:i.manifest.version,timeoutMs:tr,commandTimeoutMs:nr})}function Ql(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,pixelDensity:e.metadata.pixelDensity,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function $l(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await Xl(t,n,r,i,a);e.installed&&await z(a),s=Ql(await Zl({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){if(t.signal?.throwIfAborted(),fr(e))throw e;return{outcome:`captured`,capture:await ru({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=sl(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});if(c.outcome===`unusable`)return{outcome:`unusable`,decision:c.decision};let l=c.outcome===`system-surface-only`;return!l&&o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:{xml:s.xml,metadata:l?{...s.metadata,systemSurfaceOnly:!0}:s.metadata}}}async function eu(e){e?.throwIfAborted(),await g(250),e?.throwIfAborted()}async function tu(e){throw h({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),e.retireHelper&&await Nl({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),nu(e.contentRecovery,e.attempts)}function nu(e,n){return new t(`COMMAND_FAILED`,e.failureReason,{...e.diagnostics,androidSnapshotHelperFailureReason:e.reason,attempts:n,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function ru(e){let t=iu(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await z(e.helperDeviceKey),await Pl(e.adb,e.artifact.manifest.packageName),ur({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),au(e.error,t)}function iu(e){let t=s(e),n=lu(t.details?.helper);if(n&&n!==t.message)return`${t.message}: ${n}`;if(n)return n;let r=(typeof t.details?.stderr==`string`?t.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return r?`${t.message}: ${r}`:t.message}function au(e,n){let r=s(e),i=ou(r);return new t(o(r.code),`Android snapshot helper failed: ${n}`,{...r.details,...cu(r),androidSnapshotHelperFailureReason:n,...i?{androidCaptureFailureReason:i}:{},hint:su(r,i)},e)}function ou(e){return mt(e)}function su(e,t){return t===`accessibility-timeout`?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function cu(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function lu(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}async function uu(e){if(e)return{artifact:e};let t=Fe(),n=E.join(Ie(),`android`,`snapshot-helper`,`dist`),r=E.join(n,`agent-device-android-snapshot-helper-${t}.manifest.json`);try{await x().files.access(r)}catch{return{}}try{let e=rr(JSON.parse(await x().files.readText(r))),t=E.join(n,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await x().files.access(t),{artifact:{apkPath:t,manifest:e}}}catch(e){return{errorReason:s(e).message}}}function du(e){let n=e??`the bundled helper artifact was not found`;return new t(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${n}`,{androidSnapshotHelperFailureReason:n,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function fu(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function pu(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function mu(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const hu=Object.freeze({now:()=>Date.now(),sleep:g});async function gu(e,t,n,r,i={},a=hu){let o=await Iu(e),s=a.now()+1500,c=null;for(;;){let l=await Eu(e,t,n,r,o,i);if(l.reason===`ime_capture`)return l;let u=s-a.now();if(l.ok&&c?.ok||u<=0)return l;c=l,await a.sleep(Math.min(150,u))}}async function _u(e,t,n,r={}){return Cu(await Rl(e,r),t,n)}async function vu(e,t,n,r){let i=await Iu(e);return Du(await Rl(e,r),t,n,i).targetInput}async function yu(e,t,n,r={}){try{return await vu(e,t,n,r)}catch(e){return h({level:`warn`,phase:`android_fill_pre_action_target_capture_failed`,data:{error:e instanceof Error?e.message:String(e)}}),null}}function bu(e,n,r){if(r?.ok)return;let a=r?xu(e,n,r):null;if(a)return a;throw i(new t(`COMMAND_FAILED`,wu(r),Tu(e,r)),`unknown`)}function xu(e,t,n){let r=n.targetInput,i=n.actualInput;if(e.length===0||n.reason===`ime_capture`||!t||!r||!i||J(t)||J(r)||J(i)||!Hu(t,r)||!Hu(t,i)||t.text===n.actual)return null;let a=Uu(t);return h({level:`warn`,phase:`android_fill_verification_unconfirmed`,data:{target:a}}),{verification:`unconfirmed`,requested:e,before:t.text,after:n.actual,target:a}}function Su(e,t,n,r,i={}){let a=Du(e,t,n,i);return Ou(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:ku(a,r)??Au(a,r)}function Cu(e,t,n){return Du(e,t,n).targetInput?.text??null}function wu(e){return e?.reason===`ime_capture`?`Android fill input was captured by the active keyboard instead of the app field`:e?.reason===`masked_unverified`?`Android fill verification could not confirm masked text value`:`Android fill verification failed`}function Tu(e,t){let n=Ns(e,t);return t?.reason===`ime_capture`&&(n.hint=`The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill.`),n}async function Eu(e,t,n,r,i,a){return Su(await Rl(e,a),t,n,r,i)}function Du(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of Gc(e)){let e=Fu(a,r);e&&Lu(i,e,t,n)}return zu(i)}function Ou(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function ku(e,t){let n=e.actualInput;if(!n||!Vu(n))return null;let r=n.text??null,i=Array.from(ju(n)).length,a=Array.from(t).length,o=a===0?i===0:i>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function Au(e,t){let n=e.actualInput;return{ok:n!==null&&Mu(ju(n),t),actual:n?.text??null,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:n}}function ju(e){return e.hintShowing?``:e.text??``}function Mu(e,t){if(e===t)return!0;if(t.length===0)return!1;let n=Nu(e),r=Nu(t);return!n||!r?!1:!!(n===r||Pu(n,r))}function Nu(e){return e.replaceAll(/\s+/g,` `).trim()}function Pu(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function Fu(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:ne({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Bu(e.className??``),hintShowing:e.hintShowing===!0,placeholder:e.hint??null}}async function Iu(e){try{return{activeInputMethodPackage:(await Co(e)).inputMethodPackage}}catch(e){return h({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function Lu(e,t,n,r){let i=de(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=Ru(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=Ru(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=Ru(e.anyAtPoint,t))}function Ru(e,t){return e&&e.area<t.area?e:t}function zu(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Bu(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function Vu(e){return J(e)}function Hu(e,t){return e.resourceId||t.resourceId?e.resourceId===t.resourceId&&e.packageName===t.packageName:e.className===t.className&&e.packageName===t.packageName&&e.rect.x===t.rect.x&&e.rect.y===t.rect.y&&e.rect.width===t.rect.width&&e.rect.height===t.rect.height}function Uu(e){return{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:e.rect}}async function Wu(e,t){return await Gt(t.stateDir),await ds(t.stateDir,e.id,async()=>await Ku(e,t))}function Gu(e){let t=n(e).details?.hint;return{outcome:`helper-unavailable`,reason:s(e).message,...typeof t==`string`?{hint:t}:{}}}async function Ku(e,t){let n=x().imeRecoveryMarkers,r=y(e),i=C(e),a=W(e),o;try{o=await Wo(i),await Jo({adb:r,adbProvider:i,artifact:o,deviceKey:a})}catch(e){return Gu(e)}let{manifest:s}=o,c=await G(r);if(c===s.serviceComponent){let i=await n.write(t.stateDir,e.id),o=await K(r);return i&&q.add(a),{outcome:`settled`,activated:!1,alreadyActive:!0,...i?{}:{persistFailed:!0},previousIme:o,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName}}let l=await K(r);if(!await is(r,c))return await os(r,l,e.id),S({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName};let u=(await n.read(t.stateDir)).includes(e.id);if(!await n.write(t.stateDir,e.id))return await os(r,l,e.id),S({level:`warn`,phase:`android_test_ime_marker_persist_failed`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName};await b(r,[`ime`,`enable`,s.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let d=await b(r,[`ime`,`set`,s.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),f=await G(r);return f===s.serviceComponent?(q.add(a),S({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:c}}),{outcome:`settled`,activated:!0,alreadyActive:!1,previousIme:c,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName}):(q.delete(a),await os(r,l,e.id),u||await n.clear(t.stateDir,e.id),S({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:f,stderr:d.stderr.trim()}}),{outcome:`settled`,activated:!1,alreadyActive:!1,helperServiceComponent:s.serviceComponent,helperPackageName:s.packageName})}function qu(e){return E.join(e,`android-test-ime-pending`)}function Ju(e,t){return E.join(qu(e),encodeURIComponent(t))}async function Yu(e,t){let n=x().files,r,i=!1;try{let a=qu(e);if(r=Ju(e,t),await n.ensureDirectory(a),(await Qu(r))?.serial===t)return!0;let o={version:1,serial:t};if(await n.writeAtomicText(r,`${JSON.stringify(o)}\n`,384),i=!0,(await Qu(r))?.serial!==t)throw Error(`Android test IME marker read-back did not match the requested device.`);return!0}catch(a){return i&&r&&await n.remove(r,{force:!0}).catch(()=>{}),h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:e,serial:t,error:s(a).message}}),!1}}async function Xu(e,t){await x().files.remove(Ju(e,t),{force:!0}).catch(()=>{})}async function Zu(e){let t=x().files,n;try{n=await t.readDirectory(qu(e))}catch{return[]}let r=[];for(let t of n)try{let n=E.join(qu(e),t),i=await Qu(n);i&&Ju(e,i.serial)===n&&r.push(i.serial)}catch{}return[...new Set(r)].sort()}async function Qu(e){try{return $u(await x().files.readText(e))}catch{return}}function $u(e){try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))return;let n=t;return n.version===1&&typeof n.serial==`string`&&n.serial.length>0?{version:1,serial:n.serial}:void 0}catch{return}}const ed=new Jt(`utf-16le`);let td;async function nd(e,t){for(let n of[`AndroidManifest.xml`,`base/manifest/AndroidManifest.xml`]){let r=await rd(e,n,t);if(!r)continue;let i=id(r);if(i)return i}return await pd(e,t)}async function rd(e,t,n){try{let r=await Ae(`unzip`,[`-p`,e,t],{allowFailure:!0,binaryStdout:!0,signal:n});return r.exitCode!==0||!r.stdoutBuffer||r.stdoutBuffer.length===0?void 0:r.stdoutBuffer}catch{n?.throwIfAborted();return}}function id(e){return e.subarray(0,Math.min(e.length,128)).toString(`utf8`).trimStart().startsWith(`<`)?ad(e.toString(`utf8`)):od(e)}function ad(e){return e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i)?.[1]}function od(e){if(e.length<8||e.readUInt16LE(0)!==3)return;let t;for(let n=e.readUInt16LE(2);n+8<=e.length;){let r=e.readUInt16LE(n),i=e.readUInt16LE(n+2),a=e.readUInt32LE(n+4);if(a<=0||n+a>e.length)return;if(r===1)t=cd(e.subarray(n,n+a));else if(r===258&&t){let r=sd(e,n,i,t);if(r)return r}n+=a}}function sd(e,t,n,r){if(n<36||t+n>e.length||r[e.readUInt32LE(t+20)]!==`manifest`)return;let i=e.readUInt16LE(t+24),a=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let n=s+t*a;if(n+20>e.length)return;if(r[e.readUInt32LE(n+4)]!==`package`)continue;let i=e.readUInt32LE(n+8);if(i!==4294967295)return r[i];let o=e.readUInt8(n+15),c=e.readUInt32LE(n+16);return o===3?r[c]:void 0}}function cd(e){if(e.length<28)return[];let t=e.readUInt32LE(8),n=e.readUInt32LE(16),r=e.readUInt32LE(20),i=!!(n&256),a=[];for(let n=0;n<t;n+=1){let t=28+n*4;if(t+4>e.length)return a;let o=r+e.readUInt32LE(t);a.push(i?ld(e,o):ud(e,o))}return a}function ld(e,t){let[,n]=dd(e,t),[r,i]=dd(e,t+n),a=t+n+i;return e.subarray(a,a+r).toString(`utf8`)}function ud(e,t){let[n,r]=fd(e,t),i=t+r;return ed.decode(e.subarray(i,i+n*2))}function dd(e,t){let n=e.readUInt8(t);if(!(n&128))return[n,1];let r=e.readUInt8(t+1);return[(n&127)<<8|r,2]}function fd(e,t){let n=e.readUInt16LE(t);if(!(n&32768))return[n,2];let r=e.readUInt16LE(t+2);return[(n&32767)<<16|r,4]}async function pd(e,t){t?.throwIfAborted();let n=await md();if(!n)return;let r=await Ae(n,[`dump`,`badging`,e],{allowFailure:!0,signal:t});if(r.exitCode===0)return r.stdout.match(/package:\s+name='([^']+)'/)?.[1]}async function md(){if(td!==void 0)return td??void 0;try{let e=x().files;for(let t of Ct()){let n=E.join(t,`build-tools`);try{let t=(await e.readDirectory(n)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}));for(let r of t){let t=E.join(n,r,`aapt`);if(E.isAbsolute(t)&&await e.isExecutable(t))return td=t,t}}catch{}}}catch{}td=null}async function hd(e,t){let n=e.kind===`url`&&Le(e.url),r=await Re({source:e,isInstallablePath:(e,t)=>t.isFile()&&gd(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await _d(r.installablePath,t?.signal);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function gd(e){let t=E.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function _d(e,t){let n=E.extname(e).toLowerCase();return n!==`.apk`&&n!==`.aab`?{}:{packageName:await nd(e,t)}}async function vd(e,n,r,i={}){let a=typeof r.action==`string`&&r.action.trim()?r.action.trim():`${n}.TEST_PUSH`,o=[`am`,`broadcast`,`-a`,a,`-p`,n],s=typeof r.receiver==`string`?r.receiver.trim():``;s&&o.push(`-n`,s);let c=r.extras;if(c!==void 0&&(typeof c!=`object`||!c||Array.isArray(c)))throw new t(`INVALID_ARGS`,`Android push payload extras must be an object`);let l=c??{},u=0;for(let[e,t]of Object.entries(l))e&&(yd(o,e,t),u+=1);return await T(e,o,{signal:i.signal}),{action:a,extrasCount:u}}function yd(e,n,r){if(typeof r==`string`){e.push(`--es`,n,r);return}if(typeof r==`boolean`){e.push(`--ez`,n,r?`true`:`false`);return}if(typeof r==`number`&&Number.isFinite(r)){if(Number.isInteger(r)){e.push(`--ei`,n,String(r));return}e.push(`--ef`,n,String(r));return}throw new t(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}function Z(e){let t=e.replaceAll(`,`,``).match(/^-?\d+(?:\.\d+)?/);if(!t)return null;let n=Number(t[0]);return Number.isFinite(n)?n:null}function bd(e){let t=Td(e.map(e=>e.intendedVsyncNs)),n=[];for(let e=1;e<t.length;e+=1){let r=t[e]-t[e-1];r>=4e6&&r<=5e7&&n.push(r)}if(n.length!==0)return Ed(n)}function xd(e){let{frames:t,frameDeadlineNs:n,summaryDroppedFrameCount:r}=e;return r===void 0?n===void 0?[]:t.filter(e=>e.durationNs>n):r<=0?[]:[...t].sort((e,t)=>t.durationNs-e.durationNs).slice(0,r).sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}function Sd(e){let{frames:t,windowStartNs:n,measuredAtMs:r,uptimeMs:i}=e;if(t.length===0||n===void 0)return[];let a=[],o=[];for(let e of t){let t=o.at(-1);if(!t||e.intendedVsyncNs-t.frameCompletedNs<=5e8){o.push(e);continue}a.push(o),o=[e]}return o.length>0&&a.push(o),a.map(e=>wd({frames:e,windowStartNs:n,measuredAtMs:r,uptimeMs:i})).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}function Cd(e){return Math.round(e*10)/10}function wd(e){let{frames:t,windowStartNs:n,measuredAtMs:r,uptimeMs:i}=e,a=Math.min(...t.map(e=>e.intendedVsyncNs)),o=Math.max(...t.map(e=>e.frameCompletedNs)),s=Math.max(0,Math.round((a-n)/1e6)),c=Math.max(s,Math.round((o-n)/1e6)),l=i!==void 0&&Number.isFinite(r)?r-i:void 0;return{startOffsetMs:s,endOffsetMs:c,startAt:l===void 0?void 0:new Date(l+a/1e6).toISOString(),endAt:l===void 0?void 0:new Date(l+o/1e6).toISOString(),missedDeadlineFrameCount:t.length,worstFrameMs:Cd(Math.max(...t.map(e=>e.durationNs))/1e6)}}function Td(e){return[...new Set(e.filter(e=>Number.isFinite(e)))].sort((e,t)=>e-t)}function Ed(e){let t=[...e].sort((e,t)=>e-t),n=Math.floor(t.length/2);return t.length%2==1?t[n]:(t[n-1]+t[n])/2}function Dd(e,t,n){Od(e,t);let r=Rd(e),i=Pd(e),a=Ad(i,r,t),o=Date.parse(n),s=Bd({frames:i,measuredAtMs:o,summary:r}),c=xd({frames:i,frameDeadlineNs:a,summaryDroppedFrameCount:r?.droppedFrameCount}),l=r?.sampleWindowMs??s.sampleWindowMs??Wd(i),u=jd(r,i,c),d=Nd({droppedFrames:c,timing:s,measuredAtMs:o,summary:r});return{...u,sampleWindowMs:l,...Md(a),windowStartedAt:s.windowStartedAt,windowEndedAt:s.windowEndedAt,timestampSource:s.timestampSource,measuredAt:n,method:`adb-shell-dumpsys-gfxinfo-framestats`,source:r?`android-gfxinfo-summary`:`framestats-rows`,worstWindows:d&&d.length>0?d:void 0}}function Od(e,n){if(/no process found for:/i.test(e))throw new t(`COMMAND_FAILED`,`Android gfxinfo did not find a running process for ${n}`,{metric:`fps`,package:n,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf after the interaction you want to inspect.`})}function kd(e){throw new t(`COMMAND_FAILED`,`Failed to parse Android framestats output for ${e}`,{metric:`fps`,package:e,hint:`Retry perf after exercising the app screen. If the problem persists, capture adb shell dumpsys gfxinfo <package> framestats output for debugging.`})}function Ad(e,n,r){let i=bd(e);if(!n&&e.length===0&&kd(r),n||i!==void 0)return i;throw new t(`COMMAND_FAILED`,`Failed to infer Android frame deadline from framestats output for ${r}`,{metric:`fps`,package:r,hint:`Retry perf after a longer interaction window so consecutive Android frame timestamps are available.`})}function jd(e,t,n){let r=e?.totalFrameCount??t.length,i=e?.droppedFrameCount??n.length;return{totalFrameCount:r,droppedFrameCount:i,droppedFramePercent:e?.droppedFramePercent??(r>0?Kt(i/r*100):0)}}function Md(e){return{frameDeadlineMs:e===void 0?void 0:Cd(e/1e6),refreshRateHz:e===void 0?void 0:Cd(1e9/e)}}function Nd(e){let{droppedFrames:t,timing:n,measuredAtMs:r,summary:i}=e;if(t.length===0)return;let a=Sd({frames:t,windowStartNs:n.windowStartNs,measuredAtMs:r,uptimeMs:i?.uptimeMs});return a.length>0?a:void 0}function Pd(e){let t=[],n=null;for(let r of e.split(`
|
|
13
|
+
`)){let e=r.trim();if(e.length===0||e===`---PROFILEDATA---`)continue;let i=e.split(`,`).map(e=>e.trim());if(Fd(i)){n=new Map(i.map((e,t)=>[e,t]));continue}let a=Id(i,n);a&&t.push(a)}return t.sort((e,t)=>e.intendedVsyncNs-t.intendedVsyncNs)}function Fd(e){return e.includes(`IntendedVsync`)&&e.includes(`FrameCompleted`)}function Id(e,t){if(!t||e.length<t.size)return;let n=Ld(e,t,`Flags`),r=Ld(e,t,`IntendedVsync`),i=Ld(e,t,`FrameCompleted`);if(!(n!==0||r===null||i===null||r<=0||i<=r))return{intendedVsyncNs:r,frameCompletedNs:i,durationNs:i-r}}function Ld(e,t,n){let r=t.get(n);if(r===void 0)return null;let i=Number(e[r]);return Number.isFinite(i)?i:null}function Rd(e){let t=e.split(/\nProfile data in ms:\n/i)[0]??``,n=Gd(t,`Total frames rendered`),r=t.match(/^\s*Janky frames:\s*([0-9][0-9,]*)\s*\(([0-9.]+)%\)/im);if(n===void 0||!r)return;let i=r[1],a=r[2];if(i===void 0||a===void 0)return;let o=Z(i)??void 0,s=Number(a);if(o===void 0||!Number.isFinite(s)||n<0)return;let c=Gd(t,`Uptime`),l=Gd(t,`Stats since`);return{droppedFramePercent:Kt(s),droppedFrameCount:o,totalFrameCount:n,sampleWindowMs:zd({uptimeMs:c,statsSinceNs:l}),uptimeMs:c,statsSinceNs:l}}function zd(e){let{uptimeMs:t,statsSinceNs:n}=e;if(t===void 0||n===void 0)return;let r=t-Math.round(n/1e6);return r>=0?r:void 0}function Bd(e){let{frames:t,measuredAtMs:n,summary:r}=e,i=Vd(t),a=r?.statsSinceNs,o=a??i.firstFrameNs,s=Hd(o,i.lastFrameNs),c=r?.sampleWindowMs??s;if(!Number.isFinite(n)||r?.uptimeMs===void 0||o===void 0)return{sampleWindowMs:c,windowStartNs:o};let l=n-r.uptimeMs;return{sampleWindowMs:c,windowStartNs:o,windowStartedAt:new Date(l+o/1e6).toISOString(),windowEndedAt:Ud({deviceBootWallClockMs:l,measuredAtMs:n,summaryStartNs:a,lastFrameNs:i.lastFrameNs}),timestampSource:`estimated-from-device-uptime`}}function Vd(e){return e.length===0?{}:{firstFrameNs:Math.min(...e.map(e=>e.intendedVsyncNs)),lastFrameNs:Math.max(...e.map(e=>e.frameCompletedNs))}}function Hd(e,t){if(e!==void 0&&t!==void 0)return Math.max(0,Math.round((t-e)/1e6))}function Ud(e){let{deviceBootWallClockMs:t,measuredAtMs:n,summaryStartNs:r,lastFrameNs:i}=e;return r===void 0?i===void 0?void 0:new Date(t+i/1e6).toISOString():new Date(n).toISOString()}function Wd(e){if(e.length===0)return;let t=Vd(e);return Hd(t.firstFrameNs,t.lastFrameNs)}function Gd(e,t){let n=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),r=e.match(RegExp(`^\\s*${n}:\\s*([0-9][0-9,]*)`,`im`));if(!r)return;let i=r[1];return i===void 0?void 0:Z(i)??void 0}async function Kd(e,t,n={}){let r=y(e,n.adb);try{let i=Dd((await b(r,[`dumpsys`,`gfxinfo`,t,`framestats`],{timeoutMs:15e3})).stdout,t,new Date().toISOString());return await qd(e,t,n),i}catch(e){throw Jd(t,e)}}async function qd(e,t,n={}){let r=y(e,n.adb);try{await b(r,[`dumpsys`,`gfxinfo`,t,`reset`],{allowFailure:!0,timeoutMs:3e3})}catch{}}function Jd(e,n){return n instanceof t?new t(n.code,n.message,{...n.details??{},metric:`fps`,package:e},n):new t(`COMMAND_FAILED`,`Failed to sample Android fps for ${e}`,{metric:`fps`,package:e},n)}async function Yd(e,t,n,r,i){return{capture:{durationMs:r,packageName:t.packageName,appPid:t.appPid,artifactPath:t.outPath,sizeBytes:n},frameHealth:t.kind===`perfetto`?await Xd(e,t.packageName,i):void 0,notes:[t.kind===`perfetto`?`Frame health is sampled from Android gfxinfo around the trace window; open the Perfetto artifact for timeline root cause.`:`Open the Simpleperf report artifact for symbol-level CPU attribution.`]}}async function Xd(e,t,n){try{let r=await Kd(e,t,n);return{available:!0,droppedFramePercent:r.droppedFramePercent,droppedFrameCount:r.droppedFrameCount,totalFrameCount:r.totalFrameCount,method:r.method,worstWindows:r.worstWindows?.slice(0,3).map(e=>({startOffsetMs:e.startOffsetMs,endOffsetMs:e.endOffsetMs,missedDeadlineFrameCount:e.missedDeadlineFrameCount,worstFrameMs:e.worstFrameMs}))}}catch(e){return{available:!1,reason:e instanceof Error?e.message:`Android frame health was not available`}}}async function Zd(e,t,n){let r=y(e,n.adb);await rf(r,t),await sf(r,t),await of(r,t,n.files);let i=await nf(t.outPath,n.files);await ef(r,t.remotePath);let a=Date.now(),o=Math.max(0,a-t.startedAt),s=await Yd(e,t,i,o,{adb:r});return{...t,action:`stop`,platform:`android`,state:`stopped`,stoppedAt:a,durationMs:o,sizeBytes:i,method:t.kind===`simpleperf`?Kr:qr,artifact:{path:t.outPath,sizeBytes:i},summary:s,message:`Stopped Android ${t.kind} ${t.type} for ${t.packageName}`}}async function Qd(e,t,n={}){let r=y(e,n.adb);try{t.state===`running`&&(await rf(r,t),await sf(r,t).catch(()=>{}))}finally{await ef(r,t.remotePath)}}function $d(e,t,n=Yr){return`${n}/agent-device-${e.replaceAll(/[^A-Za-z0-9_.-]/g,`_`)}-${Date.now()}-${t}`}async function ef(e,t){try{await b(e,[`rm`,`-f`,t],{allowFailure:!0,timeoutMs:Jr})}catch{}}async function tf(e,t,n=x().files){await n.ensureDirectory(E.dirname(e)),await n.writeBytes(e,Buffer.from(`${JSON.stringify(t,null,2)}\n`))}async function nf(e,n=x().files){try{return(await n.stat(e)).size}catch(n){throw new t(`COMMAND_FAILED`,`Profiler artifact was not written: ${e}`,{outPath:e,hint:`Retry the profiling command and check daemon logs if the artifact path is still missing.`},n)}}async function rf(e,t){try{await b(e,[_(af(t.profilerPid))],{timeoutMs:N})}catch(e){throw M(`stop`,t.kind,t.packageName,e)}}function af(e){return[`pid=${v(e)}`,`kill -INT "$pid" 2>/dev/null || true`,`for i in 1 2 3 4 5 6 7 8 9 10; do kill -0 "$pid" 2>/dev/null || exit 0; sleep 0.2; done`,`kill -TERM "$pid" 2>/dev/null || true`,`for i in 1 2 3 4 5 6 7 8 9 10; do kill -0 "$pid" 2>/dev/null || exit 0; sleep 0.2; done`,`echo "profiler process did not stop after SIGTERM" >&2`,`exit 1`].join(`; `)}async function of(e,n,r){await(r??x().files).ensureDirectory(E.dirname(n.outPath));try{await e([`pull`,n.remotePath,n.outPath],{timeoutMs:N})}catch(e){throw new t(`COMMAND_FAILED`,`Failed to pull Android ${n.kind} artifact for ${n.packageName}`,{package:n.packageName,tool:n.kind,remotePath:n.remotePath,outPath:n.outPath,hint:`Check that the profiling command ran long enough to create an artifact, then retry stop with the same session.`},e)}}async function sf(e,n){let r;for(let t=0;t<12;t+=1){let t=await cf(e,n.remotePath);if(t!==void 0&&t>0&&t===r)return;r=t,await g(250)}throw new t(`COMMAND_FAILED`,`Android ${n.kind} artifact is not ready to pull`,{package:n.packageName,tool:n.kind,remotePath:n.remotePath,hint:`The profiler stopped, but the remote artifact was missing, empty, or still changing. Retry stop with the same session or inspect the device-side artifact.`})}async function cf(e,t){let n=v(t),r=await b(e,[_(`if [ -f ${n} ]; then stat -c %s ${n} 2>/dev/null || wc -c < ${n}; fi`)],{allowFailure:!0,timeoutMs:Jr});if(r.exitCode!==0)return;let i=Number(r.stdout.trim().split(/\s+/)[0]);return Number.isFinite(i)?i:void 0}async function lf(e,t,n,r={}){let i=y(e,r.adb),a=await Xr(i,t);await Zr(i,`perfetto`,t);let o=$d(t,`app.perfetto-trace`,`/data/misc/perfetto-traces`),s;try{await qd(e,t,{adb:i}),s=await df(i,o,t)}catch(e){throw await ef(i,o),e}return{type:`trace`,kind:`perfetto`,packageName:t,appPid:a,profilerPid:s,remotePath:o,outPath:n,startedAt:Date.now(),state:`running`,action:`start`,platform:`android`,method:qr,message:`Started Android Perfetto trace for ${t}`}}async function uf(e,t,n,r={}){return await Zd(e,{...t,outPath:n},r)}async function df(e,n,r){try{let i=Qr((await b(e,[`perfetto`,`--background-wait`,`-o`,n,`-t`,`3600s`,`sched`,`freq`,`idle`,`am`,`wm`,`gfx`,`view`,`binder_driver`,`hal`,`dalvik`],{timeoutMs:N})).stdout);if(i)return i;throw new t(`COMMAND_FAILED`,`Android perfetto did not return a profiler pid`,{package:r,tool:`perfetto`,hint:`Retry perf trace start. If perfetto exits immediately, verify the device permits trace capture.`})}catch(e){throw M(`start`,`perfetto`,r,e)}}function ff(e){let t=[];for(let n of u(e)){let e=n.match(/^([0-9]+(?:\.[0-9]+)?)%\s+(.+)$/);if(!e)continue;let r=Number(e[1]),i=e[2]?.trim();if(!Number.isFinite(r)||!i)continue;let a=i.split(/\s{2,}/).filter(Boolean);if(t.push({percentage:Kt(r),command:a[0],dso:a[1],symbol:a.slice(2).join(` `)||void 0}),t.length>=50)break}return t}async function pf(e,t,n,r={}){let i=y(e,r.adb),a=await Xr(i,t);await Zr(i,`simpleperf`,t);let o=$d(t,`cpu.perf.data`),s;try{s=await gf(i,a,o,t)}catch(e){throw await ef(i,o),e}return{type:`cpu-profile`,kind:`simpleperf`,packageName:t,appPid:a,profilerPid:s,remotePath:o,outPath:n,startedAt:Date.now(),state:`running`,action:`start`,platform:`android`,method:Kr,message:`Started Android Simpleperf CPU profile for ${t}`}}async function mf(e,t,n,r={}){return await Zd(e,{...t,outPath:n},r)}async function hf(e,t,n,r={}){let i=y(e,r.adb);await Zr(i,`simpleperf`,t.packageName);let a=await yf(i,t),o=new Date().toISOString(),s=ff(a.stdout),c=s.slice(0,10).map(e=>({symbol:e.symbol??`<unknown>`,binary:e.dso,selfSamplePercent:e.percentage}));await tf(n,{kind:`simpleperf-report`,generatedAt:o,packageName:t.packageName,appPid:t.appPid,sourceProfilePath:t.outPath,sourceRemotePath:t.remotePath,entryCount:s.length,summary:{topFunctions:c},entries:s},r.files);let l=await nf(n,r.files);return{action:`report`,platform:`android`,type:`cpu-profile-report`,kind:`simpleperf`,packageName:t.packageName,appPid:t.appPid,sourceProfilePath:t.outPath,outPath:n,sizeBytes:l,generatedAt:o,entryCount:s.length,summary:{topFunctions:c},method:Kr,message:`Wrote Android Simpleperf report for ${t.packageName}`}}async function gf(e,n,r,i){try{let a=Qr((await b(e,[_(_f(n,r))],{timeoutMs:N})).stdout);if(a)return a;throw new t(`COMMAND_FAILED`,`Android simpleperf did not return a profiler pid`,{package:i,tool:`simpleperf`,hint:`Retry perf. If simpleperf exits immediately, verify the app is profileable and the device permits native profiling.`})}catch(e){throw M(`start`,`simpleperf`,i,e)}}function _f(e,t){return vf([`simpleperf`,`record`,`-e`,`cpu-clock:u`,`-p`,e,`-o`,t,`--duration`,`3600`],`simpleperf`)}function vf(e,t){let n=e.map(v).join(` `),r=`${Yr}/agent-device-${t}-${Date.now()}.err`;return[`err=${v(r)}`,`(${n}) >/dev/null 2>"$err" & pid=$!`,`sleep 1`,`if kill -0 "$pid" 2>/dev/null; then rm -f "$err"; echo "$pid"; exit 0; fi`,`cat "$err" >&2`,`rm -f "$err"`,`exit 1`].join(`; `)}async function yf(e,t){try{return await b(e,[`simpleperf`,`report`,`-i`,t.remotePath,`--stdio`,`--sort`,`comm,dso,symbol`],{timeoutMs:N})}catch(e){throw M(`report`,`simpleperf`,t.packageName,e)}}const bf=15e3,xf=12e4;async function Sf(e,t,n={}){let r=y(e,n.adb);try{return Ef((await b(r,[`dumpsys`,`meminfo`,t],{timeoutMs:bf})).stdout,t,new Date().toISOString())}catch(e){throw Pf(`memory`,t,e)}}async function Cf(e,n,r,i={}){let a=y(e,i.adb),o=i.files??x().files,s=await Df(a,n),c=Of(n);await o.ensureDirectory(E.dirname(r));let l=await wf(o,r);try{je(await b(a,[`am`,`dumpheap`,n,c],{allowFailure:!0,timeoutMs:xf}),`Failed to capture Android heap dump for ${n}`,e=>({kind:`android-hprof`,package:n,pid:s,remotePath:c,hint:kf(e.stdout,e.stderr)}));let e=await a([`pull`,c,r],{allowFailure:!0,timeoutMs:xf});if(e.exitCode!==0)throw await Tf(o,r,l),w(`Failed to pull Android heap dump for ${n}`,e,{kind:`android-hprof`,package:n,pid:s,remotePath:c,path:r,hint:`Verify the daemon can write the requested --out path and retry. The heap dump stays on-device only until cleanup runs.`});let i=await o.stat(r).catch(()=>null);if(!i?.isFile||i.size<=0)throw await Tf(o,r,l),new t(`COMMAND_FAILED`,`Android heap dump artifact is missing or empty`,{kind:`android-hprof`,package:n,pid:s,path:r,remotePath:c,hint:`Retry with a writable --out path. If the file is still empty, inspect adb pull output with --debug.`});return{available:!0,kind:`android-hprof`,path:r,sizeBytes:i.size,measuredAt:new Date().toISOString(),method:`adb-shell-am-dumpheap`,packageName:n,pid:s,remotePath:c}}finally{await b(a,[`rm`,`-f`,c],{allowFailure:!0,timeoutMs:bf}).catch(()=>{})}}async function wf(e,t){return await e.stat(t).then(e=>e.isFile).catch(()=>!1)}async function Tf(e,t,n){n||await e.remove(t,{force:!0}).catch(()=>{})}function Ef(e,n,r){if(/no process found for:/i.test(e))throw new t(`COMMAND_FAILED`,`Android meminfo did not find a running process for ${n}`,{metric:`memory`,package:n,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf.`});let i=Ff(e,`TOTAL PSS`)??If(e);if(i===void 0)throw new t(`COMMAND_FAILED`,`Failed to parse Android meminfo output for ${n}`,{metric:`memory`,package:n,hint:`Retry perf after reopening the app session. If the problem persists, capture adb shell dumpsys meminfo output for debugging.`});return{totalPssKb:i,totalRssKb:Ff(e,`TOTAL RSS`),measuredAt:r,method:`adb-shell-dumpsys-meminfo`,topConsumers:Af(e)}}async function Df(e,n){let r=await b(e,[`pidof`,n],{allowFailure:!0,timeoutMs:bf}),i=r.stdout.trim().split(/\s+/).map(Number).find(e=>Number.isInteger(e)&&e>0);if(r.exitCode===0&&i!==void 0)return i;throw new t(`COMMAND_FAILED`,`No running Android process found for ${n}`,{kind:`android-hprof`,package:n,stdout:r.stdout,stderr:r.stderr,hint:`Run open <app> for this session again to ensure the Android app is active, then retry perf memory snapshot.`})}function Of(e){return`/data/local/tmp/agent-device-${e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)}-${Date.now()}.hprof`}function kf(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`profileable`)||n.includes(`debuggable`)||n.includes(`not allowed`)?`Android heap dumps require a debuggable/profileable app process on many devices. Use a debug/profileable build, reopen the app, then retry.`:n.includes(`permission`)||n.includes(`denied`)?`The device denied heap dump access. Use a debug/profileable build or a device image that permits app heap dumping.`:`Reopen the app to refresh the process, then retry perf memory snapshot. If it still fails, run with --debug and inspect adb am dumpheap output.`}function Af(e){let t=e.split(`
|
|
14
|
+
`).flatMap(e=>jf(e)??[]).sort((e,t)=>t.pssKb-e.pssKb).slice(0,5);return t.length>0?t:void 0}function jf(e){let t=e.trim();if(Mf(t))return;let n=t.match(/^(.+?)\s+([0-9][0-9,]*(?:\(\d+\))?)(?:\s|$)/);if(n)return Nf(n[1],n[2])}function Mf(e){if(!e||e.startsWith(`**`)||e.startsWith(`-`)||e.includes(`:`))return!0;let t=/^\S.+\s+\d/.test(e);return/^(pss|total|native|dalvik|unknown|app summary\b)/i.test(e)&&!t}function Nf(e,t){let n=e?.trim(),r=t?Z(t):null;if(!(!n||n===`TOTAL`||r===null||r<=0)&&!/^(pss|private|shared|heap|size|alloc|free)$/i.test(n))return{name:n,pssKb:r}}function Pf(e,n,r){return r instanceof t?new t(r.code,r.message,{...r.details??{},metric:e,package:n},r):new t(`COMMAND_FAILED`,`Failed to sample Android ${e} for ${n}`,{metric:e,package:n},r)}function Ff(e,t){let n=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),r=e.match(RegExp(`${n}:\\s*([0-9][0-9,]*)`,`i`));if(!r)return;let i=r[1];return i===void 0?void 0:Z(i)??void 0}function If(e){for(let t of e.split(`
|
|
15
|
+
`)){let e=t.trim();if(!/^TOTAL\b(?!\s+PSS:)/.test(e))continue;let n=e.split(/\s+/).slice(1).find(e=>Z(e)!==null);return n?Z(n)??void 0:void 0}}async function Lf(e,t,n){let r=await T(e,[`dumpsys`,`package`,t],{allowFailure:!0});return r.exitCode===0?qf(r.stdout,n):{requested:void 0,grants:void 0}}async function Rf(e){let t=await T(e,[`am`,`get-current-user`],{allowFailure:!0});if(t.exitCode!==0)return;let n=Number.parseInt(t.stdout.trim(),10);return Number.isInteger(n)&&n>=0?n:void 0}const zf=/^\s*User (\d+):/,Bf=/^\s*runtime permissions:\s*$/,Vf=/^\s*([\w.]+): granted=(true|false)\b/,Hf=/^\s*Package \[.+?\]/,Uf=/^\s*requested permissions:\s*$/,Wf=/^\s*([A-Za-z][\w.]*)/;function Gf(e){return e.split(`
|
|
16
|
+
`).filter(e=>e.trim().length>0).map(e=>({text:e,indent:e.length-e.trimStart().length}))}function Kf(e,t){let n=Q(Q(Q(Gf(e),e=>e.indent===0&&e.text.trim()===`Packages:`),e=>zf.exec(e.text)?.[1]===String(t)),e=>Bf.test(e.text));if(!n)return;let r=new Map;for(let{text:e}of n){let t=Vf.exec(e);t&&r.set(t[1],t[2]===`true`?`granted`:`not_granted`)}return r}function Q(e,t){if(!e)return;let n=e.findIndex(e=>t(e));if(n<0)return;let r=e.slice(n+1),i=r.findIndex(t=>t.indent<=e[n].indent);return i<0?r:r.slice(0,i)}function qf(e,t){return{requested:Jf(e),grants:Kf(e,t)}}function Jf(e){let t=Q(Q(Q(Gf(e),e=>e.indent===0&&e.text.trim()===`Packages:`),e=>Hf.test(e.text)),e=>Uf.test(e.text));if(!t)return;let n=[];for(let{text:e}of t){let t=Wf.exec(e)?.[1];t&&t.includes(`.`)&&!n.includes(t)&&n.push(t)}return n}function Yf(e,t,n){if(n!==`not_granted`)return`${n===`granted`?`${t} was granted before this revoke, and Android kills an app when a granted permission is revoked: if ${e} was running it is no longer.`:`Whether ${t} was granted before this revoke could not be read (adb did not report the acting user's runtime permission state), and Android kills an app when a granted permission is revoked: ${e} may no longer be running.`} Relaunch it with open ${e} --relaunch before the next interaction.`}const Xf=[`all`,`camera`,`microphone`,`photos`,`contacts`,`notifications`,`calendar`,`location`,`media-library`],Zf={calendar:[`android.permission.WRITE_CALENDAR`,`android.permission.READ_CALENDAR`],camera:[`android.permission.CAMERA`],contacts:[`android.permission.READ_CONTACTS`,`android.permission.WRITE_CONTACTS`],location:[`android.permission.ACCESS_FINE_LOCATION`,`android.permission.ACCESS_COARSE_LOCATION`],"media-library":[`android.permission.WRITE_EXTERNAL_STORAGE`,`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_AUDIO`,`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_MEDIA_VIDEO`],microphone:[`android.permission.RECORD_AUDIO`]};async function Qf(e){let n=await Rf(e);if(n!==void 0)return n;throw new t(`COMMAND_FAILED`,`Could not determine which Android user the session runs as, so no permission was changed.`,{deviceId:e.id,hint:`Check adb -s ${e.id} shell am get-current-user — if the device is still booting, retry once it reports a user. agent-device refuses to change permissions it cannot scope, because pm would silently apply them to user 0.`})}async function $f(e,t,n,r){let i=xe(n),a=bp(r?.permissionTarget,r?.permissionMode),o=await Qf(e),s=[`--user`,String(o)];if(a.kind===`all`)return await np(e,t,i,o,s);if(i===`grant`){let n=await vp(e,t,a,o,s);return tp(ep(a),n)}if(a.kind===`pm`)return await Cp(e,t,i,a,o,s);let{grants:c}=await Lf(e,t,o),l=await yp(e,t,i,a,s),{priorGrantState:u,warnings:d}=Tp(t,l,l.map(e=>c?.get(e)??`unknown`));return tp(a.kind,l,{priorGrantState:u,warnings:d})}function ep(e){return e.kind===`pm`?e.name:e.kind}function tp(e,t,n){return{permission:e,permissions:[...t],...n?{priorGrantState:n.priorGrantState,...n.warnings.length>0?{warnings:n.warnings}:{}}:{}}}async function np(e,n,r,i,a){let{requested:o,grants:s}=await Lf(e,n,i);if(o===void 0)throw new t(`COMMAND_FAILED`,`Could not read declared permissions for ${n}, so no permission was changed.`,{appPackage:n});let c=r===`grant`?void 0:s,l=[],u=[];for(let t of lp(o))await rp({device:e,appPackage:n,action:r,userArgs:a,grants:c,applied:l,warnings:u},t);return{permission:`all`,permissions:l,...u.length>0?{warnings:u}:{}}}async function rp(e,t){return t.kind===`notification`?await ip(e):t.kind===`photos`?await ap(e):await op(e,t.value)}async function ip(e){let{device:t,appPackage:n,action:r,userArgs:i}=e;await Dp(t,n,r,{appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`},i),sp(e,`android.permission.POST_NOTIFICATIONS`)}async function ap(e){let{device:t,appPackage:n,action:r,userArgs:i,warnings:a}=e,o=await mp(t,n,r===`grant`?`grant`:`revoke`,i);if(o===void 0){a.push(`Skipped Android photos permission for ${n}: device refused both media candidates.`);return}await cp(e,o)}async function op(e,t){let{device:n,appPackage:r,action:i,userArgs:a,warnings:o}=e,s=await pp(n,i===`grant`?`grant`:`revoke`,a,r,t);if(s.kind===`skipped`){o.push(`Skipped ${t} for ${r}: ${s.detail}`);return}await cp(e,t)}function sp(e,t){let{appPackage:n,action:r,grants:i,applied:a,warnings:o}=e;a.push(t),r!==`grant`&&up(o,i,n,t)}async function cp(e,t){sp(e,t),e.action===`reset`&&await Op(e.device,e.appPackage,t,e.userArgs)}function lp(e){let t=[],n=!1;for(let r of e)r===`android.permission.POST_NOTIFICATIONS`?t.push({kind:`notification`}):r===`android.permission.READ_MEDIA_IMAGES`||r===`android.permission.READ_EXTERNAL_STORAGE`?n||(n=!0,t.push({kind:`photos`})):t.push({kind:`pm`,value:r});return t}function up(e,t,n,r){let i=Yf(n,r,t?.get(r)??`unknown`);i&&e.push(i)}const dp=[[/not a changeable permission/,`not-changeable`],[/has not requested permission/,`not-requested`],[/is not a runtime permission/,`not-runtime-permission`],[/unknown permission/,`unknown-permission`],[/managed by role/,`role-managed`]];function fp(e){let t=e.toLowerCase();return dp.find(([e])=>e.test(t))?.[1]}async function pp(e,t,n,r,i){let a=await T(e,[`pm`,t,...n,r,i],{allowFailure:!0});if(a.exitCode===0)return{kind:`applied`};let o=fp(a.stderr);if(o)return{kind:`skipped`,reason:o,detail:_p(a.stderr)};throw w(`Failed to ${t} Android permission ${i} for ${r}`,a,{appPackage:r,permission:i})}async function mp(e,t,n,r){try{return await Ep(e,t,n,r)}catch(e){if(hp(e))return;throw e}}function hp(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details?.attempts;return gp(n)&&n.length>0&&n.every(e=>e.reason!==void 0)}function gp(e){return Array.isArray(e)&&e.every(e=>typeof e==`object`&&!!e&&typeof e.permission==`string`&&typeof e.detail==`string`)}function _p(e){let t=e.split(`
|
|
17
|
+
`).map(e=>e.trim()).filter(e=>e.length>0),n=t[0]??`unknown device error`;return(n.endsWith(`:`)&&t[1]?`${n} ${t[1]}`:n).slice(0,200)}async function vp(e,t,n,r,i){if(n.kind===`notifications`)return await Dp(e,t,`grant`,n,i),[n.permission];if(n.kind===`photos`)return[await Ep(e,t,`grant`,i)];if(n.kind===`pm`){let a=[...await xp(e,t,n.values,r)];for(let n of a)await T(e,[`pm`,`grant`,...i,t,n]);return a}throw n.kind===`all`?Error(`Unhandled Android permission target: all is resolved by the caller.`):Error(`Unhandled Android permission target: ${JSON.stringify(n)}`)}async function yp(e,t,n,r,i){if(r.kind===`notifications`)return await Dp(e,t,n,r,i),[r.permission];if(r.kind===`photos`){let r=await Ep(e,t,`revoke`,i);return n===`reset`&&await Op(e,t,r,i),[r]}throw r.kind===`pm`?Error(`Unhandled Android permission target: pm is resolved by the caller.`):r.kind===`all`?Error(`Unhandled Android permission target: all is resolved by the caller.`):Error(`Unhandled Android permission target: ${JSON.stringify(r)}`)}function bp(e,n){let r=Ce(e);if(n?.trim())throw new t(`INVALID_ARGS`,`Android does not support permission modes. Received: ${n}.`);if(r===`all`)return{kind:`all`};if(r===`photos`)return{kind:`photos`};if(r===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};let i=r in Zf?Zf[r]:void 0;if(i)return{kind:`pm`,name:r,values:i};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use ${Xf.join(`|`)}.`,{hint:`Android custom permission ids are attempted through all, not individually.`})}async function xp(e,t,n,r){let{requested:i}=await Lf(e,t,r);return Sp(i,n,t)}function Sp(e,n,r){if(e===void 0)return n;let i=n.filter(t=>e.includes(t));if(i.length===0)throw new t(`COMMAND_FAILED`,`Package ${r} has not requested permission ${n.join(`, `)}, so no permission was changed.`,{appPackage:r,permissions:n});return i}async function Cp(e,t,n,r,i,a){let{requested:o,grants:s}=await Lf(e,t,i),c=Sp(o,r.values,t);await wp(e,t,c,n,a);let{priorGrantState:l,warnings:u}=Tp(t,c,c.map(e=>s?.get(e)??`unknown`));return tp(r.name,c,{priorGrantState:l,warnings:u})}async function wp(e,t,n,r,i){for(let r of n)await T(e,[`pm`,`revoke`,...i,t,r]);if(r===`reset`)for(let r of n)await Op(e,t,r,i)}function Tp(e,t,n){return{priorGrantState:n.includes(`granted`)?`granted`:n.includes(`unknown`)?`unknown`:`not_granted`,warnings:t.flatMap((t,r)=>{let i=Yf(e,t,n[r]);return i?[i]:[]})}}async function Ep(e,n,r,i){let a=await kp(e),o=a!==null&&a>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],s=[];for(let t of o){let a=await T(e,[`pm`,r,...i,n,t],{allowFailure:!0});if(a.exitCode===0)return t;s.push({permission:t,reason:fp(a.stderr),detail:_p(a.stderr)})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:a,attempts:s})}async function Dp(e,t,n,r,i){let a=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await T(e,[`pm`,`grant`,...i,t,r.permission],{allowFailure:!0}):(await T(e,[`pm`,`revoke`,...i,t,r.permission],{allowFailure:!0}),n===`reset`&&await Op(e,t,r.permission,i)),await T(e,[`appops`,`set`,...i,t,r.appOps,a])}async function Op(e,t,n,r){for(let i of[`user-set`,`user-fixed`])await T(e,[`pm`,`clear-permission-flags`,...r,t,n,i],{allowFailure:!0})}async function kp(e){let t=await T(e,[`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const Ap=[`cmd`,`connectivity`,`airplane-mode`];async function jp(e,n){let r=n?`enabled`:`disabled`;await Mp(e),await T(e,[...Ap,n?`enable`:`disable`]);let i=await Np(e);if(i!==r)throw new t(`COMMAND_FAILED`,`Android airplane mode reads ${i} after requesting ${r}.`,{deviceId:e.id,requested:r,airplaneMode:i});return{airplaneMode:i}}async function Mp(e){let{state:n,result:r}=await Pp(e);if(!n)throw r.exitCode!==0&&ut(r.stdout,r.stderr)?new t(`UNSUPPORTED_OPERATION`,`The connectivity service on this Android build has no airplane-mode command, so nothing was changed.`,{deviceId:e.id,hint:`settings airplane needs cmd connectivity airplane-mode, which requires Android 11 (API 30) or newer. Use a newer device or emulator image.`,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}):w(`Failed to read Android airplane mode`,r,{deviceId:e.id})}async function Np(e){let{state:t,result:n}=await Pp(e);if(t)return t;throw w(`Failed to read Android airplane mode after changing it`,n,{deviceId:e.id})}async function Pp(e){let t=await T(e,[...Ap],{allowFailure:!0});return{state:t.exitCode===0?Fp(t.stdout):void 0,result:t}}function Fp(e){let t=e.trim().toLowerCase();if(t===`enabled`)return`enabled`;if(t===`disabled`)return`disabled`}const Ip=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`],Lp={"extra-small":`0.82`,small:`0.88`,medium:`0.94`,large:`1.0`,"extra-large":`1.12`,"extra-extra-large":`1.24`,"extra-extra-extra-large":`1.35`,"accessibility-medium":`1.5`,"accessibility-large":`1.75`,"accessibility-extra-large":`2.0`,"accessibility-extra-extra-large":`2.5`,"accessibility-extra-extra-extra-large":`3.2`},Rp=Lp.large;async function zp(e,n,r,i,a){switch(n.toLowerCase()){case`wifi`:{let t=ye(r);await T(e,[`svc`,`wifi`,t?`enable`:`disable`]);return}case`airplane`:return await jp(e,ye(r));case`location`:{if(r.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:r}=we(a);return await lt(e,[`emu`,`geo`,`fix`,String(r),String(n)]),{latitude:n,longitude:r}}let n=ye(r)?`3`:`0`;await T(e,[`settings`,`put`,`secure`,`location_mode`,n]);return}case`animations`:{let t=ye(r)?`1`:`0`;for(let n of Ip)await T(e,[`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...Ip]}}case`appearance`:{let t=await Yp(e,r);await T(e,[`cmd`,`uimode`,`night`,t===`dark`?`yes`:`no`]);return}case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await Ot(e,i);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await T(e,[`am`,`force-stop`,n.value],{allowFailure:!0});let a=await T(e,[`pm`,`clear`,n.value],{allowFailure:!0});if(a.exitCode!==0||!/\bSuccess\b/i.test(a.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await Kp(e,Gp(r));return;case`permission`:if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);return await $f(e,i,r,a);case`text-size`:return await Hp(e,r);default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}const Bp={"text-size":Up};async function Vp(e,t){return await Bp[t](e)}async function Hp(e,t){let n=Se(t),r=Lp[n];return await T(e,[`settings`,`put`,`system`,`font_scale`,r]),_e(n,r)}async function Up(e){let n=(await T(e,[`settings`,`get`,`system`,`font_scale`])).stdout.trim(),r=n===`null`?Rp:n,i=/^(\d+(\.\d+)?)$/.test(r)?Number(r):NaN;if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Android reported an unusable font scale: ${n||`(empty)`}`,{deviceId:e.id,fontScale:n,hint:"Run `adb shell settings get system font_scale` to see what the device holds."});return _e(Wp(i),r)}function Wp(e){let t=be[0],n=1/0;for(let r of be){let i=Math.abs(Number.parseFloat(Lp[r])-e);i>=n||(t=r,n=i)}return t}function Gp(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function Kp(e,n){let i=qp(e,n),a=[];for(let t of i){let n=await lt(e,t,{allowFailure:!0});if(n.exitCode===0)return;a.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let o=r(a);throw a.length>0&&a.every(e=>Jp(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:o})}function qp(e,t){let n=t===`match`?`1`:`9999`,r=[Pe(`adb`,`shell`,[`cmd`,`fingerprint`,`touch`,n]),Pe(`adb`,`shell`,[`cmd`,`fingerprint`,`finger`,n])];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function Jp(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function Yp(e,n){let r=ve(n);if(r!==`toggle`)return r;let i=await T(e,[`cmd`,`uimode`,`night`],{allowFailure:!0});if(i.exitCode!==0)throw w(`Failed to read current Android appearance`,i);let a=Xp(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`auto`?`dark`:a===`dark`?`light`:`dark`}function Xp(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}const Zp=Buffer.from([137,80,78,71,13,10,26,10]);async function Qp(e,t,n={}){if(n.stabilize===!1)return await tm(e,t);await $p(e);try{return await g(1e3),await tm(e,t)}finally{await em(e).catch(()=>{})}}async function $p(e){let t=t=>T(e,t,{allowFailure:!0});await t([`settings`,`put`,`global`,`sysui_demo_allowed`,`1`]);let n=e=>t([`am`,`broadcast`,`-a`,`com.android.systemui.demo`,`-e`,`command`,...e]);await n([`clock`,`-e`,`hhmm`,`0941`]),await n([`notifications`,`-e`,`visible`,`false`])}async function em(e){await T(e,[`am`,`broadcast`,`-a`,`com.android.systemui.demo`,`-e`,`command`,`exit`],{allowFailure:!0})}async function tm(e,t){let n=new AbortController,r=Va(e,{timeoutMs:2e3,signal:n.signal});try{await rm(e,t);let n=await nm(r,250);return n?{displayRotation:n}:{}}finally{n.abort()}}async function nm(e,t){let n;try{return await Promise.race([e,new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{clearTimeout(n)}}async function rm(e,n){let r=await ct(e,[`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(Zp);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=im(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await x().files.writeBytes(n,r.stdoutBuffer.subarray(i,a))}function im(e,t){let n=t+Zp.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}async function am(e,t,n=0){let r=qe(e);if(r){await r({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}let i=await um(e,`type`,t);if(i.backend===`test-ime`){await dm(e,i.packageName,t,n);return}if(n>0&&Array.from(t).length>1){await pm(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await pm(e,{action:`type`,text:t,chunkSize:8,delayMs:0})}async function om(e,t,n,r,i=0,a={}){let o=await yu(e,t,n,a),s=qe(e);if(s)return await s({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),$(`fill`,`provider-native`,r),bu(r,o,await gu(e,t,n,r,a));let c=null,u=0;try{for(let s of sm(i)){await Wa(e,t,n),u+=1;let i=await um(e,`fill`,r);if(i.backend===`test-ime`)return bu(r,o,await fm(e,i.packageName,t,n,r,o,a));let l=await cm(e,{x:t,y:n,text:r,beforeTarget:o,attempt:s},a);if(c=l,l.ok)return;if(l.reason===`ime_capture`)return bu(r,o,l);let d=xu(r,o,l);if(d)return d}}catch(e){throw l(e,u)}return bu(r,o,c)}function sm(e){return[{clearPadding:12,minClear:8,maxClear:48,chunkSize:e>0?1:8,inputDelayMs:e},{clearPadding:24,minClear:16,maxClear:96,chunkSize:e>0?1:4,inputDelayMs:e>0?e:15}]}async function cm(e,t,n){let{x:r,y:i,text:a,beforeTarget:o,attempt:s}=t;return await vm(e,lm(a,o,s)),await pm(e,{action:`fill`,text:a,chunkSize:s.chunkSize,delayMs:s.inputDelayMs}),gu(e,r,i,a,n)}function lm(e,t,n){let r=Array.from(e).length;return Dm(r>0?r+n.clearPadding:t?.text?Array.from(t.text).length+n.clearPadding:n.maxClear,n.minClear,n.maxClear)}async function um(e,t,n){if(us(e))return{backend:`test-ime`,packageName:(await Wo(C(e))).manifest.packageName};let r=await ym(e,t),i=r?.inputMethodPackage;return Xo(i)?{backend:`test-ime`,packageName:i}:(xm(n),bm(r,t),{backend:`adb-shell`})}async function dm(e,t,n,r){let i=y(e);await hm(e,mm(n,r>0?1:1/0,r),{delayMs:r,sendChunk:async e=>await Zo(i,t,e)}),$(`type`,`test-ime`,n)}async function fm(e,t,n,r,i,a,o){let s=y(e),c=null,u=0;try{for(let l=0;l<2;l+=1){l>0&&(await Wa(e,n,r),u+=1),await Qo(s,t),u+=1,i&&(await Zo(s,t,i),u+=1);let d=await gu(e,n,r,i,o);if(c=d,d.ok||xu(i,a,d))break}}catch(e){throw l(e,u)}return $(`fill`,`test-ime`,i),c}async function pm(e,t){await hm(e,mm(t.text,t.chunkSize,t.delayMs),{delayMs:t.delayMs,sendChunk:async t=>{try{await _m(e,t)}catch(e){throw rt(e)}}}),$(t.action,`adb-shell`,t.text)}function mm(e,t,n){let r=e.split(`
|
|
18
|
+
`);return r.flatMap((e,i)=>{let a=Em(e,t),o=i+1===r.length,s=a.map((e,t)=>({kind:`chunk`,text:e,pauseAfter:n>0&&!(o&&t+1===a.length)}));return o?s:[...s,{kind:`enter`}]})}async function hm(e,t,n){let r=0;try{for(let i of t){if(i.kind===`enter`){await gm(e),r+=1;continue}i.text&&(await n.sendChunk(i.text),r+=1),i.pauseAfter&&await g(n.delayMs)}}catch(e){throw l(e,r)}}async function gm(e){try{await T(e,[`input`,`keyevent`,`ENTER`])}catch(e){throw rt(e)}}async function _m(e,t){try{await T(e,[`input`,`text`,Cm(t)])}catch(e){throw wm(e)?Tm(t,e):e}}async function vm(e,t){let n=Math.max(0,t),r=0;try{await T(e,[`input`,`keyevent`,`KEYCODE_MOVE_END`],{allowFailure:!0}),r+=1;for(let t=0;t<n;t+=24){let i=Math.min(24,n-t);await T(e,[`input`,`keyevent`,...Array(i).fill(`KEYCODE_DEL`)],{allowFailure:!0}),r+=1}}catch(e){throw l(e,r)}}async function ym(e,t){try{return await Co(e)}catch(e){return h({level:`warn`,phase:`android_input_ownership_probe_failed`,data:{action:t,error:e instanceof Error?e.message:String(e)}}),null}}function bm(e,n){if(!(!e||e.inputOwner!==`ime`))throw new t(`COMMAND_FAILED`,`KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.`,{failureReason:`ime_capture`,action:n,inputOwner:e.inputOwner,inputType:e.inputType,type:e.type,inputMethodPackage:e.inputMethodPackage,focusedPackage:e.focusedPackage,focusedResourceId:e.focusedResourceId,nextAction:`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`})}function xm(e){if(!Sm(e))throw Tm(e)}function Sm(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&t!==`
|
|
19
|
+
`&&(e<32||e>126))return!1}return!0}function Cm(e){return e.replaceAll(` `,`%s`)}function wm(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details?.stderr,r=(typeof n==`string`?n:``).toLowerCase();return!!(r.includes(`exception occurred while executing 'text'`)||r.includes(`nullpointerexception`)&&r.includes(`inputshellcommand.sendtext`))}function Tm(e,n){return new t(`COMMAND_FAILED`,"Android text input requires provider-native text injection or the bundled test IME helper for non-ASCII/control characters; the adb-shell fallback supports ASCII text only. On emulators the test IME activates automatically; on real devices pass `open --test-ime` to enable it (see `agent-device doctor` for the current IME state).",{backend:`adb-shell`,textLength:Array.from(e).length,textPreview:e.slice(0,32)},n instanceof Error?n:void 0)}function Em(e,t){let n=Math.max(1,Math.floor(t)),r=[],i=Array.from(e);for(let e=0;e<i.length;e+=n)r.push(i.slice(e,e+n).join(``));return r.length>0?r:[``]}function $(e,t,n){h({phase:`android_text_injection`,data:{action:e,backend:t,textLength:Array.from(n).length}})}function Dm(e,t,n){return Math.max(t,Math.min(n,e))}var Om=e({ANDROID_FOCUSED_WINDOW_MARKER:()=>Pt,ANDROID_FOCUS_MARKERS:()=>Mt,ANDROID_IME_HELPER_SERVICE_COMPONENT:()=>`com.callstack.agentdevice.imehelper/.TestInputMethodService`,ANDROID_SNAPSHOT_PRESENTATION_DEFAULT_DEADLINE_MS:()=>250,ANDROID_TEST_IME_SETTINGS_KEYS:()=>rs,ANDROID_TOUCH_PLAN_PROTOCOL:()=>la,AndroidSnapshotPresentationFailure:()=>X,activateAndroidTestIme:()=>Wu,androidAdbForwardsDeviceExitStatus:()=>Xt,androidAdbHostTarget:()=>tt,androidAdbInvocation:()=>$e,androidAdbResultError:()=>w,androidAdbSerialTarget:()=>et,androidAppsDiscoveryHint:()=>kt,androidCaptureFailureReasonDetail:()=>Er,androidCaptureFailureReasonFromExitCode:()=>Tr,androidCaptureFailureReasonFromHelperResult:()=>wr,androidClipboardShellSupportForResult:()=>Am,androidDeviceChecks:()=>xs,androidFillFailureDetails:()=>Tu,androidFillFailureMessage:()=>wu,androidRevokedPermissionWarning:()=>Yf,androidSnapshotPublicationInput:()=>Ll,androidToolchainCheck:()=>bs,androidUiNodes:()=>Gc,annotateAndroidNativePerfError:()=>M,appSwitcherAndroid:()=>Ha,attachAdbFailureHint:()=>it,backAndroid:()=>Ma,buildAndroidFillUnconfirmedVerification:()=>xu,buildAndroidNativeToolUnavailableHint:()=>Vr,buildAndroidSnapshotClickabilityEvidence:()=>al,buildAndroidSnapshotHelperArgs:()=>bi,buildAndroidSnapshotHelperCaptureOptions:()=>vi,buildUiHierarchySnapshot:()=>Tc,captureAndroidHeapSnapshot:()=>Cf,captureAndroidLogcatWithAdb:()=>jm,captureAndroidSnapshotWithHelper:()=>_i,captureAndroidSnapshotWithHelperSession:()=>ia,classifyAdbFailure:()=>st,classifyAndroidAlertIdentifier:()=>ln,classifyAndroidAppTarget:()=>wt,classifyAndroidHelperContent:()=>sl,cleanupAndroidNativePerfSession:()=>Qd,clearAndroidImeHelperText:()=>Qo,clearAndroidTestImeRecoveryMarker:()=>Xu,closeAndroidApp:()=>yt,completeAndroidFillVerification:()=>bu,createAndroidPortReverseManager:()=>Ge,createAndroidSnapshotCapture:()=>Il,createAndroidSnapshotPresentationBudget:()=>bc,createAndroidSnapshotPresentationNode:()=>gc,createAndroidWindowDumpReader:()=>Rt,createDeviceAdbExecutor:()=>Ke,createLocalAndroidAdbProvider:()=>He,dismissAndroidKeyboard:()=>wo,dismissAndroidKeyboardWithAdb:()=>To,doubleTapAndroid:()=>Aa,ensureAndroidEmulatorBooted:()=>St,ensureAndroidImeHelper:()=>Jo,ensureAndroidSdkPathConfigured:()=>vt,ensureAndroidSnapshotHelper:()=>_r,executeAndroidTouchHelperPlan:()=>pa,executeAndroidTouchPlan:()=>Da,fillAndroid:()=>om,findAndroidAlertCandidate:()=>un,focusAndroid:()=>Wa,forceStopAndroidAppWithAdb:()=>oo,forgetAndroidSnapshotHelperInstall:()=>ur,formatAndroidInstalledPackageRequiredMessage:()=>Dt,getAndroidAppState:()=>It,getAndroidBlockingDialogObservation:()=>Lt,getAndroidImeHelperDeviceKey:()=>W,getAndroidKeyboardState:()=>Co,getAndroidKeyboardStatusWithAdb:()=>H,getAndroidScreenSize:()=>Ja,handleAndroidAlert:()=>Ya,homeAndroid:()=>Na,inferAndroidAppName:()=>Et,inferAndroidPackageAfterOpen:()=>Nm,inspectInstalledAndroidHelper:()=>Wn,installAndroidAdbPackage:()=>Je,installAndroidInstallablePath:()=>vo,isAmStartError:()=>xt,isAndroidImeHelperPackage:()=>Xo,isAndroidPermissionPackage:()=>en,isAndroidSnapshotPresentationFailure:()=>vc,isAndroidTestImeActive:()=>us,listAndroidAdbSerialsQuick:()=>vs,listAndroidAppsWithAdb:()=>km,longPressAndroid:()=>Ua,lowerAndroidAdbInvocation:()=>Ze,lowerAndroidTouchPlan:()=>Ta,makeEnsureAndroidHelperInstalled:()=>Kn,normalizeAndroidTouchHelperGestureRequest:()=>va,openAndroidApp:()=>_t,openAndroidAppWithAdb:()=>co,openAndroidDevice:()=>ht,parseAndroidAdbArgv:()=>nt,parseAndroidHelperManifest:()=>rr,parseAndroidLaunchComponent:()=>bt,parseAndroidLaunchablePackages:()=>jt,parseAndroidSnapshotHelperManifest:()=>rr,parseAndroidSnapshotHelperOutput:()=>ki,parseAndroidUserInstalledPackages:()=>At,parseInstrumentationRecords:()=>Nn,parseUiHierarchyTree:()=>rl,prepareAndroidInstallArtifact:()=>hd,pressAndroid:()=>V,pressAndroidEnter:()=>Pa,pressAndroidTvRemote:()=>ja,pullAndroidAdbFile:()=>We,pushAndroidNotification:()=>vd,readAndroidBlockingDialogFocus:()=>Nt,readAndroidClipboardText:()=>Io,readAndroidClipboardWithAdb:()=>Lo,readAndroidDefaultInputMethod:()=>G,readAndroidFillTargetBeforeMutation:()=>yu,readAndroidGestureViewport:()=>Oa,readAndroidHelperManifestInteger:()=>An,readAndroidHelperManifestLiteral:()=>O,readAndroidSetting:()=>Vp,readAndroidTestImeRecoveryMarkers:()=>Zu,readAndroidTextAtPoint:()=>_u,readAndroidTextAtPointInHierarchy:()=>Cu,readAndroidTouchHelperFinalRecord:()=>xa,readAndroidTouchHelperViewportReading:()=>ma,readInstrumentationResultBoolean:()=>zn,readInstrumentationResultNumber:()=>k,resetAndroidAdbShellProtocolProbes:()=>Zt,resetAndroidFramePerfStats:()=>qd,resetAndroidImeHelperInstallCache:()=>Yo,resetAndroidSnapshotHelperInstallCache:()=>pr,resetAndroidSnapshotHelperRuntime:()=>Pl,resetAndroidSnapshotHelperSessions:()=>ra,resetAndroidTestImeActivationCacheForTests:()=>fs,resetAndroidWindowDumpFocusMemoForTests:()=>Ft,resolveAndroidAdbExecutor:()=>y,resolveAndroidAdbProvider:()=>C,resolveAndroidApp:()=>Ot,resolveAndroidArchivePackageName:()=>nd,resolveAndroidHelperArtifact:()=>Gn,resolveAndroidImeHelperArtifact:()=>Go,resolveAndroidPackageForOpen:()=>Mm,resolveAndroidSnapshotHelperCaptureOptions:()=>yi,resolveAndroidTextInjector:()=>qe,resolveAndroidTouchProvider:()=>Be,resolveScopedAndroidAdbBackgroundTransport:()=>Ue,restoreAndroidTestIme:()=>ms,restoreOrphanedAndroidTestImeOnDaemonStartup:()=>_s,retireAndroidSnapshotHelperAfterContentFailure:()=>Nl,runAdbExecOut:()=>Ye,runAdbShell:()=>b,runAndroidAdb:()=>lt,runAndroidExecOut:()=>ct,runAndroidHostAdb:()=>ze,runAndroidShell:()=>T,runAndroidSnapshotHelperSessionTouchCommand:()=>oa,sampleAndroidFramePerf:()=>Kd,sampleAndroidMemoryPerf:()=>Sf,screenshotAndroid:()=>Qp,scrollAndroid:()=>Ga,selectAndroidImeHelperArtifact:()=>Wo,sendAndroidImeHelperText:()=>Zo,serializeAndroidAdbInvocation:()=>Qe,setAndroidOrientation:()=>Fa,setAndroidPermission:()=>$f,setAndroidSetting:()=>zp,setAndroidTestImeActiveForTests:()=>ps,sleep:()=>g,snapshotAndroid:()=>zl,startAndroidPerfettoTrace:()=>lf,startAndroidSimpleperfProfile:()=>pf,stopAndroidPerfettoTrace:()=>uf,stopAndroidSimpleperfProfile:()=>mf,stopAndroidSnapshotHelperSession:()=>z,stopAndroidSnapshotHelperSessionForDevice:()=>na,typeAndroid:()=>am,validateAndroidGestureViewport:()=>Bn,validateAndroidRegularPresentation:()=>xc,verifyAndroidFilledText:()=>gu,verifyAndroidFilledTextInHierarchy:()=>Su,verifyAndroidHelperApkChecksum:()=>Xn,waitForAndroidBoot:()=>gt,withAndroidAdbProvider:()=>Ve,withAndroidAppResolutionCacheInvalidated:()=>Tt,withAndroidHostAdbTransport:()=>Xe,writeAndroidClipboardText:()=>Ro,writeAndroidClipboardWithAdb:()=>zo,writeAndroidSimpleperfReport:()=>hf,writeAndroidTestImeRecoveryMarker:()=>Yu});async function km(...e){let{listAndroidAppsWithAdb:t}=await import(`./app-helpers.js`);return await t(...e)}async function Am(...e){let{androidClipboardShellSupportForResult:t}=await import(`./clipboard-shell-response.js`);return t(...e)}async function jm(...e){let{captureAndroidLogcatWithAdb:t}=await import(`./logcat.js`);return await t(...e)}async function Mm(...e){let{resolveAndroidPackageForOpen:t}=await import(`./open-target-resolution.js`);return await t(...e)}async function Nm(...e){let{inferAndroidPackageAfterOpen:t}=await import(`./open-target-resolution.js`);return await t(...e)}export{ja as A,Ma as C,Ua as D,Na as E,Fa as M,Da as N,V as O,Oa as P,Ha as S,Wa as T,Ro as _,am as a,co as b,zp as c,wo as d,To as f,Lo as g,Io as h,om as i,Ga as j,Pa as k,zl as l,H as m,km as n,Qp as o,Co as p,Om as r,Vp as s,jm as t,Ll as u,zo as v,Aa as w,Ya as x,oo as y};
|