agent-device 0.20.5 → 0.20.7

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.
Files changed (196) hide show
  1. package/README.md +5 -3
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.apk → agent-device-android-ime-helper-0.20.7.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.manifest.json → agent-device-android-ime-helper-0.20.7.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.apk → agent-device-android-snapshot-helper-0.20.7.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.manifest.json → agent-device-android-snapshot-helper-0.20.7.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +48 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +108 -1
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +630 -89
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +149 -10
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +161 -32
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +18 -1
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +145 -20
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +234 -0
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +106 -448
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +602 -0
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
  37. package/dist/src/agent-browser-tool.js +1 -1
  38. package/dist/src/agent-device-client.js +2 -2
  39. package/dist/src/android-adb.js +1 -1
  40. package/dist/src/android.js +1 -1
  41. package/dist/src/app-helpers.js +1 -1
  42. package/dist/src/app-lifecycle.js +7 -7
  43. package/dist/src/app-lifecycle2.js +2 -0
  44. package/dist/src/app-log-files.js +1 -0
  45. package/dist/src/app-log-reconnect.js +1 -0
  46. package/dist/src/app-log-runtime.js +4 -0
  47. package/dist/src/app-resolution.js +2 -1
  48. package/dist/src/apps.js +5 -5
  49. package/dist/src/audio-probe.js +1 -1
  50. package/dist/src/auth-session.js +1 -0
  51. package/dist/src/auth.js +2 -0
  52. package/dist/src/boot-diagnostics.js +2 -2
  53. package/dist/src/cli-config.js +1 -1
  54. package/dist/src/cli-grammar.js +1 -0
  55. package/dist/src/cli-help.js +204 -254
  56. package/dist/src/cli-output.js +1 -0
  57. package/dist/src/cli-runner.js +1 -2
  58. package/dist/src/cli.js +6 -16
  59. package/dist/src/client-metro.js +1 -1
  60. package/dist/src/cloud-artifacts.d.ts +2 -137
  61. package/dist/src/command-metadata.js +1 -1
  62. package/dist/src/command-schema.js +3 -3
  63. package/dist/src/connection-runtime.js +1 -0
  64. package/dist/src/connection.js +5 -0
  65. package/dist/src/context.js +1 -1
  66. package/dist/src/daemon-shutdown-report.js +1 -0
  67. package/dist/src/daemon.js +2 -0
  68. package/dist/src/debug-symbols.js +3 -3
  69. package/dist/src/device-claim-inspection.js +1 -0
  70. package/dist/src/device-input-state.js +2 -2
  71. package/dist/src/device.js +1 -1
  72. package/dist/src/device2.js +2 -0
  73. package/dist/src/find.js +1 -1
  74. package/dist/src/finders.js +1 -1
  75. package/dist/src/generic-settle.js +1 -0
  76. package/dist/src/generic.js +1 -1
  77. package/dist/src/harmonyos.js +1 -0
  78. package/dist/src/helper.js +1 -1
  79. package/dist/src/host-process.js +2 -2
  80. package/dist/src/ime-lifecycle.js +7 -7
  81. package/dist/src/index.d.ts +69 -18
  82. package/dist/src/input-actions.js +4 -4
  83. package/dist/src/input-actions2.js +1 -1
  84. package/dist/src/input-actions3.js +1 -0
  85. package/dist/src/install-artifact.js +1 -5
  86. package/dist/src/install-artifact2.js +1 -1
  87. package/dist/src/install-source2.js +1 -1
  88. package/dist/src/interaction-runtime.js +1 -0
  89. package/dist/src/interaction-snapshot.js +1 -1
  90. package/dist/src/interaction-touch-reference-frame.js +1 -0
  91. package/dist/src/interaction.js +1 -1
  92. package/dist/src/interactor.js +2 -2
  93. package/dist/src/interactor2.js +1 -1
  94. package/dist/src/internal/bin.js +2 -2
  95. package/dist/src/internal/daemon.js +9 -16
  96. package/dist/src/inventory.js +5 -0
  97. package/dist/src/inventory2.js +1 -0
  98. package/dist/src/inventory3.js +2 -0
  99. package/dist/src/inventory4.js +1 -0
  100. package/dist/src/inventory5.js +1 -0
  101. package/dist/src/inventory6.js +1 -0
  102. package/dist/src/lease-context.js +1 -1
  103. package/dist/src/lease.js +1 -1
  104. package/dist/src/limrun-runtime-dependencies.js +1 -0
  105. package/dist/src/limrun.d.ts +10 -104
  106. package/dist/src/limrun.js +1 -1
  107. package/dist/src/linux.js +1 -1
  108. package/dist/src/logcat.js +1 -1
  109. package/dist/src/manifest.js +1 -1
  110. package/dist/src/owner-identity.js +1 -0
  111. package/dist/src/physical-device-control.js +1 -1
  112. package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
  113. package/dist/src/platform-runtime-app-log-process.js +1 -0
  114. package/dist/src/platform-runtime-host.js +1 -0
  115. package/dist/src/platform-runtime-network-web-transport.js +1 -0
  116. package/dist/src/platform-runtime-operation-host.js +5 -0
  117. package/dist/src/platform-runtime-toolchain-host.js +1 -0
  118. package/dist/src/platform-runtime.js +1 -0
  119. package/dist/src/prepare-kind.js +15 -0
  120. package/dist/src/process-entry.js +1 -0
  121. package/dist/src/process-exit.js +1 -0
  122. package/dist/src/process-lock.js +1 -1
  123. package/dist/src/provider-webdriver.js +1 -0
  124. package/dist/src/provider.js +1 -0
  125. package/dist/src/proxy.js +2 -0
  126. package/dist/src/react-native.js +1 -1
  127. package/dist/src/record-trace.js +1 -1
  128. package/dist/src/registry.js +25 -24
  129. package/dist/src/remote-config.js +1 -1
  130. package/dist/src/remote-config2.js +1 -1
  131. package/dist/src/replay.js +3 -0
  132. package/dist/src/reporting.js +4 -4
  133. package/dist/src/runner-client.js +1 -1
  134. package/dist/src/runner-disposal.js +1 -1
  135. package/dist/src/runner-lease.js +1 -1
  136. package/dist/src/runtime.js +3 -3
  137. package/dist/src/runtime2.js +4 -0
  138. package/dist/src/runtime3.js +3 -0
  139. package/dist/src/runtime4.js +1 -0
  140. package/dist/src/runtime5.js +1 -0
  141. package/dist/src/runtime6.js +1 -0
  142. package/dist/src/runtime7.js +1 -0
  143. package/dist/src/screenshot-result.js +4 -4
  144. package/dist/src/screenshot.js +1 -0
  145. package/dist/src/sdk-android-adb.d.ts +20 -2
  146. package/dist/src/sdk-android-adb.js +2 -2
  147. package/dist/src/sdk-batch-runner.js +3 -3
  148. package/dist/src/sdk-contracts.d.ts +47 -6
  149. package/dist/src/sdk-contracts.js +1 -1
  150. package/dist/src/sdk-device.js +1 -1
  151. package/dist/src/sdk-finders.d.ts +4 -20
  152. package/dist/src/sdk-finders.js +1 -1
  153. package/dist/src/sdk-remote-config.js +1 -1
  154. package/dist/src/sdk-selectors.d.ts +601 -0
  155. package/dist/src/sdk-selectors.js +1 -1
  156. package/dist/src/selector-runtime.js +1 -1
  157. package/dist/src/selector-vocabulary.js +1 -1
  158. package/dist/src/selectors.d.ts +1 -46
  159. package/dist/src/selectors.js +1 -1
  160. package/dist/src/server.js +3 -3
  161. package/dist/src/session-target-evidence.js +1 -1
  162. package/dist/src/session.js +10 -9
  163. package/dist/src/shared.js +2 -0
  164. package/dist/src/shell-quote.js +1 -0
  165. package/dist/src/simulator.js +1 -1
  166. package/dist/src/snapshot-runtime.js +1 -0
  167. package/dist/src/snapshot-session.js +1 -0
  168. package/dist/src/snapshot.js +1 -1
  169. package/dist/src/snapshot2.js +1 -1
  170. package/dist/src/src.js +1 -1
  171. package/dist/src/src2.js +2 -0
  172. package/dist/src/src3.js +1 -0
  173. package/dist/src/text-surface.js +1 -0
  174. package/dist/src/timing-safe-equal.js +1 -0
  175. package/dist/src/tool-provider.js +3 -3
  176. package/dist/src/tool-provider2.js +1 -1
  177. package/dist/src/tool-provider3.js +1 -1
  178. package/dist/src/update-check.js +1 -1
  179. package/dist/src/version.js +1 -1
  180. package/dist/src/web.js +1 -1
  181. package/package.json +72 -50
  182. package/server.json +3 -3
  183. package/skills/agent-device/SKILL.md +6 -31
  184. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +0 -1
  185. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +0 -1
  186. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
  187. package/dist/src/app-log-request-scope.js +0 -1
  188. package/dist/src/devices.js +0 -1
  189. package/dist/src/devices2.js +0 -1
  190. package/dist/src/devices3.js +0 -1
  191. package/dist/src/devices4.js +0 -1
  192. package/dist/src/interaction.d.ts +0 -230
  193. package/dist/src/provider-limrun-runtime.js +0 -1
  194. package/dist/src/register-builtins.js +0 -1
  195. package/dist/src/screenshot-geometry.js +0 -1
  196. package/dist/src/viewport-dimension.js +0 -14
