agent-device 0.16.14 → 0.17.0

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 (46) hide show
  1. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.14.apk → agent-device-android-multitouch-helper-0.17.0.apk} +0 -0
  2. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.0.apk.sha256 +1 -0
  3. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.14.manifest.json → agent-device-android-multitouch-helper-0.17.0.manifest.json} +4 -4
  4. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.14.apk → agent-device-android-snapshot-helper-0.17.0.apk} +0 -0
  5. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.0.apk.sha256 +1 -0
  6. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.14.manifest.json → agent-device-android-snapshot-helper-0.17.0.manifest.json} +6 -6
  7. package/dist/src/1352.js +1 -1
  8. package/dist/src/221.js +4 -4
  9. package/dist/src/2415.js +29 -29
  10. package/dist/src/2805.js +1 -1
  11. package/dist/src/6232.js +1 -1
  12. package/dist/src/7599.js +4 -3
  13. package/dist/src/8020.js +1 -0
  14. package/dist/src/8699.js +1 -1
  15. package/dist/src/940.js +1 -1
  16. package/dist/src/9533.js +1 -1
  17. package/dist/src/android-snapshot-helper.d.ts +1 -0
  18. package/dist/src/apple.js +1 -1
  19. package/dist/src/args.js +14 -9
  20. package/dist/src/cli.js +9 -9
  21. package/dist/src/command-metadata.js +1 -1
  22. package/dist/src/contracts.d.ts +1 -0
  23. package/dist/src/find.js +1 -1
  24. package/dist/src/finders.d.ts +1 -0
  25. package/dist/src/generic.js +9 -9
  26. package/dist/src/index.d.ts +19 -1
  27. package/dist/src/selectors.d.ts +1 -0
  28. package/dist/src/session.js +11 -11
  29. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +4 -0
  30. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +71 -0
  31. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +41 -7
  32. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +154 -11
  33. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +11 -0
  34. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +12 -4
  35. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +26 -0
  36. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
  37. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +7 -1
  38. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +571 -56
  39. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +21 -0
  40. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +11 -0
  41. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +13 -2
  42. package/ios-runner/README.md +13 -0
  43. package/package.json +1 -1
  44. package/server.json +2 -2
  45. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.14.apk.sha256 +0 -1
  46. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.14.apk.sha256 +0 -1
@@ -0,0 +1 @@
1
+ 5d44d6844bd050d159d1f2f8fadd6200166ac5b5c67ebdce7d9f57f880690555 agent-device-android-multitouch-helper-0.17.0.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-multitouch-helper",
3
- "version": "0.16.14",
4
- "assetName": "agent-device-android-multitouch-helper-0.16.14.apk",
5
- "sha256": "9c73eeabd11869aa1d1cdae98a27decae8368d1a293bc33c3386702c1bbbcabd",
3
+ "version": "0.17.0",
4
+ "assetName": "agent-device-android-multitouch-helper-0.17.0.apk",
5
+ "sha256": "5d44d6844bd050d159d1f2f8fadd6200166ac5b5c67ebdce7d9f57f880690555",
6
6
  "packageName": "com.callstack.agentdevice.multitouchhelper",
7
- "versionCode": 16014,
7
+ "versionCode": 17000,
8
8
  "instrumentationRunner": "com.callstack.agentdevice.multitouchhelper/.MultiTouchInstrumentation",
9
9
  "statusProtocol": "android-multitouch-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ 8ec1a43c2b6a9003452763c8f8601444720bcb1efcc3cd24f3afd61157d0e29b agent-device-android-snapshot-helper-0.17.0.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.16.14",
4
- "releaseTag": "v0.16.14",
5
- "assetName": "agent-device-android-snapshot-helper-0.16.14.apk",
3
+ "version": "0.17.0",
4
+ "releaseTag": "v0.17.0",
5
+ "assetName": "agent-device-android-snapshot-helper-0.17.0.apk",
6
6
  "apkUrl": null,
