agent-device 0.20.2 → 0.20.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.2.apk → agent-device-android-ime-helper-0.20.4.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.4.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.2.manifest.json → agent-device-android-ime-helper-0.20.4.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.4.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.4.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.2.manifest.json → agent-device-android-snapshot-helper-0.20.4.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +57 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +45 -185
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +257 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +3 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +8 -2
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.d.ts +4 -27
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -0
- package/dist/src/app-inventory.d.ts +4 -0
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +27 -19
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -14
- package/dist/src/client-metro.js +1 -1
- package/dist/src/{tv-remote.d.ts → cloud-artifacts.d.ts} +109 -126
- 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/context.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/debug-symbols.js +4 -4
- package/dist/src/device-input-state.d.ts +26 -0
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device.js +1 -9
- package/dist/src/devices2.js +1 -1
- package/dist/src/entities.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.d.ts +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/ime-lifecycle.js +9 -0
- package/dist/src/index.d.ts +593 -556
- package/dist/src/input-actions.js +4 -4
- package/dist/src/install-artifact.js +4 -4
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.d.ts +7 -4
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +14 -14
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +171 -190
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/metro.d.ts +1 -1
- package/dist/src/parser.js +2 -0
- package/dist/src/path-resolution.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/plist-xml.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -1
- package/dist/src/provider-limrun-runtime.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +22 -22
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/reporting.js +7 -7
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-provider.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/screenshot-geometry.js +1 -0
- package/dist/src/screenshot-result.js +6 -0
- package/dist/src/sdk-android-adb.d.ts +5 -6
- package/dist/src/sdk-android-adb.js +3 -3
- package/dist/src/sdk-batch-runner.d.ts +2 -2
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +21 -25
- package/dist/src/sdk-contracts.js +2 -2
- 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.d.ts +19 -4
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +8 -8
- package/dist/src/setting-state.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.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/version.js +1 -1
- package/dist/src/viewport-dimension.js +14 -0
- package/package.json +28 -19
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.2.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.2.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.2.apk.sha256 +0 -1
- package/dist/src/android-input-method-overlays.js +0 -1
- package/dist/src/android-input-ownership.js +0 -1
- package/dist/src/apple-multitouch-support.js +0 -1
- package/dist/src/click-button.d.ts +0 -5
- package/dist/src/compatibility-policy.js +0 -1
- package/dist/src/gesture-plan-types.js +0 -1
- package/dist/src/gesture-plan.js +0 -1
- package/dist/src/launch-console.js +0 -1
- package/dist/src/recording-export-quality.js +0 -15
- package/dist/src/rolldown-runtime.js +0 -1
- package/dist/src/runtime2.js +0 -1
- package/dist/src/sdk-app-inventory.d.ts +0 -4
- package/dist/src/sdk-app-inventory.js +0 -1
- package/dist/src/snapshot-diagnostics.js +0 -6
- package/dist/src/xml.js +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
2
|
-
`);if(n===-1)return null;let r=e.slice(0,n),i=p(e.slice(n+1));return i?{header:r,payload:i}:null}function re(e,t){let n=new Map(t.map(e=>[e.index,e]));return e.flatMap((e,t)=>ie(e).flatMap((e,r)=>ae(e,n,t,r)))}function ie(e){return!
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{q as t}from"./sdk-batch-runner.js";import{h as n,v as r}from"./sdk-android-adb.js";import i from"node:path";import a from"node:fs/promises";const o=/^[0-9a-fA-F-]{32,36}$/;function s(e){if(!(!e||!o.test(e)))return e.replaceAll(`-`,``).toUpperCase()}function c(e,t){return`${e.uuid}:${l(t)}`}function l(e){return`0x${e.toString(16)}`}function u(e){return typeof e==`string`&&e.length>0?e:void 0}function d(...e){for(let t of e){let e=u(t);if(e)return e}}function f(e){let t=e.filter(e=>!!e);return t.length>0?t.join(` `):void 0}function p(e){try{let n=JSON.parse(e);return t(n)?n:null}catch{return null}}function m(e){if(typeof e==`number`&&Number.isSafeInteger(e))return e;if(typeof e==`string`){let t=e.startsWith(`0x`)?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function h(e,t,n){if(!Object.hasOwn(e,t))return;let r=m(e[t]);if(r!==void 0)return r;v(n,t)}function g(e,t,n){if(!Object.hasOwn(e,t))return;let r=_(e[t]);if(r!==void 0)return r;v(n,t)}function _(e){if(typeof e==`bigint`)return e;if(typeof e==`number`&&Number.isSafeInteger(e)||typeof e==`string`&&/^(?:0x[0-9a-fA-F]+|\d+)$/.test(e))return BigInt(e)}function v(t,n){throw new e(`INVALID_ARGS`,`Invalid ${t} numeric field: ${n}`,{hint:`Crash artifact numeric fields must be integer numbers or integer numeric strings.`})}function y(e){return e.length===1?e[0]:void 0}function b(e){return[...new Set(e)]}function x(e){let t=e.match(/^(.*) \+ (\d+)$/);return t?{symbol:t[1],location:Number(t[2])}:{symbol:e}}const S=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;function ee(e){return te(e)??w(e)}function te(e){let t=ne(e);if(!t)return null;let n=(Array.isArray(t.payload.usedImages)?t.payload.usedImages:[]).flatMap((e,t)=>C(e,t));if(n.length===0)return null;let r=re(Array.isArray(t.payload.threads)?t.payload.threads:[],n);return{format:`ips`,images:n,addresses:r.map(({frame:e,...t})=>t),document:t,frameMatches:r,write:e=>oe(t,r,e)}}function ne(e){let t=p(e);if(t)return{payload:t};let n=e.indexOf(`
|
|
2
|
+
`);if(n===-1)return null;let r=e.slice(0,n),i=p(e.slice(n+1));return i?{header:r,payload:i}:null}function re(e,t){let n=new Map(t.map(e=>[e.index,e]));return e.flatMap((e,t)=>ie(e).flatMap((e,r)=>ae(e,n,t,r)))}function ie(e){return!t(e)||!Array.isArray(e.frames)?[]:e.frames.filter(t)}function ae(e,t,n,r){let i=h(e,`imageIndex`,`IPS frame`),a=g(e,`imageOffset`,`IPS frame`);if(i===void 0||a===void 0)return[];let o=t.get(i);return o?[{frame:e,frameIndex:r,threadIndex:n,image:o,address:o.base+a}]:[]}function oe(e,t,n){for(let e of t){let t=n.get(c(e.image,e.address))?.text;t&&se(e.frame,t)}e.payload.agentDeviceSymbolication={tool:`agent-device debug symbols`,symbolicatedFrames:[...n.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}\n`;return e.header?`${e.header}\n${r}`:r}function se(e,t){let n=x(t);e.symbol=n.symbol,n.location!==void 0&&(e.symbolLocation=n.location)}function C(e,n){if(!t(e))return[];let r=s(u(e.uuid)),a=g(e,`base`,`IPS usedImages`);if(!r||a===void 0)return[];let o=u(e.path);return[{index:n,name:u(e.name)??(o?i.basename(o):`image-${n}`),uuid:r,arch:u(e.arch),base:a,path:o}]}function w(e){let t=e.split(`
|
|
3
3
|
`),n=T(t);if(n.length===0)return null;let r=O(t,n);return{format:`text`,images:n,addresses:r,lines:t,frameMatches:r,write(e){let n=new Map(r.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let i=n.get(r);if(!i)return t;let a=e.get(c(i.image,i.address))?.text;return!a||t.includes(a)?t:`${t} // ${a}`}).join(`
|
|
4
|
-
`)}}}function T(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=E(r);e&&t.push(e)}return t}function E(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=s(t[4]);if(!n)return null;let r=D(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function D(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&S.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let a=i.basename(t);return{name:e.startsWith(a)?a:e}}function O(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=k(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function k(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=A(t,r,i);return a?{image:a,address:i}:null}function A(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>j(e,n))??y(r)}function j(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const M=1e4;async function N(e){return e.dsym&&e.searchPath?[H(e.cwd,e.dsym),...await P(H(e.cwd,e.searchPath))]:e.dsym?[H(e.cwd,e.dsym)]:e.searchPath?await P(H(e.cwd,e.searchPath)):[]}async function P(t){let n=[],r=0;async function o(s){if(n.length>=200)return;if(r+=1,r>M)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:M,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await F(s,t)).isDirectory()){s===t&&I(t);return}if(s.endsWith(`.dSYM`)){n.push(s);return}let c=await a.readdir(s,{withFileTypes:!0});for(let e of c)e.isDirectory()&&await o(i.join(s,e.name))}return await o(t),n}async function F(t,n){try{return await a.stat(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function I(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function L(t,n){let r=(await Promise.all(b(t).map(e=>R(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function R(e,
|
|
5
|
-
`).flatMap(t=>{let n=t.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=s(n?.[1]);return n&&r?[{dsymPath:e,uuid:r,arch:n[2],binaryPath:n[3].trim()}]:[]})}function V(t,n,r){let i=new Map;for(let e of t){let t=n.find(t=>t.uuid===e.uuid&&(e.arch===void 0||t.arch===void 0||t.arch===e.arch));t&&i.set(e.uuid,{image:e,dsym:t})}if(i.size>0)return i;let a=b(t.map(e=>e.uuid)),o=b(n.map(e=>e.uuid));throw new e(`COMMAND_FAILED`,r?`dSYM UUID does not match any Apple image in the crash artifact.`:`No matching dSYM UUID found under search path.`,{artifactUuidCount:a.length,artifactUuidSample:a.slice(0,5),dsymUuidCount:o.length,dsymUuidSample:o.slice(0,5),hint:`Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path.`})}function H(e,t){return i.resolve(e,t)}function U(e,t){return e.format===`ips`?W(e.document,e.frameMatches,t):ve(e.lines,e.frameMatches,t)}function W(e,t,n){let r=me(e.payload),i={format:`ips`,...G(e),crashedThread:r,topFrames:_e(t,r,n),findings:[]};return{...i,findings:Y(i)}}function G(e){let t=e.payload,n=pe(e.header);return{appName:K(t,n),bundleId:ce(t,n),version:le(t,n),incident:ue(t,n),timestamp:de(t,n),exceptionType:fe(t.exception),exceptionCodes:he(t.exception),terminationReason:ge(t.termination)}}function K(e,t){return d(e.procName,t?.app_name,t?.name)}function ce(e,
|
|
4
|
+
`)}}}function T(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=E(r);e&&t.push(e)}return t}function E(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=s(t[4]);if(!n)return null;let r=D(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function D(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&S.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let a=i.basename(t);return{name:e.startsWith(a)?a:e}}function O(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=k(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function k(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=A(t,r,i);return a?{image:a,address:i}:null}function A(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>j(e,n))??y(r)}function j(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const M=1e4;async function N(e){return e.dsym&&e.searchPath?[H(e.cwd,e.dsym),...await P(H(e.cwd,e.searchPath))]:e.dsym?[H(e.cwd,e.dsym)]:e.searchPath?await P(H(e.cwd,e.searchPath)):[]}async function P(t){let n=[],r=0;async function o(s){if(n.length>=200)return;if(r+=1,r>M)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:M,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await F(s,t)).isDirectory()){s===t&&I(t);return}if(s.endsWith(`.dSYM`)){n.push(s);return}let c=await a.readdir(s,{withFileTypes:!0});for(let e of c)e.isDirectory()&&await o(i.join(s,e.name))}return await o(t),n}async function F(t,n){try{return await a.stat(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function I(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function L(t,n){let r=(await Promise.all(b(t).map(e=>R(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function R(e,t){return await z(e),B(e,n(await r(t,[`--uuid`,e],{timeoutMs:15e3,allowFailure:!0}),`Failed to inspect dSYM UUIDs: ${e}`,{hint:`Verify the dSYM bundle is valid and readable.`}).stdout)}async function z(t){if(!((await a.stat(t).catch(()=>null))?.isDirectory()&&t.endsWith(`.dSYM`)))throw new e(`INVALID_ARGS`,`Not a .dSYM bundle: ${t}`,{hint:`Pass the .dSYM bundle path, not the DWARF executable inside it.`})}function B(e,t){return t.split(`
|
|
5
|
+
`).flatMap(t=>{let n=t.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=s(n?.[1]);return n&&r?[{dsymPath:e,uuid:r,arch:n[2],binaryPath:n[3].trim()}]:[]})}function V(t,n,r){let i=new Map;for(let e of t){let t=n.find(t=>t.uuid===e.uuid&&(e.arch===void 0||t.arch===void 0||t.arch===e.arch));t&&i.set(e.uuid,{image:e,dsym:t})}if(i.size>0)return i;let a=b(t.map(e=>e.uuid)),o=b(n.map(e=>e.uuid));throw new e(`COMMAND_FAILED`,r?`dSYM UUID does not match any Apple image in the crash artifact.`:`No matching dSYM UUID found under search path.`,{artifactUuidCount:a.length,artifactUuidSample:a.slice(0,5),dsymUuidCount:o.length,dsymUuidSample:o.slice(0,5),hint:`Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path.`})}function H(e,t){return i.resolve(e,t)}function U(e,t){return e.format===`ips`?W(e.document,e.frameMatches,t):ve(e.lines,e.frameMatches,t)}function W(e,t,n){let r=me(e.payload),i={format:`ips`,...G(e),crashedThread:r,topFrames:_e(t,r,n),findings:[]};return{...i,findings:Y(i)}}function G(e){let t=e.payload,n=pe(e.header);return{appName:K(t,n),bundleId:ce(t,n),version:le(t,n),incident:ue(t,n),timestamp:de(t,n),exceptionType:fe(t.exception),exceptionCodes:he(t.exception),terminationReason:ge(t.termination)}}function K(e,t){return d(e.procName,t?.app_name,t?.name)}function ce(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleIdentifier,n?.bundleID)}function le(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleShortVersionString,n?.app_version)}function ue(e,t){return d(e.incident,t?.incident_id)}function de(e,t){return d(e.captureTime,t?.timestamp)}function fe(e){return t(e)?u(e.type):void 0}function pe(e){return e?p(e):null}function me(e){let n=m(e.faultingThread);if(n!==void 0)return n;let r=(Array.isArray(e.threads)?e.threads:[]).findIndex(e=>t(e)&&e.triggered===!0);return r===-1?void 0:r}function he(e){return t(e)?d(e.codes,e.rawCodes):void 0}function ge(e){if(t(e))return f([u(e.namespace),u(e.code),u(e.reason)])}function _e(e,t,n){return e.filter(e=>t===void 0||e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function ve(e,t,n){let r=be(e),i={format:`text`,appName:ye(e),bundleId:q(e,`Identifier`),version:q(e,`Version`),incident:q(e,`Incident Identifier`),timestamp:q(e,`Date/Time`),exceptionType:q(e,`Exception Type`),exceptionCodes:q(e,`Exception Codes`),terminationReason:q(e,`Termination Reason`),crashedThread:r,topFrames:xe(t,r,n),findings:[]};return{...i,findings:Y(i)}}function ye(e){return q(e,`Process`)?.replace(/\s+\[\d+\]$/,``)}function q(e,t){let n=`${t}:`,r=e.find(e=>e.trimStart().startsWith(n));return r&&r.slice(r.indexOf(`:`)+1).trim()||void 0}function be(e){let t=q(e,`Triggered by Thread`),n=t?Number.parseInt(t,10):NaN;if(Number.isSafeInteger(n))return n;for(let t of e){let e=t.match(/^Thread\s+(\d+)\s+Crashed:/);if(e)return Number(e[1])}}function xe(e,t,n){return t===void 0?[]:e.filter(e=>e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function J(e,t,n,r){return{index:e,image:t.name,address:l(n),symbol:r.get(c(t,n))?.text}}function Y(e){return[Se(e),e.exceptionType?`Exception: ${e.exceptionType}`:void 0,e.terminationReason?`Termination: ${e.terminationReason}`:void 0].filter(e=>!!e).slice(0,3)}function Se(e){let t=e.topFrames.find(e=>e.symbol);return t?`Start with ${t.symbol} in ${t.image}; it is the first symbolicated frame captured on the crashed thread.`:e.topFrames.length>0?`No symbolicated frame was found on the crashed thread; verify matching dSYMs for the top images.`:void 0}async function Ce(e,t,n){let r=new Map;for(let i of we(e,t).values())for(let e of await Te(n,i))r.set(c(e.image,e.address),e);return r}function we(e,t){let n=new Map;for(let r of e){let e=t.get(r.image.uuid);if(!e)continue;let i=`${r.image.uuid}:${e.dsym.binaryPath}`,a=n.get(i)??{...e,addresses:[]};a.addresses.push(r.address),n.set(i,a)}return n}async function Te(e,t){let i=b(t.addresses.map(l)),a=n(await r(e,Ee(t,i),{timeoutMs:3e4,allowFailure:!0}),`atos failed while symbolicating crash frames.`,{hint:`Verify the crash artifact and dSYM were produced from the same build and architecture.`});return De(t.image,i,a.stdout)}function Ee(e,t){return[`-arch`,e.image.arch??e.dsym.arch??`arm64`,`-o`,e.dsym.binaryPath,`-l`,l(e.image.base),...t]}function De(e,t,n){let r=Oe(n);return t.map((t,n)=>{let i=r[n]?.trim();return{image:e,address:BigInt(t),text:ke(i,t)?i:void 0}})}function Oe(e){let t=e.split(/\r?\n/);return t.at(-1)===``&&t.pop(),t}function ke(e,t){if(!e)return!1;let n=e.trim().toLowerCase();return!n||n===`??`||n===t.toLowerCase()?!1:!n.startsWith(`0x`)}async function Ae(){return{dwarfdump:await X(`dwarfdump`),atos:await X(`atos`)}}async function X(t){try{let e=await r(`xcrun`,[`--find`,t],{timeoutMs:5e3,allowFailure:!0}),n=e.stdout.trim();if(e.exitCode===0&&n.length>0)return n}catch{}throw new e(`TOOL_MISSING`,`Apple symbolication tool not found: ${t}`,{hint:`Install Xcode Command Line Tools and verify xcrun --find dwarfdump and xcrun --find atos succeed.`})}const Z=64*1024*1024;async function je(t){if(t.action!==void 0&&t.action!==`symbols`)throw new e(`INVALID_ARGS`,`debug supports only the symbols workflow.`,{hint:`Use debug symbols --artifact <crash.ips|crash.log> --dsym <App.dSYM> or --search-path <dir> --out <path>.`});let n=t.cwd??process.cwd(),r=$(n,t.artifact),o=$(n,t.out??Pe(r)),s=ee(await Me(r,`crash artifact`));s||Q();let c=await N({cwd:n,dsym:t.dsym,searchPath:t.searchPath});if(c.length===0)throw new e(`INVALID_ARGS`,`debug symbols requires --dsym or --search-path.`,{hint:`Pass a matching .dSYM bundle directly, or pass --search-path <dir> so agent-device can match crash image UUIDs to local dSYMs.`});let l=await Ae(),u=await L(c,l.dwarfdump),d=V(s.images,u,!!t.dsym),f=await Ce(s.addresses,d,l.atos),p=s.write(f);await a.mkdir(i.dirname(o),{recursive:!0}),await a.writeFile(o,p,`utf8`);let m=[...d.values()].map(({image:e,dsym:t})=>({name:e.name,uuid:e.uuid,arch:e.arch??t.arch,dsymPath:t.dsymPath,binaryPath:t.binaryPath})),h=[...f.values()].filter(e=>e.text).length,g=s.images.length-m.length,_=g>0?[`${g} Apple image${g===1?``:`s`} had no matching dSYM and were left unchanged.`]:void 0;return{kind:`debugSymbols`,platform:`apple`,artifactPath:r,outPath:o,crash:U(s,f),matchedImages:m,symbolicatedFrames:h,skippedImages:g,warnings:_,message:`Symbolicated ${h} frame${h===1?``:`s`} -> ${o}`}}function Q(){throw new e(`UNSUPPORTED_OPERATION`,`debug symbols currently supports Apple crash artifacts with Binary Images or IPS usedImages.`,{hint:`For Android Java/R8 crashes, use retrace with mapping.txt. For Android native crashes, use ndk-stack or addr2line with unstripped .so symbols. Capture the crash with logs, then symbolicate externally until Android support is added.`})}async function Me(t,n){await Ne(t,n);try{return await a.readFile(t,`utf8`)}catch(r){let i=r instanceof Error?r.message:String(r);throw new e(`INVALID_ARGS`,`Failed to read ${n}: ${t}`,{message:i})}}async function Ne(t,n){try{let r=await a.stat(t);if(r.size<=Z)return;throw new e(`INVALID_ARGS`,`${n} is too large: ${t}`,{actualBytes:r.size,maxBytes:Z,hint:`Pass a bounded Apple .ips/.crash artifact. For very large logs, first narrow the log to the crash report, or use logs grep/tail for lead-up context.`})}catch(r){if(r instanceof e)throw r;let i=r instanceof Error?r.message:String(r);throw new e(`INVALID_ARGS`,`Failed to read ${n}: ${t}`,{message:i})}}function $(e,t){return i.resolve(e,t)}function Pe(e){let t=i.extname(e);return`${t?e.slice(0,-t.length):e}-symbolicated${t||`.log`}`}export{je as symbolicateCrashArtifact};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { t as AndroidAdbExecutor } from "./sdk-android-adb.js";
|
|
2
|
+
//#region packages/contracts/src/android-input-ownership.d.ts
|
|
3
|
+
type AndroidInputOwner = 'app' | 'ime' | 'unknown';
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/platforms/android/device-input-state.d.ts
|
|
6
|
+
type AndroidKeyboardType = 'text' | 'number' | 'email' | 'phone' | 'password' | 'datetime' | 'unknown';
|
|
7
|
+
type AndroidKeyboardState = {
|
|
8
|
+
visible: boolean;
|
|
9
|
+
inputType?: string;
|
|
10
|
+
type?: AndroidKeyboardType;
|
|
11
|
+
inputMethodPackage?: string;
|
|
12
|
+
focusedPackage?: string;
|
|
13
|
+
focusedResourceId?: string;
|
|
14
|
+
inputOwner: AndroidInputOwner;
|
|
15
|
+
};
|
|
16
|
+
type AndroidKeyboardDismissResult = AndroidKeyboardState & {
|
|
17
|
+
attempts: number;
|
|
18
|
+
wasVisible: boolean;
|
|
19
|
+
dismissed: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare function getAndroidKeyboardStatusWithAdb(adb: AndroidAdbExecutor): Promise<AndroidKeyboardState>;
|
|
22
|
+
declare function dismissAndroidKeyboardWithAdb(adb: AndroidAdbExecutor): Promise<AndroidKeyboardDismissResult>;
|
|
23
|
+
declare function readAndroidClipboardWithAdb(adb: AndroidAdbExecutor): Promise<string>;
|
|
24
|
+
declare function writeAndroidClipboardWithAdb(adb: AndroidAdbExecutor, text: string): Promise<void>;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { readAndroidClipboardWithAdb as a, getAndroidKeyboardStatusWithAdb as i, AndroidKeyboardState as n, writeAndroidClipboardWithAdb as o, dismissAndroidKeyboardWithAdb as r, AndroidInputOwner as s, AndroidKeyboardDismissResult as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{C as n,D as r,E as i,O as a}from"./device.js";import{j as o,n as s,s as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{i as u}from"./install-artifact.js";var d=e({dismissAndroidKeyboard:()=>v,dismissAndroidKeyboardWithAdb:()=>y,getAndroidKeyboardState:()=>g,getAndroidKeyboardStatusWithAdb:()=>_,readAndroidClipboardText:()=>A,readAndroidClipboardWithAdb:()=>j,writeAndroidClipboardText:()=>M,writeAndroidClipboardWithAdb:()=>N});const f=[`mInputShown`,`mIsInputViewShown`,`isInputViewShown`,`mDecorViewVisible`,`mWindowVisible`,`mInShowWindow`],p=new Map([[2,`number`],[3,`phone`],[4,`datetime`]]),m=new Set([32,208]),h=new Set([128,224,144]);async function g(e){return await _(c(e))}async function _(e){let t=await e([`shell`,`dumpsys`,`input_method`],{allowFailure:!0});if(t.exitCode!==0)throw s(`Failed to query Android keyboard state`,t);return b(t.stdout)}async function v(e){return await y(c(e))}async function y(e){let n=await _(e),r=n,i=0;for(;r.visible&&i<2;)await e([`shell`,`input`,`keyevent`,`111`]),i+=1,await l(120),r=await _(e);if(n.visible&&r.visible)throw new t(`UNSUPPORTED_OPERATION`,`Android keyboard dismiss is unavailable for the current IME without back navigation.`,{attempts:i,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner});return{attempts:i,wasVisible:n.visible,dismissed:n.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}function b(e){let t=T(e)??x(e),r=S(e),i=C(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),o=C(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),s=a(e),c=n(i,o,s);return w(i,o,s),{visible:t??!1,inputType:r,type:r?k(r):void 0,inputMethodPackage:s,focusedPackage:i,focusedResourceId:o,inputOwner:c}}function x(e){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/)?.[1];if(!t)return null;let n=Number.parseInt(t,16);return Number.isNaN(n)?null:(n&1)!=0}function S(e){let t=C(e,/\binputType=0x([0-9a-fA-F]+)\b/gi);return t?`0x${t.toLowerCase()}`:void 0}function C(e,t){let n;for(let r of e.matchAll(t))n=r[1];return n}function w(e,t,n){n||!i(e)&&!r(t)||o({level:`warn`,phase:`android_input_ownership_fallback`,data:{focusedPackage:e,focusedResourceId:t}})}function T(e){return D(E(e,f))}function E(e,t){let n=new Map,r=RegExp(`\\b(${t.join(`|`)})=([a-zA-Z]+)\\b`,`g`);for(let t of e.matchAll(r)){let e=t[1],r=t[2]?.toLowerCase();!e||r!==`true`&&r!==`false`||n.set(e,r===`true`)}return n}function D(e){if(e.size===0)return null;let t=O(e,[`mWindowVisible`,`mDecorViewVisible`,`mInShowWindow`]);if(t!==void 0)return t;let n=e.get(`mInputShown`);return n===void 0?O(e,[`mIsInputViewShown`,`isInputViewShown`])??null:n}function O(e,t){for(let n of t){let t=e.get(n);if(t!==void 0)return t}}function k(e){let t=Number.parseInt(e.replace(/^0x/i,``),16);if(Number.isNaN(t))return`unknown`;let n=t&15,r=p.get(n);if(r)return r;if(n!==1)return`unknown`;let i=t&4080;return m.has(i)?`email`:h.has(i)?`password`:`text`}async function A(e){return await j(c(e))}async function j(e){return F(await P(e,[`shell`,`cmd`,`clipboard`,`get`,`text`],`read`))}async function M(e,t){await N(c(e),t)}async function N(e,t){await P(e,[`shell`,`cmd`,`clipboard`,`set`,`text`,t],`write`)}async function P(e,n,r){let i=await e(n,{allowFailure:!0});if(u(i.stdout,i.stderr))throw new t(`UNSUPPORTED_OPERATION`,`Android shell clipboard ${r} is not supported on this device.`);if(i.exitCode!==0)throw s(`Failed to ${r} Android clipboard text`,i);return i.stdout}function F(e){let t=e.replace(/\r\n/g,`
|
|
2
2
|
`).replace(/\n$/,``),n=t.match(/^clipboard text:\s*(.*)$/i);return n?n[1]??``:t.trim().toLowerCase()===`null`?``:t}export{A as a,N as c,_ as i,y as n,j as o,g as r,M as s,d as t};
|
package/dist/src/device.js
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`||e===`\r`||e===` `}function De(e){return e===`=`||e===`/`||e===`>`||Ee(e)}function Oe(e){let t=``,n=0;for(;n<e.length;){let r=e.indexOf(`&`,n);if(r<0){t+=e.slice(n);break}t+=e.slice(n,r);let i=e.indexOf(`;`,r+1);if(i<0){t+=e.slice(r);break}let a=e.slice(r+1,i);t+=ke(a)??e.slice(r,i+1),n=i+1}return t}function ke(e){switch(e){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`;default:return Ae(e)}}function Ae(e){if(!e.startsWith(`#`))return;let t=e[1]?.toLowerCase()===`x`?16:10,n=t===16?e.slice(2):e.slice(1);if(!n||!je(n,t))return;let r=Number.parseInt(n,t);if(Number.isFinite(r))try{return String.fromCodePoint(r)}catch{return}}function je(e,t){for(let n of e){let e=n.charCodeAt(0),r=e>=48&&e<=57;if(t===10){if(!r)return!1;continue}if(!r&&!(e>=65&&e<=70)&&!(e>=97&&e<=102))return!1}return!0}function Me(e,t){return e.get(t)??null}function Ne(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 Pe(t),Ke(t),Fe(t,{actionableContentMemo:new WeakMap}),Ge(t),t}function Pe(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Pe(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function Fe(e,t){for(let n of e.children)Fe(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Be(e,t));r.length!==0&&(e.children=n.filter(e=>Ie(e,r)))}function Ie(e,t){return Le(e)||!Re(e,t)}function Le(e){return ze(e)&&!e.hittable&&e.children.length===0}function Re(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!Ue(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&We(n.rect,e.rect)>=.9)return!0;return!1}function ze(e){let t=e.identifier?.trim()??``;return!!(t&&!b(t))}function Be(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&Ue(e)&&(Ve(e)||He(e,t))}function Ve(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!b(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!b(n))}function He(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||He(e,t)));return t.actionableContentMemo.set(e,r),r}function Ue(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function We(e,t){let n=t.width*t.height;return n<=0?0:ie(e,t)/n}function Ge(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),Ze(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function Ke(e){let t=e.children.filter(Je);if(t.length<2)return;let n=t.filter(e=>Ye(e)&&Xe(e));if(n.length===0)return;let r=qe(n);e.children=e.children.filter(e=>Ye(e)?Xe(e)?r===void 0||e.windowLayer===r:!1:!0)}function qe(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function Je(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ye(e){return e.windowType===1}function Xe(e){return e.windowActive===!0||e.windowFocused===!0}function Ze(e){if(!e.scrollable||!ne(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Qe(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Qe(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 $e(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=et(e);return t.interactiveOnly?tt(e,a,n,r,i):a.isStructural||a.isVisual?it(e,a,r):!0}function et(e){let t=ot(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!b(e.label??``),hasMeaningfulId:r&&!b(e.identifier??``),isStructural:st(t),isVisual:t===`imageview`||t===`imagebutton`}}function tt(e,t,n,r,i){return rt(e)?!1:e.focused||e.hittable||ne(t.type)&&r?!0:nt(t,n,r,i)}function nt(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function rt(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function it(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function at(e){if(!e)return!1;let t=ot(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function ot(e){return e?e.toLowerCase():``}function st(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function b(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function ct(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 lt(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 x(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ut(n,t);return dt(t),{status:t.status,results:t.results}}function ut(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},mt(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ft(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},mt(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&pt(t)}function dt(e){ft(e),pt(e)}function ft(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function pt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function mt(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function S(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function C(e){if(e===`true`)return!0;if(e===`false`)return!1}function ht(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 w(e,n,r,i){if(e!==r)throw new t(`INVALID_ARGS`,`Android ${i} manifest ${n} must be "${r}".`);return r}function T(e,n,r){if(typeof e!=`string`||e.length===0)throw new t(`INVALID_ARGS`,`Android ${r} manifest ${n} is required.`);return e}function gt(e,n){let r=T(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 E=`android-snapshot-helper-v1`,D=`uiautomator-xml`,_t={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function vt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let n=e;return{name:k(n.name,`name`,`android-snapshot-helper`),version:A(n.version,`version`),releaseTag:Ct(n.releaseTag),assetName:Ct(n.assetName),apkUrl:wt(n.apkUrl,`apkUrl`),sha256:St(n.sha256),checksumName:Ct(n.checksumName),packageName:A(n.packageName,`packageName`),versionCode:O(n.versionCode,`versionCode`),instrumentationRunner:A(n.instrumentationRunner,`instrumentationRunner`),minSdk:O(n.minSdk,`minSdk`),targetSdk:n.targetSdk===void 0?void 0:O(n.targetSdk,`targetSdk`),outputFormat:k(n.outputFormat,`outputFormat`,D),statusProtocol:k(n.statusProtocol,`statusProtocol`,E),installArgs:bt(n.installArgs)}}function O(e,t){return ht(e,t,`snapshot helper`)}function k(e,t,n){return w(e,t,n,`snapshot helper`)}function yt(e){return xt(bt(e.installArgs))}function bt(e){let n=Tt(e,`installArgs`);if(n[0]!==`install`)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(n.some(e=>e.includes(`\0`)))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=n.slice(1).find(e=>!Et(e));if(r)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return n}function xt(e){let n={};for(let r of e.slice(1)){let e=Dt(r);if(!e)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);n[e]=!0}return n}function St(e){let n=A(e,`sha256`).trim().toLowerCase();if(n.length!==64||!Ot(n))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return n}function A(e,n){if(typeof e!=`string`||e.trim().length===0)throw new t(`INVALID_ARGS`,`Android snapshot helper manifest ${n} is required.`);return e}function Ct(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function wt(e,t){return e===null?null:A(e,t)}function Tt(e,n){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new t(`INVALID_ARGS`,`Android snapshot helper manifest ${n} must be a string array.`);return e}function Et(e){return Dt(e)!==void 0}function Dt(e){if(Object.hasOwn(_t,e))return _t[e]}function Ot(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}async function kt(e){let n=At(e),r=await e.adb(jt(n),{allowFailure:!0,timeoutMs:n.commandTimeoutMs}),{output:i,cleanupDone:a}=await Mt(e,n,r);if(n.outputPath&&!a&&await zt(e.adb,n.outputPath),r.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android snapshot helper failed`,f(r,{helper:i.metadata}));return i}function At(e){let t=j(e.timeoutMs,8e3),n=j(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:j(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:j(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:j(e.commandTimeoutMs,t+5e3),maxDepth:j(e.maxDepth,128),maxNodes:j(e.maxNodes,5e3),packageName:n,runner:j(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function j(e,t){return e===void 0?t:e}function jt(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 Mt(e,t,n){try{return{output:Bt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Nt(e,t,n,r)}}async function Nt(e,n,r,i){if(i instanceof t&&r.exitCode!==0&&i.details?.helper)throw i;let a=await Pt(e,n,r);if(a)return{output:a,cleanupDone:!0};throw new t(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},i)}async function Pt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await It(e.adb,t.outputPath,Rt(`${n.stdout}\n${n.stderr}`)??Ft(t))}function Ft(e){return{outputFormat:D,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function It(e,t,n){let r;try{r=await e(Lt(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 Lt(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Rt(e){try{return Jt(Ht(x(e).results))}catch{return null}}async function zt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Bt(e){let t=x(e),n=Ht(t.results);return{xml:Wt(Vt(t.status),n),metadata:{...Jt(n),transport:`instrumentation`}}}function Vt(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:M(n.chunkIndex),count:M(n.chunkCount),payloadBase64:e})}return t}function Ht(e){let n=e.find(e=>e.agentDeviceProtocol===E);if(!n)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(n.ok!==`true`)throw new t(`COMMAND_FAILED`,Ut(n),{errorType:n.errorType,helper:n});return n}function Ut(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Wt(e,n){if(e.length===0)throw new t(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:n});let r=Gt(e),i=Buffer.concat(qt(Kt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Gt(e){let n=e[0]?.count??e.length;if(n<1||e.length!==n||e.some(e=>e.count!==n))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:n,actualChunks:e.length});return n}function Kt(e,n){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=n)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:n});if(r.has(i.index))throw new t(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function qt(e,n){let r=[];for(let i=0;i<n;i+=1){let a=e.get(i);if(a===void 0)throw new t(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:n});r.push(Buffer.from(a,`base64`))}return r}function Jt(e){return{helperApiVersion:e.helperApiVersion,outputFormat:D,waitForIdleTimeoutMs:M(e.waitForIdleTimeoutMs),waitForIdleQuietMs:M(e.waitForIdleQuietMs),timeoutMs:M(e.timeoutMs),maxDepth:M(e.maxDepth),maxNodes:M(e.maxNodes),rootPresent:Xt(e.rootPresent),captureMode:Yt(e.captureMode),windowCount:M(e.windowCount),nodeCount:M(e.nodeCount),truncated:Xt(e.truncated),elapsedMs:M(e.elapsedMs)}}function Yt(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const M=S,Xt=C,Zt=2e3,Qt=5e3,N=new Map,$t=new Map;async function en(e){if(!xn()||!e.adbProvider?.spawn)return;let t=At(e),n=e.deviceKey??`android:default`,r=bn(n,t,e);if($t.get(n)===r)return;let i=N.get(n);if(i&&i.identity!==r&&(await F(n),i=void 0),!i)try{i=await cn({deviceKey:n,identity:r,options:e,resolved:t})}catch(e){$t.set(n,r),l({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e)}});return}try{let e=i.capturedCount>0,n=await dn(i,t);return i.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){throw await F(n),e}}async function tn(e){let n=N.get(e.deviceKey);if(!n)return;if(!nn(n.helper,e.helper)){l({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:n.helper,requestedHelper:e.helper}}),await F(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{let t=await L(n,i,e.timeoutMs);a=gn(t.slice(0,rn(t))),an(a,r)}catch(t){throw await F(e.deviceKey),t}if(a.ok!==`true`)throw new t(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function nn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&P(e.helperVersion,t.helperVersion)&&P(e.helperVersionCode,t.helperVersionCode)&&P(e.sha256,t.sha256)}function P(e,t){return e===void 0||t===void 0||e===t}function rn(e){let t=e.indexOf(`
|
|
3
|
-
|
|
4
|
-
`);return t<0?e.length:t}function an(e,n){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new t(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==n)throw new t(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:n})}async function F(e){let t=N.get(e);if(t){N.delete(e);try{await L(t,`quit ${Date.now()}`,1e3)}catch{}try{await t.process.kill(`SIGTERM`)}catch{}await ln(t.process,Zt);try{await vn(t)}catch{}l({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:t.port,capturedCount:t.capturedCount,lifetimeMs:Date.now()-t.startedAtMs}})}}async function on(e){await F(I(e))}function I(e){return`${e.platform}:${e.id}`}function sn(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+1e4,3e3))}async function cn(e){let n=await Sn();await e.options.adb([`forward`,`tcp:${n}`,`tcp:${n}`],{allowFailure:!1,timeoutMs:Qt});let r=jt({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new t(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(n),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:n,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await un(o,1e4),N.set(e.deviceKey,s),l({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:n,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(e){await vn(s);try{o.kill(`SIGTERM`)}catch{}throw await ln(o,Zt),e}}function ln(e,t){return new Promise(n=>{let r=setTimeout(n,t);e.once(`close`,()=>{clearTimeout(r),n()}),e.once(`exit`,()=>{clearTimeout(r),n()})})}function un(e,n){return new Promise((r,i)=>{let a=``,o=setTimeout(()=>{i(new t(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:a,timeoutMs:n}))},n),s=e=>{a+=e.toString(),a.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&a.includes(`sessionReady=true`)&&(clearTimeout(o),r())};e.stdout?.on(`data`,s),e.stderr?.on(`data`,s),e.once(`exit`,(e,n)=>{clearTimeout(o),i(new t(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:a,exitCode:e,signal:n}))}),e.on(`error`,e=>{clearTimeout(o),i(e)})})}async function dn(e,t){let n=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`,r=sn(t);return fn(await L(e,`snapshot ${n}`,r),n)}function L(e,n,r){return new Promise((i,a)=>{let o=ue.connect({host:`127.0.0.1`,port:e.port}),s=[],c=setTimeout(()=>{o.destroy(),a(new t(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:n,timeoutMs:r,port:e.port}))},r);o.on(`connect`,()=>{o.write(`${n}\n`)}),o.on(`data`,e=>{s.push(Buffer.from(e))}),o.on(`error`,e=>{clearTimeout(c),a(e)}),o.on(`close`,()=>{clearTimeout(c),i(Buffer.concat(s).toString(`utf8`))})})}function fn(e,t){let{headers:n,xml:r}=pn(e);return mn(n,t),hn(n,r),{xml:r,metadata:_n(n)}}function pn(e){let n=e.indexOf(`
|
|
5
|
-
|
|
6
|
-
`);if(n<0)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});return{headers:gn(e.slice(0,n)),xml:e.slice(n+2)}}function mn(e,n){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==n)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:n});if(e.ok!==`true`)throw new t(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function hn(e,n){let r=S(e.byteLength);if(r!==void 0&&Buffer.byteLength(n,`utf8`)!==r)throw new t(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(n,`utf8`)});if(!n.includes(`<hierarchy`)||!n.includes(`</hierarchy>`))throw new t(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:n})}function gn(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 _n(e){return{helperApiVersion:e.helperApiVersion,outputFormat:D,waitForIdleTimeoutMs:S(e.waitForIdleTimeoutMs),waitForIdleQuietMs:S(e.waitForIdleQuietMs),timeoutMs:S(e.timeoutMs),maxDepth:S(e.maxDepth),maxNodes:S(e.maxNodes),rootPresent:C(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:S(e.windowCount),nodeCount:S(e.nodeCount),truncated:C(e.truncated),elapsedMs:S(e.elapsedMs)}}async function vn(e){await e.process.stdin?.end(),await e.process.stdout?.destroy(),await e.process.stderr?.destroy(),await yn(e)}async function yn(e){await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:Qt})}function bn(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 xn(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}function Sn(){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))})})}const Cn=1e4;async function wn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:c,deviceKey:l,installTimeoutMs:d,helperLabel:f}=e,p=`${l}\0${r}\0${i}\0${o}`;if(c.has(p))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await jn(a,o,f);let m=await Tn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(m.reason===`current`)return c.add(p),{packageName:r,versionCode:i,...m,installed:!1};let h=await s(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:d});if(h.exitCode!==0)throw u(`Failed to install ${f}`,h,{packageName:r,versionCode:i,reason:m.reason});return c.add(p),{packageName:r,versionCode:i,...m,installed:!0}}async function Tn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a}=e,o=await On(t,r);if(o===void 0)return{reason:`missing`};if(o<i)return{installedVersionCode:o,reason:`outdated`};if(o>i)return{installedVersionCode:o,reason:`current`};try{let e=await kn(t,n,r);return{installedVersionCode:o,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return{installedVersionCode:o,reason:`unverifiable`}}}async function En(n){let r=h(),i=g.join(ee(),`android`,n.helperDirName,`dist`),a=g.join(i,n.manifestFileName(r));try{let e=n.parseManifest(JSON.parse(await _.readFile(a,`utf8`))),t=g.join(i,e.assetName);return await _.access(t),{apkPath:t,manifest:e}}catch(r){throw new t(`UNSUPPORTED_OPERATION`,n.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function Dn(e){return async t=>await wn({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 On(e,t){let n=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3});if(n.exitCode!==0)return;let r=RegExp(`package:${Nn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${n.stdout}\n${n.stderr}`);return r?Number(r[1]):void 0}async function kn(e,n,r){let i=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:Cn}),a=An(`${i.stdout}\n${i.stderr}`);if(i.exitCode!==0||!a)throw new t(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let o=await _.mkdtemp(g.join(le.tmpdir(),`agent-device-helper-`)),s=g.join(o,`base.apk`);try{let e=await d(a,s,{provider:n,allowFailure:!0,timeoutMs:Cn});if(e.exitCode!==0)throw u(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:a});return await Mn(s)}finally{await _.rm(o,{recursive:!0,force:!0})}}function An(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function jn(e,n,r){let i=await Mn(e);if(i!==n)throw new t(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:n,actualSha256:i})}async function Mn(e){let t=ce.createHash(`sha256`);return t.update(await _.readFile(e)),t.digest(`hex`)}function Nn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const R=new Map;function Pn(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of R.keys())e.startsWith(t)&&z(e)}function Fn(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function In(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of R.keys())t!==e&&t.startsWith(i)&&R.delete(t);R.set(e,t)}function z(e){e&&R.delete(e)}async function Ln(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=Fn(e.deviceKey,i,a,o),c=s?R.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 jn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Bn(t,i,e.timeoutMs),reason:`forced`}:await Tn({adb:t,adbProvider:zn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o}),{installedVersionCode:d}=l,f=`installedSha256`in l?l.installedSha256:void 0,p=l.reason;if(p===`current`){if(d===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return In(s,d),{packageName:i,versionCode:a,installedVersionCode:d,installedSha256:f,installed:!1,reason:p}}let m;try{m=await Vn(t,e.adbProvider??t,n.apkPath,yt(n.manifest),{packageName:i,timeoutMs:e.timeoutMs})}catch(e){throw z(s),Rn(e,{packageName:i,versionCode:a})}if(m.exitCode!==0)throw z(s),Rn(u(`Failed to install Android snapshot helper`,m,{packageName:i,versionCode:a}));return In(s,a),{packageName:i,versionCode:a,installedVersionCode:d,installedSha256:f,installed:!0,reason:p}}function Rn(e,t){let n=i(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function zn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Bn(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n});if(r.exitCode===0)return Hn(`${r.stdout}\n${r.stderr}`,t)}async function Vn(e,t,n,r,i){let a=async()=>await s(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs}),o=await a();if(o.exitCode===0||!Un(o))return o;let c=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs}),l=await a();return l.exitCode===0?l:{...l,stderr:[l.stderr,c.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${c.stderr}`:``].filter(Boolean).join(`
|
|
7
|
-
`)}}function Hn(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 Un(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const Wn=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]),Gn=new Set([`android`,`com.android.systemui`]),Kn=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,B=/^android:id\/button[123]$/i,qn=/(?:^|:)id\/permission_/i,Jn=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,Yn=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,Xn=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function Zn(e){if(e!==null){if(B.test(e))return`button`;if(Kn.test(e))return`content`}}function Qn(e){let t=er(e),n=t.nodes;if(n.length===0)return null;let r=ar(n),i=n.filter(e=>V(e)&&!hr(e)),a=cr(i),o=lr(i,a),s=gr(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 $n(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 er(e){let t=e.filter(e=>pr(e));if(t.length)return{nodes:t,source:`permission`};let n=ir(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:tr(e),source:`native-dialog`}}function tr(e){let t=e.filter(e=>nr(e.type??``)),n=e.filter(e=>Kn.test(e.identifier??``)),r=t.length?[...t,...n]:rr(n);if(r.length===0)return[];let i=ur(e,r);return i===void 0?r:fr(e,i)}function nr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function rr(e){let t=e.some(e=>B.test(e.identifier??``)),n=e.some(e=>!B.test(e.identifier??``));return t&&n?e:[]}function ir(e){let t=e.filter(e=>mr(e));if(t.length===0)return[];let n=ur(e,t);return n===void 0?t:fr(e,n).filter(e=>e.bundleId&&Gn.has(e.bundleId))}function ar(e){let t=new Set,n=[];for(let i of e){let e=V(i);if(!e||!i.rect||!hr(i))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=r(i.rect);n.push({label:e,x:o.x,y:o.y,role:or(i,e)})}return n}function or(e,t){return sr(e.identifier??``)||(Yn.test(t.trim())?`accept`:Xn.test(t.trim())?`dismiss`:`neutral`)}function sr(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 cr(e){return V(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||V(e[0])}function lr(e,t){let n=e.map(e=>V(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
8
|
-
`):void 0}function ur(e,t){let n=t[0];if(!n)return;let r=dr(e,n.index);for(let n of t.slice(1)){let t=new Set(dr(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 dr(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 fr(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 pr(e){let t=e.bundleId??``;return Wn.has(t)||qn.test(e.identifier??``)}function mr(e){let t=e.bundleId??``;return Gn.has(t)&&Jn.test(V(e))}function hr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||B.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function V(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function gr(e){return e.find(e=>e.bundleId)?.bundleId}const _r=new Set([`android`,`com.android.systemui`]);function vr(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Or(e,n.foregroundAppPackage);return br(r,t)?H(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Er(r)?{outcome:`ok`}:yr(r)?{outcome:`system-surface-only`}:xr(r)?{outcome:`ok`}:Sr(r)?H(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Cr(r)||wr(r,t)?H(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Tr(r)?H(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function H(e,t,n,r){return{outcome:`unusable`,decision:Dr(e,t,n,r)}}function yr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function br(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function xr(e){return Sr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Sr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Cr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function wr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Tr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Er(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Dr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Vr(e,t)}}function Or(e,t){let n=kr(t);for(let t of fe(e))Ar(n,t);return Lr(n)}function kr(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 Ar(e,t){e.nodeCount+=1,Br(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&jr(e,t.resourceId),Mr(e,t),Nr(e,t)}function jr(e,t){let n=Zn(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Mr(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 Nr(e,t){Rr(t)&&(e.meaningfulNodeCount+=1,Pr(e,t),Ir(e,t))}function Pr(e,t){e.currentWindowType===1&&!zr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Fr(e)&&!ae(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Fr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Ir(e,t){zr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),se({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Lr(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 Rr(e){return e.visibleToUser===!1?!1:U(e.text)||U(e.desc)||U(e.resourceId)}function U(e){return e!==null&&e.trim()!==``}function zr(e){return e===null||_r.has(e)}function Br(e){return e!==null&&_r.has(e)}function Vr(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}const W=5e3,Hr=3e4;async function Ur(e,t={}){let n=c(e,t.helperAdb).exec;return(await Jr(e,t,n)).xml}async function Wr(e,t={}){let n=c(e,t.helperAdb).exec,r=await Jr(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=me(i,void 0,t),n=Gr(e.truncated,r.metadata);return{...e,...Kr(n),androidSnapshot:r.metadata}}let a=Ne(i),o=y(a,void 0,t),s=Gr(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&qr({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:l,...u}=o;return{...u,...Kr(s),androidSnapshot:r.metadata}}function Gr(e,t){return e===!0||t.helperTruncated===!0?!0:e}function Kr(e){return e===!0?{truncated:!0}:{}}function qr(e){if(di(e.interactiveSnapshot.nodes).size>0||ui(e.xml))return;let t=y(e.tree,void 0,{...e.options,interactiveOnly:!1});fi(te(n(t.nodes)),t,e.interactiveSnapshot)}async function Jr(e,t,n){let r=c(e,t.helperAdb),i=await o(`android_snapshot_helper_artifact_resolution`,async()=>await ci(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await Yr(e,t,n,i.artifact);throw l({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),li(i.errorReason)}async function Yr(e,t,n,r){let i=I(e),a=c(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;try{let o=await Xr(t,n,a,r,i);o.installed&&await F(i),e=Qr(await Zr({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i}),r,o.reason)}catch(e){return await ei({error:e,helperDeviceKey:i,artifact:r,adb:n})}let o=vr(e.xml,e.metadata,{foregroundAppPackage:t.appBundleId});return o.outcome===`system-surface-only`?(l({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{xml:e.xml,metadata:{...e.metadata,systemSurfaceOnly:!0}}):o.outcome===`ok`?e:await $r({contentRecovery:o.decision,helperDeviceKey:i,artifact:r,adb:n})}finally{o&&await F(i)}}async function Xr(e,t,n,r,i){let a=await o(`android_snapshot_helper_install`,async()=>await Ln({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return l({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 Zr(t){let{options:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:s}=t,c={adb:r,adbProvider:i,deviceKey:s,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:n.helperWaitForIdleTimeoutMs??500,timeoutMs:W,commandTimeoutMs:Hr};try{let e=await o(`android_snapshot_helper_session_capture`,async()=>await en(c),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:W});if(e)return e}catch(t){l({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await G(r,a.manifest.packageName)}return await o(`android_snapshot_helper_capture`,async()=>await kt(c),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:W,commandTimeoutMs:Hr})}function Qr(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 $r(e){throw l({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,...e.contentRecovery.diagnostics}}),await G(e.adb,e.artifact.manifest.packageName),new t(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,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 ei(e){let t=ti(e.error);throw l({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await F(e.helperDeviceKey),await G(e.adb,e.artifact.manifest.packageName),Pn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),ni(e.error,t)}async function G(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await oe(150),l({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){l({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}function ti(t){let n=e(t),r=oi(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 ni(n,r){let i=e(n);return new t(a(i.code),`Android snapshot helper failed: ${r}`,{...i.details,...ii(i),androidSnapshotHelperFailureReason:r,hint:ri(i)},n)}function ri(e){return si(e.details?.helper,e.message)||ai(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 ii(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 ai(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function oi(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function si(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=oi(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function ci(t){if(t)return{artifact:t};let n=h(),r=g.join(ee(),`android`,`snapshot-helper`,`dist`),i=g.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await _.access(i)}catch{return{}}try{let e=vt(JSON.parse(await _.readFile(i,`utf8`))),t=g.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await _.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function li(e){let n=e??`the bundled helper artifact was not found`;return new t(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${n}`,{androidSnapshotHelperFailureReason:n,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function ui(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function di(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 fi(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`,pi=`android-ime-helper-v1`;async function mi(){return await En({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:hi,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function hi(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let n=e;return{name:w(n.name,`name`,`android-ime-helper`,K),version:T(n.version,`version`,K),assetName:T(n.assetName,`assetName`,K),sha256:gt(n.sha256,K),packageName:w(n.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,K),versionCode:ht(n.versionCode,`versionCode`,K),serviceComponent:w(n.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,K),broadcastProtocol:w(n.broadcastProtocol,`broadcastProtocol`,pi,K)}}const gi=Dn({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function q(e){return`${e.platform}:${e.id}`}async function _i(e,t,n){await yi(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function vi(e,t){await yi(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function yi(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,pi);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 u(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const J=`agent_device_ime_helper_previous_ime`,Y=`secure`,bi=`default_input_method`,X=new Set;function xi(e){return X.has(q(e))}function Z(e){return g.join(e,`android-test-ime-pending`)}function Si(e,t){return g.join(Z(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Ci(t,n){try{await _.mkdir(Z(t),{recursive:!0}),await _.writeFile(Si(t,n),n)}catch(r){l({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function Q(e,t){await _.rm(Si(e,t),{force:!0}).catch(()=>{})}async function wi(e){let t;try{t=await _.readdir(Z(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await _.readFile(g.join(Z(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Ti(e,t={}){let n=p(e),r=c(e),i=await mi(),{manifest:a}=i,o=q(e);await gi({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await $(n);if(s===a.serviceComponent)return X.add(o),t.stateDir&&await Ci(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await Ai(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(X.add(o),!await ji(n,s))return X.delete(o),l({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 Ci(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let u=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),d=await $(n);return d===a.serviceComponent?(l({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 Mi(n).catch(()=>{}),t.stateDir&&await Q(t.stateDir,e.id),l({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:d,stderr:u.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Ei(e,t={}){let n=q(e);if(!X.has(n))return{restored:!1,reason:`no-record`};X.delete(n);let r=await Oi(p(e),e);return t.stateDir&&Di(r.reason)&&await Q(t.stateDir,e.id),r}function Di(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Oi(e,t){let n=t.id;if(X.has(q(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await Ai(e);if(!r)return{restored:!1,reason:`no-record`};let i=await $(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return l({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await $(e);return a===r?(await Mi(e).catch(()=>{}),l({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(l({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function ki(t){let n=await wi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){l({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 Oi(p(n),n);e.restored&&l({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Di(e.reason)&&await Q(t.stateDir,i)}catch(t){l({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function $(e){let t=await e([`shell`,`settings`,`get`,Y,bi],{allowFailure:!0,timeoutMs:5e3});return Ni(t.exitCode===0?t.stdout:``)}async function Ai(e){let t=await e([`shell`,`settings`,`get`,Y,J],{allowFailure:!0,timeoutMs:5e3});return Ni(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 Ai(e)===t:!1}async function Mi(e){await e([`shell`,`settings`,`delete`,Y,J],{allowFailure:!0,timeoutMs:5e3})}function Ni(e){let t=e.trim();return!t||t===`null`?``:t}async function Pi(){try{return(await m(`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 Fi={previousIme:J,defaultInputMethod:bi},Ii=`limrun`,Li=Ii;function Ri(e){if(e===`ios-instance`)return`ios`;if(e===`android-instance`)return`android`}function zi(e,t,n){return{platform:e===`ios`?`apple`:`android`,...e===`ios`?{appleOs:`ios`}:{},id:Vi(e,t.leaseId),name:`Limrun ${e} ${n.slice(0,8)}`,kind:e===`ios`?`simulator`:`emulator`,target:`mobile`,booted:!0}}function Bi(e){let[t,n,r]=e.split(`:`);if(t===Li&&!(n!==`ios`&&n!==`android`)&&r)return{platform:n,leaseId:r}}function Vi(e,t){return`${Li}:${e}:${t}`}export{v as A,F as C,x as D,E,S as O,tn as S,vt as T,$n as _,Fi as a,En as b,Pi as c,ki as d,vi as f,Wr as g,Ur as h,Ri as i,fe as k,$ as l,_i as m,zi as n,Ti as o,mi as p,Bi as r,xi as s,Ii as t,Ei as u,Qn as v,on as w,I as x,Ln as y};
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{c as t,o as n,s as r,y as i}from"./sdk-device.js";const a=new Set([`com.google.android.inputmethod.latin`,`com.samsung.android.honeyboard`,`com.touchtype.swiftkey`,`com.microsoft.swiftkey`]);function o(e){let t=m(e.packageName),n=(e.resourceId??``).toLowerCase(),r=m(e.activeInputMethodPackage);if(t&&r&&t===r)return{inputMethodOwned:!0,source:`active-input-method`};if(r&&n.startsWith(`${r}:id/`))return{inputMethodOwned:!0,source:`active-input-method-resource`};if(t&&a.has(t))return{inputMethodOwned:!0,source:`known-ime-package`};for(let e of a)if(n.startsWith(`${e}:id/`))return{inputMethodOwned:!0,source:`known-ime-resource`};return{inputMethodOwned:!1,source:`app`}}function s(e,t,n){return o({packageName:e,resourceId:t,activeInputMethodPackage:n}).inputMethodOwned}function c(e){return o(e).inputMethodOwned}function l(e){let t=m(e);return!!(t&&a.has(t))}function u(e){let t=(e??``).toLowerCase();for(let e of a)if(t.startsWith(`${e}:id/`))return!0;return!1}function d(e,t,n){return!e&&!t?`unknown`:s(e,t,n)?`ime`:`app`}function f(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let n=p(e.match(t)?.[1]);if(n)return n}}function p(e){let t=(e??``).trim();if(t)return m((t.split(`/`)[0]??``).match(/[a-zA-Z0-9_.]+/)?.[0])}function m(e){return(e??``).trim().toLowerCase()||void 0}const h=`com.android.systemui`;function g(e){let t=e??``;if(!t.startsWith(`com.android.systemui:id/`))return!1;let n=t.slice(`${h}:id/`.length);return/(^|_)(status_bar|navigation_bar)(_|$)/.test(n)}function _(e){return`systemChrome`in e&&e.systemChrome===!0}function v(e){if(!_(e))return e;let{systemChrome:t,...n}=e;return n}function y(e){return e.some(_)?e.map(v):e}const b={ios:`iOS`,ipados:`iPadOS`,tvos:`tvOS`,watchos:`watchOS`,visionos:`visionOS`,macos:`macOS`},x={visionos:`visionOS uses spatial input and does not support two-finger touch synthesis.`,tvos:`tvOS has no touch input — this gesture is supported on Android and the iOS simulator only.`,macos:`macOS automation has no multi-touch input — this gesture is supported on Android and the iOS simulator only.`};function S(t,r){if(!n(t.platform))throw C(r,t.platform);let a=i(t);if(!((a===`ios`||a===`ipados`)&&t.kind===`simulator`))throw a===`ios`||a===`ipados`?new e(`UNSUPPORTED_OPERATION`,`gesture ${r} is not supported on physical iOS devices`,{hint:`Two-finger gesture synthesis is iOS-simulator only — not available on physical iOS devices.`}):C(r,b[a],x[a])}function C(t,n,r){return new e(`UNSUPPORTED_OPERATION`,`gesture ${t} is not supported on ${n}`,r===void 0?void 0:{hint:r})}function w(e){let t=e.state??`stopped`;return{audio:`probe`,state:t,active:t===`running`,heard:!1,source:e.source,backend:e.backend,durationMs:e.durationMs,elapsedMs:e.elapsedMs??0,bucketMs:e.bucketMs,sampleCount:0,mediaElementCount:e.mediaElementCount,sourceCount:e.sourceCount??0,rmsDbfs:[],peakDbfs:[],reason:e.reason,notes:e.notes}}function T(e,t){let n=A(e),r=E(n),i=O(n.rmsDbfs),a=O(n.peakDbfs),o=[...k(n.notes)??[],...t.notes??[]];return{audio:`probe`,state:r,active:r===`running`&&j(n.active,t.activeFallback??!0),heard:n.heard===!0,source:t.source,backend:M(n.backend)??t.backend,durationMs:D(n.durationMs,t.durationMs),elapsedMs:D(n.elapsedMs,t.elapsedMs),bucketMs:D(n.bucketMs,t.bucketMs),sampleCount:D(n.sampleCount,i.length),mediaElementCount:t.mediaElementCount===void 0?N(n.mediaElementCount):D(n.mediaElementCount,t.mediaElementCount),sourceCount:D(n.sourceCount,t.sourceCount??0),rmsDbfs:i,peakDbfs:a,startedAt:M(n.startedAt),stoppedAt:M(n.stoppedAt),reason:M(n.reason),notes:o.length>0?o:void 0}}function E(e){return e.state===`running`?`running`:`stopped`}function D(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}function O(e){if(!Array.isArray(e))return[];let t=[];for(let n of e)typeof n==`number`&&Number.isFinite(n)&&t.push(n);return t}function k(e){if(Array.isArray(e))return e.filter(e=>typeof e==`string`)}function A(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function j(e,t){return typeof e==`boolean`?e:t}function M(e){return typeof e==`string`?e:void 0}function N(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function P(e){return process.platform===`darwin`&&(t(e)||r(e)&&e.kind===`simulator`||e.platform===`android`&&e.kind===`emulator`)}function F(e){return e.platform===`web`||P(e)}const I=`user-installed`;function L(e){return e??`user-installed`}function R(t){if(t===void 0)throw new e(`INVALID_ARGS`,`appsFilter must be resolved before executing the apps command`);return t}const z=[`android`,`apple`,`vega`,`linux`],B={platform:`web`,id:`agent-browser-chrome`,name:`Agent Browser Chrome`,kind:`device`,target:`desktop`,booted:!0};function V(e){let t=U();for(let n of e){let e=W(n);t[e].available+=1,n.booted===!0&&(t[e].booted+=1)}return t}function H(e){return e.platform===`macos`||e.platform===`apple`&&e.target===`desktop`}function U(){return{android:{available:0,booted:0},apple:{available:0,booted:0},vega:{available:0,booted:0},linux:{available:0,booted:0},web:{available:0,booted:0}}}function W(e){return r(e)||t(e)?`apple`:e.platform}const G=[`portrait`,`portrait-upside-down`,`landscape-left`,`landscape-right`],K={portrait:0,"landscape-left":1,"portrait-upside-down":2,"landscape-right":3};function q(e){return K[e]*90}function J(e){return K[e]%2==0?`PORTRAIT`:`LANDSCAPE`}function Y(t){if(t===void 0)throw new e(`INVALID_ARGS`,`orientation requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.`);switch(t?.trim().toLowerCase()){case`portrait`:return`portrait`;case`portrait-upside-down`:case`upside-down`:return`portrait-upside-down`;case`landscape-left`:case`left`:return`landscape-left`;case`landscape-right`:case`right`:return`landscape-right`;default:throw new e(`INVALID_ARGS`,`Invalid rotation: ${t}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}export{d as C,u as D,l as E,f as O,v as S,c as T,S as _,Y as a,g as b,V as c,R as d,L as f,T as g,w as h,q as i,H as l,P as m,K as n,z as o,F as p,J as r,B as s,G as t,I as u,h as v,o as w,y as x,_ as y};
|
package/dist/src/devices2.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{b as t,s as n}from"./sdk-device.js";import{o as r}from"./boot-diagnostics.js";import{a as i,r as a}from"./tool-provider.js";import{I as o}from"./physical-device-control.js";import{r as s}from"./simulator.js";import{buildHostMacDevice as c}from"./devices.js";import
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{b as t,s as n}from"./sdk-device.js";import{o as r}from"./boot-diagnostics.js";import{a as i,r as a}from"./tool-provider.js";import{I as o}from"./physical-device-control.js";import{r as s}from"./simulator.js";import{buildHostMacDevice as c}from"./devices.js";import l from"node:path";import{promises as u}from"node:fs";import d from"node:os";const f=/^(iphone|ipad|ipod|appletv|realitydevice)/i,p=/ipad/i,m=/\b(apple vision|vision pro|xros|visionos|realitydevice)\b/i,h=/\b(iphone|ipad|ipod)\b/i,g=/^appletv/i,_=[`apple tv`,`appletv`,`tvos`],v=/^==\s*(.+?)\s*==$/,y=/^(?<name>.+?)\s+(?:\[(?<idBracket>[^[\]]+)\]|\((?<osVersion>[^)]+)\)\s+\((?<idParen>[^)]+)\))\s*$/;function b(e){return(e??``).trim().toLowerCase()}function x(e){return b(e)}function S(e){return b(e.hardwareProperties?.platform)}function C(e){return e.includes(`tvos`)}function w(e){return e.includes(`xros`)||e.includes(`visionos`)}function T(e){return C(x(e))?`tv`:`mobile`}function E(e){let t=x(e);return t.includes(`ios`)||t.includes(`tvos`)||t.includes(`xros`)||t.includes(`visionos`)}function D(e){let t=b(e);return _.some(e=>t.includes(e))}function O(e){return h.test(e.trim())}function k(e){return D(e)?`tv`:O(e)||m.test(e)?`mobile`:null}function A(e,t){return e===`tv`?`tvos`:t.some(e=>m.test(e))?`visionos`:t.some(e=>p.test(e))?`ipados`:`ios`}function j(e){return f.test(e.trim())}function M(e){return g.test(e.trim())}function N(e){return[e.name??``,e.deviceProperties?.name??``,e.deviceProperties?.deviceType??``]}function P(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??``}function F(e){return C(S(e))||M(P(e))||N(e).some(D)?`tv`:`mobile`}function I(e){let t=S(e);return t.includes(`ios`)||t.includes(`tvos`)||w(t)||j(P(e))?!0:N(e).some(D)}async function L(e={}){let n=r(e.simulatorSetPath),a=e.target,s;try{s=await i(o([`list`,`devices`,`-j`],{simulatorSetPath:n}))}catch{return null}let c;try{c=JSON.parse(s.stdout)}catch{return null}return t(R(c,n)).find(e=>!a||e.target===a)??null}function R(e,t){let n=[];for(let[r,i]of Object.entries(e.devices))if(E(r))for(let e of i){if(!e.isAvailable)continue;let i=T(r),a={platform:`apple`,id:e.udid,name:e.name,kind:`simulator`,target:i,appleOs:A(i,[e.deviceTypeIdentifier??``,e.name]),booted:e.state===`Booted`,...t?{simulatorSetPath:t}:{}};a.booted&&s(a),n.push(a)}return n}function z(e){let t=[];for(let n of e.result?.devices??[]){if(!I(n))continue;let e=n.hardwareProperties?.udid??n.identifier??``,r=n.name??n.deviceProperties?.name??e;if(!e)continue;let i=F(n);t.push({platform:`apple`,id:e,name:r,kind:`device`,target:i,appleOs:A(i,[P(n),...N(n)]),iosPhysicalDeviceBackend:`coredevice`,booted:!0})}return t}function B(e){let t=y.exec(e);if(!t?.groups)return null;let n=t.groups.name?.trim()??``,r=t.groups.idBracket?.trim()??t.groups.idParen?.trim()??``,i=t.groups.osVersion?.trim();return!n||!r?null:{name:n,id:r,osVersion:i}}function V(e,t,n){let r=k(e);return r?{platform:`apple`,id:t,name:e,kind:`device`,target:r,appleOs:A(r,n?[e,n]:[e]),iosPhysicalDeviceBackend:`xctest`,booted:!0}:null}function H(e){let t=[],n=null;for(let r of e.split(/\r?\n/)){let e=r.trim();if(!e)continue;let i=v.exec(e);if(i){n=i[1]?.trim()??null;continue}if(n!==`Devices`)continue;let a=B(e);if(!a)continue;let o=V(a.name,a.id,a.osVersion);o&&t.push(o)}return t}function U(e,t){let n=new Set(e.map(e=>e.id)),r=[...e];for(let e of t)n.has(e.id)||(n.add(e.id),r.push(e));return r}async function W(){let e=null;try{if(e=l.join(d.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),(await i([`devicectl`,`list`,`devices`,`--json-output`,e],{allowFailure:!0,timeoutMs:8e3})).exitCode!==0)return[];let t=await u.readFile(e,`utf8`);return z(JSON.parse(t))}catch{return[]}finally{e&&await u.rm(e,{force:!0}).catch(()=>{})}}async function G(){try{let e=await i([`xctrace`,`list`,`devices`],{allowFailure:!0});return e.exitCode===0?H(e.stdout):[]}catch{return[]}}async function K(s={}){if(process.platform!==`darwin`)throw new e(`UNSUPPORTED_PLATFORM`,`Apple tools are only available on macOS`);if(!await a().whichCommand(`xcrun`))throw new e(`TOOL_MISSING`,`xcrun not found in PATH`);let l=r(s.simulatorSetPath),u=await i(o([`list`,`devices`,`-j`],{simulatorSetPath:l})),d=[];try{d=R(JSON.parse(u.stdout),l)}catch(t){throw new e(`COMMAND_FAILED`,`Failed to parse simctl devices JSON`,void 0,t)}if(d.push(c()),s.udid&&d.some(e=>n(e)&&e.id===s.udid))return d;if(l)return t(d);let[f,p]=await Promise.all([W(),G()]);return d=U(d,f),t(U(d,p))}export{L as findBootableIosSimulator,K as listAppleDevices};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let n=Number(t[1]),r=Number(t[2]),i=Number(t[3]),a=Number(t[4]);return{x:n,y:r,width:Math.max(0,i-n),height:Math.max(0,a-r)}}function t(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 r(e,t)}})}function n(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}function r(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{n,e as r,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{I as t,L as n,M as r,nn as i,rn as a,z as o}from"./viewport-dimension.js";import{L as s,M as c,N as l,P as u}from"./sdk-batch-runner.js";import"./screenshot-result.js";import{h as d,j as f}from"./sdk-selectors.js";import{c as p,n as m,s as h,t as g}from"./context.js";import{Jt as _,h as v,in as y}from"./internal/daemon.js";import{D as b,o as x,t as S}from"./selector-runtime.js";async function C(e){let{req:t,sessionName:n,logPath:i,sessionStore:a,invoke:o}=e,l=t.command;if(l!==`find`)return null;let d=c(t.positionals??[],t.flags);if(!d.ok)return h(d.code,d.message);let{locator:f,query:m,action:g,value:_}=d.parsed;if(t.flags?.record&&!u(g))return h(`INVALID_ARGS`,`find ${g} is a mutating action and is always recorded; --record only applies to a read-only find (exists, wait, get text, get attrs).`);let v=await S({req:t,sessionName:n,logPath:i,sessionStore:a});if(v)return v;let y=a.get(n);if(!y)return p();let x=y.device,C=s(f,m),O=T({device:x,session:y,req:t,logPath:i,locator:f,query:m,sessionStore:a,sessionName:n}),k={req:t,sessionName:n,logPath:i,sessionStore:a,invoke:o,session:y,device:x,command:l,locator:f,query:m,publicFlags:W(t.flags)},A=await O();if(r(A.snapshotQuality))return E(A.snapshotQuality);let{nodes:j}=A,M=D({nodes:j,locator:f,query:m,selectorChain:C,flags:t.flags,platform:x.platform});if(!M.ok)return b(M.response,A);let N=M.node,F=P(j,N),I=await w(k,{node:N,resolvedNode:F,ref:`@${F.ref}`,nodes:j,actionFlags:{...t.flags??{},noRecord:!0}},g,_);return I&&b(I,A)}async function w(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 T(e){let{device:t,session:n,req:r,logPath:i,locator:a,query:o}=e,{sessionStore:s,sessionName:c}=e,l=x({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 E(e){return h(`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 D(e){let{nodes:t,locator:n,query:r,selectorChain:i,flags:a,platform:o}=e,s=t.filter(e=>!F(e,t[0]));if(i){let e=d(s,i,{platform:o,requireRect:!0,requireUnique:!1});return e?{ok:!0,node:e.node}:{ok:!1,response:h(`COMMAND_FAILED`,`find did not match any element`)}}let c=l(s,n,r,{requireRect:!0});if(c.matches=k(c.matches,t),c.matches.length>1){let e=O(c.matches,a);if(!e)return{ok:!1,response:G(c.matches,n,r)};c.matches=e}let u=c.matches[0]??null;return u?{ok:!0,node:u}:{ok:!1,response:h(`COMMAND_FAILED`,`find did not match any element`)}}function O(e,t){return t?.findFirst?[e[0]]:t?.findLast?[e[e.length-1]]:null}function k(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 A(i.length>0?i:t,n)}function A(e,t){return e.length<2?e:e.map((e,n)=>({node:e,index:n,score:j(e,t)})).sort((e,t)=>t.score===e.score?N(e.node)-N(t.node)||e.index-t.index:t.score-e.score).map(e=>e.node)}function j(e,t){let r=n(t,e);if(r.reason===`covered`)return 0;let i=M(r,t[0]);return i>0?i:e.hittable&&e.rect&&!F(e,t[0])?3:+!!e.rect}function M(e,t){return e.node.rect?e.reason===`semantic-target`||e.reason===`same-rect-descendant`?4:e.reason===`hittable-ancestor`&&!F(e.node,t)?2:0:0}function N(e){return e.rect?e.rect.width*e.rect.height:1/0}function P(e,n){let r=t(e,n);return F(r,e[0])&&n.rect?n:r}function F(e,t){if(!t?.rect||!e.rect)return!1;let n=e.type?.toLowerCase()??``;return!n.includes(`application`)&&!n.includes(`window`)?!1:I(e.rect,t.rect)}function I(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}async function L(t,n){let{req:r,sessionName:o,sessionStore:s,session:c,invoke:l,command:u,locator:d,query:f,publicFlags:p}=t,m=await l({token:r.token,session:o,command:`click`,positionals:[n.ref],flags:n.actionFlags,internal:{findResolvedTarget:!0}});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:d,query:f};h&&(g.x=h.x,g.y=h.y);let _=i(m.data)??`Tapped ${n.ref}${h?` (${h.x}, ${h.y})`:``}`;return Object.assign(g,a(_)),v(s,c,r,u,{ref:n.ref,action:`click`,locator:d,query:f},{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 h(`INVALID_ARGS`,`find fill requires text`);let u=await s({token:r.token,session:i,command:`fill`,positionals:[t.ref,n],flags:t.actionFlags,internal:{findResolvedTarget:!0}});return u.ok&&v(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 h(`INVALID_ARGS`,`find type requires text`);let s=await V(e,t);if(!s.ok)return s;_(o);let c=await m(i,`type`,[n],r.flags?.out,{...g(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?(_(o),{ok:!0,data:await m(i,`focus`,[String(c.x),String(c.y)],r.flags?.out,{...g(a,r.flags,o.appBundleId,o.trace?.outPath)})??{ref:n.ref}}):h(`COMMAND_FAILED`,`matched element has no bounds`)}function H(e,t){let n=[e.resolvedNode,e.node].find(o);return n?h(`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;v(i,a,r,o,{ref:t.ref,action:n},{flags:s})}function W(e){return{...y(e)??{}}}function G(e,t,n){let r=e.slice(0,8).map(e=>{let t=f(e)||e.label||e.identifier||e.type||``;return`@${e.ref}${t?`(${t})`:``}`});return h(`AMBIGUOUS_MATCH`,`find matched ${e.length} elements for ${t} "${n}". Use a more specific locator or selector.`,{locator:t,query:n,matches:e.length,candidates:r})}function K(e){return e!==`role`}export{G as buildAmbiguousMatchError,C as handleFindCommands};
|
package/dist/src/finders.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as findBestMatchesByLocator, r as parseFindArgs, t as FindMatchOptions } from "./sdk-finders.js";
|
|
2
2
|
export { FindMatchOptions, findBestMatchesByLocator, parseFindArgs };
|
package/dist/src/finders.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{I as e}from"./sdk-batch-runner.js";import{t}from"./sdk-finders.js";export{t as findBestMatchesByLocator,e as parseFindArgs};
|
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{nn as t}from"./viewport-dimension.js";import{i as n,n as r}from"./cli-runner.js";async function i({command:t,positionals:i,flags:s,client:c,debug:l,replayTestReporterRuntime:u}){let{result:d,cliOutput:f}=await r({client:c,command:t,positionals:i,flags:s});if(e(s.responseLevel))return n(s,d,()=>JSON.stringify(d,null,2)),!0;if(f)o(s,f);else{let e=await a(t,s,d,{debug:l,replayTestReporterRuntime:u});e!==0&&process.exit(e)}return!0}function a(e,r,i,a={}){return e===`test`?import(`./reporting.js`).then(({renderReplayTestResponse:e})=>e({suite:i,debug:a.debug,verbose:r.verbose,json:r.json,reporter:r.reporter,reportJunit:r.reportJunit,reporterRuntime:a.replayTestReporterRuntime})):(n(r,i,()=>t(i)),0)}function o(e,t){!e.json&&t.stderr&&process.stderr.write(t.stderr),n(e,e.json?t.jsonData??t.data:t.data,()=>t.text)}export{i as runGenericClientBackedCommand};
|
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
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{g as n,y 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{P as a,A as c,F as i,N as n,z as o,M as r,I as s,p as t};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{t as o}from"./screenshot-geometry.js";import{K as s,Q as c}from"./sdk-selectors.js";import{T as l,b as u,y as d}from"./device.js";import{I as f,a as p,c as m,j as h,n as g,o as ee,p as te,s as ne,v as re}from"./sdk-android-adb.js";import{n as ie,t as ae}from"./version.js";import{t as oe}from"./timeouts.js";import"./install-artifact.js";import{r as se,t as ce}from"./entities.js";import _ from"node:path";import le from"node:crypto";import ue from"node:os";import v from"node:fs/promises";import de from"node:net";function fe(){let e=[],t=()=>e[e.length-1]===!0;return{open(n,r){let i=t()||u(n);return r||e.push(i),i},close(){e.pop()}}}function*pe(e){let t=/<node\b[^>]*>|<\/node>/g,n=fe(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=me(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function me(e){let t=be(e),n=se(t.bounds);return{...t,...n?{rect:n}:{}}}function he(e,t,n){let{sourceNodes:r,...i}=y(ke(e),t,n);return i}function y(e,t,n){let r={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:n.depth??1/0,options:n,analysis:at(e),interactiveDescendantMemo:new Map,truncated:!1},i=n.scope?it(e,n.scope):null,a=i?[i]:e.children;for(let e of a)if(ge(r,e,0),r.truncated)break;let o={nodes:r.nodes,sourceNodes:r.sourceNodes,analysis:r.analysis};return r.truncated?{...o,truncated:!0}:o}function ge(e,t,n,r,i=!1,a=!1,o=!1){if(e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes){e.truncated=!0;return}if(n>e.maxDepth)return;let s=e.options.raw?!0:Ye(t,e.options,i,ye(e,t),a),c=o||u(t.identifier),l=s?_e(e,t,r,c):r,d=i||!!t.hittable,f=a||tt(t.type);for(let r of t.children)if(ge(e,r,n+1,l,d,f,c),e.truncated)return}function _e(e,t,n,r){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,focused:t.focused,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:ve(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function ve(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function ye(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(n.visibleToUser!==!1&&(n.hittable||ye(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function be(e){let t=xe(e),n=e=>Oe(t,e),r=e=>{let t=n(e);if(t!==null)return t===`true`},i=e=>{let t=n(e);if(t===null||t.trim()===``)return;let r=Number(t);return Number.isFinite(r)?r:void 0},a=(e,t)=>{let n=i(t);return n===void 0?{}:{[e]:n}},o=(e,t)=>{let r=se(n(t));return r===void 0?{}:{[e]:r}},s=(e,t)=>{let n=r(t);return n===void 0?{}:{[e]:n}};return{text:n(`text`),desc:n(`content-desc`),resourceId:n(`resource-id`),packageName:n(`package`),className:n(`class`),bounds:n(`bounds`),clickable:r(`clickable`),enabled:r(`enabled`),focusable:r(`focusable`),focused:r(`focused`),password:r(`password`),...s(`visibleToUser`,`visible-to-user`),...a(`drawingOrder`,`drawing-order`),...s(`scrollable`,`scrollable`),...s(`canScrollForward`,`can-scroll-forward`),...s(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...s(`windowActive`,`window-active`),...s(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function xe(e){let t=new Map,n=e.indexOf(` `),r=e.lastIndexOf(`>`);if(n<0||r<=n)return t;let i=n;for(;i<r;){let n=Se(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Se(e,t,n){if(t=b(e,t,n),t>=n||we(e[t]))return;let r=t;t=Ce(e,t,n);let i=e.slice(r,t);if(t=b(e,t,n),!i||e[t]!==`=`)return;t=b(e,t+1,n);let a=e[t];if(!Te(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:ce(e.slice(o,s)),nextCursor:s+1}}function Ce(e,t,n){for(;t<n&&!De(e[t]??``);)t+=1;return t}function b(e,t,n){for(;t<n&&Ee(e[t]??``);)t+=1;return t}function we(e){return e===`/`||e===`>`}function Te(e){return e===`"`||e===`'`}function Ee(e){return e===` `||e===`
|
|
2
|
+
`||e===`\r`||e===` `}function De(e){return e===`=`||e===`/`||e===`>`||Ee(e)}function Oe(e,t){return e.get(t)??null}function ke(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},n=[t],r=/<node\b[^>]*>|<\/node>/g,i=r.exec(e);for(;i;){let t=i[0];if(t.startsWith(`</node`)){n.length>1&&n.pop(),i=r.exec(e);continue}let a=me(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,hittable:a.clickable??a.focusable,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return Ae(t),He(t),je(t,{actionableContentMemo:new WeakMap}),Ve(t),t}function Ae(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Ae(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function je(e,t){for(let n of e.children)je(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Ie(e,t));r.length!==0&&(e.children=n.filter(e=>Me(e,r)))}function Me(e,t){return Ne(e)||!Pe(e,t)}function Ne(e){return Fe(e)&&!e.hittable&&e.children.length===0}function Pe(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!ze(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Be(n.rect,e.rect)>=.9)return!0;return!1}function Fe(e){let t=e.identifier?.trim()??``;return!!(t&&!x(t))}function Ie(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&ze(e)&&(Le(e)||Re(e,t))}function Le(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!x(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!x(n))}function Re(e,t){let n=t.actionableContentMemo.get(e);if(n!==void 0)return n;let r=e.children.some(e=>e.visibleToUser!==!1&&(!!e.hittable||Re(e,t)));return t.actionableContentMemo.set(e,r),r}function ze(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Be(e,t){let n=t.width*t.height;return n<=0?0:o(e,t)/n}function Ve(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),qe(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function He(e){let t=e.children.filter(We);if(t.length<2)return;let n=t.filter(e=>Ge(e)&&Ke(e));if(n.length===0)return;let r=Ue(n);e.children=e.children.filter(e=>Ge(e)?Ke(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ue(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function We(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ge(e){return e.windowType===1}function Ke(e){return e.windowActive===!0||e.windowFocused===!0}function qe(e){if(!e.scrollable||!c(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Je(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Je(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function Ye(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Xe(e);return t.interactiveOnly?Ze(e,a,n,r,i):a.isStructural||a.isVisual?et(e,a,r):!0}function Xe(e){let t=nt(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!x(e.label??``),hasMeaningfulId:r&&!x(e.identifier??``),isStructural:rt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ze(e,t,n,r,i){return $e(e)?!1:e.focused||e.hittable||c(t.type)&&r?!0:Qe(t,n,r,i)}function Qe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function $e(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function et(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function tt(e){if(!e)return!1;let t=nt(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function nt(e){return e?e.toLowerCase():``}function rt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function x(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function it(e,t){let n=t.toLowerCase(),r=[...e.children],i=0;for(;i<r.length;){let e=r[i++],t=e.label?.toLowerCase()??``,a=e.value?.toLowerCase()??``,o=e.identifier?.toLowerCase()??``;if(t.includes(n)||a.includes(n)||o.includes(n))return e;r.push(...e.children)}return null}function at(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}function S(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ot(n,t);return st(t),{status:t.status,results:t.results}}function ot(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ut(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ct(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ut(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&<(t)}function st(e){ct(e),lt(e)}function ct(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function lt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ut(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function C(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function w(e){if(e===`true`)return!0;if(e===`false`)return!1}function dt(e,t,r){if(typeof e!=`number`||!Number.isInteger(e))throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} must be an integer.`);return e}function T(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function E(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ft(e,t){let r=E(e,`sha256`,t).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new n(`INVALID_ARGS`,`Android ${t} manifest sha256 must be a 64-character hex string.`);return r}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,pt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:yt(t.apkUrl,`apkUrl`),sha256:vt(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:gt(t.installArgs)}}function k(e,t){return dt(e,t,`snapshot helper`)}function A(e,t,n){return T(e,t,n,`snapshot helper`)}function ht(e){return _t(gt(e.installArgs))}function gt(e){let t=bt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!xt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function _t(e){let t={};for(let r of e.slice(1)){let e=St(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function vt(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ct(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function yt(e,t){return e===null?null:j(e,t)}function bt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function xt(e){return St(e)!==void 0}function St(e){if(Object.hasOwn(pt,e))return pt[e]}function Ct(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const wt=2e3,Tt=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function Et(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Tt,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Dt(e){return e instanceof n&&e.details?.reason===Tt}async function Ot(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Mt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Nt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function kt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function At(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function jt(){N.clear()}async function Mt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Nt(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function Pt(e){let t=Ft(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(It(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Lt(e,t,i);if(t.outputPath&&!o&&await Wt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,te(i,{helper:a.metadata}));return a}function Ft(e){let t=R(e.timeoutMs,8e3),n=R(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:R(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:R(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:R(e.commandTimeoutMs,t+5e3),maxDepth:R(e.maxDepth,128),maxNodes:R(e.maxNodes,5e3),packageName:n,runner:R(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function R(e,t){return e===void 0?t:e}function It(e){return[`shell`,`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],e.runner]}async function Lt(e,t,n){try{return{output:Gt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Rt(e,t,n,r)}}async function Rt(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await zt(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},i)}async function zt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Vt(e.adb,t.outputPath,Ut(`${n.stdout}\n${n.stderr}`)??Bt(t))}function Bt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Vt(e,t,n){let r;try{r=await e(Ht(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Ht(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ut(e){try{return $t(qt(S(e).results))}catch{return null}}async function Wt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Gt(e){let t=S(e),n=qt(t.results);return{xml:Yt(Kt(t.status),n),metadata:{...$t(n),transport:`instrumentation`}}}function Kt(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:z(n.chunkIndex),count:z(n.chunkCount),payloadBase64:e})}return t}function qt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Jt(t),{errorType:t.errorType,helper:t});return t}function Jt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Yt(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=Xt(e),i=Buffer.concat(Qt(Zt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Xt(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function Zt(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Qt(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function $t(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs),waitForIdleQuietMs:z(e.waitForIdleQuietMs),timeoutMs:z(e.timeoutMs),maxDepth:z(e.maxDepth),maxNodes:z(e.maxNodes),rootPresent:tn(e.rootPresent),captureMode:en(e.captureMode),windowCount:z(e.windowCount),nodeCount:z(e.nodeCount),truncated:tn(e.truncated),elapsedMs:z(e.elapsedMs)}}function en(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const z=C,tn=w;function nn(){return new Promise((e,t)=>{let n=de.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function B(e,t,r,i){return new Promise((a,o)=>{let s=de.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${t}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function rn(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return un(await B(e.port,`snapshot ${t}`,an(e),e.signal),t)}function an(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function on(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function sn(e){let t=e.indexOf(`
|
|
3
|
+
|
|
4
|
+
`);return pn(e.slice(0,t<0?e.length:t))}function cn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:t})}function ln(e,t){let n=sn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function un(e,t){let r=e.indexOf(`
|
|
5
|
+
|
|
6
|
+
`);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=pn(e.slice(0,r)),a=e.slice(r+2);return dn(i,t),fn(i,a),{xml:a,metadata:mn(i)}}function dn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function fn(e,t){let r=C(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function pn(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function mn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:C(e.waitForIdleTimeoutMs),waitForIdleQuietMs:C(e.waitForIdleQuietMs),timeoutMs:C(e.timeoutMs),maxDepth:C(e.maxDepth),maxNodes:C(e.maxNodes),rootPresent:w(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:C(e.windowCount),nodeCount:C(e.nodeCount),truncated:w(e.truncated),elapsedMs:C(e.elapsedMs)}}const hn=5e3,V=new Map,gn=new Map;async function _n(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!An()||!e.adbProvider?.spawn)return;let n=bn(Ft(e)),r=await vn({deviceKey:t,identity:kn(t,n,e),options:e,resolved:n});if(r)return await yn({session:r,deviceKey:t,options:e,resolved:n})}async function vn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(gn.get(t)===n)return;let a=V.get(t);if(a&&a.identity!==n&&(await H(t),a=void 0),!a)try{a=await On({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),gn.set(t,n),h({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Dt(e))throw e;return}return a}async function yn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await rn({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await H(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:xn(e)}});return}}function bn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function xn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Sn(e){let t=V.get(e.deviceKey);if(!t)return;if(!Cn(t.helper,e.helper)){h({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await H(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=sn(await B(t.port,i,e.timeoutMs)),cn(a,r)}catch(t){throw await H(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function Cn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&wn(e.helperVersion,t.helperVersion)&&wn(e.helperVersionCode,t.helperVersionCode)&&wn(e.sha256,t.sha256)}function wn(e,t){return e===void 0||t===void 0||e===t}async function H(e,t={}){let n=V.get(e);if(!n)return;V.delete(e);let r=kt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await Tn(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:wt:hn,s=i?250:2e3,[c,l]=await Promise.all([At({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Ot({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,forceKilled:!a.exited&&c,forced:i||t.signal?.aborted===!0,runtimeForceStopped:l.runtimeForceStopped,externalCleanupTimedOut:l.timedOut}}),!a.exited&&!l.runtimeForceStopped&&I({deviceKey:e,packageName:n.helper.packageName,cause:t.cause})}async function Tn(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=ln(await B(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await L(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function En(e){await H(P(e))}async function Dn(){let e=await Promise.allSettled([...V.keys()].map(e=>H(e)));gn.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);jt()}async function On(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:hn,signal:e.options.signal});let r=It({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await on(o,1e4,e.options.signal),V.set(e.deviceKey,s),h({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(t){let n=kt(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([L(n,250),Ot({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:wt})]);throw r.runtimeForceStopped||I({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function kn(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function An(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const jn=1e4;async function Mn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await zn(a,o,u);let f=await Nn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let m=await p(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(m.exitCode!==0)throw g(`Failed to install ${u}`,m,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Nn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await In(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await Ln(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Pn(t){let r=ie(),i=_.join(ae(),`android`,t.helperDirName,`dist`),a=_.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await v.readFile(a,`utf8`))),n=_.join(i,e.assetName);return await v.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function Fn(e){return async t=>await Mn({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function In(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Vn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Ln(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:jn,signal:i}),o=Rn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new n(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=await v.mkdtemp(_.join(ue.tmpdir(),`agent-device-helper-`)),c=_.join(s,`base.apk`);try{let e=await ee(o,c,{provider:t,allowFailure:!0,timeoutMs:jn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Bn(c)}finally{await v.rm(s,{recursive:!0,force:!0})}}function Rn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function zn(e,t,r){let i=await Bn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Bn(e){let t=le.createHash(`sha256`);return t.update(await v.readFile(e)),t.digest(`hex`)}function Vn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const U=new Map;function Hn(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of U.keys())e.startsWith(t)&&Gn(e)}function Un(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Wn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of U.keys())t!==e&&t.startsWith(i)&&U.delete(t);U.set(e,t)}function Gn(e){e&&U.delete(e)}async function Kn(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Un(e.deviceKey,i,a,o),c=s?U.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await zn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Yn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Nn({adb:t,adbProvider:Jn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Wn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Xn(t,e.adbProvider??t,n.apkPath,ht(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Gn(s),qn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Gn(s),qn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Wn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function qn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Jn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Yn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Zn(`${i.stdout}\n${i.stderr}`,t)}async function Xn(e,t,n,r,i){let a=async()=>await p(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!Qn(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
|
|
7
|
+
`)}}function Zn(e,t){let n=`package:${t}`;for(let t of e.split(/\r?\n/)){if(!t.startsWith(n)||t.length>n.length&&!/\s/.test(t[n.length]??``))continue;let e=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(e)return Number(e[1])}}function Qn(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const $n=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function er(e){return $n.has(e)}const tr=new Set([`android`,`com.android.systemui`]),nr=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,W=/^android:id\/button[123]$/i,rr=/(?:^|:)id\/permission_/i,ir=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,ar=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,or=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function sr(e){if(e!==null){if(W.test(e))return`button`;if(nr.test(e))return`content`}}function cr(e){let t=ur(e),n=t.nodes;if(n.length===0)return null;let r=hr(n),i=n.filter(e=>G(e)&&!Tr(e)),a=vr(i),o=yr(i,a),s=Er(n);return{alert:{...a?{title:a}:{},...o?{message:o}:{},buttons:r.map(e=>e.label),platform:`android`,source:t.source,...s?{packageName:s}:{}},buttons:r}}function lr(e,t){let n=t===`accept`?`accept`:`dismiss`;return e.find(e=>e.role===n)||(t===`dismiss`?e.find(e=>e.role===`neutral`)??null:e.length===1?e[0]??null:null)}function ur(e){let t=e.filter(e=>Cr(e));if(t.length)return{nodes:t,source:`permission`};let n=mr(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:dr(e),source:`native-dialog`}}function dr(e){let t=e.filter(e=>fr(e.type??``)),n=e.filter(e=>nr.test(e.identifier??``)),r=t.length?[...t,...n]:pr(n);if(r.length===0)return[];let i=br(e,r);return i===void 0?r:Sr(e,i)}function fr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function pr(e){let t=e.some(e=>W.test(e.identifier??``)),n=e.some(e=>!W.test(e.identifier??``));return t&&n?e:[]}function mr(e){let t=e.filter(e=>wr(e));if(t.length===0)return[];let n=br(e,t);return n===void 0?t:Sr(e,n).filter(e=>e.bundleId&&tr.has(e.bundleId))}function hr(e){let t=new Set,n=[];for(let r of e){let e=G(r);if(!e||!r.rect||!Tr(r))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=i(r.rect);n.push({label:e,x:o.x,y:o.y,role:gr(r,e)})}return n}function gr(e,t){return _r(e.identifier??``)||(ar.test(t.trim())?`accept`:or.test(t.trim())?`dismiss`:`neutral`)}function _r(e){return/(?:^|:)id\/button1$/i.test(e)?`accept`:/(?:^|:)id\/button2$/i.test(e)?`dismiss`:/(?:^|:)id\/button3$/i.test(e)?`neutral`:/(?:^|:)id\/permission_allow/i.test(e)?`accept`:/(?:^|:)id\/permission_deny/i.test(e)?`dismiss`:null}function vr(e){return G(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||G(e[0])}function yr(e,t){let n=e.map(e=>G(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
8
|
+
`):void 0}function br(e,t){let n=t[0];if(!n)return;let r=xr(e,n.index);for(let n of t.slice(1)){let t=new Set(xr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function xr(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function Sr(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function Cr(e){let t=e.bundleId??``;return $n.has(t)||rr.test(e.identifier??``)}function wr(e){let t=e.bundleId??``;return tr.has(t)&&ir.test(G(e))}function Tr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||W.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function G(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Er(e){return e.find(e=>e.bundleId)?.bundleId}const Dr=new Set([`android`,`com.android.systemui`]);function Or(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Rr(e,n.foregroundAppPackage);return Ar(r,t)?K(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Ir(r)?{outcome:`ok`}:kr(r)?{outcome:`system-surface-only`}:jr(r)?{outcome:`ok`}:Mr(r)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Nr(r)||Pr(r,t)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Fr(r)?K(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function K(e,t,n,r){return{outcome:`unusable`,decision:Lr(e,t,n,r)}}function kr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function Ar(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function jr(e){return Mr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Mr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Nr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Pr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Fr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Ir(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Lr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Qr(e,t)}}function Rr(e,t){let n=zr(t);for(let t of pe(e))Br(n,t);return qr(n)}function zr(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function Br(e,t){e.nodeCount+=1,Zr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Vr(e,t.resourceId),Hr(e,t),Ur(e,t)}function Vr(e,t){let n=sr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Hr(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Ur(e,t){Jr(t)&&(e.meaningfulNodeCount+=1,Wr(e,t),Kr(e,t))}function Wr(e,t){e.currentWindowType===1&&!Xr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Gr(e)&&!d(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Gr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Kr(e,t){Xr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),l({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function qr(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Jr(e){return e.visibleToUser===!1?!1:Yr(e.text)||Yr(e.desc)||Yr(e.resourceId)}function Yr(e){return e!==null&&e.trim()!==``}function Xr(e){return e===null||Dr.has(e)}function Zr(e){return e!==null&&Dr.has(e)}function Qr(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}const $r=5e3,ei=3e4;async function ti(e,t={}){let n=m(e,t.helperAdb).exec;return(await oi(e,t,n)).xml}async function ni(e,t={}){let n=m(e,t.helperAdb).exec,r=await oi(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=he(i,void 0,t),n=ri(e.truncated,r.metadata);return{...e,...ii(n),androidSnapshot:r.metadata}}let a=ke(i),o=y(a,void 0,t),s=ri(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ai({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...ii(s),androidSnapshot:r.metadata}}function ri(e,t){return e===!0||t.helperTruncated===!0?!0:e}function ii(e){return e===!0?{truncated:!0}:{}}function ai(e){if(Ei(e.interactiveSnapshot.nodes).size>0||Ti(e.xml))return;let t=y(e.tree,void 0,{...e.options,interactiveOnly:!1});Di(s(r(t.nodes)),t,e.interactiveSnapshot)}async function oi(e,t,n){let r=m(e,t.helperAdb),i=await f(`android_snapshot_helper_artifact_resolution`,async()=>await Ci(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await si(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),wi(i.errorReason)}async function si(e,t,n,r){let i=P(e),a=m(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await fi(t.signal);let s=await di({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3)return await pi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n});e=s.decision.reason}}finally{o&&await H(i)}}async function ci(e,t,n,r,i){let a=await f(`android_snapshot_helper_install`,async()=>await Kn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return h({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function li(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:$r,commandTimeoutMs:ei,signal:n};try{let e=await f(`android_snapshot_helper_session_capture`,async()=>await _n(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r});if(e)return e}catch(t){if(n?.throwIfAborted(),Dt(t))throw t;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await hi(r,a.manifest.packageName)}return await f(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r,commandTimeoutMs:ei})}function ui(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function di(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await ci(t,n,r,i,a);e.installed&&await H(a),s=ui(await li({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await mi({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=Or(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(h({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function fi(e){e?.throwIfAborted(),await oe(250),e?.throwIfAborted()}async function pi(e){throw h({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),await hi(e.adb,e.artifact.manifest.packageName),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function mi(e){let t=gi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await H(e.helperDeviceKey),await hi(e.adb,e.artifact.manifest.packageName),Hn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),_i(e.error,t)}async function hi(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await oe(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){h({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}function gi(t){let n=e(t),r=xi(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function _i(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...yi(a),androidSnapshotHelperFailureReason:i,hint:vi(a)},r)}function vi(e){return Si(e.details?.helper,e.message)||bi(e)?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function yi(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function bi(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function xi(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function Si(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=xi(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ci(t){if(t)return{artifact:t};let n=ie(),r=_.join(ae(),`android`,`snapshot-helper`,`dist`),i=_.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await v.access(i)}catch{return{}}try{let e=mt(JSON.parse(await v.readFile(i,`utf8`))),t=_.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await v.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function wi(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function Ti(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Ei(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function Di(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const q=`IME helper`,Oi=`android-ime-helper-v1`;async function ki(){return await Pn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Ai,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Ai(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:T(t.name,`name`,`android-ime-helper`,q),version:E(t.version,`version`,q),assetName:E(t.assetName,`assetName`,q),sha256:ft(t.sha256,q),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,q),versionCode:dt(t.versionCode,`versionCode`,q),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,q),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Oi,q)}}const ji=Fn({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function J(e){return`${e.platform}:${e.id}`}async function Mi(e,t,n){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Ni(e,t){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Pi(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Oi);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const Y=`agent_device_ime_helper_previous_ime`,X=`secure`,Fi=`default_input_method`,Z=new Set;function Ii(e){return Z.has(J(e))}function Q(e){return _.join(e,`android-test-ime-pending`)}function Li(e,t){return _.join(Q(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Ri(t,n){try{await v.mkdir(Q(t),{recursive:!0}),await v.writeFile(Li(t,n),n)}catch(r){h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function zi(e,t){await v.rm(Li(e,t),{force:!0}).catch(()=>{})}async function Bi(e){let t;try{t=await v.readdir(Q(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await v.readFile(_.join(Q(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Vi(e,t={}){let n=ne(e),r=m(e),i=await ki(),{manifest:a}=i,o=J(e);await ji({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await $(n);if(s===a.serviceComponent)return Z.add(o),t.stateDir&&await Ri(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await Ki(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(Z.add(o),!await qi(n,s))return Z.delete(o),h({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Ri(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await $(n);return l===a.serviceComponent?(h({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(Z.delete(o),await Ji(n).catch(()=>{}),t.stateDir&&await zi(t.stateDir,e.id),h({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Hi(e,t={}){let n=J(e);if(!Z.has(n))return{restored:!1,reason:`no-record`};Z.delete(n);let r=await Wi(ne(e),e);return t.stateDir&&Ui(r.reason)&&await zi(t.stateDir,e.id),r}function Ui(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Wi(e,t){let n=t.id;if(Z.has(J(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await Ki(e);if(!r)return{restored:!1,reason:`no-record`};let i=await $(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return h({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await $(e);return a===r?(await Ji(e).catch(()=>{}),h({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(h({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function Gi(t){let n=await Bi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){h({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).message}});return}for(let i of n){if(!r.has(i))continue;let n={platform:`android`,id:i,name:i,kind:i.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{let e=await Wi(ne(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Ui(e.reason)&&await zi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function $(e){let t=await e([`shell`,`settings`,`get`,X,Fi],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)}async function Ki(e){let t=await e([`shell`,`settings`,`get`,X,Y],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)||void 0}async function qi(e,t){return(await e([`shell`,`settings`,`put`,X,Y,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await Ki(e)===t:!1}async function Ji(e){await e([`shell`,`settings`,`delete`,X,Y],{allowFailure:!0,timeoutMs:5e3})}function Yi(e){let t=e.trim();return!t||t===`null`?``:t}async function Xi(){try{return(await re(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
9
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const Zi={previousIme:Y,defaultInputMethod:Fi};export{F as C,C as D,S as E,pe as O,P as S,D as T,Pn as _,$ as a,H as b,Ni as c,ti as d,ni as f,Kn as g,er as h,Xi as i,ki as l,cr as m,Vi as n,Hi as o,lr as p,Ii as r,Gi as s,Zi as t,Mi as u,Dn as v,mt as w,En as x,Sn as y};
|