agent-device 0.20.7 → 0.20.8
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.7.apk → agent-device-android-ime-helper-0.20.8.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.7.manifest.json → agent-device-android-ime-helper-0.20.8.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.7.apk → agent-device-android-snapshot-helper-0.20.8.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.7.manifest.json → agent-device-android-snapshot-helper-0.20.8.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +4 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android.js +1 -1
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apps.js +5 -5
- package/dist/src/auth-session.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +1 -1
- package/dist/src/cli.js +4 -4
- package/dist/src/client-metro.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/debug-symbols.js +3 -3
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device-ready.js +1 -0
- package/dist/src/dispatch.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/handler-utils.js +1 -0
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -0
- package/dist/src/helper.js +1 -1
- package/dist/src/host-process.js +3 -2
- package/dist/src/ime-lifecycle.js +5 -5
- package/dist/src/index.d.ts +21 -21
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +1 -1
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +7 -29
- package/dist/src/inventory2.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/notifications.js +1 -1
- package/dist/src/output-path.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -0
- package/dist/src/platform-runtime-toolchain-host.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/prepare-kind.js +13 -13
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -0
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-telemetry.js +1 -0
- package/dist/src/registry.js +4 -4
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +3 -3
- package/dist/src/runtime3.js +3 -3
- package/dist/src/runtime4.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +5 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +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 +10 -10
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-session.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +2 -2
- package/dist/src/src3.js +1 -1
- package/dist/src/text-surface.js +1 -1
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +23 -0
- package/dist/src/web.js +1 -1
- package/package.json +2 -4
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +0 -1
- package/dist/src/context.js +0 -1
- package/dist/src/provider.js +0 -1
- package/dist/src/runner-client.js +0 -1
- package/dist/src/runner-provider.js +0 -1
- package/skills/agent-device/SKILL.md +0 -20
- package/skills/dogfood/SKILL.md +0 -27
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{n as o,r as s,s as c,t as l}from"./version.js";import{
|
|
2
|
-
`||e===`\r`||e===` `}function Te(e){return e===`=`||e===`/`||e===`>`||we(e)}function Ee(e,t){return e.get(t)??null}function De(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=fe(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 Oe(t),Be(t),ke(t,{actionableContentMemo:new WeakMap}),ze(t),t}function Oe(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Oe(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function ke(e,t){for(let n of e.children)ke(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Pe(e,t));r.length!==0&&(e.children=n.filter(e=>Ae(e,r)))}function Ae(e,t){return je(e)||!Me(e,t)}function je(e){return Ne(e)&&!e.hittable&&e.children.length===0}function Me(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!Le(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Re(n.rect,e.rect)>=.9)return!0;return!1}function Ne(e){let t=e.identifier?.trim()??``;return!!(t&&!C(t))}function Pe(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&Le(e)&&(Fe(e)||Ie(e,t))}function Fe(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!C(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!C(n))}function Ie(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||Ie(e,t)));return t.actionableContentMemo.set(e,r),r}function Le(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Re(e,t){let n=t.width*t.height;return n<=0?0:s(e,t)/n}function ze(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),Ge(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function Be(e){let t=e.children.filter(He);if(t.length<2)return;let n=t.filter(e=>Ue(e)&&We(e));if(n.length===0)return;let r=Ve(n);e.children=e.children.filter(e=>Ue(e)?We(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ve(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function He(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ue(e){return e.windowType===1}function We(e){return e.windowActive===!0||e.windowFocused===!0}function Ge(e){if(!e.scrollable||!f(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Ke(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Ke(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 qe(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Je(e);return t.interactiveOnly?Ye(e,a,n,r,i):a.isStructural||a.isVisual?Qe(e,a,r):!0}function Je(e){let t=et(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!C(e.label??``),hasMeaningfulId:r&&!C(e.identifier??``),isStructural:tt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ye(e,t,n,r,i){return Ze(e)?!1:e.focused||e.hittable||f(t.type)&&r?!0:Xe(t,n,r,i)}function Xe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function Ze(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function Qe(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function $e(e){if(!e)return!1;let t=et(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function et(e){return e?e.toLowerCase():``}function tt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function C(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function nt(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 rt(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 w(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))it(n,t);return at(t),{status:t.status,results:t.results}}function it(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ct(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ot(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ct(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&st(t)}function at(e){ot(e),st(e)}function ot(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function st(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ct(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function T(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function E(e){if(e===`true`)return!0;if(e===`false`)return!1}function lt(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 D(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function O(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ut(e,t){let r=O(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 k=`android-snapshot-helper-v1`,A=`uiautomator-xml`,dt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function ft(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:M(t.name,`name`,`android-snapshot-helper`),version:N(t.version,`version`),releaseTag:P(t.releaseTag),assetName:P(t.assetName),apkUrl:_t(t.apkUrl,`apkUrl`),sha256:gt(t.sha256),checksumName:P(t.checksumName),packageName:N(t.packageName,`packageName`),versionCode:j(t.versionCode,`versionCode`),instrumentationRunner:N(t.instrumentationRunner,`instrumentationRunner`),minSdk:j(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:j(t.targetSdk,`targetSdk`),outputFormat:M(t.outputFormat,`outputFormat`,A),statusProtocol:M(t.statusProtocol,`statusProtocol`,k),installArgs:mt(t.installArgs)}}function j(e,t){return lt(e,t,`snapshot helper`)}function M(e,t,n){return D(e,t,n,`snapshot helper`)}function pt(e){return ht(mt(e.installArgs))}function mt(e){let t=vt(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=>!yt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function ht(e){let t={};for(let r of e.slice(1)){let e=bt(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function gt(e){let t=N(e,`sha256`).trim().toLowerCase();if(t.length!==64||!xt(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function N(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 P(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function _t(e,t){return e===null?null:N(e,t)}function vt(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 yt(e){return bt(e)!==void 0}function bt(e){if(Object.hasOwn(dt,e))return dt[e]}function xt(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 St=2e3,Ct=`android_snapshot_helper_retirement_unconfirmed`,F=new Map;function I(e){return`${e.platform}:${e.id}`}async function wt(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||L(e)}async function Tt(e){let t=F.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){F.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}L({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function L(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw F.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Ct,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Et(e){return e instanceof n&&e.details?.reason===Ct}async function Dt(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 Ot(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function kt(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 kt(e.processExit,e.timeoutMs)}function jt(){F.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 Tt({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 wt({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await wt({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`,ne(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:A,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(w(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=w(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===k);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:A,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=T,tn=E;function nn(){return new Promise((e,t)=>{let n=le.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function rn(e,t,r,i){return new Promise((a,o)=>{let s=le.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${t}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function an(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return dn(await rn(e.port,`snapshot ${t}`,on(e),e.signal),t)}function on(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function sn(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function cn(e){let t=e.indexOf(`
|
|
1
|
+
import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{n as o,r as s,s as c,t as l}from"./version.js";import{Hn as u,Q as d,Z as f,rt as p}from"./sdk-batch-runner.js";import{I as m,a as ee,f as te,i as ne,j as h,n as g,o as re,s as _,v as ie}from"./sdk-android-adb.js";import{t as ae}from"./timeouts.js";import"./install-artifact.js";import{r as oe,t as se}from"./entities.js";import v from"node:path";import ce from"node:crypto";import le from"node:os";import y from"node:fs/promises";import ue from"node:net";function de(){let e=[],t=()=>e[e.length-1]===!0;return{open(n,r){let i=t()||d(n);return r||e.push(i),i},close(){e.pop()}}}function*fe(e){let t=/<node\b[^>]*>|<\/node>/g,n=de(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=pe(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function pe(e){let t=ye(e),n=oe(t.bounds);return{...t,...n?{rect:n}:{}}}function me(e,t,n){let{sourceNodes:r,...i}=b(ke(e),t,n);return i}function b(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(he(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 he(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,ve(e,t),a),c=o||d(t.identifier),l=s?ge(e,t,r,c):r,u=i||!!t.hittable,f=a||tt(t.type);for(let r of t.children)if(he(e,r,n+1,l,u,f,c),e.truncated)return}function ge(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:_e(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function _e(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function ve(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||ve(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function ye(e){let t=be(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=oe(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 be(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=xe(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function xe(e,t,n){if(t=Ce(e,t,n),t>=n||we(e[t]))return;let r=t;t=Se(e,t,n);let i=e.slice(r,t);if(t=Ce(e,t,n),!i||e[t]!==`=`)return;t=Ce(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:se(e.slice(o,s)),nextCursor:s+1}}function Se(e,t,n){for(;t<n&&!De(e[t]??``);)t+=1;return t}function Ce(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=pe(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,hittable:a.clickable??a.focusable,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return Ae(t),He(t),je(t,{actionableContentMemo:new WeakMap}),Ve(t),t}function Ae(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Ae(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function je(e,t){for(let n of e.children)je(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Ie(e,t));r.length!==0&&(e.children=n.filter(e=>Me(e,r)))}function Me(e,t){return Ne(e)||!Pe(e,t)}function Ne(e){return Fe(e)&&!e.hittable&&e.children.length===0}function Pe(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!ze(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Be(n.rect,e.rect)>=.9)return!0;return!1}function Fe(e){let t=e.identifier?.trim()??``;return!!(t&&!x(t))}function Ie(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&ze(e)&&(Le(e)||Re(e,t))}function Le(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!x(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!x(n))}function Re(e,t){let n=t.actionableContentMemo.get(e);if(n!==void 0)return n;let r=e.children.some(e=>e.visibleToUser!==!1&&(!!e.hittable||Re(e,t)));return t.actionableContentMemo.set(e,r),r}function ze(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Be(e,t){let n=t.width*t.height;return n<=0?0:s(e,t)/n}function Ve(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),qe(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function He(e){let t=e.children.filter(We);if(t.length<2)return;let n=t.filter(e=>Ge(e)&&Ke(e));if(n.length===0)return;let r=Ue(n);e.children=e.children.filter(e=>Ge(e)?Ke(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ue(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function We(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ge(e){return e.windowType===1}function Ke(e){return e.windowActive===!0||e.windowFocused===!0}function qe(e){if(!e.scrollable||!u(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Je(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Je(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function Ye(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Xe(e);return t.interactiveOnly?Ze(e,a,n,r,i):a.isStructural||a.isVisual?et(e,a,r):!0}function Xe(e){let t=nt(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!x(e.label??``),hasMeaningfulId:r&&!x(e.identifier??``),isStructural:rt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ze(e,t,n,r,i){return $e(e)?!1:e.focused||e.hittable||u(t.type)&&r?!0:Qe(t,n,r,i)}function Qe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function $e(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function et(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function tt(e){if(!e)return!1;let t=nt(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function nt(e){return e?e.toLowerCase():``}function rt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function x(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function it(e,t){let n=t.toLowerCase(),r=[...e.children],i=0;for(;i<r.length;){let e=r[i++],t=e.label?.toLowerCase()??``,a=e.value?.toLowerCase()??``,o=e.identifier?.toLowerCase()??``;if(t.includes(n)||a.includes(n)||o.includes(n))return e;r.push(...e.children)}return null}function at(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}function S(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ot(n,t);return st(t),{status:t.status,results:t.results}}function ot(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ut(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ct(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ut(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&<(t)}function st(e){ct(e),lt(e)}function ct(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function lt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ut(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function C(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function w(e){if(e===`true`)return!0;if(e===`false`)return!1}function dt(e,t,r){if(typeof e!=`number`||!Number.isInteger(e))throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} must be an integer.`);return e}function T(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function E(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ft(e,t){let r=E(e,`sha256`,t).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new n(`INVALID_ARGS`,`Android ${t} manifest sha256 must be a 64-character hex string.`);return r}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,pt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:yt(t.apkUrl,`apkUrl`),sha256:vt(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:gt(t.installArgs)}}function k(e,t){return dt(e,t,`snapshot helper`)}function A(e,t,n){return T(e,t,n,`snapshot helper`)}function ht(e){return _t(gt(e.installArgs))}function gt(e){let t=bt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!xt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function _t(e){let t={};for(let r of e.slice(1)){let e=St(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function vt(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ct(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function yt(e,t){return e===null?null:j(e,t)}function bt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function xt(e){return St(e)!==void 0}function St(e){if(Object.hasOwn(pt,e))return pt[e]}function Ct(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const wt=2e3,Tt=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function Et(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Tt,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Dt(e){return e instanceof n&&e.details?.reason===Tt}async function Ot(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Mt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Nt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function kt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function At(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function jt(){N.clear()}async function Mt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Nt(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function Pt(e){let t=Ft(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(It(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Lt(e,t,i);if(t.outputPath&&!o&&await Wt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,te(i,{helper:a.metadata}));return a}function Ft(e){let t=R(e.timeoutMs,8e3),n=R(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:R(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:R(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:R(e.commandTimeoutMs,t+5e3),maxDepth:R(e.maxDepth,128),maxNodes:R(e.maxNodes,5e3),packageName:n,runner:R(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function R(e,t){return e===void 0?t:e}function It(e){return[`shell`,`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],e.runner]}async function Lt(e,t,n){try{return{output:Gt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Rt(e,t,n,r)}}async function Rt(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await zt(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},i)}async function zt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Vt(e.adb,t.outputPath,Ut(`${n.stdout}\n${n.stderr}`)??Bt(t))}function Bt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Vt(e,t,n){let r;try{r=await e(Ht(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Ht(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ut(e){try{return $t(qt(S(e).results))}catch{return null}}async function Wt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Gt(e){let t=S(e),n=qt(t.results);return{xml:Yt(Kt(t.status),n),metadata:{...$t(n),transport:`instrumentation`}}}function Kt(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:z(n.chunkIndex),count:z(n.chunkCount),payloadBase64:e})}return t}function qt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Jt(t),{errorType:t.errorType,helper:t});return t}function Jt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Yt(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=Xt(e),i=Buffer.concat(Qt(Zt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Xt(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function Zt(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Qt(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function $t(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs),waitForIdleQuietMs:z(e.waitForIdleQuietMs),timeoutMs:z(e.timeoutMs),maxDepth:z(e.maxDepth),maxNodes:z(e.maxNodes),rootPresent:tn(e.rootPresent),captureMode:en(e.captureMode),windowCount:z(e.windowCount),nodeCount:z(e.nodeCount),truncated:tn(e.truncated),elapsedMs:z(e.elapsedMs)}}function en(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const z=C,tn=w;function nn(){return new Promise((e,t)=>{let n=ue.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function rn(e,t,r,i){return new Promise((a,o)=>{let s=ue.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${t}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function an(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return dn(await rn(e.port,`snapshot ${t}`,on(e),e.signal),t)}function on(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function sn(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function cn(e){let t=e.indexOf(`
|
|
3
3
|
|
|
4
4
|
`);return mn(e.slice(0,t<0?e.length:t))}function ln(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:t})}function un(e,t){let n=cn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function dn(e,t){let r=e.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=mn(e.slice(0,r)),a=e.slice(r+2);return fn(i,t),pn(i,a),{xml:a,metadata:hn(i)}}function fn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function pn(e,t){let r=T(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function mn(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function hn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:A,waitForIdleTimeoutMs:T(e.waitForIdleTimeoutMs),waitForIdleQuietMs:T(e.waitForIdleQuietMs),timeoutMs:T(e.timeoutMs),maxDepth:T(e.maxDepth),maxNodes:T(e.maxNodes),rootPresent:E(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:T(e.windowCount),nodeCount:T(e.nodeCount),truncated:E(e.truncated),elapsedMs:T(e.elapsedMs)}}const gn=5e3,B=new Map,_n=new Map;async function vn(e){let t=e.deviceKey??`android:default`;if(await Tt({deviceKey:t,adb:e.adb,signal:e.signal}),!jn()||!e.adbProvider?.spawn)return;let n=xn(Ft(e)),r=await yn({deviceKey:t,identity:An(t,n,e),options:e,resolved:n});if(r)return await bn({session:r,deviceKey:t,options:e,resolved:n})}async function yn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(_n.get(t)===n)return;let a=B.get(t);if(a&&a.identity!==n&&(await V(t),a=void 0),!a)try{a=await kn({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),_n.set(t,n),m({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Et(e))throw e;return}return a}async function bn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await an({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await V(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),m({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:Sn(e)}});return}}function xn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function Sn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Cn(e){let t=B.get(e.deviceKey);if(!t)return;if(!wn(t.helper,e.helper)){m({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await V(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=cn(await rn(t.port,i,e.timeoutMs)),ln(a,r)}catch(t){throw await V(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function wn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&Tn(e.helperVersion,t.helperVersion)&&Tn(e.helperVersionCode,t.helperVersionCode)&&Tn(e.sha256,t.sha256)}function Tn(e,t){return e===void 0||t===void 0||e===t}async function V(e,t={}){let n=B.get(e);if(!n)return!1;B.delete(e);let r=Ot(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await En(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:St:gn,s=i?250:2e3,[c,l]=await Promise.all([At({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Dt({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);return m({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&&L({deviceKey:e,packageName:n.helper.packageName,cause:t.cause}),!0}async function En(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=un(await rn(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await kt(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function Dn(e){await V(I(e))}async function On(){let e=await Promise.allSettled([...B.keys()].map(e=>V(e)));_n.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);jt()}async function kn(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:gn,signal:e.options.signal});let r=It({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await sn(o,1e4,e.options.signal),B.set(e.deviceKey,s),m({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=Ot(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([kt(n,250),Dt({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:St})]);throw r.runtimeForceStopped||L({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function An(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function jn(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const Mn=1e4;async function Nn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await Bn(a,o,u);let f=await Pn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let p=await re(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(p.exitCode!==0)throw g(`Failed to install ${u}`,p,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Pn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await Ln(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await Rn(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Fn(t){let r=o(),i=y.join(l(),`android`,t.helperDirName,`dist`),a=y.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await b.readFile(a,`utf8`))),n=y.join(i,e.assetName);return await b.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function In(e){return async t=>await Nn({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function Ln(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Hn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Rn(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:Mn,signal:i}),o=zn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new n(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=await b.mkdtemp(y.join(ce.tmpdir(),`agent-device-helper-`)),c=y.join(s,`base.apk`);try{let e=await te(o,c,{provider:t,allowFailure:!0,timeoutMs:Mn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Vn(c)}finally{await b.rm(s,{recursive:!0,force:!0})}}function zn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function Bn(e,t,r){let i=await Vn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Vn(e){let t=se.createHash(`sha256`);return t.update(await b.readFile(e)),t.digest(`hex`)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const H=new Map;function Un(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of H.keys())e.startsWith(t)&&Kn(e)}function Wn(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Gn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of H.keys())t!==e&&t.startsWith(i)&&H.delete(t);H.set(e,t)}function Kn(e){e&&H.delete(e)}async function qn(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Wn(e.deviceKey,i,a,o),c=s?H.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await Bn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Xn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Pn({adb:t,adbProvider:Yn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Gn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Zn(t,e.adbProvider??t,n.apkPath,pt(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Kn(s),Jn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Kn(s),Jn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Gn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function Jn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Yn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Xn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Qn(`${i.stdout}\n${i.stderr}`,t)}async function Zn(e,t,n,r,i){let a=async()=>await re(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!$n(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
|
|
6
|
+
`);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=mn(e.slice(0,r)),a=e.slice(r+2);return fn(i,t),pn(i,a),{xml:a,metadata:hn(i)}}function fn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function pn(e,t){let r=C(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function mn(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function hn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:C(e.waitForIdleTimeoutMs),waitForIdleQuietMs:C(e.waitForIdleQuietMs),timeoutMs:C(e.timeoutMs),maxDepth:C(e.maxDepth),maxNodes:C(e.maxNodes),rootPresent:w(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:C(e.windowCount),nodeCount:C(e.nodeCount),truncated:w(e.truncated),elapsedMs:C(e.elapsedMs)}}const gn=5e3,B=new Map,_n=new Map;async function vn(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!jn()||!e.adbProvider?.spawn)return;let n=xn(Ft(e)),r=await yn({deviceKey:t,identity:An(t,n,e),options:e,resolved:n});if(r)return await bn({session:r,deviceKey:t,options:e,resolved:n})}async function yn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(_n.get(t)===n)return;let a=B.get(t);if(a&&a.identity!==n&&(await V(t),a=void 0),!a)try{a=await kn({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),_n.set(t,n),h({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Dt(e))throw e;return}return a}async function bn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await an({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await V(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:Sn(e)}});return}}function xn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function Sn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Cn(e){let t=B.get(e.deviceKey);if(!t)return;if(!wn(t.helper,e.helper)){h({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await V(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=cn(await rn(t.port,i,e.timeoutMs)),ln(a,r)}catch(t){throw await V(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function wn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&Tn(e.helperVersion,t.helperVersion)&&Tn(e.helperVersionCode,t.helperVersionCode)&&Tn(e.sha256,t.sha256)}function Tn(e,t){return e===void 0||t===void 0||e===t}async function V(e,t={}){let n=B.get(e);if(!n)return!1;B.delete(e);let r=kt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await En(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:wt:gn,s=i?250:2e3,[c,l]=await Promise.all([At({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Ot({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);return h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,forceKilled:!a.exited&&c,forced:i||t.signal?.aborted===!0,runtimeForceStopped:l.runtimeForceStopped,externalCleanupTimedOut:l.timedOut}}),!a.exited&&!l.runtimeForceStopped&&I({deviceKey:e,packageName:n.helper.packageName,cause:t.cause}),!0}async function En(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=un(await rn(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await L(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function Dn(e){await V(P(e))}async function On(){let e=await Promise.allSettled([...B.keys()].map(e=>V(e)));_n.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);jt()}async function kn(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:gn,signal:e.options.signal});let r=It({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await sn(o,1e4,e.options.signal),B.set(e.deviceKey,s),h({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(t){let n=kt(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([L(n,250),Ot({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:wt})]);throw r.runtimeForceStopped||I({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function An(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function jn(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const Mn=1e4;async function Nn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await Bn(a,o,u);let f=await Pn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let p=await ne(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(p.exitCode!==0)throw g(`Failed to install ${u}`,p,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Pn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await Ln(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await Rn(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Fn(t){let r=o(),i=v.join(l(),`android`,t.helperDirName,`dist`),a=v.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await y.readFile(a,`utf8`))),n=v.join(i,e.assetName);return await y.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function In(e){return async t=>await Nn({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function Ln(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Hn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Rn(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:Mn,signal:i}),o=zn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new n(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=await y.mkdtemp(v.join(le.tmpdir(),`agent-device-helper-`)),c=v.join(s,`base.apk`);try{let e=await ee(o,c,{provider:t,allowFailure:!0,timeoutMs:Mn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Vn(c)}finally{await y.rm(s,{recursive:!0,force:!0})}}function zn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function Bn(e,t,r){let i=await Vn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Vn(e){let t=ce.createHash(`sha256`);return t.update(await y.readFile(e)),t.digest(`hex`)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const H=new Map;function Un(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of H.keys())e.startsWith(t)&&Kn(e)}function Wn(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Gn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of H.keys())t!==e&&t.startsWith(i)&&H.delete(t);H.set(e,t)}function Kn(e){e&&H.delete(e)}async function qn(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Wn(e.deviceKey,i,a,o),c=s?H.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await Bn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Xn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Pn({adb:t,adbProvider:Yn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Gn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Zn(t,e.adbProvider??t,n.apkPath,ht(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Kn(s),Jn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Kn(s),Jn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Gn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function Jn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Yn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Xn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Qn(`${i.stdout}\n${i.stderr}`,t)}async function Zn(e,t,n,r,i){let a=async()=>await ne(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!$n(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
|
|
7
7
|
`)}}function Qn(e,t){let n=`package:${t}`;for(let t of e.split(/\r?\n/)){if(!t.startsWith(n)||t.length>n.length&&!/\s/.test(t[n.length]??``))continue;let e=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(e)return Number(e[1])}}function $n(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const er=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function tr(e){return er.has(e)}const nr=new Set([`android`,`com.android.systemui`]),rr=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,U=/^android:id\/button[123]$/i,ir=/(?:^|:)id\/permission_/i,ar=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,or=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,sr=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function cr(e){if(e!==null){if(U.test(e))return`button`;if(rr.test(e))return`content`}}function lr(e){let t=dr(e),n=t.nodes;if(n.length===0)return null;let r=gr(n),i=n.filter(e=>W(e)&&!Er(e)),a=yr(i),o=br(i,a),s=Dr(n);return{alert:{...a?{title:a}:{},...o?{message:o}:{},buttons:r.map(e=>e.label),platform:`android`,source:t.source,...s?{packageName:s}:{}},buttons:r}}function ur(e,t){let n=t===`accept`?`accept`:`dismiss`;return e.find(e=>e.role===n)||(t===`dismiss`?e.find(e=>e.role===`neutral`)??null:e.length===1?e[0]??null:null)}function dr(e){let t=e.filter(e=>wr(e));if(t.length)return{nodes:t,source:`permission`};let n=hr(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:fr(e),source:`native-dialog`}}function fr(e){let t=e.filter(e=>pr(e.type??``)),n=e.filter(e=>rr.test(e.identifier??``)),r=t.length?[...t,...n]:mr(n);if(r.length===0)return[];let i=xr(e,r);return i===void 0?r:Cr(e,i)}function pr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function mr(e){let t=e.some(e=>U.test(e.identifier??``)),n=e.some(e=>!U.test(e.identifier??``));return t&&n?e:[]}function hr(e){let t=e.filter(e=>Tr(e));if(t.length===0)return[];let n=xr(e,t);return n===void 0?t:Cr(e,n).filter(e=>e.bundleId&&nr.has(e.bundleId))}function gr(e){let t=new Set,n=[];for(let r of e){let e=W(r);if(!e||!r.rect||!Er(r))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=i(r.rect);n.push({label:e,x:o.x,y:o.y,role:_r(r,e)})}return n}function _r(e,t){return vr(e.identifier??``)||(or.test(t.trim())?`accept`:sr.test(t.trim())?`dismiss`:`neutral`)}function vr(e){return/(?:^|:)id\/button1$/i.test(e)?`accept`:/(?:^|:)id\/button2$/i.test(e)?`dismiss`:/(?:^|:)id\/button3$/i.test(e)?`neutral`:/(?:^|:)id\/permission_allow/i.test(e)?`accept`:/(?:^|:)id\/permission_deny/i.test(e)?`dismiss`:null}function yr(e){return W(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||W(e[0])}function br(e,t){let n=e.map(e=>W(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
|
|
8
|
-
`):void 0}function xr(e,t){let n=t[0];if(!n)return;let r=Sr(e,n.index);for(let n of t.slice(1)){let t=new Set(Sr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function Sr(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function Cr(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function wr(e){let t=e.bundleId??``;return er.has(t)||ir.test(e.identifier??``)}function Tr(e){let t=e.bundleId??``;return nr.has(t)&&ar.test(W(e))}function Er(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||U.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function W(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Dr(e){return e.find(e=>e.bundleId)?.bundleId}const Or=new Set([`android`,`com.android.systemui`]);function kr(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=zr(e,n.foregroundAppPackage);return jr(r,t)?G(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Lr(r)?{outcome:`ok`}:Ar(r)?{outcome:`system-surface-only`}:Mr(r)?{outcome:`ok`}:Nr(r)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Pr(r)||Fr(r,t)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Ir(r)?G(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function G(e,t,n,r){return{outcome:`unusable`,decision:Rr(e,t,n,r)}}function Ar(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function jr(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function Mr(e){return Nr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Nr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Pr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Fr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Ir(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Lr(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Rr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:$r(e,t)}}function zr(e,t){let n=Br(t);for(let t of de(e))Vr(n,t);return Jr(n)}function Br(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function Vr(e,t){e.nodeCount+=1,Qr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Hr(e,t.resourceId),Ur(e,t),Wr(e,t)}function Hr(e,t){let n=cr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Ur(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Wr(e,t){Yr(t)&&(e.meaningfulNodeCount+=1,Gr(e,t),qr(e,t))}function Gr(e,t){e.currentWindowType===1&&!Zr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Kr(e)&&!p(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Kr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function qr(e,t){Zr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),u({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Jr(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Yr(e){return e.visibleToUser===!1?!1:Xr(e.text)||Xr(e.desc)||Xr(e.resourceId)}function Xr(e){return e!==null&&e.trim()!==``}function Zr(e){return e===null||Or.has(e)}function Qr(e){return e!==null&&Or.has(e)}function $r(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function ei(e){let t=await V(e.deviceKey,{signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await ti(e.adb,e.packageName)}async function ti(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await ie(150),m({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){m({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}const ni=5e3,ri=3e4;async function ii(e,t={}){let n=v(e,t.helperAdb).exec;return(await li(e,t,n)).xml}async function ai(e,t={}){let n=v(e,t.helperAdb).exec,r=await li(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=pe(i,void 0,t),n=oi(e.truncated,r.metadata);return{...e,...si(n),androidSnapshot:r.metadata}}let a=De(i),o=x(a,void 0,t),s=oi(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ci({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...si(s),androidSnapshot:r.metadata}}function oi(e,t){return e===!0||t.helperTruncated===!0?!0:e}function si(e){return e===!0?{truncated:!0}:{}}function ci(e){if(Oi(e.interactiveSnapshot.nodes).size>0||Di(e.xml))return;let t=x(e.tree,void 0,{...e.options,interactiveOnly:!1});ki(c(r(t.nodes)),t,e.interactiveSnapshot)}async function li(e,t,n){let r=v(e,t.helperAdb),i=await h(`android_snapshot_helper_artifact_resolution`,async()=>await Ti(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await ui(e,t,n,i.artifact);throw m({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),Ei(i.errorReason)}async function ui(e,t,n,r){let i=I(e),a=v(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await hi(t.signal);let s=await mi({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3)return await gi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal});e=s.decision.reason}}finally{o&&await V(i)}}async function di(e,t,n,r,i){let a=await h(`android_snapshot_helper_install`,async()=>await qn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return m({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function fi(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:ni,commandTimeoutMs:ri,signal:n};try{let e=await h(`android_snapshot_helper_session_capture`,async()=>await vn(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni});if(e)return e}catch(t){if(n?.throwIfAborted(),Et(t))throw t;m({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await ti(r,a.manifest.packageName)}return await h(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni,commandTimeoutMs:ri})}function pi(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function mi(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await di(t,n,r,i,a);e.installed&&await V(a),s=pi(await fi({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await _i({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=kr(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(m({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&&m({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function hi(e){e?.throwIfAborted(),await ie(250),e?.throwIfAborted()}async function gi(e){throw m({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),await ei({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function _i(e){let t=vi(e.error);throw m({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await V(e.helperDeviceKey),await ti(e.adb,e.artifact.manifest.packageName),Un({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),yi(e.error,t)}function vi(t){let n=e(t),r=Ci(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function yi(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...xi(a),androidSnapshotHelperFailureReason:i,hint:bi(a)},r)}function bi(e){return wi(e.details?.helper,e.message)||Si(e)?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function xi(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function Si(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function Ci(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function wi(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=Ci(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ti(t){if(t)return{artifact:t};let n=o(),r=y.join(l(),`android`,`snapshot-helper`,`dist`),i=y.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await b.access(i)}catch{return{}}try{let e=ft(JSON.parse(await b.readFile(i,`utf8`))),t=y.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await b.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function Ei(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function Di(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Oi(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function ki(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const K=`IME helper`,Ai=`android-ime-helper-v1`;async function ji(){return await Fn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Mi,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Mi(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:D(t.name,`name`,`android-ime-helper`,K),version:O(t.version,`version`,K),assetName:O(t.assetName,`assetName`,K),sha256:ut(t.sha256,K),packageName:D(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,K),versionCode:lt(t.versionCode,`versionCode`,K),serviceComponent:D(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,K),broadcastProtocol:D(t.broadcastProtocol,`broadcastProtocol`,Ai,K)}}const Ni=In({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function q(e){return`${e.platform}:${e.id}`}async function Pi(e,t,n){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Fi(e,t){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Ii(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Ai);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const J=`agent_device_ime_helper_previous_ime`,Y=`secure`,Li=`default_input_method`,X=new Set;function Ri(e){return X.has(q(e))}function Z(e){return y.join(e,`android-test-ime-pending`)}function zi(e,t){return y.join(Z(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Bi(t,n){try{await b.mkdir(Z(t),{recursive:!0}),await b.writeFile(zi(t,n),n)}catch(r){m({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function Vi(e,t){await b.rm(zi(e,t),{force:!0}).catch(()=>{})}async function Hi(e){let t;try{t=await b.readdir(Z(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await b.readFile(y.join(Z(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Ui(e,t={}){let n=_(e),r=v(e),i=await ji(),{manifest:a}=i,o=q(e);await Ni({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await Q(n);if(s===a.serviceComponent)return X.add(o),t.stateDir&&await Bi(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await $(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(X.add(o),!await Ji(n,s))return X.delete(o),m({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Bi(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await Q(n);return l===a.serviceComponent?(m({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(X.delete(o),await Yi(n).catch(()=>{}),t.stateDir&&await Vi(t.stateDir,e.id),m({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Wi(e,t={}){let n=q(e);if(!X.has(n))return{restored:!1,reason:`no-record`};X.delete(n);let r=await Ki(_(e),e);return t.stateDir&&Gi(r.reason)&&await Vi(t.stateDir,e.id),r}function Gi(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Ki(e,t){let n=t.id;if(X.has(q(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await $(e);if(!r)return{restored:!1,reason:`no-record`};let i=await Q(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return m({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await Q(e);return a===r?(await Yi(e).catch(()=>{}),m({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(m({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function qi(t){let n=await Hi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){m({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).message}});return}for(let i of n){if(!r.has(i))continue;let n={platform:`android`,id:i,name:i,kind:i.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{let e=await Ki(_(n),n);e.restored&&m({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Gi(e.reason)&&await Vi(t.stateDir,i)}catch(t){m({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function Q(e){let t=await e([`shell`,`settings`,`get`,Y,Li],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)}async function $(e){let t=await e([`shell`,`settings`,`get`,Y,J],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)||void 0}async function Ji(e,t){return(await e([`shell`,`settings`,`put`,Y,J,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await $(e)===t:!1}async function Yi(e){await e([`shell`,`settings`,`delete`,Y,J],{allowFailure:!0,timeoutMs:5e3})}function Xi(e){let t=e.trim();return!t||t===`null`?``:t}async function Zi(){try{return(await ee(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
9
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const Qi={previousIme:J,defaultInputMethod:Li};export{
|
|
8
|
+
`):void 0}function xr(e,t){let n=t[0];if(!n)return;let r=Sr(e,n.index);for(let n of t.slice(1)){let t=new Set(Sr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function Sr(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function Cr(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function wr(e){let t=e.bundleId??``;return er.has(t)||ir.test(e.identifier??``)}function Tr(e){let t=e.bundleId??``;return nr.has(t)&&ar.test(W(e))}function Er(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||U.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function W(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Dr(e){return e.find(e=>e.bundleId)?.bundleId}const Or=new Set([`android`,`com.android.systemui`]);function kr(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=zr(e,n.foregroundAppPackage);return jr(r,t)?G(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Lr(r)?{outcome:`ok`}:Ar(r)?{outcome:`system-surface-only`}:Mr(r)?{outcome:`ok`}:Nr(r)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Pr(r)||Fr(r,t)?G(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Ir(r)?G(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function G(e,t,n,r){return{outcome:`unusable`,decision:Rr(e,t,n,r)}}function Ar(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function jr(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function Mr(e){return Nr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Nr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Pr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Fr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Ir(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Lr(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Rr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:$r(e,t)}}function zr(e,t){let n=Br(t);for(let t of fe(e))Vr(n,t);return Jr(n)}function Br(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function Vr(e,t){e.nodeCount+=1,Qr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Hr(e,t.resourceId),Ur(e,t),Wr(e,t)}function Hr(e,t){let n=cr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Ur(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Wr(e,t){Yr(t)&&(e.meaningfulNodeCount+=1,Gr(e,t),qr(e,t))}function Gr(e,t){e.currentWindowType===1&&!Zr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Kr(e)&&!f(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Kr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function qr(e,t){Zr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),p({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Jr(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Yr(e){return e.visibleToUser===!1?!1:Xr(e.text)||Xr(e.desc)||Xr(e.resourceId)}function Xr(e){return e!==null&&e.trim()!==``}function Zr(e){return e===null||Or.has(e)}function Qr(e){return e!==null&&Or.has(e)}function $r(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function ei(e){let t=await V(e.deviceKey,{signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await ti(e.adb,e.packageName)}async function ti(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await ae(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){h({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}const ni=5e3,ri=3e4;async function ii(e,t={}){let n=_(e,t.helperAdb).exec;return(await li(e,t,n)).xml}async function ai(e,t={}){let n=_(e,t.helperAdb).exec,r=await li(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=me(i,void 0,t),n=oi(e.truncated,r.metadata);return{...e,...si(n),androidSnapshot:r.metadata}}let a=ke(i),o=b(a,void 0,t),s=oi(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ci({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...si(s),androidSnapshot:r.metadata}}function oi(e,t){return e===!0||t.helperTruncated===!0?!0:e}function si(e){return e===!0?{truncated:!0}:{}}function ci(e){if(Oi(e.interactiveSnapshot.nodes).size>0||Di(e.xml))return;let t=b(e.tree,void 0,{...e.options,interactiveOnly:!1});ki(c(r(t.nodes)),t,e.interactiveSnapshot)}async function li(e,t,n){let r=_(e,t.helperAdb),i=await m(`android_snapshot_helper_artifact_resolution`,async()=>await Ti(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await ui(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),Ei(i.errorReason)}async function ui(e,t,n,r){let i=P(e),a=_(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await hi(t.signal);let s=await mi({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3)return await gi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal});e=s.decision.reason}}finally{o&&await V(i)}}async function di(e,t,n,r,i){let a=await m(`android_snapshot_helper_install`,async()=>await qn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return h({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function fi(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:ni,commandTimeoutMs:ri,signal:n};try{let e=await m(`android_snapshot_helper_session_capture`,async()=>await vn(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni});if(e)return e}catch(t){if(n?.throwIfAborted(),Dt(t))throw t;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await ti(r,a.manifest.packageName)}return await m(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:ni,commandTimeoutMs:ri})}function pi(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function mi(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await di(t,n,r,i,a);e.installed&&await V(a),s=pi(await fi({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await _i({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=kr(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(h({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function hi(e){e?.throwIfAborted(),await ae(250),e?.throwIfAborted()}async function gi(e){throw h({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),await ei({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function _i(e){let t=vi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await V(e.helperDeviceKey),await ti(e.adb,e.artifact.manifest.packageName),Un({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),yi(e.error,t)}function vi(t){let n=e(t),r=Ci(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function yi(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...xi(a),androidSnapshotHelperFailureReason:i,hint:bi(a)},r)}function bi(e){return wi(e.details?.helper,e.message)||Si(e)?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function xi(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function Si(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function Ci(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function wi(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=Ci(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ti(t){if(t)return{artifact:t};let n=o(),r=v.join(l(),`android`,`snapshot-helper`,`dist`),i=v.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await y.access(i)}catch{return{}}try{let e=mt(JSON.parse(await y.readFile(i,`utf8`))),t=v.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await y.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function Ei(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function Di(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Oi(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function ki(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const K=`IME helper`,Ai=`android-ime-helper-v1`;async function ji(){return await Fn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Mi,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Mi(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:T(t.name,`name`,`android-ime-helper`,K),version:E(t.version,`version`,K),assetName:E(t.assetName,`assetName`,K),sha256:ft(t.sha256,K),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,K),versionCode:dt(t.versionCode,`versionCode`,K),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,K),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Ai,K)}}const Ni=In({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function q(e){return`${e.platform}:${e.id}`}async function Pi(e,t,n){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Fi(e,t){await Ii(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Ii(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Ai);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const J=`agent_device_ime_helper_previous_ime`,Y=`secure`,Li=`default_input_method`,X=new Set;function Ri(e){return X.has(q(e))}function Z(e){return v.join(e,`android-test-ime-pending`)}function zi(e,t){return v.join(Z(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Bi(t,n){try{await y.mkdir(Z(t),{recursive:!0}),await y.writeFile(zi(t,n),n)}catch(r){h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function Vi(e,t){await y.rm(zi(e,t),{force:!0}).catch(()=>{})}async function Hi(e){let t;try{t=await y.readdir(Z(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await y.readFile(v.join(Z(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Ui(e,t={}){let n=re(e),r=_(e),i=await ji(),{manifest:a}=i,o=q(e);await Ni({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await Q(n);if(s===a.serviceComponent)return X.add(o),t.stateDir&&await Bi(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await $(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(X.add(o),!await Ji(n,s))return X.delete(o),h({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Bi(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await Q(n);return l===a.serviceComponent?(h({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(X.delete(o),await Yi(n).catch(()=>{}),t.stateDir&&await Vi(t.stateDir,e.id),h({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Wi(e,t={}){let n=q(e);if(!X.has(n))return{restored:!1,reason:`no-record`};X.delete(n);let r=await Ki(re(e),e);return t.stateDir&&Gi(r.reason)&&await Vi(t.stateDir,e.id),r}function Gi(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Ki(e,t){let n=t.id;if(X.has(q(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await $(e);if(!r)return{restored:!1,reason:`no-record`};let i=await Q(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return h({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await Q(e);return a===r?(await Yi(e).catch(()=>{}),h({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(h({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function qi(t){let n=await Hi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){h({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).message}});return}for(let i of n){if(!r.has(i))continue;let n={platform:`android`,id:i,name:i,kind:i.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{let e=await Ki(re(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Gi(e.reason)&&await Vi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function Q(e){let t=await e([`shell`,`settings`,`get`,Y,Li],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)}async function $(e){let t=await e([`shell`,`settings`,`get`,Y,J],{allowFailure:!0,timeoutMs:5e3});return Xi(t.exitCode===0?t.stdout:``)||void 0}async function Ji(e,t){return(await e([`shell`,`settings`,`put`,Y,J,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await $(e)===t:!1}async function Yi(e){await e([`shell`,`settings`,`delete`,Y,J],{allowFailure:!0,timeoutMs:5e3})}function Xi(e){let t=e.trim();return!t||t===`null`?``:t}async function Zi(){try{return(await ie(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
|
|
9
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const Qi={previousIme:J,defaultInputMethod:Li};export{F as C,C as D,S as E,fe as O,P as S,D as T,Fn as _,Q as a,V as b,Fi as c,ii as d,ai as f,qn as g,tr as h,Zi as i,ji as l,lr as m,Ui as n,Wi as o,ur as p,Ri as r,qi as s,Qi as t,Pi as u,On as v,mt as w,Dn as x,Cn as y};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -233,6 +233,27 @@ type ShutdownCommandResult = {
|
|
|
233
233
|
appleOs?: AppleOS;
|
|
234
234
|
};
|
|
235
235
|
//#endregion
|
|
236
|
+
//#region packages/contracts/src/perf.d.ts
|
|
237
|
+
declare const PERF_AREA_VALUES: readonly ['metrics', 'frames', 'memory', 'cpu', 'trace'];
|
|
238
|
+
declare const PERF_ACTION_VALUES: readonly ['sample', 'snapshot', 'start', 'stop', 'report'];
|
|
239
|
+
declare const PERF_SUBJECT_VALUES: readonly ['profile'];
|
|
240
|
+
declare const PERF_KIND_VALUES: readonly ['xctrace', 'simpleperf', 'perfetto', 'android-hprof', 'memgraph'];
|
|
241
|
+
type PerfArea = (typeof PERF_AREA_VALUES)[number];
|
|
242
|
+
type PerfAction = (typeof PERF_ACTION_VALUES)[number];
|
|
243
|
+
type PerfSubject = (typeof PERF_SUBJECT_VALUES)[number];
|
|
244
|
+
type PerfKind = (typeof PERF_KIND_VALUES)[number];
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region packages/contracts/src/json.d.ts
|
|
247
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
248
|
+
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
249
|
+
type JsonObject = {
|
|
250
|
+
[key: string]: JsonValue;
|
|
251
|
+
};
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region packages/contracts/src/logs.d.ts
|
|
254
|
+
declare const LOG_ACTION_VALUES: readonly ['path', 'start', 'stop', 'doctor', 'mark', 'clear'];
|
|
255
|
+
type LogAction = (typeof LOG_ACTION_VALUES)[number];
|
|
256
|
+
//#endregion
|
|
236
257
|
//#region packages/contracts/src/recording-scope.d.ts
|
|
237
258
|
declare const RECORDING_SCOPE_VALUES: readonly ['app', 'device', 'system'];
|
|
238
259
|
type RecordingScope = (typeof RECORDING_SCOPE_VALUES)[number];
|
|
@@ -280,27 +301,6 @@ type TraceCommandResult = {
|
|
|
280
301
|
artifacts: DaemonArtifact[];
|
|
281
302
|
};
|
|
282
303
|
//#endregion
|
|
283
|
-
//#region packages/contracts/src/perf.d.ts
|
|
284
|
-
declare const PERF_AREA_VALUES: readonly ['metrics', 'frames', 'memory', 'cpu', 'trace'];
|
|
285
|
-
declare const PERF_ACTION_VALUES: readonly ['sample', 'snapshot', 'start', 'stop', 'report'];
|
|
286
|
-
declare const PERF_SUBJECT_VALUES: readonly ['profile'];
|
|
287
|
-
declare const PERF_KIND_VALUES: readonly ['xctrace', 'simpleperf', 'perfetto', 'android-hprof', 'memgraph'];
|
|
288
|
-
type PerfArea = (typeof PERF_AREA_VALUES)[number];
|
|
289
|
-
type PerfAction = (typeof PERF_ACTION_VALUES)[number];
|
|
290
|
-
type PerfSubject = (typeof PERF_SUBJECT_VALUES)[number];
|
|
291
|
-
type PerfKind = (typeof PERF_KIND_VALUES)[number];
|
|
292
|
-
//#endregion
|
|
293
|
-
//#region packages/contracts/src/json.d.ts
|
|
294
|
-
type JsonPrimitive = string | number | boolean | null;
|
|
295
|
-
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
296
|
-
type JsonObject = {
|
|
297
|
-
[key: string]: JsonValue;
|
|
298
|
-
};
|
|
299
|
-
//#endregion
|
|
300
|
-
//#region packages/contracts/src/logs.d.ts
|
|
301
|
-
declare const LOG_ACTION_VALUES: readonly ['path', 'start', 'stop', 'doctor', 'mark', 'clear'];
|
|
302
|
-
type LogAction = (typeof LOG_ACTION_VALUES)[number];
|
|
303
|
-
//#endregion
|
|
304
304
|
//#region packages/contracts/src/recording-export-quality.d.ts
|
|
305
305
|
declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
|
|
306
306
|
type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{L as n,R as r,T as i,at as a,z as o}from"./version.js";import{$ as s}from"./sdk-batch-runner.js";import{n as c}from"./device.js";import{A as l,F as u,c as d,f,l as p,o as m,s as ee}from"./sdk-android-adb.js";import{n as te}from"./shell-quote.js";import{t as h}from"./timeouts.js";import{a as g}from"./install-artifact.js";import{r as _}from"./device-input-state.js";import{C as ne,D as v,E as re,O as ie,S as ae,T as oe,_ as se,b as ce,c as le,d as y,g as ue,l as b,r as x,u as S,w as de,y as C}from"./ime-lifecycle.js";function fe(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=he(t),r={failureReason:t.reason??`text_mismatch`,targetInput:T(t.targetInput),actualInput:T(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function w(e){return e?e.password?!0:pe(e.text):!1}function pe(e){return e?Array.from(e).every(me):!1}function T(e){if(!e)return null;let t=w(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function me(e){return e===`•`||e===`*`||e===`●`}function he(e){return e.masked===!0||w(e.targetInput)||w(e.actualInput)}async function E(e,t,n,r){let i=[0,150,350],a=null,o=null,s=await j(e);for(let c of i){c>0&&await h(c);let i=await Ce(e,t,n,r,s);if(a=i,i.reason===`ime_capture`)return i;o=i.ok?i:null}return o??a??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function ge(e,t,n){return be(await y(e),t,n)}async function _e(e,t,n){let r=await j(e);return k(await y(e),t,n,r).targetInput}async function ve(e,t,n){try{return await _e(e,t,n)}catch(e){return l({level:`warn`,phase:`android_fill_pre_action_target_capture_failed`,data:{error:e instanceof Error?e.message:String(e)}}),null}}function D(e,n,r){if(r?.ok)return;let i=r?O(e,n,r):null;if(i)return i;throw new t(`COMMAND_FAILED`,xe(r),Se(e,r))}function O(e,t,n){let r=n.targetInput,i=n.actualInput;if(n.reason===`ime_capture`||!t||!r||!i||w(t)||w(r)||w(i)||!N(t,r)||!N(t,i)||t.text===n.actual)return null;let a=Fe(t);return l({level:`warn`,phase:`android_fill_verification_unconfirmed`,data:{target:a}}),{verification:`unconfirmed`,requested:e,before:t.text,after:n.actual,target:a}}function ye(e,t,n,r,i={}){let a=k(e,t,n,i);return we(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:Te(a,r)??Ee(a,r)}function be(e,t,n){return k(e,t,n).targetInput?.text??null}function xe(e){return e?.reason===`ime_capture`?`Android fill input was captured by the active keyboard instead of the app field`:e?.reason===`masked_unverified`?`Android fill verification could not confirm masked text value`:`Android fill verification failed`}function Se(e,t){let n=fe(e,t);return t?.reason===`ime_capture`&&(n.hint=`The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill.`),n}async function Ce(e,t,n,r,i){return ye(await y(e),t,n,r,i)}function k(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of ie(e)){let e=ke(a,r);e&&Ae(i,e,t,n)}return Me(i)}function we(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function Te(e,t){let n=e.actualInput;if(!n||!Pe(n))return null;let r=n.text??null,i=Array.from(r??``).length,a=Array.from(t).length,o=r!==null&&i>0&&a>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function Ee(e,t){let n=e.actualInput?.text??null;return{ok:De(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function De(e,t){if(e===t)return!0;let n=A(e),r=A(t);return!n||!r?!1:!!(n===r||Oe(n,r))}function A(e){return(e??``).replace(/\s+/g,` `).trim()}function Oe(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function ke(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:s({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Ne(e.className??``)}}async function j(e){try{return{activeInputMethodPackage:(await _(e)).inputMethodPackage}}catch(e){return l({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function Ae(e,t,n,r){let i=je(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=M(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=M(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=M(e.anyAtPoint,t))}function je(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function M(e,t){return e&&e.area<t.area?e:t}function Me(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Ne(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function Pe(e){return w(e)}function N(e,t){return e.resourceId||t.resourceId?e.resourceId===t.resourceId&&e.packageName===t.packageName:e.className===t.className&&e.packageName===t.packageName&&e.rect.x===t.rect.x&&e.rect.y===t.rect.y&&e.rect.width===t.rect.width&&e.rect.height===t.rect.height}function Fe(e){return{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:e.rect}}function P(e){if(!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return e}const F=45e3,I=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,Ie=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function Le(e,t){let n=await R(e),r=Be(t),i=Math.max(45e3,r.durationMs+15e3),a=Buffer.from(JSON.stringify({protocol:`android-touch-plan-v1`,...r})).toString(`base64`),o=await u(`android_touch_helper_gesture`,async()=>{let e=await C({deviceKey:n.deviceKey,action:`gesture`,helper:L(n.artifact),payloadBase64:a,timeoutMs:i});return e?{...B(e),helperTransport:`persistent-session`}:{...await z({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`gesture`,`-e`,`payloadBase64`,a],timeoutMs:i,readResult:B}),helperTransport:`instrumentation`}},{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version});return{backend:`android-helper`,helperVersion:n.artifact.manifest.version,installReason:n.install.reason,...o}}async function Re(e){let t=await R(e);try{let e=await C({deviceKey:t.deviceKey,action:`viewport`,helper:L(t.artifact),timeoutMs:F});if(e)return V(e)}catch(e){await ce(t.deviceKey),l({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await z({adb:t.adb,runner:t.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`viewport`],timeoutMs:F,readResult:V})}function L(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function R(e){let t=ee(e),n=t.snapshotHelperArtifact??await ze(),r=ae(e);await ne({deviceKey:r,adb:t.exec});let i=await u(`android_touch_helper_install`,async()=>await ue({adb:t.exec,adbProvider:t,artifact:n,deviceKey:r,timeoutMs:3e4}),{packageName:n.manifest.packageName,versionCode:n.manifest.versionCode});return l({phase:`android_touch_helper_install_decision`,data:i}),i.installed&&await ce(r),{adb:t.exec,artifact:n,install:i,deviceKey:r}}async function ze(){return await se({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=de(e);return{...t,assetName:t.assetName??`agent-device-android-snapshot-helper-${t.version}.apk`}},unavailableMessage:`Android touch gestures require the bundled Android automation helper artifact, but it was not found or could not be read`})}function Be(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(Ve)}}function Ve(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function z(e){let n=await e.adb([`shell`,`am`,`instrument`,`-w`,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=He(`${n.stdout}\n${n.stderr}`)}catch(e){if(e instanceof t){if(e.code===Ie)throw new t(`COMMAND_FAILED`,e.message,e.details,e);if(e.code!==I)throw e}throw new t(`COMMAND_FAILED`,n.exitCode===0?`Android automation helper output could not be parsed`:`Android automation helper failed before returning parseable output`,f(n),e)}if(n.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android automation helper failed`,f(n,{helper:r}));return e.readResult(r)}function He(e){let n=re(e).results.find(e=>e.agentDeviceProtocol===oe);if(!n)throw new t(I,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(Ie,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function B(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:v(e.injectedEvents),elapsedMs:v(e.elapsedMs)}}function V(e){let n=v(e.x),r=v(e.y),i=v(e.width),a=v(e.height);if(n===void 0||r===void 0||i===void 0||a===void 0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return P({x:n,y:r,width:i,height:a})}function Ue(e){if(e.topology===`two`||e.intent===`longPress`)return e;let[{pointerId:t,samples:n}]=e.pointers,i=[...new Set([...o(e.durationMs,`android`),...n.map(({offsetMs:e})=>e)])].sort((e,t)=>e-t),a=0,s=i.map(e=>{for(;a<n.length-2&&e>n[a+1].offsetMs;)a+=1;let t=n[a],i=n[a+1],o=i.offsetMs-t.offsetMs;return{offsetMs:e,point:e===i.offsetMs||o===0?i.point:r(t.point,i.point,(e-t.offsetMs)/o)}}),c=[s[0],s[1],s[2],...s.slice(3)];return{...e,pointers:[{pointerId:t,samples:c}]}}async function H(e,t){let n=Ue(t),r=p(e);if(r){let e=n.intent===`longPress`?{...n,viewport:P(await r.gestureViewport())}:n;return{backend:`provider-native-touch`,...await r.touch(e)??{}}}return await Le(e,n)}async function U(e){let t=p(e);return t?P(await t.gestureViewport()):await Re(e)}var We=e({appSwitcherAndroid:()=>Ke,backAndroid:()=>K,fillAndroid:()=>Ye,focusAndroid:()=>Y,getAndroidScreenSize:()=>X,homeAndroid:()=>q,longPressAndroid:()=>qe,pressAndroid:()=>W,pressAndroidEnter:()=>Ge,pressAndroidTvRemote:()=>G,readAndroidTextAtPoint:()=>ge,scrollAndroid:()=>Qe,setAndroidOrientation:()=>J,typeAndroid:()=>Je});async function W(e,t,n){await g(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function G(e,t,n){let r=i(t);await g(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function K(e){await g(e,[`shell`,`input`,`keyevent`,`4`])}async function q(e){await g(e,[`shell`,`input`,`keyevent`,`3`])}async function Ge(e){await g(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function J(e,t){let n=$e(t);await g(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await g(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function Ke(e){await g(e,[`shell`,`input`,`keyevent`,`187`])}async function qe(e,t,n,r=800){let i={x:t,y:n};return await H(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function Je(e,t,n=0){let r=d(e);if(r){await r({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(x(e)){await Xe(e,t,n);return}if(rt(t),await et(e,`type`),n>0&&Array.from(t).length>1){await Z(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await Z(e,{action:`type`,text:t,chunkSize:tt,delayMs:0})}async function Y(e,t,n){await W(e,t,n)}async function Ye(e,t,n,r,i=0){let a=await ve(e,t,n),o=d(e);if(o)return await o({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),$(`fill`,`provider-native`,r),D(r,a,await E(e,t,n,r));if(x(e))return D(r,a,await Ze(e,t,n,r,a));rt(r);let s=Array.from(r).length,c=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:i>0?1:tt,inputDelayMs:i},{clearPadding:24,minClear:16,maxClear:96,chunkSize:i>0?1:4,inputDelayMs:i>0?i:15}],l=null;for(let i of c){await Y(e,t,n),await et(e,`fill`),await ct(e,lt(s+i.clearPadding,i.minClear,i.maxClear)),await Z(e,{action:`fill`,text:r,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let o=await E(e,t,n,r);if(l=o,o.ok)return;if(o.reason===`ime_capture`)return D(r,a,o);let c=O(r,a,o);if(c)return c}return D(r,a,l)}async function Xe(e,t,n){let r=m(e),i=(await b()).manifest.packageName,a=t.split(`
|
|
2
|
-
`);for(let[t,o]of a.entries()){let s=n>0?
|
|
3
|
-
`);for(let[r,i]of n.entries()){let a=
|
|
4
|
-
`&&(e<32||e>126))return!1}return!0}function
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{L as n,R as r,T as i,at as a,z as o}from"./version.js";import{rt as s}from"./sdk-batch-runner.js";import{n as c}from"./device.js";import{I as l,c as u,f as d,j as f,l as p,o as m,s as ee}from"./sdk-android-adb.js";import{n as te}from"./shell-quote.js";import{t as h}from"./timeouts.js";import{i as g}from"./install-artifact.js";import{r as _}from"./device-input-state.js";import{C as ne,D as v,E as re,O as ie,S as ae,T as oe,_ as se,b as ce,c as le,d as y,g as ue,l as b,r as de,u as x,w as fe,y as S}from"./ime-lifecycle.js";function pe(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=ge(t),r={failureReason:t.reason??`text_mismatch`,targetInput:w(t.targetInput),actualInput:w(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function C(e){return e?e.password?!0:me(e.text):!1}function me(e){return e?Array.from(e).every(he):!1}function w(e){if(!e)return null;let t=C(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function he(e){return e===`•`||e===`*`||e===`●`}function ge(e){return e.masked===!0||C(e.targetInput)||C(e.actualInput)}async function T(e,t,n,r){let i=[0,150,350],a=null,o=null,s=await A(e);for(let c of i){c>0&&await h(c);let i=await we(e,t,n,r,s);if(a=i,i.reason===`ime_capture`)return i;o=i.ok?i:null}return o??a??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function _e(e,t,n){return xe(await y(e),t,n)}async function ve(e,t,n){let r=await A(e);return O(await y(e),t,n,r).targetInput}async function ye(e,t,n){try{return await ve(e,t,n)}catch(e){return f({level:`warn`,phase:`android_fill_pre_action_target_capture_failed`,data:{error:e instanceof Error?e.message:String(e)}}),null}}function E(e,n,r){if(r?.ok)return;let i=r?D(e,n,r):null;if(i)return i;throw new t(`COMMAND_FAILED`,Se(r),Ce(e,r))}function D(e,t,n){let r=n.targetInput,i=n.actualInput;if(n.reason===`ime_capture`||!t||!r||!i||C(t)||C(r)||C(i)||!M(t,r)||!M(t,i)||t.text===n.actual)return null;let a=Ie(t);return f({level:`warn`,phase:`android_fill_verification_unconfirmed`,data:{target:a}}),{verification:`unconfirmed`,requested:e,before:t.text,after:n.actual,target:a}}function be(e,t,n,r,i={}){let a=O(e,t,n,i);return Te(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:Ee(a,r)??De(a,r)}function xe(e,t,n){return O(e,t,n).targetInput?.text??null}function Se(e){return e?.reason===`ime_capture`?`Android fill input was captured by the active keyboard instead of the app field`:e?.reason===`masked_unverified`?`Android fill verification could not confirm masked text value`:`Android fill verification failed`}function Ce(e,t){let n=pe(e,t);return t?.reason===`ime_capture`&&(n.hint=`The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill.`),n}async function we(e,t,n,r,i){return be(await y(e),t,n,r,i)}function O(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of ie(e)){let e=Ae(a,r);e&&je(i,e,t,n)}return Ne(i)}function Te(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function Ee(e,t){let n=e.actualInput;if(!n||!Fe(n))return null;let r=n.text??null,i=Array.from(r??``).length,a=Array.from(t).length,o=r!==null&&i>0&&a>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function De(e,t){let n=e.actualInput?.text??null;return{ok:Oe(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function Oe(e,t){if(e===t)return!0;let n=k(e),r=k(t);return!n||!r?!1:!!(n===r||ke(n,r))}function k(e){return(e??``).replace(/\s+/g,` `).trim()}function ke(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function Ae(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:s({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:Pe(e.className??``)}}async function A(e){try{return{activeInputMethodPackage:(await _(e)).inputMethodPackage}}catch(e){return f({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function je(e,t,n,r){let i=Me(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=j(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=j(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=j(e.anyAtPoint,t))}function Me(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function j(e,t){return e&&e.area<t.area?e:t}function Ne(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function Pe(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function Fe(e){return C(e)}function M(e,t){return e.resourceId||t.resourceId?e.resourceId===t.resourceId&&e.packageName===t.packageName:e.className===t.className&&e.packageName===t.packageName&&e.rect.x===t.rect.x&&e.rect.y===t.rect.y&&e.rect.width===t.rect.width&&e.rect.height===t.rect.height}function Ie(e){return{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:e.rect}}function N(e){if(!Number.isFinite(e.x)||!Number.isFinite(e.y)||!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return e}const P=45e3,F=`ANDROID_TOUCH_HELPER_NO_FINAL_RESULT`,I=`ANDROID_TOUCH_HELPER_REPORTED_FAILURE`;async function Le(e,t){let n=await R(e),r=Be(t),i=Math.max(45e3,r.durationMs+15e3),a=Buffer.from(JSON.stringify({protocol:`android-touch-plan-v1`,...r})).toString(`base64`),o=await l(`android_touch_helper_gesture`,async()=>{let e=await S({deviceKey:n.deviceKey,action:`gesture`,helper:L(n.artifact),payloadBase64:a,timeoutMs:i});return e?{...B(e),helperTransport:`persistent-session`}:{...await z({adb:n.adb,runner:n.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`gesture`,`-e`,`payloadBase64`,a],timeoutMs:i,readResult:B}),helperTransport:`instrumentation`}},{packageName:n.artifact.manifest.packageName,version:n.artifact.manifest.version});return{backend:`android-helper`,helperVersion:n.artifact.manifest.version,installReason:n.install.reason,...o}}async function Re(e){let t=await R(e);try{let e=await S({deviceKey:t.deviceKey,action:`viewport`,helper:L(t.artifact),timeoutMs:P});if(e)return V(e)}catch(e){await ce(t.deviceKey),f({level:`warn`,phase:`android_touch_helper_viewport_session_fallback`,data:{reason:e instanceof Error?e.message:String(e)}})}return await z({adb:t.adb,runner:t.artifact.manifest.instrumentationRunner,extraArgs:[`-e`,`mode`,`viewport`],timeoutMs:P,readResult:V})}function L(e){return{packageName:e.manifest.packageName,runner:e.manifest.instrumentationRunner,helperVersion:e.manifest.version,helperVersionCode:e.manifest.versionCode,sha256:e.manifest.sha256}}async function R(e){let t=ee(e),n=t.snapshotHelperArtifact??await ze(),r=ae(e);await ne({deviceKey:r,adb:t.exec});let i=await l(`android_touch_helper_install`,async()=>await ue({adb:t.exec,adbProvider:t,artifact:n,deviceKey:r,timeoutMs:3e4}),{packageName:n.manifest.packageName,versionCode:n.manifest.versionCode});return f({phase:`android_touch_helper_install_decision`,data:i}),i.installed&&await ce(r),{adb:t.exec,artifact:n,install:i,deviceKey:r}}async function ze(){return await se({helperDirName:`snapshot-helper`,manifestFileName:e=>`agent-device-android-snapshot-helper-${e}.manifest.json`,parseManifest:e=>{let t=fe(e);return{...t,assetName:t.assetName??`agent-device-android-snapshot-helper-${t.version}.apk`}},unavailableMessage:`Android touch gestures require the bundled Android automation helper artifact, but it was not found or could not be read`})}function Be(e){return{kind:e.topology===`single`?`swipe`:`transform`,durationMs:e.durationMs,pointers:e.pointers.map(Ve)}}function Ve(e){return{pointerId:e.pointerId,samples:e.samples.map(({offsetMs:e,point:t})=>({offsetMs:e,x:t.x,y:t.y}))}}async function z(e){let n=await e.adb([`shell`,`am`,`instrument`,`-w`,...e.extraArgs,e.runner],{allowFailure:!0,timeoutMs:e.timeoutMs}),r;try{r=He(`${n.stdout}\n${n.stderr}`)}catch(e){if(e instanceof t){if(e.code===I)throw new t(`COMMAND_FAILED`,e.message,e.details,e);if(e.code!==F)throw e}throw new t(`COMMAND_FAILED`,n.exitCode===0?`Android automation helper output could not be parsed`:`Android automation helper failed before returning parseable output`,d(n),e)}if(n.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android automation helper failed`,d(n,{helper:r}));return e.readResult(r)}function He(e){let n=re(e).results.find(e=>e.agentDeviceProtocol===oe);if(!n)throw new t(F,`Android automation helper did not return a final result`);if(n.ok!==`true`)throw new t(I,n.message&&n.message!==`null`?n.message:n.errorType||`Android automation helper returned an error`,{errorType:n.errorType,helper:n});return n}function B(e){return{helperKind:e.kind,helperApiVersion:e.helperApiVersion,injectedEvents:v(e.injectedEvents),elapsedMs:v(e.elapsedMs)}}function V(e){let n=v(e.x),r=v(e.y),i=v(e.width),a=v(e.height);if(n===void 0||r===void 0||i===void 0||a===void 0)throw new t(`COMMAND_FAILED`,`Android helper returned an invalid gesture viewport`);return N({x:n,y:r,width:i,height:a})}function Ue(e){if(e.topology===`two`||e.intent===`longPress`)return e;let[{pointerId:t,samples:n}]=e.pointers,i=[...new Set([...o(e.durationMs,`android`),...n.map(({offsetMs:e})=>e)])].sort((e,t)=>e-t),a=0,s=i.map(e=>{for(;a<n.length-2&&e>n[a+1].offsetMs;)a+=1;let t=n[a],i=n[a+1],o=i.offsetMs-t.offsetMs;return{offsetMs:e,point:e===i.offsetMs||o===0?i.point:r(t.point,i.point,(e-t.offsetMs)/o)}}),c=[s[0],s[1],s[2],...s.slice(3)];return{...e,pointers:[{pointerId:t,samples:c}]}}async function H(e,t){let n=Ue(t),r=p(e);if(r){let e=n.intent===`longPress`?{...n,viewport:N(await r.gestureViewport())}:n;return{backend:`provider-native-touch`,...await r.touch(e)??{}}}return await Le(e,n)}async function U(e){let t=p(e);return t?N(await t.gestureViewport()):await Re(e)}var We=e({appSwitcherAndroid:()=>Y,backAndroid:()=>K,fillAndroid:()=>Je,focusAndroid:()=>X,getAndroidScreenSize:()=>Z,homeAndroid:()=>q,longPressAndroid:()=>Ke,pressAndroid:()=>W,pressAndroidEnter:()=>Ge,pressAndroidTvRemote:()=>G,readAndroidTextAtPoint:()=>_e,scrollAndroid:()=>Ze,setAndroidOrientation:()=>J,typeAndroid:()=>qe});async function W(e,t,n){await g(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function G(e,t,n){let r=i(t);await g(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function K(e){await g(e,[`shell`,`input`,`keyevent`,`4`])}async function q(e){await g(e,[`shell`,`input`,`keyevent`,`3`])}async function Ge(e){await g(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function J(e,t){let n=Qe(t);await g(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await g(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function Y(e){await g(e,[`shell`,`input`,`keyevent`,`187`])}async function Ke(e,t,n,r=800){let i={x:t,y:n};return await H(e,{topology:`single`,intent:`longPress`,durationMs:r,pointers:[{pointerId:0,samples:[{offsetMs:0,point:i},{offsetMs:r,point:i}]}]})}async function qe(e,t,n=0){let r=u(e);if(r){await r({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(de(e)){await Ye(e,t,n);return}if(nt(t),await $e(e,`type`),n>0&&Array.from(t).length>1){await Q(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await Q(e,{action:`type`,text:t,chunkSize:et,delayMs:0})}async function X(e,t,n){await W(e,t,n)}async function Je(e,t,n,r,i=0){let a=await ye(e,t,n),o=u(e);if(o)return await o({action:`fill`,target:{x:t,y:n},text:r,delayMs:i}),$(`fill`,`provider-native`,r),E(r,a,await T(e,t,n,r));if(de(e))return E(r,a,await Xe(e,t,n,r,a));nt(r);let s=Array.from(r).length,c=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:i>0?1:et,inputDelayMs:i},{clearPadding:24,minClear:16,maxClear:96,chunkSize:i>0?1:4,inputDelayMs:i>0?i:15}],l=null;for(let i of c){await X(e,t,n),await $e(e,`fill`),await ct(e,lt(s+i.clearPadding,i.minClear,i.maxClear)),await Q(e,{action:`fill`,text:r,chunkSize:i.chunkSize,delayMs:i.inputDelayMs});let o=await T(e,t,n,r);if(l=o,o.ok)return;if(o.reason===`ime_capture`)return E(r,a,o);let c=D(r,a,o);if(c)return c}return E(r,a,l)}async function Ye(e,t,n){let r=m(e),i=(await b()).manifest.packageName,a=t.split(`
|
|
2
|
+
`);for(let[t,o]of a.entries()){let s=n>0?st(o,1):[o];for(let[e,o]of s.entries())o&&await x(r,i,o),n>0&&(e+1<s.length||t+1<a.length)&&await h(n);t+1<a.length&&await g(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(`type`,`test-ime`,t)}async function Xe(e,t,n,r,i){let a=m(e),o=(await b()).manifest.packageName,s=null;for(let c=0;c<2;c+=1){await X(e,t,n),await le(a,o),r&&await x(a,o,r);let c=await T(e,t,n,r);if(s=c,c.ok||D(r,i,c))break}return $(`fill`,`test-ime`,r),s}async function Ze(e,t,r){let i=await U(e),o=a({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:i.width,referenceHeight:i.height}),s={...o,referenceWidth:i.x+i.width,referenceHeight:i.y+i.height,x1:i.x+o.x1,y1:i.y+o.y1,x2:i.x+o.x2,y2:i.y+o.y2},c=Math.max(r?.durationMs??300,16),l=await H(e,n({intent:`pan`,origin:{x:s.x1,y:s.y1},delta:{x:s.x2-s.x1,y:s.y2-s.y1},durationMs:c},i,`android`));return{...s,...r?.durationMs===void 0?{}:{durationMs:c},...l}}function Qe(e){let n=c[e];if(n===void 0)throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`);return String(n)}async function $e(e,n){let r;try{r=await _(e)}catch(e){f({level:`warn`,phase:`android_input_ownership_probe_failed`,data:{action:n,error:e instanceof Error?e.message:String(e)}});return}if(r.inputOwner===`ime`)throw new t(`COMMAND_FAILED`,`KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.`,{failureReason:`ime_capture`,action:n,inputOwner:r.inputOwner,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,nextAction:`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`})}async function Z(e){let n=(await g(e,[`shell`,`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}const et=8;async function Q(e,t){let n=t.text.split(`
|
|
3
|
+
`);for(let[r,i]of n.entries()){let a=st(i,t.chunkSize);for(let[i,o]of a.entries())await tt(e,o),t.delayMs>0&&(i+1<a.length||r+1<n.length)&&await h(t.delayMs);r+1<n.length&&await g(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(t.action,`adb-shell`,t.text)}async function tt(e,t){if(t)try{await g(e,[`shell`,`input`,`text`,te(it(t))])}catch(e){throw at(e)?ot(t,e):e}}function nt(e){if(!rt(e))throw ot(e)}function rt(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&t!==`
|
|
4
|
+
`&&(e<32||e>126))return!1}return!0}function it(e){return e.replace(/ /g,`%s`)}function at(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details?.stderr,r=(typeof n==`string`?n:``).toLowerCase();return!!(r.includes(`exception occurred while executing 'text'`)||r.includes(`nullpointerexception`)&&r.includes(`inputshellcommand.sendtext`))}function ot(e,n){return new t(`COMMAND_FAILED`,"Android text input requires provider-native text injection or the bundled test IME helper for non-ASCII/control characters; the adb-shell fallback supports ASCII text only. On emulators the test IME activates automatically; on real devices pass `open --test-ime` to enable it (see `agent-device doctor` for the current IME state).",{backend:`adb-shell`,textLength:Array.from(e).length,textPreview:e.slice(0,32)},n instanceof Error?n:void 0)}function st(e,t){let n=Math.max(1,Math.floor(t)),r=[],i=Array.from(e);for(let e=0;e<i.length;e+=n)r.push(i.slice(e,e+n).join(``));return r.length>0?r:[``]}function $(e,t,n){f({phase:`android_text_injection`,data:{action:e,backend:t,textLength:Array.from(n).length}})}async function ct(e,t){let n=Math.max(0,t);await g(e,[`shell`,`input`,`keyevent`,`KEYCODE_MOVE_END`],{allowFailure:!0});for(let t=0;t<n;t+=24){let r=Math.min(24,n-t);await g(e,[`shell`,`input`,`keyevent`,...Array(r).fill(`KEYCODE_DEL`)],{allowFailure:!0})}}function lt(e,t,n){return Math.max(t,Math.min(n,e))}export{Z as a,Ke as c,Ze as d,J as f,U as h,X as i,W as l,H as m,K as n,q as o,qe as p,Je as r,We as s,Y as t,G as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{at as t}from"./version.js";import{t as n}from"./timeouts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{at as t}from"./version.js";import{t as n}from"./timeouts.js";import{n as r}from"./hdc.js";import i from"node:path";import{randomUUID as a}from"node:crypto";import{promises as o}from"node:fs";import s from"node:os";async function c(e,t={}){let n=`/data/local/tmp/agent-device-layout-${a()}.json`,c=await o.mkdtemp(i.join(s.tmpdir(),`agent-device-harmony-layout-`)),l=i.join(c,`layout.json`);try{return await r(e,[`shell`,`uitest`,`dumpLayout`,`-p`,n],{timeoutMs:3e4}),await r(e,[`file`,`recv`,n,l],{timeoutMs:15e3}),d(u(await o.readFile(l,`utf8`)),t)}finally{await r(e,[`shell`,`rm`,`-f`,n],{allowFailure:!0}).catch(()=>{}),await o.rm(c,{recursive:!0,force:!0})}}async function l(t){let n=(await c(t)).nodes.find(e=>e.type===`Application`&&e.rect)?.rect;if(!n||n.width<=0||n.height<=0)throw new e(`COMMAND_FAILED`,`HarmonyOS snapshot did not expose an application viewport`);return n}function u(t){try{let e=JSON.parse(t);if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`layout root is not an object`);return e}catch(t){throw new e(`COMMAND_FAILED`,`HarmonyOS uitest returned an invalid layout JSON document`,{cause:t instanceof Error?t.message:String(t)})}}function d(e,t){let n=[],r=0,i=0,a=!1,o=(e,s,c)=>{if(r+=1,i=Math.max(i,s),n.length>=5e3){a=!0;return}let l=f(e.attributes??{},n.length,s,c),u=!t.interactiveOnly||l.hittable===!0?n.push(l)-1:c;if(s<(t.depth??1/0))for(let t of e.children??[])o(t,s+1,u)};return o(e,0),{nodes:n,...a?{truncated:!0}:{},analysis:{rawNodeCount:r,maxDepth:i}}}function f(e,t,n,r){let i=p(e,`text`)??p(e,`originalText`),a=p(e,`description`),o=p(e,`id`)??p(e,`key`),s=m(p(e,`bounds`));return{index:t,type:p(e,`type`)===`root`?`Application`:p(e,`type`),...a?{label:a}:{},...i?{value:i}:{},...o?{identifier:o}:{},...s?{rect:s}:{},enabled:p(e,`enabled`)!==`false`,focused:p(e,`focused`)===`true`,visibleToUser:p(e,`visible`)!==`false`,hittable:p(e,`clickable`)===`true`,depth:n,...r===void 0?{}:{parentIndex:r}}}function p(e,t){let n=e[t];return typeof n==`string`?n:void 0}function m(e){if(!e)return;let t=/^\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]$/.exec(e);if(!t)return;let[,n,r,i,a]=t,o=Number(n),s=Number(r),c=Number(i)-o,l=Number(a)-s;return c>=0&&l>=0?{x:o,y:s,width:c,height:l}:void 0}async function h(e,t,n){await r(e,[`shell`,`uitest`,`uiInput`,`click`,String(t),String(n)])}async function g(e,t,n){await r(e,[`shell`,`uitest`,`uiInput`,`doubleClick`,String(t),String(n)])}async function _(e,t,n,i=800){await r(e,[`shell`,`uitest`,`uiInput`,`longClick`,String(t),String(n)])}async function v(e,t,i=0){await r(e,[`shell`,`uitest`,`uiInput`,`text`,t]),i>0&&await n(i)}async function y(e,t,i,a,o=0){await r(e,[`shell`,`uitest`,`uiInput`,`inputText`,String(t),String(i),a]),o>0&&await n(o)}async function b(e,n,i){let a=await l(e),o=t({direction:n,amount:i?.amount,pixels:i?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await r(e,[`shell`,`uitest`,`uiInput`,`swipe`,String(o.x1),String(o.y1),String(o.x2),String(o.y2),String(i?.durationMs??300)]),o}async function x(t,n){if(n.topology!==`single`)throw new e(`UNSUPPORTED_OPERATION`,`HarmonyOS HDC does not support multi-touch gestures`);let i=n.pointers[0].samples,a=i[0],o=i.at(-1);if(!a||!o)throw new e(`COMMAND_FAILED`,`HarmonyOS gesture plan has no pointer endpoints`);let s=Math.hypot(o.point.x-a.point.x,o.point.y-a.point.y),c=Math.max(200,Math.min(4e4,Math.round(s/n.durationMs*1e3))),l=n.intent===`fling`?`fling`:`swipe`;return await r(t,[`shell`,`uitest`,`uiInput`,l,String(Math.round(a.point.x)),String(Math.round(a.point.y)),String(Math.round(o.point.x)),String(Math.round(o.point.y)),String(c)]),{backend:`harmonyos-hdc-uiinput`,command:l,velocity:c,viewport:n.viewport}}async function S(e){await r(e,[`shell`,`uitest`,`uiInput`,`keyEvent`,`Back`])}async function C(e){await r(e,[`shell`,`uitest`,`uiInput`,`keyEvent`,`Home`])}async function w(e){await r(e,[`shell`,`uitest`,`uiInput`,`keyEvent`,`Recent`])}async function T(e,t){await r(e,[`shell`,`uitest`,`uiInput`,`keyEvent`,t])}async function E(t,n){throw new e(`UNSUPPORTED_OPERATION`,`HarmonyOS orientation control is not available through the public HDC API.`)}export{w as appSwitcherHarmony,S as backHarmony,g as doubleClickHarmony,y as fillHarmony,C as homeHarmony,_ as longPressHarmony,c as n,x as performHarmonyGesture,h as pressHarmony,T as pressHarmonyKeyboardKey,b as scrollHarmony,E as setHarmonyOrientation,l as t,v as typeHarmony};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t,v as n}from"./sdk-contracts.js";import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t,v as n}from"./sdk-contracts.js";import{b as r,o as i,v as a,w as o}from"./sdk-android-adb.js";import{t as s}from"./timeouts.js";import{n as c,t as l}from"./manifest.js";import{n as u,r as d}from"./install-source2.js";import{i as f,n as p,o as m,t as h}from"./boot-diagnostics.js";import g from"node:path";function _(e={}){let t=e.ttlMs??3e4,n=e.nowMs??Date.now,r=new Map,i=e=>{let t=y(e);for(let e of r.keys())e.startsWith(t)&&r.delete(e)};return{get(e,t){let i=v(e,t),a=r.get(i);if(a){if(a.expiresAtMs<=n()){r.delete(i);return}return a.value}},set(e,i,a){return r.set(v(e,i),{value:a,expiresAtMs:n()+t}),a},clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function v(e,t){return[e.platform,e.deviceId,e.variant??``,t.trim().toLowerCase()].join(`\0`)}function y(e){return[e.platform,e.deviceId,``].join(`\0`)}var b=e({ensureAndroidEmulatorBooted:()=>S,waitForAndroidBoot:()=>A});const x=1e4;async function S(e,n){await c();let i=e.avdName.trim();if(!i)throw new t(`INVALID_ARGS`,`Android emulator boot requires a non-empty AVD name.`);let a=e.timeoutMs??12e4;if(!await o(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await o(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`);let s=await C(n,e.serial),l=w(s,i,e.serial);if(!l)throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:s.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let u=l.name,d=Date.now(),f=T(l)?l:void 0;if(!f){let t=[`-avd`,u];e.headless&&t.push(`-no-window`,`-no-audio`),r(`emulator`,t)}let p=f??await O({dependencies:n,avdName:u,serial:e.serial,timeoutMs:a}),m=Date.now()-d;return await A(p.id,Math.max(1e3,a-m)),{...(await C(n,e.serial)).find(e=>e.id===p.id)??p,name:u,booted:!0}}async function C(e,t){return await e.discoverLocal({platform:`android`,kind:`emulator`,...t?{serial:t}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}})}function w(e,t,n){let r=D(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&D(e.name)===r&&(!n||!T(e)||e.id===n))}function T(e){return E(e.id)}function E(e){return e.startsWith(`emulator-`)}function D(e){return e.toLowerCase().replace(/_/g,` `).replace(/\s+/g,` `).trim()}async function O(e){let n=Date.now(),r=Math.min(1e3,Math.max(50,Math.floor(e.timeoutMs/20)));for(;Date.now()-n<e.timeoutMs;){try{let t=w(await C(e.dependencies,e.serial),e.avdName,e.serial);if(t&&T(t))return t}catch{}await s(r)}throw new t(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:`Check emulator logs and verify the AVD can start from command line.`})}async function k(e,t=x){return await a(`adb`,[`-s`,e,`shell`,`getprop`,`sys.boot_completed`],{allowFailure:!0,timeoutMs:t})}async function A(e,n=6e4){let r=f.fromTimeoutMs(n),i=Math.min(1e3,Math.max(50,Math.floor(n/20))),a=Math.max(1,Math.ceil(n/i)),o,s=!1;try{await m(async({deadline:i})=>{if(i?.isExpired())throw s=!0,new t(`COMMAND_FAILED`,`Android boot deadline exceeded`,{serial:e,timeoutMs:n,elapsedMs:r.elapsedMs(),message:`timeout`});let a=Math.max(1e3,i?.remainingMs()??n),c=await k(e,Math.min(a,x));if(o=c,c.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode})},{maxAttempts:a,baseDelayMs:i,maxDelayMs:i,jitter:0,shouldRetry:e=>{let t=p({error:e,stdout:o?.stdout,stderr:o?.stderr,context:{platform:`android`,phase:`boot`}});return t!==`ADB_TRANSPORT_UNAVAILABLE`&&t!==`ANDROID_BOOT_TIMEOUT`}},{deadline:r,phase:`boot`,classifyReason:e=>p({error:e,stdout:o?.stdout,stderr:o?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(t){j({error:t,serial:e,timeoutMs:n,deadline:r,lastBootResult:o,timedOut:s})}}function j(e){let t=n(e.error),r=M(e,t);throw P(t,r,e.timedOut,N(e,r))}function M(e,t){let n=p({error:e.error,stdout:e.lastBootResult?.stdout,stderr:e.lastBootResult?.stderr,context:{platform:`android`,phase:`boot`}});return n===`BOOT_COMMAND_FAILED`&&t.message===`Android device is still booting`?`ANDROID_BOOT_TIMEOUT`:n}function N(e,t){return{serial:e.serial,timeoutMs:e.timeoutMs,elapsedMs:e.deadline.elapsedMs(),reason:t,hint:h(t),stdout:e.lastBootResult?.stdout,stderr:e.lastBootResult?.stderr,exitCode:e.lastBootResult?.exitCode,...n(e.error).details??{}}}function P(e,n,r,i){return r||n===`ANDROID_BOOT_TIMEOUT`?new t(`COMMAND_FAILED`,`Android device did not finish booting in time`,i):e.code===`TOOL_MISSING`?new t(`TOOL_MISSING`,e.message,i):n===`ADB_TRANSPORT_UNAVAILABLE`?new t(`COMMAND_FAILED`,e.message,i):new t(e.code,e.message,i,e.cause)}async function F(e,t,n){return await i(e)(t,n)}function I(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`no shell command implementation`)||n.includes(`unknown command`)}var L=e({prepareAndroidInstallArtifact:()=>R});async function R(e,t){let n=e.kind===`url`&&u(e.url),r=await d({source:e,isInstallablePath:(e,t)=>t.isFile()&&z(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await B(r.installablePath);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function z(e){let t=g.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function B(e){let t=g.extname(e).toLowerCase();return t!==`.apk`&&t!==`.aab`?{}:{packageName:await l(e)}}export{b as a,F as i,R as n,A as o,I as r,_ as s,L as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{c as t}from"./version.js";import{_ as n}from"./sdk-device.js";import{t as r}from"./runtime.js";import{N as i}from"./runner-disposal.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{c as t}from"./version.js";import{_ as n}from"./sdk-device.js";import{t as r}from"./runtime.js";import{N as i}from"./runner-disposal.js";import{a,n as o,r as s,t as c}from"./dispatch.js";import{Zt as l,gn as u,qt as d,tn as f}from"./internal/daemon.js";import{a as p,f as m,u as h,y as g}from"./selector-runtime.js";import{a as _,l as v}from"./snapshot-session.js";async function y(e){let{session:n,node:r,rootViewport:i,requestOptions:a}=e,o=h(r);if(!o)return null;let s;try{s=await p(n,o,a)}catch{return null}if(!s.found||!s.node?.rect)return null;let c={rect:s.node.rect,hittable:s.node.hittable===!0};return t(c,i)?c.rect:null}function b(t){let n=t.sessionStore.get(t.sessionName);if(!n)throw new e(`SESSION_NOT_FOUND`,a);return r({backend:x({...t,session:n}),...v(`interaction commands`,{plural:!0}),sessions:d({sessionName:t.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0,omitRefFrameSnapshot:t.req.internal?.findResolvedTarget!==void 0},setRecord:e=>{e.snapshot&&(l(n,e.snapshot),t.sessionStore.set(t.sessionName,n))}}),signal:i(t.req.meta?.requestId)})}function x(e){let{req:t,session:r}=e,i=S(r);return{platform:n(r.device),captureSnapshot:async(n,i)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0,includeRects:i?.includeRects===!0,signal:n.signal})}),resolveGestureViewport:async()=>e.pairedGestureViewport??await s(r.device,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)),confirmOffscreenTargetVisible:m(r,{skipPendingPostGestureStabilization:!1})?async(n,i,a)=>await y({session:r,node:i,rootViewport:a,requestOptions:_({req:t,logPath:e.logPath,traceLogPath:r.trace?.outPath})}):void 0,tap:async(n,i)=>(f(r),C(await c(r.device,`press`,[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))),tapTarget:i?.clickRef?async(e,t)=>(f(r),await i.clickRef?.(t.ref),{ref:g(t.ref)}):void 0,fill:async(n,i,a,o)=>(f(r),C(await c(r.device,`fill`,[String(i.x),String(i.y),a],t.flags?.out,{...e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath),allowNonHittableCoordinateFallback:o?.allowNonHittableCoordinateFallback}))),fillTarget:i?.fillRef?async(e,t,n,a)=>(f(r),await i.fillRef?.(t.ref,n,a),{ref:g(t.ref),text:n,delayMs:a?.delayMs??0}):void 0,longPress:async(n,i,a)=>(f(r),C(await c(r.device,`longpress`,[String(i.x),String(i.y),...a?.durationMs===void 0?[]:[String(a.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))),performGesture:async(n,i)=>(f(r),C(await o(r.device,i,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))),typeText:async(n,i)=>(f(r),C(await c(r.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))))}}function S(e){if(e.device.platform!==`web`)return;let t=u();return t.clickRef||t.fillRef?t:void 0}function C(e){return e&&typeof e==`object`?e:void 0}export{b as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"./prepare-kind.js";import{
|
|
1
|
+
import{z as e}from"./prepare-kind.js";import{Zt as t,an as n}from"./internal/daemon.js";async function r(r,i,a,o,s){let c={...i??{},snapshotInteractiveOnly:s.interactiveOnly,...s.preferredBackend?{snapshotPreferredBackend:s.preferredBackend}:{}},l=o(c,r.appBundleId,r.trace?.outPath),{snapshot:u}=await n({device:r.device,session:r,flags:c,outPath:c.out,logPath:l.logPath??``,includeRects:s.includeRects,androidFreshnessMode:s.androidFreshnessMode,signal:s.signal});return e(u.snapshotQuality)||(t(r,u),a.set(r.name,r)),u}export{r as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as e,M as t,P as n}from"./screenshot-result.js";import{i
|
|
1
|
+
import{I as e,M as t,P as n,X as r}from"./screenshot-result.js";import{i}from"./session-target-evidence.js";import{j as a}from"./sdk-android-adb.js";import{a as o}from"./input-actions.js";import{Ht as s,Ut as c,dn as l,un as u}from"./internal/daemon.js";function d(e){let{session:t,sessionStore:n,command:a,positionals:o,actionCommand:c=a,retryPositionals:d,flags:m,result:h,responseData:g,recordedTarget:_,recordedTargets:v,scheduleInteractionOutcomeRetry:y=!0,actionStartedAt:b,actionFinishedAt:x,androidFreshnessBaseline:S}=e,C=l(m),[w,T]=p({command:a,positionals:o,flags:C,result:h,responseData:g}),E=r(t)&&_?i(_):void 0,D=r(t)&&v?f(v):void 0;return n.recordAction(t,{command:a,positionals:o,flags:C??{},result:w,...E?{targetEvidence:E}:{},...D?{targetEvidences:D}:{}}),u({session:t,command:a,action:c,positionals:d??o,flags:m,scheduleOutcomeRetry:y,androidFreshnessBaseline:S}),s(t,c,o,w,C??{},b,x),{ok:!0,data:T}}function f(e){let t=i(e.source),n=i(e.destination);return t&&n?{source:t,destination:n}:void 0}function p(r){if(r.command!==`fill`||typeof r.flags?.recordAs!=`string`)return[r.result,r.responseData];let i=e({ts:0,command:`fill`,positionals:r.positionals,flags:r.flags,result:r.result}),a=n(r.flags.recordAs);return[t(r.result,i,a),t(r.responseData,i,a)]}async function m(e){let{session:t,flags:n,sessionStore:r,contextFromFlags:i,captureSnapshotForSession:a}=e,s=t.screenRecording?.handle;if(!s)return;let l=s.inspect().touchReferenceFrame;if(l)return l;if(t.device.platform===`android`){let e=await o(t.device),n={referenceWidth:e.width,referenceHeight:e.height};return s.setTouchReferenceFrame(n),n}let u=c(t.snapshot);if(u)return s.setTouchReferenceFrame(u),u;let d=c(await a(t,n,r,i,{interactiveOnly:!0}));return d&&s.setTouchReferenceFrame(d),d}async function h(e){try{return await m(e)}catch(t){a({level:`warn`,phase:`touch_reference_frame_resolve_failed`,data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function g(e){return c({nodes:e,createdAt:0})}export{h as n,d as r,g as t};
|