agent-device 0.20.4 → 0.20.6
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/README.md +2 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.4.apk → agent-device-android-ime-helper-0.20.6.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.4.manifest.json → agent-device-android-ime-helper-0.20.6.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.4.apk → agent-device-android-snapshot-helper-0.20.6.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.4.manifest.json → agent-device-android-snapshot-helper-0.20.6.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +41 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +298 -92
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +118 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +134 -27
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +48 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +177 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +105 -448
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +587 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android.js +1 -1
- package/dist/src/app-log-request-scope.js +1 -1
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +34 -24
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -15
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/context.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -0
- package/dist/src/generic.js +1 -1
- package/dist/src/ime-lifecycle.js +3 -3
- package/dist/src/index.d.ts +27 -7
- package/dist/src/input-actions.js +4 -4
- package/dist/src/interaction-runtime.js +1 -0
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +15 -15
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +23 -2
- package/dist/src/linux.js +1 -1
- package/dist/src/process-exit.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +25 -24
- package/dist/src/remote-config.js +1 -1
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/reporting.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/screenshot-geometry.js +1 -1
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/sdk-android-adb.d.ts +20 -2
- package/dist/src/sdk-android-adb.js +1 -1
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +17 -2
- package/dist/src/sdk-finders.d.ts +4 -20
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/{interaction.d.ts → sdk-selectors.d.ts} +98 -3
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.d.ts +1 -46
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +9 -8
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/text-surface.js +1 -0
- package/dist/src/viewport-dimension.js +13 -12
- package/dist/src/web.js +1 -1
- package/package.json +42 -34
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.4.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.4.apk.sha256 +0 -1
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{f as t,m as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{f as t,m as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>] [--clean]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect local advisory device ownership without daemon side effects`,description:`Inspect advisory host-local device ownership claims without starting or contacting a daemon. --stale only inspects proven-stale claims; it does not reclaim claims or clean platform resources.`},usageOverride:`device status [--platform <platform>] [--udid <udid>] [--serial <serial>] [--stale]`,listUsageOverride:`device status`,positionalArgs:[`status`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
|
|
2
2
|
|
|
3
3
|
Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ Use the /agent-device base path when connecting through cloudflared, ngrok, or a
|
|
|
9
9
|
Examples:
|
|
10
10
|
agent-device proxy --port 4310
|
|
11
11
|
cloudflared tunnel --url http://127.0.0.1:4310
|
|
12
|
-
agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token
|
|
12
|
+
agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`},usageOverride:`proxy [--host <host>] [--port <port>] [--daemon-auth-token <token>] [--state-dir <path>]`,listUsageOverride:`proxy`,allowedFlags:[`proxyHost`,`proxyPort`,`daemonAuthToken`,`stateDir`]},"react-devtools":{text:{summary:`Inspect components, hooks, and render profiles`,description:`Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis`},usageOverride:`react-devtools [...args]`,listUsageOverride:`react-devtools`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},web:{text:{summary:`Manage web automation backend`,description:`Install and inspect the managed web automation backend used by --platform web.
|
|
13
13
|
|
|
14
14
|
First-run flow:
|
|
15
15
|
agent-device web setup
|
|
@@ -19,4 +19,4 @@ First-run flow:
|
|
|
19
19
|
|
|
20
20
|
Runtime web commands do not install the backend implicitly. If the managed backend is missing, run agent-device web setup. The backend is resolved only from the managed install in the effective agent-device state dir.
|
|
21
21
|
|
|
22
|
-
Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health
|
|
22
|
+
Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`},usageOverride:`web setup | web doctor`,listUsageOverride:`web setup|doctor`,positionalArgs:[`setup|doctor`],supportedFlags:[`stateDir`]}},o=r();function s(e){return Object.hasOwn(a,e)?a[e]:void 0}function c(e){return Object.hasOwn(o,e)?o[e]:void 0}const l=new Map(i().map(e=>[e.name,{supportedFlags:t}]));function u(e){if(e)return p(e)}function d(e){let t=p(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function f(t,n,r){let i=u(t);if(!t||!i||i.allowsExtraPositionals)return;let a=i.positionalArgs?.length??0;if(!(n.length<=a))throw new e(`INVALID_ARGS`,`${r?`${r} ${t}`:t} accepts at most ${a} positional argument(s), received ${n.length}: ${n.join(` `)}`)}function p(e){let t=s(e);if(t)return t;let n=l.get(e),r=c(e);if(!(!n||!r))return{...n,...r}}function m(e,t){let n=u(e);if(!n?.defaults)return!1;let r=!1;for(let[e,i]of Object.entries(n.defaults))t[e]===void 0&&(t[e]=i,r=!0);return r}export{u as i,f as n,d as r,m as t};
|
package/dist/src/context.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{Mt as t,Nt as n,bn as r,et as i,in as a,nt as o,rn as s,rt as c,t as l,tt as u,xn as d}from"./viewport-dimension.js";import{K as f,S as p,U as m,b as ee,p as te,q as h,r as g,x as ne,y as re}from"./screenshot-geometry.js";import{a as ie,g as ae,s as _}from"./sdk-batch-runner.js";import{M as oe}from"./screenshot-result.js";import{_ as se,c as v,f as ce,h as y,o as b,p as le,s as x,v as S}from"./sdk-device.js";import{_ as ue,a as de}from"./device.js";import{d as fe}from"./runtime.js";import{I as C,N as pe,j as w}from"./sdk-android-adb.js";import{t as me}from"./timeouts.js";import{a as he,o as ge}from"./boot-diagnostics.js";import{i as _e}from"./lease-context.js";import{i as ve,n as ye,r as be,t as xe}from"./register-builtins.js";import Se from"node:path";import{AsyncLocalStorage as T}from"node:async_hooks";import Ce,{promises as E}from"node:fs";let we=[];const D=new T;async function Te(e,t){return await D.run([...e],t)}function Ee(e,t){for(let n of O()){if(!n.ownsDevice(e))continue;let r=n.getInteractor(e,t);if(r)return r}}function De(e){return O().some(t=>t.ownsDevice(e))}async function Oe(e,t,n,r){for(let i of O()){if(!i.ownsDevice(e))continue;if(!i.installApp)throw M(i,e,`install`);let a=await i.installApp?.(e,t,n,r);if(a)return a;throw M(i,e,`install`)}}async function ke(e,t,n){for(let r of O()){if(!r.ownsDevice(e))continue;if(!r.installInstallablePath)throw M(r,e,`install_from_source`);let i=await r.installInstallablePath?.(e,t,n);if(i)return i;throw M(r,e,`install_from_source`)}}async function Ae(e){for(let t of O()){if(!j(t,e.provider))continue;let n=await t.configurePortReverse?.(e);if(n)return n}}function O(){return D.getStore()??we}function je(e,t={}){let n=e.map(e=>e.provider);return{providerRuntimeIds:n,providerRuntimeRequiredIds:Pe([...n,...t.providerRuntimeRequiredIds??[]]),leaseLifecycleProvider:Fe(e),recoverableProviderIds:e.filter(e=>e.recoverExpiredLease!==void 0).map(e=>e.provider),recoverExpiredLease:Ne(e),cloudArtifactProvider:Ie(e),deviceInventoryProvider:Le(e),appleRunnerProvider:Me(e),providerDeviceRuntimeScope:async t=>await Te(e,t)}}function Me(e){if(e.some(k))return t=>{for(let n of e){if(!k(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerProvider(t.device);if(e)return e}}}function k(e){return`getAppleRunnerProvider`in e&&typeof e.getAppleRunnerProvider==`function`}function Ne(t){if(t.some(e=>e.recoverExpiredLease!==void 0))return async n=>{let r=t.find(e=>j(e,n.leaseProvider));if(!r?.recoverExpiredLease)throw new e(`UNSUPPORTED_OPERATION`,`Provider ${n.leaseProvider??`unknown`} cannot recover an expired lease.`,{provider:n.leaseProvider,leaseId:n.leaseId});await r.recoverExpiredLease(n)}}function Pe(e){return[...new Set(e)]}function Fe(e){if(e.length!==0)return{allocate:async(t,n)=>await A(e,`allocate`,t,n),heartbeat:async(t,n)=>await A(e,`heartbeat`,t,n),release:async(t,n)=>await A(e,`release`,t,n)}}function Ie(e){if(e.length!==0)return{listCloudArtifacts:async t=>await Re(e,t)}}function Le(e){if(e.length!==0)return async t=>{for(let n of e){if(!j(n,t.leaseProvider))continue;let e=await n.deviceInventoryProvider(t);if(e)return e}return null}}async function Re(e,t){for(let n of e){if(!j(n,t.provider))continue;let e=await n.cloudArtifacts?.listCloudArtifacts?.(t);if(e)return e}}async function A(e,t,n,r){for(let i of e){if(!j(i,n.leaseProvider))continue;let e=i.leaseLifecycle[t],a=e?await e(n,r):void 0;if(a)return a}}function j(e,t){return e.provider===t}function M(t,n,r){throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime ${t.provider} does not support ${r} for this device.`,{provider:t.provider,deviceId:n.id,platform:y(n)})}const N=new T,ze=new T;async function Be(t,n,r){let i=await Ve(t,n,r);if(i)return i;let a=await He(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&We(n,a)){let{findBootableIosSimulator:e}=await import(`./devices2.js`),t=await e({simulatorSetPath:r.simulatorSetPath,target:n.target});if(t)return t}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function Ve(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||P(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>le(e,n)&&x(e)&&e.kind===`simulator`&&e.booted===!0);if(a.length<2)return;let{findIosSimulatorInstalledApp:o}=await import(`./apps.js`).then(e=>e.t),s=(await Promise.all(a.map(async e=>await o(e,i)?e:void 0))).filter(e=>e!==void 0);if(s.length===1)return s[0];let c=a.map(e=>({id:e.id,name:e.name}));throw s.length===0?new e(`APP_NOT_INSTALLED`,`No booted iOS simulator has ${i} installed`,{appTarget:i,candidates:c,hint:`Install the app on a booted simulator, or pass --udid to select the intended device explicitly.`}):new e(`AMBIGUOUS_MATCH`,`Multiple booted iOS simulators have ${i} installed`,{appTarget:i,candidates:s.map(e=>({id:e.id,name:e.name})),hint:`Pass --udid to select the intended simulator explicitly.`})}async function He(e,t,n){try{return await S(e,t,n)}catch(e){if(Ue(e,t))return;throw e}}function Ue(t,n){return!P(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function We(e,t){return!P(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function P(e){return!!(e.udid||e.serial||e.deviceName)}async function Ge(e,t={}){let n=Ke(e),{iosSimulatorSetPath:r,...i}=n,a=$e(n,t),o={simulatorSetPath:r,allowStoppedAndroidAvdPlaceholders:t.allowStoppedAndroidAvdPlaceholders},s={platform:n.platform,target:e.target,cacheHit:!1};return await C(`resolve_target_device`,async()=>{let e=Qe(a);if(e)return s.cacheHit=!0,e;let c=await F(n);if(c)return I(i)?L(a,await Be(c,i,{simulatorSetPath:r,allowLocalSimulatorFallback:n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):L(a,await S(c,i,o));let l=await ve(n);return I(i)?L(a,await Be(l,i,{simulatorSetPath:r,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):L(a,await S(l,i,o))},s)}function Ke(t){let n=t.platform;if(t.target&&!n)throw new e(`INVALID_ARGS`,`Device target selector requires --platform. Use --platform ios|macos|android|vega|linux|apple with --target mobile|tv|desktop.`);let r=se({simulatorSetPath:ge(t.iosSimulatorDeviceSet),platform:n,target:t.target}),i=he(t.androidDeviceAllowlist);return{platform:n,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial,leaseId:t.leaseId,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId,iosSimulatorSetPath:r,androidSerialAllowlist:i?Array.from(i).sort():void 0}}async function qe(e){return N.getStore()?await e():await N.run(new Map,e)}async function Je(e,t){return e?await ze.run(e,t):await t()}async function Ye(e,t){return await Je(e,async()=>await qe(t))}async function Xe(e){return await F(e)??await ve(e)}async function F(e){let t=ze.getStore();if(!t)return null;let n=await t(e);return n==null?null:n.map(e=>({...e}))}function Ze(e){return b(e.platform)}function I(e){return Ze(e)}function Qe(e){let t=N.getStore()?.get(e);if(t)return{...t}}function L(e,t){return N.getStore()?.set(e,{...t}),t}function $e(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}xe();const et={device:!0},tt=[`open`,`close`],nt=[`record`],rt=[`audio`,`find`,`get`,`is`,`network`,`screenshot`,`snapshot`,`wait`],it=[`click`,`fill`,`focus`,`press`,`scroll`,`type`],at=[`viewport`],R=new Set([...tt,...nt,...rt,...it,...at]),z=ot(ie(ae));function ot(e){let t={};for(let[n,r]of Object.entries(e))t[n]=R.has(n)?{...r,web:et}:r;for(let t of R)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function B(e,t){let n=z[e];if(!n)return!0;let r=be(t.platform);if(!r)return!1;let i=n[r.capability.bucket];if(!i)return!1;let a=r.capability.supportsByDefault?.[e];return a&&!a(t)?!1:i[t.kind??`unknown`]===!0}function st(e,t){return be(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function ct(){return Object.keys(z).sort()}function lt(e){let t=z[e];if(!t)return[];let n=[`apple`,`android`,`vega`,`linux`,`web`],r=[];for(let e of n){let n=t[e];n&&Object.values(n).some(e=>e===!0)&&r.push(e)}return r}function ut(e,t){if(t.platform===`web`||t.appleOs===`watchos`)throw H(e,V(e,t));if(dt(e)){ft(e,t);return}if(t.appleOs===`visionos`)throw H(e,V(e,t));if(e.intent===`fling`&&`direction`in e&&t.platform===`linux`)throw H(e,`gesture fling is not supported on Linux`)}function dt(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function ft(e,t){if(t.platform===`android`){if(t.target!==`tv`)return;throw H(e,`gesture ${e.intent} is not supported on Android TV`,`Android TV has no touch input — this gesture is supported on Android phones, tablets, and the iOS simulator only.`)}if(t.platform!==`apple`)throw H(e,V(e,t));ue(t,e.intent)}function V(e,t){return`gesture ${e.intent} is not supported on ${t.appleOs??t.platform}`}function H(t,n,r){return new e(`UNSUPPORTED_OPERATION`,n,{gesture:t.intent,...r?{hint:r}:{}})}const U=`No active session. Run open first.`;function W(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function pt(){return W(`SESSION_NOT_FOUND`,U)}function mt(e,t,n){if(B(e,t))return null;let r=n?.hint?st(e,t):void 0;return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:n?.message??`${e} is not supported on this device`,...r?{hint:r}:{}}}}const ht=/^[A-Za-z0-9_.:-]{1,64}$/,G=8*1024,K=4*1024;function gt(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!ht.test(n))throw new e(`INVALID_ARGS`,`Invalid trigger-app-event event name: ${n}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});if(t.length>2)throw new e(`INVALID_ARGS`,`trigger-app-event accepts at most two arguments: <event> [payloadJson]`);return{eventName:n,payload:vt(r,n)}}function _t(t,n,r){let i=y(t),a=yt(t);if(!a)throw new e(`UNSUPPORTED_OPERATION`,`No app event URL template configured for ${i}.`,{hint:`Set AGENT_DEVICE_${i.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):``,s=a.replaceAll(`{event}`,encodeURIComponent(n)).replaceAll(`{payload}`,encodeURIComponent(o)).replaceAll(`{platform}`,encodeURIComponent(i));if(s.length>K)throw new e(`INVALID_ARGS`,`trigger-app-event URL exceeds maximum supported length`,{hint:`Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.`,length:s.length,maxLength:K});return s}function vt(t,n){if(t)try{let r=JSON.parse(t);if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,`utf8`)>G)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${G} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function yt(e){return((x(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:v(e)?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE)?.trim()||void 0}const q=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function bt(e,t){return b(e.platform)&&t>1}function xt(e,t,n=2e4){if(e.length===0)return[];let r=t>0?t:e.length,i=[],a=[],o=0;for(let t of e){let e=(t.durationMs??0)+(t.pauseMs??0)+250,s=a.length>0&&o+e>n,c=a.length>=r;(s||c)&&(i.push(a),a=[],o=0),a.push(t),o+=e}return a.length>0&&i.push(a),i}function St(e,t){if(t<=0)return[0,0];let[n,r]=q[e%q.length];return[n*t,r*t]}async function Ct(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await me(t)}async function wt(e,t){let{x:n,y:r}=J(t,`longpress requires x y [durationMs]`,{hint:`Direct platform longpress requires coordinates. In an open daemon session, use agent-device longpress @ref|selector [durationMs]; otherwise run snapshot -i, use the target rect center as x y, then retry longpress x y durationMs.`}),i=t[2]?Number(t[2]):void 0;return await e.longPress(n,r,i),{x:n,y:r,durationMs:i,...s(`Long pressed (${n}, ${r})`)}}async function Tt(e,t){let{x:n,y:r}=J(t,`focus requires x y`);return await e.focus(n,r),{x:n,y:r,...s(`Focused (${n}, ${r})`)}}async function Et(t,n,r){let a=Zt(n);if(a)throw new e(`INVALID_ARGS`,`type does not accept a target ref like "${a}"`,{hint:`Use fill ${a} "text" to target that field, or press ${a} then type "text" to append.`});let o=n.join(` `);if(!o)throw new e(`INVALID_ARGS`,`type requires text`);let c=i(r?.delayMs??0,`delay-ms`,0,1e4);return await t.type(o,c),{text:o,delayMs:c,...s(Z(`Typed`,o))}}async function Dt(t,n,r){if(r?.directElementSelector)return await Ot(t,r.directElementSelector,n,r);let a=Number(n[0]),o=Number(n[1]),c=n.slice(2).join(` `);if(Number.isNaN(a)||Number.isNaN(o)||!c)throw new e(`INVALID_ARGS`,`fill requires x y text`);let l=i(r?.delayMs??0,`delay-ms`,0,1e4);return await t.fill(a,o,c,l),{x:a,y:o,text:c,delayMs:l,...s(Z(`Filled`,c))}}async function Ot(t,n,r,a){if(!t.fillElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector fill is not supported`);let o=r.join(` `);if(!o)throw new e(`INVALID_ARGS`,`fill requires text`);let c=i(a.delayMs??0,`delay-ms`,0,1e4),l=await t.fillElementSelector(n,o,c);return{selector:n.raw,text:o,delayMs:c,...l??{},...s(Z(`Filled`,o))}}async function kt(e,t,n,r){if(r?.directElementSelector&&x(e))return await At(t,r.directElementSelector);let{x:i,y:a}=J(n,`press requires x y`);if(v(e)&&r?.surface&&r.surface!==`app`)return await jt(i,a,r);let o=h(r);if(o!==`primary`)return await Mt(e,i,a,o,r);let s=Ft(r);return It(s),bt(e,s.count)?await Rt(e,i,a,s,r):await Vt(t,i,a,s)}async function At(t,n){if(!t.tapElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector tap is not supported`);let r=await t.tapElementSelector(n),i=r?.maestroNonHittableCoordinateFallbackUsed===!0;return{selector:n.raw,...r??{},...s(i?p:`Tapped ${n.raw}`)}}function J(t,n,r){let i=Number(t[0]),a=Number(t[1]);if(Number.isNaN(i)||Number.isNaN(a))throw new e(`INVALID_ARGS`,n,r);return{x:i,y:a}}async function jt(t,n,r){let i=h(r);if(i!==`primary`)throw new e(`UNSUPPORTED_OPERATION`,`${i} click is not supported on macOS ${r.surface} sessions.`);let{runMacOsPressAction:a}=await import(`./helper.js`).then(e=>e.t);return await a(t,n,{bundleId:r.appBundleId,surface:r.surface}),{x:t,y:n,...s(X({x:t,y:n}))}}async function Mt(e,t,n,r,i){if(Nt(e,r,i),e.platform===`linux`)return await Pt(t,n,r);let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},Ht(i)),{x:t,y:n,button:r,...s(X({x:t,y:n,button:r}))}}function Nt(e,t,n){let r=f({commandLabel:`click`,platform:y(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function Pt(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}return{x:e,y:t,button:n,...s(X({x:e,y:t,button:n}))}}function Ft(e){return{count:Y(e?.count,1,`count`,1,200),intervalMs:Y(e?.intervalMs,0,`interval-ms`,0,1e4),holdMs:Y(e?.holdMs,0,`hold-ms`,0,1e4),jitterPx:Y(e?.jitterPx,0,`jitter-px`,0,100),doubleTap:!!e?.doubleTap}}function Y(e,t,n,r,a){return i(e===void 0?t:e,n,r,a)}function It({doubleTap:t,holdMs:n,jitterPx:r}){if(t&&n>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with hold-ms`);if(t&&r>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with jitter-px`)}async function Lt(e,t,n){let{runAppleRunnerCommand:r}=await import(`./runner-client.js`).then(e=>e.o),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=xt(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),Ht(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Bt(e,f)}u+=s.completedSteps,d.push(...s.results),f+=t.length}return{...c??{},completedSteps:u,sequenceResults:d,...l?.gestureEndUptimeMs===void 0?{}:{gestureEndUptimeMs:l.gestureEndUptimeMs}}}async function Rt(e,t,n,r,i){let a=await Lt(e,zt(e,t,n,r),i);return{x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,timingMode:`runner-sequence`,...a,...s(X({x:t,y:n}))}}function zt(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&x(e)&&!ce(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=St(o,r.jitterPx),l=o===r.count-1;return{kind:i,x:t+s,y:n+c,...a?{synthesized:!0}:{},...r.holdMs>0?{durationMs:r.holdMs}:{},...!l&&r.intervalMs>0?{pauseMs:r.intervalMs}:{}}})}function Bt(t,n){if(n===0||!(t instanceof e)||!t.details)return t;let r=t.details.failedStepIndex;if(typeof r!=`number`)return t;let i=t.details.completedSteps;return new e(t.code,t.message,{...t.details,failedStepIndex:r+n,chunkStepIndex:r,...typeof i==`number`?{completedSteps:n+i}:{}},t.cause)}async function Vt(e,t,n,r){let i;return await Ct(r.count,r.intervalMs,async a=>{let[o,s]=St(a,r.jitterPx),c=t+o,l=n+s;if(r.doubleTap){let t=await e.doubleTap(c,l);i??=t??void 0;return}if(r.holdMs>0){let t=await e.longPress(c,l,r.holdMs);i??=t??void 0}else{let t=await e.tap(c,l);i??=t??void 0}}),a({x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,...i},X({x:t,y:n}))}function Ht(e){return{verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,requestId:e?.requestId,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir}}async function Ut(t,n,r){let i=n[0],s=n[1]?Number(n[1]):void 0,c=r?.pixels,l=r?.durationMs;if(!i)throw new e(`INVALID_ARGS`,`scroll requires direction`);Wt(s,c,l);let u=Yt(i),d={amount:s,pixels:c,durationMs:l},{interactionResult:f,completedPasses:p}=await Kt(t,r,u,d);return a(qt(u,d,p,f),o(u.direction,u.edge,p,s,c))}function Wt(e,t,n){Gt(e),ne(n),re({amount:e,pixels:t})}function Gt(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Kt(e,t,n,r){if(n.edge){let i=n.edge,a=await c({edge:i,captureState:async n=>await Jt(e,t,i,n),scroll:async()=>await e.scroll(n.direction,r)});return{interactionResult:a.result??{},completedPasses:a.passes}}return{interactionResult:await e.scroll(n.direction,r)??{},completedPasses:1}}function qt(e,t,n,r){let i=ee(r);return{direction:e.direction,...e.edge?{edge:e.edge,passes:n}:{},...t.amount===void 0?{}:{amount:t.amount},...t.pixels===void 0?{}:{pixels:t.pixels},...i===void 0?{}:{durationMs:i},...r}}async function Jt(t,n,r,i){if(typeof t.snapshot!=`function`)throw new e(`UNSUPPORTED_OPERATION`,`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let a=t.snapshot;return await u({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function Yt(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:m(e)}}async function Xt(e,t,n){let{x:r,y:i}=J(t,`read requires x y`);if(e.platform===`android`){let{readAndroidTextAtPoint:t}=await import(`./input-actions.js`).then(e=>e.s);return{action:`read`,text:await t(e,r,i)??``}}if(e.platform===`linux`){let{readLinuxTextAtPoint:e}=await import(`./snapshot.js`).then(e=>e.n);return{action:`read`,text:await e(r,i,n?.surface)}}if(v(e)&&n?.surface&&n.surface!==`app`){let{runMacOsReadTextAction:e}=await import(`./helper.js`).then(e=>e.t);return{action:`read`,text:(await e(r,i,{bundleId:n.appBundleId,surface:n.surface})).text}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(e,{command:`readText`,x:r,y:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId,iosXctestrunFile:n?.iosXctestrunFile,iosXctestDerivedDataPath:n?.iosXctestDerivedDataPath,iosXctestEnvDir:n?.iosXctestEnvDir});return{action:`read`,text:typeof o.text==`string`?o.text:typeof o.message==`string`?o.message:``}}function Zt(e){return fe(e[0])}function X(e){return e.button&&e.button!==`primary`?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function Z(e,t){return`${e} ${Array.from(t).length} chars`}function Qt(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)}function $t(t,n){let r=n?.subject??`Payload`,i=t.trim();if(!i)throw new e(`INVALID_ARGS`,`${r} cannot be empty`);let a=n?.expandPath?n.expandPath(i,n.cwd):i;try{if(!Ce.statSync(a).isFile())throw new e(`INVALID_ARGS`,`${r} path is not a file: ${a}`);return{kind:`file`,path:a}}catch(t){if(t instanceof e)throw t;let n=t.code;if(n===`EACCES`||n===`EPERM`)throw new e(`INVALID_ARGS`,`${r} file is not readable: ${a}`);if(n&&n!==`ENOENT`)throw new e(`COMMAND_FAILED`,`Unable to read ${r} file: ${a}`,{cause:String(t)})}if(Qt(i))return{kind:`inline`,text:i};throw new e(`INVALID_ARGS`,`${r} file not found: ${a}`)}async function en(t){let n=$t(t,{subject:`Push payload`}),r=n.kind===`inline`?n.text:await tn(n.path);try{let t=JSON.parse(r);if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`push payload must be a JSON object`);return t}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid push payload JSON: ${t}`)}}async function tn(t){try{return await E.readFile(t,`utf8`)}catch(n){let r=n.code;throw r===`ENOENT`?new e(`INVALID_ARGS`,`Push payload file not found: ${t}`):r===`EISDIR`?new e(`INVALID_ARGS`,`Push payload path is not a file: ${t}`):r===`EACCES`||r===`EPERM`?new e(`INVALID_ARGS`,`Push payload file is not readable: ${t}`):new e(`COMMAND_FAILED`,`Unable to read push payload file: ${t}`,{cause:String(n)})}}xe();async function Q(t,n){if(De(t)){let r=Ee(t,n);if(r)return r;throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime does not have an active interactor for this device.`,{deviceId:t.id,platform:y(t)})}return await ye(t.platform).createInteractor(t,n)}async function nn(e,t,n,r,i){let a=$(i),o=await Q(e,a);return w({level:`debug`,phase:`platform_command_prepare`,data:{command:t,platform:e.platform,kind:e.kind}}),await C(`platform_command`,async()=>await sn(e,o,t,n,r,i,a),{command:t,platform:e.platform})}async function rn(t,n,r){let i=await Q(t,$(r));if(!i.performGesture)throw new e(`UNSUPPORTED_OPERATION`,`Gesture execution is unavailable`);return await i.performGesture(n)}async function an(e,t){return await(await Q(e,$(t))).gestureViewport?.()}function $(e){return{requestId:e?.requestId,signal:e?.signal,appBundleId:e?.appBundleId,verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir,runnerLeaseContext:e?.runnerLeaseContext}}const on={open:({device:e,interactor:t,positionals:n,context:r})=>cn(e,t,n,r),close:async({device:e,interactor:t,positionals:n})=>{let r=n[0];return r?(await t.close(r),{app:r,...s(`Closed: ${r}`)}):(e.platform===`web`&&await t.close(``),{closed:`session`,...s(`Closed session`)})},press:({device:e,interactor:t,positionals:n,context:r})=>kt(e,t,n,r),longpress:({interactor:e,positionals:t})=>wt(e,t),focus:({interactor:e,positionals:t})=>Tt(e,t),type:({interactor:e,positionals:t,context:n})=>Et(e,t,n),fill:({interactor:e,positionals:t,context:n})=>Dt(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>Ut(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>ln(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>un(e,t,n,r),viewport:({interactor:e,positionals:t})=>dn(e,t),back:async({interactor:e,context:t})=>(await e.back(t?.backMode),{action:`back`,mode:t?.backMode??`in-app`,...s(`Back`)}),home:async({interactor:e})=>(await e.home(),{action:`home`,...s(`Home`)}),orientation:async({interactor:e,positionals:t})=>{let n=de(t[0]),r=(await e.setOrientation(n))?.orientation??n;return{action:`orientation`,orientation:r,...s(`Rotated to ${r}`)}},"app-switcher":async({interactor:e})=>(await e.appSwitcher(),{action:`app-switcher`,...s(`Opened app switcher`)}),clipboard:({interactor:e,positionals:t})=>fn(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>mn(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>pn(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>_n(e,t,n,r),push:({device:e,positionals:t,context:n})=>vn(e,t,n),snapshot:({interactor:e,context:t})=>yn(e,t),read:({device:e,positionals:t,context:n})=>Xt(e,t,n)};async function sn(t,n,r,i,a,o,s){let c=Object.hasOwn(on,r)?on[r]:void 0;if(!c)throw new e(`INVALID_ARGS`,`Unknown command: ${r}`);return await c({device:t,interactor:n,positionals:i,outPath:a,context:o,runnerCtx:s})}async function cn(r,i,a,o){let c=a[0],l=a[1],u=o?.launchConsole,d=o?.launchArgs;if(a.length>2)throw new e(`INVALID_ARGS`,`open accepts at most two arguments: <app|url> [url]`);if(!c){if(u)throw new e(`INVALID_ARGS`,`--launch-console requires an app target`);if(d&&d.length>0)throw new e(`INVALID_ARGS`,`--launch-args requires an app target`);return await i.openDevice(),{app:null,...s(`Opened device`)}}if(u&&(!x(r)||r.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,n);if(r.platform===`linux`&&d&&d.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on Linux.`);if(l!==void 0){if(_(c))throw new e(`INVALID_ARGS`,`open <app> <url> requires an app target as the first argument`);if(!_(l))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(u)throw new e(`INVALID_ARGS`,t);return await i.open(c,{activity:o?.activity,appBundleId:o?.appBundleId,launchArgs:d,terminateRunningApp:o?.terminateRunningApp,url:l}),{app:c,url:l,...s(`Opened: ${c}`)}}if(u&&_(c))throw new e(`INVALID_ARGS`,t);if(o?.clearAppState){if(_(c))throw new e(`INVALID_ARGS`,`Clearing app state requires an app target, not a deep link.`);await i.setSetting(`clear-app-state`,`clear`,c)}return await i.open(c,{activity:o?.activity,appBundleId:o?.appBundleId,launchConsole:u,launchArgs:d,terminateRunningApp:o?.terminateRunningApp}),{app:c,...u?{launchConsole:u}:{},...s(`Opened: ${c}`)}}async function ln(e,t,n,r){let{eventName:i,payload:a}=gt(n),o=_t(e,i,a);return await t.open(o,{appBundleId:r?.appBundleId}),{event:i,eventUrl:o,transport:`deep-link`,...s(`Triggered app event: ${i}`)}}async function un(e,t,n,r){let i=t[0]??n??`./screenshot-${Date.now()}.png`;await E.mkdir(Se.dirname(i),{recursive:!0});let a=d(r);return await e.screenshot(i,{appBundleId:r?.appBundleId,pixelDensity:a.pixelDensity,fullscreen:a.fullscreen,normalizeStatusBar:a.normalizeStatusBar,stabilize:a.stabilize,surface:r?.surface,skipIosSimulatorBootCheck:r?.skipIosSimulatorBootCheck,captureBackend:r?.screenshotCaptureBackend}),{path:i,...s(`Saved screenshot: ${i}`)}}async function dn(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=l(n[0],`width`),i=l(n[1],`height`);if(!t.setViewport)throw new e(`UNSUPPORTED_OPERATION`,`viewport is not supported by this backend`);return await t.setViewport(r,i),{width:r,height:i,...s(`Viewport set: ${r}x${i}`)}}async function fn(t,n){let r=(n[0]??``).toLowerCase();if(r!==`read`&&r!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write`);if(r===`read`){if(n.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments`);return{action:r,text:await t.readClipboard()}}if(n.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text (use "" to clear clipboard)`);let i=n.slice(1).join(` `);return await t.writeClipboard(i),{action:r,textLength:Array.from(i).length,...s(`Clipboard updated`)}}async function pn(t,n,r,a){if(t.target!==`tv`)throw new e(`UNSUPPORTED_OPERATION`,`tv-remote is supported only on TV targets`,{hint:`Select an Android TV, tvOS, or Vega OS target with --target tv.`});if(r.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button`);let o=te(r[0]),c=a?.durationMs===void 0?void 0:i(a.durationMs,`durationMs`,0,1e4);return await n.tvRemote(o,c),{action:`tv-remote`,button:o,...c===void 0?{}:{durationMs:c},...s(`Pressed TV remote ${o}`)}}async function mn(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!oe(a))throw new e(`INVALID_ARGS`,`keyboard requires a subcommand: status, get, dismiss, enter, or return`);if(n.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one subcommand argument`);if(t.platform===`android`)return await hn(t,a);if(x(t))return await gn(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android and iOS`)}async function hn(e,t){if(t===`enter`||t===`return`){let{pressAndroidEnter:t}=await import(`./input-actions.js`).then(e=>e.s);return await t(e),{platform:`android`,action:`enter`,...s(`Keyboard enter pressed`)}}if(t===`dismiss`){let{dismissAndroidKeyboard:t}=await import(`./device-input-state.js`).then(e=>e.t),n=await t(e);return{platform:`android`,action:`dismiss`,attempts:n.attempts,wasVisible:n.wasVisible,dismissed:n.dismissed,visible:n.visible,inputType:n.inputType,type:n.type,inputMethodPackage:n.inputMethodPackage,focusedPackage:n.focusedPackage,focusedResourceId:n.focusedResourceId,inputOwner:n.inputOwner}}let{getAndroidKeyboardState:n}=await import(`./device-input-state.js`).then(e=>e.t),r=await n(e);return{platform:`android`,action:`status`,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}async function gn(t,n,r,i){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is currently supported only on Android; use keyboard dismiss or enter on iOS`);if(n===`enter`||n===`return`){let{runAppleRunnerCommand:e}=await import(`./runner-client.js`).then(e=>e.o),n=await e(t,{command:`keyboardReturn`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`enter`,visible:n.visible,wasVisible:n.wasVisible,...s(`Keyboard enter pressed`)}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(t,{command:`keyboardDismiss`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`dismiss`,wasVisible:o.wasVisible,dismissed:o.dismissed,visible:o.visible,...s(o.dismissed?`Keyboard dismissed`:`Keyboard already hidden`)}}async function _n(t,n,r,i){let[o,c,l,u]=r;if(!o||!c&&o!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(o===`clear-app-state`){let r=(c===`clear`?l:c)??i?.appBundleId;if(!r)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);w({level:`debug`,phase:`settings_apply`,data:{setting:o,state:`clear`,appBundleId:r,platform:t.platform}});let u=await n.setSetting(o,`clear`,r);return u&&typeof u==`object`?a({setting:o,state:`clear`,...u},bn(u)??`Cleared user data for ${r}`):{setting:o,state:`clear`,...s(`Cleared user data for ${r}`)}}if(!c)throw new e(`INVALID_ARGS`,`settings requires setting state`);let d=o===`location`&&c===`set`,f=(o===`permission`||d?r[4]:r[2])??i?.appBundleId,p=o===`permission`?{permissionTarget:l,permissionMode:u}:d?{latitude:g(l,`latitude`),longitude:g(u,`longitude`)}:void 0;w({level:`debug`,phase:`settings_apply`,data:d?{setting:o,state:c,latitude:l,longitude:u,platform:t.platform}:o===`permission`?{setting:o,state:c,permissionTarget:l,permissionMode:u,platform:t.platform}:{setting:o,state:c,appBundleId:f,platform:t.platform}});let m=await n.setSetting(o,c,f,p);return m&&typeof m==`object`?a({setting:o,state:c,...m},bn(m)??`Updated setting: ${o}`):{setting:o,state:c,...s(`Updated setting: ${o}`)}}async function vn(t,n,r){let i=n[0]?.trim(),a=n[1]?.trim();if(!i||!a)throw new e(`INVALID_ARGS`,`push requires <bundle|package> <payload.json|inline-json>`);let o=await en(a);if(x(t)){let{pushIosNotification:e}=await import(`./apps.js`).then(e=>e.t);return await e(t,i,o),{platform:`ios`,bundleId:i,...s(`Pushed notification to ${i}`)}}let{pushAndroidNotification:c}=await import(`./notifications.js`),l=await c(t,i,o);return{platform:`android`,package:i,action:l.action,extrasCount:l.extrasCount,...s(`Pushed notification to ${i}`)}}async function yn(e,t){let n=t??{};return await e.snapshot({appBundleId:n.appBundleId,signal:n.signal,interactiveOnly:n.snapshotInteractiveOnly,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw,includeRects:n.snapshotIncludeRects,includeHiddenContentHints:n.snapshotIncludeHiddenContentHints,surface:n.surface})}function bn(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}function xn(e,t,n,i,a,o){return{requestId:a??pe().requestId,appBundleId:n,runnerLeaseContext:_e({meta:o}),activity:t?.activity,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,clearAppState:t?.clearAppState,verbose:t?.verbose,logPath:e,traceLogPath:i,iosXctestrunFile:t?.iosXctestrunFile,iosXctestDerivedDataPath:t?.iosXctestDerivedDataPath,iosXctestEnvDir:t?.iosXctestEnvDir,screenshotCaptureBackend:t?.maestro?.screenshotCaptureBackend,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,snapshotIncludeHiddenContentHints:t?.snapshotIncludeHiddenContentHints,...r(t),count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,durationMs:t?.durationMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:h(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}export{De as S,Ye as _,$t as a,Oe as b,pt as c,ct as d,ut as f,Ge as g,Xe as h,an as i,mt as l,Ke as m,nn as n,U as o,lt as p,rn as r,W as s,xn as t,B as u,Ae as v,ke as x,je as y};
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{A as t,At as n,Mt as r,O as i,S as a,ct as o,d as s,it as c,j as l,k as u,lt as d}from"./screenshot-geometry.js";import{a as f,h as p,s as m}from"./sdk-batch-runner.js";import{_ as ee,c as h,f as te,h as g,o as _,p as ne,s as v,v as y}from"./sdk-device.js";import{Ht as re,Vt as b,ct as ie,fn as x,lt as ae,pn as S,st as C,t as oe,ut as se}from"./viewport-dimension.js";import{M as ce}from"./screenshot-result.js";import{_ as le,a as ue}from"./device.js";import{f as de}from"./runtime.js";import{I as fe,N as pe,j as w}from"./sdk-android-adb.js";import{t as me}from"./timeouts.js";import{a as he,o as ge}from"./boot-diagnostics.js";import{i as _e}from"./lease-context.js";import{i as T,n as ve,r as E,t as D}from"./register-builtins.js";import ye from"node:path";import{AsyncLocalStorage as O}from"node:async_hooks";import be,{promises as k}from"node:fs";let xe=[];const A=new O;async function Se(e,t){return await A.run([...e],t)}function Ce(e,t){for(let n of M()){if(!n.ownsDevice(e))continue;let r=n.getInteractor(e,t);if(r)return r}}function j(e){return M().some(t=>t.ownsDevice(e))}async function we(e,t,n,r){for(let i of M()){if(!i.ownsDevice(e))continue;if(!i.installApp)throw I(i,e,`install`);let a=await i.installApp?.(e,t,n,r);if(a)return a;throw I(i,e,`install`)}}async function Te(e,t,n){for(let r of M()){if(!r.ownsDevice(e))continue;if(!r.installInstallablePath)throw I(r,e,`install_from_source`);let i=await r.installInstallablePath?.(e,t,n);if(i)return i;throw I(r,e,`install_from_source`)}}async function Ee(e){for(let t of M()){if(!F(t,e.provider))continue;let n=await t.configurePortReverse?.(e);if(n)return n}}function M(){return A.getStore()??xe}function De(e,t={}){let n=e.map(e=>e.provider);return{providerRuntimeIds:n,providerRuntimeRequiredIds:Ae([...n,...t.providerRuntimeRequiredIds??[]]),leaseLifecycleProvider:je(e),recoverableProviderIds:e.filter(e=>e.recoverExpiredLease!==void 0).map(e=>e.provider),recoverExpiredLease:ke(e),cloudArtifactProvider:Me(e),deviceInventoryProvider:Ne(e),appleRunnerProvider:Oe(e),providerDeviceRuntimeScope:async t=>await Se(e,t)}}function Oe(e){if(e.some(N))return t=>{for(let n of e){if(!N(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerProvider(t.device);if(e)return e}}}function N(e){return`getAppleRunnerProvider`in e&&typeof e.getAppleRunnerProvider==`function`}function ke(t){if(t.some(e=>e.recoverExpiredLease!==void 0))return async n=>{let r=t.find(e=>F(e,n.leaseProvider));if(!r?.recoverExpiredLease)throw new e(`UNSUPPORTED_OPERATION`,`Provider ${n.leaseProvider??`unknown`} cannot recover an expired lease.`,{provider:n.leaseProvider,leaseId:n.leaseId});await r.recoverExpiredLease(n)}}function Ae(e){return[...new Set(e)]}function je(e){if(e.length!==0)return{allocate:async(t,n)=>await P(e,`allocate`,t,n),heartbeat:async(t,n)=>await P(e,`heartbeat`,t,n),release:async(t,n)=>await P(e,`release`,t,n)}}function Me(e){if(e.length!==0)return{listCloudArtifacts:async t=>await Pe(e,t)}}function Ne(e){if(e.length!==0)return async t=>{for(let n of e){if(!F(n,t.leaseProvider))continue;let e=await n.deviceInventoryProvider(t);if(e)return e}return null}}async function Pe(e,t){for(let n of e){if(!F(n,t.provider))continue;let e=await n.cloudArtifacts?.listCloudArtifacts?.(t);if(e)return e}}async function P(e,t,n,r){for(let i of e){if(!F(i,n.leaseProvider))continue;let e=i.leaseLifecycle[t],a=e?await e(n,r):void 0;if(a)return a}}function F(e,t){return e.provider===t}function I(t,n,r){throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime ${t.provider} does not support ${r} for this device.`,{provider:t.provider,deviceId:n.id,platform:g(n)})}const L=new O,R=new O;async function z(t,n,r){let i=await Fe(t,n,r);if(i)return i;let a=await Ie(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&Re(n,a)){let{findBootableIosSimulator:e}=await import(`./devices2.js`),t=await e({simulatorSetPath:r.simulatorSetPath,target:n.target});if(t)return t}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function Fe(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||V(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>ne(e,n)&&v(e)&&e.kind===`simulator`&&e.booted===!0);if(a.length<2)return;let{findIosSimulatorInstalledApp:o}=await import(`./apps.js`).then(e=>e.t),s=(await Promise.all(a.map(async e=>await o(e,i)?e:void 0))).filter(e=>e!==void 0);if(s.length===1)return s[0];throw s.length===0?new e(`APP_NOT_INSTALLED`,`No booted iOS simulator has ${i} installed`,{appTarget:i,...B(a),hint:`Install the app on a booted simulator, or pass --udid to select the intended device explicitly.`}):new e(`AMBIGUOUS_MATCH`,`Multiple booted iOS simulators have ${i} installed`,{appTarget:i,...B(s),hint:`Pass --udid to select the intended simulator explicitly.`})}function B(e){return{devices:e.map(e=>({id:e.id,name:e.name}))}}async function Ie(e,t,n){try{return await y(e,t,n)}catch(e){if(Le(e,t))return;throw e}}function Le(t,n){return!V(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function Re(e,t){return!V(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function V(e){return!!(e.udid||e.serial||e.deviceName)}async function ze(e,t={}){let n=Be(e),{iosSimulatorSetPath:r,...i}=n,a=Ye(n,t),o={simulatorSetPath:r,allowStoppedAndroidAvdPlaceholders:t.allowStoppedAndroidAvdPlaceholders},s={platform:n.platform,target:e.target,cacheHit:!1};return await fe(`resolve_target_device`,async()=>{let e=Je(a);if(e)return s.cacheHit=!0,e;let c=await Ge(n);if(c)return qe(i)?H(a,await z(c,i,{simulatorSetPath:r,allowLocalSimulatorFallback:n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):H(a,await y(c,i,o));let l=await T(n);return qe(i)?H(a,await z(l,i,{simulatorSetPath:r,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):H(a,await y(l,i,o))},s)}function Be(t){let n=t.platform;if(t.target&&!n)throw new e(`INVALID_ARGS`,`Device target selector requires --platform. Use --platform ios|macos|android|vega|linux|apple with --target mobile|tv|desktop.`);let r=ee({simulatorSetPath:ge(t.iosSimulatorDeviceSet),platform:n,target:t.target}),i=he(t.androidDeviceAllowlist);return{platform:n,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial,leaseId:t.leaseId,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId,iosSimulatorSetPath:r,androidSerialAllowlist:i?Array.from(i).sort():void 0}}async function Ve(e){return L.getStore()?await e():await L.run(new Map,e)}async function He(e,t){return e?await R.run(e,t):await t()}async function Ue(e,t){return await He(e,async()=>await Ve(t))}async function We(e){return await Ge(e)??await T(e)}async function Ge(e){let t=R.getStore();if(!t)return null;let n=await t(e);return n==null?null:n.map(e=>({...e}))}function Ke(e){return _(e.platform)}function qe(e){return Ke(e)}function Je(e){let t=L.getStore()?.get(e);if(t)return{...t}}function H(e,t){return L.getStore()?.set(e,{...t}),t}function Ye(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}D();const Xe={device:!0},Ze=[`open`,`close`],Qe=[`record`],$e=[`audio`,`find`,`get`,`is`,`network`,`screenshot`,`snapshot`,`wait`],et=[`click`,`fill`,`focus`,`press`,`scroll`,`type`],tt=[`viewport`],nt=new Set([...Ze,...Qe,...$e,...et,...tt]),U=rt(f(p));function rt(e){let t={};for(let[n,r]of Object.entries(e))t[n]=nt.has(n)?{...r,web:Xe}:r;for(let t of nt)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function it(e,t){let n=U[e];if(!n)return!0;let r=E(t.platform);if(!r)return!1;let i=n[r.capability.bucket];if(!i)return!1;let a=r.capability.supportsByDefault?.[e];return a&&!a(t)?!1:i[t.kind??`unknown`]===!0}function at(e,t){return E(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function ot(){return Object.keys(U).sort()}function st(e){let t=U[e];if(!t)return[];let n=[`apple`,`android`,`vega`,`linux`,`web`],r=[];for(let e of n){let n=t[e];n&&Object.values(n).some(e=>e===!0)&&r.push(e)}return r}function ct(e,t){if(e.intent===`drag`){lt(e,t);return}if(t.platform===`web`||t.appleOs===`watchos`)throw G(e,W(e,t));if(ut(e)){dt(e,t);return}if(t.appleOs===`visionos`)throw G(e,W(e,t));if(e.intent===`fling`&&`direction`in e&&t.platform===`linux`)throw G(e,`gesture fling is not supported on Linux`)}function lt(e,t){let n=t.platform===`android`&&t.target!==`tv`,r=t.platform===`apple`&&(t.appleOs===`ios`||t.appleOs===`ipados`||t.appleOs===void 0&&t.target!==`desktop`&&t.target!==`tv`);if(!(n||r))throw G(e,W(e,t),`Target-authored drag requires an adapter that preserves source hold, timed movement, and destination hold; it is supported on Android touch devices and iOS/iPadOS.`)}function ut(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function dt(e,t){if(t.platform===`android`){if(t.target!==`tv`)return;throw G(e,`gesture ${e.intent} is not supported on Android TV`,`Android TV has no touch input — this gesture is supported on Android phones, tablets, and the iOS simulator only.`)}if(t.platform!==`apple`)throw G(e,W(e,t));le(t,e.intent)}function W(e,t){return`gesture ${e.intent} is not supported on ${t.appleOs??t.platform}`}function G(t,n,r){return new e(`UNSUPPORTED_OPERATION`,n,{gesture:t.intent,...r?{hint:r}:{}})}const ft=`No active session. Run open first.`;function pt(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function mt(){return pt(`SESSION_NOT_FOUND`,ft)}function ht(e,t,n){if(it(e,t))return null;let r=n?.hint?at(e,t):void 0;return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:n?.message??`${e} is not supported on this device`,...r?{hint:r}:{}}}}const gt=/^[A-Za-z0-9_.:-]{1,64}$/,_t=8*1024,vt=4*1024;function yt(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!gt.test(n))throw new e(`INVALID_ARGS`,`Invalid trigger-app-event event name: ${n}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});if(t.length>2)throw new e(`INVALID_ARGS`,`trigger-app-event accepts at most two arguments: <event> [payloadJson]`);return{eventName:n,payload:xt(r,n)}}function bt(t,n,r){let i=g(t),a=St(t);if(!a)throw new e(`UNSUPPORTED_OPERATION`,`No app event URL template configured for ${i}.`,{hint:`Set AGENT_DEVICE_${i.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):``,s=a.replaceAll(`{event}`,encodeURIComponent(n)).replaceAll(`{payload}`,encodeURIComponent(o)).replaceAll(`{platform}`,encodeURIComponent(i));if(s.length>vt)throw new e(`INVALID_ARGS`,`trigger-app-event URL exceeds maximum supported length`,{hint:`Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.`,length:s.length,maxLength:vt});return s}function xt(t,n){if(t)try{let r=JSON.parse(t);if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,`utf8`)>_t)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${_t} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function St(e){return((v(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:h(e)?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE)?.trim()||void 0}const Ct=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function wt(e,t){return _(e.platform)&&t>1}function Tt(e,t,n=2e4){if(e.length===0)return[];let r=t>0?t:e.length,i=[],a=[],o=0;for(let t of e){let e=(t.durationMs??0)+(t.pauseMs??0)+250,s=a.length>0&&o+e>n,c=a.length>=r;(s||c)&&(i.push(a),a=[],o=0),a.push(t),o+=e}return a.length>0&&i.push(a),i}function Et(e,t){if(t<=0)return[0,0];let[n,r]=Ct[e%Ct.length];return[n*t,r*t]}async function Dt(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await me(t)}async function Ot(e,t){let{x:n,y:r}=K(t,`longpress requires x y [durationMs]`,{hint:`Direct platform longpress requires coordinates. In an open daemon session, use agent-device longpress @ref|selector [durationMs]; otherwise run snapshot -i, use the target rect center as x y, then retry longpress x y durationMs.`}),i=t[2]?Number(t[2]):void 0;return await e.longPress(n,r,i),{x:n,y:r,durationMs:i,...x(`Long pressed (${n}, ${r})`)}}async function kt(e,t){let{x:n,y:r}=K(t,`focus requires x y`);return await e.focus(n,r),{x:n,y:r,...x(`Focused (${n}, ${r})`)}}async function At(t,n,r){let i=tn(n);if(i)throw new e(`INVALID_ARGS`,`type does not accept a target ref like "${i}"`,{hint:`Use fill ${i} "text" to target that field, or press ${i} then type "text" to append.`});let a=n.join(` `);if(!a)throw new e(`INVALID_ARGS`,`type requires text`);let o=C(r?.delayMs??0,`delay-ms`,0,1e4),s=(await t.type(a,o))?.textEntryRoute;return{...s===void 0?{}:{textEntryRoute:s},text:a,delayMs:o,...x(Y(`Typed`,a))}}async function jt(t,n,r){if(r?.directElementSelector)return await Mt(t,r.directElementSelector,n,r);let i=Number(n[0]),a=Number(n[1]),o=n.slice(2).join(` `);if(Number.isNaN(i)||Number.isNaN(a)||!o)throw new e(`INVALID_ARGS`,`fill requires x y text`);let s=C(r?.delayMs??0,`delay-ms`,0,1e4);return{x:i,y:a,text:o,delayMs:s,...(await t.fill(i,a,o,s,{allowNonHittableCoordinateFallback:r?.allowNonHittableCoordinateFallback===!0}))?.maestroNonHittableCoordinateFallbackUsed===!0?{maestroNonHittableCoordinateFallbackUsed:!0}:{},...x(Y(`Filled`,o))}}async function Mt(t,n,r,i){if(!t.fillElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector fill is not supported`);let a=r.join(` `);if(!a)throw new e(`INVALID_ARGS`,`fill requires text`);let o=C(i.delayMs??0,`delay-ms`,0,1e4),s=await t.fillElementSelector(n,a,o);return{selector:n.raw,text:a,delayMs:o,...s??{},...x(Y(`Filled`,a))}}async function Nt(e,t,n,r){if(r?.directElementSelector&&v(e))return await Pt(t,r.directElementSelector);let{x:i,y:a}=K(n,`press requires x y`);if(h(e)&&r?.surface&&r.surface!==`app`)return await Ft(i,a,r);let o=d(r);if(o!==`primary`)return await It(e,i,a,o,r);let s=zt(r);return Bt(s),wt(e,s.count)?await Ht(e,i,a,s,r):await Gt(t,i,a,s)}async function Pt(t,n){if(!t.tapElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector tap is not supported`);let r=await t.tapElementSelector(n),i=r?.maestroNonHittableCoordinateFallbackUsed===!0;return{selector:n.raw,...r??{},...x(i?l:`Tapped ${n.raw}`)}}function K(t,n,r){let i=Number(t[0]),a=Number(t[1]);if(Number.isNaN(i)||Number.isNaN(a))throw new e(`INVALID_ARGS`,n,r);return{x:i,y:a}}async function Ft(t,n,r){let i=d(r);if(i!==`primary`)throw new e(`UNSUPPORTED_OPERATION`,`${i} click is not supported on macOS ${r.surface} sessions.`);let{runMacOsPressAction:a}=await import(`./helper.js`).then(e=>e.t);return await a(t,n,{bundleId:r.appBundleId,surface:r.surface}),{x:t,y:n,...x(J({x:t,y:n}))}}async function It(e,t,n,r,i){if(Lt(e,r,i),e.platform===`linux`)return await Rt(t,n,r);let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},Kt(i)),{x:t,y:n,button:r,...x(J({x:t,y:n,button:r}))}}function Lt(e,t,n){let r=o({commandLabel:`click`,platform:g(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function Rt(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}return{x:e,y:t,button:n,...x(J({x:e,y:t,button:n}))}}function zt(e){return{count:q(e?.count,1,`count`,1,200),intervalMs:q(e?.intervalMs,0,`interval-ms`,0,1e4),holdMs:q(e?.holdMs,0,`hold-ms`,0,1e4),jitterPx:q(e?.jitterPx,0,`jitter-px`,0,100),doubleTap:!!e?.doubleTap}}function q(e,t,n,r,i){return C(e===void 0?t:e,n,r,i)}function Bt({doubleTap:t,holdMs:n,jitterPx:r}){if(t&&n>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with hold-ms`);if(t&&r>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with jitter-px`)}async function Vt(e,t,n){let{runAppleRunnerCommand:r}=await import(`./runner-client.js`).then(e=>e.o),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=Tt(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),Kt(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Wt(e,f)}u+=s.completedSteps,d.push(...s.results),f+=t.length}return{...c??{},completedSteps:u,sequenceResults:d,...l?.gestureEndUptimeMs===void 0?{}:{gestureEndUptimeMs:l.gestureEndUptimeMs}}}async function Ht(e,t,n,r,i){let a=await Vt(e,Ut(e,t,n,r),i);return{x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,timingMode:`runner-sequence`,...a,...x(J({x:t,y:n}))}}function Ut(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&v(e)&&!te(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=Et(o,r.jitterPx),l=o===r.count-1;return{kind:i,x:t+s,y:n+c,...a?{synthesized:!0}:{},...r.holdMs>0?{durationMs:r.holdMs}:{},...!l&&r.intervalMs>0?{pauseMs:r.intervalMs}:{}}})}function Wt(t,n){if(n===0||!(t instanceof e)||!t.details)return t;let r=t.details.failedStepIndex;if(typeof r!=`number`)return t;let i=t.details.completedSteps;return new e(t.code,t.message,{...t.details,failedStepIndex:r+n,chunkStepIndex:r,...typeof i==`number`?{completedSteps:n+i}:{}},t.cause)}async function Gt(e,t,n,r){let i;return await Dt(r.count,r.intervalMs,async a=>{let[o,s]=Et(a,r.jitterPx),c=t+o,l=n+s;if(r.doubleTap){let t=await e.doubleTap(c,l);i??=t??void 0;return}if(r.holdMs>0){let t=await e.longPress(c,l,r.holdMs);i??=t??void 0}else{let t=await e.tap(c,l);i??=t??void 0}}),S({x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,...i},J({x:t,y:n}))}function Kt(e){return{verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,requestId:e?.requestId,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir}}async function qt(t,n,r){let i=n[0],a=n[1]?Number(n[1]):void 0,o=r?.pixels,s=r?.durationMs;if(!i)throw new e(`INVALID_ARGS`,`scroll requires direction`);Jt(a,o,s);let c=$t(i),l={amount:a,pixels:o,durationMs:s},{interactionResult:u,completedPasses:d}=await Xt(t,r,c,l);return S(Zt(c,l,d,u),ae(c.direction,c.edge,d,a,o))}function Jt(e,n,r){Yt(e),t(r),i({amount:e,pixels:n})}function Yt(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Xt(e,t,n,r){if(n.edge){let i=n.edge,a=await se({edge:i,captureState:async n=>await Qt(e,t,i,n),scroll:async()=>await e.scroll(n.direction,r)});return{interactionResult:a.result??{},completedPasses:a.passes}}return{interactionResult:await e.scroll(n.direction,r)??{},completedPasses:1}}function Zt(e,t,n,r){let i=u(r);return{direction:e.direction,...e.edge?{edge:e.edge,passes:n}:{},...t.amount===void 0?{}:{amount:t.amount},...t.pixels===void 0?{}:{pixels:t.pixels},...i===void 0?{}:{durationMs:i},...r}}async function Qt(t,n,r,i){if(typeof t.snapshot!=`function`)throw new e(`UNSUPPORTED_OPERATION`,`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let a=t.snapshot;return await ie({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function $t(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:c(e)}}async function en(e,t,n){let{x:r,y:i}=K(t,`read requires x y`);if(e.platform===`android`){let{readAndroidTextAtPoint:t}=await import(`./input-actions.js`).then(e=>e.s);return{action:`read`,text:await t(e,r,i)??``}}if(e.platform===`linux`){let{readLinuxTextAtPoint:e}=await import(`./snapshot.js`).then(e=>e.n);return{action:`read`,text:await e(r,i,n?.surface)}}if(h(e)&&n?.surface&&n.surface!==`app`){let{runMacOsReadTextAction:e}=await import(`./helper.js`).then(e=>e.t);return{action:`read`,text:(await e(r,i,{bundleId:n.appBundleId,surface:n.surface})).text}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(e,{command:`readText`,x:r,y:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId,iosXctestrunFile:n?.iosXctestrunFile,iosXctestDerivedDataPath:n?.iosXctestDerivedDataPath,iosXctestEnvDir:n?.iosXctestEnvDir});return{action:`read`,text:typeof o.text==`string`?o.text:typeof o.message==`string`?o.message:``}}function tn(e){return de(e[0])}function J(e){return e.button&&e.button!==`primary`?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function Y(e,t){return`${e} ${Array.from(t).length} chars`}function nn(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)}function X(t,n){let r=n?.subject??`Payload`,i=t.trim();if(!i)throw new e(`INVALID_ARGS`,`${r} cannot be empty`);let a=n?.expandPath?n.expandPath(i,n.cwd):i;try{if(!be.statSync(a).isFile())throw new e(`INVALID_ARGS`,`${r} path is not a file: ${a}`);return{kind:`file`,path:a}}catch(t){if(t instanceof e)throw t;let n=t.code;if(n===`EACCES`||n===`EPERM`)throw new e(`INVALID_ARGS`,`${r} file is not readable: ${a}`);if(n&&n!==`ENOENT`)throw new e(`COMMAND_FAILED`,`Unable to read ${r} file: ${a}`,{cause:String(t)})}if(nn(i))return{kind:`inline`,text:i};throw new e(`INVALID_ARGS`,`${r} file not found: ${a}`)}async function rn(t){let n=X(t,{subject:`Push payload`}),r=n.kind===`inline`?n.text:await an(n.path);try{let t=JSON.parse(r);if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`push payload must be a JSON object`);return t}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid push payload JSON: ${t}`)}}async function an(t){try{return await k.readFile(t,`utf8`)}catch(n){let r=n.code;throw r===`ENOENT`?new e(`INVALID_ARGS`,`Push payload file not found: ${t}`):r===`EISDIR`?new e(`INVALID_ARGS`,`Push payload path is not a file: ${t}`):r===`EACCES`||r===`EPERM`?new e(`INVALID_ARGS`,`Push payload file is not readable: ${t}`):new e(`COMMAND_FAILED`,`Unable to read push payload file: ${t}`,{cause:String(n)})}}D();async function Z(t,n){if(j(t)){let r=Ce(t,n);if(r)return r;throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime does not have an active interactor for this device.`,{deviceId:t.id,platform:g(t)})}return await ve(t.platform).createInteractor(t,n)}async function on(e,t,n,r,i){let a=Q(i),o=await Z(e,a);return w({level:`debug`,phase:`platform_command_prepare`,data:{command:t,platform:e.platform,kind:e.kind}}),await fe(`platform_command`,async()=>await un(e,o,t,n,r,i,a),{command:t,platform:e.platform})}async function sn(t,n,r){let i=await Z(t,Q(r));if(!i.performGesture)throw new e(`UNSUPPORTED_OPERATION`,`Gesture execution is unavailable`);return await i.performGesture(n)}async function cn(e,t){return await(await Z(e,Q(t))).gestureViewport?.()}function Q(e){return{requestId:e?.requestId,signal:e?.signal,appBundleId:e?.appBundleId,verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir,runnerLeaseContext:e?.runnerLeaseContext}}const ln={open:({device:e,interactor:t,positionals:n,context:r})=>dn(e,t,n,r),close:async({device:e,interactor:t,positionals:n})=>{let r=n[0];return r?(await t.close(r),{app:r,...x(`Closed: ${r}`)}):(e.platform===`web`&&await t.close(``),{closed:`session`,...x(`Closed session`)})},press:({device:e,interactor:t,positionals:n,context:r})=>Nt(e,t,n,r),longpress:({interactor:e,positionals:t})=>Ot(e,t),focus:({interactor:e,positionals:t})=>kt(e,t),type:({interactor:e,positionals:t,context:n})=>At(e,t,n),fill:({interactor:e,positionals:t,context:n})=>jt(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>qt(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>fn(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>pn(e,t,n,r),viewport:({interactor:e,positionals:t})=>mn(e,t),back:async({interactor:e,context:t})=>(await e.back(t?.backMode),{action:`back`,mode:t?.backMode??`in-app`,...x(`Back`)}),home:async({interactor:e})=>(await e.home(),{action:`home`,...x(`Home`)}),orientation:async({interactor:e,positionals:t})=>{let n=ue(t[0]),r=(await e.setOrientation(n))?.orientation??n;return{action:`orientation`,orientation:r,...x(`Rotated to ${r}`)}},"app-switcher":async({interactor:e})=>(await e.appSwitcher(),{action:`app-switcher`,...x(`Opened app switcher`)}),clipboard:({interactor:e,positionals:t})=>hn(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>_n(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>gn(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>xn(e,t,n,r),push:({device:e,positionals:t,context:n})=>Sn(e,t,n),snapshot:({interactor:e,context:t})=>Cn(e,t),read:({device:e,positionals:t,context:n})=>en(e,t,n)};async function un(t,n,r,i,a,o,s){let c=Object.hasOwn(ln,r)?ln[r]:void 0;if(!c)throw new e(`INVALID_ARGS`,`Unknown command: ${r}`);return await c({device:t,interactor:n,positionals:i,outPath:a,context:o,runnerCtx:s})}async function dn(t,n,r,i){let a=r[0],o=r[1],s=i?.launchConsole,c=i?.launchArgs;if(r.length>2)throw new e(`INVALID_ARGS`,`open accepts at most two arguments: <app|url> [url]`);if(!a){if(s)throw new e(`INVALID_ARGS`,`--launch-console requires an app target`);if(c&&c.length>0)throw new e(`INVALID_ARGS`,`--launch-args requires an app target`);return await n.openDevice(),{app:null,...x(`Opened device`)}}if(s&&(!v(t)||t.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,re);if(t.platform===`linux`&&c&&c.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on Linux.`);if(o!==void 0){if(m(a))throw new e(`INVALID_ARGS`,`open <app> <url> requires an app target as the first argument`);if(!m(o))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(s)throw new e(`INVALID_ARGS`,b);return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchArgs:c,terminateRunningApp:i?.terminateRunningApp,url:o}),{app:a,url:o,...x(`Opened: ${a}`)}}if(s&&m(a))throw new e(`INVALID_ARGS`,b);if(i?.clearAppState){if(m(a))throw new e(`INVALID_ARGS`,`Clearing app state requires an app target, not a deep link.`);await n.setSetting(`clear-app-state`,`clear`,a)}return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchConsole:s,launchArgs:c,terminateRunningApp:i?.terminateRunningApp}),{app:a,...s?{launchConsole:s}:{},...x(`Opened: ${a}`)}}async function fn(e,t,n,r){let{eventName:i,payload:a}=yt(n),o=bt(e,i,a);return await t.open(o,{appBundleId:r?.appBundleId}),{event:i,eventUrl:o,transport:`deep-link`,...x(`Triggered app event: ${i}`)}}async function pn(e,t,n,i){let a=t[0]??n??`./screenshot-${Date.now()}.png`;await k.mkdir(ye.dirname(a),{recursive:!0});let o=r(i);return await e.screenshot(a,{appBundleId:i?.appBundleId,pixelDensity:o.pixelDensity,fullscreen:o.fullscreen,normalizeStatusBar:o.normalizeStatusBar,stabilize:o.stabilize,surface:i?.surface,skipIosSimulatorBootCheck:i?.skipIosSimulatorBootCheck,captureBackend:i?.screenshotCaptureBackend}),{path:a,...x(`Saved screenshot: ${a}`)}}async function mn(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=oe(n[0],`width`),i=oe(n[1],`height`);if(!t.setViewport)throw new e(`UNSUPPORTED_OPERATION`,`viewport is not supported by this backend`);return await t.setViewport(r,i),{width:r,height:i,...x(`Viewport set: ${r}x${i}`)}}async function hn(t,n){let r=(n[0]??``).toLowerCase();if(r!==`read`&&r!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write`);if(r===`read`){if(n.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments`);return{action:r,text:await t.readClipboard()}}if(n.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text (use "" to clear clipboard)`);let i=n.slice(1).join(` `);return await t.writeClipboard(i),{action:r,textLength:Array.from(i).length,...x(`Clipboard updated`)}}async function gn(t,n,r,i){if(t.target!==`tv`)throw new e(`UNSUPPORTED_OPERATION`,`tv-remote is supported only on TV targets`,{hint:`Select an Android TV, tvOS, or Vega OS target with --target tv.`});if(r.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button`);let o=a(r[0]),s=i?.durationMs===void 0?void 0:C(i.durationMs,`durationMs`,0,1e4);return await n.tvRemote(o,s),{action:`tv-remote`,button:o,...s===void 0?{}:{durationMs:s},...x(`Pressed TV remote ${o}`)}}async function _n(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!ce(a))throw new e(`INVALID_ARGS`,`keyboard requires a subcommand: status, get, dismiss, enter, or return`);if(n.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one subcommand argument`);if(t.platform===`android`)return await vn(t,a);if(v(t))return await yn(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android and iOS`)}async function vn(e,t){if(t===`enter`||t===`return`){let{pressAndroidEnter:t}=await import(`./input-actions.js`).then(e=>e.s);return await t(e),{platform:`android`,action:`enter`,...x(`Keyboard enter pressed`)}}if(t===`dismiss`){let{dismissAndroidKeyboard:t}=await import(`./device-input-state.js`).then(e=>e.t),n=await t(e);return{platform:`android`,action:`dismiss`,attempts:n.attempts,wasVisible:n.wasVisible,dismissed:n.dismissed,visible:n.visible,inputType:n.inputType,type:n.type,inputMethodPackage:n.inputMethodPackage,focusedPackage:n.focusedPackage,focusedResourceId:n.focusedResourceId,inputOwner:n.inputOwner}}let{getAndroidKeyboardState:n}=await import(`./device-input-state.js`).then(e=>e.t),r=await n(e);return{platform:`android`,action:`status`,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}async function yn(t,n,r,i){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is currently supported only on Android; use keyboard dismiss or enter on iOS`);if(n===`enter`||n===`return`){let{runAppleRunnerCommand:e}=await import(`./runner-client.js`).then(e=>e.o),n=await e(t,{command:`keyboardReturn`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`enter`,visible:n.visible,wasVisible:n.wasVisible,...x(`Keyboard enter pressed`)}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(t,{command:`keyboardDismiss`,appBundleId:r?.appBundleId},i),s=typeof o.keyboardDismissMechanism==`string`?o.keyboardDismissMechanism:void 0;return{platform:`ios`,action:`dismiss`,wasVisible:o.wasVisible,dismissed:o.dismissed,visible:o.visible,mechanism:s,...x(bn(o.dismissed===!0,s))}}function bn(e,t){return e?t===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`:`Keyboard already hidden`}async function xn(t,n,r,i){let[a,o,c,l]=r;if(!a||!o&&a!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(a===`clear-app-state`){let r=(o===`clear`?c:o)??i?.appBundleId;if(!r)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);w({level:`debug`,phase:`settings_apply`,data:{setting:a,state:`clear`,appBundleId:r,platform:t.platform}});let s=await n.setSetting(a,`clear`,r);return s&&typeof s==`object`?S({setting:a,state:`clear`,...s},$(s)??`Cleared user data for ${r}`):{setting:a,state:`clear`,...x(`Cleared user data for ${r}`)}}if(!o)throw new e(`INVALID_ARGS`,`settings requires setting state`);let u=a===`location`&&o===`set`,d=(a===`permission`||u?r[4]:r[2])??i?.appBundleId,f=a===`permission`?{permissionTarget:c,permissionMode:l}:u?{latitude:s(c,`latitude`),longitude:s(l,`longitude`)}:void 0;w({level:`debug`,phase:`settings_apply`,data:u?{setting:a,state:o,latitude:c,longitude:l,platform:t.platform}:a===`permission`?{setting:a,state:o,permissionTarget:c,permissionMode:l,platform:t.platform}:{setting:a,state:o,appBundleId:d,platform:t.platform}});let p=await n.setSetting(a,o,d,f);return p&&typeof p==`object`?S({setting:a,state:o,...p},$(p)??`Updated setting: ${a}`):{setting:a,state:o,...x(`Updated setting: ${a}`)}}async function Sn(t,n,r){let i=n[0]?.trim(),a=n[1]?.trim();if(!i||!a)throw new e(`INVALID_ARGS`,`push requires <bundle|package> <payload.json|inline-json>`);let o=await rn(a);if(v(t)){let{pushIosNotification:e}=await import(`./apps.js`).then(e=>e.t);return await e(t,i,o),{platform:`ios`,bundleId:i,...x(`Pushed notification to ${i}`)}}let{pushAndroidNotification:s}=await import(`./notifications.js`),c=await s(t,i,o);return{platform:`android`,package:i,action:c.action,extrasCount:c.extrasCount,...x(`Pushed notification to ${i}`)}}async function Cn(e,t){let n=t??{};return await e.snapshot({appBundleId:n.appBundleId,signal:n.signal,interactiveOnly:n.snapshotInteractiveOnly,preferredBackend:n.snapshotPreferredBackend,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw,includeRects:n.snapshotIncludeRects,includeHiddenContentHints:n.snapshotIncludeHiddenContentHints,surface:n.surface})}function $(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}function wn(e,t,r,i,a,o){return{requestId:a??pe().requestId,appBundleId:r,runnerLeaseContext:_e({meta:o}),activity:t?.activity,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,clearAppState:t?.clearAppState,verbose:t?.verbose,logPath:e,traceLogPath:i,iosXctestrunFile:t?.iosXctestrunFile,iosXctestDerivedDataPath:t?.iosXctestDerivedDataPath,iosXctestEnvDir:t?.iosXctestEnvDir,screenshotCaptureBackend:t?.maestro?.screenshotCaptureBackend,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotPreferredBackend:t?.snapshotPreferredBackend,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,snapshotIncludeHiddenContentHints:t?.snapshotIncludeHiddenContentHints,...n(t),count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,durationMs:t?.durationMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:d(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}export{j as S,Ue as _,X as a,we as b,mt as c,ot as d,ct as f,ze as g,We as h,cn as i,ht as l,Be as m,on as n,ft as o,st as p,sn as r,pt as s,wn as t,it as u,Ee as v,Te as x,De as y};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{pn as t}from"./sdk-batch-runner.js";import{h as n,v as r}from"./sdk-android-adb.js";import i from"node:path";import a from"node:fs/promises";const o=/^[0-9a-fA-F-]{32,36}$/;function s(e){if(!(!e||!o.test(e)))return e.replaceAll(`-`,``).toUpperCase()}function c(e,t){return`${e.uuid}:${l(t)}`}function l(e){return`0x${e.toString(16)}`}function u(e){return typeof e==`string`&&e.length>0?e:void 0}function d(...e){for(let t of e){let e=u(t);if(e)return e}}function f(e){let t=e.filter(e=>!!e);return t.length>0?t.join(` `):void 0}function p(e){try{let n=JSON.parse(e);return t(n)?n:null}catch{return null}}function m(e){if(typeof e==`number`&&Number.isSafeInteger(e))return e;if(typeof e==`string`){let t=e.startsWith(`0x`)?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function h(e,t,n){if(!Object.hasOwn(e,t))return;let r=m(e[t]);if(r!==void 0)return r;v(n,t)}function g(e,t,n){if(!Object.hasOwn(e,t))return;let r=_(e[t]);if(r!==void 0)return r;v(n,t)}function _(e){if(typeof e==`bigint`)return e;if(typeof e==`number`&&Number.isSafeInteger(e)||typeof e==`string`&&/^(?:0x[0-9a-fA-F]+|\d+)$/.test(e))return BigInt(e)}function v(t,n){throw new e(`INVALID_ARGS`,`Invalid ${t} numeric field: ${n}`,{hint:`Crash artifact numeric fields must be integer numbers or integer numeric strings.`})}function y(e){return e.length===1?e[0]:void 0}function b(e){return[...new Set(e)]}function x(e){let t=e.match(/^(.*) \+ (\d+)$/);return t?{symbol:t[1],location:Number(t[2])}:{symbol:e}}const S=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;function ee(e){return te(e)??w(e)}function te(e){let t=ne(e);if(!t)return null;let n=(Array.isArray(t.payload.usedImages)?t.payload.usedImages:[]).flatMap((e,t)=>C(e,t));if(n.length===0)return null;let r=re(Array.isArray(t.payload.threads)?t.payload.threads:[],n);return{format:`ips`,images:n,addresses:r.map(({frame:e,...t})=>t),document:t,frameMatches:r,write:e=>oe(t,r,e)}}function ne(e){let t=p(e);if(t)return{payload:t};let n=e.indexOf(`
|
|
2
2
|
`);if(n===-1)return null;let r=e.slice(0,n),i=p(e.slice(n+1));return i?{header:r,payload:i}:null}function re(e,t){let n=new Map(t.map(e=>[e.index,e]));return e.flatMap((e,t)=>ie(e).flatMap((e,r)=>ae(e,n,t,r)))}function ie(e){return!t(e)||!Array.isArray(e.frames)?[]:e.frames.filter(t)}function ae(e,t,n,r){let i=h(e,`imageIndex`,`IPS frame`),a=g(e,`imageOffset`,`IPS frame`);if(i===void 0||a===void 0)return[];let o=t.get(i);return o?[{frame:e,frameIndex:r,threadIndex:n,image:o,address:o.base+a}]:[]}function oe(e,t,n){for(let e of t){let t=n.get(c(e.image,e.address))?.text;t&&se(e.frame,t)}e.payload.agentDeviceSymbolication={tool:`agent-device debug symbols`,symbolicatedFrames:[...n.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}\n`;return e.header?`${e.header}\n${r}`:r}function se(e,t){let n=x(t);e.symbol=n.symbol,n.location!==void 0&&(e.symbolLocation=n.location)}function C(e,n){if(!t(e))return[];let r=s(u(e.uuid)),a=g(e,`base`,`IPS usedImages`);if(!r||a===void 0)return[];let o=u(e.path);return[{index:n,name:u(e.name)??(o?i.basename(o):`image-${n}`),uuid:r,arch:u(e.arch),base:a,path:o}]}function w(e){let t=e.split(`
|
|
3
3
|
`),n=T(t);if(n.length===0)return null;let r=O(t,n);return{format:`text`,images:n,addresses:r,lines:t,frameMatches:r,write(e){let n=new Map(r.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let i=n.get(r);if(!i)return t;let a=e.get(c(i.image,i.address))?.text;return!a||t.includes(a)?t:`${t} // ${a}`}).join(`
|
|
4
4
|
`)}}}function T(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=E(r);e&&t.push(e)}return t}function E(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=s(t[4]);if(!n)return null;let r=D(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function D(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&S.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let a=i.basename(t);return{name:e.startsWith(a)?a:e}}function O(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=k(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function k(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=A(t,r,i);return a?{image:a,address:i}:null}function A(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>j(e,n))??y(r)}function j(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const M=1e4;async function N(e){return e.dsym&&e.searchPath?[H(e.cwd,e.dsym),...await P(H(e.cwd,e.searchPath))]:e.dsym?[H(e.cwd,e.dsym)]:e.searchPath?await P(H(e.cwd,e.searchPath)):[]}async function P(t){let n=[],r=0;async function o(s){if(n.length>=200)return;if(r+=1,r>M)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:M,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await F(s,t)).isDirectory()){s===t&&I(t);return}if(s.endsWith(`.dSYM`)){n.push(s);return}let c=await a.readdir(s,{withFileTypes:!0});for(let e of c)e.isDirectory()&&await o(i.join(s,e.name))}return await o(t),n}async function F(t,n){try{return await a.stat(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function I(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function L(t,n){let r=(await Promise.all(b(t).map(e=>R(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function R(e,t){return await z(e),B(e,n(await r(t,[`--uuid`,e],{timeoutMs:15e3,allowFailure:!0}),`Failed to inspect dSYM UUIDs: ${e}`,{hint:`Verify the dSYM bundle is valid and readable.`}).stdout)}async function z(t){if(!((await a.stat(t).catch(()=>null))?.isDirectory()&&t.endsWith(`.dSYM`)))throw new e(`INVALID_ARGS`,`Not a .dSYM bundle: ${t}`,{hint:`Pass the .dSYM bundle path, not the DWARF executable inside it.`})}function B(e,t){return t.split(`
|
package/dist/src/find.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{u as e}from"./sdk-contracts.js";import{At as t,Ft as n,I as r,Mt as i,R as a,Xt as o,jt as s}from"./sdk-batch-runner.js";import{H as c,I as l,V as u,W as d,bt as f,dn as p,fn as m}from"./viewport-dimension.js";import"./screenshot-result.js";import{c as h,n as g,s as _,t as v}from"./context.js";import{Kt as y,m as b,nn as x}from"./internal/daemon.js";import{o as S,s as C,t as w}from"./selector-runtime.js";function T(e){return e.kind===`ambiguous`?e.matchedNodes:e.kind===`resolved`?[e.resolution.node]:[]}function E(e){if(e.ambiguity!==`reject-candidates`)throw Error(`find's resolution policy must reject candidates, got "${e.ambiguity}"`)}async function D(e){let{req:r,sessionName:a,logPath:o,sessionStore:s,invoke:c}=e,u=r.command;if(u!==`find`)return null;let d=t(r.positionals??[],r.flags);if(!d.ok)return _(d.code,d.message);let{locator:f,query:p,action:m,value:g}=d.parsed;if(r.flags?.record&&!i(m))return _(`INVALID_ARGS`,`find ${m} is a mutating action and is always recorded; --record only applies to a read-only find (exists, wait, list, get text, get attrs).`);let v=await w({req:r,sessionName:a,logPath:o,sessionStore:s});if(v)return v;let y=s.get(a);if(!y)return h();let b=y.device,x=n(f,p),S=k({device:b,session:y,req:r,logPath:o,locator:f,query:p,sessionStore:s,sessionName:a}),T={req:r,sessionName:a,logPath:o,sessionStore:s,invoke:c,session:y,device:b,command:u,locator:f,query:p,publicFlags:J(r.flags)},E=await S();if(l(E.snapshotQuality))return A(E.snapshotQuality);let{nodes:D}=E,M=j({nodes:D,locator:f,query:p,selectorExpression:x,flags:r.flags,platform:b.platform});if(!M.ok)return C(M.response,E);let N=M.node,P=R(D,N),F=await O(T,{node:N,resolvedNode:P,ref:`@${P.ref}`,nodes:D,actionFlags:{...r.flags??{},noRecord:!0}},m,g);return F&&C(F,E)}async function O(e,t,n,r){let i={click:()=>V(e,t),fill:()=>H(e,t,r),focus:()=>U(e,t),type:()=>W(e,t,r)}[n];return i?await i():null}function k(e){let{device:t,session:n,req:r,logPath:i,locator:a,query:o}=e,{sessionStore:s,sessionName:c}=e,l=S({device:t,session:n,sessionStore:s,sessionName:c,req:r,logPath:i});return async()=>{let{snapshot:e}=await l.capture({flags:{...r.flags,snapshotInteractiveOnly:!0},recovery:{legacyIosSparse:{query:o,shouldScope:X(a)},sparseVerdictQueryScope:{query:o,shouldScope:X(a)}}});return{nodes:e.nodes,snapshotQuality:e.snapshotQuality,systemSurfaceOnly:e.systemSurfaceOnly}}}function A(e){return _(`COMMAND_FAILED`,`find could not read the current accessibility tree`,{reason:e.reason,hint:`The snapshot quality verdict is sparse. Use screenshot as visual truth, navigate with coordinates if needed, then retry find after reaching a readable screen.`})}function j(e){let{nodes:t,locator:n,query:i,selectorExpression:o,flags:c,platform:l}=e,u=t.filter(e=>!z(e,t[0])),d=a.findAct,f;if(f=o?T(r(u,o,d,{platform:l})):s(u,n,i,{requireRect:d.requireRect}).matches,f=N(f,t),f.length>1){E(d);let e=M(f,c);if(!e)return{ok:!1,response:Y(f,n,i)};f=e}let p=f[0]??null;return p?{ok:!0,node:p}:{ok:!1,response:_(`COMMAND_FAILED`,`find did not match any element`)}}function M(e,t){return t?.findFirst?[e[0]]:t?.findLast?[e[e.length-1]]:null}function N(t,n){let r=n[0]?.rect;if(!r)return t;let i=t.filter(t=>{if(!t.rect)return!1;let n=e(t.rect);return n.x>=r.x&&n.x<=r.x+r.width&&n.y>=r.y&&n.y<=r.y+r.height});return P(i.length>0?i:t,n)}function P(e,t){return e.length<2?e:e.map((e,n)=>({node:e,index:n,score:F(e,t)})).sort((e,t)=>t.score===e.score?L(e.node)-L(t.node)||e.index-t.index:t.score-e.score).map(e=>e.node)}function F(e,t){let n=c(t,e);if(n.reason===`covered`)return 0;let r=I(n,t[0]);return r>0?r:e.hittable&&e.rect&&!z(e,t[0])?3:+!!e.rect}function I(e,t){return e.node.rect?e.reason===`semantic-target`||e.reason===`same-rect-descendant`?4:e.reason===`hittable-ancestor`&&!z(e.node,t)?2:0:0}function L(e){return e.rect?e.rect.width*e.rect.height:1/0}function R(e,t){let n=u(e,t);return z(n,e[0])&&t.rect?t:n}function z(e,t){return!t?.rect||!e.rect||!o(e)?!1:B(e.rect,t.rect)}function B(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}async function V(t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,locator:l,query:u,publicFlags:d}=t,f=await s({token:r.token,session:i,command:`click`,positionals:[n.ref],flags:n.actionFlags,internal:{findResolvedTarget:!0}});if(!f.ok)return f;let h=n.resolvedNode.rect?e(n.resolvedNode.rect):n.node.rect?e(n.node.rect):null,g={ref:n.ref,locator:l,query:u};h&&(g.x=h.x,g.y=h.y);let _=p(f.data)??`Tapped ${n.ref}${h?` (${h.x}, ${h.y})`:``}`;return Object.assign(g,m(_)),b(a,o,r,c,{ref:n.ref,action:`click`,locator:l,query:u},{flags:d}),{ok:!0,data:g}}async function H(e,t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,publicFlags:l}=e;if(!n)return _(`INVALID_ARGS`,`find fill requires text`);let u=await s({token:r.token,session:i,command:`fill`,positionals:[t.ref,n],flags:t.actionFlags,internal:{findResolvedTarget:!0}});return u.ok&&b(a,o,r,c,{ref:t.ref,action:`fill`},{flags:l}),u}async function U(e,t){let n=await G(e,t);return n.ok&&q(e,t,`focus`),n}async function W(e,t,n){let{req:r,device:i,logPath:a,session:o}=e;if(!n)return _(`INVALID_ARGS`,`find type requires text`);let s=await G(e,t);if(!s.ok)return s;y(o);let c=await g(i,`type`,[n],r.flags?.out,{...v(a,r.flags,o.appBundleId,o.trace?.outPath)});return q(e,t,`type`),{ok:!0,data:c??{ref:t.ref}}}async function G(t,n){let{req:r,device:i,logPath:a,session:o}=t,s=K(n,`be focused`);if(s)return s;let c=n.resolvedNode.rect?e(n.resolvedNode.rect):null;return c?(y(o),{ok:!0,data:await g(i,`focus`,[String(c.x),String(c.y)],r.flags?.out,{...v(a,r.flags,o.appBundleId,o.trace?.outPath)})??{ref:n.ref}}):_(`COMMAND_FAILED`,`matched element has no bounds`)}function K(e,t){let n=[e.resolvedNode,e.node].find(d);return n?_(`COMMAND_FAILED`,`Matched element ${e.ref} is covered by another visible element and cannot ${t} safely`,{ref:`@${n.ref}`,interactionBlocked:n.interactionBlocked,hint:`Use a different visible target, scroll it clear of the overlay, or inspect with snapshot/screenshot before retrying.`}):null}function q(e,t,n){let{req:r,sessionStore:i,session:a,command:o,publicFlags:s}=e;b(i,a,r,o,{ref:t.ref,action:n},{flags:s})}function J(e){return{...x(e)??{}}}function Y(e,t,n){let r={matches:e.length,candidates:e.slice(0,5).map(e=>f(e,0,!1))};return _(`AMBIGUOUS_MATCH`,`find matched ${e.length} elements for ${t} "${n}". Use a more specific locator or selector.`,{locator:t,query:n,...r})}function X(e){return e!==`role`}export{Y as buildAmbiguousMatchError,D as handleFindCommands};
|
package/dist/src/finders.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Pt as e}from"./sdk-batch-runner.js";import{t}from"./sdk-finders.js";export{t as findBestMatchesByLocator,e as parseFindArgs};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as e}from"./sdk-batch-runner.js";import{zt as t}from"./internal/daemon.js";import{D as n,T as r}from"./selector-runtime.js";import{t as i}from"./interaction-runtime.js";import{t as a}from"./interaction-snapshot.js";function o(t){if(!e(t.command))return{};let i=n(t.command,t.flags);if(i)return{response:i};let a=r(t.flags);if(!a)return{};let o=t.session.snapshot?.nodes??[];return{observe:async()=>await s(t,a,o)}}async function s(e,n,r){let i=c(e);if(!i)return;let a=await i.interactions.settleObservation({...n,baselineNodes:r,session:e.sessionName,requestId:e.req.meta?.requestId}),o=t(e.session,a);return o===void 0?a:{...a,refsGeneration:o}}function c(e){try{return i({req:e.req,sessionName:e.sessionName,logPath:e.logPath,sessionStore:e.sessionStore,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:a})}catch{return}}export{o as planGenericSettleObservation};
|
package/dist/src/generic.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{a as e}from"./sdk-contracts.js";import{dn as t}from"./viewport-dimension.js";import{i as n,n as r}from"./cli-runner.js";async function i({command:t,positionals:i,flags:s,client:c,debug:l,replayTestReporterRuntime:u}){let{result:d,cliOutput:f}=await r({client:c,command:t,positionals:i,flags:s});if(e(s.responseLevel))return n(s,d,()=>JSON.stringify(d,null,2)),!0;if(f)o(s,f);else{let e=await a(t,s,d,{debug:l,replayTestReporterRuntime:u});e!==0&&process.exit(e)}return!0}function a(e,r,i,a={}){return e===`test`?import(`./reporting.js`).then(({renderReplayTestResponse:e})=>e({suite:i,debug:a.debug,verbose:r.verbose,json:r.json,reporter:r.reporter,reportJunit:r.reportJunit,reporterRuntime:a.replayTestReporterRuntime})):(n(r,i,()=>t(i)),0)}function o(e,t){!e.json&&t.stderr&&process.stderr.write(t.stderr),n(e,e.json?t.jsonData??t.data:t.data,()=>t.text)}export{i as runGenericClientBackedCommand};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{t as
|
|
2
|
-
`||e===`\r`||e===` `}function De(e){return e===`=`||e===`/`||e===`>`||Ee(e)}function Oe(e,t){return e.get(t)??null}function ke(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,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=me(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,hittable:a.clickable??a.focusable,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return Ae(t),He(t),je(t,{actionableContentMemo:new WeakMap}),Ve(t),t}function Ae(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Ae(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function je(e,t){for(let n of e.children)je(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Ie(e,t));r.length!==0&&(e.children=n.filter(e=>Me(e,r)))}function Me(e,t){return Ne(e)||!Pe(e,t)}function Ne(e){return Fe(e)&&!e.hittable&&e.children.length===0}function Pe(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!ze(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Be(n.rect,e.rect)>=.9)return!0;return!1}function Fe(e){let t=e.identifier?.trim()??``;return!!(t&&!x(t))}function Ie(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&ze(e)&&(Le(e)||Re(e,t))}function Le(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!x(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!x(n))}function Re(e,t){let n=t.actionableContentMemo.get(e);if(n!==void 0)return n;let r=e.children.some(e=>e.visibleToUser!==!1&&(!!e.hittable||Re(e,t)));return t.actionableContentMemo.set(e,r),r}function ze(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Be(e,t){let n=t.width*t.height;return n<=0?0:o(e,t)/n}function Ve(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),qe(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function He(e){let t=e.children.filter(We);if(t.length<2)return;let n=t.filter(e=>Ge(e)&&Ke(e));if(n.length===0)return;let r=Ue(n);e.children=e.children.filter(e=>Ge(e)?Ke(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ue(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function We(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ge(e){return e.windowType===1}function Ke(e){return e.windowActive===!0||e.windowFocused===!0}function qe(e){if(!e.scrollable||!c(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Je(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Je(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function Ye(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Xe(e);return t.interactiveOnly?Ze(e,a,n,r,i):a.isStructural||a.isVisual?et(e,a,r):!0}function Xe(e){let t=nt(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!x(e.label??``),hasMeaningfulId:r&&!x(e.identifier??``),isStructural:rt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ze(e,t,n,r,i){return $e(e)?!1:e.focused||e.hittable||c(t.type)&&r?!0:Qe(t,n,r,i)}function Qe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function $e(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function et(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function tt(e){if(!e)return!1;let t=nt(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function nt(e){return e?e.toLowerCase():``}function rt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function x(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function it(e,t){let n=t.toLowerCase(),r=[...e.children],i=0;for(;i<r.length;){let e=r[i++],t=e.label?.toLowerCase()??``,a=e.value?.toLowerCase()??``,o=e.identifier?.toLowerCase()??``;if(t.includes(n)||a.includes(n)||o.includes(n))return e;r.push(...e.children)}return null}function at(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 S(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ot(n,t);return st(t),{status:t.status,results:t.results}}function ot(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ut(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ct(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ut(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&<(t)}function st(e){ct(e),lt(e)}function ct(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function lt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ut(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function C(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function w(e){if(e===`true`)return!0;if(e===`false`)return!1}function dt(e,t,r){if(typeof e!=`number`||!Number.isInteger(e))throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} must be an integer.`);return e}function T(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function E(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ft(e,t){let r=E(e,`sha256`,t).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new n(`INVALID_ARGS`,`Android ${t} manifest sha256 must be a 64-character hex string.`);return r}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,pt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:yt(t.apkUrl,`apkUrl`),sha256:vt(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:gt(t.installArgs)}}function k(e,t){return dt(e,t,`snapshot helper`)}function A(e,t,n){return T(e,t,n,`snapshot helper`)}function ht(e){return _t(gt(e.installArgs))}function gt(e){let t=bt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!xt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function _t(e){let t={};for(let r of e.slice(1)){let e=St(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function vt(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ct(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function yt(e,t){return e===null?null:j(e,t)}function bt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function xt(e){return St(e)!==void 0}function St(e){if(Object.hasOwn(pt,e))return pt[e]}function Ct(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 wt=2e3,Tt=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function Et(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Tt,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Dt(e){return e instanceof n&&e.details?.reason===Tt}async function Ot(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Mt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Nt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function kt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(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 At(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function jt(){N.clear()}async function Mt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Nt(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 Pt(e){let t=Ft(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(It(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Lt(e,t,i);if(t.outputPath&&!o&&await Wt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,te(i,{helper:a.metadata}));return a}function Ft(e){let t=R(e.timeoutMs,8e3),n=R(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:R(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:R(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:R(e.commandTimeoutMs,t+5e3),maxDepth:R(e.maxDepth,128),maxNodes:R(e.maxNodes,5e3),packageName:n,runner:R(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function R(e,t){return e===void 0?t:e}function It(e){return[`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)],e.runner]}async function Lt(e,t,n){try{return{output:Gt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Rt(e,t,n,r)}}async function Rt(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await zt(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`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},i)}async function zt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Vt(e.adb,t.outputPath,Ut(`${n.stdout}\n${n.stderr}`)??Bt(t))}function Bt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Vt(e,t,n){let r;try{r=await e(Ht(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 Ht(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ut(e){try{return $t(qt(S(e).results))}catch{return null}}async function Wt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Gt(e){let t=S(e),n=qt(t.results);return{xml:Yt(Kt(t.status),n),metadata:{...$t(n),transport:`instrumentation`}}}function Kt(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:z(n.chunkIndex),count:z(n.chunkCount),payloadBase64:e})}return t}function qt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Jt(t),{errorType:t.errorType,helper:t});return t}function Jt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Yt(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=Xt(e),i=Buffer.concat(Qt(Zt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Xt(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function Zt(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Qt(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function $t(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs),waitForIdleQuietMs:z(e.waitForIdleQuietMs),timeoutMs:z(e.timeoutMs),maxDepth:z(e.maxDepth),maxNodes:z(e.maxNodes),rootPresent:tn(e.rootPresent),captureMode:en(e.captureMode),windowCount:z(e.windowCount),nodeCount:z(e.nodeCount),truncated:tn(e.truncated),elapsedMs:z(e.elapsedMs)}}function en(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const z=C,tn=w;function nn(){return new Promise((e,t)=>{let n=de.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 B(e,t,r,i){return new Promise((a,o)=>{let s=de.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,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(`${t}\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 rn(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return un(await B(e.port,`snapshot ${t}`,an(e),e.signal),t)}function an(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function on(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),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,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function sn(e){let t=e.indexOf(`
|
|
1
|
+
import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{a as o,t as s}from"./screenshot-geometry.js";import{un as c}from"./sdk-batch-runner.js";import{T as l,b as u,y as d}from"./device.js";import{I as f,a as p,c as m,j as h,n as g,o as ee,p as te,s as ne,v as re}from"./sdk-android-adb.js";import{n as ie,t as ae}from"./version.js";import{t as oe}from"./timeouts.js";import"./install-artifact.js";import{r as se,t as ce}from"./entities.js";import _ from"node:path";import le from"node:crypto";import ue from"node:os";import v from"node:fs/promises";import de from"node:net";function fe(){let e=[],t=()=>e[e.length-1]===!0;return{open(n,r){let i=t()||u(n);return r||e.push(i),i},close(){e.pop()}}}function*pe(e){let t=/<node\b[^>]*>|<\/node>/g,n=fe(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=me(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function me(e){let t=be(e),n=se(t.bounds);return{...t,...n?{rect:n}:{}}}function he(e,t,n){let{sourceNodes:r,...i}=y(ke(e),t,n);return i}function y(e,t,n){let r={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:n.depth??1/0,options:n,analysis:at(e),interactiveDescendantMemo:new Map,truncated:!1},i=n.scope?it(e,n.scope):null,a=i?[i]:e.children;for(let e of a)if(ge(r,e,0),r.truncated)break;let o={nodes:r.nodes,sourceNodes:r.sourceNodes,analysis:r.analysis};return r.truncated?{...o,truncated:!0}:o}function ge(e,t,n,r,i=!1,a=!1,o=!1){if(e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes){e.truncated=!0;return}if(n>e.maxDepth)return;let s=e.options.raw?!0:Ye(t,e.options,i,ye(e,t),a),c=o||u(t.identifier),l=s?_e(e,t,r,c):r,d=i||!!t.hittable,f=a||tt(t.type);for(let r of t.children)if(ge(e,r,n+1,l,d,f,c),e.truncated)return}function _e(e,t,n,r){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,focused:t.focused,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:ve(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function ve(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function ye(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(n.visibleToUser!==!1&&(n.hittable||ye(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function be(e){let t=xe(e),n=e=>Oe(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=se(n(t));return r===void 0?{}:{[e]:r}},s=(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`),...s(`visibleToUser`,`visible-to-user`),...a(`drawingOrder`,`drawing-order`),...s(`scrollable`,`scrollable`),...s(`canScrollForward`,`can-scroll-forward`),...s(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...s(`windowActive`,`window-active`),...s(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function xe(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=Se(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Se(e,t,n){if(t=b(e,t,n),t>=n||we(e[t]))return;let r=t;t=Ce(e,t,n);let i=e.slice(r,t);if(t=b(e,t,n),!i||e[t]!==`=`)return;t=b(e,t+1,n);let a=e[t];if(!Te(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:ce(e.slice(o,s)),nextCursor:s+1}}function Ce(e,t,n){for(;t<n&&!De(e[t]??``);)t+=1;return t}function b(e,t,n){for(;t<n&&Ee(e[t]??``);)t+=1;return t}function we(e){return e===`/`||e===`>`}function Te(e){return e===`"`||e===`'`}function Ee(e){return e===` `||e===`
|
|
2
|
+
`||e===`\r`||e===` `}function De(e){return e===`=`||e===`/`||e===`>`||Ee(e)}function Oe(e,t){return e.get(t)??null}function ke(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,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=me(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,hittable:a.clickable??a.focusable,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return Ae(t),He(t),je(t,{actionableContentMemo:new WeakMap}),Ve(t),t}function Ae(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Ae(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function je(e,t){for(let n of e.children)je(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Ie(e,t));r.length!==0&&(e.children=n.filter(e=>Me(e,r)))}function Me(e,t){return Ne(e)||!Pe(e,t)}function Ne(e){return Fe(e)&&!e.hittable&&e.children.length===0}function Pe(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!ze(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Be(n.rect,e.rect)>=.9)return!0;return!1}function Fe(e){let t=e.identifier?.trim()??``;return!!(t&&!x(t))}function Ie(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&ze(e)&&(Le(e)||Re(e,t))}function Le(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!x(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!x(n))}function Re(e,t){let n=t.actionableContentMemo.get(e);if(n!==void 0)return n;let r=e.children.some(e=>e.visibleToUser!==!1&&(!!e.hittable||Re(e,t)));return t.actionableContentMemo.set(e,r),r}function ze(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Be(e,t){let n=t.width*t.height;return n<=0?0:s(e,t)/n}function Ve(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),qe(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function He(e){let t=e.children.filter(We);if(t.length<2)return;let n=t.filter(e=>Ge(e)&&Ke(e));if(n.length===0)return;let r=Ue(n);e.children=e.children.filter(e=>Ge(e)?Ke(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ue(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function We(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ge(e){return e.windowType===1}function Ke(e){return e.windowActive===!0||e.windowFocused===!0}function qe(e){if(!e.scrollable||!c(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Je(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Je(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function Ye(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Xe(e);return t.interactiveOnly?Ze(e,a,n,r,i):a.isStructural||a.isVisual?et(e,a,r):!0}function Xe(e){let t=nt(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!x(e.label??``),hasMeaningfulId:r&&!x(e.identifier??``),isStructural:rt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ze(e,t,n,r,i){return $e(e)?!1:e.focused||e.hittable||c(t.type)&&r?!0:Qe(t,n,r,i)}function Qe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function $e(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function et(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function tt(e){if(!e)return!1;let t=nt(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function nt(e){return e?e.toLowerCase():``}function rt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function x(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function it(e,t){let n=t.toLowerCase(),r=[...e.children],i=0;for(;i<r.length;){let e=r[i++],t=e.label?.toLowerCase()??``,a=e.value?.toLowerCase()??``,o=e.identifier?.toLowerCase()??``;if(t.includes(n)||a.includes(n)||o.includes(n))return e;r.push(...e.children)}return null}function at(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 S(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ot(n,t);return st(t),{status:t.status,results:t.results}}function ot(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ut(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ct(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ut(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&<(t)}function st(e){ct(e),lt(e)}function ct(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function lt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ut(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function C(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function w(e){if(e===`true`)return!0;if(e===`false`)return!1}function dt(e,t,r){if(typeof e!=`number`||!Number.isInteger(e))throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} must be an integer.`);return e}function T(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function E(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ft(e,t){let r=E(e,`sha256`,t).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new n(`INVALID_ARGS`,`Android ${t} manifest sha256 must be a 64-character hex string.`);return r}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,pt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:yt(t.apkUrl,`apkUrl`),sha256:vt(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:gt(t.installArgs)}}function k(e,t){return dt(e,t,`snapshot helper`)}function A(e,t,n){return T(e,t,n,`snapshot helper`)}function ht(e){return _t(gt(e.installArgs))}function gt(e){let t=bt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!xt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function _t(e){let t={};for(let r of e.slice(1)){let e=St(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function vt(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ct(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function yt(e,t){return e===null?null:j(e,t)}function bt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function xt(e){return St(e)!==void 0}function St(e){if(Object.hasOwn(pt,e))return pt[e]}function Ct(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 wt=2e3,Tt=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function Et(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Tt,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Dt(e){return e instanceof n&&e.details?.reason===Tt}async function Ot(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Mt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Nt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function kt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(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 At(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function jt(){N.clear()}async function Mt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Nt(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 Pt(e){let t=Ft(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(It(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Lt(e,t,i);if(t.outputPath&&!o&&await Wt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,te(i,{helper:a.metadata}));return a}function Ft(e){let t=R(e.timeoutMs,8e3),n=R(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:R(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:R(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:R(e.commandTimeoutMs,t+5e3),maxDepth:R(e.maxDepth,128),maxNodes:R(e.maxNodes,5e3),packageName:n,runner:R(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function R(e,t){return e===void 0?t:e}function It(e){return[`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)],e.runner]}async function Lt(e,t,n){try{return{output:Gt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Rt(e,t,n,r)}}async function Rt(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await zt(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`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},i)}async function zt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Vt(e.adb,t.outputPath,Ut(`${n.stdout}\n${n.stderr}`)??Bt(t))}function Bt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Vt(e,t,n){let r;try{r=await e(Ht(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 Ht(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ut(e){try{return $t(qt(S(e).results))}catch{return null}}async function Wt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Gt(e){let t=S(e),n=qt(t.results);return{xml:Yt(Kt(t.status),n),metadata:{...$t(n),transport:`instrumentation`}}}function Kt(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:z(n.chunkIndex),count:z(n.chunkCount),payloadBase64:e})}return t}function qt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Jt(t),{errorType:t.errorType,helper:t});return t}function Jt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Yt(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=Xt(e),i=Buffer.concat(Qt(Zt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Xt(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function Zt(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Qt(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function $t(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs),waitForIdleQuietMs:z(e.waitForIdleQuietMs),timeoutMs:z(e.timeoutMs),maxDepth:z(e.maxDepth),maxNodes:z(e.maxNodes),rootPresent:tn(e.rootPresent),captureMode:en(e.captureMode),windowCount:z(e.windowCount),nodeCount:z(e.nodeCount),truncated:tn(e.truncated),elapsedMs:z(e.elapsedMs)}}function en(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const z=C,tn=w;function nn(){return new Promise((e,t)=>{let n=de.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 B(e,t,r,i){return new Promise((a,o)=>{let s=de.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,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(`${t}\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 rn(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return un(await B(e.port,`snapshot ${t}`,an(e),e.signal),t)}function an(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function on(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),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,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function sn(e){let t=e.indexOf(`
|
|
3
3
|
|
|
4
4
|
`);return pn(e.slice(0,t<0?e.length:t))}function cn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:t})}function ln(e,t){let n=sn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function un(e,t){let r=e.indexOf(`
|
|
5
5
|
|
|
6
6
|
`);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=pn(e.slice(0,r)),a=e.slice(r+2);return dn(i,t),fn(i,a),{xml:a,metadata:mn(i)}}function dn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function fn(e,t){let r=C(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function pn(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 mn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:C(e.waitForIdleTimeoutMs),waitForIdleQuietMs:C(e.waitForIdleQuietMs),timeoutMs:C(e.timeoutMs),maxDepth:C(e.maxDepth),maxNodes:C(e.maxNodes),rootPresent:w(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:C(e.windowCount),nodeCount:C(e.nodeCount),truncated:w(e.truncated),elapsedMs:C(e.elapsedMs)}}const hn=5e3,V=new Map,gn=new Map;async function _n(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!An()||!e.adbProvider?.spawn)return;let n=bn(Ft(e)),r=await vn({deviceKey:t,identity:kn(t,n,e),options:e,resolved:n});if(r)return await yn({session:r,deviceKey:t,options:e,resolved:n})}async function vn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(gn.get(t)===n)return;let a=V.get(t);if(a&&a.identity!==n&&(await H(t),a=void 0),!a)try{a=await On({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),gn.set(t,n),h({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Dt(e))throw e;return}return a}async function yn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await rn({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 H(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:xn(e)}});return}}function bn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function xn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Sn(e){let t=V.get(e.deviceKey);if(!t)return;if(!Cn(t.helper,e.helper)){h({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await H(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=sn(await B(t.port,i,e.timeoutMs)),cn(a,r)}catch(t){throw await H(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function Cn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&wn(e.helperVersion,t.helperVersion)&&wn(e.helperVersionCode,t.helperVersionCode)&&wn(e.sha256,t.sha256)}function wn(e,t){return e===void 0||t===void 0||e===t}async function H(e,t={}){let n=V.get(e);if(!n)return;V.delete(e);let r=kt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await Tn(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:wt:hn,s=i?250:2e3,[c,l]=await Promise.all([At({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Ot({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,forceKilled:!a.exited&&c,forced:i||t.signal?.aborted===!0,runtimeForceStopped:l.runtimeForceStopped,externalCleanupTimedOut:l.timedOut}}),!a.exited&&!l.runtimeForceStopped&&I({deviceKey:e,packageName:n.helper.packageName,cause:t.cause})}async function Tn(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=ln(await B(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await L(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function En(e){await H(P(e))}async function Dn(){let e=await Promise.allSettled([...V.keys()].map(e=>H(e)));gn.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);jt()}async function On(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:hn,signal:e.options.signal});let r=It({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={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:o,startedAtMs:Date.now(),capturedCount:0};try{return await on(o,1e4,e.options.signal),V.set(e.deviceKey,s),h({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(t){let n=kt(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([L(n,250),Ot({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:wt})]);throw r.runtimeForceStopped||I({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function kn(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 An(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const jn=1e4;async function Mn(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 zn(a,o,u);let f=await Nn({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 m=await p(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(m.exitCode!==0)throw g(`Failed to install ${u}`,m,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Nn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await In(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 Ln(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Pn(t){let r=ie(),i=_.join(ae(),`android`,t.helperDirName,`dist`),a=_.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await v.readFile(a,`utf8`))),n=_.join(i,e.assetName);return await v.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function Fn(e){return async t=>await Mn({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 In(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Vn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Ln(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:jn,signal:i}),o=Rn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new n(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=await v.mkdtemp(_.join(ue.tmpdir(),`agent-device-helper-`)),c=_.join(s,`base.apk`);try{let e=await ee(o,c,{provider:t,allowFailure:!0,timeoutMs:jn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Bn(c)}finally{await v.rm(s,{recursive:!0,force:!0})}}function Rn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function zn(e,t,r){let i=await Bn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Bn(e){let t=le.createHash(`sha256`);return t.update(await v.readFile(e)),t.digest(`hex`)}function Vn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const U=new Map;function Hn(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of U.keys())e.startsWith(t)&&Gn(e)}function Un(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Wn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of U.keys())t!==e&&t.startsWith(i)&&U.delete(t);U.set(e,t)}function Gn(e){e&&U.delete(e)}async function Kn(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Un(e.deviceKey,i,a,o),c=s?U.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await zn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Yn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Nn({adb:t,adbProvider:Jn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Wn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Xn(t,e.adbProvider??t,n.apkPath,ht(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Gn(s),qn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Gn(s),qn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Wn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function qn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Jn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Yn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Zn(`${i.stdout}\n${i.stderr}`,t)}async function Xn(e,t,n,r,i){let a=async()=>await p(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!Qn(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
|
|
7
7
|
`)}}function Zn(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 Qn(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const $n=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function er(e){return $n.has(e)}const tr=new Set([`android`,`com.android.systemui`]),nr=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,W=/^android:id\/button[123]$/i,rr=/(?:^|:)id\/permission_/i,ir=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,ar=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,or=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function sr(e){if(e!==null){if(W.test(e))return`button`;if(nr.test(e))return`content`}}function cr(e){let t=ur(e),n=t.nodes;if(n.length===0)return null;let r=hr(n),i=n.filter(e=>G(e)&&!Tr(e)),a=vr(i),o=yr(i,a),s=Er(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 lr(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 ur(e){let t=e.filter(e=>Cr(e));if(t.length)return{nodes:t,source:`permission`};let n=mr(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:dr(e),source:`native-dialog`}}function dr(e){let t=e.filter(e=>fr(e.type??``)),n=e.filter(e=>nr.test(e.identifier??``)),r=t.length?[...t,...n]:pr(n);if(r.length===0)return[];let i=br(e,r);return i===void 0?r:Sr(e,i)}function fr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function pr(e){let t=e.some(e=>W.test(e.identifier??``)),n=e.some(e=>!W.test(e.identifier??``));return t&&n?e:[]}function mr(e){let t=e.filter(e=>wr(e));if(t.length===0)return[];let n=br(e,t);return n===void 0?t:Sr(e,n).filter(e=>e.bundleId&&tr.has(e.bundleId))}function hr(e){let t=new Set,n=[];for(let r of e){let e=G(r);if(!e||!r.rect||!Tr(r))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=i(r.rect);n.push({label:e,x:o.x,y:o.y,role:gr(r,e)})}return n}function gr(e,t){return _r(e.identifier??``)||(ar.test(t.trim())?`accept`:or.test(t.trim())?`dismiss`:`neutral`)}function _r(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 vr(e){return G(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||G(e[0])}function yr(e,t){let n=e.map(e=>G(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
8
|
-
`):void 0}function br(e,t){let n=t[0];if(!n)return;let r=xr(e,n.index);for(let n of t.slice(1)){let t=new Set(xr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function xr(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 Sr(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 Cr(e){let t=e.bundleId??``;return $n.has(t)||rr.test(e.identifier??``)}function wr(e){let t=e.bundleId??``;return tr.has(t)&&ir.test(G(e))}function Tr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||W.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function G(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Er(e){return e.find(e=>e.bundleId)?.bundleId}const Dr=new Set([`android`,`com.android.systemui`]);function Or(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Rr(e,n.foregroundAppPackage);return Ar(r,t)?K(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Ir(r)?{outcome:`ok`}:kr(r)?{outcome:`system-surface-only`}:jr(r)?{outcome:`ok`}:Mr(r)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Nr(r)||Pr(r,t)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Fr(r)?K(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function K(e,t,n,r){return{outcome:`unusable`,decision:Lr(e,t,n,r)}}function kr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function Ar(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function jr(e){return Mr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Mr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Nr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Pr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Fr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Ir(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Lr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Qr(e,t)}}function Rr(e,t){let n=zr(t);for(let t of pe(e))Br(n,t);return qr(n)}function zr(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 Br(e,t){e.nodeCount+=1,Zr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Vr(e,t.resourceId),Hr(e,t),Ur(e,t)}function Vr(e,t){let n=sr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Hr(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 Ur(e,t){Jr(t)&&(e.meaningfulNodeCount+=1,Wr(e,t),Kr(e,t))}function Wr(e,t){e.currentWindowType===1&&!Xr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Gr(e)&&!d(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Gr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Kr(e,t){Xr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),l({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function qr(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 Jr(e){return e.visibleToUser===!1?!1:Yr(e.text)||Yr(e.desc)||Yr(e.resourceId)}function Yr(e){return e!==null&&e.trim()!==``}function Xr(e){return e===null||Dr.has(e)}function Zr(e){return e!==null&&Dr.has(e)}function Qr(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}:{}}}const $r=5e3,ei=3e4;async function ti(e,t={}){let n=m(e,t.helperAdb).exec;return(await oi(e,t,n)).xml}async function ni(e,t={}){let n=m(e,t.helperAdb).exec,r=await oi(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=he(i,void 0,t),n=ri(e.truncated,r.metadata);return{...e,...ii(n),androidSnapshot:r.metadata}}let a=ke(i),o=y(a,void 0,t),s=ri(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ai({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...ii(s),androidSnapshot:r.metadata}}function ri(e,t){return e===!0||t.helperTruncated===!0?!0:e}function ii(e){return e===!0?{truncated:!0}:{}}function ai(e){if(Ei(e.interactiveSnapshot.nodes).size>0||Ti(e.xml))return;let t=y(e.tree,void 0,{...e.options,interactiveOnly:!1});Di(s(r(t.nodes)),t,e.interactiveSnapshot)}async function oi(e,t,n){let r=m(e,t.helperAdb),i=await f(`android_snapshot_helper_artifact_resolution`,async()=>await Ci(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await si(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),wi(i.errorReason)}async function si(e,t,n,r){let i=P(e),a=m(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await fi(t.signal);let s=await di({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)return await pi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n});e=s.decision.reason}}finally{o&&await H(i)}}async function ci(e,t,n,r,i){let a=await f(`android_snapshot_helper_install`,async()=>await Kn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});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 li(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:$r,commandTimeoutMs:ei,signal:n};try{let e=await f(`android_snapshot_helper_session_capture`,async()=>await _n(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r});if(e)return e}catch(t){if(n?.throwIfAborted(),Dt(t))throw t;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await hi(r,a.manifest.packageName)}return await f(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r,commandTimeoutMs:ei})}function ui(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,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 di(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await ci(t,n,r,i,a);e.installed&&await H(a),s=ui(await li({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await mi({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=Or(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(h({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function fi(e){e?.throwIfAborted(),await oe(250),e?.throwIfAborted()}async function pi(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}}),await hi(e.adb,e.artifact.manifest.packageName),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,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 mi(e){let t=gi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await H(e.helperDeviceKey),await hi(e.adb,e.artifact.manifest.packageName),Hn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),_i(e.error,t)}async function hi(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await oe(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){h({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}function gi(t){let n=e(t),r=xi(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function _i(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...yi(a),androidSnapshotHelperFailureReason:i,hint:vi(a)},r)}function vi(e){return Si(e.details?.helper,e.message)||bi(e)?`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 yi(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 bi(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function xi(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function Si(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=xi(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ci(t){if(t)return{artifact:t};let n=ie(),r=_.join(ae(),`android`,`snapshot-helper`,`dist`),i=_.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await v.access(i)}catch{return{}}try{let e=mt(JSON.parse(await v.readFile(i,`utf8`))),t=_.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await v.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function wi(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,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 Ti(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Ei(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 Di(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 q=`IME helper`,Oi=`android-ime-helper-v1`;async function ki(){return await Pn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Ai,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Ai(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:T(t.name,`name`,`android-ime-helper`,q),version:E(t.version,`version`,q),assetName:E(t.assetName,`assetName`,q),sha256:ft(t.sha256,q),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,q),versionCode:dt(t.versionCode,`versionCode`,q),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,q),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Oi,q)}}const ji=Fn({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function J(e){return`${e.platform}:${e.id}`}async function Mi(e,t,n){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Ni(e,t){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Pi(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Oi);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const Y=`agent_device_ime_helper_previous_ime`,X=`secure`,Fi=`default_input_method`,Z=new Set;function Ii(e){return Z.has(J(e))}function Q(e){return _.join(e,`android-test-ime-pending`)}function Li(e,t){return _.join(Q(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Ri(t,n){try{await v.mkdir(Q(t),{recursive:!0}),await v.writeFile(Li(t,n),n)}catch(r){h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function zi(e,t){await v.rm(Li(e,t),{force:!0}).catch(()=>{})}async function Bi(e){let t;try{t=await v.readdir(Q(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await v.readFile(_.join(Q(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Vi(e,t={}){let n=ne(e),r=m(e),i=await ki(),{manifest:a}=i,o=J(e);await ji({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await $(n);if(s===a.serviceComponent)return Z.add(o),t.stateDir&&await Ri(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await Ki(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(Z.add(o),!await qi(n,s))return Z.delete(o),h({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Ri(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await $(n);return l===a.serviceComponent?(h({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(Z.delete(o),await Ji(n).catch(()=>{}),t.stateDir&&await zi(t.stateDir,e.id),h({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Hi(e,t={}){let n=J(e);if(!Z.has(n))return{restored:!1,reason:`no-record`};Z.delete(n);let r=await Wi(ne(e),e);return t.stateDir&&Ui(r.reason)&&await zi(t.stateDir,e.id),r}function Ui(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Wi(e,t){let n=t.id;if(Z.has(J(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await Ki(e);if(!r)return{restored:!1,reason:`no-record`};let i=await $(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return h({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await $(e);return a===r?(await Ji(e).catch(()=>{}),h({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(h({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function Gi(t){let n=await Bi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){h({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).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{let e=await Wi(ne(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Ui(e.reason)&&await zi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function $(e){let t=await e([`shell`,`settings`,`get`,X,Fi],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)}async function Ki(e){let t=await e([`shell`,`settings`,`get`,X,Y],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)||void 0}async function qi(e,t){return(await e([`shell`,`settings`,`put`,X,Y,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await Ki(e)===t:!1}async function Ji(e){await e([`shell`,`settings`,`delete`,X,Y],{allowFailure:!0,timeoutMs:5e3})}function Yi(e){let t=e.trim();return!t||t===`null`?``:t}async function Xi(){try{return(await re(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
8
|
+
`):void 0}function br(e,t){let n=t[0];if(!n)return;let r=xr(e,n.index);for(let n of t.slice(1)){let t=new Set(xr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function xr(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 Sr(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 Cr(e){let t=e.bundleId??``;return $n.has(t)||rr.test(e.identifier??``)}function wr(e){let t=e.bundleId??``;return tr.has(t)&&ir.test(G(e))}function Tr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||W.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function G(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Er(e){return e.find(e=>e.bundleId)?.bundleId}const Dr=new Set([`android`,`com.android.systemui`]);function Or(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Rr(e,n.foregroundAppPackage);return Ar(r,t)?K(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Ir(r)?{outcome:`ok`}:kr(r)?{outcome:`system-surface-only`}:jr(r)?{outcome:`ok`}:Mr(r)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Nr(r)||Pr(r,t)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Fr(r)?K(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function K(e,t,n,r){return{outcome:`unusable`,decision:Lr(e,t,n,r)}}function kr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function Ar(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function jr(e){return Mr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Mr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Nr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Pr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Fr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Ir(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Lr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Qr(e,t)}}function Rr(e,t){let n=zr(t);for(let t of pe(e))Br(n,t);return qr(n)}function zr(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 Br(e,t){e.nodeCount+=1,Zr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Vr(e,t.resourceId),Hr(e,t),Ur(e,t)}function Vr(e,t){let n=sr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Hr(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 Ur(e,t){Jr(t)&&(e.meaningfulNodeCount+=1,Wr(e,t),Kr(e,t))}function Wr(e,t){e.currentWindowType===1&&!Xr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Gr(e)&&!d(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Gr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Kr(e,t){Xr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),l({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function qr(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 Jr(e){return e.visibleToUser===!1?!1:Yr(e.text)||Yr(e.desc)||Yr(e.resourceId)}function Yr(e){return e!==null&&e.trim()!==``}function Xr(e){return e===null||Dr.has(e)}function Zr(e){return e!==null&&Dr.has(e)}function Qr(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}:{}}}const $r=5e3,ei=3e4;async function ti(e,t={}){let n=m(e,t.helperAdb).exec;return(await oi(e,t,n)).xml}async function ni(e,t={}){let n=m(e,t.helperAdb).exec,r=await oi(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=he(i,void 0,t),n=ri(e.truncated,r.metadata);return{...e,...ii(n),androidSnapshot:r.metadata}}let a=ke(i),o=y(a,void 0,t),s=ri(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ai({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...ii(s),androidSnapshot:r.metadata}}function ri(e,t){return e===!0||t.helperTruncated===!0?!0:e}function ii(e){return e===!0?{truncated:!0}:{}}function ai(e){if(Ei(e.interactiveSnapshot.nodes).size>0||Ti(e.xml))return;let t=y(e.tree,void 0,{...e.options,interactiveOnly:!1});Di(o(r(t.nodes)),t,e.interactiveSnapshot)}async function oi(e,t,n){let r=m(e,t.helperAdb),i=await f(`android_snapshot_helper_artifact_resolution`,async()=>await Ci(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await si(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),wi(i.errorReason)}async function si(e,t,n,r){let i=P(e),a=m(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await fi(t.signal);let s=await di({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)return await pi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n});e=s.decision.reason}}finally{o&&await H(i)}}async function ci(e,t,n,r,i){let a=await f(`android_snapshot_helper_install`,async()=>await Kn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});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 li(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:$r,commandTimeoutMs:ei,signal:n};try{let e=await f(`android_snapshot_helper_session_capture`,async()=>await _n(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r});if(e)return e}catch(t){if(n?.throwIfAborted(),Dt(t))throw t;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await hi(r,a.manifest.packageName)}return await f(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r,commandTimeoutMs:ei})}function ui(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,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 di(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await ci(t,n,r,i,a);e.installed&&await H(a),s=ui(await li({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await mi({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=Or(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(h({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function fi(e){e?.throwIfAborted(),await oe(250),e?.throwIfAborted()}async function pi(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}}),await hi(e.adb,e.artifact.manifest.packageName),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,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 mi(e){let t=gi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await H(e.helperDeviceKey),await hi(e.adb,e.artifact.manifest.packageName),Hn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),_i(e.error,t)}async function hi(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await oe(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){h({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}function gi(t){let n=e(t),r=xi(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function _i(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...yi(a),androidSnapshotHelperFailureReason:i,hint:vi(a)},r)}function vi(e){return Si(e.details?.helper,e.message)||bi(e)?`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 yi(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 bi(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function xi(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function Si(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=xi(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ci(t){if(t)return{artifact:t};let n=ie(),r=_.join(ae(),`android`,`snapshot-helper`,`dist`),i=_.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await v.access(i)}catch{return{}}try{let e=mt(JSON.parse(await v.readFile(i,`utf8`))),t=_.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await v.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function wi(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,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 Ti(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Ei(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 Di(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 q=`IME helper`,Oi=`android-ime-helper-v1`;async function ki(){return await Pn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Ai,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Ai(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:T(t.name,`name`,`android-ime-helper`,q),version:E(t.version,`version`,q),assetName:E(t.assetName,`assetName`,q),sha256:ft(t.sha256,q),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,q),versionCode:dt(t.versionCode,`versionCode`,q),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,q),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Oi,q)}}const ji=Fn({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function J(e){return`${e.platform}:${e.id}`}async function Mi(e,t,n){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Ni(e,t){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Pi(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Oi);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const Y=`agent_device_ime_helper_previous_ime`,X=`secure`,Fi=`default_input_method`,Z=new Set;function Ii(e){return Z.has(J(e))}function Q(e){return _.join(e,`android-test-ime-pending`)}function Li(e,t){return _.join(Q(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Ri(t,n){try{await v.mkdir(Q(t),{recursive:!0}),await v.writeFile(Li(t,n),n)}catch(r){h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function zi(e,t){await v.rm(Li(e,t),{force:!0}).catch(()=>{})}async function Bi(e){let t;try{t=await v.readdir(Q(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await v.readFile(_.join(Q(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Vi(e,t={}){let n=ne(e),r=m(e),i=await ki(),{manifest:a}=i,o=J(e);await ji({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await $(n);if(s===a.serviceComponent)return Z.add(o),t.stateDir&&await Ri(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await Ki(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(Z.add(o),!await qi(n,s))return Z.delete(o),h({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Ri(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await $(n);return l===a.serviceComponent?(h({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(Z.delete(o),await Ji(n).catch(()=>{}),t.stateDir&&await zi(t.stateDir,e.id),h({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Hi(e,t={}){let n=J(e);if(!Z.has(n))return{restored:!1,reason:`no-record`};Z.delete(n);let r=await Wi(ne(e),e);return t.stateDir&&Ui(r.reason)&&await zi(t.stateDir,e.id),r}function Ui(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Wi(e,t){let n=t.id;if(Z.has(J(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await Ki(e);if(!r)return{restored:!1,reason:`no-record`};let i=await $(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return h({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await $(e);return a===r?(await Ji(e).catch(()=>{}),h({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(h({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function Gi(t){let n=await Bi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){h({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).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{let e=await Wi(ne(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Ui(e.reason)&&await zi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function $(e){let t=await e([`shell`,`settings`,`get`,X,Fi],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)}async function Ki(e){let t=await e([`shell`,`settings`,`get`,X,Y],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)||void 0}async function qi(e,t){return(await e([`shell`,`settings`,`put`,X,Y,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await Ki(e)===t:!1}async function Ji(e){await e([`shell`,`settings`,`delete`,X,Y],{allowFailure:!0,timeoutMs:5e3})}function Yi(e){let t=e.trim();return!t||t===`null`?``:t}async function Xi(){try{return(await re(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
9
9
|
`).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 Zi={previousIme:Y,defaultInputMethod:Fi};export{F as C,C as D,S as E,pe as O,P as S,D as T,Pn as _,$ as a,H as b,Ni as c,ti as d,ni as f,Kn as g,er as h,Xi as i,ki as l,cr as m,Vi as n,Hi as o,lr as p,Ii as r,Gi as s,Zi as t,Mi as u,Dn as v,mt as w,En as x,Sn as y};
|