agent-device 0.20.8 → 0.20.10
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 +94 -31
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +13 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +10 -117
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +103 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +108 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +179 -73
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +61 -0
- package/dist/src/ai-sdk.js +1 -0
- package/dist/src/android-adb.d.ts +6 -6
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +6 -7
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +2 -0
- package/dist/src/appearance.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/artifacts.d.ts +1 -1
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/bounds.js +1 -0
- package/dist/src/byte-limit-stream.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +42 -30
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +7 -7
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +1582 -0
- package/dist/src/command-catalog.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -0
- package/dist/src/config.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols.js +3 -3
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device-ready.js +1 -1
- package/dist/src/device2.js +2 -2
- package/dist/src/dispatch.js +1 -1
- package/dist/src/entities.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper-package-install.js +1 -0
- package/dist/src/helper.js +2 -2
- package/dist/src/host-process.js +1 -1
- package/dist/src/ime-lifecycle.js +2 -9
- package/dist/src/ime-recovery-marker.js +1 -0
- package/dist/src/index.d.ts +2 -1569
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact.js +1 -1
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -0
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -0
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -0
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +4 -7
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/keyed-lock.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +13 -3
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -0
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -0
- package/dist/src/observability.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf.js +4 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -1
- package/dist/src/project-runtime.js +1 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -0
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-export-quality.js +1 -0
- package/dist/src/registry.js +29 -26
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +5 -5
- package/dist/src/rolldown-runtime.js +1 -0
- package/dist/src/runner-client.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime-transport.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -3
- package/dist/src/runtime3.js +1 -3
- package/dist/src/runtime4.js +3 -1
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -0
- package/dist/src/runtime9.js +1 -0
- package/dist/src/scoped-provider.js +1 -0
- package/dist/src/screenshot-density.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/script-source-bundle.js +16 -0
- package/dist/src/sdk-android-adb.d.ts +44 -26
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +125 -88
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +107 -95
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/sdk.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +10 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +1 -30
- package/dist/src/session2.js +27 -0
- package/dist/src/setting-state.js +1 -1
- package/dist/src/shared.js +1 -1
- package/dist/src/simctl.js +1 -0
- package/dist/src/simulator-state.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -0
- package/dist/src/snapshot-session.js +1 -1
- package/dist/src/snapshot.js +8 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -2
- package/dist/src/src3.js +2 -1
- package/dist/src/src4.js +1 -0
- package/dist/src/string-enum.js +1 -0
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/verdict.js +1 -0
- package/dist/src/verified-file.js +1 -0
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +27 -10
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +0 -1
- package/dist/src/interaction-touch-reference-frame.js +0 -1
- package/dist/src/notifications.js +0 -1
- package/dist/src/platform-runtime-toolchain-host.js +0 -1
- package/dist/src/prepare-kind.js +0 -15
- package/dist/src/selector-vocabulary.js +0 -1
- package/dist/src/text-surface.js +0 -1
package/dist/src/dispatch.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{A as t,Ft as n,M as r,N as i,P as a,dt as o,ft as s,j as c,p as l,st as u,w as d}from"./version.js";import{G as f,Y as ee,a as te,h as ne,s as p}from"./sdk-batch-runner.js";import{_ as m,b as re,c as h,h as ie,l as g,m as _,s as v,x as y,y as ae}from"./sdk-device.js";import{Gt as oe,Kt as se,Xt as b,_n as x,dt as ce,ft as le,gn as S,n as ue,pt as de,ut as C}from"./prepare-kind.js";import{A as fe}from"./screenshot-result.js";import{a as pe}from"./device.js";import{f as me}from"./runtime.js";import{I as he,j as w}from"./sdk-android-adb.js";import{t as ge}from"./timeouts.js";import{F as _e}from"./runner-disposal.js";import{H as ve,U as ye}from"./physical-device-control.js";import be from"node:path";import{AsyncLocalStorage as T}from"node:async_hooks";import xe,{promises as Se}from"node:fs";let Ce=[];const E=new T;async function we(e,t){return await E.run([...e],t)}function Te(e,t){for(let n of O()){if(!n.ownsDevice(e))continue;let r=n.getInteractor(e,t);if(r)return r}}function D(e){return O().some(t=>t.ownsDevice(e))}async function Ee(e,t,n,r){for(let i of O()){if(!i.ownsDevice(e))continue;if(!i.installApp)throw j(i,e,`install`);let a=await i.installApp?.(e,t,n,r);if(a)return a;throw j(i,e,`install`)}}async function De(e,t,n){for(let r of O()){if(!r.ownsDevice(e))continue;if(!r.installInstallablePath)throw j(r,e,`install_from_source`);let i=await r.installInstallablePath?.(e,t,n);if(i)return i;throw j(r,e,`install_from_source`)}}async function Oe(e){for(let t of O()){if(!A(t,e.provider))continue;let n=await t.configurePortReverse?.(e);if(n)return n}}function O(){return E.getStore()??Ce}function ke(e,t={}){ze(e);let n=e.map(e=>e.provider);return{providerRuntimeIds:n,providerRuntimeRequiredIds:Fe([...n,...t.providerRuntimeRequiredIds??[]]),leaseLifecycleProvider:Ie(e),recoverableProviderIds:e.filter(e=>e.recoverExpiredLease!==void 0).map(e=>e.provider),recoverExpiredLease:Pe(e),cloudArtifactProvider:Le(e),deviceInventorySource:Re(e),appleRunnerProvider:je(e),appleRunnerScreenRecordingTransport:Ae(e),providerDeviceRuntimeScope:async t=>await we(e,t)}}function Ae(e){if(e.some(Ne))return t=>{for(let n of e){if(!Ne(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerScreenRecordingTransport(t.device);if(e)return e}}}function je(e){if(e.some(Me))return t=>{for(let n of e){if(!Me(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerProvider(t.device);if(e)return e}}}function Me(e){return`getAppleRunnerProvider`in e&&typeof e.getAppleRunnerProvider==`function`}function Ne(e){return`getAppleRunnerScreenRecordingTransport`in e&&typeof e.getAppleRunnerScreenRecordingTransport==`function`}function Pe(t){if(t.some(e=>e.recoverExpiredLease!==void 0))return async n=>{let r=t.find(e=>A(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 Fe(e){return[...new Set(e)]}function Ie(e){if(e.length!==0)return{allocate:async(t,n)=>await k(e,`allocate`,t,n),heartbeat:async(t,n)=>await k(e,`heartbeat`,t,n),release:async(t,n)=>await k(e,`release`,t,n)}}function Le(e){if(e.length!==0)return{listCloudArtifacts:async t=>await Be(e,t)}}function Re(e){if(e.length!==0)return{discover:async(t,n)=>{n.throwIfAborted();for(let r of e){if(!A(r,t.leaseProvider))continue;let e=await r.deviceInventoryProvider(t,n);if(n.throwIfAborted(),e!=null)return{kind:`inventory`,devices:e}}return{kind:`declined`}}}}function ze(e){let t=new Set;for(let n of e){if(t.has(n.provider))throw TypeError(`Duplicate provider device runtime: ${n.provider}`);t.add(n.provider)}}async function Be(e,t){for(let n of e){if(!A(n,t.provider))continue;let e=await n.cloudArtifacts?.listCloudArtifacts?.(t);if(e)return e}}async function k(e,t,n,r){for(let i of e){if(!A(i,n.leaseProvider))continue;let e=i.leaseLifecycle[t],a=e?await e(n,r):void 0;if(a)return a}}function A(e,t){return e.provider===t}function j(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:m(n)})}const Ve=`device_inventory_context_unavailable`,He=new T;async function Ue(e,t){return await He.run(e,t)}async function We(e){return await qe(`providerFirst`,e)}async function Ge(e){let t=Je(),n=await t.providerFirst.discoverWithSource(e,t.requestScope);return{devices:n.devices.map(e=>({...e})),source:n.source}}async function Ke(e){return await qe(`localOnly`,e)}async function qe(e,t){let n=Je();return(await n[e].discover(t,n.requestScope)).map(e=>({...e}))}function Je(){let t=He.getStore();if(!t)throw new e(`COMMAND_FAILED`,`Device inventory gateway is unavailable outside request execution`,{reason:Ve});return t}function Ye(t){return _e(t)||t instanceof e&&t.code===`COMMAND_FAILED`&&t.details?.reason===Ve?!0:t instanceof Error&&t.name===`AbortError`}const M=new T;async function Xe(t,n,r){let i=await Ze(t,n,r);if(i)return i;let a=await $e(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&tt(n,a)){let e;try{[e]=await Ke({platform:n.platform??`ios`,target:n.target,iosSimulatorSetPath:r.simulatorSetPath,kind:`simulator`})}catch(e){if(Ye(e))throw e}if(e)return e}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function Ze(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||N(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>ie(e,n)&&h(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,...Qe(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,...Qe(s),hint:`Pass --udid to select the intended simulator explicitly.`})}function Qe(e){return{devices:e.map(e=>({id:e.id,name:e.name}))}}async function $e(e,t,n){try{return await re(e,t,n)}catch(e){if(et(e,t))return;throw e}}function et(t,n){return!N(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function tt(e,t){return!N(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function N(e){return!!(e.udid||e.serial||e.deviceName)}async function nt(e,t={}){let n=rt(e),{iosSimulatorSetPath:r,...i}=n,a=lt(n,t),o={simulatorSetPath:r,allowStoppedAndroidAvdPlaceholders:t.allowStoppedAndroidAvdPlaceholders},s={platform:n.platform,target:e.target,cacheHit:!1};return await he(`resolve_target_device`,async()=>{let e=st(a);if(e)return s.cacheHit=!0,e;let c=await Ge(n),l=[...c.devices];return ot(i)?ct(a,await Xe(l,i,{simulatorSetPath:r,allowLocalSimulatorFallback:c.source===`local`||n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):ct(a,await re(l,i,o))},s)}function rt(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=ae({simulatorSetPath:ye(t.iosSimulatorDeviceSet),platform:n,target:t.target}),i=ve(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 it(e){return M.getStore()?await e():await M.run(new Map,e)}function at(e){return v(e.platform)}function ot(e){return at(e)}function st(e){let t=M.getStore()?.get(e);if(t)return{...t}}function ct(e,t){return M.getStore()?.set(e,{...t}),t}function lt(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}const P=new Map;function ut(e){for(let t of e.platforms){if(P.has(t))throw Error(`PlatformPlugin already registered for platform "${t}"`);P.set(t,e)}}function dt(t){let n=P.get(t);if(!n)throw new e(`UNSUPPORTED_PLATFORM`,`Unsupported platform: ${t}`);return n}function F(e){return P.get(e)}const I={appAndDeviceLifecycle:!0,keyboard:!0,orientation:!0,physicalDeviceSurfaces:!1},ft={ios:I,ipados:I,visionos:{appAndDeviceLifecycle:!0,keyboard:!0,orientation:!0,physicalDeviceSurfaces:!1},tvos:{appAndDeviceLifecycle:!0,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!1},macos:{appAndDeviceLifecycle:!1,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!0},watchos:{appAndDeviceLifecycle:!1,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!1}};function L(e){return v(e.platform)?ft[y(e)]:void 0}const R=e=>{let t=L(e);return t?t.appAndDeviceLifecycle:!0},z=e=>e.platform!==`apple`||e.kind!==`device`||e.iosPhysicalDeviceBackend!==`xctest`,B=e=>R(e)&&z(e),pt=e=>{let t=L(e);return t?t.keyboard:e.platform===`android`},mt=e=>{let t=L(e);return t?t.orientation:e.platform===`android`},V=e=>{let t=L(e);return t&&t.physicalDeviceSurfaces||e.kind===`simulator`},ht=e=>e.platform===`android`||e.platform===`apple`&&y(e)===`ios`||V(e),gt=e=>e.platform===`android`?e.target===`tv`:_(e),_t={[b.boot]:R,[b.apps]:z,[b.install]:B,[b.reinstall]:B,[b.installFromSource]:B,[b.perf]:z,[b.push]:R,[b.home]:R,[b.appSwitcher]:R,[b.clipboard]:e=>e.platform===`android`||e.platform===`linux`||V(e),[b.keyboard]:pt,[b.orientation]:mt,[b.tvRemote]:gt,[b.alert]:ht,[b.settings]:e=>e.platform===`android`||V(e),[b.audio]:f},vt={[b.apps]:H,[b.install]:H,[b.reinstall]:H,[b.installFromSource]:H,[b.perf]:H,[b.viewport]:e=>e.platform===`apple`?`viewport resizes web targets only (--platform web). Apple screen geometry is fixed by the selected simulator or device type — open a different simulator to test another screen size.`:void 0,[b.tvRemote]:e=>e.platform===`android`?e.target===`tv`?void 0:`tv-remote is supported only on Android TV targets.`:L(e)?_(e)?void 0:`tv-remote is supported only on tvOS devices.`:void 0};function H(e){if(!z(e))return`This command requires a CoreDevice-backed physical iOS device. The selected XCTest backend supports open, close, interactions, snapshots, and screenshots.`}const yt={id:`apple`,platforms:[`apple`],familySelector:`apple`,capability:{bucket:`apple`,supportsByDefault:_t,unsupportedHintByDefault:vt},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`apple`},providers:{platformGatedResolvers:[`appleRunnerProvider`,`appleToolProvider`]},createInteractor:async(e,t)=>{let{createAppleInteractor:n}=await import(`./interactor.js`);return n(e,t)}},bt=[b.open,b.close,b.back,b.home,b.tvRemote],xt=e=>e.target===`tv`,St=e=>e.kind===`emulator`&&xt(e),Ct={id:`vega`,platforms:[`vega`],capability:{bucket:`vega`,supportsByDefault:Object.fromEntries(bt.map(e=>[e,xt])),unsupportedHintByDefault:Object.fromEntries(bt.map(e=>[e,t=>St(t)?void 0:`${e} currently supports only Vega Virtual Devices.`]))},providers:{platformGatedResolvers:[`vegaToolProvider`]},createInteractor:async(e,t)=>{let{createVegaInteractor:n}=await import(`./interactor2.js`);return n(e,t)}},wt=[yt,{id:`android`,platforms:[`android`],capability:{bucket:`android`,supportsByDefault:{[b.audio]:f,[b.tvRemote]:e=>e.target===`tv`},unsupportedHintByDefault:{[b.tvRemote]:e=>e.target===`tv`?void 0:`tv-remote is supported only on Android TV targets.`}},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`android`},providers:{platformGatedResolvers:[`androidAdbProvider`]},createInteractor:async(e,t)=>{let{createAndroidInteractor:n}=await import(`./android.js`).then(e=>e.t);return n(e,void 0,t)}},{id:`harmonyos`,platforms:[`harmonyos`],capability:{bucket:`harmonyos`},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`harmonyos`},createInteractor:async(e,t)=>{let{createHarmonyInteractor:n}=await import(`./harmonyos.js`);return n(e,t)}},Ct,{id:`linux`,platforms:[`linux`],capability:{bucket:`linux`},providers:{platformGatedResolvers:[`linuxToolProvider`]},createInteractor:async()=>{let{createLinuxInteractor:e}=await import(`./linux.js`);return e()}},{id:`web`,platforms:[`web`],capability:{bucket:`web`},providers:{platformGatedResolvers:[`webProvider`]},createInteractor:async()=>{let{createWebInteractor:e}=await import(`./web.js`);return e()}}];let Tt=!1;function U(){if(!Tt){for(let e of wt)ut(e);Tt=!0}}U();const Et={device:!0},Dt={emulator:!0,device:!0},Ot=new Set(`open.perf.close.back.apps.appstate.app-switcher.click.fill.find.focus.get.home.gesture.install.keyboard.is.longpress.press.reinstall.screenshot.scroll.settings.snapshot.swipe.type.wait`.split(`.`)),kt=[`open`,`close`],At=[`audio`,`find`,`get`,`is`,`screenshot`,`snapshot`,`wait`],jt=[`click`,`fill`,`focus`,`press`,`scroll`,`type`],Mt=[`viewport`],Nt=new Set([...kt,...At,...jt,...Mt]),Pt=Ft(te(ne));function Ft(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Ot.has(n)?{...r,harmonyos:Dt}:r;return It(t)}function It(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Nt.has(n)?{...r,web:Et}:r;for(let t of Nt)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function Lt(e,t){let n=Pt[e];if(!n)return!0;let r=F(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 Rt(e,t){return F(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function zt(){return ne.filter(e=>`capability`in e&&e.capability!==void 0||e.platformExecution.kind===`device-runtime`).map(e=>e.name).sort()}function Bt(e){let t=Pt[e];if(!t)return[];let n=[`apple`,`android`,`harmonyos`,`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 Vt(e,t){if(e.intent===`drag`){Ht(e,t);return}if(t.platform===`web`||t.appleOs===`watchos`)throw G(e,W(e,t));if(Wt(e)){Gt(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 Ht(e,t){if(!Ut(t))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.platform===`android`?e.target!==`tv`:e.platform===`apple`?e.appleOs===void 0?e.target!==`desktop`&&e.target!==`tv`:e.appleOs===`ios`||e.appleOs===`ipados`:!1}function Wt(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function Gt(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));ee(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 Kt=`No active session. Run open first.`;function qt(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function Jt(){return qt(`SESSION_NOT_FOUND`,Kt)}function Yt(e,t,n){if(Lt(e,t))return null;let r=n?.hint?Rt(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 Xt=/^[A-Za-z0-9_.:-]{1,64}$/,Zt=8*1024,Qt=4*1024;function $t(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!Xt.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:tn(r,n)}}function en(t,n,r){let i=m(t),a=nn(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>Qt)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:Qt});return s}function tn(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`)>Zt)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${Zt} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function nn(e){return((h(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:g(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}function rn(e){let t=e?e.textEntryReadiness:void 0,n=ln(t)?{textEntryReadiness:t}:{},r=an(e);return r?{...n,...r}:n}function an(e){if(!on(e))return null;let t=sn(e.target);return t?{verification:`unconfirmed`,requested:e.requested,before:e.before,after:e.after,target:t}:null}function on(e){return!!(e&&e.verification===`unconfirmed`&&typeof e.requested==`string`&&K(e.before)&&K(e.after))}function sn(e){if(!dn(e)||!cn(e))return null;let t=un(e.rect);return t?{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:t}:null}function cn(e){return K(e.resourceId)&&K(e.className)&&K(e.packageName)}function ln(e){return typeof e==`string`&&i.includes(e)}function K(e){return e===null||typeof e==`string`}function un(e){return!dn(e)||![e.x,e.y,e.width,e.height].every(e=>typeof e==`number`)?null:e}function dn(e){return!!e&&typeof e==`object`}const q=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function fn(e,t){return v(e.platform)&&t>1}function pn(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 mn(e,t){if(t<=0)return[0,0];let[n,r]=q[e%q.length];return[n*t,r*t]}async function hn(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await ge(t)}async function gn(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 _n(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 vn(t,n,r){let i=Un(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,...S(Z(`Typed`,a))}}async function yn(t,n,r){if(r?.directElementSelector)return await bn(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),c=await t.fill(i,a,o,s,{allowNonHittableCoordinateFallback:r?.allowNonHittableCoordinateFallback===!0});return{x:i,y:a,text:o,delayMs:s,...c?.maestroNonHittableCoordinateFallbackUsed===!0?{maestroNonHittableCoordinateFallbackUsed:!0}:{},...rn(c),...S(Z(`Filled`,o))}}async function bn(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??{},...S(Z(`Filled`,a))}}async function xn(e,t,n,r){if(r?.directElementSelector&&h(e))return await Sn(t,r.directElementSelector);let{x:i,y:a}=J(n,`press requires x y`);if(g(e)&&r?.surface&&r.surface!==`app`)return await Cn(i,a,r);let o=s(r);if(o!==`primary`)return await wn(e,i,a,o,r);let c=Dn(r);return On(c),fn(e,c.count)?await An(e,i,a,c,r):await Nn(t,i,a,c)}async function Sn(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?a:`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 Cn(t,n,r){let i=s(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 wn(e,t,n,r,i){if(Tn(e,r,i),e.platform===`linux`)return await En(t,n,r);let{runAppleRunnerCommand:a}=await import(`./internal/daemon.js`).then(e=>e.lt);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},Pn(i)),{x:t,y:n,button:r,...S(X({x:t,y:n,button:r}))}}function Tn(e,t,n){let r=o({commandLabel:`click`,platform:m(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function En(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}return{x:e,y:t,button:n,...S(X({x:e,y:t,button:n}))}}function Dn(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,i){return C(e===void 0?t:e,n,r,i)}function On({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 kn(e,t,n){let{runAppleRunnerCommand:r}=await import(`./internal/daemon.js`).then(e=>e.lt),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=pn(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),Pn(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Mn(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 An(e,t,n,r,i){let a=await kn(e,jn(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 jn(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&h(e)&&!_(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=mn(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 Mn(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 Nn(e,t,n,r){let i;return await hn(r.count,r.intervalMs,async a=>{let[o,s]=mn(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}}),x({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 Pn(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 Fn(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`);In(a,o,s);let c=Vn(i),l={amount:a,pixels:o,durationMs:s},{interactionResult:u,completedPasses:d}=await Rn(t,r,c,l);return x(zn(c,l,d,u),le(c.direction,c.edge,d,a,o))}function In(e,n,i){Ln(e),r(i),t({amount:e,pixels:n})}function Ln(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Rn(e,t,n,r){if(n.edge){let i=n.edge,a=await de({edge:i,captureState:async n=>await Bn(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 zn(e,t,n,r){let i=c(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 Bn(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 ce({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function Vn(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:u(e)}}async function Hn(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(g(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(`./internal/daemon.js`).then(e=>e.lt),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 Un(e){return me(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 Wn(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)}function Gn(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(!xe.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(Wn(i))return{kind:`inline`,text:i};throw new e(`INVALID_ARGS`,`${r} file not found: ${a}`)}async function Kn(t){let n=Gn(t,{subject:`Push payload`}),r=n.kind===`inline`?n.text:await qn(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 qn(t){try{return await Se.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)})}}U();async function Q(t,n){if(D(t)){let r=Te(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:m(t)})}return await dt(t.platform).createInteractor(t,n)}async function Jn(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 he(`platform_command`,async()=>await Qn(e,o,t,n,r,i,a),{command:t,platform:e.platform})}async function Yn(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 Xn(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 Zn={open:({device:e,interactor:t,positionals:n,context:r})=>$n(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})=>xn(e,t,n,r),longpress:({interactor:e,positionals:t})=>gn(e,t),focus:({interactor:e,positionals:t})=>_n(e,t),type:({interactor:e,positionals:t,context:n})=>vn(e,t,n),fill:({interactor:e,positionals:t,context:n})=>yn(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>Fn(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>er(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>tr(e,t,n,r),viewport:({interactor:e,positionals:t})=>nr(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=pe(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})=>rr(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>ar(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>ir(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>ur(e,t,n,r),push:({device:e,positionals:t,context:n})=>hr(e,t,n),snapshot:({interactor:e,context:t})=>gr(e,t),read:({device:e,positionals:t,context:n})=>Hn(e,t,n)};async function Qn(t,n,r,i,a,o,s){let c=Object.hasOwn(Zn,r)?Zn[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 $n(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,...S(`Opened device`)}}if(s&&(!h(t)||t.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,se);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(p(a))throw new e(`INVALID_ARGS`,`open <app> <url> requires an app target as the first argument`);if(!p(o))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(s)throw new e(`INVALID_ARGS`,oe);return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchArgs:c,terminateRunningApp:i?.terminateRunningApp,url:o}),{app:a,url:o,...S(`Opened: ${a}`)}}if(s&&p(a))throw new e(`INVALID_ARGS`,oe);if(i?.clearAppState){if(p(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}:{},...S(`Opened: ${a}`)}}async function er(e,t,n,r){let{eventName:i,payload:a}=$t(n),o=en(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 tr(e,t,r,i){let a=t[0]??r??`./screenshot-${Date.now()}.png`;await Se.mkdir(be.dirname(a),{recursive:!0});let o=n(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,...S(`Saved screenshot: ${a}`)}}async function nr(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=ue(n[0],`width`),i=ue(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 rr(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 ir(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 a=d(r[0]),o=i?.durationMs===void 0?void 0:C(i.durationMs,`durationMs`,0,1e4);return await n.tvRemote(a,o),{action:`tv-remote`,button:a,...o===void 0?{}:{durationMs:o},...S(`Pressed TV remote ${a}`)}}async function ar(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!fe(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 sr(t,a);if(t.platform===`harmonyos`)return await or(t,a);if(h(t))return await cr(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android, HarmonyOS, and iOS`)}async function or(t,n){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is not available through the public HarmonyOS HDC API; use keyboard dismiss or enter`);let{pressHarmonyKeyboardKey:r}=await import(`./input-actions2.js`);return await r(t,n===`dismiss`?`Back`:`Enter`),{platform:`harmonyos`,action:n===`dismiss`?`dismiss`:`enter`,...S(n===`dismiss`?`Keyboard dismissed`:`Keyboard enter pressed`)}}async function sr(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 cr(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(`./internal/daemon.js`).then(e=>e.lt),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(`./internal/daemon.js`).then(e=>e.lt),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,...S(lr(o.dismissed===!0,s))}}function lr(e,t){return e?t===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`:`Keyboard already hidden`}async function ur(t,n,r,i){let[a,o,s,c]=r;if(!a||!o&&a!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(a===`clear-app-state`)return await dr(t,n,o,s,i);if(!o)throw new e(`INVALID_ARGS`,`settings requires setting state`);return await fr(t,n,a,o,s,c,r,i)}async function dr(t,n,r,i,a){let o=(r===`clear`?i:r)??a?.appBundleId;if(!o)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:`clear-app-state`,state:`clear`,appBundleId:o,platform:t.platform}});let s=await n.setSetting(`clear-app-state`,`clear`,o);return s&&typeof s==`object`?x({setting:`clear-app-state`,state:`clear`,...s},_r(s)??`Cleared user data for ${o}`):{setting:`clear-app-state`,state:`clear`,...S(`Cleared user data for ${o}`)}}async function fr(e,t,n,r,i,a,o,s){let c=n===`location`&&r===`set`,l=(n===`permission`||c?o[4]:o[2])??s?.appBundleId;w({level:`debug`,phase:`settings_apply`,data:mr(e,n,r,i,a,l,c)});let u=await t.setSetting(n,r,l,pr(n,i,a,c));return u&&typeof u==`object`?x({setting:n,state:r,...u},_r(u)??`Updated setting: ${n}`):{setting:n,state:r,...S(`Updated setting: ${n}`)}}function pr(e,t,n,r){if(e===`permission`)return{permissionTarget:t,permissionMode:n};if(r)return{latitude:l(t,`latitude`),longitude:l(n,`longitude`)}}function mr(e,t,n,r,i,a,o){return o?{setting:t,state:n,latitude:r,longitude:i,platform:e.platform}:t===`permission`?{setting:t,state:n,permissionTarget:r,permissionMode:i,platform:e.platform}:{setting:t,state:n,appBundleId:a,platform:e.platform}}async function hr(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 Kn(a);if(h(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:s}=await import(`./notifications.js`),c=await s(t,i,o);return{platform:`android`,package:i,action:c.action,extrasCount:c.extrasCount,...S(`Pushed notification to ${i}`)}}async function gr(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,customActions:n.snapshotCustomActions,includeRects:n.snapshotIncludeRects,includeHiddenContentHints:n.snapshotIncludeHiddenContentHints,surface:n.surface})}function _r(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}export{ke as C,D as E,Oe as S,De as T,it as _,Kt as a,Ye as b,Yt as c,Vt as d,Bt as f,nt as g,rt as h,Gn as i,Lt as l,F as m,Yn as n,qt as o,U as p,Xn as r,Jt as s,Jn as t,zt as u,We as v,Ee as w,Ue as x,Ke as y};
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{D as t,t as n}from"./location-coordinates.js";import{Ft as r,a as i,f as a}from"./sdk-batch-runner.js";import{_ as o,b as s,c,h as l,l as u,m as d,s as f,y as ee}from"./sdk-device.js";import{bn as p,c as m,ft as h,ht as te,mt as ne,pt as re,yn as g}from"./script-source-bundle.js";import{G as _,V as ie,W as v,d as y,f as ae,i as oe,m as se,p as ce,u as le}from"./interaction.js";import{M as ue}from"./screenshot-result.js";import{a as de}from"./device.js";import{s as fe}from"./runtime.js";import{A as b,F as x}from"./sdk-android-adb.js";import{t as pe}from"./timeouts.js";import{i as S,r as me,t as C}from"./interactors.js";import{o as he,s as ge}from"./simctl.js";import{d as _e,f as ve,u as ye}from"./verified-file.js";import be from"node:path";import{promises as xe}from"node:fs";import{AsyncLocalStorage as Se}from"node:async_hooks";const w=new Se;async function Ce(t,n,r){let i=await we(t,n,r);if(i)return i;let a=await E(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&O(n,a)){let e;try{[e]=await ye({platform:n.platform??`ios`,target:n.target,iosSimulatorSetPath:r.simulatorSetPath,kind:`simulator`})}catch(e){if(ve(e))throw e}if(e)return e}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function we(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||k(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>l(e,n)&&c(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,...T(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,...T(s),hint:`Pass --udid to select the intended simulator explicitly.`})}function T(e){return{devices:e.map(e=>({id:e.id,name:e.name}))}}async function E(e,t,n){try{return await s(e,t,n)}catch(e){if(D(e,t))return;throw e}}function D(t,n){return!k(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function O(e,t){return!k(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function k(e){return!!(e.udid||e.serial||e.deviceName)}async function Te(e,t={}){let n={...A(e),androidAvdSelection:t.androidAvdSelection??`running-only`},{iosSimulatorSetPath:r,...i}=n,a=Ae(n,t),o={simulatorSetPath:r},c={platform:n.platform,target:e.target,cacheHit:!1};return await x(`resolve_target_device`,async()=>{let e=ke(a);if(e)return c.cacheHit=!0,e;let l=await _e(n),u=[...l.devices];return Oe(i)?j(a,await Ce(u,i,{simulatorSetPath:r,allowLocalSimulatorFallback:l.source===`local`||n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):j(a,await s(u,i,o))},c)}function A(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 Ee(e){return w.getStore()?await e():await w.run(new Map,e)}function De(e){return f(e.platform)}function Oe(e){return De(e)}function ke(e){let t=w.getStore()?.get(e);if(t)return{...t}}function j(e,t){return w.getStore()?.set(e,{...t}),t}function Ae(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}me();const je={device:!0},Me={emulator:!0,device:!0},Ne=new Set([`perf`,`back`,`app-switcher`,`click`,`fill`,`find`,`focus`,`get`,`home`,`gesture`,`keyboard`,`is`,`longpress`,`press`,`screenshot`,`scroll`,`settings`,`swipe`,`type`,`wait`]),Pe=[`audio`,`find`,`get`,`is`,`screenshot`,`wait`],Fe=[`click`,`fill`,`focus`,`hover`,`press`,`scroll`,`type`],Ie=[`viewport`],M=new Set([...Pe,...Fe,...Ie]),N=Le(i(a));function Le(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Ne.has(n)?{...r,harmonyos:Me}:r;return Re(t)}function Re(e){let t={};for(let[n,r]of Object.entries(e))t[n]=M.has(n)?{...r,web:je}:r;for(let t of M)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function P(e,t){let n=N[e];if(!n)return!0;let r=S(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 ze(e,t){return S(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function Be(){return a.filter(e=>e.catalog.group===`public`&&(`capability`in e&&e.capability!==void 0||e.platformExecution.kind===`device-runtime`)).map(e=>e.name).sort()}function Ve(e){let t=N[e];if(!t)return[];let n=[`apple`,`android`,`harmonyos`,`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 He(e,t){if(e.intent===`drag`){Ue(e,t);return}if(t.platform===`web`||t.appleOs===`watchos`)throw I(e,F(e,t));if(Ge(e)){Ke(e,t);return}if(t.appleOs===`visionos`)throw I(e,F(e,t));if(e.intent===`fling`&&`direction`in e&&t.platform===`linux`)throw I(e,`gesture fling is not supported on Linux`)}function Ue(e,t){if(!We(t))throw I(e,F(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 We(e){return e.platform===`android`?e.target!==`tv`:e.platform===`apple`?e.appleOs===void 0?e.target!==`desktop`&&e.target!==`tv`:e.appleOs===`ios`||e.appleOs===`ipados`:!1}function Ge(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function Ke(e,t){if(t.platform===`android`){if(t.target!==`tv`)return;throw I(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 I(e,F(e,t));r(t,e.intent)}function F(e,t){return`gesture ${e.intent} is not supported on ${t.appleOs??t.platform}`}function I(t,n,r){return new e(`UNSUPPORTED_OPERATION`,n,{gesture:t.intent,...r?{hint:r}:{}})}const L=`No active session. Run open first.`;function R(e,t,n,r){return{ok:!1,error:{code:e,message:t,...r?.hint?{hint:r.hint}:{},...r?.retriable===void 0?{}:{retriable:r.retriable},...n?{details:n}:{}}}}function qe(){return R(`SESSION_NOT_FOUND`,L)}function Je(e,t,n){if(P(e,t))return null;let r=n?.hint?ze(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 Ye=/^[A-Za-z0-9_.:-]{1,64}$/,z=8*1024,B=4*1024;function Xe(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!Ye.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:Qe(r,n)}}function Ze(t,n,r){let i=o(t),a=$e(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 s=r?JSON.stringify(r):``,c=a.replaceAll(`{event}`,encodeURIComponent(n)).replaceAll(`{payload}`,encodeURIComponent(s)).replaceAll(`{platform}`,encodeURIComponent(i));if(c.length>B)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:c.length,maxLength:B});return c}function Qe(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`)>z)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${z} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function $e(e){return((c(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:u(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}function et(e){let t=e?e.textEntryReadiness:void 0,n=at(t)?{textEntryReadiness:t}:{},r=tt(e);return r?{...n,...r}:n}function tt(e){if(!nt(e))return null;let t=rt(e.target);return t?{verification:`unconfirmed`,requested:e.requested,before:e.before,after:e.after,target:t}:null}function nt(e){return!!(e&&e.verification===`unconfirmed`&&typeof e.requested==`string`&&V(e.before)&&V(e.after))}function rt(e){if(!H(e)||!it(e))return null;let t=ot(e.rect);return t?{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:t}:null}function it(e){return V(e.resourceId)&&V(e.className)&&V(e.packageName)}function at(e){return typeof e==`string`&&ce.includes(e)}function V(e){return e===null||typeof e==`string`}function ot(e){return!H(e)||![e.x,e.y,e.width,e.height].every(e=>typeof e==`number`)?null:e}function H(e){return!!e&&typeof e==`object`}const U=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function st(e,t){return f(e.platform)&&t>1}function ct(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 W(e,t){if(t<=0)return[0,0];let[n,r]=U[e%U.length];return[n*t,r*t]}async function lt(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await pe(t)}async function ut(e,t){let{x:n,y:r}=G(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,...g(`Long pressed (${n}, ${r})`)}}async function dt(t,n){let{x:r,y:i}=G(n,`hover requires x y`,{hint:`Direct platform hover requires coordinates. In an open daemon session, use agent-device hover @ref|selector; otherwise run snapshot -i, use the target rect center as x y, then retry hover x y.`});if(!t.hover)throw new e(`UNSUPPORTED_OPERATION`,`hover is not supported on this platform`,{hint:`hover raises pointer hover state and is available on web targets only. On touch platforms use longpress for hold gestures.`});return await t.hover(r,i),{x:r,y:i,...g(`Hovered (${r}, ${i})`)}}async function ft(e,t){let{x:n,y:r}=G(t,`focus requires x y`);return await e.focus(n,r),{x:n,y:r,...g(`Focused (${n}, ${r})`)}}async function pt(t,n,r){let i=Lt(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=h(r?.delayMs??0,`delay-ms`,0,1e4),s=(await t.type(a,o))?.textEntryRoute;return{...s===void 0?{}:{textEntryRoute:s},text:a,delayMs:o,...g(Y(`Typed`,a))}}async function mt(t,n,r){if(r?.directElementSelector)return await ht(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=h(r?.delayMs??0,`delay-ms`,0,1e4),c=await t.fill(i,a,o,s,{allowNonHittableCoordinateFallback:r?.allowNonHittableCoordinateFallback===!0});return{x:i,y:a,text:o,delayMs:s,...c?.maestroNonHittableCoordinateFallbackUsed===!0?{maestroNonHittableCoordinateFallbackUsed:!0}:{},...et(c),...g(Y(`Filled`,o))}}async function ht(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=h(i.delayMs??0,`delay-ms`,0,1e4),s=await t.fillElementSelector(n,a,o);return{selector:n.raw,text:a,delayMs:o,...s??{},...g(Y(`Filled`,a))}}async function gt(e,t,n,r){if(r?.directElementSelector&&c(e))return await _t(t,r.directElementSelector);let{x:i,y:a}=G(n,`press requires x y`);if(u(e)&&r?.surface&&r.surface!==`app`)return await vt(i,a,r);let o=_(r);if(o!==`primary`)return await yt(e,i,a,o,r);let s=St(r);return Ct(s),st(e,s.count)?await Tt(e,i,a,s,r):await Ot(t,i,a,s)}async function _t(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??{},...g(i?se:`Tapped ${n.raw}`)}}function G(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 vt(t,n,r){let i=_(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,...g(J({x:t,y:n}))}}async function yt(e,t,n,r,i){if(bt(e,r,i),e.platform===`linux`)return await xt(t,n,r);let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.r);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},q(i)),{x:t,y:n,button:r,...g(J({x:t,y:n,button:r}))}}function bt(e,t,n){let r=v({commandLabel:`click`,platform:o(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function xt(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}return{x:e,y:t,button:n,...g(J({x:e,y:t,button:n}))}}function St(e){return{count:K(e?.count,1,`count`,1,200),intervalMs:K(e?.intervalMs,0,`interval-ms`,0,1e4),holdMs:K(e?.holdMs,0,`hold-ms`,0,1e4),jitterPx:K(e?.jitterPx,0,`jitter-px`,0,100),doubleTap:!!e?.doubleTap}}function K(e,t,n,r,i){return h(e===void 0?t:e,n,r,i)}function Ct({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 wt(e,t,n){let{runAppleRunnerCommand:r}=await import(`./runner-client.js`).then(e=>e.r),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=ct(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),q(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Dt(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 Tt(e,t,n,r,i){let a=await wt(e,Et(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,...g(J({x:t,y:n}))}}function Et(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&c(e)&&!d(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=W(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 Dt(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 Ot(e,t,n,r){let i;return await lt(r.count,r.intervalMs,async a=>{let[o,s]=W(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}}),p({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 q(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 kt(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`);At(a,o,s);let c=Ft(i),l={amount:a,pixels:o,durationMs:s},{interactionResult:u,completedPasses:d}=await Mt(t,r,c,l);return p(Nt(c,l,d,u),ne(c.direction,c.edge,d,a,o))}function At(e,t,n){jt(e),ae(n),le({amount:e,pixels:t})}function jt(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Mt(e,t,n,r){if(n.edge){let i=n.edge,a=await te({edge:i,captureState:async n=>await Pt(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 Nt(e,t,n,r){let i=y(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 Pt(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 re({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function Ft(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:ie(e)}}async function It(e,t,n){let{x:r,y:i}=G(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(`./snapshot3.js`);return{action:`read`,text:await e(r,i,n?.surface)}}if(u(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.r),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 Lt(e){return fe(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`}async function Rt(e,t,n,r,i){let a=X(i);return await zt(e,await C(e,a),t,n,r,i,a)}async function zt(e,t,n,r,i,a,o){return b({level:`debug`,phase:`platform_command_prepare`,data:{command:n,platform:e.platform,kind:e.kind}}),await x(`platform_command`,async()=>await Ht(e,t,n,r,i,a,o),{command:n,platform:e.platform})}async function Bt(t,n,r){let i=await C(t,X(r));if(!i.performGesture)throw new e(`UNSUPPORTED_OPERATION`,`Gesture execution is unavailable`);return await i.performGesture(n)}async function Vt(e,t){return await(await C(e,X(t))).gestureViewport?.()}function X(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 Z={press:({device:e,interactor:t,positionals:n,context:r})=>gt(e,t,n,r),longpress:({interactor:e,positionals:t})=>ut(e,t),hover:({interactor:e,positionals:t})=>dt(e,t),focus:({interactor:e,positionals:t})=>ft(e,t),type:({interactor:e,positionals:t,context:n})=>pt(e,t,n),fill:({interactor:e,positionals:t,context:n})=>mt(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>kt(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>Ut(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>Wt(e,t,n,r),viewport:({interactor:e,positionals:t})=>Gt(e,t),back:async({interactor:e,context:t})=>(await e.back(t?.backMode),{action:`back`,mode:t?.backMode??`in-app`,...g(`Back`)}),home:async({interactor:e})=>(await e.home(),{action:`home`,...g(`Home`)}),orientation:async({interactor:e,positionals:t})=>{let n=de(t[0]),r=(await e.setOrientation(n))?.orientation??n;return{action:`orientation`,orientation:r,...g(`Rotated to ${r}`)}},"app-switcher":async({interactor:e})=>(await e.appSwitcher(),{action:`app-switcher`,...g(`Opened app switcher`)}),clipboard:({interactor:e,positionals:t})=>Kt(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>Q(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>qt(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>Qt(e,t,n,r),read:({device:e,positionals:t,context:n})=>It(e,t,n)};async function Ht(t,n,r,i,a,o,s){let c=Object.hasOwn(Z,r)?Z[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 Ut(e,t,n,r){let{eventName:i,payload:a}=Xe(n),o=Ze(e,i,a);return await t.open(o,{appBundleId:r?.appBundleId}),{event:i,eventUrl:o,transport:`deep-link`,...g(`Triggered app event: ${i}`)}}async function Wt(e,n,r,i){let a=n[0]??r??`./screenshot-${Date.now()}.png`;await xe.mkdir(be.dirname(a),{recursive:!0});let o=t(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,...g(`Saved screenshot: ${a}`)}}async function Gt(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=m(n[0],`width`),i=m(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,...g(`Viewport set: ${r}x${i}`)}}async function Kt(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,...g(`Clipboard updated`)}}async function qt(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 a=oe(r[0]),o=i?.durationMs===void 0?void 0:h(i.durationMs,`durationMs`,0,1e4);return await n.tvRemote(a,o),{action:`tv-remote`,button:a,...o===void 0?{}:{durationMs:o},...g(`Pressed TV remote ${a}`)}}async function Q(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!ue(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 Yt(t,a);if(t.platform===`harmonyos`)return await Jt(t,a);if(c(t))return await Xt(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android, HarmonyOS, and iOS`)}async function Jt(t,n){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is not available through the public HarmonyOS HDC API; use keyboard dismiss or enter`);let{pressHarmonyKeyboardKey:r}=await import(`./input-actions2.js`);return await r(t,n===`dismiss`?`Back`:`Enter`),{platform:`harmonyos`,action:n===`dismiss`?`dismiss`:`enter`,...g(n===`dismiss`?`Keyboard dismissed`:`Keyboard enter pressed`)}}async function Yt(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`,...g(`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 Xt(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.r),n=await e(t,{command:`keyboardReturn`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`enter`,visible:n.visible,wasVisible:n.wasVisible,...g(`Keyboard enter pressed`)}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.r),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,...g(Zt(o.dismissed===!0,s))}}function Zt(e,t){return e?t===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`:`Keyboard already hidden`}async function Qt(t,n,r,i){let[a,o,s,c]=r;if(!a||!o&&a!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(a===`clear-app-state`)return await $t(t,n,o,s,i);if(!o)throw new e(`INVALID_ARGS`,`settings requires setting state`);return await en(t,n,a,o,s,c,r,i)}async function $t(t,n,r,i,a){let o=(r===`clear`?i:r)??a?.appBundleId;if(!o)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);b({level:`debug`,phase:`settings_apply`,data:{setting:`clear-app-state`,state:`clear`,appBundleId:o,platform:t.platform}});let s=await n.setSetting(`clear-app-state`,`clear`,o);return s&&typeof s==`object`?p({setting:`clear-app-state`,state:`clear`,...s},$(s)??`Cleared user data for ${o}`):{setting:`clear-app-state`,state:`clear`,...g(`Cleared user data for ${o}`)}}async function en(e,t,n,r,i,a,o,s){let c=n===`location`&&r===`set`,l=(n===`permission`||c?o[4]:o[2])??s?.appBundleId;b({level:`debug`,phase:`settings_apply`,data:nn(e,n,r,i,a,l,c)});let u=await t.setSetting(n,r,l,tn(n,i,a,c));return u&&typeof u==`object`?p({setting:n,state:r,...u},$(u)??`Updated setting: ${n}`):{setting:n,state:r,...g(`Updated setting: ${n}`)}}function tn(e,t,r,i){if(e===`permission`)return{permissionTarget:t,permissionMode:r};if(i)return{latitude:n(t,`latitude`),longitude:n(r,`longitude`)}}function nn(e,t,n,r,i,a,o){return o?{setting:t,state:n,latitude:r,longitude:i,platform:e.platform}:t===`permission`?{setting:t,state:n,permissionTarget:r,permissionMode:i,platform:e.platform}:{setting:t,state:n,appBundleId:a,platform:e.platform}}function $(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}export{R as a,P as c,Ve as d,A as f,L as i,Be as l,Ee as m,Bt as n,qe as o,Te as p,Vt as r,Je as s,Rt as t,He as u};
|
package/dist/src/entities.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e){
|
|
1
|
+
function e(e){return e.replace(/&(#(?:x|X)[0-9a-fA-F]+|#[0-9]+|amp|lt|gt|quot|apos);/g,(e,t)=>{switch(t){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`;default:return n(e,t)}})}function t(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}function n(e,t){let n=t.slice(0,2).toLowerCase()===`#x`?Number.parseInt(t.slice(2),16):Number(t.slice(1));if(!Number.isInteger(n)||n<0||n>1114111)return e;try{return String.fromCodePoint(n)}catch{return e}}export{t as n,e as t};
|
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{Sn as t,Tn as n,bn as r,xn as i}from"./sdk-batch-runner.js";import{$ as a,Et as o,Y as s,Z as c,et as l,gt as u,vn as d,yn as f}from"./script-source-bundle.js";import"./screenshot-result.js";import{t as p}from"./verdict.js";import{a as m,o as h,t as g}from"./dispatch.js";import{At as _,bt as v,jt as y}from"./internal/daemon.js";import{o as b,s as x,t as S}from"./selector-runtime.js";import{t as C}from"./handler-utils.js";function w(e){if(e.ambiguity!==`reject-candidates`)throw Error(`find's resolution policy must reject candidates, got "${e.ambiguity}"`)}async function T(e){let{req:i,sessionName:a,logPath:o,sessionStore:s,invoke:l}=e,d=i.command;if(d!==`find`)return null;let f=r(i.positionals??[],i.flags);if(!f.ok)return m(f.code,f.message);let{locator:g,query:_,action:v,value:y}=f.parsed;if(i.flags?.record&&!t(v))return m(`INVALID_ARGS`,`find ${v} is a mutating action and is always recorded; --record only applies to a read-only find (exists, wait, list, get text, get attrs).`);let b=await S({req:i,sessionName:a,logPath:o,sessionStore:s});if(b)return b;let C=s.get(a);if(!C)return h();let w=C.device,T=n(g,_),A=D({device:w,session:C,req:i,logPath:o,locator:g,query:_,sessionStore:s,sessionName:a}),j={req:i,sessionName:a,logPath:o,sessionStore:s,invoke:l,session:C,device:w,command:d,locator:g,query:_,publicFlags:W(i.flags)},M=await A();if(p(M.snapshotQuality))return O(M.snapshotQuality);let{nodes:N}=M,P=k({nodes:N,locator:g,query:_,selectorExpression:T,flags:i.flags,platform:w.platform});if(!P.ok)return x(P.response,M);let F=P.node,I=await c(u.findAct,N,F),L=I.node,R=await E(j,{node:F,resolvedNode:L,ref:`@${L.ref}`,nodes:N,actionFlags:{...i.flags??{},noRecord:!0},...I.kind===`occluded`?{occludedNode:I.node}:{}},v,y);return R&&x(R,M)}async function E(e,t,n,r){let i={click:()=>L(e,t),fill:()=>R(e,t,r),focus:()=>z(e,t),type:()=>B(e,t,r)}[n];return i?await i():null}function D(e){let{device:t,session:n,req:r,logPath:i,locator:a,query:o}=e,{sessionStore:s,sessionName:c}=e,l=b({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:K(a)},sparseVerdictQueryScope:{query:o,shouldScope:K(a)}}});return{nodes:e.nodes,snapshotQuality:e.snapshotQuality,systemSurfaceOnly:e.systemSurfaceOnly}}}function O(e){return m(`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 k(e){let{nodes:t,locator:n,query:r,selectorExpression:o,flags:c,platform:l}=e,d=u.findAct,f=t.filter(e=>!a(e,t[0])),p=d.resolution,h;if(h=o?s(d,f,o,{platform:l}).list?.matchedNodes??[]:i(f,n,r,{requireRect:p.requireRect}).matches,h=j(h,t),h.length>1){w(p);let e=A(h,c);if(!e)return{ok:!1,response:G(h,n,r)};h=e}let g=h[0]??null;return g?{ok:!0,node:g}:{ok:!1,response:m(`COMMAND_FAILED`,`find did not match any element`)}}function A(e,t){return t?.findFirst?[e[0]]:t?.findLast?[e[e.length-1]]:null}function j(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 M(i.length>0?i:t,n)}function M(e,t){return e.length<2?e:e.map((e,n)=>({node:e,index:n,score:N(e,t)})).sort((e,t)=>t.score===e.score?F(e.node)-F(t.node)||e.index-t.index:t.score-e.score).map(e=>e.node)}function N(e,t){let n=l(t,e);if(n.reason===`covered`)return 0;let r=P(n,t[0]);return r>0?r:e.hittable&&e.rect&&!a(e,t[0])?3:+!!e.rect}function P(e,t){return e.node.rect?e.reason===`semantic-target`||e.reason===`same-rect-descendant`?4:e.reason===`hittable-ancestor`&&!a(e.node,t)?2:0:0}function F(e){return e.rect?e.rect.width*e.rect.height:1/0}function I(e){return{ref:e.ref,node:e.resolvedNode,nodes:e.nodes}}async function L(t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,locator:l,query:u,publicFlags:p}=t,m=await s({token:r.token,session:i,command:`click`,positionals:[n.ref],flags:n.actionFlags,internal:{findResolvedTarget:I(n)}});if(!m.ok)return m;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 _=d(m.data)??`Tapped ${n.ref}${h?` (${h.x}, ${h.y})`:``}`;return Object.assign(g,f(_)),C(a,o,r,c,{ref:n.ref,action:`click`,locator:l,query:u},{flags:p}),{ok:!0,data:g}}async function R(e,t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,publicFlags:l}=e;if(!n)return m(`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:I(t)}});return u.ok&&C(a,o,r,c,{ref:t.ref,action:`fill`},{flags:l}),u}async function z(e,t){let n=await V(e,t);return n.ok&&U(e,t,`focus`),n}async function B(e,t,n){let{req:r,device:i,logPath:a,session:o}=e;if(!n)return m(`INVALID_ARGS`,`find type requires text`);let s=await V(e,t);if(!s.ok)return s;v(o);let c=await g(i,`type`,[n],r.flags?.out,{...y(a,r.flags,o.appBundleId,o.trace?.outPath)});return U(e,t,`type`),{ok:!0,data:c??{ref:t.ref}}}async function V(t,n){let{req:r,device:i,logPath:a,session:o}=t,s=H(n,`be focused`);if(s)return s;let c=n.resolvedNode.rect?e(n.resolvedNode.rect):null;return c?(v(o),{ok:!0,data:await g(i,`focus`,[String(c.x),String(c.y)],r.flags?.out,{...y(a,r.flags,o.appBundleId,o.trace?.outPath)})??{ref:n.ref}}):m(`COMMAND_FAILED`,`matched element has no bounds`)}function H(e,t){let n=e.occludedNode;return n?m(`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 U(e,t,n){let{req:r,sessionStore:i,session:a,command:o,publicFlags:s}=e;C(i,a,r,o,{ref:t.ref,action:n},{flags:s})}function W(e){return{..._(e)??{}}}function G(e,t,n){let r={matches:e.length,candidates:e.slice(0,5).map(e=>o(e,0,!1))};return m(`AMBIGUOUS_MATCH`,`find matched ${e.length} elements for ${t} "${n}". Use a more specific locator or selector.`,{locator:t,query:n,...r})}function K(e){return e!==`role`}export{G as buildAmbiguousMatchError,T as handleFindCommands};
|
package/dist/src/finders.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{wn as e}from"./sdk-batch-runner.js";import{t}from"./sdk-finders.js";export{t as findBestMatchesByLocator,e as parseFindArgs};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{p as e}from"./sdk-batch-runner.js";import{pt as t}from"./internal/daemon.js";import{C as n,x 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{vn as t}from"./script-source-bundle.js";import{t as n}from"./shared.js";import{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};
|
package/dist/src/harmonyos.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{F as t}from"./sdk-android-adb.js";import{n}from"./hdc.js";import{closeHarmonyApp as r,openHarmonyApp as i}from"./app-lifecycle2.js";import{appSwitcherHarmony as a,backHarmony as o,doubleClickHarmony as s,fillHarmony as c,homeHarmony as l,longPressHarmony as u,n as d,performHarmonyGesture as f,pressHarmony as p,scrollHarmony as m,setHarmonyOrientation as h,t as g,typeHarmony as _}from"./input-actions2.js";import{randomUUID as v}from"node:crypto";import{promises as y}from"node:fs";async function b(t,r){let i=`/data/local/tmp/agent-device-screen-${v()}.jpeg`;try{await n(t,[`shell`,`snapshot_display`,`-f`,i],{timeoutMs:15e3}),await n(t,[`file`,`recv`,i,r],{timeoutMs:15e3});let a=await y.readFile(r);if(a.length<3||a[0]!==255||a[1]!==216||a[2]!==255)throw new e(`COMMAND_FAILED`,`HarmonyOS screenshot is not a JPEG file`)}finally{await n(t,[`shell`,`rm`,`-f`,i],{allowFailure:!0}).catch(()=>{})}}async function x(t,r,i,a){if(r!==`clear-app-state`)throw new e(`UNSUPPORTED_OPERATION`,`HarmonyOS setting "${r}" is not supported`,{hint:`HarmonyOS currently supports settings clear-app-state for an app bundle only.`});if(i!==`clear`)throw new e(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!a)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);return await n(t,[`shell`,`aa`,`force-stop`,a],{timeoutMs:15e3}),await n(t,[`shell`,`bm`,`clean`,`-n`,a,`-d`,`-c`],{timeoutMs:15e3}),{bundleId:a,forceStopped:!0,clearedData:!0,clearedCache:!0}}function S(n,v){let y=t=>async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} is not supported on HarmonyOS`)};return{open:(e,t)=>i(n,e,{activity:t?.activity}),openDevice:()=>l(n),close:e=>r(n,e),tap:(e,t)=>p(n,e,t),doubleTap:(e,t)=>s(n,e,t),longPress:(e,t,r)=>u(n,e,t,r),focus:(e,t)=>p(n,e,t),type:(e,t)=>_(n,e,t),fill:(e,t,r,i)=>c(n,e,t,r,i),scroll:(e,t)=>m(n,e,t),performGesture:e=>f(n,e),gestureViewport:()=>g(n),screenshot:e=>b(n,e),snapshot:async e=>({...await t(`snapshot_capture`,async()=>await d(n,e),{backend:`harmonyos-arkui`}),backend:`harmonyos-arkui`}),back:()=>o(n),home:()=>l(n),setOrientation:e=>h(n,e),appSwitcher:()=>a(n),tvRemote:y(`tv-remote`),readClipboard:y(`clipboard`),writeClipboard:y(`clipboard`),setSetting:(e,t,r)=>x(n,e,t,r)}}export{S as createHarmonyInteractor};
|
package/dist/src/hdc.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-android-adb.js";import n from"node:path";import{promises as r}from"node:fs";var i=e({DEFAULT_HARMONY_HDC_TIMEOUT_MS:()=>a,ensureHarmonyToolchainPathConfigured:()=>s,runHarmonyHdc:()=>o});const a=15e3;async function o(e,n,r){return await t(`hdc`,[`-t`,e.id,...n],{timeoutMs:a,...r})}async function s(e=process.env){let t=[e.HDC_SDK_PATH,e.DEVECO_SDK_HOME?n.join(e.DEVECO_SDK_HOME,`default`,`openharmony`,`toolchains`):void 0,e.HARMONYOS_COMMAND_LINE_TOOLS?n.join(e.HARMONYOS_COMMAND_LINE_TOOLS,`sdk`,`default`,`openharmony`,`toolchains`):void 0].filter(e=>!!e?.trim()),i=[];for(let e of t)try{await r.access(n.join(e,`hdc`),r.constants.X_OK),i.push(e)}catch{}if(i.length===0)return;let a=(e.PATH??``).split(n.delimiter).filter(Boolean);e.PATH=[...new Set([...i,...a])].join(n.delimiter)}export{o as n,i as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{E as e,_ as t}from"./sdk-contracts.js";import{a as n,i as r,n as i}from"./sdk-android-adb.js";import{n as a,t as o}from"./version.js";import s from"node:path";import c from"node:crypto";import l from"node:os";import u from"node:fs/promises";function d(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))f(n,t);return p(t),{status:t.status,results:t.results}}function f(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},g(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){m(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},g(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&h(t)}function p(e){m(e),h(e)}function m(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function h(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function g(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function _(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function v(e){if(e===`true`)return!0;if(e===`false`)return!1}function y(e,n,r){if(typeof e!=`number`||!Number.isInteger(e))throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} must be an integer.`);return e}function b(e,n,r,i){if(e!==r)throw new t(`INVALID_ARGS`,`Android ${i} manifest ${n} must be "${r}".`);return r}function x(e,n,r){if(typeof e!=`string`||e.length===0)throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} is required.`);return e}function S(e,n){let r=x(e,`sha256`,n).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new t(`INVALID_ARGS`,`Android ${n} manifest sha256 must be a 64-character hex string.`);return r}const C=1e4;async function w(e){let{adb:t,adbProvider:n,packageName:a,versionCode:o,apkPath:s,sha256:c,cache:l,deviceKey:u,installTimeoutMs:d,helperLabel:f}=e,p=`${u}\0${a}\0${o}\0${c}`;if(l.has(p))return{packageName:a,versionCode:o,installedSha256:c,installed:!1,reason:`current`};await j(s,c,f);let m=await T({adb:t,adbProvider:n,packageName:a,versionCode:o,sha256:c});if(m.reason===`current`)return l.add(p),{packageName:a,versionCode:o,...m,installed:!1};let h=await r(s,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:d});if(h.exitCode!==0)throw i(`Failed to install ${f}`,h,{packageName:a,versionCode:o,reason:m.reason});return l.add(p),{packageName:a,versionCode:o,...m,installed:!0}}async function T(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await O(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 k(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function E(n){let r=a(),i=s.join(o(),`android`,n.helperDirName,`dist`),c=s.join(i,n.manifestFileName(r));try{let e=n.parseManifest(JSON.parse(await u.readFile(c,`utf8`))),t=s.join(i,e.assetName);return await u.access(t),{apkPath:t,manifest:e}}catch(r){throw new t(`UNSUPPORTED_OPERATION`,n.unavailableMessage,{manifestPath:c,error:e(r).message},r)}}function D(e){return async t=>await w({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 O(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:${N(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function k(e,r,a,o){let c=await e([`shell`,`pm`,`path`,a],{allowFailure:!0,timeoutMs:C,signal:o}),d=A(`${c.stdout}\n${c.stderr}`);if(c.exitCode!==0||!d)throw new t(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let f=await u.mkdtemp(s.join(l.tmpdir(),`agent-device-helper-`)),p=s.join(f,`base.apk`);try{let e=await n(d,p,{provider:r,allowFailure:!0,timeoutMs:C,signal:o});if(e.exitCode!==0)throw i(`Could not read installed Android helper APK`,e,{packageName:a,remotePath:d});return await M(p)}finally{await u.rm(f,{recursive:!0,force:!0})}}function A(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function j(e,n,r){let i=await M(e);if(i!==n)throw new t(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:n,actualSha256:i})}async function M(e){let t=c.createHash(`sha256`);return t.update(await u.readFile(e)),t.digest(`hex`)}function N(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}export{d as a,S as c,_ as d,j as i,x as l,D as n,y as o,E as r,b as s,T as t,v as u};
|
package/dist/src/helper.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`),await i(`swift`,[`build`,`-c`,`release`,`--package-path`,t],{cwd:t,timeoutMs:12e4}),await u.mkdir(g,{recursive:!0});let s=`${a}.tmp`;return await u.copyFile(o,s),await u.rename(s,a),await u.chmod(a,493),await u.writeFile(_,`${JSON.stringify({fingerprint:r},null,2)}\n`,`utf8`),a}async function k(){let e=process.env[h]?.trim();if(e){let t=await n(e,h);if(t)return t}if(o())return m;if(process.platform!==`darwin`)throw new t(`UNSUPPORTED_PLATFORM`,`macOS helper is only available on macOS`);return await O()}async function A(e){return r(await k(),[`audio-probe`,`--duration-ms`,String(e.durationMs),`--bucket-ms`,String(e.bucketMs),`--out`,e.statusPath],{allowFailure:!0,captureOutput:!0})}async function j(e,n={}){let r={allowFailure:!0,timeoutMs:3e4,signal:n.signal},o=a().macosHelper,s=o?m:await k(),c=o?await o.run(e,r):await i(s,e,r),l=c.stdout.trim(),u=null;if(l)try{u=JSON.parse(l)}catch{u=null}if(c.exitCode===0&&u?.ok)return u.data;throw new t(`COMMAND_FAILED`,u&&!u.ok?u.error?.message??`macOS helper exited with code ${c.exitCode}`:l||c.stderr.trim()||`macOS helper exited with code ${c.exitCode}`,{helperPath:s,args:e,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,...u&&!u.ok?u.error?.details:{}})}async function M(){return await j([`app`,`frontmost`])}async function N(e){return await j([`app`,`quit`,`--bundle-id`,y(e)])}async function P(e,t){return await j([`permission`,e,t])}async function F(e,t={}){let n=[`alert`,e];return b(n,t),await j(n)}async function I(e,t={}){let n=[`snapshot`,`--surface`,e];return b(n,t),await j(n,{signal:t.signal})}async function L(e,t,n={}){let r=[`read`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function R(e,t,n={}){let r=[`press`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function z(e,t={}){let n=[`screenshot`,`--out`,e];return b(n,t),t.fullscreen&&n.push(`--fullscreen`),await j(n)}export{
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{g as n,v as r}from"./sdk-android-adb.js";import{i,r as a,t as o}from"./tool-provider.js";import s from"node:path";import{createHash as c}from"node:crypto";import{existsSync as l,promises as u}from"node:fs";import d from"node:os";import{fileURLToPath as f}from"node:url";var p=e({quitMacOsApp:()=>N,resolveFrontmostMacOsApp:()=>M,resolveMacOsHelperPackageRootFrom:()=>x,runMacOsAlertAction:()=>F,runMacOsPermissionAction:()=>P,runMacOsPressAction:()=>R,runMacOsReadTextAction:()=>L,runMacOsScreenshotAction:()=>z,runMacOsSnapshotAction:()=>I,startMacOsAudioProbeProcess:()=>A});const m=`agent-device-macos-helper`,h=`AGENT_DEVICE_MACOS_HELPER_BIN`,g=s.join(d.homedir(),`.agent-device`,`macos-helper`,`current`),_=s.join(g,`manifest.json`),v=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function y(e){let n=e.trim();if(!v.test(n))throw new t(`INVALID_ARGS`,`macOS bundle id must use reverse-DNS form like com.example.App`,{bundleId:e});return n}function b(e,t){t.bundleId&&e.push(`--bundle-id`,y(t.bundleId)),t.surface&&e.push(`--surface`,t.surface)}function x(e){let n=s.dirname(e);for(;;){let e=s.join(n,`apple`,`macos-helper`);if(l(s.join(e,`Package.swift`)))return e;let t=s.dirname(n);if(t===n)break;n=t}throw new t(`COMMAND_FAILED`,`Unable to locate macOS helper package root`,{modulePath:e})}function S(){return x(f(import.meta.url))}function C(){return s.join(S(),`.build`,`release`,m)}function w(){return s.join(g,m)}async function T(e){let t=await u.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=s.join(e,t.name);return t.isDirectory()?t.name===`.build`?[]:await T(n):!t.isFile()||!t.name.endsWith(`.swift`)&&t.name!==`Package.swift`?[]:[n]}))).flat().sort()}async function E(e){let t=await T(e),n=c(`sha256`);for(let r of t)n.update(s.relative(e,r)),n.update(`\0`),n.update(await u.readFile(r)),n.update(`\0`);let r=await i(`swift`,[`--version`],{allowFailure:!0,cwd:e,timeoutMs:1e4});return n.update(`swift-version`),n.update(`\0`),n.update(r.stdout||r.stderr||`exit:${r.exitCode}`),n.update(`\0`),n.digest(`hex`)}async function D(){try{let e=JSON.parse(await u.readFile(_,`utf8`));return typeof e.fingerprint==`string`?e.fingerprint:null}catch{return null}}async function O(){let e=await n(process.env[h],h);if(e)return e;let t=S(),r=await E(t),a=w();try{if(await D()===r)return await u.access(a),a}catch{}let o=C();process.stderr.write(`agent-device: building macOS helper (first run or helper update)
|
|
2
|
+
`),await i(`swift`,[`build`,`-c`,`release`,`--package-path`,t],{cwd:t,timeoutMs:12e4}),await u.mkdir(g,{recursive:!0});let s=`${a}.tmp`;return await u.copyFile(o,s),await u.rename(s,a),await u.chmod(a,493),await u.writeFile(_,`${JSON.stringify({fingerprint:r},null,2)}\n`,`utf8`),a}async function k(){let e=process.env[h]?.trim();if(e){let t=await n(e,h);if(t)return t}if(o())return m;if(process.platform!==`darwin`)throw new t(`UNSUPPORTED_PLATFORM`,`macOS helper is only available on macOS`);return await O()}async function A(e){return r(await k(),[`audio-probe`,`--duration-ms`,String(e.durationMs),`--bucket-ms`,String(e.bucketMs),`--out`,e.statusPath],{allowFailure:!0,captureOutput:!0})}async function j(e,n={}){let r={allowFailure:!0,timeoutMs:3e4,signal:n.signal},o=a().macosHelper,s=o?m:await k(),c=o?await o.run(e,r):await i(s,e,r),l=c.stdout.trim(),u=null;if(l)try{u=JSON.parse(l)}catch{u=null}if(c.exitCode===0&&u?.ok)return u.data;throw new t(`COMMAND_FAILED`,u&&!u.ok?u.error?.message??`macOS helper exited with code ${c.exitCode}`:l||c.stderr.trim()||`macOS helper exited with code ${c.exitCode}`,{helperPath:s,args:e,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,...u&&!u.ok?u.error?.details:{}})}async function M(){return await j([`app`,`frontmost`])}async function N(e){return await j([`app`,`quit`,`--bundle-id`,y(e)])}async function P(e,t){return await j([`permission`,e,t])}async function F(e,t={}){let n=[`alert`,e];return b(n,t),await j(n)}async function I(e,t={}){let n=[`snapshot`,`--surface`,e];return b(n,t),await j(n,{signal:t.signal})}async function L(e,t,n={}){let r=[`read`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function R(e,t,n={}){let r=[`press`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function z(e,t={}){let n=[`screenshot`,`--out`,e];return b(n,t),t.fullscreen&&n.push(`--fullscreen`),await j(n)}export{z as a,P as i,N as n,A as o,F as r,p as t};
|
package/dist/src/host-process.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{S as e,_ as t}from"./sdk-android-adb.js";import{t as n}from"./timeouts.js";const r=1e3,i=process.platform===`win32`?`ps`:`/bin/ps`;function a(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function o(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,0),!0}catch(e){return e.code===`EPERM`}}function s(e){return d(e,`lstart=`)}function c(e){return d(e,`command=`)}function l(e){return d(e,`state=`)?.startsWith(`Z`)??!1}function u(t){let n=new Map,i=h(t);if(i.length===0)return n;try{let t=e(`ps`,[`-p`,i.join(`,`),`-o`,`pid=,state=,lstart=`],{allowFailure:!0,timeoutMs:r});if(t.exitCode!==0)return n;for(let e of t.stdout.split(`
|
|
2
2
|
`)){let t=/^\s*(\d+)\s+(\S+)\s+(.+?)\s*$/.exec(e);if(!t)continue;let r=Number.parseInt(t[1],10);!Number.isInteger(r)||r<=0||n.set(r,{state:t[2],startTime:t[3]})}}catch{}return n}function d(t,n){if(!Number.isInteger(t)||t<=0)return null;try{let a=e(i,[`-p`,String(t),`-o`,n],{allowFailure:!0,timeoutMs:r});if(a.exitCode!==0)return null;let o=a.stdout.trim();return o.length>0?o:null}catch{return null}}function f(e){let t=[];for(let n of e.split(`
|
|
3
3
|
`)){let e=/^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10),i=Number.parseInt(e[2],10),a=e[3];!Number.isInteger(r)||r<=0||t.push({pid:r,ppid:Number.isInteger(i)&&i>0?i:void 0,command:a})}return t}async function p(e){let n=await(e.runCommand??t)(e.runCommand?`ps`:i,[`-ax`,`-o`,`pid=,ppid=,command=`],{allowFailure:!0,timeoutMs:e.timeoutMs});return n.exitCode===0?f(n.stdout):[]}function m(e,t){let n=new Set(h(e)),r=!0;for(;r;){r=!1;for(let e of t)e.ppid===void 0||!n.has(e.ppid)||n.has(e.pid)||(n.add(e.pid),r=!0)}return t.filter(e=>n.has(e.pid))}function h(e,t={}){return[...new Set(e)].filter(e=>Number.isInteger(e)&&e>0&&e!==t.excludePid)}function g(e,t){let n=h(e,{excludePid:process.pid}),r=0;for(let e of n)try{process.kill(e,t),r+=1}catch{}return r}async function _(e,t){if(!a(e))return!0;let r=Date.now();for(;Date.now()-r<t;)if(await n(50),!a(e))return!0;return!a(e)}async function v(e){let t=h(e.pids,{excludePid:process.pid});t.length!==0&&(g(t,`SIGTERM`),await Promise.all(t.map(async t=>await _(t,e.termTimeoutMs))),g(t.filter(e=>a(e)),`SIGKILL`),await Promise.all(t.map(async t=>await _(t,e.killTimeoutMs))))}export{p as a,s as c,_ as d,l as i,g as l,a as n,u as o,o as r,c as s,m as t,v as u};
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import{
|
|
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=pe(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||!u(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||u(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=ue.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 rn(e,t,r,i){return new Promise((a,o)=>{let s=ue.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 an(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return dn(await rn(e.port,`snapshot ${t}`,on(e),e.signal),t)}function on(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function sn(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 cn(e){let t=e.indexOf(`
|
|
3
|
-
|
|
4
|
-
`);return mn(e.slice(0,t<0?e.length:t))}function ln(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 un(e,t){let n=cn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function dn(e,t){let r=e.indexOf(`
|
|
5
|
-
|
|
6
|
-
`);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=mn(e.slice(0,r)),a=e.slice(r+2);return fn(i,t),pn(i,a),{xml:a,metadata:hn(i)}}function fn(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 pn(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 mn(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 hn(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 gn=5e3,B=new Map,_n=new Map;async function vn(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!jn()||!e.adbProvider?.spawn)return;let n=xn(Ft(e)),r=await yn({deviceKey:t,identity:An(t,n,e),options:e,resolved:n});if(r)return await bn({session:r,deviceKey:t,options:e,resolved:n})}async function yn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(_n.get(t)===n)return;let a=B.get(t);if(a&&a.identity!==n&&(await V(t),a=void 0),!a)try{a=await kn({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),_n.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 bn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await an({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 V(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:Sn(e)}});return}}function xn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function Sn(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 Cn(e){let t=B.get(e.deviceKey);if(!t)return;if(!wn(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 V(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=cn(await rn(t.port,i,e.timeoutMs)),ln(a,r)}catch(t){throw await V(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 wn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&Tn(e.helperVersion,t.helperVersion)&&Tn(e.helperVersionCode,t.helperVersionCode)&&Tn(e.sha256,t.sha256)}function Tn(e,t){return e===void 0||t===void 0||e===t}async function V(e,t={}){let n=B.get(e);if(!n)return!1;B.delete(e);let r=kt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await En(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:wt:gn,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})]);return h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,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}),!0}async function En(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=un(await rn(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 Dn(e){await V(P(e))}async function On(){let e=await Promise.allSettled([...B.keys()].map(e=>V(e)));_n.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 kn(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:gn,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 sn(o,1e4,e.options.signal),B.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 An(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 jn(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const Mn=1e4;async function Nn(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 Bn(a,o,u);let f=await Pn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let p=await ne(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(p.exitCode!==0)throw g(`Failed to install ${u}`,p,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Pn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await Ln(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 Rn(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Fn(t){let r=o(),i=v.join(l(),`android`,t.helperDirName,`dist`),a=v.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await y.readFile(a,`utf8`))),n=v.join(i,e.assetName);return await y.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function In(e){return async t=>await Nn({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 Ln(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:${Hn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Rn(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:Mn,signal:i}),o=zn(`${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 y.mkdtemp(v.join(le.tmpdir(),`agent-device-helper-`)),c=v.join(s,`base.apk`);try{let e=await ee(o,c,{provider:t,allowFailure:!0,timeoutMs:Mn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Vn(c)}finally{await y.rm(s,{recursive:!0,force:!0})}}function zn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function Bn(e,t,r){let i=await Vn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Vn(e){let t=ce.createHash(`sha256`);return t.update(await y.readFile(e)),t.digest(`hex`)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const H=new Map;function Un(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of H.keys())e.startsWith(t)&&Kn(e)}function Wn(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Gn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of H.keys())t!==e&&t.startsWith(i)&&H.delete(t);H.set(e,t)}function Kn(e){e&&H.delete(e)}async function qn(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=Wn(e.deviceKey,i,a,o),c=s?H.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 Bn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Xn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Pn({adb:t,adbProvider:Yn(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 Gn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Zn(t,e.adbProvider??t,n.apkPath,ht(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Kn(s),Jn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Kn(s),Jn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Gn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function Jn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Yn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Xn(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 Qn(`${i.stdout}\n${i.stderr}`,t)}async function Zn(e,t,n,r,i){let a=async()=>await ne(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!$n(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
|
-
`)}}function Qn(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 $n(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const er=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function tr(e){return er.has(e)}const nr=new Set([`android`,`com.android.systemui`]),rr=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,U=/^android:id\/button[123]$/i,ir=/(?:^|:)id\/permission_/i,ar=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,or=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,sr=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function cr(e){if(e!==null){if(U.test(e))return`button`;if(rr.test(e))return`content`}}function lr(e){let t=dr(e),n=t.nodes;if(n.length===0)return null;let r=gr(n),i=n.filter(e=>W(e)&&!Er(e)),a=yr(i),o=br(i,a),s=Dr(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 ur(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 dr(e){let t=e.filter(e=>wr(e));if(t.length)return{nodes:t,source:`permission`};let n=hr(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:fr(e),source:`native-dialog`}}function fr(e){let t=e.filter(e=>pr(e.type??``)),n=e.filter(e=>rr.test(e.identifier??``)),r=t.length?[...t,...n]:mr(n);if(r.length===0)return[];let i=xr(e,r);return i===void 0?r:Cr(e,i)}function pr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function mr(e){let t=e.some(e=>U.test(e.identifier??``)),n=e.some(e=>!U.test(e.identifier??``));return t&&n?e:[]}function hr(e){let t=e.filter(e=>Tr(e));if(t.length===0)return[];let n=xr(e,t);return n===void 0?t:Cr(e,n).filter(e=>e.bundleId&&nr.has(e.bundleId))}function gr(e){let t=new Set,n=[];for(let r of e){let e=W(r);if(!e||!r.rect||!Er(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:_r(r,e)})}return n}function _r(e,t){return vr(e.identifier??``)||(or.test(t.trim())?`accept`:sr.test(t.trim())?`dismiss`:`neutral`)}function vr(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 yr(e){return W(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||W(e[0])}function br(e,t){let n=e.map(e=>W(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
8
|
-
`):void 0}function xr(e,t){let n=t[0];if(!n)return;let r=Sr(e,n.index);for(let n of t.slice(1)){let t=new Set(Sr(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 Sr(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 Cr(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 wr(e){let t=e.bundleId??``;return er.has(t)||ir.test(e.identifier??``)}function Tr(e){let t=e.bundleId??``;return nr.has(t)&&ar.test(W(e))}function Er(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||U.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function W(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Dr(e){return e.find(e=>e.bundleId)?.bundleId}const Or=new Set([`android`,`com.android.systemui`]);function kr(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=zr(e,n.foregroundAppPackage);return jr(r,t)?G(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Lr(r)?{outcome:`ok`}:Ar(r)?{outcome:`system-surface-only`}:Mr(r)?{outcome:`ok`}:Nr(r)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Pr(r)||Fr(r,t)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Ir(r)?G(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function G(e,t,n,r){return{outcome:`unusable`,decision:Rr(e,t,n,r)}}function Ar(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function jr(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function Mr(e){return Nr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Nr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Pr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Fr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Ir(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Lr(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Rr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:$r(e,t)}}function zr(e,t){let n=Br(t);for(let t of fe(e))Vr(n,t);return Jr(n)}function Br(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 Vr(e,t){e.nodeCount+=1,Qr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Hr(e,t.resourceId),Ur(e,t),Wr(e,t)}function Hr(e,t){let n=cr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Ur(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 Wr(e,t){Yr(t)&&(e.meaningfulNodeCount+=1,Gr(e,t),qr(e,t))}function Gr(e,t){e.currentWindowType===1&&!Zr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Kr(e)&&!f(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Kr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function qr(e,t){Zr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),p({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Jr(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 Yr(e){return e.visibleToUser===!1?!1:Xr(e.text)||Xr(e.desc)||Xr(e.resourceId)}function Xr(e){return e!==null&&e.trim()!==``}function Zr(e){return e===null||Or.has(e)}function Qr(e){return e!==null&&Or.has(e)}function $r(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function ei(e){let t=await V(e.deviceKey,{signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await ti(e.adb,e.packageName)}async function ti(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await ae(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}})}}const ni=5e3,ri=3e4;async function ii(e,t={}){let n=_(e,t.helperAdb).exec;return(await li(e,t,n)).xml}async function ai(e,t={}){let n=_(e,t.helperAdb).exec,r=await li(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=me(i,void 0,t),n=oi(e.truncated,r.metadata);return{...e,...si(n),androidSnapshot:r.metadata}}let a=ke(i),o=b(a,void 0,t),s=oi(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ci({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...si(s),androidSnapshot:r.metadata}}function oi(e,t){return e===!0||t.helperTruncated===!0?!0:e}function si(e){return e===!0?{truncated:!0}:{}}function ci(e){if(Oi(e.interactiveSnapshot.nodes).size>0||Di(e.xml))return;let t=b(e.tree,void 0,{...e.options,interactiveOnly:!1});ki(c(r(t.nodes)),t,e.interactiveSnapshot)}async function li(e,t,n){let r=_(e,t.helperAdb),i=await m(`android_snapshot_helper_artifact_resolution`,async()=>await Ti(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await ui(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),Ei(i.errorReason)}async function ui(e,t,n,r){let i=P(e),a=_(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await hi(t.signal);let s=await mi({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 gi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal});e=s.decision.reason}}finally{o&&await V(i)}}async function di(e,t,n,r,i){let a=await m(`android_snapshot_helper_install`,async()=>await qn({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 fi(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:ni,commandTimeoutMs:ri,signal:n};try{let e=await m(`android_snapshot_helper_session_capture`,async()=>await vn(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni});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 ti(r,a.manifest.packageName)}return await m(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni,commandTimeoutMs:ri})}function pi(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 mi(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await di(t,n,r,i,a);e.installed&&await V(a),s=pi(await fi({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await _i({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=kr(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 hi(e){e?.throwIfAborted(),await ae(250),e?.throwIfAborted()}async function gi(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 ei({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),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 _i(e){let t=vi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await V(e.helperDeviceKey),await ti(e.adb,e.artifact.manifest.packageName),Un({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),yi(e.error,t)}function vi(t){let n=e(t),r=Ci(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 yi(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...xi(a),androidSnapshotHelperFailureReason:i,hint:bi(a)},r)}function bi(e){return wi(e.details?.helper,e.message)||Si(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 xi(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 Si(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function Ci(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function wi(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=Ci(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ti(t){if(t)return{artifact:t};let n=o(),r=v.join(l(),`android`,`snapshot-helper`,`dist`),i=v.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await y.access(i)}catch{return{}}try{let e=mt(JSON.parse(await y.readFile(i,`utf8`))),t=v.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await y.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function Ei(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 Di(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Oi(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 ki(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 K=`IME helper`,Ai=`android-ime-helper-v1`;async function ji(){return await Fn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Mi,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Mi(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`,K),version:E(t.version,`version`,K),assetName:E(t.assetName,`assetName`,K),sha256:ft(t.sha256,K),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,K),versionCode:dt(t.versionCode,`versionCode`,K),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,K),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Ai,K)}}const Ni=In({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function q(e){return`${e.platform}:${e.id}`}async function Pi(e,t,n){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Fi(e,t){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Ii(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Ai);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 J=`agent_device_ime_helper_previous_ime`,Y=`secure`,Li=`default_input_method`,X=new Set;function Ri(e){return X.has(q(e))}function Z(e){return v.join(e,`android-test-ime-pending`)}function zi(e,t){return v.join(Z(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Bi(t,n){try{await y.mkdir(Z(t),{recursive:!0}),await y.writeFile(zi(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 Vi(e,t){await y.rm(zi(e,t),{force:!0}).catch(()=>{})}async function Hi(e){let t;try{t=await y.readdir(Z(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await y.readFile(v.join(Z(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Ui(e,t={}){let n=re(e),r=_(e),i=await ji(),{manifest:a}=i,o=q(e);await Ni({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await Q(n);if(s===a.serviceComponent)return X.add(o),t.stateDir&&await Bi(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await $(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(X.add(o),!await Ji(n,s))return X.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 Bi(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 Q(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}):(X.delete(o),await Yi(n).catch(()=>{}),t.stateDir&&await Vi(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 Wi(e,t={}){let n=q(e);if(!X.has(n))return{restored:!1,reason:`no-record`};X.delete(n);let r=await Ki(re(e),e);return t.stateDir&&Gi(r.reason)&&await Vi(t.stateDir,e.id),r}function Gi(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Ki(e,t){let n=t.id;if(X.has(q(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await $(e);if(!r)return{restored:!1,reason:`no-record`};let i=await Q(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 Q(e);return a===r?(await Yi(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 qi(t){let n=await Hi(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 Ki(re(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Gi(e.reason)&&await Vi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function Q(e){let t=await e([`shell`,`settings`,`get`,Y,Li],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)}async function $(e){let t=await e([`shell`,`settings`,`get`,Y,J],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)||void 0}async function Ji(e,t){return(await e([`shell`,`settings`,`put`,Y,J,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await $(e)===t:!1}async function Yi(e){await e([`shell`,`settings`,`delete`,Y,J],{allowFailure:!0,timeoutMs:5e3})}function Xi(e){let t=e.trim();return!t||t===`null`?``:t}async function Zi(){try{return(await ie(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
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 Qi={previousIme:J,defaultInputMethod:Li};export{F as C,C as D,S as E,fe as O,P as S,D as T,Fn as _,Q as a,V as b,Fi as c,ii as d,ai as f,qn as g,tr as h,Zi as i,ji as l,lr as m,Ui as n,Wi as o,ur as p,Ri as r,qi as s,Qi as t,Pi as u,On as v,mt as w,Dn as x,Cn as y};
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{E as t,_ as n}from"./sdk-contracts.js";import{mt as r}from"./sdk-batch-runner.js";import{A as i,_ as a,n as o,o as s,s as c}from"./sdk-android-adb.js";import{c as l,l as u,n as d,o as f,r as p,s as m}from"./helper-package-install.js";import{t as h}from"./keyed-lock.js";import{i as g,r as _,t as v}from"./ime-recovery-marker.js";const y=`IME helper`,b=`android-ime-helper-v1`;async function x(e){return e.imeHelperArtifact??await S()}async function S(){return await p({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:C,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function C(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:m(t.name,`name`,`android-ime-helper`,y),version:u(t.version,`version`,y),assetName:u(t.assetName,`assetName`,y),sha256:l(t.sha256,y),packageName:m(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,y),versionCode:f(t.versionCode,`versionCode`,y),serviceComponent:m(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,y),broadcastProtocol:m(t.broadcastProtocol,`broadcastProtocol`,b,y)}}const w=d({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function T(e){return`${e.platform}:${e.id}`}async function E(e,t,n){await O(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function D(e,t){await O(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function O(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,b);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 o(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}var k=e({ANDROID_TEST_IME_SETTINGS_KEYS:()=>Z,activateAndroidTestIme:()=>I,isAndroidTestImeActive:()=>F,listAndroidAdbSerialsQuick:()=>X,readAndroidDefaultInputMethod:()=>U,restoreAndroidTestIme:()=>R,restoreOrphanedAndroidTestImeOnDaemonStartup:()=>V});const A=`agent_device_ime_helper_previous_ime`,j=`secure`,M=`default_input_method`,N=new Set,P=new Map;function F(e){return N.has(T(e))}async function I(e,t){return await r(t.stateDir),await H(t.stateDir,e.id,async()=>await L(e,t))}async function L(e,n){let r=s(e),a=c(e),o=T(e),l;try{l=await x(a),await w({adb:r,adbProvider:a,artifact:l,deviceKey:o})}catch(e){return{outcome:`helper-unavailable`,reason:t(e).message}}let{manifest:u}=l,d=await U(r);if(d===u.serviceComponent){let t=await g(n.stateDir,e.id),i=await W(r);return t&&N.add(o),{outcome:`settled`,activated:!1,alreadyActive:!0,...t?{}:{persistFailed:!0},previousIme:i,helperServiceComponent:u.serviceComponent,helperPackageName:u.packageName}}let f=await W(r);if(!await G(r,d))return await q(r,f,e.id),i({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:d}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:u.serviceComponent,helperPackageName:u.packageName};let p=(await _(n.stateDir)).includes(e.id);if(!await g(n.stateDir,e.id))return await q(r,f,e.id),i({level:`warn`,phase:`android_test_ime_marker_persist_failed`,data:{device:e.id,previousIme:d}}),{outcome:`settled`,activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:u.serviceComponent,helperPackageName:u.packageName};await r([`shell`,`ime`,`enable`,u.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let m=await r([`shell`,`ime`,`set`,u.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),h=await U(r);return h===u.serviceComponent?(N.add(o),i({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:d}}),{outcome:`settled`,activated:!0,alreadyActive:!1,previousIme:d,helperServiceComponent:u.serviceComponent,helperPackageName:u.packageName}):(N.delete(o),await q(r,f,e.id),p||await v(n.stateDir,e.id),i({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:h,stderr:m.stderr.trim()}}),{outcome:`settled`,activated:!1,alreadyActive:!1,helperServiceComponent:u.serviceComponent,helperPackageName:u.packageName})}async function R(e,t){return await H(t.stateDir,e.id,async()=>{let n=T(e);if(!N.has(n))return{restored:!1,reason:`no-record`};N.delete(n);let r=await B(s(e),e);return z(r.reason)&&await v(t.stateDir,e.id),r})}function z(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function B(e,t){let n=t.id;if(N.has(T(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await W(e);if(!r)return{restored:!1,reason:`no-record`};let a=await U(e);if(a!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return i({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:a,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let o=await U(e);return o===r?(await K(e).catch(()=>{}),i({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(i({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:o}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function V(e){let n=await _(e.stateDir);if(n.length===0)return;let r;try{r=new Set(await e.listSerials())}catch(e){i({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:t(e).message}});return}for(let a of n){if(!r.has(a))continue;let n={platform:`android`,id:a,name:a,kind:a.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{await H(e.stateDir,a,async()=>{let t=await B(s(n),n);t.restored&&i({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:a,previousIme:t.previousIme}}),z(t.reason)&&await v(e.stateDir,a)})}catch(e){i({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:a,error:t(e).message}})}}}function H(e,t,n){return h(P,`${e}:${t}`,n)}async function U(e){let t=await e([`shell`,`settings`,`get`,j,M],{allowFailure:!0,timeoutMs:5e3});return Y(t.exitCode===0?t.stdout:``)}async function W(e){let t=await e([`shell`,`settings`,`get`,j,A],{allowFailure:!0,timeoutMs:5e3});return Y(t.exitCode===0?t.stdout:``)||void 0}async function G(e,t){return(await e([`shell`,`settings`,`put`,j,A,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await W(e)===t:!1}async function K(e){await e([`shell`,`settings`,`delete`,j,A],{allowFailure:!0,timeoutMs:5e3})}async function q(e,n,r){try{(n?await G(e,n):await J(e))||i({level:`warn`,phase:`android_test_ime_record_rollback_failed`,data:{device:r,hadPriorRecord:n!==void 0}})}catch(e){i({level:`warn`,phase:`android_test_ime_record_rollback_failed`,data:{device:r,hadPriorRecord:n!==void 0,error:t(e).message}})}}async function J(e){return await K(e),await W(e)===void 0}function Y(e){let t=e.trim();return!t||t===`null`?``:t}async function X(){try{return(await a(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
2
|
+
`).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 Z={previousIme:A,defaultInputMethod:M};export{D as a,E as c,U as i,k as n,S as o,F as r,x as s,Z as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{E as t}from"./sdk-contracts.js";import{A as n}from"./sdk-android-adb.js";import r from"node:path";import{randomUUID as i}from"node:crypto";import a from"node:fs/promises";var o=e({clearAndroidTestImeRecoveryMarker:()=>d,readAndroidTestImeRecoveryMarkers:()=>f,writeAndroidTestImeRecoveryMarker:()=>l});function s(e){return r.join(e,`android-test-ime-pending`)}function c(e,t){return r.join(s(e),encodeURIComponent(t))}async function l(e,o){let l,d,f,m=!1;try{let t=s(e);if(f=c(e,o),await a.mkdir(t,{recursive:!0}),(await p(f))?.serial===o)return!0;l=r.join(t,`.${encodeURIComponent(o)}.${i()}.tmp`);let n={version:1,serial:o};if(d=await a.open(l,`wx`,384),await d.writeFile(`${JSON.stringify(n)}\n`,`utf8`),await d.sync(),await d.close(),d=void 0,await a.rename(l,f),l=void 0,m=!0,await u(t),(await p(f))?.serial!==o)throw Error(`Android test IME marker read-back did not match the requested device.`);return!0}catch(r){return d&&await d.close().catch(()=>{}),l&&await a.rm(l,{force:!0}).catch(()=>{}),m&&f&&await a.rm(f,{force:!0}).catch(()=>{}),n({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:e,serial:o,error:t(r).message}}),!1}}async function u(e){let t;try{t=await a.open(e,`r`),await t.sync()}catch{}finally{t&&await t.close().catch(()=>{})}}async function d(e,t){await a.rm(c(e,t),{force:!0}).catch(()=>{})}async function f(e){let t;try{t=await a.readdir(s(e))}catch{return[]}let n=[];for(let i of t)try{let t=r.join(s(e),i),a=await p(t);a&&c(e,a.serial)===t&&n.push(a.serial)}catch{}return[...new Set(n)].sort()}async function p(e){try{return m(await a.readFile(e,`utf8`))}catch{return}}function m(e){try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))return;let n=t;return n.version===1&&typeof n.serial==`string`&&n.serial.length>0?{version:1,serial:n.serial}:void 0}catch{return}}export{l as i,o as n,f as r,d as t};
|