@@ -1,2 +1,2 @@
1
- import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{g as n,y as r}from"./sdk-android-adb.js";import{i,r as a,t as o}from"./tool-provider.js";import s from"node:path";import{createHash as c}from"node:crypto";import{existsSync as l,promises as u}from"node:fs";import d from"node:os";import{fileURLToPath as f}from"node:url";var p=e({quitMacOsApp:()=>N,resolveFrontmostMacOsApp:()=>M,resolveMacOsHelperPackageRootFrom:()=>x,runMacOsAlertAction:()=>F,runMacOsPermissionAction:()=>P,runMacOsPressAction:()=>R,runMacOsReadTextAction:()=>L,runMacOsScreenshotAction:()=>z,runMacOsSnapshotAction:()=>I,startMacOsAudioProbeProcess:()=>A});const m=`agent-device-macos-helper`,h=`AGENT_DEVICE_MACOS_HELPER_BIN`,g=s.join(d.homedir(),`.agent-device`,`macos-helper`,`current`),_=s.join(g,`manifest.json`),v=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function y(e){let n=e.trim();if(!v.test(n))throw new t(`INVALID_ARGS`,`macOS bundle id must use reverse-DNS form like com.example.App`,{bundleId:e});return n}function b(e,t){t.bundleId&&e.push(`--bundle-id`,y(t.bundleId)),t.surface&&e.push(`--surface`,t.surface)}function x(e){let n=s.dirname(e);for(;;){let e=s.join(n,`apple`,`macos-helper`);if(l(s.join(e,`Package.swift`)))return e;let t=s.dirname(n);if(t===n)break;n=t}throw new t(`COMMAND_FAILED`,`Unable to locate macOS helper package root`,{modulePath:e})}function S(){return x(f(import.meta.url))}function C(){return s.join(S(),`.build`,`release`,m)}function w(){return s.join(g,m)}async function T(e){let t=await u.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=s.join(e,t.name);return t.isDirectory()?t.name===`.build`?[]:await T(n):!t.isFile()||!t.name.endsWith(`.swift`)&&t.name!==`Package.swift`?[]:[n]}))).flat().sort()}async function E(e){let t=await T(e),n=c(`sha256`);for(let r of t)n.update(s.relative(e,r)),n.update(`\0`),n.update(await u.readFile(r)),n.update(`\0`);let r=await i(`swift`,[`--version`],{allowFailure:!0,cwd:e,timeoutMs:1e4});return n.update(`swift-version`),n.update(`\0`),n.update(r.stdout||r.stderr||`exit:${r.exitCode}`),n.update(`\0`),n.digest(`hex`)}async function D(){try{let e=JSON.parse(await u.readFile(_,`utf8`));return typeof e.fingerprint==`string`?e.fingerprint:null}catch{return null}}async function O(){let e=await n(process.env[h],h);if(e)return e;let t=S(),r=await E(t),a=w();try{if(await D()===r)return await u.access(a),a}catch{}let o=C();process.stderr.write(`agent-device: building macOS helper (first run or helper update)
1
+ import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{h as n,v as r}from"./sdk-android-adb.js";import{i,r as a,t as o}from"./tool-provider.js";import s from"node:path";import{createHash as c}from"node:crypto";import{existsSync as l,promises as u}from"node:fs";import d from"node:os";import{fileURLToPath as f}from"node:url";var p=e({quitMacOsApp:()=>N,resolveFrontmostMacOsApp:()=>M,resolveMacOsHelperPackageRootFrom:()=>x,runMacOsAlertAction:()=>F,runMacOsPermissionAction:()=>P,runMacOsPressAction:()=>R,runMacOsReadTextAction:()=>L,runMacOsScreenshotAction:()=>z,runMacOsSnapshotAction:()=>I,startMacOsAudioProbeProcess:()=>A});const m=`agent-device-macos-helper`,h=`AGENT_DEVICE_MACOS_HELPER_BIN`,g=s.join(d.homedir(),`.agent-device`,`macos-helper`,`current`),_=s.join(g,`manifest.json`),v=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function y(e){let n=e.trim();if(!v.test(n))throw new t(`INVALID_ARGS`,`macOS bundle id must use reverse-DNS form like com.example.App`,{bundleId:e});return n}function b(e,t){t.bundleId&&e.push(`--bundle-id`,y(t.bundleId)),t.surface&&e.push(`--surface`,t.surface)}function x(e){let n=s.dirname(e);for(;;){let e=s.join(n,`apple`,`macos-helper`);if(l(s.join(e,`Package.swift`)))return e;let t=s.dirname(n);if(t===n)break;n=t}throw new t(`COMMAND_FAILED`,`Unable to locate macOS helper package root`,{modulePath:e})}function S(){return x(f(import.meta.url))}function C(){return s.join(S(),`.build`,`release`,m)}function w(){return s.join(g,m)}async function T(e){let t=await u.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=s.join(e,t.name);return t.isDirectory()?t.name===`.build`?[]:await T(n):!t.isFile()||!t.name.endsWith(`.swift`)&&t.name!==`Package.swift`?[]:[n]}))).flat().sort()}async function E(e){let t=await T(e),n=c(`sha256`);for(let r of t)n.update(s.relative(e,r)),n.update(`\0`),n.update(await u.readFile(r)),n.update(`\0`);let r=await i(`swift`,[`--version`],{allowFailure:!0,cwd:e,timeoutMs:1e4});return n.update(`swift-version`),n.update(`\0`),n.update(r.stdout||r.stderr||`exit:${r.exitCode}`),n.update(`\0`),n.digest(`hex`)}async function D(){try{let e=JSON.parse(await u.readFile(_,`utf8`));return typeof e.fingerprint==`string`?e.fingerprint:null}catch{return null}}async function O(){let e=await n(process.env[h],h);if(e)return e;let t=S(),r=await E(t),a=w();try{if(await D()===r)return await u.access(a),a}catch{}let o=C();process.stderr.write(`agent-device: building macOS helper (first run or helper update)
2
2
  `),await i(`swift`,[`build`,`-c`,`release`,`--package-path`,t],{cwd:t,timeoutMs:12e4}),await u.mkdir(g,{recursive:!0});let s=`${a}.tmp`;return await u.copyFile(o,s),await u.rename(s,a),await u.chmod(a,493),await u.writeFile(_,`${JSON.stringify({fingerprint:r},null,2)}\n`,`utf8`),a}async function k(){let e=process.env[h]?.trim();if(e){let t=await n(e,h);if(t)return t}if(o())return m;if(process.platform!==`darwin`)throw new t(`UNSUPPORTED_PLATFORM`,`macOS helper is only available on macOS`);return await O()}async function A(e){return r(await k(),[`audio-probe`,`--duration-ms`,String(e.durationMs),`--bucket-ms`,String(e.bucketMs),`--out`,e.statusPath],{allowFailure:!0,captureOutput:!0})}async function j(e,n={}){let r={allowFailure:!0,timeoutMs:3e4,signal:n.signal},o=a().macosHelper,s=o?m:await k(),c=o?await o.run(e,r):await i(s,e,r),l=c.stdout.trim(),u=null;if(l)try{u=JSON.parse(l)}catch{u=null}if(c.exitCode===0&&u?.ok)return u.data;throw new t(`COMMAND_FAILED`,u&&!u.ok?u.error?.message??`macOS helper exited with code ${c.exitCode}`:l||c.stderr.trim()||`macOS helper exited with code ${c.exitCode}`,{helperPath:s,args:e,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,...u&&!u.ok?u.error?.details:{}})}async function M(){return await j([`app`,`frontmost`])}async function N(e){return await j([`app`,`quit`,`--bundle-id`,y(e)])}async function P(e,t){return await j([`permission`,e,t])}async function F(e,t={}){let n=[`alert`,e];return b(n,t),await j(n)}async function I(e,t={}){let n=[`snapshot`,`--surface`,e];return b(n,t),await j(n,{signal:t.signal})}async function L(e,t,n={}){let r=[`read`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function R(e,t,n={}){let r=[`press`,`--x`,String(e),`--y`,String(t)];return b(r,n),await j(r)}async function z(e,t={}){let n=[`screenshot`,`--out`,e];return b(n,t),t.fullscreen&&n.push(`--fullscreen`),await j(n)}export{P as a,A as c,F as i,N as n,z as o,M as r,I as s,p as t};
@@ -1,2 +1,2 @@
1
- import{C as e,v as t}from"./sdk-android-adb.js";import{t as n}from"./timeouts.js";function r(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function i(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,0),!0}catch(e){return e.code===`EPERM`}}function a(e){return s(e,`lstart=`)}function o(e){return s(e,`command=`)}function s(t,n){if(!Number.isInteger(t)||t<=0)return null;try{let r=e(`ps`,[`-p`,String(t),`-o`,n],{allowFailure:!0,timeoutMs:1e3});if(r.exitCode!==0)return null;let i=r.stdout.trim();return i.length>0?i:null}catch{return null}}function c(e){let t=[];for(let n of e.split(`
2
- `)){let e=/^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10),i=Number.parseInt(e[2],10),a=e[3];!Number.isInteger(r)||r<=0||t.push({pid:r,ppid:Number.isInteger(i)&&i>0?i:void 0,command:a})}return t}async function l(e){let n=await(e.runCommand??t)(`ps`,[`-ax`,`-o`,`pid=,ppid=,command=`],{allowFailure:!0,timeoutMs:e.timeoutMs});return n.exitCode===0?c(n.stdout):[]}function u(e,t){let n=new Set(d(e)),r=!0;for(;r;){r=!1;for(let e of t)e.ppid===void 0||!n.has(e.ppid)||n.has(e.pid)||(n.add(e.pid),r=!0)}return t.filter(e=>n.has(e.pid))}function d(e,t={}){return[...new Set(e)].filter(e=>Number.isInteger(e)&&e>0&&e!==t.excludePid)}function f(e,t){let n=d(e,{excludePid:process.pid}),r=0;for(let e of n)try{process.kill(e,t),r+=1}catch{}return r}async function p(e,t){if(!r(e))return!0;let i=Date.now();for(;Date.now()-i<t;)if(await n(50),!r(e))return!0;return!r(e)}async function m(e){let t=d(e.pids,{excludePid:process.pid});t.length!==0&&(f(t,`SIGTERM`),await Promise.all(t.map(async t=>await p(t,e.termTimeoutMs))),f(t.filter(e=>r(e)),`SIGKILL`),await Promise.all(t.map(async t=>await p(t,e.killTimeoutMs))))}export{o as a,m as c,l as i,d as l,r as n,a as o,i as r,f as s,u as t,p as u};
1
+ import{S as e,_ as t}from"./sdk-android-adb.js";import{t as n}from"./timeouts.js";function r(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function i(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(-e,0),!0}catch(e){return e.code===`EPERM`}}function a(e){return c(e,`lstart=`)}function o(e){return c(e,`command=`)}function s(e){return c(e,`state=`)?.startsWith(`Z`)??!1}function c(t,n){if(!Number.isInteger(t)||t<=0)return null;try{let r=e(`ps`,[`-p`,String(t),`-o`,n],{allowFailure:!0,timeoutMs:1e3});if(r.exitCode!==0)return null;let i=r.stdout.trim();return i.length>0?i:null}catch{return null}}function l(e){let t=[];for(let n of e.split(`
2
+ `)){let e=/^\s*(\d+)\s+(\d+)\s+(.+?)\s*$/.exec(n);if(!e)continue;let r=Number.parseInt(e[1],10),i=Number.parseInt(e[2],10),a=e[3];!Number.isInteger(r)||r<=0||t.push({pid:r,ppid:Number.isInteger(i)&&i>0?i:void 0,command:a})}return t}async function u(e){let n=await(e.runCommand??t)(`ps`,[`-ax`,`-o`,`pid=,ppid=,command=`],{allowFailure:!0,timeoutMs:e.timeoutMs});return n.exitCode===0?l(n.stdout):[]}function d(e,t){let n=new Set(f(e)),r=!0;for(;r;){r=!1;for(let e of t)e.ppid===void 0||!n.has(e.ppid)||n.has(e.pid)||(n.add(e.pid),r=!0)}return t.filter(e=>n.has(e.pid))}function f(e,t={}){return[...new Set(e)].filter(e=>Number.isInteger(e)&&e>0&&e!==t.excludePid)}function p(e,t){let n=f(e,{excludePid:process.pid}),r=0;for(let e of n)try{process.kill(e,t),r+=1}catch{}return r}async function m(e,t){if(!r(e))return!0;let i=Date.now();for(;Date.now()-i<t;)if(await n(50),!r(e))return!0;return!r(e)}async function h(e){let t=f(e.pids,{excludePid:process.pid});t.length!==0&&(p(t,`SIGTERM`),await Promise.all(t.map(async t=>await m(t,e.termTimeoutMs))),p(t.filter(e=>r(e)),`SIGKILL`),await Promise.all(t.map(async t=>await m(t,e.killTimeoutMs))))}export{u as a,p as c,m as d,s as i,h as l,r as n,o,i as r,a as s,d as t,f as u};
@@ -1,9 +1,9 @@
1
- import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{t as o}from"./screenshot-geometry.js";import{Z as s,rt as c}from"./sdk-selectors.js";import{T as l,b as u,y as d}from"./device.js";import{I as f,a as p,c as m,j as h,n as g,o as ee,p as te,s as ne,v as re}from"./sdk-android-adb.js";import{n as ie,t as ae}from"./version.js";import{t as oe}from"./timeouts.js";import"./install-artifact.js";import{r as se,t as ce}from"./entities.js";import _ from"node:path";import le from"node:crypto";import ue from"node:os";import v from"node:fs/promises";import de from"node:net";function fe(){let e=[],t=()=>e[e.length-1]===!0;return{open(n,r){let i=t()||u(n);return r||e.push(i),i},close(){e.pop()}}}function*pe(e){let t=/<node\b[^>]*>|<\/node>/g,n=fe(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=me(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function me(e){let t=be(e),n=se(t.bounds);return{...t,...n?{rect:n}:{}}}function he(e,t,n){let{sourceNodes:r,...i}=y(ke(e),t,n);return i}function y(e,t,n){let r={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:n.depth??1/0,options:n,analysis:at(e),interactiveDescendantMemo:new Map,truncated:!1},i=n.scope?it(e,n.scope):null,a=i?[i]:e.children;for(let e of a)if(ge(r,e,0),r.truncated)break;let o={nodes:r.nodes,sourceNodes:r.sourceNodes,analysis:r.analysis};return r.truncated?{...o,truncated:!0}:o}function ge(e,t,n,r,i=!1,a=!1,o=!1){if(e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes){e.truncated=!0;return}if(n>e.maxDepth)return;let s=e.options.raw?!0:Ye(t,e.options,i,ye(e,t),a),c=o||u(t.identifier),l=s?_e(e,t,r,c):r,d=i||!!t.hittable,f=a||tt(t.type);for(let r of t.children)if(ge(e,r,n+1,l,d,f,c),e.truncated)return}function _e(e,t,n,r){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,focused:t.focused,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:ve(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function ve(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function ye(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(n.visibleToUser!==!1&&(n.hittable||ye(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function be(e){let t=xe(e),n=e=>Oe(t,e),r=e=>{let t=n(e);if(t!==null)return t===`true`},i=e=>{let t=n(e);if(t===null||t.trim()===``)return;let r=Number(t);return Number.isFinite(r)?r:void 0},a=(e,t)=>{let n=i(t);return n===void 0?{}:{[e]:n}},o=(e,t)=>{let r=se(n(t));return r===void 0?{}:{[e]:r}},s=(e,t)=>{let n=r(t);return n===void 0?{}:{[e]:n}};return{text:n(`text`),desc:n(`content-desc`),resourceId:n(`resource-id`),packageName:n(`package`),className:n(`class`),bounds:n(`bounds`),clickable:r(`clickable`),enabled:r(`enabled`),focusable:r(`focusable`),focused:r(`focused`),password:r(`password`),...s(`visibleToUser`,`visible-to-user`),...a(`drawingOrder`,`drawing-order`),...s(`scrollable`,`scrollable`),...s(`canScrollForward`,`can-scroll-forward`),...s(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...s(`windowActive`,`window-active`),...s(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function xe(e){let t=new Map,n=e.indexOf(` `),r=e.lastIndexOf(`>`);if(n<0||r<=n)return t;let i=n;for(;i<r;){let n=Se(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Se(e,t,n){if(t=b(e,t,n),t>=n||we(e[t]))return;let r=t;t=Ce(e,t,n);let i=e.slice(r,t);if(t=b(e,t,n),!i||e[t]!==`=`)return;t=b(e,t+1,n);let a=e[t];if(!Te(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:ce(e.slice(o,s)),nextCursor:s+1}}function Ce(e,t,n){for(;t<n&&!De(e[t]??``);)t+=1;return t}function b(e,t,n){for(;t<n&&Ee(e[t]??``);)t+=1;return t}function we(e){return e===`/`||e===`>`}function Te(e){return e===`"`||e===`'`}function Ee(e){return e===` `||e===`
2
- `||e===`\r`||e===` `}function De(e){return e===`=`||e===`/`||e===`>`||Ee(e)}function Oe(e,t){return e.get(t)??null}function ke(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},n=[t],r=/<node\b[^>]*>|<\/node>/g,i=r.exec(e);for(;i;){let t=i[0];if(t.startsWith(`</node`)){n.length>1&&n.pop(),i=r.exec(e);continue}let a=me(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,hittable:a.clickable??a.focusable,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return Ae(t),He(t),je(t,{actionableContentMemo:new WeakMap}),Ve(t),t}function Ae(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(Ae(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function je(e,t){for(let n of e.children)je(n,t);if(e.children.length<2)return;let n=e.children,r=n.filter(e=>Ie(e,t));r.length!==0&&(e.children=n.filter(e=>Me(e,r)))}function Me(e,t){return Ne(e)||!Pe(e,t)}function Ne(e){return Fe(e)&&!e.hittable&&e.children.length===0}function Pe(e,t){if(e.visibleToUser===!1||e.drawingOrder===void 0||!ze(e))return!1;for(let n of t)if(!(n===e||n.drawingOrder<=e.drawingOrder)&&Be(n.rect,e.rect)>=.9)return!0;return!1}function Fe(e){let t=e.identifier?.trim()??``;return!!(t&&!x(t))}function Ie(e,t){return e.visibleToUser!==!1&&e.drawingOrder!==void 0&&ze(e)&&(Le(e)||Re(e,t))}function Le(e){if(e.visibleToUser===!1)return!1;if(e.hittable)return!0;let t=e.label?.trim()??``;if(t&&!x(t))return!0;let n=e.identifier?.trim()??``;return!!(n&&!x(n))}function Re(e,t){let n=t.actionableContentMemo.get(e);if(n!==void 0)return n;let r=e.children.some(e=>e.visibleToUser!==!1&&(!!e.hittable||Re(e,t)));return t.actionableContentMemo.set(e,r),r}function ze(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function Be(e,t){let n=t.width*t.height;return n<=0?0:o(e,t)/n}function Ve(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),qe(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function He(e){let t=e.children.filter(We);if(t.length<2)return;let n=t.filter(e=>Ge(e)&&Ke(e));if(n.length===0)return;let r=Ue(n);e.children=e.children.filter(e=>Ge(e)?Ke(e)?r===void 0||e.windowLayer===r:!1:!0)}function Ue(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function We(e){return e.windowIndex!==void 0||e.windowType!==void 0}function Ge(e){return e.windowType===1}function Ke(e){return e.windowActive===!0||e.windowFocused===!0}function qe(e){if(!e.scrollable||!c(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=Je(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function Je(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function Ye(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=Xe(e);return t.interactiveOnly?Ze(e,a,n,r,i):a.isStructural||a.isVisual?et(e,a,r):!0}function Xe(e){let t=nt(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!x(e.label??``),hasMeaningfulId:r&&!x(e.identifier??``),isStructural:rt(t),isVisual:t===`imageview`||t===`imagebutton`}}function Ze(e,t,n,r,i){return $e(e)?!1:e.focused||e.hittable||c(t.type)&&r?!0:Qe(t,n,r,i)}function Qe(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r?!1:t||n||r}function $e(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function et(e,t,n){return e.hittable||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function tt(e){if(!e)return!1;let t=nt(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function nt(e){return e?e.toLowerCase():``}function rt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function x(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function it(e,t){let n=t.toLowerCase(),r=[...e.children],i=0;for(;i<r.length;){let e=r[i++],t=e.label?.toLowerCase()??``,a=e.value?.toLowerCase()??``,o=e.identifier?.toLowerCase()??``;if(t.includes(n)||a.includes(n)||o.includes(n))return e;r.push(...e.children)}return null}function at(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}function S(e){let t={status:[],results:[],currentStatus:null,currentResult:null};for(let n of e.split(/\r?\n/))ot(n,t);return st(t),{status:t.status,results:t.results}}function ot(e,t){if(e.startsWith(`INSTRUMENTATION_STATUS: `)){t.currentStatus??={},ut(e.slice(24),t.currentStatus);return}if(e.startsWith(`INSTRUMENTATION_STATUS_CODE: `)){ct(t);return}if(e.startsWith(`INSTRUMENTATION_RESULT: `)){t.currentResult??={},ut(e.slice(24),t.currentResult);return}e.startsWith(`INSTRUMENTATION_CODE: `)&&lt(t)}function st(e){ct(e),lt(e)}function ct(e){e.currentStatus&&=(e.status.push(e.currentStatus),null)}function lt(e){e.currentResult&&=(e.results.push(e.currentResult),null)}function ut(e,t){let n=e.indexOf(`=`);n<0||(t[e.slice(0,n)]=e.slice(n+1))}function C(e){if(e===void 0)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function w(e){if(e===`true`)return!0;if(e===`false`)return!1}function dt(e,t,r){if(typeof e!=`number`||!Number.isInteger(e))throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} must be an integer.`);return e}function T(e,t,r,i){if(e!==r)throw new n(`INVALID_ARGS`,`Android ${i} manifest ${t} must be "${r}".`);return r}function E(e,t,r){if(typeof e!=`string`||e.length===0)throw new n(`INVALID_ARGS`,`Android ${r} manifest ${t} is required.`);return e}function ft(e,t){let r=E(e,`sha256`,t).trim().toLowerCase();if(r.length!==64||!/^[0-9a-f]+$/.test(r))throw new n(`INVALID_ARGS`,`Android ${t} manifest sha256 must be a 64-character hex string.`);return r}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,pt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function mt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:yt(t.apkUrl,`apkUrl`),sha256:vt(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:gt(t.installArgs)}}function k(e,t){return dt(e,t,`snapshot helper`)}function A(e,t,n){return T(e,t,n,`snapshot helper`)}function ht(e){return _t(gt(e.installArgs))}function gt(e){let t=bt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!xt(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function _t(e){let t={};for(let r of e.slice(1)){let e=St(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function vt(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ct(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function yt(e,t){return e===null?null:j(e,t)}function bt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function xt(e){return St(e)!==void 0}function St(e){if(Object.hasOwn(pt,e))return pt[e]}function Ct(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const wt=2e3,Tt=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function Et(e){await Mt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:Tt,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Dt(e){return e instanceof n&&e.details?.reason===Tt}async function Ot(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Mt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Nt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function kt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function At(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function jt(){N.clear()}async function Mt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Nt(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function Pt(e){let t=Ft(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(It(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await Et({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Lt(e,t,i);if(t.outputPath&&!o&&await Wt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,te(i,{helper:a.metadata}));return a}function Ft(e){let t=R(e.timeoutMs,8e3),n=R(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:R(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:R(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:R(e.commandTimeoutMs,t+5e3),maxDepth:R(e.maxDepth,128),maxNodes:R(e.maxNodes,5e3),packageName:n,runner:R(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function R(e,t){return e===void 0?t:e}function It(e){return[`shell`,`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],e.runner]}async function Lt(e,t,n){try{return{output:Gt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Rt(e,t,n,r)}}async function Rt(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await zt(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},i)}async function zt(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Vt(e.adb,t.outputPath,Ut(`${n.stdout}\n${n.stderr}`)??Bt(t))}function Bt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Vt(e,t,n){let r;try{r=await e(Ht(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Ht(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function Ut(e){try{return $t(qt(S(e).results))}catch{return null}}async function Wt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Gt(e){let t=S(e),n=qt(t.results);return{xml:Yt(Kt(t.status),n),metadata:{...$t(n),transport:`instrumentation`}}}function Kt(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:z(n.chunkIndex),count:z(n.chunkCount),payloadBase64:e})}return t}function qt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Jt(t),{errorType:t.errorType,helper:t});return t}function Jt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function Yt(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=Xt(e),i=Buffer.concat(Qt(Zt(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function Xt(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function Zt(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function Qt(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function $t(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs),waitForIdleQuietMs:z(e.waitForIdleQuietMs),timeoutMs:z(e.timeoutMs),maxDepth:z(e.maxDepth),maxNodes:z(e.maxNodes),rootPresent:tn(e.rootPresent),captureMode:en(e.captureMode),windowCount:z(e.windowCount),nodeCount:z(e.nodeCount),truncated:tn(e.truncated),elapsedMs:z(e.elapsedMs)}}function en(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const z=C,tn=w;function nn(){return new Promise((e,t)=>{let n=de.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function B(e,t,r,i){return new Promise((a,o)=>{let s=de.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${t}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function rn(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return un(await B(e.port,`snapshot ${t}`,an(e),e.signal),t)}function an(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function on(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function sn(e){let t=e.indexOf(`
1
+ import{S as e,T as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{n as o,r as s,s as c,t as l}from"./version.js";import{$ as u,J as d,Vn as f,q as p}from"./sdk-batch-runner.js";import{A as m,F as h,_ as ee,a as te,f as ne,i as re,n as g,o as _,s as v}from"./sdk-android-adb.js";import{t as ie}from"./timeouts.js";import"./install-artifact.js";import{r as ae,t as oe}from"./entities.js";import y from"node:path";import se from"node:crypto";import ce from"node:os";import b from"node:fs/promises";import le from"node:net";function ue(){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*de(e){let t=/<node\b[^>]*>|<\/node>/g,n=ue(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=fe(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function fe(e){let t=ve(e),n=ae(t.bounds);return{...t,...n?{rect:n}:{}}}function pe(e,t,n){let{sourceNodes:r,...i}=x(De(e),t,n);return i}function x(e,t,n){let r={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:n.depth??1/0,options:n,analysis:rt(e),interactiveDescendantMemo:new Map,truncated:!1},i=n.scope?nt(e,n.scope):null,a=i?[i]:e.children;for(let e of a)if(me(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 me(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:qe(t,e.options,i,_e(e,t),a),c=o||d(t.identifier),l=s?he(e,t,r,c):r,u=i||!!t.hittable,f=a||$e(t.type);for(let r of t.children)if(me(e,r,n+1,l,u,f,c),e.truncated)return}function he(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:ge(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function ge(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function _e(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||_e(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function ve(e){let t=ye(e),n=e=>Ee(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=ae(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 ye(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=be(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function be(e,t,n){if(t=S(e,t,n),t>=n||Se(e[t]))return;let r=t;t=xe(e,t,n);let i=e.slice(r,t);if(t=S(e,t,n),!i||e[t]!==`=`)return;t=S(e,t+1,n);let a=e[t];if(!Ce(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:oe(e.slice(o,s)),nextCursor:s+1}}function xe(e,t,n){for(;t<n&&!Te(e[t]??``);)t+=1;return t}function S(e,t,n){for(;t<n&&we(e[t]??``);)t+=1;return t}function Se(e){return e===`/`||e===`>`}function Ce(e){return e===`"`||e===`'`}function we(e){return e===` `||e===`
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(`
3
3
 
4
- `);return pn(e.slice(0,t<0?e.length:t))}function cn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:t})}function ln(e,t){let n=sn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function un(e,t){let r=e.indexOf(`
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=pn(e.slice(0,r)),a=e.slice(r+2);return dn(i,t),fn(i,a),{xml:a,metadata:mn(i)}}function dn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function fn(e,t){let r=C(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function pn(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function mn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:C(e.waitForIdleTimeoutMs),waitForIdleQuietMs:C(e.waitForIdleQuietMs),timeoutMs:C(e.timeoutMs),maxDepth:C(e.maxDepth),maxNodes:C(e.maxNodes),rootPresent:w(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:C(e.windowCount),nodeCount:C(e.nodeCount),truncated:w(e.truncated),elapsedMs:C(e.elapsedMs)}}const hn=5e3,V=new Map,gn=new Map;async function _n(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!An()||!e.adbProvider?.spawn)return;let n=bn(Ft(e)),r=await vn({deviceKey:t,identity:kn(t,n,e),options:e,resolved:n});if(r)return await yn({session:r,deviceKey:t,options:e,resolved:n})}async function vn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(gn.get(t)===n)return;let a=V.get(t);if(a&&a.identity!==n&&(await H(t),a=void 0),!a)try{a=await On({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),gn.set(t,n),h({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Dt(e))throw e;return}return a}async function yn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await rn({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await H(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:xn(e)}});return}}function bn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function xn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Sn(e){let t=V.get(e.deviceKey);if(!t)return;if(!Cn(t.helper,e.helper)){h({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await H(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=sn(await B(t.port,i,e.timeoutMs)),cn(a,r)}catch(t){throw await H(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function Cn(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&wn(e.helperVersion,t.helperVersion)&&wn(e.helperVersionCode,t.helperVersionCode)&&wn(e.sha256,t.sha256)}function wn(e,t){return e===void 0||t===void 0||e===t}async function H(e,t={}){let n=V.get(e);if(!n)return;V.delete(e);let r=kt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await Tn(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:wt:hn,s=i?250:2e3,[c,l]=await Promise.all([At({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Ot({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);h({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,forceKilled:!a.exited&&c,forced:i||t.signal?.aborted===!0,runtimeForceStopped:l.runtimeForceStopped,externalCleanupTimedOut:l.timedOut}}),!a.exited&&!l.runtimeForceStopped&&I({deviceKey:e,packageName:n.helper.packageName,cause:t.cause})}async function Tn(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=ln(await B(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await L(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function En(e){await H(P(e))}async function Dn(){let e=await Promise.allSettled([...V.keys()].map(e=>H(e)));gn.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);jt()}async function On(e){let t=await nn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:hn,signal:e.options.signal});let r=It({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await on(o,1e4,e.options.signal),V.set(e.deviceKey,s),h({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(t){let n=kt(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([L(n,250),Ot({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:wt})]);throw r.runtimeForceStopped||I({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function kn(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function An(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const jn=1e4;async function Mn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,apkPath:a,sha256:o,cache:s,deviceKey:c,installTimeoutMs:l,helperLabel:u}=e,d=`${c}\0${r}\0${i}\0${o}`;if(s.has(d))return{packageName:r,versionCode:i,installedSha256:o,installed:!1,reason:`current`};await zn(a,o,u);let f=await Nn({adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:o});if(f.reason===`current`)return s.add(d),{packageName:r,versionCode:i,...f,installed:!1};let m=await p(a,{provider:n,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:l});if(m.exitCode!==0)throw g(`Failed to install ${u}`,m,{packageName:r,versionCode:i,reason:f.reason});return s.add(d),{packageName:r,versionCode:i,...f,installed:!0}}async function Nn(e){let{adb:t,adbProvider:n,packageName:r,versionCode:i,sha256:a,signal:o}=e,s=await In(t,r,o);if(s===void 0)return{reason:`missing`};if(s<i)return{installedVersionCode:s,reason:`outdated`};if(s>i)return{installedVersionCode:s,reason:`current`};try{let e=await Ln(t,n,r,o);return{installedVersionCode:s,installedSha256:e,reason:e===a?`current`:`mismatched`}}catch{return o?.throwIfAborted(),{installedVersionCode:s,reason:`unverifiable`}}}async function Pn(t){let r=ie(),i=_.join(ae(),`android`,t.helperDirName,`dist`),a=_.join(i,t.manifestFileName(r));try{let e=t.parseManifest(JSON.parse(await v.readFile(a,`utf8`))),n=_.join(i,e.assetName);return await v.access(n),{apkPath:n,manifest:e}}catch(r){throw new n(`UNSUPPORTED_OPERATION`,t.unavailableMessage,{manifestPath:a,error:e(r).message},r)}}function Fn(e){return async t=>await Mn({adb:t.adb,adbProvider:t.adbProvider,packageName:t.artifact.manifest.packageName,versionCode:t.artifact.manifest.versionCode,apkPath:t.artifact.apkPath,sha256:t.artifact.manifest.sha256,cache:e.cache,deviceKey:t.deviceKey,installTimeoutMs:e.installTimeoutMs,helperLabel:e.helperLabel})}async function In(e,t,n){let r=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3,signal:n});if(r.exitCode!==0)return;let i=RegExp(`package:${Vn(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}\n${r.stderr}`);return i?Number(i[1]):void 0}async function Ln(e,t,r,i){let a=await e([`shell`,`pm`,`path`,r],{allowFailure:!0,timeoutMs:jn,signal:i}),o=Rn(`${a.stdout}\n${a.stderr}`);if(a.exitCode!==0||!o)throw new n(`COMMAND_FAILED`,`Could not resolve installed Android helper APK`);let s=await v.mkdtemp(_.join(ue.tmpdir(),`agent-device-helper-`)),c=_.join(s,`base.apk`);try{let e=await ee(o,c,{provider:t,allowFailure:!0,timeoutMs:jn,signal:i});if(e.exitCode!==0)throw g(`Could not read installed Android helper APK`,e,{packageName:r,remotePath:o});return await Bn(c)}finally{await v.rm(s,{recursive:!0,force:!0})}}function Rn(e){return e.split(/\r?\n/).map(e=>e.startsWith(`package:`)?e.slice(8).trim():``).find(e=>e.endsWith(`/base.apk`))}async function zn(e,t,r){let i=await Bn(e);if(i!==t)throw new n(`COMMAND_FAILED`,`${r} APK checksum mismatch`,{apkPath:e,expectedSha256:t,actualSha256:i})}async function Bn(e){let t=le.createHash(`sha256`);return t.update(await v.readFile(e)),t.digest(`hex`)}function Vn(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const U=new Map;function Hn(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of U.keys())e.startsWith(t)&&Gn(e)}function Un(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Wn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of U.keys())t!==e&&t.startsWith(i)&&U.delete(t);U.set(e,t)}function Gn(e){e&&U.delete(e)}async function Kn(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Un(e.deviceKey,i,a,o),c=s?U.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await zn(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await Yn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await Nn({adb:t,adbProvider:Jn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Wn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Xn(t,e.adbProvider??t,n.apkPath,ht(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw Gn(s),qn(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw Gn(s),qn(g(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Wn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function qn(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Jn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function Yn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Zn(`${i.stdout}\n${i.stderr}`,t)}async function Xn(e,t,n,r,i){let a=async()=>await p(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!Qn(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
7
- `)}}function Zn(e,t){let n=`package:${t}`;for(let t of e.split(/\r?\n/)){if(!t.startsWith(n)||t.length>n.length&&!/\s/.test(t[n.length]??``))continue;let e=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(e)return Number(e[1])}}function Qn(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const $n=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function er(e){return $n.has(e)}const tr=new Set([`android`,`com.android.systemui`]),nr=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,W=/^android:id\/button[123]$/i,rr=/(?:^|:)id\/permission_/i,ir=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,ar=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,or=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function sr(e){if(e!==null){if(W.test(e))return`button`;if(nr.test(e))return`content`}}function cr(e){let t=ur(e),n=t.nodes;if(n.length===0)return null;let r=hr(n),i=n.filter(e=>G(e)&&!Tr(e)),a=vr(i),o=yr(i,a),s=Er(n);return{alert:{...a?{title:a}:{},...o?{message:o}:{},buttons:r.map(e=>e.label),platform:`android`,source:t.source,...s?{packageName:s}:{}},buttons:r}}function lr(e,t){let n=t===`accept`?`accept`:`dismiss`;return e.find(e=>e.role===n)||(t===`dismiss`?e.find(e=>e.role===`neutral`)??null:e.length===1?e[0]??null:null)}function ur(e){let t=e.filter(e=>Cr(e));if(t.length)return{nodes:t,source:`permission`};let n=mr(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:dr(e),source:`native-dialog`}}function dr(e){let t=e.filter(e=>fr(e.type??``)),n=e.filter(e=>nr.test(e.identifier??``)),r=t.length?[...t,...n]:pr(n);if(r.length===0)return[];let i=br(e,r);return i===void 0?r:Sr(e,i)}function fr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function pr(e){let t=e.some(e=>W.test(e.identifier??``)),n=e.some(e=>!W.test(e.identifier??``));return t&&n?e:[]}function mr(e){let t=e.filter(e=>wr(e));if(t.length===0)return[];let n=br(e,t);return n===void 0?t:Sr(e,n).filter(e=>e.bundleId&&tr.has(e.bundleId))}function hr(e){let t=new Set,n=[];for(let r of e){let e=G(r);if(!e||!r.rect||!Tr(r))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=i(r.rect);n.push({label:e,x:o.x,y:o.y,role:gr(r,e)})}return n}function gr(e,t){return _r(e.identifier??``)||(ar.test(t.trim())?`accept`:or.test(t.trim())?`dismiss`:`neutral`)}function _r(e){return/(?:^|:)id\/button1$/i.test(e)?`accept`:/(?:^|:)id\/button2$/i.test(e)?`dismiss`:/(?:^|:)id\/button3$/i.test(e)?`neutral`:/(?:^|:)id\/permission_allow/i.test(e)?`accept`:/(?:^|:)id\/permission_deny/i.test(e)?`dismiss`:null}function vr(e){return G(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||G(e[0])}function yr(e,t){let n=e.map(e=>G(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
8
- `):void 0}function br(e,t){let n=t[0];if(!n)return;let r=xr(e,n.index);for(let n of t.slice(1)){let t=new Set(xr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function xr(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function Sr(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function Cr(e){let t=e.bundleId??``;return $n.has(t)||rr.test(e.identifier??``)}function wr(e){let t=e.bundleId??``;return tr.has(t)&&ir.test(G(e))}function Tr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||W.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function G(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function Er(e){return e.find(e=>e.bundleId)?.bundleId}const Dr=new Set([`android`,`com.android.systemui`]);function Or(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Rr(e,n.foregroundAppPackage);return Ar(r,t)?K(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Ir(r)?{outcome:`ok`}:kr(r)?{outcome:`system-surface-only`}:jr(r)?{outcome:`ok`}:Mr(r)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Nr(r)||Pr(r,t)?K(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Fr(r)?K(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function K(e,t,n,r){return{outcome:`unusable`,decision:Lr(e,t,n,r)}}function kr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function Ar(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function jr(e){return Mr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Mr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Nr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function Pr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Fr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Ir(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Lr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Qr(e,t)}}function Rr(e,t){let n=zr(t);for(let t of pe(e))Br(n,t);return qr(n)}function zr(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function Br(e,t){e.nodeCount+=1,Zr(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&Vr(e,t.resourceId),Hr(e,t),Ur(e,t)}function Vr(e,t){let n=sr(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Hr(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Ur(e,t){Jr(t)&&(e.meaningfulNodeCount+=1,Wr(e,t),Kr(e,t))}function Wr(e,t){e.currentWindowType===1&&!Xr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Gr(e)&&!d(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Gr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Kr(e,t){Xr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),l({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function qr(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Jr(e){return e.visibleToUser===!1?!1:Yr(e.text)||Yr(e.desc)||Yr(e.resourceId)}function Yr(e){return e!==null&&e.trim()!==``}function Xr(e){return e===null||Dr.has(e)}function Zr(e){return e!==null&&Dr.has(e)}function Qr(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}const $r=5e3,ei=3e4;async function ti(e,t={}){let n=m(e,t.helperAdb).exec;return(await oi(e,t,n)).xml}async function ni(e,t={}){let n=m(e,t.helperAdb).exec,r=await oi(e,t,n),i=r.xml;if(!t.interactiveOnly){let e=he(i,void 0,t),n=ri(e.truncated,r.metadata);return{...e,...ii(n),androidSnapshot:r.metadata}}let a=ke(i),o=y(a,void 0,t),s=ri(o.truncated,r.metadata);t.includeHiddenContentHints!==!1&&ai({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...ii(s),androidSnapshot:r.metadata}}function ri(e,t){return e===!0||t.helperTruncated===!0?!0:e}function ii(e){return e===!0?{truncated:!0}:{}}function ai(e){if(Ei(e.interactiveSnapshot.nodes).size>0||Ti(e.xml))return;let t=y(e.tree,void 0,{...e.options,interactiveOnly:!1});Di(s(r(t.nodes)),t,e.interactiveSnapshot)}async function oi(e,t,n){let r=m(e,t.helperAdb),i=await f(`android_snapshot_helper_artifact_resolution`,async()=>await Ci(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await si(e,t,n,i.artifact);throw h({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),wi(i.errorReason)}async function si(e,t,n,r){let i=P(e),a=m(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await fi(t.signal);let s=await di({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3)return await pi({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n});e=s.decision.reason}}finally{o&&await H(i)}}async function ci(e,t,n,r,i){let a=await f(`android_snapshot_helper_install`,async()=>await Kn({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return h({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function li(t){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=t,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:$r,commandTimeoutMs:ei,signal:n};try{let e=await f(`android_snapshot_helper_session_capture`,async()=>await _n(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r});if(e)return e}catch(t){if(n?.throwIfAborted(),Dt(t))throw t;h({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:e(t).message}}),await hi(r,a.manifest.packageName)}return await f(`android_snapshot_helper_capture`,async()=>await Pt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$r,commandTimeoutMs:ei})}function ui(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function di(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await ci(t,n,r,i,a);e.installed&&await H(a),s=ui(await li({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await mi({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=Or(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(h({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&h({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function fi(e){e?.throwIfAborted(),await oe(250),e?.throwIfAborted()}async function pi(e){throw h({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),await hi(e.adb,e.artifact.manifest.packageName),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function mi(e){let t=gi(e.error);throw h({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await H(e.helperDeviceKey),await hi(e.adb,e.artifact.manifest.packageName),Hn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),_i(e.error,t)}async function hi(t,n){try{await t([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await oe(150),h({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(t){h({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:e(t).message}})}}function gi(t){let n=e(t),r=xi(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function _i(r,i){let a=e(r);return new n(t(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...yi(a),androidSnapshotHelperFailureReason:i,hint:vi(a)},r)}function vi(e){return Si(e.details?.helper,e.message)||bi(e)?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function yi(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function bi(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function xi(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function Si(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=xi(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function Ci(t){if(t)return{artifact:t};let n=ie(),r=_.join(ae(),`android`,`snapshot-helper`,`dist`),i=_.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await v.access(i)}catch{return{}}try{let e=mt(JSON.parse(await v.readFile(i,`utf8`))),t=_.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await v.access(t),{artifact:{apkPath:t,manifest:e}}}catch(t){return{errorReason:e(t).message}}}function wi(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function Ti(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function Ei(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function Di(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}const q=`IME helper`,Oi=`android-ime-helper-v1`;async function ki(){return await Pn({helperDirName:`ime-helper`,manifestFileName:e=>`agent-device-android-ime-helper-${e}.manifest.json`,parseManifest:Ai,unavailableMessage:`Android test IME text entry requires the bundled Android IME helper artifact, but it was not found or could not be read`})}function Ai(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android IME helper manifest must be an object.`);let t=e;return{name:T(t.name,`name`,`android-ime-helper`,q),version:E(t.version,`version`,q),assetName:E(t.assetName,`assetName`,q),sha256:ft(t.sha256,q),packageName:T(t.packageName,`packageName`,`com.callstack.agentdevice.imehelper`,q),versionCode:dt(t.versionCode,`versionCode`,q),serviceComponent:T(t.serviceComponent,`serviceComponent`,`com.callstack.agentdevice.imehelper/.TestInputMethodService`,q),broadcastProtocol:T(t.broadcastProtocol,`broadcastProtocol`,Oi,q)}}const ji=Fn({cache:new Set,installTimeoutMs:3e4,helperLabel:`Android IME helper`});function J(e){return`${e.platform}:${e.id}`}async function Mi(e,t,n){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_INPUT_TEXT_B64`,{text:Buffer.from(n,`utf8`).toString(`base64`)})}async function Ni(e,t){await Pi(e,t,`com.callstack.agentdevice.imehelper.ACTION_CLEAR_TEXT`,{})}async function Pi(e,t,n,r){let i=[`shell`,`am`,`broadcast`,`-p`,t,`-a`,n];i.push(`--es`,`protocol`,Oi);for(let[e,t]of Object.entries(r))i.push(`--es`,e,t);let a=await e(i,{allowFailure:!0,timeoutMs:1e4});if(a.exitCode!==0)throw g(`Android IME helper broadcast failed`,a,{action:n,packageName:t})}const Y=`agent_device_ime_helper_previous_ime`,X=`secure`,Fi=`default_input_method`,Z=new Set;function Ii(e){return Z.has(J(e))}function Q(e){return _.join(e,`android-test-ime-pending`)}function Li(e,t){return _.join(Q(e),t.replace(/[^a-zA-Z0-9._-]/g,`_`))}async function Ri(t,n){try{await v.mkdir(Q(t),{recursive:!0}),await v.writeFile(Li(t,n),n)}catch(r){h({level:`debug`,phase:`android_test_ime_marker_write_failed`,data:{stateDir:t,serial:n,error:e(r).message}})}}async function zi(e,t){await v.rm(Li(e,t),{force:!0}).catch(()=>{})}async function Bi(e){let t;try{t=await v.readdir(Q(e))}catch{return[]}let n=[];for(let r of t)try{let t=(await v.readFile(_.join(Q(e),r),`utf8`)).trim();t&&n.push(t)}catch{}return n}async function Vi(e,t={}){let n=ne(e),r=m(e),i=await ki(),{manifest:a}=i,o=J(e);await ji({adb:n,adbProvider:r,artifact:i,deviceKey:o});let s=await $(n);if(s===a.serviceComponent)return Z.add(o),t.stateDir&&await Ri(t.stateDir,e.id),{activated:!1,alreadyActive:!0,previousIme:await Ki(n),helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};if(Z.add(o),!await qi(n,s))return Z.delete(o),h({level:`warn`,phase:`android_test_ime_persist_failed`,data:{device:e.id,previousIme:s}}),{activated:!1,alreadyActive:!1,persistFailed:!0,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName};t.stateDir&&await Ri(t.stateDir,e.id),await n([`shell`,`ime`,`enable`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4});let c=await n([`shell`,`ime`,`set`,a.serviceComponent],{allowFailure:!0,timeoutMs:1e4}),l=await $(n);return l===a.serviceComponent?(h({phase:`android_test_ime_activated`,data:{device:e.id,previousIme:s}}),{activated:!0,alreadyActive:!1,previousIme:s,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName}):(Z.delete(o),await Ji(n).catch(()=>{}),t.stateDir&&await zi(t.stateDir,e.id),h({level:`warn`,phase:`android_test_ime_activate_failed`,data:{device:e.id,activeIme:l,stderr:c.stderr.trim()}}),{activated:!1,alreadyActive:!1,helperServiceComponent:a.serviceComponent,helperPackageName:a.packageName})}async function Hi(e,t={}){let n=J(e);if(!Z.has(n))return{restored:!1,reason:`no-record`};Z.delete(n);let r=await Wi(ne(e),e);return t.stateDir&&Ui(r.reason)&&await zi(t.stateDir,e.id),r}function Ui(e){return e===`ok`||e===`helper-not-active`||e===`no-record`}async function Wi(e,t){let n=t.id;if(Z.has(J(t)))return{restored:!1,reason:`owned-by-live-session`};let r=await Ki(e);if(!r)return{restored:!1,reason:`no-record`};let i=await $(e);if(i!==`com.callstack.agentdevice.imehelper/.TestInputMethodService`)return h({level:`debug`,phase:`android_test_ime_restore_skipped`,data:{device:n,currentIme:i,previousIme:r}}),{restored:!1,previousIme:r,reason:`helper-not-active`};await e([`shell`,`ime`,`set`,r],{allowFailure:!0,timeoutMs:1e4});let a=await $(e);return a===r?(await Ji(e).catch(()=>{}),h({phase:`android_test_ime_restored`,data:{device:n,previousIme:r}}),{restored:!0,previousIme:r,reason:`ok`}):(h({level:`warn`,phase:`android_test_ime_restore_failed`,data:{device:n,previousIme:r,afterIme:a}}),{restored:!1,previousIme:r,reason:`set-failed`})}async function Gi(t){let n=await Bi(t.stateDir);if(n.length===0)return;let r;try{r=new Set(await t.listSerials())}catch(t){h({level:`debug`,phase:`android_test_ime_startup_scan_failed`,data:{error:e(t).message}});return}for(let i of n){if(!r.has(i))continue;let n={platform:`android`,id:i,name:i,kind:i.startsWith(`emulator-`)?`emulator`:`device`,booted:!0};try{let e=await Wi(ne(n),n);e.restored&&h({level:`warn`,phase:`android_test_ime_orphan_restored`,data:{device:i,previousIme:e.previousIme}}),Ui(e.reason)&&await zi(t.stateDir,i)}catch(t){h({level:`debug`,phase:`android_test_ime_orphan_restore_failed`,data:{device:i,error:e(t).message}})}}}async function $(e){let t=await e([`shell`,`settings`,`get`,X,Fi],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)}async function Ki(e){let t=await e([`shell`,`settings`,`get`,X,Y],{allowFailure:!0,timeoutMs:5e3});return Yi(t.exitCode===0?t.stdout:``)||void 0}async function qi(e,t){return(await e([`shell`,`settings`,`put`,X,Y,t],{allowFailure:!0,timeoutMs:5e3})).exitCode===0?await Ki(e)===t:!1}async function Ji(e){await e([`shell`,`settings`,`delete`,X,Y],{allowFailure:!0,timeoutMs:5e3})}function Yi(e){let t=e.trim();return!t||t===`null`?``:t}async function Xi(){try{return(await re(`adb`,[`devices`],{timeoutMs:5e3})).stdout.split(`
9
- `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).filter(e=>e[1]===`device`).map(e=>e[0])}catch{return[]}}const Zi={previousIme:Y,defaultInputMethod:Fi};export{F as C,C as D,S as E,pe as O,P as S,D as T,Pn as _,$ as a,H as b,Ni as c,ti as d,ni as f,Kn as g,er as h,Xi as i,ki as l,cr as m,Vi as n,Hi as o,lr as p,Ii as r,Gi as s,Zi as t,Mi as u,Dn as v,mt as w,En as x,Sn as y};
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(`
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{Tt as C,T as D,w as E,de as O,I as S,k 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,ft as w,Dn as x,Cn as y};
@@ -1,8 +1,8 @@
1
1
  import { A as SnapshotNode, B as DeviceTarget, C as normalizeAgentDeviceError, F as SnapshotVisibility, H as PlatformSelector, I as centerOfRect, L as AppleOS, M as SnapshotQualityVerdict, P as SnapshotUnchanged, S as isAgentDeviceError, U as PublicPlatform, _ as SessionRuntimeHints, a as DaemonRequest, b as NormalizedError, f as LeaseBackend, g as SessionIsolationMode, h as ResponseLevel, i as DaemonLockPolicy, o as DaemonResponse, p as NetworkIncludeMode, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as AppError, y as DaemonError, z as DeviceKind } from "./sdk-contracts.js";
2
2
  import { c as ScrollDirection, d as SwipePreset, f as TransformGestureParams, l as ScrollInputDirection, s as GesturePointerCount, u as SwipePattern } from "./sdk-android-adb.js";
3
- import { c as SnapshotDiagnosticsSummary, d as DeviceRotation, f as BackMode, i as AndroidSnapshotBackendMetadata, l as SessionSurface, o as FindLocator, r as CloudProviderSessionResult, s as ScreenshotResultData, t as AgentArtifactsResult, u as TvRemoteButton } from "./cloud-artifacts.js";
4
- import { a as LongPressCommandResponseData, i as FindCommandResponseData, o as PressCommandResponseData, r as FillCommandResponseData, s as ClickButton, t as ClickCommandResponseData } from "./interaction.js";
3
+ import { C as SessionSurface, D as BackMode, E as ClickButton, S as SnapshotDiagnosticsSummary, T as DeviceRotation, b as FindLocator, d as ClickCommandResponseData, f as FillCommandResponseData, g as SettleObservation, h as PressCommandResponseData, m as LongPressCommandResponseData, p as FindCommandResponseData, w as TvRemoteButton, x as ScreenshotResultData, y as AndroidSnapshotBackendMetadata } from "./sdk-selectors.js";
5
4
  import { t as AppsFilter } from "./app-inventory.js";
5
+ import { r as CloudProviderSessionResult, t as AgentArtifactsResult } from "./cloud-artifacts.js";
6
6
  import { t as BatchRunResult } from "./sdk-batch-runner.js";
7
7
  import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
8
8
  import { p as createLocalArtifactAdapter } from "./sdk-io.js";
@@ -56,6 +56,13 @@ type KeyboardCommandResult = {
56
56
  focusedResourceId?: string;
57
57
  inputOwner?: 'app' | 'ime' | 'unknown';
58
58
  message?: string;
59
+ /** iOS `dismiss` only (#1598): which mechanism actually resigned the
60
+ * keyboard — 'dismissKey' (tapped the keyboard's own Hide/Dismiss/Done
61
+ * key). Generic background-tap dismissal is deliberately unsupported
62
+ * (#1606 review): no query can prove a coordinate is side-effect-free,
63
+ * so the runner only ever taps the keyboard's own control. Absent when
64
+ * the keyboard was not dismissed. */
65
+ mechanism?: 'dismissKey';
59
66
  };
60
67
  //#endregion
61
68
  //#region packages/contracts/src/navigation.d.ts
@@ -73,11 +80,17 @@ type HomeCommandResult = {
73
80
  action: 'home';
74
81
  message: string;
75
82
  };
76
- /** `back` — `{ action: 'back', mode, message: 'Back' }`; `mode` defaults to `'in-app'`. */
83
+ /**
84
+ * `back` — `{ action: 'back', mode, message: 'Back' }`; `mode` defaults to
85
+ * `'in-app'`. The one field the generic route may add on top of the dispatch
86
+ * handler's literal return: `settle`, the opt-in `--settle` observation
87
+ * (#1638), attached after the command by the generic dispatcher.
88
+ */
77
89
  type BackCommandResult = {
78
90
  action: 'back';
79
91
  mode: BackMode;
80
92
  message: string;
93
+ settle?: SettleObservation;
81
94
  };
82
95
  /** `orientation` — `{ action: 'orientation', orientation, message: 'Rotated to <orientation>' }`. */
83
96
  type OrientationCommandResult = {
@@ -142,7 +155,7 @@ type TriggerAppEventCommandResult = {
142
155
  * A discriminated union on `platform`:
143
156
  * - Apple (`ios` / `macos`) session state, with iOS-only device locators that
144
157
  * the previous hand-written mirror omitted; and
145
- * - Android foreground `package` / `activity`.
158
+ * - Android and HarmonyOS foreground `package` / `activity`.
146
159
  *
147
160
  * The handler returns one of these fixed objects (errors take the `ok: false`
148
161
  * path), so each branch is closed.
@@ -158,7 +171,7 @@ type AppStateCommandResult = {
158
171
  /** iOS only — the simulator set path, or `null` when unknown. */
159
172
  ios_simulator_device_set?: string | null;
160
173
  } | {
161
- platform: 'android';
174
+ platform: 'android' | 'harmonyos';
162
175
  package: string;
163
176
  activity: string;
164
177
  };
@@ -220,10 +233,6 @@ type ShutdownCommandResult = {
220
233
  appleOs?: AppleOS;
221
234
  };
222
235
  //#endregion
223
- //#region packages/contracts/src/logs.d.ts
224
- declare const LOG_ACTION_VALUES: readonly ['path', 'start', 'stop', 'doctor', 'mark', 'clear'];
225
- type LogAction = (typeof LOG_ACTION_VALUES)[number];
226
- //#endregion
227
236
  //#region packages/contracts/src/recording-scope.d.ts
228
237
  declare const RECORDING_SCOPE_VALUES: readonly ['app', 'device', 'system'];
229
238
  type RecordingScope = (typeof RECORDING_SCOPE_VALUES)[number];
@@ -281,10 +290,6 @@ type PerfAction = (typeof PERF_ACTION_VALUES)[number];
281
290
  type PerfSubject = (typeof PERF_SUBJECT_VALUES)[number];
282
291
  type PerfKind = (typeof PERF_KIND_VALUES)[number];
283
292
  //#endregion
284
- //#region packages/contracts/src/recording-export-quality.d.ts
285
- declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
286
- type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
287
- //#endregion
288
293
  //#region packages/contracts/src/json.d.ts
289
294
  type JsonPrimitive = string | number | boolean | null;
290
295
  type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
@@ -292,6 +297,14 @@ type JsonObject = {
292
297
  [key: string]: JsonValue;
293
298
  };
294
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
+ //#region packages/contracts/src/recording-export-quality.d.ts
305
+ declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
306
+ type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
307
+ //#endregion
295
308
  //#region packages/contracts/src/prepare.d.ts
296
309
  type PrepareIosRunnerCacheKind = 'exact' | 'restore-key' | 'miss' | 'external';
297
310
  type PrepareIosRunnerArtifactState = 'valid' | 'rebuilt';
@@ -410,6 +423,9 @@ type AgentDeviceDevice = {
410
423
  android?: {
411
424
  serial: string;
412
425
  };
426
+ harmonyos?: {
427
+ serial: string;
428
+ };
413
429
  vega?: {
414
430
  serial: string;
415
431
  };
@@ -436,6 +452,9 @@ type AgentDeviceSessionDevice = {
436
452
  android?: {
437
453
  serial: string;
438
454
  };
455
+ harmonyos?: {
456
+ serial: string;
457
+ };
439
458
  vega?: {
440
459
  serial: string;
441
460
  };
@@ -486,6 +505,12 @@ type AppOpenOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions
486
505
  launchConsole?: string;
487
506
  launchArgs?: string[];
488
507
  relaunch?: boolean;
508
+ /**
509
+ * Include the initial interactive snapshot in a fresh open response. With
510
+ * no app argument, iOS can discover the sole running app on the sole booted
511
+ * simulator and fails closed when that environment is ambiguous.
512
+ */
513
+ foreground?: boolean;
489
514
  saveScript?: boolean | string;
490
515
  /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
491
516
  force?: boolean;
@@ -507,6 +532,22 @@ type AppOpenResult = {
507
532
  startup?: StartupPerfSample;
508
533
  runtime?: SessionRuntimeHints;
509
534
  device?: AgentDeviceSessionDevice;
535
+ /**
536
+ * Initial interactive snapshot captured immediately after an open that
537
+ * requested `foreground`, composed from the same snapshot-runtime dispatch
538
+ * `agent-device snapshot -i` uses. It stays loosely typed rather than reusing
539
+ * `CaptureSnapshotResult` because the daemon-side composition does not attach
540
+ * client-only fields like `identifiers`.
541
+ */
542
+ snapshot?: Record<string, unknown>;
543
+ /**
544
+ * open --foreground: present when the session opened successfully but the
545
+ * composed initial snapshot capture failed. Carries the FULL daemon error
546
+ * shape (code, message, hint, details, diagnosticId, logPath) so recovery
547
+ * guidance survives to the caller; the session itself is open and usable —
548
+ * a `warnings` entry says so and points at `snapshot -i`.
549
+ */
550
+ initialSnapshotError?: DaemonError;
510
551
  identifiers: AgentDeviceIdentifiers;
511
552
  };
512
553
  type AppCloseOptions = AgentDeviceRequestOverrides & {
@@ -593,6 +634,8 @@ type CaptureSnapshotOptions = AgentDeviceRequestOverrides & AgentDeviceSelection
593
634
  depth?: number;
594
635
  scope?: string;
595
636
  raw?: boolean;
637
+ /** List accessibility custom actions on merged elements (iOS simulator). */
638
+ customActions?: boolean;
596
639
  forceFull?: boolean;
597
640
  timeoutMs?: number;
598
641
  /**
@@ -633,7 +676,7 @@ type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
633
676
  overlayRefs?: boolean;
634
677
  pixelDensity?: number;
635
678
  fullscreen?: boolean;
636
- maxSize?: number;
679
+ scale?: number;
637
680
  stabilize?: boolean;
638
681
  normalizeStatusBar?: boolean;
639
682
  surface?: SessionSurface;
@@ -731,6 +774,13 @@ type PanOptions = DeviceCommandBaseOptions & {
731
774
  pointerCount?: GesturePointerCount;
732
775
  durationMs?: number;
733
776
  };
777
+ type DragOptions = DeviceCommandBaseOptions & {
778
+ source: string;
779
+ destination: string;
780
+ sourceHoldMs?: number;
781
+ moveMs?: number;
782
+ destinationHoldMs?: number;
783
+ };
734
784
  type FlingOptions = DeviceCommandBaseOptions & {
735
785
  direction: ScrollDirection;
736
786
  x: number;
@@ -766,7 +816,7 @@ type RotateGestureOptions = DeviceCommandBaseOptions & {
766
816
  y?: number;
767
817
  };
768
818
  type TransformGestureOptions = DeviceCommandBaseOptions & TransformGestureParams;
769
- type ScrollOptions = DeviceCommandBaseOptions & {
819
+ type ScrollOptions = DeviceCommandBaseOptions & SettleCommandOptions & {
770
820
  direction: ScrollInputDirection;
771
821
  amount?: number;
772
822
  pixels?: number;
@@ -847,7 +897,6 @@ type RecordOptions = AgentDeviceRequestOverrides & {
847
897
  action: 'start' | 'stop';
848
898
  path?: string;
849
899
  fps?: number;
850
- maxSize?: number;
851
900
  quality?: RecordingExportQuality;
852
901
  hideTouches?: boolean;
853
902
  recordingScope?: RecordingScope;
@@ -958,7 +1007,7 @@ type FindBaseOptions = DeviceCommandBaseOptions & FindSnapshotCommandOptions & R
958
1007
  last?: boolean;
959
1008
  };
960
1009
  type FindOptions = (FindBaseOptions & {
961
- action?: 'click' | 'focus' | 'exists' | 'getText' | 'getAttrs';
1010
+ action?: 'click' | 'focus' | 'exists' | 'getText' | 'getAttrs' | 'list';
962
1011
  }) | (FindBaseOptions & {
963
1012
  action: 'wait';
964
1013
  timeoutMs?: number;
@@ -1108,6 +1157,7 @@ type JsonSchema = {
1108
1157
  items?: JsonSchema;
1109
1158
  prefixItems?: readonly JsonSchema[];
1110
1159
  oneOf?: readonly JsonSchema[];
1160
+ not?: JsonSchema;
1111
1161
  enum?: readonly unknown[];
1112
1162
  const?: unknown;
1113
1163
  minimum?: number;
@@ -1130,7 +1180,7 @@ type NavigationCommandProjection<Options, Result, Required extends boolean, Clie
1130
1180
  declare const NAVIGATION_COMMAND_PROJECTIONS: {
1131
1181
  readonly back: NavigationCommandProjection<{
1132
1182
  mode?: BackMode;
1133
- }, BackCommandResult, false, "back">;
1183
+ } & SettleCommandOptions, BackCommandResult, false, "back">;
1134
1184
  readonly home: NavigationCommandProjection<{}, HomeCommandResult, false, "home">;
1135
1185
  readonly orientation: NavigationCommandProjection<{
1136
1186
  orientation: DeviceRotation;
@@ -1478,6 +1528,7 @@ type AgentDeviceClient = {
1478
1528
  longPress: (options: LongPressOptions) => Promise<CommandResult<'longpress'>>;
1479
1529
  swipe: (options: SwipeOptions) => Promise<CommandRequestResult>;
1480
1530
  pan: (options: PanOptions) => Promise<CommandRequestResult>;
1531
+ drag: (options: DragOptions) => Promise<CommandRequestResult>;
1481
1532
  fling: (options: FlingOptions) => Promise<CommandRequestResult>;
1482
1533
  swipeGesture: (options: SwipeGestureOptions) => Promise<CommandRequestResult>;
1483
1534
  focus: (options: FocusOptions) => Promise<CommandRequestResult>;