7
- "sha256": "0d887ea04ab808776d705f7a5dc428f272f4b7e2cd8ba088d18e59fddf2a7106",
8
- "checksumName": "agent-device-android-snapshot-helper-0.16.14.apk.sha256",
7
+ "sha256": "8ec1a43c2b6a9003452763c8f8601444720bcb1efcc3cd24f3afd61157d0e29b",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.17.0.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 16014,
10
+ "versionCode": 17000,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
package/dist/src/1352.js CHANGED
@@ -1 +1 @@
1
- var e;import{AppError as s}from"./9152.js";import{SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS as t,SCREENSHOT_COMMAND_FLAG_KEYS as a}from"./5310.js";import{DEFAULT_APPS_FILTER as o}from"./1393.js";import{listCommandDescriptionMetadata as r}from"./2805.js";let i="<wifi|airplane|location> <on|off>",n="location set <lat> <lon>",l="animations <on|off>",p="appearance <light|dark|toggle>",u="faceid <match|nonmatch|enroll|unenroll>",c="touchid <match|nonmatch|enroll|unenroll>",m="fingerprint <match|nonmatch>",d="clear-app-state [app-id]",g="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",h="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",y=`macOS supports only settings ${p} and settings ${h}. wifi|airplane|location|animations remain unsupported on macOS.`,b=`settings ${i} | settings ${n} | settings ${l} | settings ${p} | settings ${u} | settings ${c} | settings ${m} | settings ${d} | settings ${g} | settings ${h}`,f=`settings requires ${i}, ${n}, ${l}, ${p}, ${u}, ${c}, ${m}, ${d}, ${g}, or ${h}`;function k(e){let s=e.trim().toLowerCase();return"appearance"===s||"permission"===s}function v(e){return`Unsupported macOS setting: ${e}. ${y}`}let D=["app","frontmost-app","desktop","menubar"];function w(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new s("INVALID_ARGS",`Invalid surface: ${e}. Use ${D.join("|")}.`)}let L="https://github.com/callstackincubator/agent-device/issues/558",O="https://github.com/callstackincubator/agent-device/issues/new";function S(...e){return e}let x=S("snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"),A=S("snapshotDepth","snapshotScope","snapshotRaw"),M=S("metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps"),E=S("metroHost","metroPort","bundleUrl"),R=S("count","intervalMs","holdMs","jitterPx","doubleTap"),U=S("replayUpdate","replayEnv"),P=[{key:"config",names:["--config"],type:"string",usageLabel:"--config <path>",usageDescription:"Load CLI defaults from a specific config file"},{key:"remoteConfig",names:["--remote-config"],type:"string",usageLabel:"--remote-config <path>",usageDescription:"Load remote host + Metro workflow settings from a specific profile file"},{key:"stateDir",names:["--state-dir"],type:"string",usageLabel:"--state-dir <path>",usageDescription:"Daemon state directory (defaults to ~/.agent-device)"},{key:"daemonBaseUrl",names:["--daemon-base-url"],type:"string",usageLabel:"--daemon-base-url <url>",usageDescription:"Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)"},{key:"daemonAuthToken",names:["--daemon-auth-token"],type:"string",usageLabel:"--daemon-auth-token <token>",usageDescription:"Remote HTTP daemon auth token (sent as request token and bearer header)"},{key:"daemonTransport",names:["--daemon-transport"],type:"enum",enumValues:["auto","socket","http"],usageLabel:"--daemon-transport auto|socket|http",usageDescription:"Daemon client transport preference"},{key:"daemonServerMode",names:["--daemon-server-mode"],type:"enum",enumValues:["socket","http","dual"],usageLabel:"--daemon-server-mode socket|http|dual",usageDescription:"Daemon server mode used when spawning daemon"},{key:"tenant",names:["--tenant"],type:"string",usageLabel:"--tenant <id>",usageDescription:"Tenant scope identifier for isolated daemon sessions"},{key:"sessionIsolation",names:["--session-isolation"],type:"enum",enumValues:["none","tenant"],usageLabel:"--session-isolation none|tenant",usageDescription:"Session isolation strategy (tenant prefixes session namespace)"},{key:"runId",names:["--run-id"],type:"string",usageLabel:"--run-id <id>",usageDescription:"Run identifier used for tenant lease admission checks"},{key:"leaseId",names:["--lease-id"],type:"string",usageLabel:"--lease-id <id>",usageDescription:"Lease identifier bound to tenant/run admission scope"},{key:"leaseBackend",names:["--lease-backend"],type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"],usageLabel:"--lease-backend ios-simulator|ios-instance|android-instance",usageDescription:"Lease backend for remote tenant connection admission"},{key:"force",names:["--force"],type:"boolean",usageLabel:"--force",usageDescription:"Force connection state replacement when reconnecting"},{key:"noLogin",names:["--no-login"],type:"boolean",usageLabel:"--no-login",usageDescription:"Connect: fail instead of starting implicit cloud login"},{key:"sessionLock",names:["--session-lock"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock reject|strip",usageDescription:"Lock bound-session device routing for this CLI invocation and nested batch steps"},{key:"sessionLocked",names:["--session-locked"],type:"boolean",usageLabel:"--session-locked",usageDescription:"Deprecated alias for --session-lock reject"},{key:"sessionLockConflicts",names:["--session-lock-conflicts"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock-conflicts reject|strip",usageDescription:"Deprecated alias for --session-lock"},{key:"platform",names:["--platform"],type:"enum",enumValues:["ios","macos","android","linux","apple"],usageLabel:"--platform ios|macos|android|linux|apple",usageDescription:"Platform to target (`apple` aliases the Apple automation backend)"},{key:"target",names:["--target"],type:"enum",enumValues:["mobile","tv","desktop"],usageLabel:"--target mobile|tv|desktop",usageDescription:"Device target class to match"},{key:"device",names:["--device"],type:"string",usageLabel:"--device <name>",usageDescription:"Device name to target"},{key:"udid",names:["--udid"],type:"string",usageLabel:"--udid <udid>",usageDescription:"iOS device UDID"},{key:"serial",names:["--serial"],type:"string",usageLabel:"--serial <serial>",usageDescription:"Android device serial"},{key:"surface",names:["--surface"],type:"enum",enumValues:D,usageLabel:"--surface app|frontmost-app|desktop|menubar",usageDescription:"macOS session surface for open (defaults to app)"},{key:"headless",names:["--headless"],type:"boolean",usageLabel:"--headless",usageDescription:"Boot: launch Android emulator without a GUI window"},{key:"metroHost",names:["--metro-host"],type:"string",usageLabel:"--metro-host <host>",usageDescription:"Session-scoped Metro/debug host hint"},{key:"metroPort",names:["--metro-port"],type:"int",min:1,max:65535,usageLabel:"--metro-port <port>",usageDescription:"Session-scoped Metro/debug port hint"},{key:"metroProjectRoot",names:["--project-root"],type:"string",usageLabel:"--project-root <path>",usageDescription:"metro prepare: React Native project root (default: cwd)"},{key:"metroKind",names:["--kind"],type:"enum",enumValues:["auto","react-native","expo"],usageLabel:"--kind auto|react-native|expo",usageDescription:"metro prepare: detect or force the Metro launcher kind"},{key:"metroPublicBaseUrl",names:["--public-base-url"],type:"string",usageLabel:"--public-base-url <url>",usageDescription:"metro prepare: public base URL used for direct bundle hints"},{key:"metroProxyBaseUrl",names:["--proxy-base-url"],type:"string",usageLabel:"--proxy-base-url <url>",usageDescription:"metro prepare: optional bridge origin for remote Metro access"},{key:"metroBearerToken",names:["--bearer-token"],type:"string",usageLabel:"--bearer-token <token>",usageDescription:"metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)"},{key:"metroPreparePort",names:["--port"],type:"int",min:1,max:65535,usageLabel:"--port <port>",usageDescription:"metro prepare: local Metro port (default: 8081)"},{key:"metroListenHost",names:["--listen-host"],type:"string",usageLabel:"--listen-host <host>",usageDescription:"metro prepare: host Metro listens on (default: 0.0.0.0)"},{key:"metroStatusHost",names:["--status-host"],type:"string",usageLabel:"--status-host <host>",usageDescription:"metro prepare: host used for local /status polling (default: 127.0.0.1)"},{key:"metroStartupTimeoutMs",names:["--startup-timeout-ms"],type:"int",min:1,usageLabel:"--startup-timeout-ms <ms>",usageDescription:"metro prepare: timeout while waiting for Metro to become ready"},{key:"metroProbeTimeoutMs",names:["--probe-timeout-ms"],type:"int",min:1,usageLabel:"--probe-timeout-ms <ms>",usageDescription:"metro prepare: timeout for /status and proxy bridge calls"},{key:"metroRuntimeFile",names:["--runtime-file"],type:"string",usageLabel:"--runtime-file <path>",usageDescription:"metro prepare: optional file path to persist the JSON result"},{key:"metroNoReuseExisting",names:["--no-reuse-existing"],type:"boolean",usageLabel:"--no-reuse-existing",usageDescription:"metro prepare: always start a fresh Metro process"},{key:"metroNoInstallDeps",names:["--no-install-deps"],type:"boolean",usageLabel:"--no-install-deps",usageDescription:"metro prepare: skip package-manager install when node_modules is missing"},{key:"bundleUrl",names:["--bundle-url"],type:"string",usageLabel:"--bundle-url <url>",usageDescription:"Session-scoped bundle URL hint"},{key:"launchUrl",names:["--launch-url"],type:"string",usageLabel:"--launch-url <url>",usageDescription:"Session-scoped deep link / launch URL hint"},{key:"iosSimulatorDeviceSet",names:["--ios-simulator-device-set"],type:"string",usageLabel:"--ios-simulator-device-set <path>",usageDescription:"Scope iOS simulator discovery/commands to this simulator device set"},{key:"androidDeviceAllowlist",names:["--android-device-allowlist"],type:"string",usageLabel:"--android-device-allowlist <serials>",usageDescription:"Comma/space separated Android serial allowlist for discovery/selection"},{key:"activity",names:["--activity"],type:"string",usageLabel:"--activity <component>",usageDescription:"Android app launch activity (package/Activity); not for URL opens"},{key:"launchConsole",names:["--launch-console"],type:"string",usageLabel:"--launch-console <path>",usageDescription:"open: capture the initial iOS simulator launch console window to a file"},{key:"launchArgs",names:["--launch-args"],type:"string",multiple:!0,usageLabel:"--launch-args <arg>",usageDescription:"open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag."},{key:"header",names:["--header"],type:"string",multiple:!0,usageLabel:"--header <name:value>",usageDescription:"install-from-source: repeatable HTTP header for URL downloads"},{key:"githubActionsArtifact",names:["--github-actions-artifact"],type:"string",usageLabel:"--github-actions-artifact <owner/repo:artifact>",usageDescription:"install-from-source: GitHub Actions artifact resolved by a remote daemon"},{key:"installSource",names:[],type:"string"},{key:"session",names:["--session"],type:"string",usageLabel:"--session <name>",usageDescription:"Named session"},{key:"count",names:["--count"],type:"int",min:1,max:200,usageLabel:"--count <n>",usageDescription:"Repeat count for press/swipe series"},{key:"fps",names:["--fps"],type:"int",min:1,max:120,usageLabel:"--fps <n>",usageDescription:"Record: target frames per second (iOS physical device runner)"},{key:"quality",names:["--quality"],type:"int",min:5,max:10,usageLabel:"--quality <5-10>",usageDescription:"Record: scale recording resolution from 5 (50%) through 10 (native resolution)"},{key:"hideTouches",names:["--hide-touches"],type:"boolean",usageLabel:"--hide-touches",usageDescription:"Record: skip touch-overlay post-processing for faster raw benchmark videos"},{key:"intervalMs",names:["--interval-ms"],type:"int",min:0,max:1e4,usageLabel:"--interval-ms <ms>",usageDescription:"Delay between press iterations"},{key:"delayMs",names:["--delay-ms"],type:"int",min:0,max:1e4,usageLabel:"--delay-ms <ms>",usageDescription:"Delay between typed characters"},{key:"holdMs",names:["--hold-ms"],type:"int",min:0,max:1e4,usageLabel:"--hold-ms <ms>",usageDescription:"Press hold duration for each iteration"},{key:"jitterPx",names:["--jitter-px"],type:"int",min:0,max:100,usageLabel:"--jitter-px <n>",usageDescription:"Deterministic coordinate jitter radius for press"},{key:"pixels",names:["--pixels"],type:"int",min:1,max:1e5,usageLabel:"--pixels <n>",usageDescription:"Scroll: explicit gesture distance in pixels"},{key:"doubleTap",names:["--double-tap"],type:"boolean",usageLabel:"--double-tap",usageDescription:"Use double-tap gesture per press iteration"},{key:"clickButton",names:["--button"],type:"enum",enumValues:["primary","secondary","middle"],usageLabel:"--button primary|secondary|middle",usageDescription:"Click: choose mouse button (middle reserved for future macOS support)"},{key:"backMode",names:["--in-app"],type:"enum",enumValues:["in-app","system"],setValue:"in-app",usageLabel:"--in-app",usageDescription:"Back: use app-provided back UI when available"},{key:"backMode",names:["--system"],type:"enum",enumValues:["in-app","system"],setValue:"system",usageLabel:"--system",usageDescription:"Back: use system back input or gesture when available"},{key:"pauseMs",names:["--pause-ms"],type:"int",min:0,max:1e4,usageLabel:"--pause-ms <ms>",usageDescription:"Delay between swipe iterations"},{key:"pattern",names:["--pattern"],type:"enum",enumValues:["one-way","ping-pong"],usageLabel:"--pattern one-way|ping-pong",usageDescription:"Swipe repeat pattern"},{key:"verbose",names:["--debug","--verbose","-v"],type:"boolean",usageLabel:"--debug, --verbose, -v",usageDescription:"Enable debug diagnostics; test --verbose prints per-test step timings without debug logs"},{key:"json",names:["--json"],type:"boolean",usageLabel:"--json",usageDescription:"JSON output"},{key:"help",names:["--help","-h"],type:"boolean",usageLabel:"--help, -h",usageDescription:"Print help and exit"},{key:"version",names:["--version","-V"],type:"boolean",usageLabel:"--version, -V",usageDescription:"Print version and exit"},{key:"snapshotDiff",names:["--diff"],type:"boolean",usageLabel:"--diff",usageDescription:"Snapshot: show structural diff against the previous session baseline"},{key:"saveScript",names:["--save-script"],type:"booleanOrString",usageLabel:"--save-script [path]",usageDescription:"Save session script (.ad) on close; optional custom output path"},{key:"networkInclude",names:["--include"],type:"enum",enumValues:["summary","headers","body","all"],usageLabel:"--include summary|headers|body|all",usageDescription:"Network: include headers, bodies, or both in output"},{key:"shutdown",names:["--shutdown"],type:"boolean",usageLabel:"--shutdown",usageDescription:"close: shutdown associated simulator/emulator after ending session"},{key:"relaunch",names:["--relaunch"],type:"boolean",usageLabel:"--relaunch",usageDescription:"open: terminate app process before launching it"},{key:"restart",names:["--restart"],type:"boolean",usageLabel:"--restart",usageDescription:"logs clear: stop active stream, clear logs, then start streaming again"},{key:"retainPaths",names:["--retain-paths"],type:"boolean",usageLabel:"--retain-paths",usageDescription:"install-from-source: keep materialized artifact paths after install"},{key:"retentionMs",names:["--retention-ms"],type:"int",min:1,usageLabel:"--retention-ms <ms>",usageDescription:"install-from-source: retention TTL for materialized artifact paths"},{key:"noRecord",names:["--no-record"],type:"boolean",usageLabel:"--no-record",usageDescription:"Do not record this action"},{key:"replayUpdate",names:["--update","-u"],type:"boolean",usageLabel:"--update, -u",usageDescription:"Replay: update selectors and rewrite replay file in place"},{key:"replayMaestro",names:["--maestro"],type:"boolean",usageLabel:"--maestro",usageDescription:`Replay: treat input as a Maestro YAML compatibility flow. Supported subset: ${(e=["app launch with Apple-platform launch arguments and Android/iOS simulator clearState","runFlow file/inline with when.platform, when.visible, when.notVisible, and limited when.true boolean/platform expressions","onFlowStart and onFlowComplete hooks","deterministic repeat.times","tapOn including optional, index, childOf, label, and absolute/percentage point taps","doubleTapOn and longPressOn","inputText, focused-field eraseText, and pasteText","openLink","visibility assertions and extendedWaitUntil","scroll and scrollUntilVisible","absolute/percentage swipe and swipe.label","screenshots","keyboard dismiss","basic pressKey, back, animation waits, and stopApp","ordered trusted runScript file/env scripts with http.post, json, and output variables"]).length>1?`${e.slice(0,-1).join(", ")}, and ${e.at(-1)}`:e[0]??""}. Unsupported syntax fails loudly with a link to ${L}`},{key:"replayEnv",names:["-e","--env"],type:"string",multiple:!0,usageLabel:"-e KEY=VALUE, --env KEY=VALUE",usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)"},{key:"failFast",names:["--fail-fast"],type:"boolean",usageLabel:"--fail-fast",usageDescription:"Test: stop the suite after the first failing script"},{key:"timeoutMs",names:["--timeout"],type:"int",min:1,usageLabel:"--timeout <ms>",usageDescription:"Prepare/Replay/Snapshot/Test: maximum wall-clock time for the command or attempt"},{key:"retries",names:["--retries"],type:"int",min:0,max:3,usageLabel:"--retries <n>",usageDescription:"Test: retry each failed script up to n additional times"},{key:"artifactsDir",names:["--artifacts-dir"],type:"string",usageLabel:"--artifacts-dir <path>",usageDescription:"Test: root directory for suite artifacts"},{key:"reportJunit",names:["--report-junit"],type:"string",usageLabel:"--report-junit <path>",usageDescription:"Test: write a JUnit XML report for the replay suite"},{key:"steps",names:["--steps"],type:"string",usageLabel:"--steps <json>",usageDescription:"Batch: JSON array of steps"},{key:"stepsFile",names:["--steps-file"],type:"string",usageLabel:"--steps-file <path>",usageDescription:"Batch: read steps JSON from file"},{key:"batchOnError",names:["--on-error"],type:"enum",enumValues:["stop"],usageLabel:"--on-error stop",usageDescription:"Batch: stop when a step fails"},{key:"batchMaxSteps",names:["--max-steps"],type:"int",min:1,max:1e3,usageLabel:"--max-steps <n>",usageDescription:"Batch: maximum number of allowed steps"},{key:"appsFilter",names:["--all"],type:"enum",enumValues:["user-installed","all"],setValue:"all",usageLabel:"--all",usageDescription:"Apps: include system/OEM apps"},{key:"snapshotInteractiveOnly",names:["-i"],type:"boolean",usageLabel:"-i",usageDescription:"Snapshot: interactive elements only"},{key:"snapshotCompact",names:["-c"],type:"boolean",usageLabel:"-c",usageDescription:"Snapshot: compact output (drop empty structure)"},{key:"snapshotDepth",names:["--depth","-d"],type:"int",min:0,usageLabel:"--depth, -d <depth>",usageDescription:"Snapshot: limit snapshot depth"},{key:"snapshotScope",names:["--scope","-s"],type:"string",usageLabel:"--scope, -s <scope>",usageDescription:"Snapshot: scope snapshot to label/identifier"},{key:"snapshotRaw",names:["--raw"],type:"boolean",usageLabel:"--raw",usageDescription:"Snapshot: raw node output"},{key:"snapshotForceFull",names:["--force-full"],type:"boolean",usageLabel:"--force-full",usageDescription:"Snapshot: re-emit the full tree even when unchanged"},{key:"findFirst",names:["--first"],type:"boolean",usageLabel:"--first",usageDescription:"Find: pick the first match when ambiguous"},{key:"findLast",names:["--last"],type:"boolean",usageLabel:"--last",usageDescription:"Find: pick the last match when ambiguous"},{key:"out",names:["--out"],type:"string",usageLabel:"--out <path>",usageDescription:"Output path"},{key:"overlayRefs",names:["--overlay-refs"],type:"boolean",usageLabel:"--overlay-refs",usageDescription:"Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide"},...t,{key:"baseline",names:["--baseline","-b"],type:"string",usageLabel:"--baseline, -b <path>",usageDescription:"Diff screenshot: path to baseline image file"},{key:"threshold",names:["--threshold"],type:"string",usageLabel:"--threshold <0-1>",usageDescription:"Diff screenshot: color distance threshold (default 0.1)"}],F=new Set(["json","config","remoteConfig","stateDir","daemonBaseUrl","daemonAuthToken","daemonTransport","daemonServerMode","tenant","sessionIsolation","runId","leaseId","leaseBackend","sessionLock","sessionLocked","sessionLockConflicts","help","version","verbose","platform","target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist","session","noRecord"]),T=new Map;for(let e of P)for(let s of e.names)T.set(s,e);function _(e){return T.get(e)}function C(){return P}let I={auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"]},connect:{usageOverride:"connect [--remote-config <path>] [--tenant <id>] [--run-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",summary:"Connect to remote daemon",allowedFlags:["force","noLogin",...M,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",allowedFlags:["shutdown"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools [...args]",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Profile React Native performance and component renders",positionalArgs:["args?"],allowsExtraPositionals:!0}},j={boot:{summary:"Boot target device/simulator",allowedFlags:["headless"]},prepare:{usageOverride:"prepare ios-runner --platform ios|macos [--timeout <ms>]",listUsageOverride:"prepare ios-runner --platform ios|macos",helpDescription:"Prepare platform helper infrastructure. ios-runner builds/reuses, starts, and health-checks the XCTest runner so later Apple snapshots and interactions do not pay first-use startup cost. In CI, run it after boot/install and before replay/test.",summary:"Prepare platform helpers",positionalArgs:["ios-runner"],allowedFlags:["timeoutMs"]},open:{helpDescription:"Boot device/simulator; optionally launch app or deep link URL (macOS also supports --surface app|frontmost-app|desktop|menubar)",summary:"Open an app, deep link or URL, save replays",positionalArgs:["appOrUrl?","url?"],allowedFlags:["activity","launchConsole","launchArgs","saveScript","relaunch","surface"]},close:{positionalArgs:["app?"],allowedFlags:["saveScript","shutdown"]},reinstall:{positionalArgs:["app","path"]},install:{positionalArgs:["app","path"]},"install-from-source":{usageOverride:"install-from-source <url> | install-from-source --github-actions-artifact <owner/repo:artifact>",listUsageOverride:"install-from-source <url> | install-from-source --github-actions-artifact",helpDescription:"Install app from a URL or remote-resolved source",summary:"Install app from a source",positionalArgs:["url?"],allowedFlags:["header","githubActionsArtifact","installSource","retainPaths","retentionMs"]},apps:{helpDescription:"List user-installed apps; use --all to include system/OEM apps",summary:"List installed apps",allowedFlags:["appsFilter"],defaults:{appsFilter:o}},push:{positionalArgs:["bundleOrPackage","payloadOrJson"]},snapshot:{usageOverride:"snapshot [--diff] [-i] [-c] [-d <depth>] [-s <scope>] [--raw] [--force-full] [--timeout <ms>]",helpDescription:"Capture accessibility tree or diff against the previous session baseline",allowedFlags:["snapshotDiff",...x,"snapshotForceFull","timeoutMs"]},diff:{usageOverride:"diff snapshot | diff screenshot --baseline <path> [current.png] [--out <diff.png>] [--threshold <0-1>] [--overlay-refs]",helpDescription:"Diff accessibility snapshot or compare screenshots pixel-by-pixel",summary:"Diff snapshot or screenshot",positionalArgs:["kind","current?"],allowedFlags:[...x,"baseline","threshold","out","overlayRefs"]},screenshot:{helpDescription:"Capture screenshot (macOS app sessions default to the app window; use --fullscreen for full desktop, --max-size to downscale, --overlay-refs to annotate current refs, or --no-stabilize for low-latency Android capture loops)",positionalArgs:["path?"],allowedFlags:a},appstate:{helpDescription:"Show foreground app/activity"},metro:{usageOverride:"metro prepare (--public-base-url <url> | --proxy-base-url <url>) [--project-root <path>] [--port <port>] [--kind auto|react-native|expo]\n agent-device metro reload [--metro-host <host>] [--metro-port <port>] [--bundle-url <url>]",listUsageOverride:"metro prepare --public-base-url <url> | --proxy-base-url <url>; metro reload",helpDescription:"Prepare a local Metro runtime or ask Metro to reload connected React Native apps",summary:"Prepare Metro or reload apps",positionalArgs:["prepare|reload"],allowedFlags:[...E,...M]},clipboard:{usageOverride:"clipboard read | clipboard write <text>",listUsageOverride:"clipboard read | clipboard write <text>",helpDescription:"Read or write device clipboard text",positionalArgs:["read|write","text?"],allowsExtraPositionals:!0},keyboard:{usageOverride:"keyboard [status|get|dismiss|enter|return]",helpDescription:"Inspect Android keyboard visibility/type or press/dismiss the device keyboard",summary:"Inspect, press, or dismiss the device keyboard",positionalArgs:["action?"]},back:{usageOverride:"back [--in-app|--system]",allowedFlags:["backMode"]},rotate:{usageOverride:"rotate <portrait|portrait-upside-down|landscape-left|landscape-right>",helpDescription:"Rotate device orientation on iOS and Android",positionalArgs:["orientation"]},wait:{usageOverride:"wait <ms>|text <text>|@ref|<selector> [timeoutMs]",positionalArgs:["durationOrSelector","timeoutMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},get:{usageOverride:"get text|attrs <@ref|selector>",positionalArgs:["subcommand","target"],allowedFlags:[...A]},find:{usageOverride:"find <locator|text> <action> [value] [--first|--last]",helpDescription:"Find by text/label/value/role/id and run action",summary:"Find an element and act",positionalArgs:["query","action","value?"],allowsExtraPositionals:!0,allowedFlags:["snapshotDepth","snapshotRaw","findFirst","findLast"]},is:{positionalArgs:["predicate","selector","value?"],allowsExtraPositionals:!0,allowedFlags:[...A]},alert:{usageOverride:"alert [get|accept|dismiss|wait] [timeout]",positionalArgs:["action?","timeout?"]},click:{usageOverride:"click <x y|@ref|selector>",positionalArgs:["target"],allowsExtraPositionals:!0,allowedFlags:[...R,"clickButton",...A]},replay:{positionalArgs:["path"],allowedFlags:["replayMaestro",...U,"timeoutMs"]},test:{usageOverride:"test <path-or-glob>...",listUsageOverride:"test <path-or-glob>...",helpDescription:"Run one or more replay scripts as a serial test suite",summary:"Run replay test suites",positionalArgs:["pathOrGlob"],allowsExtraPositionals:!0,allowedFlags:["replayMaestro",...U,"failFast","timeoutMs","retries","artifactsDir","reportJunit"]},batch:{usageOverride:"batch [--steps <json> | --steps-file <path>]",listUsageOverride:"batch --steps <json> | --steps-file <path>",helpDescription:"Execute multiple commands in one daemon request",summary:"Run multiple commands",allowedFlags:["steps","stepsFile","batchOnError","batchMaxSteps","out"]},press:{usageOverride:"press <x y|@ref|selector>",positionalArgs:["targetOrX","y?"],allowsExtraPositionals:!0,allowedFlags:[...R,...A]},longpress:{usageOverride:"longpress <x y|@ref|selector> [durationMs]",positionalArgs:["targetOrX","yOrDurationMs?","durationMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},swipe:{helpDescription:"Swipe coordinates with optional repeat pattern",positionalArgs:["x1","y1","x2","y2","durationMs?"],allowedFlags:["count","pauseMs","pattern"]},gesture:{usageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",listUsageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",helpDescription:"Run touch gestures: pan <x> <y> <dx> <dy> [durationMs], fling <up|down|left|right> <x> <y> [distance] [durationMs], swipe <left|right|left-edge|right-edge> [durationMs], pinch <scale> [x] [y], rotate <degrees> [x] [y] [velocity], or transform <x> <y> <dx> <dy> <scale> <degrees> [durationMs]",summary:"Run pan, fling, swipe, pinch, rotate, or transform gestures",positionalArgs:["pan|fling|swipe|pinch|rotate|transform","args?"],allowsExtraPositionals:!0},focus:{positionalArgs:["x","y"]},type:{positionalArgs:["text"],allowsExtraPositionals:!0,allowedFlags:["delayMs"]},fill:{usageOverride:"fill <x> <y> <text> | fill <@ref|selector> <text>",positionalArgs:["targetOrX","yOrText","text?"],allowsExtraPositionals:!0,allowedFlags:[...A,"delayMs"]},scroll:{usageOverride:"scroll <direction|top|bottom> [amount] [--pixels <n>]",helpDescription:"Scroll in direction, or verify hidden content and scroll toward top/bottom",summary:"Scroll in a direction or to an edge",positionalArgs:["directionOrEdge","amount?"],allowedFlags:["pixels"]},"trigger-app-event":{usageOverride:"trigger-app-event <event> [payloadJson]",positionalArgs:["event","payloadJson?"]},record:{usageOverride:"record start [path] [--fps <n>] [--quality <5-10>] [--hide-touches] | record stop",listUsageOverride:"record start [path] | record stop",helpDescription:"Start/stop screen recording; Android recordings longer than the 180s adb screenrecord limit are returned as multiple MP4 chunks",summary:"Start or stop screen recording",positionalArgs:["start|stop","path?"],allowedFlags:["fps","quality","hideTouches"]},"react-native":{usageOverride:"react-native dismiss-overlay",listUsageOverride:"react-native dismiss-overlay",positionalArgs:["dismiss-overlay"]},trace:{usageOverride:"trace start <path> | trace stop <path>",listUsageOverride:"trace start <path> | trace stop <path>",helpDescription:"Start/stop trace log capture; when an artifact path is requested, pass the same positional path to start and stop",summary:"Start or stop trace capture",positionalArgs:["start|stop","path?"]},logs:{usageOverride:"logs path | logs start | logs stop | logs clear [--restart] | logs doctor | logs mark [message...]",helpDescription:"Session app log info, start/stop streaming, diagnostics, and markers",summary:"Manage session app logs",positionalArgs:["path|start|stop|clear|doctor|mark","message?"],allowsExtraPositionals:!0,allowedFlags:["restart"]},network:{usageOverride:"network dump [limit] [summary|headers|body|all] [--include summary|headers|body|all] | network log [limit] [summary|headers|body|all] [--include summary|headers|body|all]",helpDescription:"Dump recent HTTP(s) traffic parsed from the session app log",summary:"Show recent HTTP traffic",positionalArgs:["dump|log","limit?","include?"],allowedFlags:["networkInclude"]},settings:{usageOverride:b,listUsageOverride:"settings [area] [options]",helpDescription:"Toggle OS settings, animation scales, appearance, and app permissions (macOS supports only settings appearance <light|dark|toggle> and settings permission <grant|reset> <accessibility|screen-recording|input-monitoring>; wifi|airplane|location|animations remain unsupported on macOS; mobile permission actions use the active session app)",summary:"Change OS settings and app permissions",positionalArgs:["setting","state","target?","mode?"]},session:{usageOverride:"session list",positionalArgs:["list?"]}},N=new Map(r().map(e=>[e.name,{helpDescription:e.description}]));function V(e){if(e)return B(e)}function $(e){let s=B(e);if(!s)throw Error(`Missing command schema for ${e}`);return s}function B(e){let s=Object.hasOwn(I,e)?I[e]:void 0;if(s)return s;let t=N.get(e),a=Object.hasOwn(j,e)?j[e]:void 0;if(t)return a?{...t,...a}:t}function K(e,s){let t=V(e);if(!t?.defaults)return!1;let a=!1;for(let[e,o]of Object.entries(t.defaults))void 0===s[e]&&(s[e]=o,a=!0);return a}export{F as GLOBAL_FLAG_KEYS,L as MAESTRO_COMPAT_TRACKER_URL,O as MAESTRO_NEW_ISSUE_URL,f as SETTINGS_INVALID_ARGS_MESSAGE,K as applyCommandDefaults,$ as getCliCommandSchema,V as getCommandSchema,_ as getFlagDefinition,C as getFlagDefinitions,v as getUnsupportedMacOsSettingMessage,k as isMacOsSettingSupported,w as parseSessionSurface};
1
+ var e;import{AppError as s}from"./9152.js";import{SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS as t,SCREENSHOT_COMMAND_FLAG_KEYS as a}from"./5310.js";import{DEFAULT_APPS_FILTER as o}from"./1393.js";import{listCommandDescriptionMetadata as r}from"./2805.js";let i="<wifi|airplane|location> <on|off>",n="location set <lat> <lon>",l="animations <on|off>",p="appearance <light|dark|toggle>",u="faceid <match|nonmatch|enroll|unenroll>",c="touchid <match|nonmatch|enroll|unenroll>",d="fingerprint <match|nonmatch>",m="clear-app-state [app-id]",g="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",h="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",y=`macOS supports only settings ${p} and settings ${h}. wifi|airplane|location|animations remain unsupported on macOS.`,f=`settings ${i} | settings ${n} | settings ${l} | settings ${p} | settings ${u} | settings ${c} | settings ${d} | settings ${m} | settings ${g} | settings ${h}`,b=`settings requires ${i}, ${n}, ${l}, ${p}, ${u}, ${c}, ${d}, ${m}, ${g}, or ${h}`;function k(e){let s=e.trim().toLowerCase();return"appearance"===s||"permission"===s}function v(e){return`Unsupported macOS setting: ${e}. ${y}`}let D=["app","frontmost-app","desktop","menubar"];function w(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new s("INVALID_ARGS",`Invalid surface: ${e}. Use ${D.join("|")}.`)}let L="https://github.com/callstackincubator/agent-device/issues/558",O="https://github.com/callstackincubator/agent-device/issues/new";function S(...e){return e}let x=S("snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"),A=S("snapshotDepth","snapshotScope","snapshotRaw"),M=S("metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps"),E=S("metroHost","metroPort","bundleUrl"),R=S("count","intervalMs","holdMs","jitterPx","doubleTap"),U=S("replayUpdate","replayEnv"),P=[{key:"config",names:["--config"],type:"string",usageLabel:"--config <path>",usageDescription:"Load CLI defaults from a specific config file"},{key:"remoteConfig",names:["--remote-config"],type:"string",usageLabel:"--remote-config <path>",usageDescription:"Load remote host + Metro workflow settings from a specific profile file"},{key:"stateDir",names:["--state-dir"],type:"string",usageLabel:"--state-dir <path>",usageDescription:"Daemon state directory (defaults to ~/.agent-device)"},{key:"daemonBaseUrl",names:["--daemon-base-url"],type:"string",usageLabel:"--daemon-base-url <url>",usageDescription:"Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)"},{key:"daemonAuthToken",names:["--daemon-auth-token"],type:"string",usageLabel:"--daemon-auth-token <token>",usageDescription:"Remote HTTP daemon auth token (sent as request token and bearer header)"},{key:"daemonTransport",names:["--daemon-transport"],type:"enum",enumValues:["auto","socket","http"],usageLabel:"--daemon-transport auto|socket|http",usageDescription:"Daemon client transport preference"},{key:"daemonServerMode",names:["--daemon-server-mode"],type:"enum",enumValues:["socket","http","dual"],usageLabel:"--daemon-server-mode socket|http|dual",usageDescription:"Daemon server mode used when spawning daemon"},{key:"tenant",names:["--tenant"],type:"string",usageLabel:"--tenant <id>",usageDescription:"Tenant scope identifier for isolated daemon sessions"},{key:"sessionIsolation",names:["--session-isolation"],type:"enum",enumValues:["none","tenant"],usageLabel:"--session-isolation none|tenant",usageDescription:"Session isolation strategy (tenant prefixes session namespace)"},{key:"runId",names:["--run-id"],type:"string",usageLabel:"--run-id <id>",usageDescription:"Run identifier used for tenant lease admission checks"},{key:"leaseId",names:["--lease-id"],type:"string",usageLabel:"--lease-id <id>",usageDescription:"Lease identifier bound to tenant/run admission scope"},{key:"leaseBackend",names:["--lease-backend"],type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"],usageLabel:"--lease-backend ios-simulator|ios-instance|android-instance",usageDescription:"Lease backend for remote tenant connection admission"},{key:"force",names:["--force"],type:"boolean",usageLabel:"--force",usageDescription:"Force connection state replacement when reconnecting"},{key:"noLogin",names:["--no-login"],type:"boolean",usageLabel:"--no-login",usageDescription:"Connect: fail instead of starting implicit cloud login"},{key:"sessionLock",names:["--session-lock"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock reject|strip",usageDescription:"Lock bound-session device routing for this CLI invocation and nested batch steps"},{key:"sessionLocked",names:["--session-locked"],type:"boolean",usageLabel:"--session-locked",usageDescription:"Deprecated alias for --session-lock reject"},{key:"sessionLockConflicts",names:["--session-lock-conflicts"],type:"enum",enumValues:["reject","strip"],usageLabel:"--session-lock-conflicts reject|strip",usageDescription:"Deprecated alias for --session-lock"},{key:"platform",names:["--platform"],type:"enum",enumValues:["ios","macos","android","linux","apple"],usageLabel:"--platform ios|macos|android|linux|apple",usageDescription:"Platform to target (`apple` aliases the Apple automation backend)"},{key:"target",names:["--target"],type:"enum",enumValues:["mobile","tv","desktop"],usageLabel:"--target mobile|tv|desktop",usageDescription:"Device target class to match"},{key:"device",names:["--device"],type:"string",usageLabel:"--device <name>",usageDescription:"Device name to target"},{key:"udid",names:["--udid"],type:"string",usageLabel:"--udid <udid>",usageDescription:"iOS device UDID"},{key:"serial",names:["--serial"],type:"string",usageLabel:"--serial <serial>",usageDescription:"Android device serial"},{key:"surface",names:["--surface"],type:"enum",enumValues:D,usageLabel:"--surface app|frontmost-app|desktop|menubar",usageDescription:"macOS session surface for open (defaults to app)"},{key:"headless",names:["--headless"],type:"boolean",usageLabel:"--headless",usageDescription:"Boot: launch Android emulator without a GUI window"},{key:"metroHost",names:["--metro-host"],type:"string",usageLabel:"--metro-host <host>",usageDescription:"Session-scoped Metro/debug host hint"},{key:"metroPort",names:["--metro-port"],type:"int",min:1,max:65535,usageLabel:"--metro-port <port>",usageDescription:"Session-scoped Metro/debug port hint"},{key:"metroProjectRoot",names:["--project-root"],type:"string",usageLabel:"--project-root <path>",usageDescription:"metro prepare: React Native project root (default: cwd)"},{key:"metroKind",names:["--kind"],type:"enum",enumValues:["auto","react-native","expo"],usageLabel:"--kind auto|react-native|expo",usageDescription:"metro prepare: detect or force the Metro launcher kind"},{key:"metroPublicBaseUrl",names:["--public-base-url"],type:"string",usageLabel:"--public-base-url <url>",usageDescription:"metro prepare: public base URL used for direct bundle hints"},{key:"metroProxyBaseUrl",names:["--proxy-base-url"],type:"string",usageLabel:"--proxy-base-url <url>",usageDescription:"metro prepare: optional bridge origin for remote Metro access"},{key:"metroBearerToken",names:["--bearer-token"],type:"string",usageLabel:"--bearer-token <token>",usageDescription:"metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)"},{key:"metroPreparePort",names:["--port"],type:"int",min:1,max:65535,usageLabel:"--port <port>",usageDescription:"metro prepare: local Metro port (default: 8081)"},{key:"metroListenHost",names:["--listen-host"],type:"string",usageLabel:"--listen-host <host>",usageDescription:"metro prepare: host Metro listens on (default: 0.0.0.0)"},{key:"metroStatusHost",names:["--status-host"],type:"string",usageLabel:"--status-host <host>",usageDescription:"metro prepare: host used for local /status polling (default: 127.0.0.1)"},{key:"metroStartupTimeoutMs",names:["--startup-timeout-ms"],type:"int",min:1,usageLabel:"--startup-timeout-ms <ms>",usageDescription:"metro prepare: timeout while waiting for Metro to become ready"},{key:"metroProbeTimeoutMs",names:["--probe-timeout-ms"],type:"int",min:1,usageLabel:"--probe-timeout-ms <ms>",usageDescription:"metro prepare: timeout for /status and proxy bridge calls"},{key:"metroRuntimeFile",names:["--runtime-file"],type:"string",usageLabel:"--runtime-file <path>",usageDescription:"metro prepare: optional file path to persist the JSON result"},{key:"metroNoReuseExisting",names:["--no-reuse-existing"],type:"boolean",usageLabel:"--no-reuse-existing",usageDescription:"metro prepare: always start a fresh Metro process"},{key:"metroNoInstallDeps",names:["--no-install-deps"],type:"boolean",usageLabel:"--no-install-deps",usageDescription:"metro prepare: skip package-manager install when node_modules is missing"},{key:"bundleUrl",names:["--bundle-url"],type:"string",usageLabel:"--bundle-url <url>",usageDescription:"Session-scoped bundle URL hint"},{key:"launchUrl",names:["--launch-url"],type:"string",usageLabel:"--launch-url <url>",usageDescription:"Session-scoped deep link / launch URL hint"},{key:"iosSimulatorDeviceSet",names:["--ios-simulator-device-set"],type:"string",usageLabel:"--ios-simulator-device-set <path>",usageDescription:"Scope iOS simulator discovery/commands to this simulator device set"},{key:"androidDeviceAllowlist",names:["--android-device-allowlist"],type:"string",usageLabel:"--android-device-allowlist <serials>",usageDescription:"Comma/space separated Android serial allowlist for discovery/selection"},{key:"activity",names:["--activity"],type:"string",usageLabel:"--activity <component>",usageDescription:"Android app launch activity (package/Activity); not for URL opens"},{key:"launchConsole",names:["--launch-console"],type:"string",usageLabel:"--launch-console <path>",usageDescription:"open: capture the initial iOS simulator launch console window to a file"},{key:"launchArgs",names:["--launch-args"],type:"string",multiple:!0,usageLabel:"--launch-args <arg>",usageDescription:"open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag."},{key:"header",names:["--header"],type:"string",multiple:!0,usageLabel:"--header <name:value>",usageDescription:"install-from-source: repeatable HTTP header for URL downloads"},{key:"githubActionsArtifact",names:["--github-actions-artifact"],type:"string",usageLabel:"--github-actions-artifact <owner/repo:artifact>",usageDescription:"install-from-source: GitHub Actions artifact resolved by a remote daemon"},{key:"installSource",names:[],type:"string"},{key:"session",names:["--session"],type:"string",usageLabel:"--session <name>",usageDescription:"Named session"},{key:"count",names:["--count"],type:"int",min:1,max:200,usageLabel:"--count <n>",usageDescription:"Repeat count for press/swipe series"},{key:"fps",names:["--fps"],type:"int",min:1,max:120,usageLabel:"--fps <n>",usageDescription:"Record: target frames per second (iOS physical device runner)"},{key:"quality",names:["--quality"],type:"int",min:5,max:10,usageLabel:"--quality <5-10>",usageDescription:"Record: scale recording resolution from 5 (50%) through 10 (native resolution)"},{key:"hideTouches",names:["--hide-touches"],type:"boolean",usageLabel:"--hide-touches",usageDescription:"Record: skip touch-overlay post-processing for faster raw benchmark videos"},{key:"intervalMs",names:["--interval-ms"],type:"int",min:0,max:1e4,usageLabel:"--interval-ms <ms>",usageDescription:"Delay between press iterations"},{key:"delayMs",names:["--delay-ms"],type:"int",min:0,max:1e4,usageLabel:"--delay-ms <ms>",usageDescription:"Delay between typed characters"},{key:"holdMs",names:["--hold-ms"],type:"int",min:0,max:1e4,usageLabel:"--hold-ms <ms>",usageDescription:"Press hold duration for each iteration"},{key:"jitterPx",names:["--jitter-px"],type:"int",min:0,max:100,usageLabel:"--jitter-px <n>",usageDescription:"Deterministic coordinate jitter radius for press"},{key:"pixels",names:["--pixels"],type:"int",min:1,max:1e5,usageLabel:"--pixels <n>",usageDescription:"Scroll: explicit gesture distance in pixels"},{key:"doubleTap",names:["--double-tap"],type:"boolean",usageLabel:"--double-tap",usageDescription:"Use double-tap gesture per press iteration"},{key:"clickButton",names:["--button"],type:"enum",enumValues:["primary","secondary","middle"],usageLabel:"--button primary|secondary|middle",usageDescription:"Click: choose mouse button (middle reserved for future macOS support)"},{key:"backMode",names:["--in-app"],type:"enum",enumValues:["in-app","system"],setValue:"in-app",usageLabel:"--in-app",usageDescription:"Back: use app-provided back UI when available"},{key:"backMode",names:["--system"],type:"enum",enumValues:["in-app","system"],setValue:"system",usageLabel:"--system",usageDescription:"Back: use system back input or gesture when available"},{key:"pauseMs",names:["--pause-ms"],type:"int",min:0,max:1e4,usageLabel:"--pause-ms <ms>",usageDescription:"Delay between swipe iterations"},{key:"pattern",names:["--pattern"],type:"enum",enumValues:["one-way","ping-pong"],usageLabel:"--pattern one-way|ping-pong",usageDescription:"Swipe repeat pattern"},{key:"verbose",names:["--debug","--verbose","-v"],type:"boolean",usageLabel:"--debug, --verbose, -v",usageDescription:"Enable debug diagnostics; test --verbose prints per-test step timings without debug logs"},{key:"json",names:["--json"],type:"boolean",usageLabel:"--json",usageDescription:"JSON output"},{key:"help",names:["--help","-h"],type:"boolean",usageLabel:"--help, -h",usageDescription:"Print help and exit"},{key:"version",names:["--version","-V"],type:"boolean",usageLabel:"--version, -V",usageDescription:"Print version and exit"},{key:"snapshotDiff",names:["--diff"],type:"boolean",usageLabel:"--diff",usageDescription:"Snapshot: show structural diff against the previous session baseline"},{key:"saveScript",names:["--save-script"],type:"booleanOrString",usageLabel:"--save-script [path]",usageDescription:"Save session script (.ad) on close; optional custom output path"},{key:"networkInclude",names:["--include"],type:"enum",enumValues:["summary","headers","body","all"],usageLabel:"--include summary|headers|body|all",usageDescription:"Network: include headers, bodies, or both in output"},{key:"shutdown",names:["--shutdown"],type:"boolean",usageLabel:"--shutdown",usageDescription:"close: shutdown associated simulator/emulator after ending session"},{key:"relaunch",names:["--relaunch"],type:"boolean",usageLabel:"--relaunch",usageDescription:"open: terminate app process before launching it"},{key:"restart",names:["--restart"],type:"boolean",usageLabel:"--restart",usageDescription:"logs clear: stop active stream, clear logs, then start streaming again"},{key:"retainPaths",names:["--retain-paths"],type:"boolean",usageLabel:"--retain-paths",usageDescription:"install-from-source: keep materialized artifact paths after install"},{key:"retentionMs",names:["--retention-ms"],type:"int",min:1,usageLabel:"--retention-ms <ms>",usageDescription:"install-from-source: retention TTL for materialized artifact paths"},{key:"noRecord",names:["--no-record"],type:"boolean",usageLabel:"--no-record",usageDescription:"Do not record this action"},{key:"replayUpdate",names:["--update","-u"],type:"boolean",usageLabel:"--update, -u",usageDescription:"Replay: update selectors and rewrite replay file in place"},{key:"replayMaestro",names:["--maestro"],type:"boolean",usageLabel:"--maestro",usageDescription:`Replay: treat input as a Maestro YAML compatibility flow. Supported subset: ${(e=["app launch with Apple-platform launch arguments and Android/iOS simulator clearState","runFlow file/inline with when.platform, when.visible, when.notVisible, and limited when.true boolean/platform expressions","onFlowStart and onFlowComplete hooks","deterministic repeat.times","tapOn including optional, index, childOf, label, and absolute/percentage point taps","doubleTapOn and longPressOn","inputText, focused-field eraseText, and pasteText","openLink","visibility assertions and extendedWaitUntil","scroll and scrollUntilVisible","absolute/percentage swipe and swipe.label","screenshots","keyboard dismiss","basic pressKey, back, animation waits, and stopApp","ordered trusted runScript file/env scripts with http.post, json, and output variables"]).length>1?`${e.slice(0,-1).join(", ")}, and ${e.at(-1)}`:e[0]??""}. Unsupported syntax fails loudly with a link to ${L}`},{key:"replayEnv",names:["-e","--env"],type:"string",multiple:!0,usageLabel:"-e KEY=VALUE, --env KEY=VALUE",usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)"},{key:"failFast",names:["--fail-fast"],type:"boolean",usageLabel:"--fail-fast",usageDescription:"Test: stop the suite after the first failing script; with sharding, each shard stops independently"},{key:"timeoutMs",names:["--timeout"],type:"int",min:1,usageLabel:"--timeout <ms>",usageDescription:"Prepare/Replay/Snapshot/Test: maximum wall-clock time for the command or attempt"},{key:"retries",names:["--retries"],type:"int",min:0,max:3,usageLabel:"--retries <n>",usageDescription:"Test: retry each failed script up to n additional times"},{key:"artifactsDir",names:["--artifacts-dir"],type:"string",usageLabel:"--artifacts-dir <path>",usageDescription:"Test: root directory for suite artifacts"},{key:"reportJunit",names:["--report-junit"],type:"string",usageLabel:"--report-junit <path>",usageDescription:"Test: write a JUnit XML report for the replay suite"},{key:"shardAll",names:["--shard-all"],type:"int",min:1,usageLabel:"--shard-all <n>",usageDescription:"Test: run the full suite on each of n devices; AD_SHARD_INDEX is zero-based"},{key:"shardSplit",names:["--shard-split"],type:"int",min:1,usageLabel:"--shard-split <n>",usageDescription:"Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based"},{key:"steps",names:["--steps"],type:"string",usageLabel:"--steps <json>",usageDescription:"Batch: JSON array of steps"},{key:"stepsFile",names:["--steps-file"],type:"string",usageLabel:"--steps-file <path>",usageDescription:"Batch: read steps JSON from file"},{key:"batchOnError",names:["--on-error"],type:"enum",enumValues:["stop"],usageLabel:"--on-error stop",usageDescription:"Batch: stop when a step fails"},{key:"batchMaxSteps",names:["--max-steps"],type:"int",min:1,max:1e3,usageLabel:"--max-steps <n>",usageDescription:"Batch: maximum number of allowed steps"},{key:"appsFilter",names:["--all"],type:"enum",enumValues:["user-installed","all"],setValue:"all",usageLabel:"--all",usageDescription:"Apps: include system/OEM apps"},{key:"snapshotInteractiveOnly",names:["-i"],type:"boolean",usageLabel:"-i",usageDescription:"Snapshot: interactive elements only"},{key:"snapshotCompact",names:["-c"],type:"boolean",usageLabel:"-c",usageDescription:"Snapshot: compact output (drop empty structure)"},{key:"snapshotDepth",names:["--depth","-d"],type:"int",min:0,usageLabel:"--depth, -d <depth>",usageDescription:"Snapshot: limit snapshot depth"},{key:"snapshotScope",names:["--scope","-s"],type:"string",usageLabel:"--scope, -s <scope>",usageDescription:"Snapshot: scope snapshot to label/identifier"},{key:"snapshotRaw",names:["--raw"],type:"boolean",usageLabel:"--raw",usageDescription:"Snapshot: raw node output"},{key:"snapshotForceFull",names:["--force-full"],type:"boolean",usageLabel:"--force-full",usageDescription:"Snapshot: re-emit the full tree even when unchanged"},{key:"findFirst",names:["--first"],type:"boolean",usageLabel:"--first",usageDescription:"Find: pick the first match when ambiguous"},{key:"findLast",names:["--last"],type:"boolean",usageLabel:"--last",usageDescription:"Find: pick the last match when ambiguous"},{key:"out",names:["--out"],type:"string",usageLabel:"--out <path>",usageDescription:"Output path"},{key:"overlayRefs",names:["--overlay-refs"],type:"boolean",usageLabel:"--overlay-refs",usageDescription:"Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide"},...t,{key:"baseline",names:["--baseline","-b"],type:"string",usageLabel:"--baseline, -b <path>",usageDescription:"Diff screenshot: path to baseline image file"},{key:"threshold",names:["--threshold"],type:"string",usageLabel:"--threshold <0-1>",usageDescription:"Diff screenshot: color distance threshold (default 0.1)"}],T=new Set(["json","config","remoteConfig","stateDir","daemonBaseUrl","daemonAuthToken","daemonTransport","daemonServerMode","tenant","sessionIsolation","runId","leaseId","leaseBackend","sessionLock","sessionLocked","sessionLockConflicts","help","version","verbose","platform","target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist","session","noRecord"]),F=new Map;for(let e of P)for(let s of e.names)F.set(s,e);function _(e){return F.get(e)}function C(){return P}let I={auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"]},connect:{usageOverride:"connect [--remote-config <path>] [--tenant <id>] [--run-id <id>] [--lease-backend <backend>] [--force] [--no-login]",helpDescription:"Connect to a remote daemon, authenticate when needed, and save remote session state. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.",summary:"Connect to remote daemon",allowedFlags:["force","noLogin",...M,"launchUrl"]},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"]},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",allowedFlags:["shutdown"]},mcp:{helpDescription:"Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.",summary:"Start MCP server"},"react-devtools":{usageOverride:"react-devtools [...args]",listUsageOverride:"react-devtools [...args]",helpDescription:"Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis",summary:"Profile React Native performance and component renders",positionalArgs:["args?"],allowsExtraPositionals:!0}},j={boot:{summary:"Boot target device/simulator",allowedFlags:["headless"]},prepare:{usageOverride:"prepare ios-runner --platform ios|macos [--timeout <ms>]",listUsageOverride:"prepare ios-runner --platform ios|macos",helpDescription:"Prepare platform helper infrastructure. ios-runner builds/reuses, starts, and health-checks the XCTest runner so later Apple snapshots and interactions do not pay first-use startup cost. In CI, run it after boot/install and before replay/test. Runner build/start output is written to the session runner.log; daemon.log is for daemon lifecycle/startup issues.",summary:"Prepare platform helpers",positionalArgs:["ios-runner"],allowedFlags:["timeoutMs"]},open:{helpDescription:"Boot device/simulator; optionally launch app or deep link URL (macOS also supports --surface app|frontmost-app|desktop|menubar)",summary:"Open an app, deep link or URL, save replays",positionalArgs:["appOrUrl?","url?"],allowedFlags:["activity","launchConsole","launchArgs","saveScript","relaunch","surface"]},close:{positionalArgs:["app?"],allowedFlags:["saveScript","shutdown"]},reinstall:{positionalArgs:["app","path"]},install:{positionalArgs:["app","path"]},"install-from-source":{usageOverride:"install-from-source <url> | install-from-source --github-actions-artifact <owner/repo:artifact>",listUsageOverride:"install-from-source <url> | install-from-source --github-actions-artifact",helpDescription:"Install app from a URL or remote-resolved source",summary:"Install app from a source",positionalArgs:["url?"],allowedFlags:["header","githubActionsArtifact","installSource","retainPaths","retentionMs"]},apps:{helpDescription:"List user-installed apps; use --all to include system/OEM apps",summary:"List installed apps",allowedFlags:["appsFilter"],defaults:{appsFilter:o}},push:{positionalArgs:["bundleOrPackage","payloadOrJson"]},snapshot:{usageOverride:"snapshot [--diff] [-i] [-c] [-d <depth>] [-s <scope>] [--raw] [--force-full] [--timeout <ms>]",helpDescription:"Capture accessibility tree or diff against the previous session baseline",allowedFlags:["snapshotDiff",...x,"snapshotForceFull","timeoutMs"]},diff:{usageOverride:"diff snapshot | diff screenshot --baseline <path> [current.png] [--out <diff.png>] [--threshold <0-1>] [--overlay-refs]",helpDescription:"Diff accessibility snapshot or compare screenshots pixel-by-pixel",summary:"Diff snapshot or screenshot",positionalArgs:["kind","current?"],allowedFlags:[...x,"baseline","threshold","out","overlayRefs"]},screenshot:{helpDescription:"Capture screenshot (macOS app sessions default to the app window; use --fullscreen for full desktop, --max-size to downscale, --overlay-refs to annotate current refs, or --no-stabilize for low-latency Android capture loops)",positionalArgs:["path?"],allowedFlags:a},appstate:{helpDescription:"Show foreground app/activity"},perf:{usageOverride:"perf [metrics|frames] [sample]",listUsageOverride:"perf [metrics|frames]",helpDescription:"Show session performance metrics or focused frame/jank health. Bare perf and metrics are aliases for perf metrics.",summary:"Show session performance and frame health",positionalArgs:["area?","action?"]},metro:{usageOverride:"metro prepare (--public-base-url <url> | --proxy-base-url <url>) [--project-root <path>] [--port <port>] [--kind auto|react-native|expo]\n agent-device metro reload [--metro-host <host>] [--metro-port <port>] [--bundle-url <url>]",listUsageOverride:"metro prepare --public-base-url <url> | --proxy-base-url <url>; metro reload",helpDescription:"Prepare a local Metro runtime or ask Metro to reload connected React Native apps",summary:"Prepare Metro or reload apps",positionalArgs:["prepare|reload"],allowedFlags:[...E,...M]},clipboard:{usageOverride:"clipboard read | clipboard write <text>",listUsageOverride:"clipboard read | clipboard write <text>",helpDescription:"Read or write device clipboard text",positionalArgs:["read|write","text?"],allowsExtraPositionals:!0},keyboard:{usageOverride:"keyboard [status|get|dismiss|enter|return]",helpDescription:"Inspect Android keyboard visibility/type or press/dismiss the device keyboard",summary:"Inspect, press, or dismiss the device keyboard",positionalArgs:["action?"]},back:{usageOverride:"back [--in-app|--system]",allowedFlags:["backMode"]},rotate:{usageOverride:"rotate <portrait|portrait-upside-down|landscape-left|landscape-right>",helpDescription:"Rotate device orientation on iOS and Android",positionalArgs:["orientation"]},wait:{usageOverride:"wait <ms>|text <text>|@ref|<selector> [timeoutMs]",positionalArgs:["durationOrSelector","timeoutMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},get:{usageOverride:"get text|attrs <@ref|selector>",positionalArgs:["subcommand","target"],allowedFlags:[...A]},find:{usageOverride:"find <locator|text> <action> [value] [--first|--last]",helpDescription:"Find by text/label/value/role/id and run action",summary:"Find an element and act",positionalArgs:["query","action","value?"],allowsExtraPositionals:!0,allowedFlags:["snapshotDepth","snapshotRaw","findFirst","findLast"]},is:{positionalArgs:["predicate","selector","value?"],allowsExtraPositionals:!0,allowedFlags:[...A]},alert:{usageOverride:"alert [get|accept|dismiss|wait] [timeout]",positionalArgs:["action?","timeout?"]},click:{usageOverride:"click <x y|@ref|selector>",positionalArgs:["target"],allowsExtraPositionals:!0,allowedFlags:[...R,"clickButton",...A]},replay:{positionalArgs:["path"],allowedFlags:["replayMaestro",...U,"timeoutMs"]},test:{usageOverride:"test <path-or-glob>...",listUsageOverride:"test <path-or-glob>...",helpDescription:"Run one or more replay scripts as a serial test suite",summary:"Run replay test suites",positionalArgs:["pathOrGlob"],allowsExtraPositionals:!0,allowedFlags:["replayMaestro",...U,"failFast","timeoutMs","retries","artifactsDir","reportJunit","shardAll","shardSplit"]},batch:{usageOverride:"batch [--steps <json> | --steps-file <path>]",listUsageOverride:"batch --steps <json> | --steps-file <path>",helpDescription:"Execute multiple commands in one daemon request",summary:"Run multiple commands",allowedFlags:["steps","stepsFile","batchOnError","batchMaxSteps","out"]},press:{usageOverride:"press <x y|@ref|selector>",positionalArgs:["targetOrX","y?"],allowsExtraPositionals:!0,allowedFlags:[...R,...A]},longpress:{usageOverride:"longpress <x y|@ref|selector> [durationMs]",positionalArgs:["targetOrX","yOrDurationMs?","durationMs?"],allowsExtraPositionals:!0,allowedFlags:[...A]},swipe:{helpDescription:"Swipe coordinates with optional repeat pattern",positionalArgs:["x1","y1","x2","y2","durationMs?"],allowedFlags:["count","pauseMs","pattern"]},gesture:{usageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",listUsageOverride:"gesture <pan|fling|swipe|pinch|rotate|transform> ...",helpDescription:"Run touch gestures: pan <x> <y> <dx> <dy> [durationMs], fling <up|down|left|right> <x> <y> [distance] [durationMs], swipe <left|right|left-edge|right-edge> [durationMs], pinch <scale> [x] [y], rotate <degrees> [x] [y] [velocity], or transform <x> <y> <dx> <dy> <scale> <degrees> [durationMs]",summary:"Run pan, fling, swipe, pinch, rotate, or transform gestures",positionalArgs:["pan|fling|swipe|pinch|rotate|transform","args?"],allowsExtraPositionals:!0},focus:{positionalArgs:["x","y"]},type:{positionalArgs:["text"],allowsExtraPositionals:!0,allowedFlags:["delayMs"]},fill:{usageOverride:"fill <x> <y> <text> | fill <@ref|selector> <text>",positionalArgs:["targetOrX","yOrText","text?"],allowsExtraPositionals:!0,allowedFlags:[...A,"delayMs"]},scroll:{usageOverride:"scroll <direction|top|bottom> [amount] [--pixels <n>]",helpDescription:"Scroll in direction, or verify hidden content and scroll toward top/bottom",summary:"Scroll in a direction or to an edge",positionalArgs:["directionOrEdge","amount?"],allowedFlags:["pixels"]},"trigger-app-event":{usageOverride:"trigger-app-event <event> [payloadJson]",positionalArgs:["event","payloadJson?"]},record:{usageOverride:"record start [path] [--fps <n>] [--quality <5-10>] [--hide-touches] | record stop",listUsageOverride:"record start [path] | record stop",helpDescription:"Start/stop screen recording; Android recordings longer than the 180s adb screenrecord limit are returned as multiple MP4 chunks",summary:"Start or stop screen recording",positionalArgs:["start|stop","path?"],allowedFlags:["fps","quality","hideTouches"]},"react-native":{usageOverride:"react-native dismiss-overlay",listUsageOverride:"react-native dismiss-overlay",positionalArgs:["dismiss-overlay"]},trace:{usageOverride:"trace start <path> | trace stop <path>",listUsageOverride:"trace start <path> | trace stop <path>",helpDescription:"Start/stop trace log capture; when an artifact path is requested, pass the same positional path to start and stop",summary:"Start or stop trace capture",positionalArgs:["start|stop","path?"]},logs:{usageOverride:"logs path | logs start | logs stop | logs clear [--restart] | logs doctor | logs mark [message...]",helpDescription:"Session app log info, start/stop streaming, diagnostics, and markers",summary:"Manage session app logs",positionalArgs:["path|start|stop|clear|doctor|mark","message?"],allowsExtraPositionals:!0,allowedFlags:["restart"]},network:{usageOverride:"network dump [limit] [summary|headers|body|all] [--include summary|headers|body|all] | network log [limit] [summary|headers|body|all] [--include summary|headers|body|all]",helpDescription:"Dump recent HTTP(s) traffic parsed from the session app log",summary:"Show recent HTTP traffic",positionalArgs:["dump|log","limit?","include?"],allowedFlags:["networkInclude"]},settings:{usageOverride:f,listUsageOverride:"settings [area] [options]",helpDescription:"Toggle OS settings, animation scales, appearance, and app permissions (macOS supports only settings appearance <light|dark|toggle> and settings permission <grant|reset> <accessibility|screen-recording|input-monitoring>; wifi|airplane|location|animations remain unsupported on macOS; mobile permission actions use the active session app)",summary:"Change OS settings and app permissions",positionalArgs:["setting","state","target?","mode?"]},session:{usageOverride:"session list",positionalArgs:["list?"]}},N=new Map(r().map(e=>[e.name,{helpDescription:e.description}]));function V(e){if(e)return B(e)}function $(e){let s=B(e);if(!s)throw Error(`Missing command schema for ${e}`);return s}function B(e){let s=Object.hasOwn(I,e)?I[e]:void 0;if(s)return s;let t=N.get(e),a=Object.hasOwn(j,e)?j[e]:void 0;if(t)return a?{...t,...a}:t}function H(e,s){let t=V(e);if(!t?.defaults)return!1;let a=!1;for(let[e,o]of Object.entries(t.defaults))void 0===s[e]&&(s[e]=o,a=!0);return a}export{T as GLOBAL_FLAG_KEYS,L as MAESTRO_COMPAT_TRACKER_URL,O as MAESTRO_NEW_ISSUE_URL,b as SETTINGS_INVALID_ARGS_MESSAGE,H as applyCommandDefaults,$ as getCliCommandSchema,V as getCommandSchema,_ as getFlagDefinition,C as getFlagDefinitions,v as getUnsupportedMacOsSettingMessage,k as isMacOsSettingSupported,w as parseSessionSurface};
package/dist/src/221.js CHANGED
@@ -1,6 +1,6 @@
1
- import e from"node:crypto";import t from"node:fs";import r from"node:fs/promises";import n from"node:os";import i from"node:path";import o from"node:net";import{AppError as a}from"./9152.js";import{intersectArea as s,isScrollableType as l}from"./4778.js";import{emitDiagnostic as u}from"./7599.js";import{installAndroidAdbPackage as d}from"./9639.js";let c="android-snapshot-helper",h="com.callstack.agentdevice.snapshothelper",p="com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",f="android-snapshot-helper-v1",w="uiautomator-xml",m={"-r":"replace","-t":"allowTestPackages","-d":"allowDowngrade","-g":"grantPermissions"};async function A(e){let t=await y(e.apkPath);if(t!==e.manifest.sha256)throw new a("COMMAND_FAILED","Android snapshot helper APK checksum mismatch",{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:t})}async function M(e){let t=e.fetch??fetch,o=await t(e.manifestUrl);if(!o.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper manifest",{manifestUrl:e.manifestUrl,status:o.status,statusText:o.statusText});let s=g(JSON.parse((await v(o,65536,"Android snapshot helper manifest")).toString("utf8")));if(!s.apkUrl)throw new a("COMMAND_FAILED","Android snapshot helper manifest does not include apkUrl",{manifestUrl:e.manifestUrl});let l=e.cacheDir??i.join(n.tmpdir(),`agent-device-android-snapshot-helper-${s.version}`),u=!e.cacheDir;await r.mkdir(l,{recursive:!0});let d=s.assetName??`agent-device-android-snapshot-helper-${s.version}.apk`,c=i.join(l,d),h=await t(s.apkUrl);if(!h.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper APK",{apkUrl:s.apkUrl,status:h.status,statusText:h.statusText});await r.writeFile(c,await v(h,0x1400000,"Android snapshot helper APK"));let p={apkPath:c,manifest:s};return await A(p),{...p,cleanup:async()=>{await r.rm(u?l:c,{recursive:u,force:!0})}}}function g(e){var t,r;if(!e||"object"!=typeof e||Array.isArray(e))throw new a("INVALID_ARGS","Android snapshot helper manifest must be an object.");return{name:D(e.name,"name",c),version:x(e.version,"version"),releaseTag:I(e.releaseTag),assetName:I(e.assetName),apkUrl:(t=e.apkUrl,r="apkUrl",null===t?null:x(t,r)),sha256:function(e){let t=x(e,"sha256").trim().toLowerCase();if(64!==t.length||!function(e){for(let t of e){let e=t.charCodeAt(0),r=e>=48&&e<=57,n=e>=97&&e<=102;if(!r&&!n)return!1}return!0}(t))throw new a("INVALID_ARGS","Android snapshot helper manifest sha256 must be a 64-character hex string.");return t}(e.sha256),checksumName:I(e.checksumName),packageName:x(e.packageName,"packageName"),versionCode:b(e.versionCode,"versionCode"),instrumentationRunner:x(e.instrumentationRunner,"instrumentationRunner"),minSdk:b(e.minSdk,"minSdk"),targetSdk:void 0===e.targetSdk?void 0:b(e.targetSdk,"targetSdk"),outputFormat:D(e.outputFormat,"outputFormat",w),statusProtocol:D(e.statusProtocol,"statusProtocol",f),installArgs:N(e.installArgs)}}async function v(e,t,r){let n=e.headers.get("content-length");if(null!==n){let e=Number(n);if(Number.isFinite(e)&&e>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:e,maxBytes:t})}if(!e.body){let n=Buffer.from(await e.arrayBuffer());if(n.length>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:n.length,maxBytes:t});return n}let i=e.body.getReader(),o=[],s=0;try{for(;;){let{done:e,value:n}=await i.read();if(e)break;if((s+=n.byteLength)>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:s,maxBytes:t});o.push(Buffer.from(n))}}finally{i.releaseLock()}return Buffer.concat(o,s)}function N(e){let t=function(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be a string array.`);return e}(e,"installArgs");if("install"!==t[0])throw new a("INVALID_ARGS",'Android snapshot helper manifest installArgs must start with "install".');if(t.some(e=>e.includes("\0")))throw new a("INVALID_ARGS","Android snapshot helper manifest installArgs must not contain null bytes.");let r=t.slice(1).find(e=>void 0===C(e));if(r)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}async function y(r){return await new Promise((n,i)=>{let o=e.createHash("sha256"),a=t.createReadStream(r);a.on("error",i),a.on("data",e=>o.update(e)),a.on("end",()=>n(o.digest("hex")))})}function x(e,t){if("string"!=typeof e||0===e.trim().length)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} is required.`);return e}function I(e){return"string"==typeof e&&e.trim().length>0?e:void 0}function b(e,t){if("number"!=typeof e||!Number.isInteger(e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be an integer.`);return e}function D(e,t,r){if(e!==r)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be "${r}".`);return r}function C(e){if(Object.hasOwn(m,e))return m[e]}function*S(e){let t=/<node\b[^>]*>/g,r=t.exec(e);for(;r;)yield _(r[0]),r=t.exec(e)}function _(e){let t,r,n,i,o,a=(t=function(e){let t=new Map,r=e.indexOf(" "),n=e.lastIndexOf(">");if(r<0||n<=r)return t;let i=r;for(;i<n&&!((i=F(e,i,n))>=n);){var o;let r=e[i];if("/"===r||">"===r)break;let a=i;for(;i<n&&!("="===(o=e[i]??"")||"/"===o||">"===o||L(o));)i+=1;let s=e.slice(a,i);if(i=F(e,i,n),!s||"="!==e[i])break;i=F(e,i+1,n);let l=e[i];if('"'!==l&&"'"!==l)break;let u=i+=1;for(;i<n&&e[i]!==l;)i+=1;if(i>=n)break;t.set(s,function(e){let t="",r=0;for(;r<e.length;){let n=e.indexOf("&",r);if(n<0){t+=e.slice(r);break}t+=e.slice(r,n);let i=e.indexOf(";",n+1);if(i<0){t+=e.slice(n);break}t+=function(e){switch(e){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'";default:return function(e){if(!e.startsWith("#"))return;let t=e[1]?.toLowerCase()==="x"?16:10,r=16===t?e.slice(2):e.slice(1);if(!r||!function(e,t){for(let r of e){let e=r.charCodeAt(0),n=e>=48&&e<=57;if(10===t){if(!n)return!1;continue}let i=e>=65&&e<=70,o=e>=97&&e<=102;if(!n&&!i&&!o)return!1}return!0}(r,t))return;let n=Number.parseInt(r,t);if(Number.isFinite(n))try{return String.fromCodePoint(n)}catch{return}}(e)}}(e.slice(n+1,i))??e.slice(n,i+1),r=i+1}return t}(e.slice(u,i))),i+=1}return t}(e),r=e=>{let r=O(t,e);if(null!==r)return"true"===r},n=(e,r)=>{let n=(e=>{let r=O(t,e);if(null===r||""===r.trim())return;let n=Number(r);return Number.isFinite(n)?n:void 0})(r);return void 0===n?{}:{[e]:n}},i=(e,t)=>{let n=r(t);return void 0===n?{}:{[e]:n}},{text:O(t,"text"),desc:O(t,"content-desc"),resourceId:O(t,"resource-id"),packageName:O(t,"package"),className:O(t,"class"),bounds:O(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused"),password:r("password"),...i("visibleToUser","visible-to-user"),...n("drawingOrder","drawing-order"),...i("scrollable","scrollable"),...i("canScrollForward","can-scroll-forward"),...i("canScrollBackward","can-scroll-backward"),...n("windowIndex","window-index"),...n("windowType","window-type"),...n("windowLayer","window-layer"),...i("windowActive","window-active"),...i("windowFocused","window-focused"),...void 0===(o=E(O(t,"window-bounds")))?{}:{windowRect:o}}),s=E(a.bounds);return{...a,...s?{rect:s}:{}}}function k(e,t,r){let{sourceNodes:n,...i}=T(P(e),t,r);return i}function T(e,t,r){let n={nodes:[],sourceNodes:[],maxNodes:t,maxDepth:r.depth??1/0,options:r,analysis:function(e){let t=0,r=0,n=[...e.children];for(;n.length>0;){let e=n.pop();t+=1,r=Math.max(r,e.depth),n.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),interactiveDescendantMemo:new Map,truncated:!1},i=r.scope?function(e,t){let r=t.toLowerCase(),n=[...e.children],i=0;for(;i<n.length;){let e=n[i++],t=e.label?.toLowerCase()??"",o=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||o.includes(r)||a.includes(r))return e;n.push(...e.children)}return null}(e,r.scope):null;for(let t of i?[i]:e.children)if(function e(t,r,n,i,o=!1,a=!1){if(t.nodes.length>=t.maxNodes){t.truncated=!0;return}if(n>t.maxDepth)return;let s=t.options.raw||function(e,t,r,n,i){var o,a,s;if(!1===e.visibleToUser)return!1;let u=function(e){let t=V(e.type),r=!!(e.label&&e.label.trim().length>0),n=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:r&&!B(e.label??""),hasMeaningfulId:n&&!B(e.identifier??""),isStructural:function(e){let t=e.split(".").pop()??e;return t.includes("layout")||"viewgroup"===t||"view"===t}(t),isVisual:"imageview"===t||"imagebutton"===t}}(e);return t.interactiveOnly?function(e,t,r,n,i){var o,a,s,u,d;return!((o=e).rect&&(o.rect.width<=0||o.rect.height<=0))&&(!!(e.hittable||l(t.type)&&n)||(a=t,s=r,u=n,d=i,(!!a.hasMeaningfulText||!!a.hasMeaningfulId)&&!a.isVisual&&(!a.isStructural||!!d)&&(s||u||d)))}(e,u,r,n,i):t.compact?u.hasMeaningfulText||u.hasMeaningfulId||!!e.hittable:!u.isStructural&&!u.isVisual||(o=e,a=u,s=n,!!o.hittable||!!a.hasMeaningfulText||!!a.hasMeaningfulId||s)}(r,t.options,o,function e(t,r){let n=t.interactiveDescendantMemo.get(r);if(void 0!==n)return n;for(let n of r.children)if(!1!==n.visibleToUser&&(n.hittable||e(t,n)))return t.interactiveDescendantMemo.set(r,!0),!0;return t.interactiveDescendantMemo.set(r,!1),!1}(t,r),a)?function(e,t,r,n){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,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:r,parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{}}),i}(t,r,n,i):i,u=o||!!r.hittable,d=a||function(e){if(!e)return!1;let t=V(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(r.type);for(let i of r.children)if(e(t,i,n+1,s,u,d),t.truncated)return}(n,t,0),n.truncated)break;let o={nodes:n.nodes,sourceNodes:n.sourceNodes,analysis:n.analysis};return n.truncated?{...o,truncated:!0}:o}function F(e,t,r){for(;t<r&&L(e[t]??"");)t+=1;return t}function L(e){return" "===e||"\n"===e||"\r"===e||" "===e}function O(e,t){return e.get(t)??null}function E(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),n=Number(t[2]);return{x:r,y:n,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-n)}}function P(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},r=[t],n=/<node\b[^>]*>|<\/node>/g,i=n.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=n.exec(e);continue}let o=_(t),a=r[r.length-1],s={type:o.className,label:o.text||o.desc,value:o.text,identifier:o.resourceId,packageName:o.packageName,rect:o.rect,enabled:o.enabled,visibleToUser:o.visibleToUser,drawingOrder:o.drawingOrder,hittable:o.clickable??o.focusable,scrollable:o.scrollable,canScrollForward:o.canScrollForward,canScrollBackward:o.canScrollBackward,windowIndex:o.windowIndex,windowType:o.windowType,windowLayer:o.windowLayer,windowActive:o.windowActive,windowFocused:o.windowFocused,windowRect:o.windowRect,depth:a.depth+1,parentIndex:void 0,children:[]};a.children.push(s),t.endsWith("/>")||r.push(s),i=n.exec(e)}return function e(t){let r=0;for(let n of t.children)!1!==n.visibleToUser&&(e(n),t.children[r]=n,r+=1);r<t.children.length&&(t.children.length=r)}(t),function(e){let t,r=e.children.filter(U);if(r.length<2)return;let n=r.filter(e=>$(e)&&H(e));if(0===n.length)return;let i=(t=n.map(e=>e.windowLayer).filter(e=>void 0!==e)).length>0?Math.max(...t):void 0;e.children=e.children.filter(e=>!$(e)||!!H(e)&&(void 0===i||e.windowLayer===i))}(t),function e(t,r){for(let n of t.children)e(n,r);if(t.children.length<2)return;let n=t.children,i=n.filter(e=>{var t,n;return t=e,n=r,!1!==t.visibleToUser&&void 0!==t.drawingOrder&&R(t)&&function e(t,r){let n=r.agentVisibleContentMemo.get(t);if(void 0!==n)return n;let i=function(t,r){if(!1===t.visibleToUser)return!1;if(t.hittable)return!0;let n=t.label?.trim()??"";if(n&&!B(n))return!0;let i=t.identifier?.trim()??"";return!(!i||B(i))||t.children.some(t=>e(t,r))}(t,r);return r.agentVisibleContentMemo.set(t,i),i}(t,n)});0!==i.length&&(t.children=n.filter(e=>!function(e,t){if(!1===e.visibleToUser||void 0===e.drawingOrder||!R(e))return!1;for(let r of t)if(r!==e&&!(r.drawingOrder<=e.drawingOrder)&&function(e,t){let r=t.width*t.height;return r<=0?0:s(e,t)/r}(r.rect,e.rect)>=.9)return!0;return!1}(e,i)))}(t,{agentVisibleContentMemo:new WeakMap}),function(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),function(e){if(!e.scrollable||!l(e.type)||`${e.type??""}`.toLowerCase().includes("horizontalscrollview"))return!1;let t=function(e){if(!e.rect||0===e.children.length)return null;let t=e.children.map(e=>e.rect).filter(e=>void 0!==e);if(0===t.length)return null;let r=Math.min(...t.map(e=>e.x)),n=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),o=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,n-r-e.rect.width),vertical:Math.max(0,o-i-e.rect.height)}}(e);return!t||!(t.horizontal>t.vertical)||!(t.horizontal>16)}(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}(t),t}function R(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function U(e){return void 0!==e.windowIndex||void 0!==e.windowType}function $(e){return 1===e.windowType}function H(e){return!0===e.windowActive||!0===e.windowFocused}function V(e){return e?e.toLowerCase():""}function B(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function K(e){let t=G(e),r=await e.adb(W(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs}),{output:n,cleanupDone:i}=await X(e,t,r);if(t.outputPath&&!i&&await J(e.adb,t.outputPath),0!==r.exitCode)throw new a("COMMAND_FAILED","Android snapshot helper failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,helper:n.metadata});return n}function G(e){let t=Q(e.timeoutMs,8e3),r=Q(e.packageName,h);return{waitForIdleTimeoutMs:Q(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:Q(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:Q(e.commandTimeoutMs,t+5e3),maxDepth:Q(e.maxDepth,128),maxNodes:Q(e.maxNodes,5e3),packageName:r,runner:Q(e.instrumentationRunner,`${r}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...void 0!==e.emitChunks?{emitChunks:e.emitChunks}:{}}}function Q(e,t){return void 0===e?t:e}function W(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]:[],...void 0!==e.emitChunks?["-e","emitChunks",String(e.emitChunks)]:[],e.runner]}async function X(e,t,r){try{return{output:Y(`${r.stdout}
1
+ import e from"node:crypto";import t from"node:fs";import r from"node:fs/promises";import n from"node:os";import i from"node:path";import o from"node:net";import{AppError as a}from"./9152.js";import{intersectArea as s,isScrollableType as l}from"./4778.js";import{emitDiagnostic as u}from"./7599.js";import{installAndroidAdbPackage as d}from"./9639.js";let c="android-snapshot-helper",h="com.callstack.agentdevice.snapshothelper",p="com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",f="android-snapshot-helper-v1",w="uiautomator-xml",m={"-r":"replace","-t":"allowTestPackages","-d":"allowDowngrade","-g":"grantPermissions"};async function A(e){let t=await x(e.apkPath);if(t!==e.manifest.sha256)throw new a("COMMAND_FAILED","Android snapshot helper APK checksum mismatch",{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:t})}async function M(e){let t=e.fetch??fetch,o=await t(e.manifestUrl);if(!o.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper manifest",{manifestUrl:e.manifestUrl,status:o.status,statusText:o.statusText});let s=g(JSON.parse((await v(o,65536,"Android snapshot helper manifest")).toString("utf8")));if(!s.apkUrl)throw new a("COMMAND_FAILED","Android snapshot helper manifest does not include apkUrl",{manifestUrl:e.manifestUrl});let l=e.cacheDir??i.join(n.tmpdir(),`agent-device-android-snapshot-helper-${s.version}`),u=!e.cacheDir;await r.mkdir(l,{recursive:!0});let d=s.assetName??`agent-device-android-snapshot-helper-${s.version}.apk`,c=i.join(l,d),h=await t(s.apkUrl);if(!h.ok)throw new a("COMMAND_FAILED","Failed to download Android snapshot helper APK",{apkUrl:s.apkUrl,status:h.status,statusText:h.statusText});await r.writeFile(c,await v(h,0x1400000,"Android snapshot helper APK"));let p={apkPath:c,manifest:s};return await A(p),{...p,cleanup:async()=>{await r.rm(u?l:c,{recursive:u,force:!0})}}}function g(e){var t,r;if(!e||"object"!=typeof e||Array.isArray(e))throw new a("INVALID_ARGS","Android snapshot helper manifest must be an object.");return{name:D(e.name,"name",c),version:y(e.version,"version"),releaseTag:I(e.releaseTag),assetName:I(e.assetName),apkUrl:(t=e.apkUrl,r="apkUrl",null===t?null:y(t,r)),sha256:function(e){let t=y(e,"sha256").trim().toLowerCase();if(64!==t.length||!function(e){for(let t of e){let e=t.charCodeAt(0),r=e>=48&&e<=57,n=e>=97&&e<=102;if(!r&&!n)return!1}return!0}(t))throw new a("INVALID_ARGS","Android snapshot helper manifest sha256 must be a 64-character hex string.");return t}(e.sha256),checksumName:I(e.checksumName),packageName:y(e.packageName,"packageName"),versionCode:C(e.versionCode,"versionCode"),instrumentationRunner:y(e.instrumentationRunner,"instrumentationRunner"),minSdk:C(e.minSdk,"minSdk"),targetSdk:void 0===e.targetSdk?void 0:C(e.targetSdk,"targetSdk"),outputFormat:D(e.outputFormat,"outputFormat",w),statusProtocol:D(e.statusProtocol,"statusProtocol",f),installArgs:N(e.installArgs)}}async function v(e,t,r){let n=e.headers.get("content-length");if(null!==n){let e=Number(n);if(Number.isFinite(e)&&e>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:e,maxBytes:t})}if(!e.body){let n=Buffer.from(await e.arrayBuffer());if(n.length>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:n.length,maxBytes:t});return n}let i=e.body.getReader(),o=[],s=0;try{for(;;){let{done:e,value:n}=await i.read();if(e)break;if((s+=n.byteLength)>t)throw new a("COMMAND_FAILED",`${r} download exceeds size limit`,{contentLength:s,maxBytes:t});o.push(Buffer.from(n))}}finally{i.releaseLock()}return Buffer.concat(o,s)}function N(e){let t=function(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be a string array.`);return e}(e,"installArgs");if("install"!==t[0])throw new a("INVALID_ARGS",'Android snapshot helper manifest installArgs must start with "install".');if(t.some(e=>e.includes("\0")))throw new a("INVALID_ARGS","Android snapshot helper manifest installArgs must not contain null bytes.");let r=t.slice(1).find(e=>void 0===b(e));if(r)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}async function x(r){return await new Promise((n,i)=>{let o=e.createHash("sha256"),a=t.createReadStream(r);a.on("error",i),a.on("data",e=>o.update(e)),a.on("end",()=>n(o.digest("hex")))})}function y(e,t){if("string"!=typeof e||0===e.trim().length)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} is required.`);return e}function I(e){return"string"==typeof e&&e.trim().length>0?e:void 0}function C(e,t){if("number"!=typeof e||!Number.isInteger(e))throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be an integer.`);return e}function D(e,t,r){if(e!==r)throw new a("INVALID_ARGS",`Android snapshot helper manifest ${t} must be "${r}".`);return r}function b(e){if(Object.hasOwn(m,e))return m[e]}function*S(e){let t=/<node\b[^>]*>/g,r=t.exec(e);for(;r;)yield _(r[0]),r=t.exec(e)}function _(e){let t,r,n,i,o,a=(t=function(e){let t=new Map,r=e.indexOf(" "),n=e.lastIndexOf(">");if(r<0||n<=r)return t;let i=r;for(;i<n;){let r=function(e,t,r){var n,i;if((t=F(e,t,r))>=r||"/"===(n=e[t])||">"===n)return;let o=t;t=function(e,t,r){for(var n;t<r&&!("="===(n=e[t]??"")||"/"===n||">"===n||L(n));)t+=1;return t}(e,t,r);let a=e.slice(o,t);if(t=F(e,t,r),!a||"="!==e[t])return;t=F(e,t+1,r);let s=e[t];if('"'!==(i=s)&&"'"!==i)return;let l=t+1,u=e.indexOf(s,l);if(!(u<0)&&!(u>=r))return{name:a,value:function(e){let t="",r=0;for(;r<e.length;){let n=e.indexOf("&",r);if(n<0){t+=e.slice(r);break}t+=e.slice(r,n);let i=e.indexOf(";",n+1);if(i<0){t+=e.slice(n);break}t+=function(e){switch(e){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'";default:return function(e){if(!e.startsWith("#"))return;let t=e[1]?.toLowerCase()==="x"?16:10,r=16===t?e.slice(2):e.slice(1);if(!r||!function(e,t){for(let r of e){let e=r.charCodeAt(0),n=e>=48&&e<=57;if(10===t){if(!n)return!1;continue}let i=e>=65&&e<=70,o=e>=97&&e<=102;if(!n&&!i&&!o)return!1}return!0}(r,t))return;let n=Number.parseInt(r,t);if(Number.isFinite(n))try{return String.fromCodePoint(n)}catch{return}}(e)}}(e.slice(n+1,i))??e.slice(n,i+1),r=i+1}return t}(e.slice(l,u)),nextCursor:u+1}}(e,i,n);if(!r)break;t.set(r.name,r.value),i=r.nextCursor}return t}(e),r=e=>{let r=O(t,e);if(null!==r)return"true"===r},n=(e,r)=>{let n=(e=>{let r=O(t,e);if(null===r||""===r.trim())return;let n=Number(r);return Number.isFinite(n)?n:void 0})(r);return void 0===n?{}:{[e]:n}},i=(e,t)=>{let n=r(t);return void 0===n?{}:{[e]:n}},{text:O(t,"text"),desc:O(t,"content-desc"),resourceId:O(t,"resource-id"),packageName:O(t,"package"),className:O(t,"class"),bounds:O(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused"),password:r("password"),...i("visibleToUser","visible-to-user"),...n("drawingOrder","drawing-order"),...i("scrollable","scrollable"),...i("canScrollForward","can-scroll-forward"),...i("canScrollBackward","can-scroll-backward"),...n("windowIndex","window-index"),...n("windowType","window-type"),...n("windowLayer","window-layer"),...i("windowActive","window-active"),...i("windowFocused","window-focused"),...void 0===(o=E(O(t,"window-bounds")))?{}:{windowRect:o}}),s=E(a.bounds);return{...a,...s?{rect:s}:{}}}function T(e,t,r){let{sourceNodes:n,...i}=k(P(e),t,r);return i}function k(e,t,r){let n={nodes:[],sourceNodes:[],...void 0!==t?{maxNodes:t}:{},maxDepth:r.depth??1/0,options:r,analysis:function(e){let t=0,r=0,n=[...e.children];for(;n.length>0;){let e=n.pop();t+=1,r=Math.max(r,e.depth),n.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(e),interactiveDescendantMemo:new Map,truncated:!1},i=r.scope?function(e,t){let r=t.toLowerCase(),n=[...e.children],i=0;for(;i<n.length;){let e=n[i++],t=e.label?.toLowerCase()??"",o=e.value?.toLowerCase()??"",a=e.identifier?.toLowerCase()??"";if(t.includes(r)||o.includes(r)||a.includes(r))return e;n.push(...e.children)}return null}(e,r.scope):null;for(let t of i?[i]:e.children)if(function e(t,r,n,i,o=!1,a=!1){if(void 0!==t.maxNodes&&t.nodes.length>=t.maxNodes){t.truncated=!0;return}if(n>t.maxDepth)return;let s=t.options.raw||function(e,t,r,n,i){var o,a,s;if(!1===e.visibleToUser)return!1;let u=function(e){let t=V(e.type),r=!!(e.label&&e.label.trim().length>0),n=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:r&&!B(e.label??""),hasMeaningfulId:n&&!B(e.identifier??""),isStructural:function(e){let t=e.split(".").pop()??e;return t.includes("layout")||"viewgroup"===t||"view"===t}(t),isVisual:"imageview"===t||"imagebutton"===t}}(e);return t.interactiveOnly?function(e,t,r,n,i){var o,a,s,u,d;return!((o=e).rect&&(o.rect.width<=0||o.rect.height<=0))&&(!!(e.hittable||l(t.type)&&n)||(a=t,s=r,u=n,d=i,(!!a.hasMeaningfulText||!!a.hasMeaningfulId)&&!a.isVisual&&(!a.isStructural||!!d)&&(s||u||d)))}(e,u,r,n,i):t.compact?u.hasMeaningfulText||u.hasMeaningfulId||!!e.hittable:!u.isStructural&&!u.isVisual||(o=e,a=u,s=n,!!o.hittable||!!a.hasMeaningfulText||!!a.hasMeaningfulId||s)}(r,t.options,o,function e(t,r){let n=t.interactiveDescendantMemo.get(r);if(void 0!==n)return n;for(let n of r.children)if(!1!==n.visibleToUser&&(n.hittable||e(t,n)))return t.interactiveDescendantMemo.set(r,!0),!0;return t.interactiveDescendantMemo.set(r,!1),!1}(t,r),a)?function(e,t,r,n){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,visibleToUser:t.visibleToUser,hittable:t.hittable,depth:r,parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{}}),i}(t,r,n,i):i,u=o||!!r.hittable,d=a||function(e){if(!e)return!1;let t=V(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(r.type);for(let i of r.children)if(e(t,i,n+1,s,u,d),t.truncated)return}(n,t,0),n.truncated)break;let o={nodes:n.nodes,sourceNodes:n.sourceNodes,analysis:n.analysis};return n.truncated?{...o,truncated:!0}:o}function F(e,t,r){for(;t<r&&L(e[t]??"");)t+=1;return t}function L(e){return" "===e||"\n"===e||"\r"===e||" "===e}function O(e,t){return e.get(t)??null}function E(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),n=Number(t[2]);return{x:r,y:n,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-n)}}function P(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,depth:-1,children:[]},r=[t],n=/<node\b[^>]*>|<\/node>/g,i=n.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=n.exec(e);continue}let o=_(t),a=r[r.length-1],s={type:o.className,label:o.text||o.desc,value:o.text,identifier:o.resourceId,packageName:o.packageName,rect:o.rect,enabled:o.enabled,visibleToUser:o.visibleToUser,drawingOrder:o.drawingOrder,hittable:o.clickable??o.focusable,scrollable:o.scrollable,canScrollForward:o.canScrollForward,canScrollBackward:o.canScrollBackward,windowIndex:o.windowIndex,windowType:o.windowType,windowLayer:o.windowLayer,windowActive:o.windowActive,windowFocused:o.windowFocused,windowRect:o.windowRect,depth:a.depth+1,parentIndex:void 0,children:[]};a.children.push(s),t.endsWith("/>")||r.push(s),i=n.exec(e)}return function e(t){let r=0;for(let n of t.children)!1!==n.visibleToUser&&(e(n),t.children[r]=n,r+=1);r<t.children.length&&(t.children.length=r)}(t),function(e){let t,r=e.children.filter(U);if(r.length<2)return;let n=r.filter(e=>$(e)&&H(e));if(0===n.length)return;let i=(t=n.map(e=>e.windowLayer).filter(e=>void 0!==e)).length>0?Math.max(...t):void 0;e.children=e.children.filter(e=>!$(e)||!!H(e)&&(void 0===i||e.windowLayer===i))}(t),function e(t,r){for(let n of t.children)e(n,r);if(t.children.length<2)return;let n=t.children,i=n.filter(e=>{var t,n;return t=e,n=r,!1!==t.visibleToUser&&void 0!==t.drawingOrder&&R(t)&&function e(t,r){let n=r.agentVisibleContentMemo.get(t);if(void 0!==n)return n;let i=function(t,r){if(!1===t.visibleToUser)return!1;if(t.hittable)return!0;let n=t.label?.trim()??"";if(n&&!B(n))return!0;let i=t.identifier?.trim()??"";return!(!i||B(i))||t.children.some(t=>e(t,r))}(t,r);return r.agentVisibleContentMemo.set(t,i),i}(t,n)});0!==i.length&&(t.children=n.filter(e=>!function(e,t){if(!1===e.visibleToUser||void 0===e.drawingOrder||!R(e))return!1;for(let r of t)if(r!==e&&!(r.drawingOrder<=e.drawingOrder)&&function(e,t){let r=t.width*t.height;return r<=0?0:s(e,t)/r}(r.rect,e.rect)>=.9)return!0;return!1}(e,i)))}(t,{agentVisibleContentMemo:new WeakMap}),function(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),function(e){if(!e.scrollable||!l(e.type)||`${e.type??""}`.toLowerCase().includes("horizontalscrollview"))return!1;let t=function(e){if(!e.rect||0===e.children.length)return null;let t=e.children.map(e=>e.rect).filter(e=>void 0!==e);if(0===t.length)return null;let r=Math.min(...t.map(e=>e.x)),n=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),o=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,n-r-e.rect.width),vertical:Math.max(0,o-i-e.rect.height)}}(e);return!t||!(t.horizontal>t.vertical)||!(t.horizontal>16)}(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}(t),t}function R(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function U(e){return void 0!==e.windowIndex||void 0!==e.windowType}function $(e){return 1===e.windowType}function H(e){return!0===e.windowActive||!0===e.windowFocused}function V(e){return e?e.toLowerCase():""}function B(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function K(e){let t=G(e),r=await e.adb(W(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs}),{output:n,cleanupDone:i}=await X(e,t,r);if(t.outputPath&&!i&&await J(e.adb,t.outputPath),0!==r.exitCode)throw new a("COMMAND_FAILED","Android snapshot helper failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode,helper:n.metadata});return n}function G(e){let t=Q(e.timeoutMs,8e3),r=Q(e.packageName,h);return{waitForIdleTimeoutMs:Q(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:Q(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:Q(e.commandTimeoutMs,t+5e3),maxDepth:Q(e.maxDepth,128),maxNodes:Q(e.maxNodes,5e3),packageName:r,runner:Q(e.instrumentationRunner,`${r}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...void 0!==e.emitChunks?{emitChunks:e.emitChunks}:{}}}function Q(e,t){return void 0===e?t:e}function W(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]:[],...void 0!==e.emitChunks?["-e","emitChunks",String(e.emitChunks)]:[],e.runner]}async function X(e,t,r){try{return{output:Y(`${r.stdout}
2
2
  ${r.stderr}`),cleanupDone:!1}}catch(n){return await z(e,t,r,n)}}async function z(e,t,r,n){if(n instanceof a&&0!==r.exitCode&&n.details?.helper)throw n;let i=await j(e,t,r);if(i)return{output:i,cleanupDone:!0};throw new a("COMMAND_FAILED",0===r.exitCode?"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},n)}async function j(e,t,r){if(0===r.exitCode&&t.outputPath){var n;return await q(e.adb,t.outputPath,function(e){try{let t=er(e);return et(ee(t.results))}catch{return null}}(`${r.stdout}
3
- ${r.stderr}`)??{outputFormat:w,waitForIdleTimeoutMs:(n=t).waitForIdleTimeoutMs,waitForIdleQuietMs:n.waitForIdleQuietMs,timeoutMs:n.timeoutMs,maxDepth:n.maxDepth,maxNodes:n.maxNodes,transport:"instrumentation"})}}async function q(e,t,r){let n;try{var i;n=await e((i=t,["shell","sh","-c",'cat "$1"; status=$?; rm -f "$1"; exit "$status"',"agent-device-snapshot-helper-output",i]),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(0!==n.exitCode)return;let o=n.stdout.trim();if(o.includes("<hierarchy")&&o.includes("</hierarchy>"))return{xml:o,metadata:r}}async function J(e,t){try{await e(["shell","rm","-f",t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Y(e){let t=er(e),r=ee(t.results);return{xml:function(e,t){if(0===e.length)throw new a("COMMAND_FAILED","Android snapshot helper did not return XML chunks",{helper:t});let r=function(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{expectedChunks:t,actualChunks:e.length});return t}(e),n=Buffer.concat(function(e,t){let r=[];for(let n=0;n<t;n+=1){let i=e.get(n);if(void 0===i)throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{missingChunkIndex:n,expectedChunks:t});r.push(Buffer.from(i,"base64"))}return r}(function(e,t){let r=new Map;for(let n of e){if(void 0===n.index||n.index<0||n.index>=t)throw new a("COMMAND_FAILED","Android snapshot helper returned invalid chunk index",{chunkIndex:n.index,expectedChunks:t});if(r.has(n.index))throw new a("COMMAND_FAILED","Android snapshot helper returned duplicate XML chunks",{chunkIndex:n.index});r.set(n.index,n.payloadBase64)}return r}(e,r),r)).toString("utf8");if(!n.includes("<hierarchy")||!n.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper output did not contain XML",{xml:n});return n}(function(e){let t=[];for(let r of e){if(r.agentDeviceProtocol!==f||r.outputFormat!==w)continue;let{payloadBase64:e}=r;void 0!==e&&t.push({index:el(r.chunkIndex),count:el(r.chunkCount),payloadBase64:e})}return t}(t.status),r),metadata:{...et(r),transport:"instrumentation"}}}function Z(e,t={outputFormat:w},r={},n=800){return{...k(e,n,r),metadata:t}}function ee(e){let t=e.find(e=>e.agentDeviceProtocol===f);if(!t)throw new a("COMMAND_FAILED","Android snapshot helper did not return a final result");if("true"!==t.ok){var r;throw new a("COMMAND_FAILED",(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android snapshot helper returned an error",{errorType:t.errorType,helper:t})}return t}function et(e){var t;return{helperApiVersion:e.helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:el(e.waitForIdleTimeoutMs),waitForIdleQuietMs:el(e.waitForIdleQuietMs),timeoutMs:el(e.timeoutMs),maxDepth:el(e.maxDepth),maxNodes:el(e.maxNodes),rootPresent:eu(e.rootPresent),captureMode:"interactive-windows"===(t=e.captureMode)||"active-window"===t?t:void 0,windowCount:el(e.windowCount),nodeCount:el(e.nodeCount),truncated:eu(e.truncated),elapsedMs:el(e.elapsedMs)}}function er(e){var t;let r={status:[],results:[],currentStatus:null,currentResult:null};for(let t of e.split(/\r?\n/))!function(e,t){if(e.startsWith("INSTRUMENTATION_STATUS: ")){t.currentStatus??={},eo(e.slice(24),t.currentStatus);return}if(e.startsWith("INSTRUMENTATION_STATUS_CODE: "))return en(t);if(e.startsWith("INSTRUMENTATION_RESULT: ")){t.currentResult??={},eo(e.slice(24),t.currentResult);return}e.startsWith("INSTRUMENTATION_CODE: ")&&ei(t)}(t,r);return en(t=r),ei(t),{status:r.status,results:r.results}}function en(e){e.currentStatus&&(e.status.push(e.currentStatus),e.currentStatus=null)}function ei(e){e.currentResult&&(e.results.push(e.currentResult),e.currentResult=null)}function eo(e,t){let r=e.indexOf("=");r<0||(t[e.slice(0,r)]=e.slice(r+1))}function ea(e){if(void 0===e)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function es(e){return"true"===e||"false"!==e&&void 0}let el=ea,eu=es,ed=new Map,ec=new Map;async function eh(e){var t,r,n;let i;if(!(void 0===(i=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION)||!/^(0|false|no|off)$/i.test(i))||!e.adbProvider?.spawn)return;let o=G(e),a=e.deviceKey??"android:default",s=(t=a,r=o,n=e,JSON.stringify({deviceKey:t,packageName:r.packageName,runner:r.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,waitForIdleTimeoutMs:r.waitForIdleTimeoutMs,waitForIdleQuietMs:r.waitForIdleQuietMs,timeoutMs:r.timeoutMs,maxDepth:r.maxDepth,maxNodes:r.maxNodes}));if(ec.get(a)===s)return;let l=ed.get(a);if(l&&l.identity!==s&&(await ep(a),l=void 0),!l)try{l=await ef({deviceKey:a,identity:s,options:e,resolved:o})}catch(e){ec.set(a,s),u({level:"warn",phase:"android_snapshot_helper_session_disabled",data:{deviceKey:a,reason:e instanceof Error?e.message:String(e)}});return}try{let e=l.capturedCount>0,t=await em(l,o);return l.capturedCount+=1,{xml:t.xml,metadata:{...t.metadata,transport:"persistent-session",sessionReused:e}}}catch(e){throw await ep(a),e}}async function ep(e){let t=ed.get(e);if(t){ed.delete(e);try{await eA(t,`quit ${Date.now()}`,1e3)}catch{}try{await t.process.kill("SIGTERM")}catch{}await ew(t.process,2e3);try{await eM(t)}catch{}u({phase:"android_snapshot_helper_session_stop",data:{deviceKey:e,port:t.port,capturedCount:t.capturedCount,lifetimeMs:Date.now()-t.startedAtMs}})}}async function ef(e){let t=await new Promise((e,t)=>{let r=o.createServer();r.unref(),r.on("error",t),r.listen(0,"127.0.0.1",()=>{let n=r.address();if(!n||"string"==typeof n)return void r.close(()=>t(Error("Failed to allocate a local TCP port")));let i=n.port;r.close(()=>e(i))})});await e.options.adb(["forward",`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:5e3});let r=W({...e.resolved,outputPath:void 0,emitChunks:!1}),n=r[r.length-1];if(!n)throw new a("INVALID_ARGS","Android snapshot helper runner was not resolved");let i=[...r.slice(0,-1),"-e","sessionPort",String(t),n],s=e.options.adbProvider.spawn(i,{allowFailure:!0,captureOutput:!1}),l={identity:e.identity,deviceKey:e.deviceKey,port:t,adb:e.options.adb,process:s,startedAtMs:Date.now(),capturedCount:0};try{var d;return await (d=s,new Promise((e,t)=>{let r="",n=setTimeout(()=>{t(new a("COMMAND_FAILED","Android snapshot helper session did not become ready",{output:r,timeoutMs:1e4}))},1e4),i=t=>{(r+=t.toString()).includes(`agentDeviceProtocol=${f}`)&&r.includes("sessionReady=true")&&(clearTimeout(n),e())};d.stdout?.on("data",i),d.stderr?.on("data",i),d.once("exit",(e,i)=>{clearTimeout(n),t(new a("COMMAND_FAILED","Android snapshot helper session exited before ready",{output:r,exitCode:e,signal:i}))}),d.on("error",e=>{clearTimeout(n),t(e)})})),ed.set(e.deviceKey,l),u({phase:"android_snapshot_helper_session_ready",data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),l}catch(e){await eM(l);try{s.kill("SIGTERM")}catch{}throw await ew(s,2e3),e}}function ew(e,t){return new Promise(r=>{let n=setTimeout(r,t);e.once("close",()=>{clearTimeout(n),r()}),e.once("exit",()=>{clearTimeout(n),r()})})}async function em(e,t){let r=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`,n=Math.max(t.timeoutMs+2e3,3e3);return function(e,t){var r;let{headers:n,xml:i}=function(e){let t=e.indexOf("\n\n");if(t<0)throw new a("COMMAND_FAILED","Android snapshot helper session returned malformed output",{response:e});return{headers:function(e){let t={};for(let r of e.split(/\r?\n/)){let e=r.indexOf("=");e<0||(t[r.slice(0,e)]=r.slice(e+1))}return t}(e.slice(0,t)),xml:e.slice(t+2)}}(e);return function(e,t){if(e.agentDeviceProtocol!==f)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong protocol",{headers:e});if(e.outputFormat!==w)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong output format",{headers:e});if(e.requestId!==t)throw new a("COMMAND_FAILED","Android snapshot helper session returned stale output",{headers:e,requestId:t});if("true"!==e.ok)throw new a("COMMAND_FAILED",e.message||e.errorType||"Android snapshot helper session returned an error",{helper:e})}(n,t),function(e,t){let r=ea(e.byteLength);if(void 0!==r&&Buffer.byteLength(t,"utf8")!==r)throw new a("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 a("COMMAND_FAILED","Android snapshot helper session did not return XML",{headers:e,xml:t})}(n,i),{xml:i,metadata:{helperApiVersion:(r=n).helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:ea(r.waitForIdleTimeoutMs),waitForIdleQuietMs:ea(r.waitForIdleQuietMs),timeoutMs:ea(r.timeoutMs),maxDepth:ea(r.maxDepth),maxNodes:ea(r.maxNodes),rootPresent:es(r.rootPresent),captureMode:"interactive-windows"===r.captureMode||"active-window"===r.captureMode?r.captureMode:void 0,windowCount:ea(r.windowCount),nodeCount:ea(r.nodeCount),truncated:es(r.truncated),elapsedMs:ea(r.elapsedMs)}}}(await eA(e,`snapshot ${r}`,n),r)}function eA(e,t,r){return new Promise((n,i)=>{let s=o.connect({host:"127.0.0.1",port:e.port}),l=[],u=setTimeout(()=>{s.destroy(),i(new a("COMMAND_FAILED","Android snapshot helper session request timed out",{command:t,timeoutMs:r,port:e.port}))},r);s.on("connect",()=>{s.write(`${t}
4
- `)}),s.on("data",e=>{l.push(Buffer.from(e))}),s.on("error",e=>{clearTimeout(u),i(e)}),s.on("close",()=>{clearTimeout(u),n(Buffer.concat(l).toString("utf8"))})})}async function eM(e){await e.process.stdin?.end(),await e.process.stdout?.destroy(),await e.process.stderr?.destroy(),await eg(e)}async function eg(e){await e.adb(["forward","--remove",`tcp:${e.port}`],{allowFailure:!0,timeoutMs:5e3})}let ev=new Map;function eN(e){ex(ey(e.deviceKey,e.packageName,e.versionCode))}function ey(e,t,r){return e?`${e}\0${t}\0${r}`:void 0}function ex(e){e&&ev.delete(e)}async function eI(e){var t,r,n;let{adb:i,artifact:o}=e,s=e.installPolicy??"missing-or-outdated",l=o.manifest.packageName,u=o.manifest.versionCode;if("never"===s)return{packageName:l,versionCode:u,installed:!1,reason:"skipped"};let d=ey(e.deviceKey,l,u),c=d?ev.get(d):void 0;if(d&&"always"!==s&&void 0!==c)return{packageName:l,versionCode:u,installedVersionCode:c,installed:!1,reason:"current"};let h=await eb(i,l,e.timeoutMs),p=(t=s,r=h,n=u,"never"===t?"skipped":"always"===t?"forced":void 0===r?"missing":r<n?"outdated":"current");if("current"===p){if(void 0===h)throw Error("Expected installed versionCode for current Android snapshot helper");return d&&ev.set(d,h),{packageName:l,versionCode:u,installedVersionCode:h,installed:!1,reason:p}}await A(o);let f=await eD(i,e.adbProvider??i,o.apkPath,function(e){let t={};for(let r of e.slice(1)){let e=C(r);if(!e)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}(N(o.manifest.installArgs)),{packageName:l,timeoutMs:e.timeoutMs});if(0!==f.exitCode)throw ex(d),new a("COMMAND_FAILED","Failed to install Android snapshot helper",{packageName:l,versionCode:u,stdout:f.stdout,stderr:f.stderr,exitCode:f.exitCode});return d&&ev.set(d,u),{packageName:l,versionCode:u,installedVersionCode:h,installed:!0,reason:p}}async function eb(e,t,r){let n=await e(["shell","cmd","package","list","packages","--show-versioncode",t],{allowFailure:!0,timeoutMs:r});if(0===n.exitCode){var i=`${n.stdout}
3
+ ${r.stderr}`)??{outputFormat:w,waitForIdleTimeoutMs:(n=t).waitForIdleTimeoutMs,waitForIdleQuietMs:n.waitForIdleQuietMs,timeoutMs:n.timeoutMs,maxDepth:n.maxDepth,maxNodes:n.maxNodes,transport:"instrumentation"})}}async function q(e,t,r){let n;try{var i;n=await e((i=t,["shell","sh","-c",'cat "$1"; status=$?; rm -f "$1"; exit "$status"',"agent-device-snapshot-helper-output",i]),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(0!==n.exitCode)return;let o=n.stdout.trim();if(o.includes("<hierarchy")&&o.includes("</hierarchy>"))return{xml:o,metadata:r}}async function J(e,t){try{await e(["shell","rm","-f",t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Y(e){let t=er(e),r=ee(t.results);return{xml:function(e,t){if(0===e.length)throw new a("COMMAND_FAILED","Android snapshot helper did not return XML chunks",{helper:t});let r=function(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{expectedChunks:t,actualChunks:e.length});return t}(e),n=Buffer.concat(function(e,t){let r=[];for(let n=0;n<t;n+=1){let i=e.get(n);if(void 0===i)throw new a("COMMAND_FAILED","Android snapshot helper returned incomplete XML chunks",{missingChunkIndex:n,expectedChunks:t});r.push(Buffer.from(i,"base64"))}return r}(function(e,t){let r=new Map;for(let n of e){if(void 0===n.index||n.index<0||n.index>=t)throw new a("COMMAND_FAILED","Android snapshot helper returned invalid chunk index",{chunkIndex:n.index,expectedChunks:t});if(r.has(n.index))throw new a("COMMAND_FAILED","Android snapshot helper returned duplicate XML chunks",{chunkIndex:n.index});r.set(n.index,n.payloadBase64)}return r}(e,r),r)).toString("utf8");if(!n.includes("<hierarchy")||!n.includes("</hierarchy>"))throw new a("COMMAND_FAILED","Android snapshot helper output did not contain XML",{xml:n});return n}(function(e){let t=[];for(let r of e){if(r.agentDeviceProtocol!==f||r.outputFormat!==w)continue;let{payloadBase64:e}=r;void 0!==e&&t.push({index:el(r.chunkIndex),count:el(r.chunkCount),payloadBase64:e})}return t}(t.status),r),metadata:{...et(r),transport:"instrumentation"}}}function Z(e,t={outputFormat:w},r={},n){return{...T(e,n,r),metadata:t}}function ee(e){let t=e.find(e=>e.agentDeviceProtocol===f);if(!t)throw new a("COMMAND_FAILED","Android snapshot helper did not return a final result");if("true"!==t.ok){var r;throw new a("COMMAND_FAILED",(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android snapshot helper returned an error",{errorType:t.errorType,helper:t})}return t}function et(e){var t;return{helperApiVersion:e.helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:el(e.waitForIdleTimeoutMs),waitForIdleQuietMs:el(e.waitForIdleQuietMs),timeoutMs:el(e.timeoutMs),maxDepth:el(e.maxDepth),maxNodes:el(e.maxNodes),rootPresent:eu(e.rootPresent),captureMode:"interactive-windows"===(t=e.captureMode)||"active-window"===t?t:void 0,windowCount:el(e.windowCount),nodeCount:el(e.nodeCount),truncated:eu(e.truncated),elapsedMs:el(e.elapsedMs)}}function er(e){var t;let r={status:[],results:[],currentStatus:null,currentResult:null};for(let t of e.split(/\r?\n/))!function(e,t){if(e.startsWith("INSTRUMENTATION_STATUS: ")){t.currentStatus??={},eo(e.slice(24),t.currentStatus);return}if(e.startsWith("INSTRUMENTATION_STATUS_CODE: "))return en(t);if(e.startsWith("INSTRUMENTATION_RESULT: ")){t.currentResult??={},eo(e.slice(24),t.currentResult);return}e.startsWith("INSTRUMENTATION_CODE: ")&&ei(t)}(t,r);return en(t=r),ei(t),{status:r.status,results:r.results}}function en(e){e.currentStatus&&(e.status.push(e.currentStatus),e.currentStatus=null)}function ei(e){e.currentResult&&(e.results.push(e.currentResult),e.currentResult=null)}function eo(e,t){let r=e.indexOf("=");r<0||(t[e.slice(0,r)]=e.slice(r+1))}function ea(e){if(void 0===e)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function es(e){return"true"===e||"false"!==e&&void 0}let el=ea,eu=es,ed=new Map,ec=new Map;async function eh(e){var t,r,n;let i;if(!(void 0===(i=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION)||!/^(0|false|no|off)$/i.test(i))||!e.adbProvider?.spawn)return;let o=G(e),a=e.deviceKey??"android:default",s=(t=a,r=o,n=e,JSON.stringify({deviceKey:t,packageName:r.packageName,runner:r.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,waitForIdleTimeoutMs:r.waitForIdleTimeoutMs,waitForIdleQuietMs:r.waitForIdleQuietMs,timeoutMs:r.timeoutMs,maxDepth:r.maxDepth,maxNodes:r.maxNodes}));if(ec.get(a)===s)return;let l=ed.get(a);if(l&&l.identity!==s&&(await ep(a),l=void 0),!l)try{l=await ef({deviceKey:a,identity:s,options:e,resolved:o})}catch(e){ec.set(a,s),u({level:"warn",phase:"android_snapshot_helper_session_disabled",data:{deviceKey:a,reason:e instanceof Error?e.message:String(e)}});return}try{let e=l.capturedCount>0,t=await em(l,o);return l.capturedCount+=1,{xml:t.xml,metadata:{...t.metadata,transport:"persistent-session",sessionReused:e}}}catch(e){throw await ep(a),e}}async function ep(e){let t=ed.get(e);if(t){ed.delete(e);try{await eA(t,`quit ${Date.now()}`,1e3)}catch{}try{await t.process.kill("SIGTERM")}catch{}await ew(t.process,2e3);try{await eM(t)}catch{}u({phase:"android_snapshot_helper_session_stop",data:{deviceKey:e,port:t.port,capturedCount:t.capturedCount,lifetimeMs:Date.now()-t.startedAtMs}})}}async function ef(e){let t=await new Promise((e,t)=>{let r=o.createServer();r.unref(),r.on("error",t),r.listen(0,"127.0.0.1",()=>{let n=r.address();if(!n||"string"==typeof n)return void r.close(()=>t(Error("Failed to allocate a local TCP port")));let i=n.port;r.close(()=>e(i))})});await e.options.adb(["forward",`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:5e3});let r=W({...e.resolved,outputPath:void 0,emitChunks:!1}),n=r[r.length-1];if(!n)throw new a("INVALID_ARGS","Android snapshot helper runner was not resolved");let i=[...r.slice(0,-1),"-e","sessionPort",String(t),n],s=e.options.adbProvider.spawn(i,{allowFailure:!0,captureOutput:!1}),l={identity:e.identity,deviceKey:e.deviceKey,port:t,adb:e.options.adb,process:s,startedAtMs:Date.now(),capturedCount:0};try{var d;return await (d=s,new Promise((e,t)=>{let r="",n=setTimeout(()=>{t(new a("COMMAND_FAILED","Android snapshot helper session did not become ready",{output:r,timeoutMs:1e4}))},1e4),i=t=>{(r+=t.toString()).includes(`agentDeviceProtocol=${f}`)&&r.includes("sessionReady=true")&&(clearTimeout(n),e())};d.stdout?.on("data",i),d.stderr?.on("data",i),d.once("exit",(e,i)=>{clearTimeout(n),t(new a("COMMAND_FAILED","Android snapshot helper session exited before ready",{output:r,exitCode:e,signal:i}))}),d.on("error",e=>{clearTimeout(n),t(e)})})),ed.set(e.deviceKey,l),u({phase:"android_snapshot_helper_session_ready",data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),l}catch(e){await eM(l);try{s.kill("SIGTERM")}catch{}throw await ew(s,2e3),e}}function ew(e,t){return new Promise(r=>{let n=setTimeout(r,t);e.once("close",()=>{clearTimeout(n),r()}),e.once("exit",()=>{clearTimeout(n),r()})})}async function em(e,t){let r=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`,n=Math.max(t.timeoutMs+2e3,3e3);return function(e,t){var r;let{headers:n,xml:i}=function(e){let t=e.indexOf("\n\n");if(t<0)throw new a("COMMAND_FAILED","Android snapshot helper session returned malformed output",{response:e});return{headers:function(e){let t={};for(let r of e.split(/\r?\n/)){let e=r.indexOf("=");e<0||(t[r.slice(0,e)]=r.slice(e+1))}return t}(e.slice(0,t)),xml:e.slice(t+2)}}(e);return function(e,t){if(e.agentDeviceProtocol!==f)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong protocol",{headers:e});if(e.outputFormat!==w)throw new a("COMMAND_FAILED","Android snapshot helper session returned wrong output format",{headers:e});if(e.requestId!==t)throw new a("COMMAND_FAILED","Android snapshot helper session returned stale output",{headers:e,requestId:t});if("true"!==e.ok)throw new a("COMMAND_FAILED",e.message||e.errorType||"Android snapshot helper session returned an error",{helper:e})}(n,t),function(e,t){let r=ea(e.byteLength);if(void 0!==r&&Buffer.byteLength(t,"utf8")!==r)throw new a("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 a("COMMAND_FAILED","Android snapshot helper session did not return XML",{headers:e,xml:t})}(n,i),{xml:i,metadata:{helperApiVersion:(r=n).helperApiVersion,outputFormat:w,waitForIdleTimeoutMs:ea(r.waitForIdleTimeoutMs),waitForIdleQuietMs:ea(r.waitForIdleQuietMs),timeoutMs:ea(r.timeoutMs),maxDepth:ea(r.maxDepth),maxNodes:ea(r.maxNodes),rootPresent:es(r.rootPresent),captureMode:"interactive-windows"===r.captureMode||"active-window"===r.captureMode?r.captureMode:void 0,windowCount:ea(r.windowCount),nodeCount:ea(r.nodeCount),truncated:es(r.truncated),elapsedMs:ea(r.elapsedMs)}}}(await eA(e,`snapshot ${r}`,n),r)}function eA(e,t,r){return new Promise((n,i)=>{let s=o.connect({host:"127.0.0.1",port:e.port}),l=[],u=setTimeout(()=>{s.destroy(),i(new a("COMMAND_FAILED","Android snapshot helper session request timed out",{command:t,timeoutMs:r,port:e.port}))},r);s.on("connect",()=>{s.write(`${t}
4
+ `)}),s.on("data",e=>{l.push(Buffer.from(e))}),s.on("error",e=>{clearTimeout(u),i(e)}),s.on("close",()=>{clearTimeout(u),n(Buffer.concat(l).toString("utf8"))})})}async function eM(e){await e.process.stdin?.end(),await e.process.stdout?.destroy(),await e.process.stderr?.destroy(),await eg(e)}async function eg(e){await e.adb(["forward","--remove",`tcp:${e.port}`],{allowFailure:!0,timeoutMs:5e3})}let ev=new Map;function eN(e){ey(ex(e.deviceKey,e.packageName,e.versionCode))}function ex(e,t,r){return e?`${e}\0${t}\0${r}`:void 0}function ey(e){e&&ev.delete(e)}async function eI(e){var t,r,n;let{adb:i,artifact:o}=e,s=e.installPolicy??"missing-or-outdated",l=o.manifest.packageName,u=o.manifest.versionCode;if("never"===s)return{packageName:l,versionCode:u,installed:!1,reason:"skipped"};let d=ex(e.deviceKey,l,u),c=d?ev.get(d):void 0;if(d&&"always"!==s&&void 0!==c)return{packageName:l,versionCode:u,installedVersionCode:c,installed:!1,reason:"current"};let h=await eC(i,l,e.timeoutMs),p=(t=s,r=h,n=u,"never"===t?"skipped":"always"===t?"forced":void 0===r?"missing":r<n?"outdated":"current");if("current"===p){if(void 0===h)throw Error("Expected installed versionCode for current Android snapshot helper");return d&&ev.set(d,h),{packageName:l,versionCode:u,installedVersionCode:h,installed:!1,reason:p}}await A(o);let f=await eD(i,e.adbProvider??i,o.apkPath,function(e){let t={};for(let r of e.slice(1)){let e=b(r);if(!e)throw new a("INVALID_ARGS",`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}(N(o.manifest.installArgs)),{packageName:l,timeoutMs:e.timeoutMs});if(0!==f.exitCode)throw ey(d),new a("COMMAND_FAILED","Failed to install Android snapshot helper",{packageName:l,versionCode:u,stdout:f.stdout,stderr:f.stderr,exitCode:f.exitCode});return d&&ev.set(d,u),{packageName:l,versionCode:u,installedVersionCode:h,installed:!0,reason:p}}async function eC(e,t,r){let n=await e(["shell","cmd","package","list","packages","--show-versioncode",t],{allowFailure:!0,timeoutMs:r});if(0===n.exitCode){var i=`${n.stdout}
5
5
  ${n.stderr}`,o=t;let e=`package:${o}`;for(let t of i.split(/\r?\n/)){if(!t.startsWith(e)||t.length>e.length&&!/\s/.test(t[e.length]??""))continue;let r=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(r)return Number(r[1])}return}}async function eD(e,t,r,n,i){var o;let a=async()=>await d(r,{allowFailure:!0,provider:t,...n,timeoutMs:i.timeoutMs}),s=await a();if(0===s.exitCode||(o=s,!`${o.stdout}
6
- ${o.stderr}`.includes("INSTALL_FAILED_UPDATE_INCOMPATIBLE")))return s;let l=await e(["uninstall",i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs}),u=await a();return 0===u.exitCode?u:{...u,stderr:[u.stderr,l.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${l.stderr}`:""].filter(Boolean).join("\n")}}export{c as ANDROID_SNAPSHOT_HELPER_NAME,w as ANDROID_SNAPSHOT_HELPER_OUTPUT_FORMAT,h as ANDROID_SNAPSHOT_HELPER_PACKAGE,f as ANDROID_SNAPSHOT_HELPER_PROTOCOL,p as ANDROID_SNAPSHOT_HELPER_RUNNER,S as androidUiNodes,T as buildUiHierarchySnapshot,K as captureAndroidSnapshotWithHelper,eh as captureAndroidSnapshotWithHelperSession,eI as ensureAndroidSnapshotHelper,eN as forgetAndroidSnapshotHelperInstall,g as parseAndroidSnapshotHelperManifest,Y as parseAndroidSnapshotHelperOutput,Z as parseAndroidSnapshotHelperXml,k as parseUiHierarchy,P as parseUiHierarchyTree,M as prepareAndroidSnapshotHelperArtifactFromManifestUrl,ep as stopAndroidSnapshotHelperSession,A as verifyAndroidSnapshotHelperArtifact};
6
+ ${o.stderr}`.includes("INSTALL_FAILED_UPDATE_INCOMPATIBLE")))return s;let l=await e(["uninstall",i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs}),u=await a();return 0===u.exitCode?u:{...u,stderr:[u.stderr,l.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${l.stderr}`:""].filter(Boolean).join("\n")}}export{c as ANDROID_SNAPSHOT_HELPER_NAME,w as ANDROID_SNAPSHOT_HELPER_OUTPUT_FORMAT,h as ANDROID_SNAPSHOT_HELPER_PACKAGE,f as ANDROID_SNAPSHOT_HELPER_PROTOCOL,p as ANDROID_SNAPSHOT_HELPER_RUNNER,S as androidUiNodes,k as buildUiHierarchySnapshot,K as captureAndroidSnapshotWithHelper,eh as captureAndroidSnapshotWithHelperSession,eI as ensureAndroidSnapshotHelper,eN as forgetAndroidSnapshotHelperInstall,g as parseAndroidSnapshotHelperManifest,Y as parseAndroidSnapshotHelperOutput,Z as parseAndroidSnapshotHelperXml,T as parseUiHierarchy,P as parseUiHierarchyTree,M as prepareAndroidSnapshotHelperArtifactFromManifestUrl,ep as stopAndroidSnapshotHelperSession,A as verifyAndroidSnapshotHelperArtifact};