agent-device 0.14.5 → 0.14.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- let e,t,s,o,r,a,n,i;import l from"node:path";import{styleText as c}from"node:util";import{pathToFileURL as p}from"node:url";import d from"node:fs";import u from"node:crypto";import{buildMobileSnapshotPresentation as m,SESSION_SURFACES as f,formatSnapshotLine as g,SETTINGS_USAGE_OVERRIDE as h,createAgentDevice as v,displayNodeLabel as y,localCommandPolicy as w,parseDeviceRotation as b,parseWaitArgs as k,buildSnapshotDisplayLines as I}from"../2007.js";import{resolveRemoteConfigProfile as A,resolveRemoteConfigPath as D,REMOTE_CONFIG_FIELD_SPECS as S,parseSourceValue as x,buildPrimaryEnvVarName as $}from"../remote-config.js";import{asAppError as L,normalizeError as N,AppError as R}from"../9152.js";import{ensureCompanionTunnel as C,stopCompanionTunnel as _}from"../1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as E}from"../2301.js";import{createRequestId as O,withDiagnosticsScope as U,getDiagnosticsMeta as P,flushDiagnosticsToSessionFile as T,emitDiagnostic as M}from"../7599.js";import{serializeOpenResult as F,serializeSnapshotResult as B,serializeSessionListEntry as j,serializeDeployResult as V,readCommandMessage as G,serializeCloseResult as q,resolveDaemonPaths as K,serializeEnsureSimulatorResult as H,serializeInstallFromSourceResult as J,serializeDevice as z,readVersion as W}from"../180.js";import{stopMetroTunnel as Y}from"../metro.js";import{runCmdStreaming as Z,runCmd as X}from"../9818.js";import{resolveUserPath as Q,expandUserHomePath as ee}from"../3267.js";import{createLocalArtifactAdapter as et}from"../io.js";import{createAgentDeviceClient as es,CLIENT_COMMANDS as eo,sendToDaemon as er}from"../9542.js";import{splitSelectorFromArgs as ea}from"../940.js";import{isEnvTruthy as en}from"../8809.js";import{parseBatchStepsJson as ei}from"../1231.js";import{maybeRunUpgradeNotifier as el}from"../113.js";function ec(e,t){for(let[s,o]of Object.entries(t))void 0!==o&&(e[s]=o);return e}let ep=["snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"],ed=["snapshotDepth","snapshotScope","snapshotRaw"],eu={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
1
+ let e,t,s,o,r,n,a,i;import l from"node:path";import{styleText as c}from"node:util";import{pathToFileURL as d}from"node:url";import p from"node:fs";import u from"node:crypto";import{buildMobileSnapshotPresentation as m,SESSION_SURFACES as f,formatSnapshotLine as g,SETTINGS_USAGE_OVERRIDE as h,createAgentDevice as v,displayNodeLabel as y,localCommandPolicy as w,parseDeviceRotation as b,parseWaitArgs as k,buildSnapshotDisplayLines as A}from"../2007.js";import{resolveRemoteConfigProfile as I,resolveRemoteConfigPath as D,REMOTE_CONFIG_FIELD_SPECS as S,parseSourceValue as x,buildPrimaryEnvVarName as $}from"../remote-config.js";import{asAppError as C,normalizeError as L,AppError as N}from"../9152.js";import{ensureCompanionTunnel as R,stopCompanionTunnel as _}from"../1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as E}from"../2301.js";import{createRequestId as O,withDiagnosticsScope as U,getDiagnosticsMeta as P,flushDiagnosticsToSessionFile as T,emitDiagnostic as M}from"../7599.js";import{serializeOpenResult as F,serializeSnapshotResult as B,serializeSessionListEntry as j,serializeDeployResult as V,readCommandMessage as G,serializeCloseResult as q,resolveDaemonPaths as H,serializeEnsureSimulatorResult as K,serializeInstallFromSourceResult as J,serializeDevice as z,readVersion as W}from"../180.js";import{stopMetroTunnel as Y}from"../metro.js";import{runCmdStreaming as Z,runCmd as X}from"../9818.js";import{resolveUserPath as Q,expandUserHomePath as ee}from"../3267.js";import{createLocalArtifactAdapter as et}from"../io.js";import{createAgentDeviceClient as es,CLIENT_COMMANDS as eo,sendToDaemon as er}from"../9542.js";import{splitSelectorFromArgs as en}from"../940.js";import{isEnvTruthy as ea}from"../8809.js";import{parseBatchStepsJson as ei}from"../1231.js";import{maybeRunUpgradeNotifier as el}from"../113.js";function ec(e,t){for(let[s,o]of Object.entries(t))void 0!==o&&(e[s]=o);return e}let ed=["snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"],ep=["snapshotDepth","snapshotScope","snapshotRaw"],eu={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
2
2
 
3
3
  Version-matched operating guide for normal agent-device work.
4
4
 
@@ -102,7 +102,7 @@ Validation and evidence:
102
102
  Android animations: settings animations off/on, not animations disable/restore.
103
103
  Debug logs: logs clear --restart, logs mark, reproduce, then logs path; do not split clear/restart into separate stop/start commands.
104
104
  Network headers: network dump --include headers; do not write network log headers.
105
- Remote config: connect --remote-config ./remote-config.json, open, snapshot, disconnect.
105
+ Remote/cloud: connect to discover a cloud profile, or connect --remote-config ./remote-config.json for a local profile; then open, snapshot, disconnect.
106
106
  macOS menu bar: open ... --platform macos --surface menubar; snapshot -i --platform macos --surface menubar.
107
107
 
108
108
  React Native dev loop:
@@ -220,7 +220,8 @@ Rules:
220
220
  @c refs reset after reload/remount. After reload, wait --connected and inspect again.
221
221
  Keep the profile window narrow; unrelated navigation makes render data noisy.
222
222
  For cross-platform validation with explicit device selectors, prefer isolated --state-dir and restart react-devtools between platforms.
223
- Remote Android and iOS bridge runs normally through agent-device react-devtools; the CLI manages the needed local service tunnel. Expo support depends on the SDK's bundled React Native runtime.
223
+ Remote Android and iOS bridge runs normally through agent-device react-devtools; the CLI keeps the needed local service tunnel alive until agent-device react-devtools stop or disconnect. Expo support depends on the SDK's bundled React Native runtime.
224
+ Remote iOS apps attempt the legacy React DevTools websocket during JavaScript startup. If the app was already open before react-devtools start, run open <bundle-id> --platform ios --relaunch, then wait --connected.
224
225
 
225
226
  Example:
226
227
  agent-device react-devtools status
@@ -234,9 +235,15 @@ Example:
234
235
 
235
236
  Use snapshot, screenshot, logs, network, and perf for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},remote:{summary:"Remote config, tenant, lease, and remote host flow",body:`agent-device help remote
236
237
 
237
- Use remote config when a profile owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
238
+ Use remote config or the cloud connection profile when a profile owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
238
239
 
239
- Normal flow:
240
+ Cloud profile flow:
241
+ agent-device connect
242
+ agent-device open com.example.app
243
+ agent-device snapshot
244
+ agent-device disconnect
245
+
246
+ Local profile flow:
240
247
  agent-device connect --remote-config ./remote-config.json
241
248
  agent-device open com.example.app
242
249
  agent-device snapshot
@@ -249,11 +256,12 @@ Script flow, per-command config:
249
256
 
250
257
  Rules:
251
258
  connect and disconnect are top-level commands. Do not write agent-device remote connect or agent-device remote disconnect.
252
- Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id in ordinary remote flows.
259
+ Use connect without --remote-config when the cloud control plane owns the connection profile.
260
+ Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
253
261
  For self-contained scripts, pass the same --remote-config to every operational command, including disconnect; a preceding connect is optional but not required.
254
262
  For remote artifact installs, use install-from-source <url> or install-from-source --github-actions-artifact org/repo:artifact; do not download CI artifacts locally first.
255
263
  After connect, let the active remote connection supply runtime hints.
256
- For remote Android and iOS bridge React DevTools, run agent-device react-devtools normally. The CLI opens the needed local service tunnel for the DevTools daemon and cleans it up when the command exits.
264
+ For remote Android and iOS bridge React DevTools, run agent-device react-devtools normally. The CLI opens the needed local service tunnel for the DevTools daemon and keeps it alive until agent-device react-devtools stop or disconnect.
257
265
  Use --debug when remote connection or transport errors need diagnostic ids and remote log hints.`},macos:{summary:"macOS desktop, frontmost-app, and menu bar surfaces",body:`agent-device help macos
258
266
 
259
267
  Use macOS only when the task targets desktop apps, desktop surfaces, or menu bar extras.
@@ -336,10 +344,10 @@ Rules:
336
344
  Prefer refs for exploration and selectors for deterministic replay.
337
345
  Use logs, network, screenshot --overlay-refs, trace, perf, or react-devtools only when they add evidence to a specific issue.
338
346
  Never delete screenshots, videos, traces, or report artifacts during a session.
339
- Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}},em=[{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:f,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:"runtime",names:["--runtime"],type:"string",usageLabel:"--runtime <id>",usageDescription:"ensure-simulator: CoreSimulator runtime identifier (e.g. com.apple.CoreSimulator.SimRuntime.iOS-18-0)"},{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 (prefer AGENT_DEVICE_PROXY_TOKEN or AGENT_DEVICE_METRO_BEARER_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:"boot",names:["--boot"],type:"boolean",usageLabel:"--boot",usageDescription:"ensure-simulator: boot the simulator after ensuring it exists"},{key:"reuseExisting",names:["--reuse-existing"],type:"boolean",usageLabel:"--reuse-existing",usageDescription:"ensure-simulator: reuse an existing simulator (default: true)"},{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:"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: disable touch overlays in the final video"},{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 and stream daemon/runner 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 iOS simulator 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:"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:"Test: maximum wall-clock time per script 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:["--user-installed"],type:"enum",setValue:"user-installed",usageLabel:"--user-installed",usageDescription:"Apps: list user-installed apps"},{key:"appsFilter",names:["--all"],type:"enum",setValue:"all",usageLabel:"--all",usageDescription:"Apps: list all apps (include system/default 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:"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"},{key:"screenshotFullscreen",names:["--fullscreen"],type:"boolean",usageLabel:"--fullscreen",usageDescription:"Screenshot: capture the full screen instead of the app window"},{key:"screenshotMaxSize",names:["--max-size"],type:"int",min:1,usageLabel:"--max-size <px>",usageDescription:"Screenshot: downscale so the longest edge is at most <px>"},{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)"}],ef=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"]),eg={boot:{helpDescription:"Ensure target device/simulator is booted and ready",summary:"Boot target device/simulator",positionalArgs:[],allowedFlags:["headless"]},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","saveScript","relaunch","surface"]},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",positionalArgs:[],allowedFlags:["force","noLogin","metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps","launchUrl"],skipCapabilityCheck:!0},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",positionalArgs:[],allowedFlags:["shutdown"],skipCapabilityCheck:!0},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"],allowedFlags:[],skipCapabilityCheck:!0},auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"],allowedFlags:[],skipCapabilityCheck:!0},close:{helpDescription:"Close app or just end session",summary:"Close app or end session",positionalArgs:["app?"],allowedFlags:["saveScript","shutdown"]},reinstall:{helpDescription:"Uninstall + install app from binary path",summary:"Reinstall app from binary path",positionalArgs:["app","path"],allowedFlags:[]},install:{helpDescription:"Install app from binary path without uninstalling first",summary:"Install app from binary path",positionalArgs:["app","path"],allowedFlags:[]},"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"]},push:{helpDescription:"Simulate push notification payload delivery",summary:"Deliver push payload",positionalArgs:["bundleOrPackage","payloadOrJson"],allowedFlags:[]},snapshot:{usageOverride:"snapshot [--diff] [-i] [-c] [-d <depth>] [-s <scope>] [--raw]",helpDescription:"Capture accessibility tree or diff against the previous session baseline",positionalArgs:[],allowedFlags:["snapshotDiff",...ep]},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:[...ep,"baseline","threshold","out","overlayRefs"]},"ensure-simulator":{helpDescription:"Ensure an iOS simulator exists in a device set (create if missing)",summary:"Ensure iOS simulator exists",positionalArgs:[],allowedFlags:["runtime","boot","reuseExisting"],skipCapabilityCheck:!0},devices:{helpDescription:"List available devices",positionalArgs:[],allowedFlags:[],skipCapabilityCheck:!0},apps:{helpDescription:"List installed apps (includes default/system apps by default)",summary:"List installed apps",positionalArgs:[],allowedFlags:["appsFilter"],defaults:{appsFilter:"all"}},appstate:{helpDescription:"Show foreground app/activity",positionalArgs:[],allowedFlags:[],skipCapabilityCheck:!0},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:["metroHost","metroPort","metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps","bundleUrl"],skipCapabilityCheck:!0},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,allowedFlags:[]},keyboard:{usageOverride:"keyboard [status|get|dismiss]",helpDescription:"Inspect Android keyboard visibility/type or dismiss the device keyboard",summary:"Inspect or dismiss the device keyboard",positionalArgs:["action?"],allowedFlags:[]},perf:{helpDescription:"Show session performance metrics, including frame health on Android and iOS devices",summary:"Show performance metrics",positionalArgs:[],allowedFlags:[]},"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,allowedFlags:[],skipCapabilityCheck:!0},back:{usageOverride:"back [--in-app|--system]",helpDescription:"Navigate back with explicit app or system semantics",summary:"Go back",positionalArgs:[],allowedFlags:["backMode"]},home:{helpDescription:"Go to home screen (where supported)",summary:"Go home",positionalArgs:[],allowedFlags:[]},rotate:{usageOverride:"rotate <portrait|portrait-upside-down|landscape-left|landscape-right>",helpDescription:"Rotate device orientation on iOS and Android",summary:"Rotate device orientation",positionalArgs:["orientation"],allowedFlags:[]},"app-switcher":{helpDescription:"Open app switcher (where supported)",summary:"Open app switcher",positionalArgs:[],allowedFlags:[]},wait:{usageOverride:"wait <ms>|text <text>|@ref|<selector> [timeoutMs]",helpDescription:"Wait for duration, text, ref, or selector to appear",summary:"Wait for time, text, ref, or selector",positionalArgs:["durationOrSelector","timeoutMs?"],allowsExtraPositionals:!0,allowedFlags:[...ed]},alert:{usageOverride:"alert [get|accept|dismiss|wait] [timeout]",helpDescription:"Inspect or handle alert (iOS simulator and macOS desktop)",summary:"Inspect or handle iOS/macOS alerts",positionalArgs:["action?","timeout?"],allowedFlags:[]},click:{usageOverride:"click <x y|@ref|selector>",helpDescription:"Tap/click by coordinates, snapshot ref, or selector",summary:"Tap by coordinates, ref, or selector",positionalArgs:["target"],allowsExtraPositionals:!0,allowedFlags:["count","intervalMs","holdMs","jitterPx","doubleTap","clickButton",...ed]},get:{usageOverride:"get text|attrs <@ref|selector>",helpDescription:"Return exposed element text/attributes by ref or selector; use snapshot -s @ref for truncated previews",summary:"Get exposed text or attrs by ref or selector",positionalArgs:["subcommand","target"],allowedFlags:[...ed]},replay:{helpDescription:"Replay a recorded session",positionalArgs:["path"],allowedFlags:["replayUpdate","replayEnv"],skipCapabilityCheck:!0},test:{usageOverride:"test <path-or-glob>...",listUsageOverride:"test <path-or-glob>...",helpDescription:"Run one or more .ad scripts as a serial test suite",summary:"Run .ad test suites",positionalArgs:["pathOrGlob"],allowsExtraPositionals:!0,allowedFlags:["replayUpdate","replayEnv","failFast","timeoutMs","retries","artifactsDir","reportJunit"],skipCapabilityCheck:!0},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",positionalArgs:[],allowedFlags:["steps","stepsFile","batchOnError","batchMaxSteps","out"],skipCapabilityCheck:!0},press:{usageOverride:"press <x y|@ref|selector>",helpDescription:"Tap/press by coordinates, snapshot ref, or selector (supports repeated series)",summary:"Press by coordinates, ref, or selector",positionalArgs:["targetOrX","y?"],allowsExtraPositionals:!0,allowedFlags:["count","intervalMs","holdMs","jitterPx","doubleTap",...ed]},longpress:{helpDescription:"Long press by coordinates (iOS and Android)",summary:"Long press by coordinates",positionalArgs:["x","y","durationMs?"],allowedFlags:[]},swipe:{helpDescription:"Swipe coordinates with optional repeat pattern",summary:"Swipe coordinates",positionalArgs:["x1","y1","x2","y2","durationMs?"],allowedFlags:["count","pauseMs","pattern"]},focus:{helpDescription:"Focus input at coordinates",positionalArgs:["x","y"],allowedFlags:[]},type:{helpDescription:"Type text in focused field",positionalArgs:["text"],allowsExtraPositionals:!0,allowedFlags:["delayMs"]},fill:{usageOverride:"fill <x> <y> <text> | fill <@ref|selector> <text>",helpDescription:"Tap then type",positionalArgs:["targetOrX","yOrText","text?"],allowsExtraPositionals:!0,allowedFlags:[...ed,"delayMs"]},scroll:{usageOverride:"scroll <direction> [amount] [--pixels <n>]",helpDescription:"Scroll in direction (relative amount or explicit pixels)",summary:"Scroll in a direction",positionalArgs:["direction","amount?"],allowedFlags:["pixels"]},pinch:{helpDescription:"Pinch/zoom gesture (Apple simulator or macOS app session)",positionalArgs:["scale","x?","y?"],allowedFlags:[]},screenshot:{helpDescription:"Capture screenshot (macOS app sessions default to the app window; use --fullscreen for full desktop, --max-size to downscale, or --overlay-refs to annotate the image with current refs)",positionalArgs:["path?"],allowedFlags:["out","overlayRefs","screenshotFullscreen","screenshotMaxSize"]},"trigger-app-event":{usageOverride:"trigger-app-event <event> [payloadJson]",helpDescription:"Trigger app-defined event hook via deep link template",summary:"Trigger app event hook",positionalArgs:["event","payloadJson?"],allowedFlags:[]},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",summary:"Start or stop screen recording",positionalArgs:["start|stop","path?"],allowedFlags:["fps","quality","hideTouches"]},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?"],allowedFlags:[],skipCapabilityCheck:!0},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"]},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:{helpDescription:"Assert UI state (visible|hidden|exists|editable|selected|text)",summary:"Assert UI state",positionalArgs:["predicate","selector","value?"],allowsExtraPositionals:!0,allowedFlags:[...ed]},settings:{usageOverride:h,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?"],allowedFlags:[]},session:{usageOverride:"session list",helpDescription:"List active sessions",positionalArgs:["list?"],allowedFlags:[],skipCapabilityCheck:!0}},eh=new Map,ev=new Map;for(let e of em){for(let t of e.names)eh.set(t,e);let t=ev.get(e.key);t?t.push(e):ev.set(e.key,[e])}function ey(e){if(e)return eg[e]}function ew(){return Object.keys(eg)}function eb(e){let t=e.endsWith("?"),s=t?e.slice(0,-1):e;return t?`[${s}]`:`<${s}>`}let ek=(e=`agent-device <command> [args] [--json]
347
+ Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}},em=[{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:f,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:"runtime",names:["--runtime"],type:"string",usageLabel:"--runtime <id>",usageDescription:"ensure-simulator: CoreSimulator runtime identifier (e.g. com.apple.CoreSimulator.SimRuntime.iOS-18-0)"},{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 (prefer AGENT_DEVICE_PROXY_TOKEN or AGENT_DEVICE_METRO_BEARER_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:"boot",names:["--boot"],type:"boolean",usageLabel:"--boot",usageDescription:"ensure-simulator: boot the simulator after ensuring it exists"},{key:"reuseExisting",names:["--reuse-existing"],type:"boolean",usageLabel:"--reuse-existing",usageDescription:"ensure-simulator: reuse an existing simulator (default: true)"},{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:"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: disable touch overlays in the final video"},{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 and stream daemon/runner 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 iOS simulator 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:"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:"Test: maximum wall-clock time per script 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:["--user-installed"],type:"enum",setValue:"user-installed",usageLabel:"--user-installed",usageDescription:"Apps: list user-installed apps"},{key:"appsFilter",names:["--all"],type:"enum",setValue:"all",usageLabel:"--all",usageDescription:"Apps: list all apps (include system/default 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:"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"},{key:"screenshotFullscreen",names:["--fullscreen"],type:"boolean",usageLabel:"--fullscreen",usageDescription:"Screenshot: capture the full screen instead of the app window"},{key:"screenshotMaxSize",names:["--max-size"],type:"int",min:1,usageLabel:"--max-size <px>",usageDescription:"Screenshot: downscale so the longest edge is at most <px>"},{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)"}],ef=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"]),eg={boot:{helpDescription:"Ensure target device/simulator is booted and ready",summary:"Boot target device/simulator",positionalArgs:[],allowedFlags:["headless"]},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","saveScript","relaunch","surface"]},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",positionalArgs:[],allowedFlags:["force","noLogin","metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps","launchUrl"],skipCapabilityCheck:!0},disconnect:{helpDescription:"Disconnect remote daemon state, stop owned Metro companion, and release lease",summary:"Disconnect remote daemon",positionalArgs:[],allowedFlags:["shutdown"],skipCapabilityCheck:!0},connection:{usageOverride:"connection status",listUsageOverride:"connection status",helpDescription:"Inspect active remote connection state",summary:"Inspect remote connection",positionalArgs:["status"],allowedFlags:[],skipCapabilityCheck:!0},auth:{usageOverride:"auth status|login|logout",listUsageOverride:"auth status|login|logout",helpDescription:"Manage cloud CLI authentication",summary:"Manage cloud authentication",positionalArgs:["status|login|logout"],allowedFlags:[],skipCapabilityCheck:!0},close:{helpDescription:"Close app or just end session",summary:"Close app or end session",positionalArgs:["app?"],allowedFlags:["saveScript","shutdown"]},reinstall:{helpDescription:"Uninstall + install app from binary path",summary:"Reinstall app from binary path",positionalArgs:["app","path"],allowedFlags:[]},install:{helpDescription:"Install app from binary path without uninstalling first",summary:"Install app from binary path",positionalArgs:["app","path"],allowedFlags:[]},"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"]},push:{helpDescription:"Simulate push notification payload delivery",summary:"Deliver push payload",positionalArgs:["bundleOrPackage","payloadOrJson"],allowedFlags:[]},snapshot:{usageOverride:"snapshot [--diff] [-i] [-c] [-d <depth>] [-s <scope>] [--raw]",helpDescription:"Capture accessibility tree or diff against the previous session baseline",positionalArgs:[],allowedFlags:["snapshotDiff",...ed]},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:[...ed,"baseline","threshold","out","overlayRefs"]},"ensure-simulator":{helpDescription:"Ensure an iOS simulator exists in a device set (create if missing)",summary:"Ensure iOS simulator exists",positionalArgs:[],allowedFlags:["runtime","boot","reuseExisting"],skipCapabilityCheck:!0},devices:{helpDescription:"List available devices",positionalArgs:[],allowedFlags:[],skipCapabilityCheck:!0},apps:{helpDescription:"List installed apps (includes default/system apps by default)",summary:"List installed apps",positionalArgs:[],allowedFlags:["appsFilter"],defaults:{appsFilter:"all"}},appstate:{helpDescription:"Show foreground app/activity",positionalArgs:[],allowedFlags:[],skipCapabilityCheck:!0},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:["metroHost","metroPort","metroProjectRoot","metroKind","metroPublicBaseUrl","metroProxyBaseUrl","metroBearerToken","metroPreparePort","metroListenHost","metroStatusHost","metroStartupTimeoutMs","metroProbeTimeoutMs","metroRuntimeFile","metroNoReuseExisting","metroNoInstallDeps","bundleUrl"],skipCapabilityCheck:!0},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,allowedFlags:[]},keyboard:{usageOverride:"keyboard [status|get|dismiss]",helpDescription:"Inspect Android keyboard visibility/type or dismiss the device keyboard",summary:"Inspect or dismiss the device keyboard",positionalArgs:["action?"],allowedFlags:[]},perf:{helpDescription:"Show session performance metrics, including frame health on Android and iOS devices",summary:"Show performance metrics",positionalArgs:[],allowedFlags:[]},"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,allowedFlags:[],skipCapabilityCheck:!0},back:{usageOverride:"back [--in-app|--system]",helpDescription:"Navigate back with explicit app or system semantics",summary:"Go back",positionalArgs:[],allowedFlags:["backMode"]},home:{helpDescription:"Go to home screen (where supported)",summary:"Go home",positionalArgs:[],allowedFlags:[]},rotate:{usageOverride:"rotate <portrait|portrait-upside-down|landscape-left|landscape-right>",helpDescription:"Rotate device orientation on iOS and Android",summary:"Rotate device orientation",positionalArgs:["orientation"],allowedFlags:[]},"app-switcher":{helpDescription:"Open app switcher (where supported)",summary:"Open app switcher",positionalArgs:[],allowedFlags:[]},wait:{usageOverride:"wait <ms>|text <text>|@ref|<selector> [timeoutMs]",helpDescription:"Wait for duration, text, ref, or selector to appear",summary:"Wait for time, text, ref, or selector",positionalArgs:["durationOrSelector","timeoutMs?"],allowsExtraPositionals:!0,allowedFlags:[...ep]},alert:{usageOverride:"alert [get|accept|dismiss|wait] [timeout]",helpDescription:"Inspect or handle alert (iOS simulator and macOS desktop)",summary:"Inspect or handle iOS/macOS alerts",positionalArgs:["action?","timeout?"],allowedFlags:[]},click:{usageOverride:"click <x y|@ref|selector>",helpDescription:"Tap/click by coordinates, snapshot ref, or selector",summary:"Tap by coordinates, ref, or selector",positionalArgs:["target"],allowsExtraPositionals:!0,allowedFlags:["count","intervalMs","holdMs","jitterPx","doubleTap","clickButton",...ep]},get:{usageOverride:"get text|attrs <@ref|selector>",helpDescription:"Return exposed element text/attributes by ref or selector; use snapshot -s @ref for truncated previews",summary:"Get exposed text or attrs by ref or selector",positionalArgs:["subcommand","target"],allowedFlags:[...ep]},replay:{helpDescription:"Replay a recorded session",positionalArgs:["path"],allowedFlags:["replayUpdate","replayEnv"],skipCapabilityCheck:!0},test:{usageOverride:"test <path-or-glob>...",listUsageOverride:"test <path-or-glob>...",helpDescription:"Run one or more .ad scripts as a serial test suite",summary:"Run .ad test suites",positionalArgs:["pathOrGlob"],allowsExtraPositionals:!0,allowedFlags:["replayUpdate","replayEnv","failFast","timeoutMs","retries","artifactsDir","reportJunit"],skipCapabilityCheck:!0},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",positionalArgs:[],allowedFlags:["steps","stepsFile","batchOnError","batchMaxSteps","out"],skipCapabilityCheck:!0},press:{usageOverride:"press <x y|@ref|selector>",helpDescription:"Tap/press by coordinates, snapshot ref, or selector (supports repeated series)",summary:"Press by coordinates, ref, or selector",positionalArgs:["targetOrX","y?"],allowsExtraPositionals:!0,allowedFlags:["count","intervalMs","holdMs","jitterPx","doubleTap",...ep]},longpress:{helpDescription:"Long press by coordinates (iOS and Android)",summary:"Long press by coordinates",positionalArgs:["x","y","durationMs?"],allowedFlags:[]},swipe:{helpDescription:"Swipe coordinates with optional repeat pattern",summary:"Swipe coordinates",positionalArgs:["x1","y1","x2","y2","durationMs?"],allowedFlags:["count","pauseMs","pattern"]},focus:{helpDescription:"Focus input at coordinates",positionalArgs:["x","y"],allowedFlags:[]},type:{helpDescription:"Type text in focused field",positionalArgs:["text"],allowsExtraPositionals:!0,allowedFlags:["delayMs"]},fill:{usageOverride:"fill <x> <y> <text> | fill <@ref|selector> <text>",helpDescription:"Tap then type",positionalArgs:["targetOrX","yOrText","text?"],allowsExtraPositionals:!0,allowedFlags:[...ep,"delayMs"]},scroll:{usageOverride:"scroll <direction> [amount] [--pixels <n>]",helpDescription:"Scroll in direction (relative amount or explicit pixels)",summary:"Scroll in a direction",positionalArgs:["direction","amount?"],allowedFlags:["pixels"]},pinch:{helpDescription:"Pinch/zoom gesture (Apple simulator or macOS app session)",positionalArgs:["scale","x?","y?"],allowedFlags:[]},screenshot:{helpDescription:"Capture screenshot (macOS app sessions default to the app window; use --fullscreen for full desktop, --max-size to downscale, or --overlay-refs to annotate the image with current refs)",positionalArgs:["path?"],allowedFlags:["out","overlayRefs","screenshotFullscreen","screenshotMaxSize"]},"trigger-app-event":{usageOverride:"trigger-app-event <event> [payloadJson]",helpDescription:"Trigger app-defined event hook via deep link template",summary:"Trigger app event hook",positionalArgs:["event","payloadJson?"],allowedFlags:[]},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",summary:"Start or stop screen recording",positionalArgs:["start|stop","path?"],allowedFlags:["fps","quality","hideTouches"]},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?"],allowedFlags:[],skipCapabilityCheck:!0},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"]},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:{helpDescription:"Assert UI state (visible|hidden|exists|editable|selected|text)",summary:"Assert UI state",positionalArgs:["predicate","selector","value?"],allowsExtraPositionals:!0,allowedFlags:[...ep]},settings:{usageOverride:h,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?"],allowedFlags:[]},session:{usageOverride:"session list",helpDescription:"List active sessions",positionalArgs:["list?"],allowedFlags:[],skipCapabilityCheck:!0}},eh=new Map,ev=new Map;for(let e of em){for(let t of e.names)eh.set(t,e);let t=ev.get(e.key);t?t.push(e):ev.set(e.key,[e])}function ey(e){if(e)return eg[e]}function ew(){return Object.keys(eg)}function eb(e){let t=e.endsWith("?"),s=t?e.slice(0,-1):e;return t?`[${s}]`:`<${s}>`}let ek=(e=`agent-device <command> [args] [--json]
340
348
 
341
349
  CLI to control iOS and Android devices for AI agents.
342
- `,t=eD("Commands:",ew().map(e=>{let t=eg[e];if(!t)throw Error(`Missing command schema for ${e}`);return{name:e,schema:t,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let s=t.positionalArgs.map(s=>{var o,r,a;let n,i,l,c;return o=e,r=t,i=(n=(a=s).endsWith("?"))?a.slice(0,-1):a,c=(l=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==r.usageOverride&&r.usageOverride.startsWith(`${o} ${i}`),n?l?`[${i}]`:c?i:`[${i}]`:c?i:`<${i}>`});return[e,...s].join(" ")}(e,t)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),s=eA("Flags:",eI(ef)),o=eS("Agent Quickstart:",["Default loop: devices/apps -> open -> snapshot -i -> press/fill/get/is/wait/find -> verify -> close.",'Use selectors or refs as positional targets: id="submit", label="Allow", or @e12 from snapshot -i.',"Plain snapshot reads state; snapshot -i is required to refresh interactive refs.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","RN warning/error overlays can block taps: snapshot -i, dismiss/close, then diff snapshot -i.",'Expo Go/dev clients: use the provided URL when given; on iOS prefer open "Expo Go" <url>; Android URL opens infer the foreground package for logs/perf when possible.',"Install flows: install/install-from-source first, then open the installed id with --relaunch.",'Text: fill \'id="field-email"\' "qa@example.com" replaces; type appends after press.','Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.',"Run mutating commands serially against one session; parallelize only read-only commands or separate sessions.","Clipboard limits: iOS Allow Paste cannot be automated through XCUITest; prefill with clipboard write. Android non-ASCII should use fill/type, not raw adb input.","After mutation: diff snapshot -i. Off-screen hints: scroll, then snapshot -i.","Raw coordinates are fallback-only: use snapshot -i -c --json rects when iOS refs no-op or child refs are missing.",'Batch JSON steps use "command", "positionals", "flags"; never "args" or "step".',"Navigation: app-owned back uses back; system back uses back --system.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: logs clear --restart/mark/path; trace start ./path; trace stop ./path; network dump --include headers.","Use agent-device commands in final plans; raw platform tools, pseudo commands, and helper prose are wrong.","Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood."]),r=eD("Agent Workflows:",[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, alerts, diagnostics, and traces"},{label:"help react-devtools",description:"React Native performance, profiling, component tree, and renders"},{label:"help remote",description:"Remote/cloud config, tenants, leases, and local service tunnels"},{label:"help macos",description:"Desktop, frontmost-app, and menu bar surfaces"},{label:"help dogfood",description:"Exploratory QA report workflow"}]),a=eS("Configuration:",["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."]),n=eD("Environment:",[{label:"AGENT_DEVICE_SESSION",description:"Default session name"},{label:"AGENT_DEVICE_PLATFORM",description:"Default platform binding"},{label:"AGENT_DEVICE_SESSION_LOCK",description:"Bound-session conflict mode"},{label:"AGENT_DEVICE_DAEMON_BASE_URL",description:"Connect to remote daemon"},{label:"AGENT_DEVICE_DAEMON_AUTH_TOKEN",description:"Remote daemon service/API token"},{label:"AGENT_DEVICE_CLOUD_BASE_URL",description:"Bridge/control-plane API origin for cloud auth and /api-keys"}]),i=eS("Examples:",["agent-device open Settings --platform ios","agent-device open TextEdit --platform macos","agent-device snapshot -i","agent-device react-devtools get tree --depth 3",'agent-device fill @e3 "test@example.com"',"agent-device replay ./session.ad","agent-device test ./suite --platform android"]),`${e}
350
+ `,t=eD("Commands:",ew().map(e=>{let t=eg[e];if(!t)throw Error(`Missing command schema for ${e}`);return{name:e,schema:t,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let s=t.positionalArgs.map(s=>{var o,r,n;let a,i,l,c;return o=e,r=t,i=(a=(n=s).endsWith("?"))?n.slice(0,-1):n,c=(l=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==r.usageOverride&&r.usageOverride.startsWith(`${o} ${i}`),a?l?`[${i}]`:c?i:`[${i}]`:c?i:`<${i}>`});return[e,...s].join(" ")}(e,t)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),s=eI("Flags:",eA(ef)),o=eS("Agent Quickstart:",["Default loop: devices/apps -> open -> snapshot -i -> press/fill/get/is/wait/find -> verify -> close.",'Use selectors or refs as positional targets: id="submit", label="Allow", or @e12 from snapshot -i.',"Plain snapshot reads state; snapshot -i is required to refresh interactive refs.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","RN warning/error overlays can block taps: snapshot -i, dismiss/close, then diff snapshot -i.",'Expo Go/dev clients: use the provided URL when given; on iOS prefer open "Expo Go" <url>; Android URL opens infer the foreground package for logs/perf when possible.',"Install flows: install/install-from-source first, then open the installed id with --relaunch.",'Text: fill \'id="field-email"\' "qa@example.com" replaces; type appends after press.','Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.',"Run mutating commands serially against one session; parallelize only read-only commands or separate sessions.","Clipboard limits: iOS Allow Paste cannot be automated through XCUITest; prefill with clipboard write. Android non-ASCII should use fill/type, not raw adb input.","After mutation: diff snapshot -i. Off-screen hints: scroll, then snapshot -i.","Raw coordinates are fallback-only: use snapshot -i -c --json rects when iOS refs no-op or child refs are missing.",'Batch JSON steps use "command", "positionals", "flags"; never "args" or "step".',"Navigation: app-owned back uses back; system back uses back --system.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: logs clear --restart/mark/path; trace start ./path; trace stop ./path; network dump --include headers.","Use agent-device commands in final plans; raw platform tools, pseudo commands, and helper prose are wrong.","Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood."]),r=eD("Agent Workflows:",[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, alerts, diagnostics, and traces"},{label:"help react-devtools",description:"React Native performance, profiling, component tree, and renders"},{label:"help remote",description:"Remote/cloud config, tenants, leases, and local service tunnels"},{label:"help macos",description:"Desktop, frontmost-app, and menu bar surfaces"},{label:"help dogfood",description:"Exploratory QA report workflow"}]),n=eS("Configuration:",["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."]),a=eD("Environment:",[{label:"AGENT_DEVICE_SESSION",description:"Default session name"},{label:"AGENT_DEVICE_PLATFORM",description:"Default platform binding"},{label:"AGENT_DEVICE_SESSION_LOCK",description:"Bound-session conflict mode"},{label:"AGENT_DEVICE_DAEMON_BASE_URL",description:"Connect to remote daemon"},{label:"AGENT_DEVICE_DAEMON_AUTH_TOKEN",description:"Remote daemon service/API token"},{label:"AGENT_DEVICE_CLOUD_BASE_URL",description:"Bridge/control-plane API origin for cloud auth and /api-keys"}]),i=eS("Examples:",["agent-device open Settings --platform ios","agent-device open TextEdit --platform macos","agent-device snapshot -i","agent-device react-devtools get tree --depth 3",'agent-device fill @e3 "test@example.com"',"agent-device replay ./session.ad","agent-device test ./suite --platform android"]),`${e}
343
351
  ${t}
344
352
 
345
353
  ${s}
@@ -348,60 +356,61 @@ ${o}
348
356
 
349
357
  ${r}
350
358
 
351
- ${a}
352
-
353
359
  ${n}
354
360
 
361
+ ${a}
362
+
355
363
  ${i}
356
- `);function eI(e){return em.filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function eA(e,t){return eD(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function eD(e,t){if(0===t.length)return`${e}
364
+ `);function eA(e){return em.filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function eI(e,t){return eD(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function eD(e,t){if(0===t.length)return`${e}
357
365
  (none)`;let s=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(s)}${e.description}`);return o.join("\n")}function eS(e,t){return 0===t.length?`${e}
358
- (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let ex=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),e$={iosSimulatorDeviceSet:["IOS_SIMULATOR_DEVICE_SET"],androidDeviceAllowlist:["ANDROID_DEVICE_ALLOWLIST"],metroBearerToken:["AGENT_DEVICE_PROXY_TOKEN"]},eL=function(){let e=new Map;for(let t of em){let s=e.get(t.key);s?s.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ef)t.set(e,new Set(["*"]));for(let e of ew()){let s=ey(e);if(s)for(let o of s.allowedFlags){let s=t.get(o);s&&s.has("*")||(s?s.add(e):t.set(o,new Set([e])))}}return[...e.entries()].map(([e,s])=>({key:e,flagDefinitions:s,config:{enabled:!ex.has(e),key:e},env:{names:[$(e),...e$[e]??[]]},supportsCommand(s){let o=t.get(e);return!!o&&(!!o.has("*")||!!s&&o.has(s))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eN=new Map(eL.map(e=>[e.key,e]));function eR(e,t){return eN.get(e)?.supportsCommand(t)??!1}function eC(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let s=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===s.type){let t=e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...s,setValue:void 0,enumValues:t}}return s}function e_(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eE(e){return e.replace(/^-+/,"")}function eO(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?e_(e):[e,void 0];return void 0!==eh.get(t)}function eU(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eP(e){process.stdout.write(`${JSON.stringify(e,null,2)}
359
- `)}function eT(e,t={}){let s=e instanceof R?N(e):e;process.stderr.write(`Error (${s.code}): ${s.message}
366
+ (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let ex=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),e$={iosSimulatorDeviceSet:["IOS_SIMULATOR_DEVICE_SET"],androidDeviceAllowlist:["ANDROID_DEVICE_ALLOWLIST"],metroBearerToken:["AGENT_DEVICE_PROXY_TOKEN"]},eC=function(){let e=new Map;for(let t of em){let s=e.get(t.key);s?s.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ef)t.set(e,new Set(["*"]));for(let e of ew()){let s=ey(e);if(s)for(let o of s.allowedFlags){let s=t.get(o);s&&s.has("*")||(s?s.add(e):t.set(o,new Set([e])))}}return[...e.entries()].map(([e,s])=>({key:e,flagDefinitions:s,config:{enabled:!ex.has(e),key:e},env:{names:[$(e),...e$[e]??[]]},supportsCommand(s){let o=t.get(e);return!!o&&(!!o.has("*")||!!s&&o.has(s))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eL=new Map(eC.map(e=>[e.key,e]));function eN(e,t){return eL.get(e)?.supportsCommand(t)??!1}function eR(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let s=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===s.type){let t=e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...s,setValue:void 0,enumValues:t}}return s}function e_(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eE(e){return e.replace(/^-+/,"")}function eO(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?e_(e):[e,void 0];return void 0!==eh.get(t)}function eU(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eP(e){process.stdout.write(`${JSON.stringify(e,null,2)}
367
+ `)}function eT(e,t={}){let s=e instanceof N?L(e):e;process.stderr.write(`Error (${s.code}): ${s.message}
360
368
  `),s.hint&&process.stderr.write(`Hint: ${s.hint}
361
369
  `),s.diagnosticId&&process.stderr.write(`Diagnostic ID: ${s.diagnosticId}
362
370
  `),s.logPath&&process.stderr.write(`Diagnostics Log: ${s.logPath}
363
371
  `),t.showDetails&&s.details&&process.stderr.write(`${JSON.stringify(s.details,null,2)}
364
372
  `)}function eM(e){return e&&e.summaryLines.length>0?`
365
- ${e.summaryLines.join("\n")}`:""}function eF(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function eB(e){return e>0?`+${e}`:String(e)}function ej(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",s=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${s}`}function eV(e){return e.min===e.max?eB(e.min):`${eB(e.min)}..${eB(e.max)}`}function eG(e){let t=process.cwd(),s=l.relative(t,e);return""!==s&&(s.startsWith("..")||l.isAbsolute(s))?e:""===s?".":`.${l.sep}${s}`}function eq(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function eK(){let e=process.env.FORCE_COLOR;return"string"==typeof e?"0"!==e:"string"!=typeof process.env.NO_COLOR&&!!process.stdout.isTTY}function eH(e,t){return t?c("dim",e):e}function eJ(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function ez(e,t){var s;let o="scroll-area"===(s=e.type)||"list"===s||"collection"===s||"table"===s?s:null;if(!o)return[];let r=[];if(e.node.hiddenContentAbove&&"below"!==t&&r.push(`[content above ${o} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&r.push(`[content below ${o} hidden]`),0===r.length)return[];let a=" ".repeat(e.depth+1);return r.map(e=>`${a}${e}`)}let eW={slug:"react-devtools-companion",runArg:E,displayName:"React DevTools companion"};async function eY(e){return await C({...e,definition:eW,localBaseUrl:e.localBaseUrl??"http://127.0.0.1:8097",registerPath:"/api/react-devtools/companion/register",unregisterPath:"/api/react-devtools/companion/unregister",devicePort:e.devicePort??8097})}async function eZ(e){return await _({...e,definition:eW})}function eX(e){var t;let s,o=e3(e);if(!d.existsSync(o))return null;try{s=JSON.parse(d.readFileSync(o,"utf8"))}catch(t){return e7(e,t),null}return!(!(t=s)||"object"!=typeof t||Array.isArray(t))&&1===t.version&&"string"==typeof t.session&&"string"==typeof t.remoteConfigPath&&"string"==typeof t.remoteConfigHash&&(void 0===t.daemon||"object"==typeof t.daemon&&null!==t.daemon&&!Array.isArray(t.daemon))&&"string"==typeof t.tenant&&"string"==typeof t.runId&&(void 0===t.leaseId||"string"==typeof t.leaseId)&&(void 0===t.leaseBackend||"string"==typeof t.leaseBackend)&&"string"==typeof t.connectedAt&&"string"==typeof t.updatedAt?s:(e7(e),null)}function eQ(e){let t=e3({stateDir:e.stateDir,session:e.state.session});d.mkdirSync(l.dirname(t),{recursive:!0}),e6(t,e.state),e6(e5(e.stateDir),{session:e.state.session})}function e0(e){return{baseUrl:function(e){if(!e)return;let t=new URL(e);for(let e of(t.username="",t.password="",[...t.searchParams.keys()]))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,"")}(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function e1(e){d.rmSync(e3(e),{force:!0});let t=e5(e.stateDir);e4(e.stateDir)===e.session&&d.rmSync(t,{force:!0})}function e2(e){try{return u.createHash("sha256").update(d.readFileSync(e)).digest("hex")}catch(t){throw new R("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function e3(e){return l.join(e.stateDir,"remote-connections",`${function(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,"_");if(!t)return"default";if(t===e)return t;let s=u.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${s}`}(e.session)}.json`)}function e5(e){return l.join(e,"remote-connections",".active-session.json")}function e8(e){let t=e4(e.stateDir);return t?eX({stateDir:e.stateDir,session:t}):null}function e4(e){let t=e5(e);if(d.existsSync(t))try{let e=JSON.parse(d.readFileSync(t,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function e6(e,t){d.writeFileSync(e,`${JSON.stringify(t,null,2)}
366
- `,{encoding:"utf8",mode:384}),d.chmodSync(e,384)}function e7(e,t){M({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),e1(e)}let e9=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]),te=new Set(["open"]);async function tt(e){let t,s,{command:o,flags:r,client:a}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let n=K(r.stateDir).baseDir,i=A({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),l={...function(e){let t={};for(let s of S){let o=e[s.key];void 0!==o&&(t[s.key]=o)}return t}(i.profile),...r,remoteConfig:i.resolvedPath},c=eX({stateDir:n,session:l.session??"default"});if(c&&c.remoteConfigPath!==i.resolvedPath)throw new R("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:i.resolvedPath});let p=c??function(e,t){if(!e.tenant)throw new R("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new R("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new R("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let s=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:e2(t),daemon:e0(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??tn(e),platform:e.platform,target:e.target,connectedAt:s,updatedAt:s}}(l,i.resolvedPath),d={...l,session:p.session},u=function(e,t){if(e)return tl(e,t)?e:void 0}(p.runtime,d.platform)??e.runtime,m=p,f=!c;if(g=o,!e9.has(g)){let e=p.leaseBackend??function(e,t){let s=tn(e);if(s)return s;throw new R("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(r,o);var g,h,v,y,w,b=p,k=r,I=e;if(b.leaseBackend&&b.leaseBackend!==I)throw new R("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:b.session,leaseBackend:b.leaseBackend});if(b.platform&&k.platform&&b.platform!==k.platform)throw new R("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:b.session,platform:b.platform});if(b.target&&k.target&&b.target!==k.target)throw new R("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:b.session,target:b.target});let t=await tc(a,m,e);d.leaseId=t.leaseId,d.leaseBackend=e,d.platform=m.platform??d.platform,d.target=m.target??d.target,(m.leaseId!==t.leaseId||m.leaseBackend!==e)&&(m={...m,leaseId:t.leaseId,leaseBackend:e,platform:m.platform??r.platform,target:m.target??r.target,updatedAt:new Date().toISOString()},f=!0)}if(h=o,v=e.batchSteps,(te.has(h)||"batch"===h&&v&&v.some(e=>{let t=e.command.trim().toLowerCase();return te.has(t)&&void 0===e.runtime}))&&ti(d)&&(!m.leaseId&&d.leaseId&&(m={...m,leaseId:d.leaseId,leaseBackend:d.leaseBackend}),e.forceRuntimePrepare||!u||!tl(u,d.platform))){if(!m.leaseId)throw new R("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await ts(d,a,p.remoteConfigPath,p.session,{tenantId:p.tenant,runId:p.runId,leaseId:m.leaseId});u=e.runtime;let r=(y=m.metro,w=e.cleanup,y?.projectRoot!==w?.projectRoot||y?.profileKey!==w?.profileKey||y?.consumerKey!==w?.consumerKey);t=r?m.metro:void 0,s=r?e.cleanup:void 0,m={...m,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},f=!0}if(f)try{eQ({stateDir:n,state:m})}catch(e){throw await to(s),e}return await to(t),{flags:{...d,session:m.session,leaseId:m.leaseId,leaseBackend:m.leaseBackend,platform:m.platform??d.platform,target:m.target??d.target},runtime:u}}async function ts(e,t,s,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new R("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new R("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let a=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:e.metroKind,publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:s,companionConsumerKey:o,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?a.iosRuntime:a.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:a.projectRoot,profileKey:s,consumerKey:o}:void 0}}async function to(e){if(e)try{await Y(e)}catch{}}async function tr(e){try{await eZ({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function ta(e,t){if(t.leaseId)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,daemonBaseUrl:t.daemon?.baseUrl,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode})}catch{}}function tn(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function ti(e){return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||e.metroKind)}function tl(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function tc(e,t,s){if(t.leaseId&&t.leaseBackend===s){let o=await tp(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:s});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:s})}async function tp(e,t,s){try{return await e.leases.heartbeat({tenant:s.tenant,runId:s.runId,leaseId:t,leaseBackend:s.leaseBackend})}catch(e){var o;if((o=e)instanceof R&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}function td(e){return{platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,androidDeviceAllowlist:e.androidDeviceAllowlist}}function tu(e,t,s){var o;if(e.json)return void eP({success:!0,data:t});let r=s?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
367
- `))}function tm(e,t){tu(e,t,()=>G(t))}let tf=async({positionals:e,flags:t,client:s})=>{if("list"!==(e[0]??"list"))throw new R("INVALID_ARGS","session only supports list");let o={sessions:(await s.sessions.list()).map(j)};return tu(t,o,()=>JSON.stringify(o,null,2)),!0},tg=async({flags:e,client:t})=>{let s=await t.devices.list(td(e));return tu(e,{devices:s.map(z)},()=>s.map(th).join("\n")),!0};function th(e){let t=e.kind?` ${e.kind}`:"",s=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${s})${o}`}let tv=async({flags:e,client:t})=>{if(!e.device)throw new R("INVALID_ARGS","ensure-simulator requires --device <name>");let s=await t.simulators.ensure({device:e.device,runtime:e.runtime,boot:e.boot,reuseExisting:e.reuseExisting,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet});return tu(e,H(s),()=>{let e=s.created?"Created":"Reused",t=s.booted?" (booted)":"";return s.runtime?`${e}: ${s.device} ${s.udid}${t}
368
- Runtime: ${s.runtime}`:`${e}: ${s.device} ${s.udid}${t}`}),!0},ty=async({positionals:e,flags:t,client:s})=>{let o=(e[0]??"").toLowerCase();if("reload"===o){let e=await s.metro.reload({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs});return tu(t,e,()=>`Reloaded React Native apps via ${e.reloadUrl}`),!0}if("prepare"!==o)throw new R("INVALID_ARGS","metro requires a subcommand: prepare or reload");if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new R("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let r=await s.metro.prepare({projectRoot:t.metroProjectRoot,kind:t.metroKind,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:t.tenant&&t.runId&&t.leaseId?{tenantId:t.tenant,runId:t.runId,leaseId:t.leaseId}:void 0,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return tu(t,r,()=>JSON.stringify(r,null,2)),!0},tw=async({flags:e,client:t})=>{let s=await t.apps.list({...td(e),appsFilter:e.appsFilter});return tu(e,{apps:s},()=>s.join("\n")),!0};function tb(e,t,s,o){var r;return"number"==typeof s||"string"==typeof(r=s)&&/^\d+$/.test(r.trim())?{kind:"github-actions-artifact",owner:e,repo:t,artifactId:function(e,t){let s="number"==typeof e?e:"string"==typeof e?Number(e):NaN;if(!Number.isInteger(s))throw new R("INVALID_ARGS",`${t} must be an integer.`);return s}(s,o)}:{kind:"github-actions-artifact",owner:e,repo:t,artifactName:tI(s,o)}}function tk(e,t){let s=e.indexOf("/");if(s<=0||s===e.length-1||-1!==e.indexOf("/",s+1))throw new R("INVALID_ARGS",`${t} must use owner/repo.`);let o={owner:e.slice(0,s).trim(),repo:e.slice(s+1).trim()};if(!o.owner||!o.repo)throw new R("INVALID_ARGS",`${t} must use owner/repo.`);return o}function tI(e,t){let s="string"==typeof e&&e.trim().length>0?e.trim():void 0;if(!s)throw new R("INVALID_ARGS",`${t} must be a non-empty string.`);return s}let tA=async({positionals:e,flags:t,client:s})=>{let o=V(await tx("install",e,t,s));return tm(t,o),!0},tD=async({positionals:e,flags:t,client:s})=>{let o=V(await tx("reinstall",e,t,s));return tm(t,o),!0},tS=async({positionals:e,flags:t,client:s})=>{let o=J(await t$(e,t,s));return tm(t,o),!0};async function tx(e,t,s,o){let r=t[0],a=t[1];if(!r||!a)throw new R("INVALID_ARGS",`${e} requires: ${e} <app> <path-to-app-binary>`);let n={app:r,appPath:a,...td(s)};return"install"===e?await o.apps.install(n):await o.apps.reinstall(n)}async function t$(e,t,s){let o=function(e,t){let s=e[0]?.trim();if(e.length>1)throw new R("INVALID_ARGS","install-from-source accepts either one <url> positional or --github-actions-artifact");let o=t.githubActionsArtifact?function(e,t="--github-actions-artifact"){let s=e.indexOf(":");if(s<=0||s===e.length-1)throw new R("INVALID_ARGS",`${t} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:o,repo:r}=tk(e.slice(0,s),t);return tb(o,r,e.slice(s+1),`${t} artifact`)}(t.githubActionsArtifact):void 0,r=t.installSource;if(1!=+!!s+ +!!o+ +!!r)throw new R("INVALID_ARGS","install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource");return o||r||{kind:"url",url:s,headers:function(e){if(!e||0===e.length)return;let t={};for(let s of e){let e=s.indexOf(":");if(e<=0)throw new R("INVALID_ARGS",`Invalid --header value "${s}". Expected "name:value".`);let o=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!o)throw new R("INVALID_ARGS",`Invalid --header value "${s}". Header name cannot be empty.`);t[o]=r}return t}(t.header)}}(e,t);if("url"!==o.kind&&t.header&&t.header.length>0)throw new R("INVALID_ARGS","install-from-source --header is only supported for URL sources");return await s.apps.installFromSource({...td(t),retainPaths:t.retainPaths,retentionMs:t.retentionMs,source:o})}let tL=async({positionals:e,flags:t,client:s})=>{let o=F(await s.apps.open({app:e[0],url:e[1],surface:t.surface,activity:t.activity,relaunch:t.relaunch,saveScript:t.saveScript,noRecord:t.noRecord,...td(t)}));return tm(t,o),!0},tN=async({positionals:e,flags:t,client:s})=>{let o=q(e[0]?await s.apps.close({app:e[0],shutdown:t.shutdown}):await s.sessions.close({shutdown:t.shutdown}));return tm(t,o),!0},tR=async({flags:e,client:t})=>{var s,o,r,a;if(!e.remoteConfig)throw new R("INVALID_ARGS","connect requires --remote-config <path>.");let n=e.tenant,i=e.runId;if(!n)throw new R("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!i)throw new R("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new R("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let l=K(e.stateDir).baseDir,c=e.session?null:e8({stateDir:l}),p=e.session??c?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${u.randomBytes(3).toString("hex")}`;if(!eX({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${u.randomBytes(2).toString("hex")}`}(l),d=A({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env}),m=e2(d.resolvedPath),f=e0(e),g=c?.session===p?c:eX({stateDir:l,session:p});if(g&&(s=g,o={flags:e,session:p,remoteConfigPath:d.resolvedPath,remoteConfigHash:m,desiredLeaseBackend:tn(e),daemon:f},s.remoteConfigPath!==o.remoteConfigPath||s.remoteConfigHash!==o.remoteConfigHash||s.session!==o.session||s.tenant!==o.flags.tenant||s.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&s.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&s.platform!==o.flags.platform||void 0!==o.flags.target&&s.target!==o.flags.target||(r=s.daemon,a=o.daemon,(r?.baseUrl??void 0)!==(a?.baseUrl??void 0)||(r?.transport??void 0)!==(a?.transport??void 0)||(r?.serverMode??void 0)!==(a?.serverMode??void 0)))&&!e.force)throw new R("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:p,remoteConfig:g.remoteConfigPath});let h=new Date().toISOString(),v={version:1,session:p,remoteConfigPath:d.resolvedPath,remoteConfigHash:m,daemon:f,tenant:n,runId:i,leaseId:g&&!e.force?g.leaseId:void 0,leaseBackend:g&&!e.force?g.leaseBackend:tn(e),platform:e.platform??(g&&!e.force?g.platform:void 0),target:e.target??(g&&!e.force?g.target:void 0),runtime:g&&!e.force?g.runtime:void 0,metro:g&&!e.force?g.metro:void 0,connectedAt:g&&!e.force?g.connectedAt:h,updatedAt:h};eQ({stateDir:l,state:v}),g&&e.force&&(await to(g.metro),await tr({stateDir:l,state:g}),await ta(t,g));let y=tE(v),w=function(e,t){if(!t.runtime&&(ti(e)||tU(t.remoteConfigPath)))return tO(t.remoteConfigPath)}(e,v);return tu(e,tP(v,w),()=>[`Connected remote session "${p}" tenant "${n}" run "${i}" ${v.leaseId?`lease ${v.leaseId}`:"lease pending"}`,y?.message,w?.message].filter(e=>!!e).join("\n")),!0},tC=async({flags:e,client:t})=>{let s=e.session??"default",o=K(e.stateDir).baseDir,r=eX({stateDir:o,session:s})??(e.session?null:e8({stateDir:o}));if(!r)return tu(e,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let a=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await to(r.metro),await tr({stateDir:o,state:r});let n=!1;if(r.leaseId)try{n=(await t.leases.release({tenant:r.tenant,runId:r.runId,leaseId:r.leaseId})).released}catch{}return e1({stateDir:o,session:a}),tu(e,{connected:!1,session:a,released:n},()=>`Disconnected remote session "${a}".`),!0},t_=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new R("INVALID_ARGS","connection accepts only: status");let s=t.session??"default",o=K(t.stateDir).baseDir,r=eX({stateDir:o,session:s})??(t.session?null:e8({stateDir:o}));if(!r)return tu(t,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let a=tE(r),n=function(e){if(!e.runtime&&tU(e.remoteConfigPath))return tO(e.remoteConfigPath)}(r);return tu(t,tP(r,n),()=>[`Connected remote session "${r.session}".`,`tenant=${r.tenant} runId=${r.runId} leaseId=${r.leaseId??"pending"} backend=${r.leaseBackend??"pending"}`,`remoteConfig=${r.remoteConfigPath}`,r.runtime?"metro=prepared":"metro=not-prepared",a?.message,n?.message].filter(e=>!!e).join("\n")),!0};function tE(e){if(!e.leaseId)return{status:"deferred",nextSteps:["agent-device install-from-source <artifact-url> --platform ios|android","agent-device open <app-id> --relaunch","agent-device snapshot -i","agent-device devices"],message:"Lease allocation is pending; run install-from-source, open, snapshot, or devices when ready to allocate or refresh the lease."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function tO(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:"deferred",nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function tU(e){try{let t=A({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function tP(e,t){let s=tE(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return u.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...s?{leasePreparation:s}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}async function tT(e){return await tM({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function tM(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tY(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tY(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||tY(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let s=tB({stateDir:e.stateDir});if(s&&!tW(s.expiresAt,e.io?.now)){let o=await tV({session:s,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"cli-session"}}if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new R("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw tK(e.command,t)}let o=await tF({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function tF(e){let t,s,o,r=e.env??e.io?.env??process.env,a=(c=r,p=e.io,t=p?.stdinIsTTY??process.stdin.isTTY,s=p?.stdoutIsTTY??process.stdout.isTTY,"true"!==(u=c).CI&&"true"!==u.GITHUB_ACTIONS&&"true"!==u.BUILDKITE&&t&&s?(m=c).SSH_TTY||m.SSH_CONNECTION||"true"===m.CODESPACES||m.GITPOD_WORKSPACE_ID||"true"===m.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===a)throw tK(e.commandLabel??"agent-device connect",r);let n=tH(r),i=await tq({baseUrl:n,pathName:"/api/control-plane/device-auth/start",body:{client:"agent-device",tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});var c,p,u,m,f,g,h=i;if(!tY(h.deviceCode)||!tY(h.userCode)||!tY(h.verificationUri))throw new R("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=i.verificationUriComplete??i.verificationUri,y="local-browser"===a?i.verificationUri:(f=i.verificationUri,g=i.userCode,(o=new URL(f)).searchParams.set("user_code",g),o.toString());"local-browser"===a?(tz(e.io,`Opening ${i.verificationUri}...
369
- `),await tJ(v,e.io)):tz(e.io,`Open this URL on your machine:
373
+ ${e.summaryLines.join("\n")}`:""}function eF(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function eB(e){return e>0?`+${e}`:String(e)}function ej(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",s=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${s}`}function eV(e){return e.min===e.max?eB(e.min):`${eB(e.min)}..${eB(e.max)}`}function eG(e){let t=process.cwd(),s=l.relative(t,e);return""!==s&&(s.startsWith("..")||l.isAbsolute(s))?e:""===s?".":`.${l.sep}${s}`}function eq(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function eH(){let e=process.env.FORCE_COLOR;return"string"==typeof e?"0"!==e:"string"!=typeof process.env.NO_COLOR&&!!process.stdout.isTTY}function eK(e,t){return t?c("dim",e):e}function eJ(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function ez(e,t){var s;let o="scroll-area"===(s=e.type)||"list"===s||"collection"===s||"table"===s?s:null;if(!o)return[];let r=[];if(e.node.hiddenContentAbove&&"below"!==t&&r.push(`[content above ${o} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&r.push(`[content below ${o} hidden]`),0===r.length)return[];let n=" ".repeat(e.depth+1);return r.map(e=>`${n}${e}`)}let eW={slug:"react-devtools-companion",runArg:E,displayName:"React DevTools companion"};async function eY(e){return await R({...e,definition:eW,localBaseUrl:e.localBaseUrl??"http://127.0.0.1:8097",registerPath:"/api/react-devtools/companion/register",unregisterPath:"/api/react-devtools/companion/unregister",devicePort:e.devicePort??8097})}async function eZ(e){return await _({...e,definition:eW})}function eX(e){var t;let s,o=e3(e);if(!p.existsSync(o))return null;try{s=JSON.parse(p.readFileSync(o,"utf8"))}catch(t){return e7(e,t),null}return!(!(t=s)||"object"!=typeof t||Array.isArray(t))&&1===t.version&&"string"==typeof t.session&&"string"==typeof t.remoteConfigPath&&"string"==typeof t.remoteConfigHash&&(void 0===t.daemon||"object"==typeof t.daemon&&null!==t.daemon&&!Array.isArray(t.daemon))&&"string"==typeof t.tenant&&"string"==typeof t.runId&&(void 0===t.leaseId||"string"==typeof t.leaseId)&&(void 0===t.leaseBackend||"string"==typeof t.leaseBackend)&&"string"==typeof t.connectedAt&&"string"==typeof t.updatedAt?s:(e7(e),null)}function eQ(e){let t=e3({stateDir:e.stateDir,session:e.state.session});p.mkdirSync(l.dirname(t),{recursive:!0}),e6(t,e.state),e6(e5(e.stateDir),{session:e.state.session})}function e0(e){return{baseUrl:function(e){if(!e)return;let t=new URL(e);for(let e of(t.username="",t.password="",[...t.searchParams.keys()]))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,"")}(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function e1(e){p.rmSync(e3(e),{force:!0});let t=e5(e.stateDir);e4(e.stateDir)===e.session&&p.rmSync(t,{force:!0})}function e2(e){try{return u.createHash("sha256").update(p.readFileSync(e)).digest("hex")}catch(t){throw new N("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function e3(e){return l.join(e.stateDir,"remote-connections",`${function(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,"_");if(!t)return"default";if(t===e)return t;let s=u.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${s}`}(e.session)}.json`)}function e5(e){return l.join(e,"remote-connections",".active-session.json")}function e8(e){let t=e4(e.stateDir);return t?eX({stateDir:e.stateDir,session:t}):null}function e4(e){let t=e5(e);if(p.existsSync(t))try{let e=JSON.parse(p.readFileSync(t,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function e6(e,t){p.writeFileSync(e,`${JSON.stringify(t,null,2)}
374
+ `,{encoding:"utf8",mode:384}),p.chmodSync(e,384)}function e7(e,t){M({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),e1(e)}let e9=S.map(e=>e.key);function te(e){let t={};for(let s of e9){let o=e[s];void 0!==o&&(t[s]=o)}return t}let tt=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]),ts=new Set(["open"]);async function to(e){let t,s,{command:o,flags:r,client:n}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=H(r.stateDir).baseDir,i=I({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),l={...te(i.profile),...r,remoteConfig:i.resolvedPath},c=eX({stateDir:a,session:l.session??"default"});if(c&&c.remoteConfigPath!==i.resolvedPath)throw new N("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:i.resolvedPath});let d=c??function(e,t){if(!e.tenant)throw new N("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new N("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new N("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let s=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:e2(t),daemon:e0(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??tl(e),platform:e.platform,target:e.target,connectedAt:s,updatedAt:s}}(l,i.resolvedPath),p={...l,session:d.session},u=function(e,t){if(e)return td(e,t)?e:void 0}(d.runtime,p.platform)??e.runtime,m=d,f=!c;if(g=o,!tt.has(g)){let e=d.leaseBackend??function(e,t){let s=tl(e);if(s)return s;throw new N("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(r,o);var g,h,v,y,w,b=d,k=r,A=e;if(b.leaseBackend&&b.leaseBackend!==A)throw new N("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:b.session,leaseBackend:b.leaseBackend});if(b.platform&&k.platform&&b.platform!==k.platform)throw new N("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:b.session,platform:b.platform});if(b.target&&k.target&&b.target!==k.target)throw new N("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:b.session,target:b.target});let t=await tp(n,m,e);p.leaseId=t.leaseId,p.leaseBackend=e,p.platform=m.platform??p.platform,p.target=m.target??p.target,(m.leaseId!==t.leaseId||m.leaseBackend!==e)&&(m={...m,leaseId:t.leaseId,leaseBackend:e,platform:m.platform??r.platform,target:m.target??r.target,updatedAt:new Date().toISOString()},f=!0)}if(h=o,v=e.batchSteps,(ts.has(h)||"batch"===h&&v&&v.some(e=>{let t=e.command.trim().toLowerCase();return ts.has(t)&&void 0===e.runtime}))&&tc(p)&&(!m.leaseId&&p.leaseId&&(m={...m,leaseId:p.leaseId,leaseBackend:p.leaseBackend}),e.forceRuntimePrepare||!u||!td(u,p.platform))){if(!m.leaseId)throw new N("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await tr(p,n,d.remoteConfigPath,d.session,{tenantId:d.tenant,runId:d.runId,leaseId:m.leaseId});u=e.runtime;let r=(y=m.metro,w=e.cleanup,y?.projectRoot!==w?.projectRoot||y?.profileKey!==w?.profileKey||y?.consumerKey!==w?.consumerKey);t=r?m.metro:void 0,s=r?e.cleanup:void 0,m={...m,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},f=!0}if(f)try{eQ({stateDir:a,state:m})}catch(e){throw await tn(s),e}return await tn(t),{flags:{...p,session:m.session,leaseId:m.leaseId,leaseBackend:m.leaseBackend,platform:m.platform??p.platform,target:m.target??p.target},runtime:u}}async function tr(e,t,s,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new N("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new N("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let n=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:e.metroKind,publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:s,companionConsumerKey:o,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?n.iosRuntime:n.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:n.projectRoot,profileKey:s,consumerKey:o}:void 0}}async function tn(e){if(e)try{await Y(e)}catch{}}async function ta(e){try{await eZ({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function ti(e,t){if(t.leaseId)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,daemonBaseUrl:t.daemon?.baseUrl,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode})}catch{}}function tl(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function tc(e){return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||e.metroKind)}function td(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function tp(e,t,s){if(t.leaseId&&t.leaseBackend===s){let o=await tu(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:s});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:s})}async function tu(e,t,s){try{return await e.leases.heartbeat({tenant:s.tenant,runId:s.runId,leaseId:t,leaseBackend:s.leaseBackend})}catch(e){var o;if((o=e)instanceof N&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}function tm(e){return{platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,androidDeviceAllowlist:e.androidDeviceAllowlist}}function tf(e,t,s){var o;if(e.json)return void eP({success:!0,data:t});let r=s?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
375
+ `))}function tg(e,t){tf(e,t,()=>G(t))}let th=async({positionals:e,flags:t,client:s})=>{if("list"!==(e[0]??"list"))throw new N("INVALID_ARGS","session only supports list");let o={sessions:(await s.sessions.list()).map(j)};return tf(t,o,()=>JSON.stringify(o,null,2)),!0},tv=async({flags:e,client:t})=>{let s=await t.devices.list(tm(e));return tf(e,{devices:s.map(z)},()=>s.map(ty).join("\n")),!0};function ty(e){let t=e.kind?` ${e.kind}`:"",s=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${s})${o}`}let tw=async({flags:e,client:t})=>{if(!e.device)throw new N("INVALID_ARGS","ensure-simulator requires --device <name>");let s=await t.simulators.ensure({device:e.device,runtime:e.runtime,boot:e.boot,reuseExisting:e.reuseExisting,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet});return tf(e,K(s),()=>{let e=s.created?"Created":"Reused",t=s.booted?" (booted)":"";return s.runtime?`${e}: ${s.device} ${s.udid}${t}
376
+ Runtime: ${s.runtime}`:`${e}: ${s.device} ${s.udid}${t}`}),!0},tb=async({positionals:e,flags:t,client:s})=>{let o=(e[0]??"").toLowerCase();if("reload"===o){let e=await s.metro.reload({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs});return tf(t,e,()=>`Reloaded React Native apps via ${e.reloadUrl}`),!0}if("prepare"!==o)throw new N("INVALID_ARGS","metro requires a subcommand: prepare or reload");if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new N("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let r=await s.metro.prepare({projectRoot:t.metroProjectRoot,kind:t.metroKind,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:t.tenant&&t.runId&&t.leaseId?{tenantId:t.tenant,runId:t.runId,leaseId:t.leaseId}:void 0,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return tf(t,r,()=>JSON.stringify(r,null,2)),!0},tk=async({flags:e,client:t})=>{let s=await t.apps.list({...tm(e),appsFilter:e.appsFilter});return tf(e,{apps:s},()=>s.join("\n")),!0};function tA(e,t,s,o){var r;return"number"==typeof s||"string"==typeof(r=s)&&/^\d+$/.test(r.trim())?{kind:"github-actions-artifact",owner:e,repo:t,artifactId:function(e,t){let s="number"==typeof e?e:"string"==typeof e?Number(e):NaN;if(!Number.isInteger(s))throw new N("INVALID_ARGS",`${t} must be an integer.`);return s}(s,o)}:{kind:"github-actions-artifact",owner:e,repo:t,artifactName:tD(s,o)}}function tI(e,t){let s=e.indexOf("/");if(s<=0||s===e.length-1||-1!==e.indexOf("/",s+1))throw new N("INVALID_ARGS",`${t} must use owner/repo.`);let o={owner:e.slice(0,s).trim(),repo:e.slice(s+1).trim()};if(!o.owner||!o.repo)throw new N("INVALID_ARGS",`${t} must use owner/repo.`);return o}function tD(e,t){let s="string"==typeof e&&e.trim().length>0?e.trim():void 0;if(!s)throw new N("INVALID_ARGS",`${t} must be a non-empty string.`);return s}let tS=async({positionals:e,flags:t,client:s})=>{let o=V(await tC("install",e,t,s));return tg(t,o),!0},tx=async({positionals:e,flags:t,client:s})=>{let o=V(await tC("reinstall",e,t,s));return tg(t,o),!0},t$=async({positionals:e,flags:t,client:s})=>{let o=J(await tL(e,t,s));return tg(t,o),!0};async function tC(e,t,s,o){let r=t[0],n=t[1];if(!r||!n)throw new N("INVALID_ARGS",`${e} requires: ${e} <app> <path-to-app-binary>`);let a={app:r,appPath:n,...tm(s)};return"install"===e?await o.apps.install(a):await o.apps.reinstall(a)}async function tL(e,t,s){let o=function(e,t){let s=e[0]?.trim();if(e.length>1)throw new N("INVALID_ARGS","install-from-source accepts either one <url> positional or --github-actions-artifact");let o=t.githubActionsArtifact?function(e,t="--github-actions-artifact"){let s=e.indexOf(":");if(s<=0||s===e.length-1)throw new N("INVALID_ARGS",`${t} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:o,repo:r}=tI(e.slice(0,s),t);return tA(o,r,e.slice(s+1),`${t} artifact`)}(t.githubActionsArtifact):void 0,r=t.installSource;if(1!=+!!s+ +!!o+ +!!r)throw new N("INVALID_ARGS","install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource");return o||r||{kind:"url",url:s,headers:function(e){if(!e||0===e.length)return;let t={};for(let s of e){let e=s.indexOf(":");if(e<=0)throw new N("INVALID_ARGS",`Invalid --header value "${s}". Expected "name:value".`);let o=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!o)throw new N("INVALID_ARGS",`Invalid --header value "${s}". Header name cannot be empty.`);t[o]=r}return t}(t.header)}}(e,t);if("url"!==o.kind&&t.header&&t.header.length>0)throw new N("INVALID_ARGS","install-from-source --header is only supported for URL sources");return await s.apps.installFromSource({...tm(t),retainPaths:t.retainPaths,retentionMs:t.retentionMs,source:o})}let tN=async({positionals:e,flags:t,client:s})=>{let o=F(await s.apps.open({app:e[0],url:e[1],surface:t.surface,activity:t.activity,relaunch:t.relaunch,saveScript:t.saveScript,noRecord:t.noRecord,...tm(t)}));return tg(t,o),!0},tR=async({positionals:e,flags:t,client:s})=>{let o=q(e[0]?await s.apps.close({app:e[0],shutdown:t.shutdown}):await s.sessions.close({shutdown:t.shutdown}));return tg(t,o),!0};async function t_(e){return await tE({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function tE(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tJ(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tJ(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||tJ(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let s=await tM({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(s)return{flags:{...e.flags,daemonAuthToken:s.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new N("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw tV(e.command,t)}let o=await tU({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function tO(e){let t=e.env??e.io?.env??process.env;if(tJ(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:tG(t)};if(tJ(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:tG(t)};let s=await tM({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(s)return{accessToken:s.accessToken,cloudBaseUrl:s.cloudBaseUrl};if(e.flags.noLogin)throw new N("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let o=await tU({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:o.accessToken,cloudBaseUrl:o.session.cloudBaseUrl}}async function tU(e){let t,s,o,r=e.env??e.io?.env??process.env,n=(c=r,d=e.io,t=d?.stdinIsTTY??process.stdin.isTTY,s=d?.stdoutIsTTY??process.stdout.isTTY,"true"!==(u=c).CI&&"true"!==u.GITHUB_ACTIONS&&"true"!==u.BUILDKITE&&t&&s?(m=c).SSH_TTY||m.SSH_CONNECTION||"true"===m.CODESPACES||m.GITPOD_WORKSPACE_ID||"true"===m.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===n)throw tV(e.commandLabel??"agent-device connect",r);let a=tG(r),i=await tj({baseUrl:a,pathName:"/api/control-plane/device-auth/start",body:{client:"agent-device",tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});var c,d,u,m,f,g,h=i;if(!tJ(h.deviceCode)||!tJ(h.userCode)||!tJ(h.verificationUri))throw new N("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=i.verificationUriComplete??i.verificationUri,y="local-browser"===n?i.verificationUri:(f=i.verificationUri,g=i.userCode,(o=new URL(f)).searchParams.set("user_code",g),o.toString());"local-browser"===n?(tH(e.io,`Opening ${i.verificationUri}...
377
+ `),await tq(v,e.io)):tH(e.io,`Open this URL on your machine:
370
378
  ${y}
371
379
 
372
380
  Waiting for approval for 10 minutes...
373
- `);let w=await tG({cloudBaseUrl:n,deviceCode:i.deviceCode,expiresIn:i.expiresIn,interval:i.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),b=w.cliSession?.refreshCredential??w.cliSession?.refreshToken;if(!tY(w.accessToken)||!tY(b))throw new R("UNAUTHORIZED","Device authorization did not return CLI credentials.");let k=new Date(e.io?.now?.()??Date.now()).toISOString(),I={version:1,id:w.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:n,workspaceId:w.cliSession?.workspaceId,accountId:w.cliSession?.accountId,name:w.cliSession?.name,refreshCredential:b,createdAt:k,expiresAt:w.cliSession?.expiresAt};return function(e){let t=tj(e.stateDir);d.mkdirSync(l.dirname(t),{recursive:!0,mode:448}),d.writeFileSync(t,`${JSON.stringify(e.session,null,2)}
374
- `,{mode:384});try{d.chmodSync(t,384)}catch{}}({stateDir:e.stateDir,session:I}),{accessToken:w.accessToken,expiresAt:w.expiresAt,session:I}}function tB(e){let t=tj(e.stateDir);if(!d.existsSync(t))return null;try{let e=JSON.parse(d.readFileSync(t,"utf8"));if(1!==e.version||!tY(e.id)||!tY(e.cloudBaseUrl)||!tY(e.refreshCredential)||!tY(e.createdAt))return null;return e}catch{return null}}function tj(e){return l.join(e,"auth","cli-session.json")}async function tV(e){let t=tH(e.env,e.session.cloudBaseUrl),s=await tq({baseUrl:t,pathName:"/api/control-plane/cli-session/refresh",body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(tY(s.accessToken))return{accessToken:s.accessToken,expiresAt:s.expiresAt};if("revoked"===s.status||"revoked"===s.error)throw new R("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error});throw new R("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error})}async function tG(e){let t=e.now??Date.now,s=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+s,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tq({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tY(t.accessToken))return t;if("slow_down"===t.status||"slow_down"===t.error)r+=1e3;else if("authorization_pending"!==t.status&&"authorization_pending"!==t.error)throw new R("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tZ(r)}throw new R("TIMEOUT","Device authorization expired before approval.")}async function tq(e){let t=e.fetchImpl??fetch,s=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new R("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new R("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:s.status,response:r});return r}function tK(e,t){let s=tH(t);return new R("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",s).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tH(e,t){let s=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(s).toString().replace(/\/+$/,"")}catch(e){throw new R("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:s},e instanceof Error?e:void 0)}}async function tJ(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let s=process.platform;try{"darwin"===s?await X("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===s?await X("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await X("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tz(t,`Open this URL on your machine:
381
+ `);let w=await tB({cloudBaseUrl:a,deviceCode:i.deviceCode,expiresIn:i.expiresIn,interval:i.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),b=w.cliSession?.refreshCredential??w.cliSession?.refreshToken;if(!tJ(w.accessToken)||!tJ(b))throw new N("UNAUTHORIZED","Device authorization did not return CLI credentials.");let k=new Date(e.io?.now?.()??Date.now()).toISOString(),A={version:1,id:w.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:a,workspaceId:w.cliSession?.workspaceId,accountId:w.cliSession?.accountId,name:w.cliSession?.name,refreshCredential:b,createdAt:k,expiresAt:w.cliSession?.expiresAt};return function(e){let t=tT(e.stateDir);p.mkdirSync(l.dirname(t),{recursive:!0,mode:448}),p.writeFileSync(t,`${JSON.stringify(e.session,null,2)}
382
+ `,{mode:384});try{p.chmodSync(t,384)}catch{}}({stateDir:e.stateDir,session:A}),{accessToken:w.accessToken,expiresAt:w.expiresAt,session:A}}function tP(e){let t=tT(e.stateDir);if(!p.existsSync(t))return null;try{let e=JSON.parse(p.readFileSync(t,"utf8"));if(1!==e.version||!tJ(e.id)||!tJ(e.cloudBaseUrl)||!tJ(e.refreshCredential)||!tJ(e.createdAt))return null;return e}catch{return null}}function tT(e){return l.join(e,"auth","cli-session.json")}async function tM(e){let t=tP({stateDir:e.stateDir});return!t||tK(t.expiresAt,e.io?.now)?null:{accessToken:(await tF({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:tG(e.env,t.cloudBaseUrl)}}async function tF(e){let t=tG(e.env,e.session.cloudBaseUrl),s=await tj({baseUrl:t,pathName:"/api/control-plane/cli-session/refresh",body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(tJ(s.accessToken))return{accessToken:s.accessToken,expiresAt:s.expiresAt};if("revoked"===s.status||"revoked"===s.error)throw new N("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error});throw new N("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error})}async function tB(e){let t=e.now??Date.now,s=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+s,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tj({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tJ(t.accessToken))return t;if("slow_down"===t.status||"slow_down"===t.error)r+=1e3;else if("authorization_pending"!==t.status&&"authorization_pending"!==t.error)throw new N("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tz(r)}throw new N("TIMEOUT","Device authorization expired before approval.")}async function tj(e){let t=e.fetchImpl??fetch,s=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new N("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new N("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:s.status,response:r});return r}function tV(e,t){let s=tG(t);return new N("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",s).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tG(e,t){let s=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(s).toString().replace(/\/+$/,"")}catch(e){throw new N("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:s},e instanceof Error?e:void 0)}}async function tq(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let s=process.platform;try{"darwin"===s?await X("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===s?await X("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await X("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tH(t,`Open this URL on your machine:
375
383
  ${e}
376
- `)}}function tz(e,t){(e?.stderr??process.stderr).write(t)}function tW(e,t){if(!e)return!1;let s=Date.parse(e);return!Number.isFinite(s)||s<=(t?.()??Date.now())}function tY(e){return"string"==typeof e&&e.trim().length>0}async function tZ(e){await new Promise(t=>setTimeout(t,e))}let tX=async({positionals:e,flags:t})=>{let s=e[0]??"status",o=K(t.stateDir).baseDir;if("status"===s){var r;let e,s=(e=tB({stateDir:(r={stateDir:o}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:tW(e.expiresAt,r.now)}:{authenticated:!1,source:"none"};return tu(t,s,()=>{var e;return(e=s).authenticated?["Authenticated with cloud CLI session.",`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?"status=expired":null].filter(e=>!!e).join("\n"):"Not authenticated."}),!0}if("login"===s){let e=await tF({stateDir:o,flags:t,commandLabel:"agent-device auth login"});return tu(t,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===s){let e,s=(e=tj({stateDir:o}.stateDir),!!d.existsSync(e)&&(d.rmSync(e,{force:!0}),!0));return tu(t,{authenticated:!1,removed:s},()=>s?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new R("INVALID_ARGS","auth accepts only: status, login, logout")},tQ=async({flags:e,client:t})=>{let s=B(await t.capture.snapshot({...td(e),interactiveOnly:e.snapshotInteractiveOnly,compact:e.snapshotCompact,depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}));return tu(e,s,()=>(function(e,t={}){var s,o,r,a,n,i;let l,c,p,d,u,f=e.nodes,h=Array.isArray(f)?f:[],v="string"==typeof e.backend?e.backend:void 0,w=t.raw||"macos-helper"===v?null:m(h),b=!!e.truncated,k=w?.nodes??h,A=t.raw||"macos-helper"===v?null:function(e,t,s,o){let r=e.visibility;if(r&&"object"==typeof r&&"boolean"==typeof r.partial&&"number"==typeof r.visibleNodeCount&&"number"==typeof r.totalNodeCount&&Array.isArray(r.reasons))return{partial:r.partial,visibleNodeCount:r.visibleNodeCount,totalNodeCount:r.totalNodeCount,reasons:r.reasons.filter(e=>"string"==typeof e)};let a=t?.hiddenCount??0,n=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return a>0?{partial:!0,visibleNodeCount:s,totalNodeCount:o,reasons:["offscreen-nodes"]}:n?{partial:!0,visibleNodeCount:s,totalNodeCount:s,reasons:[]}:null}(e,w,k.length,h.length),D=(s=h.length,o=A,l=b?" (truncated)":"",o?.partial?o.totalNodeCount>o.visibleNodeCount?`Snapshot: ${o.visibleNodeCount} visible nodes (${o.totalNodeCount} total)${l}`:`Snapshot: ${o.visibleNodeCount} visible nodes${l}`:`Snapshot: ${s} nodes${l}`),S=(c="string"==typeof(r=e).appName?r.appName:void 0,p="string"==typeof r.appBundleId?r.appBundleId:void 0,d=[],c&&d.push(`Page: ${c}`),p&&d.push(`App: ${p}`),d.length>0?`${d.join("\n")}
377
- `:""),x=(a=e,n=h,i=t,u=eJ(a),!i.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let s of e){let e=(s.type??"").toLowerCase(),o=y(s).trim().toLowerCase();if(!o)continue;let r=`${e}|${o}`;t.set(r,(t.get(r)??0)+1)}let s=0;for(let e of t.values())e>1&&(s+=e);return s>=8}(n)&&u.push("Warning: possible repeated nav subtree detected."),u),$=x.length>0?`${x.join("\n")}
384
+ `)}}function tH(e,t){(e?.stderr??process.stderr).write(t)}function tK(e,t){if(!e)return!1;let s=Date.parse(e);return!Number.isFinite(s)||s<=(t?.()??Date.now())}function tJ(e){return"string"==typeof e&&e.trim().length>0}async function tz(e){await new Promise(t=>setTimeout(t,e))}async function tW(e){let t=await tO({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),s=await tY({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),o=function(e){try{return I(e)}catch(s){let t=C(s);throw new N("COMMAND_FAILED","Cloud connection profile returned invalid remote config.",{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(e){var t;let s=function e(t){return Array.isArray(t)?t.map(e):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).filter(([,e])=>void 0!==e).sort(([e],[t])=>e.localeCompare(t)).map(([t,s])=>[t,e(s)])):t}(e.profile),o=l.join(e.stateDir,"remote-connections","generated");p.mkdirSync(o,{recursive:!0,mode:448});let r=l.join(o,`cloud-${(t=s,u.createHash("sha256").update(JSON.stringify(t)).digest("hex").slice(0,16))}.json`);p.writeFileSync(r,`${JSON.stringify(s,null,2)}
385
+ `,{mode:384});try{p.chmodSync(r,384)}catch{}return r}({stateDir:e.stateDir,profile:s}),cwd:e.cwd,env:e.env});return{flags:{...te(o.profile),...e.flags,remoteConfig:o.resolvedPath,daemonAuthToken:t.accessToken},remoteConfigPath:o.resolvedPath}}async function tY(e){let t=e.fetchImpl??fetch,s=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim())try{r=JSON.parse(o)}catch(e){throw new N("COMMAND_FAILED",`Cloud connection profile endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new N("UNAUTHORIZED","Cloud connection profile endpoint rejected the request.",{status:s.status,response:r});var n=r;if(!n||"object"!=typeof n||Array.isArray(n))throw new N("COMMAND_FAILED","Cloud connection profile response is invalid.");let a=n.connection;if(!a||"object"!=typeof a)throw new N("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(void 0!==a.remoteConfigProfile){var i=a.remoteConfigProfile;if(!i||"object"!=typeof i||Array.isArray(i))throw new N("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(i).length)throw new N("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return i}throw new N("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}let tZ=async({flags:e,client:t})=>{var s,o,r,n;let a=H(e.stateDir).baseDir,i=e.remoteConfig?function(e){if(!e.remoteConfig)throw new N("INVALID_ARGS","connect requires --remote-config <path>.");let t=I({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tW({flags:e,stateDir:a,cwd:process.cwd(),env:process.env}),l=i.flags,c=l.tenant,d=l.runId;if(!c)throw new N("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!d)throw new N("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!l.daemonBaseUrl)throw new N("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let p=l.session?null:e8({stateDir:a}),m=l.session??p?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${u.randomBytes(3).toString("hex")}`;if(!eX({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${u.randomBytes(2).toString("hex")}`}(a),f=e2(i.remoteConfigPath),g=e0(l),h=p?.session===m?p:eX({stateDir:a,session:m});if(h&&(s=h,o={flags:l,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,desiredLeaseBackend:tl(l),daemon:g},s.remoteConfigPath!==o.remoteConfigPath||s.remoteConfigHash!==o.remoteConfigHash||s.session!==o.session||s.tenant!==o.flags.tenant||s.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&s.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&s.platform!==o.flags.platform||void 0!==o.flags.target&&s.target!==o.flags.target||(r=s.daemon,n=o.daemon,(r?.baseUrl??void 0)!==(n?.baseUrl??void 0)||(r?.transport??void 0)!==(n?.transport??void 0)||(r?.serverMode??void 0)!==(n?.serverMode??void 0)))&&!l.force)throw new N("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:m,remoteConfig:h.remoteConfigPath});let v=new Date().toISOString(),y={version:1,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,daemon:g,tenant:c,runId:d,leaseId:h&&!l.force?h.leaseId:void 0,leaseBackend:h&&!l.force?h.leaseBackend:tl(l),platform:l.platform??(h&&!l.force?h.platform:void 0),target:l.target??(h&&!l.force?h.target:void 0),runtime:h&&!l.force?h.runtime:void 0,metro:h&&!l.force?h.metro:void 0,connectedAt:h&&!l.force?h.connectedAt:v,updatedAt:v};eQ({stateDir:a,state:y}),h&&l.force&&(await tn(h.metro),await ta({stateDir:a,state:h}),await ti(t,h));let w=t0(y),b=function(e,t){if(!t.runtime&&(tc(e)||t2(t.remoteConfigPath)))return t1(t.remoteConfigPath)}(l,y);return tf(l,t3(y,b),()=>[`Connected remote session "${m}" tenant "${c}" run "${d}" ${y.leaseId?`lease ${y.leaseId}`:"lease pending"}`,w?.message,b?.message].filter(e=>!!e).join("\n")),!0},tX=async({flags:e,client:t})=>{let s=e.session??"default",o=H(e.stateDir).baseDir,r=eX({stateDir:o,session:s})??(e.session?null:e8({stateDir:o}));if(!r)return tf(e,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tn(r.metro),await ta({stateDir:o,state:r});let a=!1;if(r.leaseId)try{a=(await t.leases.release({tenant:r.tenant,runId:r.runId,leaseId:r.leaseId})).released}catch{}return e1({stateDir:o,session:n}),tf(e,{connected:!1,session:n,released:a},()=>`Disconnected remote session "${n}".`),!0},tQ=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new N("INVALID_ARGS","connection accepts only: status");let s=t.session??"default",o=H(t.stateDir).baseDir,r=eX({stateDir:o,session:s})??(t.session?null:e8({stateDir:o}));if(!r)return tf(t,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=t0(r),a=function(e){if(!e.runtime&&t2(e.remoteConfigPath))return t1(e.remoteConfigPath)}(r);return tf(t,t3(r,a),()=>[`Connected remote session "${r.session}".`,`tenant=${r.tenant} runId=${r.runId} leaseId=${r.leaseId??"pending"} backend=${r.leaseBackend??"pending"}`,`remoteConfig=${r.remoteConfigPath}`,r.runtime?"metro=prepared":"metro=not-prepared",n?.message,a?.message].filter(e=>!!e).join("\n")),!0};function t0(e){if(!e.leaseId)return{status:"deferred",nextSteps:["agent-device install-from-source <artifact-url> --platform ios|android","agent-device open <app-id> --relaunch","agent-device snapshot -i","agent-device devices"],message:"Lease allocation is pending; run install-from-source, open, snapshot, or devices when ready to allocate or refresh the lease."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function t1(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:"deferred",nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function t2(e){try{let t=I({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function t3(e,t){let s=t0(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return u.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...s?{leasePreparation:s}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t5=async({positionals:e,flags:t})=>{let s=e[0]??"status",o=H(t.stateDir).baseDir;if("status"===s){var r;let e,s=(e=tP({stateDir:(r={stateDir:o}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:tK(e.expiresAt,r.now)}:{authenticated:!1,source:"none"};return tf(t,s,()=>{var e;return(e=s).authenticated?["Authenticated with cloud CLI session.",`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?"status=expired":null].filter(e=>!!e).join("\n"):"Not authenticated."}),!0}if("login"===s){let e=await tU({stateDir:o,flags:t,commandLabel:"agent-device auth login"});return tf(t,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===s){let e,s=(e=tT({stateDir:o}.stateDir),!!p.existsSync(e)&&(p.rmSync(e,{force:!0}),!0));return tf(t,{authenticated:!1,removed:s},()=>s?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new N("INVALID_ARGS","auth accepts only: status, login, logout")},t8=async({flags:e,client:t})=>{let s=B(await t.capture.snapshot({...tm(e),interactiveOnly:e.snapshotInteractiveOnly,compact:e.snapshotCompact,depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}));return tf(e,s,()=>(function(e,t={}){var s,o,r,n,a,i;let l,c,d,p,u,f=e.nodes,h=Array.isArray(f)?f:[],v="string"==typeof e.backend?e.backend:void 0,w=t.raw||"macos-helper"===v?null:m(h),b=!!e.truncated,k=w?.nodes??h,I=t.raw||"macos-helper"===v?null:function(e,t,s,o){let r=e.visibility;if(r&&"object"==typeof r&&"boolean"==typeof r.partial&&"number"==typeof r.visibleNodeCount&&"number"==typeof r.totalNodeCount&&Array.isArray(r.reasons))return{partial:r.partial,visibleNodeCount:r.visibleNodeCount,totalNodeCount:r.totalNodeCount,reasons:r.reasons.filter(e=>"string"==typeof e)};let n=t?.hiddenCount??0,a=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return n>0?{partial:!0,visibleNodeCount:s,totalNodeCount:o,reasons:["offscreen-nodes"]}:a?{partial:!0,visibleNodeCount:s,totalNodeCount:s,reasons:[]}:null}(e,w,k.length,h.length),D=(s=h.length,o=I,l=b?" (truncated)":"",o?.partial?o.totalNodeCount>o.visibleNodeCount?`Snapshot: ${o.visibleNodeCount} visible nodes (${o.totalNodeCount} total)${l}`:`Snapshot: ${o.visibleNodeCount} visible nodes${l}`:`Snapshot: ${s} nodes${l}`),S=(c="string"==typeof(r=e).appName?r.appName:void 0,d="string"==typeof r.appBundleId?r.appBundleId:void 0,p=[],c&&p.push(`Page: ${c}`),d&&p.push(`App: ${d}`),p.length>0?`${p.join("\n")}
386
+ `:""),x=(n=e,a=h,i=t,u=eJ(n),!i.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let s of e){let e=(s.type??"").toLowerCase(),o=y(s).trim().toLowerCase();if(!o)continue;let r=`${e}|${o}`;t.set(r,(t.get(r)??0)+1)}let s=0;for(let e of t.values())e>1&&(s+=e);return s>=8}(a)&&u.push("Warning: possible repeated nav subtree detected."),u),$=x.length>0?`${x.join("\n")}
378
387
  `:"";return 0===h.length?`${S}${D}
379
388
  ${$}`:t.raw?`${S}${D}
380
389
  ${$}${h.map(e=>JSON.stringify(e)).join("\n")}
381
390
  `:t.flatten?`${S}${D}
382
- ${$}${I(k,{summarizeTextSurfaces:!0}).flatMap(e=>[g(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...ez({...e,depth:0})]).join("\n")}${eM(w)}
391
+ ${$}${A(k,{summarizeTextSurfaces:!0}).flatMap(e=>[g(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...ez({...e,depth:0})]).join("\n")}${eM(w)}
383
392
  `:`${S}${D}
384
- ${$}${(function(e){let t=[],s=[],o=e=>{for(;s.length>0&&e<=s[s.length-1].depth;)t.push(...ez(s.pop(),"below"))};for(let r of e)o(r.depth),t.push(r.text),t.push(...ez(r,"above")),r.node.hiddenContentBelow&&s.push(r);return o(0),t})(I(k,{summarizeTextSurfaces:!0})).join("\n")}${eM(w)}
385
- `})(s,{raw:e.snapshotRaw,flatten:e.snapshotInteractiveOnly})),!0},t0=async({positionals:e,flags:t,client:s})=>{let o=await s.capture.screenshot({path:e[0]??t.out,overlayRefs:t.overlayRefs,maxSize:t.screenshotMaxSize,...void 0!==t.screenshotFullscreen?{fullscreen:t.screenshotFullscreen}:{}});return tu(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},t1=async({positionals:e,flags:t,client:s})=>{var o;if("snapshot"===e[0]){let e=await s.capture.diff({...td(t),kind:"snapshot",out:t.out,interactiveOnly:t.snapshotInteractiveOnly,compact:t.snapshotCompact,depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw});return tu(t,e,()=>(function(e){var t;let s=!0===e.baselineInitialized,o=e.summary??{},r=eq(o.additions),a=eq(o.removals),n=eq(o.unchanged),i=eK(),l=eJ(e),p=l.length>0?`${l.join("\n")}
386
- `:"";if(s)return`${p}Baseline initialized (${n} lines).
387
- `;let d=(function(e){if(0===e.length)return e;let t=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>"added"===e.kind||"removed"===e.kind).map(e=>e.index);if(0===t.length)return e;let s=Array(e.length).fill(!1);for(let o of t){let t=Math.max(0,o-1),r=Math.min(e.length-1,o+1);for(let e=t;e<=r;e+=1)s[e]=!0}return e.filter((e,t)=>s[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let t="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=t.startsWith(" ")?`+${t}`:`+ ${t}`;return i?c("green",e):e}if("removed"===e.kind){let e=t.startsWith(" ")?`-${t}`:`- ${t}`;return i?c("red",e):e}return i?c("dim",t):t}),u=d.length>0?`${d.join("\n")}
388
- `:"";if(!i)return`${p}${u}${r} additions, ${a} removals, ${n} unchanged
389
- `;let m=`${(t=String(r),c("green",t))} additions, ${c("red",String(a))} removals, ${c("dim",String(n))} unchanged`;return`${p}${u}${m}
390
- `})(e)),!0}if("screenshot"!==e[0])return!1;let r=t.baseline;if(!r||"string"!=typeof r)throw new R("INVALID_ARGS","diff screenshot requires --baseline <path>");let a=Q(r),n="string"==typeof t.out?Q(t.out):void 0,i=e[1];if(e.length>2)throw new R("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=v({backend:(o=s,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,s)=>{let r=await o.capture.screenshot({path:t,session:e.session,overlayRefs:s?.overlayRefs,fullscreen:s?.fullscreen,surface:s?.surface});return{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}}}}),artifacts:et(),sessions:{get:e=>({name:e}),set:()=>{}},policy:w()}),p=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:a},current:i?{kind:"path",path:Q(i)}:{kind:"live"},...n?{out:{kind:"path",path:n}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(t.threshold),overlayRefs:t.overlayRefs,surface:t.surface});return tu(t,p,()=>{var e,t,s,o;let r,a,n,i,l,d,u,m;return r=eK(),a=!0===p.match,n=p.dimensionMismatch,(i=[]).push(...function(e,t){if(!0===e.match){let e=t?c("green","✓"):"✓";return[`${e} Screenshots match.`]}let s=e.dimensionMismatch,o=t?c("red","✗"):"✗";if(s){let e=s.expected,t=s.actual;return[`${o} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let r=eq(e.differentPixels),a=eq(e.mismatchPercentage),n=0===a&&r>0?"<0.01":String(a),i=`${n}% pixels differ`;return[`${o} ${t?c("red",i):i}`]}(p,r)),i.push(...function(e,t,s){if(t)return[];let o=[];if(e.diffPath){let t=eG(e.diffPath),r=s?c("dim","Diff image:"):"Diff image:",a=s?c("green",t):t;o.push(` ${r} ${a}`)}if(e.currentOverlayPath){let t=eG(e.currentOverlayPath),r=s?c("dim","Current overlay:"):"Current overlay:",a=s?c("green",t):t,n=eq(e.currentOverlayRefCount),i=n>0?` (${n} refs)`:"";o.push(` ${r} ${a}${i}`)}return o}(p,a,r)),a||n||(i.push(...(e=p,t=r,l=eq(e.differentPixels),d=eq(e.totalPixels),u=t?c("red",String(l)):String(l),[` ${u} different / ${d} total pixels`])),i.push(...(s=p,o=r,0===(m=function(e){let t=[];for(let s of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),s=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${s}`}(s.texts)} dx=${eV(s.xRange)}px dy=${eV(s.yRange)}px`);let s=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);s.length>0&&t.push(`non-text controls: ${s.map(ej).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(ej).join("; ")}`),t.slice(0,6)}(s)).length?[]:[` ${eH("Hints:",o)}`,...m.map(e=>` - ${e}`)])),i.push(...function(e,t){let s=Array.isArray(e.regions)?e.regions:[];if(0===s.length)return[];let o=[` ${eH("Changed regions:",t)}`];for(let e of s.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),s=e.rect,o=[` ${e.index}. ${e.location} x=${s.x} y=${s.y} ${s.width}x${s.height}, ${t}% of diff, change=${e.dominantChange}`],r=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);r&&o.push(` ${r}`);let a=e.currentOverlayMatches?.[0];if(a){let e=a.label?` "${a.label}"`:"";o.push(` overlaps @${a.ref}${e}, ${a.regionCoveragePercentage}% of region`)}return o}(e));return o}(p,r)),i.push(...function(e,t){let s=e.ocr?.matches??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eH(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${s.length}; px):`,t)}`,` ${eH("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let s=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${eB(s.x)},${eB(s.y)} | ${eB(s.width)},${eB(s.height)} | ${eF(t.baselineRect)} | ${eF(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(p,r)),i.push(...function(e,t){let s=e.nonTextDeltas??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eH(`Non-text visual deltas (showing ${o.length}/${s.length}; px):`,t)}`,` ${eH("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of o)r.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${eF(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(p,r))),`${i.join("\n")}
391
- `}),!0},t2={[eo.wait]:async({positionals:e,flags:t,client:s})=>(tm(t,await s.command.wait(function(e,t){let s=k(e);if(!s)throw new R("INVALID_ARGS","wait requires <ms>, text <text>, @ref, or <selector> [timeoutMs].");let o={...td(t),depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw};if("sleep"===s.kind)return{...o,durationMs:s.durationMs};if("text"===s.kind){if(!s.text)throw new R("INVALID_ARGS","wait requires text.");return{...o,text:s.text,...t3(s.timeoutMs)}}return"ref"===s.kind?{...o,ref:s.rawRef,...t3(s.timeoutMs)}:{...o,selector:s.selectorExpression,...t3(s.timeoutMs)}}(e,t))),!0),[eo.alert]:async({positionals:e,flags:t,client:s})=>(tm(t,await s.command.alert(function(e,t){if(e.length>2)throw new R("INVALID_ARGS","alert accepts at most action and timeout arguments.");let s=function(e){let t=e?.toLowerCase();if(void 0===t||"get"===t||"accept"===t||"dismiss"===t||"wait"===t)return t;throw new R("INVALID_ARGS","alert action must be get, accept, dismiss, or wait.")}(e[0]),o=function(e,t){if(void 0===e)return;let s=Number(e);if(Number.isFinite(s))return s;throw new R("INVALID_ARGS",`${t} must be a finite number.`)}(e[1],"alert timeout");return{...td(t),...s?{action:s}:{},...void 0!==o?{timeoutMs:o}:{}}}(e,t))),!0),[eo.appState]:async({flags:e,client:t})=>{let s=await t.command.appState(td(e));return tu(e,s,()=>(function(e){if("ios"===e.platform){let t=[`Foreground app: ${e.appName??e.appBundleId??"unknown"}`];return e.appBundleId&&t.push(`Bundle: ${e.appBundleId}`),e.source&&t.push(`Source: ${e.source}`),t.join("\n")}if("android"===e.platform){let t=[`Foreground app: ${e.package??"unknown"}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join("\n")}return null})(s)),!0},[eo.back]:async({flags:e,client:t})=>(tm(e,await t.command.back({...td(e),mode:e.backMode})),!0),[eo.home]:async({flags:e,client:t})=>(tm(e,await t.command.home(td(e))),!0),[eo.rotate]:async({positionals:e,flags:t,client:s})=>(tm(t,await s.command.rotate(function(e,t){if(e.length>1)throw new R("INVALID_ARGS","rotate accepts exactly one orientation argument.");return{...td(t),orientation:b(e[0])}}(e,t))),!0),[eo.appSwitcher]:async({flags:e,client:t})=>(tm(e,await t.command.appSwitcher(td(e))),!0),[eo.keyboard]:async({positionals:e,flags:t,client:s})=>(tm(t,await s.command.keyboard(function(e,t){if(e.length>1)throw new R("INVALID_ARGS","keyboard accepts at most one action argument.");let s=function(e){let t=e?.toLowerCase();if("get"===t)return"status";if(void 0===t||"status"===t||"dismiss"===t)return t;throw new R("INVALID_ARGS","keyboard action must be status, get, or dismiss.")}(e[0]);return{...td(t),...s?{action:s}:{}}}(e,t))),!0),[eo.clipboard]:async({positionals:e,flags:t,client:s})=>{var o,r;return o=t,r=await s.command.clipboard(function(e,t){let s=e[0]?.toLowerCase();if("read"!==s&&"write"!==s)throw new R("INVALID_ARGS","clipboard requires a subcommand: read or write.");let o=td(t);if("read"===s){if(1!==e.length)throw new R("INVALID_ARGS","clipboard read does not accept additional arguments.");return{...o,action:s}}if(e.length<2)throw new R("INVALID_ARGS","clipboard write requires text.");return{...o,action:s,text:e.slice(1).join(" ")}}(e,t)),o.json?tu(o,r):"read"===r.action?process.stdout.write(`${r.text}
392
- `):tm(o,r),!0}};function t3(e){return null===e?{}:{timeoutMs:e}}function t5(e){let{suite:t,json:s,verbose:o,reportJunit:r}=e;return(r&&function(e,t){let s=l.dirname(e);try{d.mkdirSync(s,{recursive:!0}),d.writeFileSync(e,function(e){let t=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${e.total}" failures="${e.failed}" skipped="${e.skipped}" time="${t6(e.durationMs)}">`];for(let s of e.tests)t.push(...function(e){let t=t7(l.basename(e.file)),s=t7("."===l.dirname(e.file)?e.file:l.dirname(e.file)),o=t7(e.file),r=t6(e.durationMs),a=[` <testcase classname="${s}" name="${t}" file="${o}" time="${r}">`];"failed"===e.status?a.push(` <failure message="${t7(e.error.message)}">${t7(function(e){let t=[e.error.message];e.error.hint&&t.push(`hint: ${e.error.hint}`),e.error.diagnosticId&&t.push(`diagnosticId: ${e.error.diagnosticId}`),e.error.logPath&&t.push(`logPath: ${e.error.logPath}`),e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`);let s=e.error.details?JSON.stringify(e.error.details,null,2):void 0;return s&&t.push(`details: ${s}`),t.join("\n")}(e))}</failure>`):"skipped"===e.status&&a.push(` <skipped message="${t7(e.message)}" />`);let n=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return"attempts"in e&&t.push(`attempts: ${e.attempts}`),"session"in e&&t.push(`session: ${e.session}`),"replayed"in e&&t.push(`replayed: ${e.replayed}`),"healed"in e&&t.push(`healed: ${e.healed}`),"artifactsDir"in e&&e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`),"passed"===e.status&&e.attempts>1&&t.push("flaky: true"),t.join("\n")}(e);return n&&a.push(` <system-out>${t7(n)}</system-out>`),a.push(" </testcase>"),a}(s));return t.push(" </testsuite>"),t.push("</testsuites>"),`${t.join("\n")}
393
- `}(t),"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new R("COMMAND_FAILED",`Failed to write JUnit report to ${e}: ${t}`)}}(r,t),s)?(eP({success:!0,data:t}),function(e){return+(e.failed>0)}(t)):function(e,t={}){let s=e.tests.filter(t4);if(t.verbose)for(let t of e.tests)!function(e){if("failed"===e.status)return t8(e);let t="passed"===e.status?t4(e)?"FLAKY":"PASS":"skipped"===e.status?"SKIP":"INFO",s="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${t} ${e.file}${s}${o}
393
+ ${$}${(function(e){let t=[],s=[],o=e=>{for(;s.length>0&&e<=s[s.length-1].depth;)t.push(...ez(s.pop(),"below"))};for(let r of e)o(r.depth),t.push(r.text),t.push(...ez(r,"above")),r.node.hiddenContentBelow&&s.push(r);return o(0),t})(A(k,{summarizeTextSurfaces:!0})).join("\n")}${eM(w)}
394
+ `})(s,{raw:e.snapshotRaw,flatten:e.snapshotInteractiveOnly})),!0},t4=async({positionals:e,flags:t,client:s})=>{let o=await s.capture.screenshot({path:e[0]??t.out,overlayRefs:t.overlayRefs,maxSize:t.screenshotMaxSize,...void 0!==t.screenshotFullscreen?{fullscreen:t.screenshotFullscreen}:{}});return tf(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},t6=async({positionals:e,flags:t,client:s})=>{var o;if("snapshot"===e[0]){let e=await s.capture.diff({...tm(t),kind:"snapshot",out:t.out,interactiveOnly:t.snapshotInteractiveOnly,compact:t.snapshotCompact,depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw});return tf(t,e,()=>(function(e){var t;let s=!0===e.baselineInitialized,o=e.summary??{},r=eq(o.additions),n=eq(o.removals),a=eq(o.unchanged),i=eH(),l=eJ(e),d=l.length>0?`${l.join("\n")}
395
+ `:"";if(s)return`${d}Baseline initialized (${a} lines).
396
+ `;let p=(function(e){if(0===e.length)return e;let t=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>"added"===e.kind||"removed"===e.kind).map(e=>e.index);if(0===t.length)return e;let s=Array(e.length).fill(!1);for(let o of t){let t=Math.max(0,o-1),r=Math.min(e.length-1,o+1);for(let e=t;e<=r;e+=1)s[e]=!0}return e.filter((e,t)=>s[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let t="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=t.startsWith(" ")?`+${t}`:`+ ${t}`;return i?c("green",e):e}if("removed"===e.kind){let e=t.startsWith(" ")?`-${t}`:`- ${t}`;return i?c("red",e):e}return i?c("dim",t):t}),u=p.length>0?`${p.join("\n")}
397
+ `:"";if(!i)return`${d}${u}${r} additions, ${n} removals, ${a} unchanged
398
+ `;let m=`${(t=String(r),c("green",t))} additions, ${c("red",String(n))} removals, ${c("dim",String(a))} unchanged`;return`${d}${u}${m}
399
+ `})(e)),!0}if("screenshot"!==e[0])return!1;let r=t.baseline;if(!r||"string"!=typeof r)throw new N("INVALID_ARGS","diff screenshot requires --baseline <path>");let n=Q(r),a="string"==typeof t.out?Q(t.out):void 0,i=e[1];if(e.length>2)throw new N("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=v({backend:(o=s,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,s)=>{let r=await o.capture.screenshot({path:t,session:e.session,overlayRefs:s?.overlayRefs,fullscreen:s?.fullscreen,surface:s?.surface});return{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}}}}),artifacts:et(),sessions:{get:e=>({name:e}),set:()=>{}},policy:w()}),d=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:n},current:i?{kind:"path",path:Q(i)}:{kind:"live"},...a?{out:{kind:"path",path:a}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(t.threshold),overlayRefs:t.overlayRefs,surface:t.surface});return tf(t,d,()=>{var e,t,s,o;let r,n,a,i,l,p,u,m;return r=eH(),n=!0===d.match,a=d.dimensionMismatch,(i=[]).push(...function(e,t){if(!0===e.match){let e=t?c("green","✓"):"✓";return[`${e} Screenshots match.`]}let s=e.dimensionMismatch,o=t?c("red","✗"):"✗";if(s){let e=s.expected,t=s.actual;return[`${o} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let r=eq(e.differentPixels),n=eq(e.mismatchPercentage),a=0===n&&r>0?"<0.01":String(n),i=`${a}% pixels differ`;return[`${o} ${t?c("red",i):i}`]}(d,r)),i.push(...function(e,t,s){if(t)return[];let o=[];if(e.diffPath){let t=eG(e.diffPath),r=s?c("dim","Diff image:"):"Diff image:",n=s?c("green",t):t;o.push(` ${r} ${n}`)}if(e.currentOverlayPath){let t=eG(e.currentOverlayPath),r=s?c("dim","Current overlay:"):"Current overlay:",n=s?c("green",t):t,a=eq(e.currentOverlayRefCount),i=a>0?` (${a} refs)`:"";o.push(` ${r} ${n}${i}`)}return o}(d,n,r)),n||a||(i.push(...(e=d,t=r,l=eq(e.differentPixels),p=eq(e.totalPixels),u=t?c("red",String(l)):String(l),[` ${u} different / ${p} total pixels`])),i.push(...(s=d,o=r,0===(m=function(e){let t=[];for(let s of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),s=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${s}`}(s.texts)} dx=${eV(s.xRange)}px dy=${eV(s.yRange)}px`);let s=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);s.length>0&&t.push(`non-text controls: ${s.map(ej).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(ej).join("; ")}`),t.slice(0,6)}(s)).length?[]:[` ${eK("Hints:",o)}`,...m.map(e=>` - ${e}`)])),i.push(...function(e,t){let s=Array.isArray(e.regions)?e.regions:[];if(0===s.length)return[];let o=[` ${eK("Changed regions:",t)}`];for(let e of s.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),s=e.rect,o=[` ${e.index}. ${e.location} x=${s.x} y=${s.y} ${s.width}x${s.height}, ${t}% of diff, change=${e.dominantChange}`],r=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);r&&o.push(` ${r}`);let n=e.currentOverlayMatches?.[0];if(n){let e=n.label?` "${n.label}"`:"";o.push(` overlaps @${n.ref}${e}, ${n.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,r)),i.push(...function(e,t){let s=e.ocr?.matches??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eK(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${s.length}; px):`,t)}`,` ${eK("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let s=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${eB(s.x)},${eB(s.y)} | ${eB(s.width)},${eB(s.height)} | ${eF(t.baselineRect)} | ${eF(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,r)),i.push(...function(e,t){let s=e.nonTextDeltas??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eK(`Non-text visual deltas (showing ${o.length}/${s.length}; px):`,t)}`,` ${eK("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of o)r.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${eF(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,r))),`${i.join("\n")}
400
+ `}),!0},t7={[eo.wait]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.wait(function(e,t){let s=k(e);if(!s)throw new N("INVALID_ARGS","wait requires <ms>, text <text>, @ref, or <selector> [timeoutMs].");let o={...tm(t),depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw};if("sleep"===s.kind)return{...o,durationMs:s.durationMs};if("text"===s.kind){if(!s.text)throw new N("INVALID_ARGS","wait requires text.");return{...o,text:s.text,...t9(s.timeoutMs)}}return"ref"===s.kind?{...o,ref:s.rawRef,...t9(s.timeoutMs)}:{...o,selector:s.selectorExpression,...t9(s.timeoutMs)}}(e,t))),!0),[eo.alert]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.alert(function(e,t){if(e.length>2)throw new N("INVALID_ARGS","alert accepts at most action and timeout arguments.");let s=function(e){let t=e?.toLowerCase();if(void 0===t||"get"===t||"accept"===t||"dismiss"===t||"wait"===t)return t;throw new N("INVALID_ARGS","alert action must be get, accept, dismiss, or wait.")}(e[0]),o=function(e,t){if(void 0===e)return;let s=Number(e);if(Number.isFinite(s))return s;throw new N("INVALID_ARGS",`${t} must be a finite number.`)}(e[1],"alert timeout");return{...tm(t),...s?{action:s}:{},...void 0!==o?{timeoutMs:o}:{}}}(e,t))),!0),[eo.appState]:async({flags:e,client:t})=>{let s=await t.command.appState(tm(e));return tf(e,s,()=>(function(e){if("ios"===e.platform){let t=[`Foreground app: ${e.appName??e.appBundleId??"unknown"}`];return e.appBundleId&&t.push(`Bundle: ${e.appBundleId}`),e.source&&t.push(`Source: ${e.source}`),t.join("\n")}if("android"===e.platform){let t=[`Foreground app: ${e.package??"unknown"}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join("\n")}return null})(s)),!0},[eo.back]:async({flags:e,client:t})=>(tg(e,await t.command.back({...tm(e),mode:e.backMode})),!0),[eo.home]:async({flags:e,client:t})=>(tg(e,await t.command.home(tm(e))),!0),[eo.rotate]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.rotate(function(e,t){if(e.length>1)throw new N("INVALID_ARGS","rotate accepts exactly one orientation argument.");return{...tm(t),orientation:b(e[0])}}(e,t))),!0),[eo.appSwitcher]:async({flags:e,client:t})=>(tg(e,await t.command.appSwitcher(tm(e))),!0),[eo.keyboard]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.keyboard(function(e,t){if(e.length>1)throw new N("INVALID_ARGS","keyboard accepts at most one action argument.");let s=function(e){let t=e?.toLowerCase();if("get"===t)return"status";if(void 0===t||"status"===t||"dismiss"===t)return t;throw new N("INVALID_ARGS","keyboard action must be status, get, or dismiss.")}(e[0]);return{...tm(t),...s?{action:s}:{}}}(e,t))),!0),[eo.clipboard]:async({positionals:e,flags:t,client:s})=>{var o,r;return o=t,r=await s.command.clipboard(function(e,t){let s=e[0]?.toLowerCase();if("read"!==s&&"write"!==s)throw new N("INVALID_ARGS","clipboard requires a subcommand: read or write.");let o=tm(t);if("read"===s){if(1!==e.length)throw new N("INVALID_ARGS","clipboard read does not accept additional arguments.");return{...o,action:s}}if(e.length<2)throw new N("INVALID_ARGS","clipboard write requires text.");return{...o,action:s,text:e.slice(1).join(" ")}}(e,t)),o.json?tf(o,r):"read"===r.action?process.stdout.write(`${r.text}
401
+ `):tg(o,r),!0}};function t9(e){return null===e?{}:{timeoutMs:e}}function se(e){let{suite:t,json:s,verbose:o,reportJunit:r}=e;return(r&&function(e,t){let s=l.dirname(e);try{p.mkdirSync(s,{recursive:!0}),p.writeFileSync(e,function(e){let t=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${e.total}" failures="${e.failed}" skipped="${e.skipped}" time="${so(e.durationMs)}">`];for(let s of e.tests)t.push(...function(e){let t=sr(l.basename(e.file)),s=sr("."===l.dirname(e.file)?e.file:l.dirname(e.file)),o=sr(e.file),r=so(e.durationMs),n=[` <testcase classname="${s}" name="${t}" file="${o}" time="${r}">`];"failed"===e.status?n.push(` <failure message="${sr(e.error.message)}">${sr(function(e){let t=[e.error.message];e.error.hint&&t.push(`hint: ${e.error.hint}`),e.error.diagnosticId&&t.push(`diagnosticId: ${e.error.diagnosticId}`),e.error.logPath&&t.push(`logPath: ${e.error.logPath}`),e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`);let s=e.error.details?JSON.stringify(e.error.details,null,2):void 0;return s&&t.push(`details: ${s}`),t.join("\n")}(e))}</failure>`):"skipped"===e.status&&n.push(` <skipped message="${sr(e.message)}" />`);let a=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return"attempts"in e&&t.push(`attempts: ${e.attempts}`),"session"in e&&t.push(`session: ${e.session}`),"replayed"in e&&t.push(`replayed: ${e.replayed}`),"healed"in e&&t.push(`healed: ${e.healed}`),"artifactsDir"in e&&e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`),"passed"===e.status&&e.attempts>1&&t.push("flaky: true"),t.join("\n")}(e);return a&&n.push(` <system-out>${sr(a)}</system-out>`),n.push(" </testcase>"),n}(s));return t.push(" </testsuite>"),t.push("</testsuites>"),`${t.join("\n")}
402
+ `}(t),"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new N("COMMAND_FAILED",`Failed to write JUnit report to ${e}: ${t}`)}}(r,t),s)?(eP({success:!0,data:t}),function(e){return+(e.failed>0)}(t)):function(e,t={}){let s=e.tests.filter(ss);if(t.verbose)for(let t of e.tests)!function(e){if("failed"===e.status)return st(e);let t="passed"===e.status?ss(e)?"FLAKY":"PASS":"skipped"===e.status?"SKIP":"INFO",s="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${t} ${e.file}${s}${o}
394
403
  `),"skipped"===e.status&&process.stdout.write(` ${e.message??"skipped"}
395
- `)}(t);else{for(let t of e.failures)t8(t);for(let e of s)!function(e){let t=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FLAKY ${e.file} after ${e.attempts} attempts${t}
404
+ `)}(t);else{for(let t of e.failures)st(t);for(let e of s)!function(e){let t=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FLAKY ${e.file} after ${e.attempts} attempts${t}
396
405
  `)}(e)}let o="number"==typeof e.durationMs?e.durationMs:void 0,r=s.length>0?`, ${s.length} flaky`:"";return process.stdout.write(`Test summary: ${e.passed} passed, ${e.failed} failed${r}${void 0!==o?` in ${o}ms`:""}
397
- `),function(e){return+(e.failed>0)}(e)}(t,{verbose:o})}function t8(e){let t=e.attempts>1?` after ${e.attempts} attempts`:"",s=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FAIL ${e.file}${t}${s}
406
+ `),function(e){return+(e.failed>0)}(e)}(t,{verbose:o})}function st(e){let t=e.attempts>1?` after ${e.attempts} attempts`:"",s=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FAIL ${e.file}${t}${s}
398
407
  `),process.stdout.write(` ${e.error?.message??"Unknown test failure"}
399
408
  `),e.error?.hint&&process.stdout.write(` hint: ${e.error.hint}
400
409
  `),e.artifactsDir&&process.stdout.write(` artifacts: ${e.artifactsDir}
401
410
  `),e.error?.logPath&&process.stdout.write(` log: ${e.error.logPath}
402
411
  `),e.error?.diagnosticId&&process.stdout.write(` diagnostic: ${e.error.diagnosticId}
403
- `)}function t4(e){return"passed"===e.status&&e.attempts>1}function t6(e){return(Math.max(0,e)/1e3).toFixed(3)}function t7(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}let t9={[eo.batch]:({data:e})=>{let t="number"==typeof e.total?e.total:0,s="number"==typeof e.executed?e.executed:0,o="number"==typeof e.totalDurationMs?e.totalDurationMs:void 0;for(let r of(process.stdout.write(`Batch completed: ${s}/${t} steps${void 0!==o?` in ${o}ms`:""}
404
- `),Array.isArray(e.results)?e.results:[])){let e=function(e){var t;let s=st(e);if(!s)return;let o="number"==typeof s.step?s.step:void 0,r="string"==typeof s.command?s.command:"step",a=!1!==s.ok,n=st(s.data),i=st(s.error),l=a?G(n)??r:(t=i,("string"==typeof t?.message&&t.message.length>0?t.message:null)??r),c=void 0!==o?`${o}. `:"- ",p="number"==typeof s.durationMs?s.durationMs:void 0,d=void 0!==p?` (${p}ms)`:"";return`${c}${a?"OK":"FAILED"} ${l}${d}
412
+ `)}function ss(e){return"passed"===e.status&&e.attempts>1}function so(e){return(Math.max(0,e)/1e3).toFixed(3)}function sr(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}let sn={[eo.batch]:({data:e})=>{let t="number"==typeof e.total?e.total:0,s="number"==typeof e.executed?e.executed:0,o="number"==typeof e.totalDurationMs?e.totalDurationMs:void 0;for(let r of(process.stdout.write(`Batch completed: ${s}/${t} steps${void 0!==o?` in ${o}ms`:""}
413
+ `),Array.isArray(e.results)?e.results:[])){let e=function(e){var t;let s=si(e);if(!s)return;let o="number"==typeof s.step?s.step:void 0,r="string"==typeof s.command?s.command:"step",n=!1!==s.ok,a=si(s.data),i=si(s.error),l=n?G(a)??r:(t=i,("string"==typeof t?.message&&t.message.length>0?t.message:null)??r),c=void 0!==o?`${o}. `:"- ",d="number"==typeof s.durationMs?s.durationMs:void 0,p=void 0!==d?` (${d}ms)`:"";return`${c}${n?"OK":"FAILED"} ${l}${p}
405
414
  `}(r);e&&process.stdout.write(e)}return!0},[eo.get]:({positionals:e,data:t})=>{var s,o;let r;return s=e,o=t,"text"===(r=s[0])?(process.stdout.write(`${"string"==typeof o.text?o.text:""}
406
415
  `),!0):"attrs"===r&&(process.stdout.write(`${JSON.stringify(o.node??{},null,2)}
407
416
  `),!0)},[eo.find]:({data:e})=>{var t;return"string"==typeof(t=e).text?(process.stdout.write(`${t.text}
@@ -411,42 +420,42 @@ ${$}${(function(e){let t=[],s=[],o=e=>{for(;s.length>0&&e<=s[s.length-1].depth;)
411
420
  `),!0),[eo.boot]:({data:e})=>{let t=e.platform??"unknown",s=e.device??e.id??"unknown";return process.stdout.write(`Boot ready: ${s} (${t})
412
421
  `),!0},[eo.record]:({data:e})=>{let t="string"==typeof e.outPath?e.outPath:"";return t&&process.stdout.write(`${t}
413
422
  `),!0},[eo.logs]:({data:e,flags:t})=>((function(e,t){var s;let o="string"==typeof e.path?e.path:"";if(!o)return;process.stdout.write(`${o}
414
- `);let r=sn(e,["active","state","backend","sizeBytes"]);r&&!t.json&&process.stderr.write(`${r}
415
- `);let a=(s=e,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(e=>{var t,o;return t=e,!0===(o=s[e])?`${t}=true`:"number"==typeof o?`${t}=${o}`:""}).filter(Boolean).join(" "));a&&!t.json&&process.stderr.write(`${a}
423
+ `);let r=su(e,["active","state","backend","sizeBytes"]);r&&!t.json&&process.stderr.write(`${r}
424
+ `);let n=(s=e,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(e=>{var t,o;return t=e,!0===(o=s[e])?`${t}=true`:"number"==typeof o?`${t}=${o}`:""}).filter(Boolean).join(" "));n&&!t.json&&process.stderr.write(`${n}
416
425
  `),e.hint&&!t.json&&process.stderr.write(`${e.hint}
417
- `),t.json||si(e.notes)})(e,t),!0),[eo.network]:({data:e})=>((function(e){let t="string"==typeof e.path?e.path:"";t&&process.stdout.write(`${t}
418
- `);let s=Array.isArray(e.entries)?e.entries:[];if(0===s.length)process.stdout.write("No recent HTTP(s) entries found.\n");else for(let e of s)!function(e){let t="string"==typeof e.method?e.method:"HTTP",s="string"==typeof e.url?e.url:"<unknown-url>",o="number"==typeof e.status?` status=${e.status}`:"",r="string"==typeof e.timestamp?`${e.timestamp} `:"",a="number"==typeof e.durationMs?` durationMs=${e.durationMs}`:"";process.stdout.write(`${r}${t} ${s}${o}${a}
419
- `),sa("headers",e.headers),sa("request",e.requestBody),sa("response",e.responseBody)}(e);let o=sn(e,["active","state","backend","include","scannedLines","matchedLines"]);o&&process.stderr.write(`${o}
420
- `),si(e.notes)})(e),!0),[eo.click]:({data:e})=>se(e),[eo.press]:({data:e})=>se(e),[eo.perf]:({data:e})=>((function(e){let t=st(e.metrics),s=st(t?.fps),o=function(e){let t=[],s=st(e?.cpu);if(s?.available===!0){let e=ss(s.usagePercent);void 0!==e&&t.push(`CPU ${so(e)}`)}let o=st(e?.memory);if(o?.available===!0){let e,s=ss(o.residentMemoryKb)??ss(o.totalPssKb)??ss(o.totalRssKb);void 0!==s&&t.push(`memory ${(e=s/1024,`${e>=10?Math.round(e):e.toFixed(1)}MB`)}`)}return t.length>0?t.join(", "):void 0}(t);if(!s)return process.stdout.write(o?`Performance: ${o}
426
+ `),t.json||sm(e.notes)})(e,t),!0),[eo.network]:({data:e})=>((function(e){let t="string"==typeof e.path?e.path:"";t&&process.stdout.write(`${t}
427
+ `);let s=Array.isArray(e.entries)?e.entries:[];if(0===s.length)process.stdout.write("No recent HTTP(s) entries found.\n");else for(let e of s)!function(e){let t="string"==typeof e.method?e.method:"HTTP",s="string"==typeof e.url?e.url:"<unknown-url>",o="number"==typeof e.status?` status=${e.status}`:"",r="string"==typeof e.timestamp?`${e.timestamp} `:"",n="number"==typeof e.durationMs?` durationMs=${e.durationMs}`:"";process.stdout.write(`${r}${t} ${s}${o}${n}
428
+ `),sp("headers",e.headers),sp("request",e.requestBody),sp("response",e.responseBody)}(e);let o=su(e,["active","state","backend","include","scannedLines","matchedLines"]);o&&process.stderr.write(`${o}
429
+ `),sm(e.notes)})(e),!0),[eo.click]:({data:e})=>sa(e),[eo.press]:({data:e})=>sa(e),[eo.perf]:({data:e})=>((function(e){let t=si(e.metrics),s=si(t?.fps),o=function(e){let t=[],s=si(e?.cpu);if(s?.available===!0){let e=sl(s.usagePercent);void 0!==e&&t.push(`CPU ${sc(e)}`)}let o=si(e?.memory);if(o?.available===!0){let e,s=sl(o.residentMemoryKb)??sl(o.totalPssKb)??sl(o.totalRssKb);void 0!==s&&t.push(`memory ${(e=s/1024,`${e>=10?Math.round(e):e.toFixed(1)}MB`)}`)}return t.length>0?t.join(", "):void 0}(t);if(!s)return process.stdout.write(o?`Performance: ${o}
421
430
  `:"Frame health: unavailable - missing frame metric\n");if(!1===s.available){if(o)return process.stdout.write(`Performance: ${o}
422
431
  `);let e="string"==typeof s.reason&&s.reason.length>0?s.reason:"not available";return process.stdout.write(`Frame health: unavailable - ${e}
423
- `)}let r=ss(s.droppedFramePercent),a=ss(s.droppedFrameCount),n=ss(s.totalFrameCount);if(void 0===r||void 0===a)return process.stdout.write(o?`Performance: ${o}
424
- `:"Frame health: unavailable - missing dropped-frame summary\n");let i=[`dropped ${so(r)}`];void 0!==n?i.push(`(${Math.round(a)}/${Math.round(n)} frames)`):i.push(`(${Math.round(a)} dropped frames)`);let l=ss(s.sampleWindowMs);void 0!==l&&i.push(`window ${sr(l)}`),process.stdout.write(`Frame health: ${i.join(" ")}
425
- `),function(e){var t;let s=Array.isArray(t=e.worstWindows)?t.filter(e=>!!e&&"object"==typeof e&&!Array.isArray(e)):[];if(0!==s.length)for(let e of(process.stdout.write("Worst windows:\n"),s)){let t=function(e){let t=ss(e.startOffsetMs),s=ss(e.endOffsetMs),o=ss(e.missedDeadlineFrameCount);if(void 0===t||void 0===s||void 0===o)return;let r=ss(e.worstFrameMs),a=void 0===r?"":`, worst ${sr(r)}`;return`- +${sr(t)}-+${sr(s)}: ${Math.round(o)} missed-deadline frames${a}
426
- `}(e);t&&process.stdout.write(t)}}(s)})(e),!0)};function se(e){let t=e.ref??"",s=e.x,o=e.y;return!!t&&"number"==typeof s&&"number"==typeof o&&(process.stdout.write(`Tapped @${t} (${s}, ${o})
427
- `),!0)}function st(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function ss(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function so(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function sr(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let s=Math.round(t/1e3);if(s<60)return`${s}s`;let o=Math.floor(s/60),r=s%60;return r>0?`${o}m ${r}s`:`${o}m`}function sa(e,t){"string"==typeof t&&process.stdout.write(` ${e}: ${t}
428
- `)}function sn(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")}function si(e){if(Array.isArray(e))for(let t of e)"string"==typeof t&&t.length>0&&process.stderr.write(`${t}
429
- `)}let sl={[eo.boot]:sc(eo.boot,({client:e,flags:t})=>e.devices.boot({...td(t),headless:t.headless})),[eo.push]:sc(eo.push,({client:e,positionals:t,flags:s})=>e.apps.push({...td(s),app:sm(t[0],"push requires bundleOrPackage"),payload:sm(t[1],"push requires payloadOrJson")})),[eo.perf]:sc(eo.perf,({client:e,flags:t})=>e.observability.perf(td(t))),[eo.click]:sc(eo.click,({client:e,positionals:t,flags:s})=>e.interactions.click({...sd(t),...sp(s),...td(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap,button:s.clickButton})),[eo.get]:sc(eo.get,({client:e,positionals:t,flags:s})=>e.interactions.get({...function(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=e.join(" ").trim();if(!t)throw new R("INVALID_ARGS","get requires @ref or selector expression");return{selector:t}}(t.slice(1)),...sp(s),...td(s),format:function(e){if("text"===e||"attrs"===e)return e;throw new R("INVALID_ARGS","get only supports text or attrs")}(t[0])})),[eo.replay]:sc(eo.replay,({client:e,positionals:t,flags:s})=>e.replay.run({...td(s),path:sm(t[0],"replay requires path"),update:s.replayUpdate,env:s.replayEnv})),[eo.test]:sc(eo.test,({client:e,positionals:t,flags:s})=>(({json:s.json}).json||process.stderr.write("Running replay suite...\n"),e.replay.test({...td(s),paths:t,update:s.replayUpdate,env:s.replayEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit}))),[eo.batch]:sc(eo.batch,({client:e,flags:t})=>e.batch.run({...td(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})),[eo.press]:sc(eo.press,({client:e,positionals:t,flags:s})=>e.interactions.press({...sd(t),...sp(s),...td(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap})),[eo.longPress]:sc(eo.longPress,({client:e,positionals:t,flags:s})=>e.interactions.longPress({...td(s),x:Number(t[0]),y:Number(t[1]),durationMs:sf(t[2])})),[eo.swipe]:sc(eo.swipe,({client:e,positionals:t,flags:s})=>e.interactions.swipe({...td(s),from:{x:Number(t[0]),y:Number(t[1])},to:{x:Number(t[2]),y:Number(t[3])},durationMs:sf(t[4]),count:s.count,pauseMs:s.pauseMs,pattern:s.pattern})),[eo.focus]:sc(eo.focus,({client:e,positionals:t,flags:s})=>e.interactions.focus({...td(s),x:Number(t[0]),y:Number(t[1])})),[eo.type]:sc(eo.type,({client:e,positionals:t,flags:s})=>e.interactions.type({...td(s),text:t.join(" "),delayMs:s.delayMs})),[eo.fill]:sc(eo.fill,({client:e,positionals:t,flags:s})=>e.interactions.fill({...function(e){if(e[0]?.startsWith("@")){let t=e.length>=3?e.slice(2).join(" "):e.slice(1).join(" ");return{ref:e[0],label:e.length>=3?e[1]:void 0,text:t}}let t=ea(e,{preferTrailingValue:!0});return t?{selector:t.selectorExpression,text:t.rest.join(" ")}:{x:Number(e[0]),y:Number(e[1]),text:e.slice(2).join(" ")}}(t),...sp(s),...td(s),delayMs:s.delayMs})),[eo.scroll]:sc(eo.scroll,({client:e,positionals:t,flags:s})=>e.interactions.scroll({...td(s),direction:function(e){if("up"===e||"down"===e||"left"===e||"right"===e)return e;throw new R("INVALID_ARGS",`Unknown direction: ${String(e)}`)}(t[0]),amount:sf(t[1]),pixels:s.pixels})),[eo.pinch]:sc(eo.pinch,({client:e,positionals:t,flags:s})=>e.interactions.pinch({...td(s),scale:Number(t[0]),x:sf(t[1]),y:sf(t[2])})),[eo.triggerAppEvent]:sc(eo.triggerAppEvent,({client:e,positionals:t,flags:s})=>e.apps.triggerEvent({...td(s),event:sm(t[0],"trigger-app-event requires event"),payload:t[1]?function(e,t){try{let t=JSON.parse(e);if(t&&"object"==typeof t&&!Array.isArray(t))return t}catch{}throw new R("INVALID_ARGS",`${t} must be a JSON object`)}(t[1],"trigger-app-event payload"):void 0})),[eo.record]:sc(eo.record,({client:e,positionals:t,flags:s})=>e.recording.record({...td(s),action:su(t[0],"record"),path:t[1],fps:s.fps,quality:s.quality,hideTouches:s.hideTouches})),[eo.trace]:sc(eo.trace,({client:e,positionals:t,flags:s})=>e.recording.trace({...td(s),action:su(t[0],"trace"),path:t[1]})),[eo.logs]:sc(eo.logs,({client:e,positionals:t,flags:s})=>e.observability.logs({...td(s),action:function(e){if(void 0!==e){if("path"===e||"start"===e||"stop"===e||"doctor"===e||"mark"===e||"clear"===e)return e;throw new R("INVALID_ARGS","logs requires path, start, stop, doctor, mark, or clear")}}(t[0]),message:t.slice(1).join(" ")||void 0,restart:s.restart})),[eo.network]:sc(eo.network,({client:e,positionals:t,flags:s})=>e.observability.network({...td(s),action:function(e){if(void 0!==e){if("dump"===e||"log"===e)return e;throw new R("INVALID_ARGS","network requires dump or log")}}(t[0]),limit:sf(t[1]),include:s.networkInclude??function(e){if(void 0!==e){if("summary"===e||"headers"===e||"body"===e||"all"===e)return e;throw new R("INVALID_ARGS","network include mode must be summary, headers, body, or all")}}(t[2])})),[eo.find]:sc(eo.find,({client:e,positionals:t,flags:s})=>{var o;return e.interactions.find({...function(e){let t=function(e){if("text"===e||"label"===e||"value"===e||"role"===e||"id"===e)return e}(e[0]),s=void 0!==t,o=s?e[1]:e[0],r=s?2:1,a=e[r];if(void 0===a)return{locator:t,query:sm(o,"find requires query")};if("get"===a){let s=e[r+1];if("text"===s)return{locator:t,query:sm(o,"find requires query"),action:"getText"};if("attrs"===s)return{locator:t,query:sm(o,"find requires query"),action:"getAttrs"};throw new R("INVALID_ARGS","find get only supports text or attrs")}if("wait"===a)return{locator:t,query:sm(o,"find requires query"),action:"wait",timeoutMs:sf(e[r+1])};if("fill"===a||"type"===a)return{locator:t,query:sm(o,"find requires query"),action:a,value:e.slice(r+1).join(" ")};if("click"===a||"focus"===a||"exists"===a)return{locator:t,query:sm(o,"find requires query"),action:a};throw new R("INVALID_ARGS",`Unsupported find action: ${a}`)}(t),...{depth:(o=s).snapshotDepth,raw:o.snapshotRaw},...td(s),first:s.findFirst,last:s.findLast})}),[eo.is]:sc(eo.is,({client:e,positionals:t,flags:s})=>e.interactions.is({...function(e){let t=e[0],s=ea(e.slice(1),{preferTrailingValue:"text"===t});if(!s)throw new R("INVALID_ARGS","is requires a selector expression");if("text"===t)return{predicate:t,selector:s.selectorExpression,value:s.rest.join(" ")};if("visible"===t||"hidden"===t||"exists"===t||"editable"===t||"selected"===t)return{predicate:t,selector:s.selectorExpression};throw new R("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text")}(t),...sp(s),...td(s)})),[eo.settings]:sc(eo.settings,({client:e,positionals:t,flags:s})=>e.settings.update(function(e,t){let s=td(t),o=e[0],r=e[1];if(("wifi"===o||"airplane"===o||"location"===o||"animations"===o)&&("on"===r||"off"===r)||"appearance"===o&&("light"===r||"dark"===r||"toggle"===r)||("faceid"===o||"touchid"===o)&&("match"===r||"nonmatch"===r||"enroll"===r||"unenroll"===r)||"fingerprint"===o&&("match"===r||"nonmatch"===r))return{...s,setting:o,state:r};if("permission"===o&&("grant"===r||"deny"===r||"reset"===r))return{...s,setting:o,state:r,permission:function(e){switch(e){case"camera":case"microphone":case"photos":case"contacts":case"contacts-limited":case"notifications":case"calendar":case"location":case"location-always":case"media-library":case"motion":case"reminders":case"siri":case"accessibility":case"screen-recording":case"input-monitoring":return e;default:throw new R("INVALID_ARGS","settings permission requires a permission target.")}}(e[2]),mode:function(e){if(void 0===e||"full"===e||"limited"===e)return e;throw new R("INVALID_ARGS","settings permission mode must be full or limited.")}(e[3])};throw new R("INVALID_ARGS","Invalid settings arguments.")}(t,s)))};function sc(e,t){return async({positionals:s,flags:o,client:r})=>{let a=await t({client:r,positionals:s,flags:o}),n=function(e,t,s,o){if(s.json){var r,a,n;return r=e,a=s,n=o,r===eo.test?t5({suite:n,json:!0,reportJunit:a.reportJunit}):(eP({success:!0,data:n}),0)}if(e===eo.test)return t5({suite:o,verbose:s.verbose,reportJunit:s.reportJunit});let i=t9[e];if(i?.({positionals:t,flags:s,data:o}))return 0;let l=G(o);return l&&process.stdout.write(`${l}
430
- `),0}(e,s,o,a);return 0!==n&&process.exit(n),!0}}function sp(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function sd(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=ea(e);return t?{selector:t.selectorExpression}:{x:Number(e[0]),y:Number(e[1])}}function su(e,t){if("start"===e||"stop"===e)return e;throw new R("INVALID_ARGS",`${t} requires start|stop`)}function sm(e,t){if(void 0===e||""===e)throw new R("INVALID_ARGS",t);return e}function sf(e){return void 0===e?void 0:Number(e)}let sg={...{session:tf,[eo.devices]:tg,[eo.apps]:tw,"ensure-simulator":tv,metro:ty,install:tA,reinstall:tD,"install-from-source":tS,connect:tR,disconnect:tC,connection:t_,auth:tX,open:tL,close:tN,[eo.snapshot]:tQ,[eo.screenshot]:t0,[eo.diff]:t1},...t2,...sl};async function sh(e){let t=sg[e.command];return!!t&&await t(e)}async function sv(e,t){let{flags:s}=e,o=function(e){if(!e?.metroProxyBaseUrl||(e.leaseBackend?"android-instance"!==e.leaseBackend&&"ios-instance"!==e.leaseBackend:"android"!==e.platform&&"ios"!==e.platform))return null;let t=e?.metroProxyBaseUrl,s=e?.metroBearerToken,o=e?.tenant,r=e?.runId,a=e?.leaseId,n=[];if(t||n.push("metroProxyBaseUrl"),s||n.push("metroBearerToken"),o||n.push("tenant"),r||n.push("runId"),a||n.push("leaseId"),n.length>0)throw new R("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});if(!t||!s||!o||!r||!a)throw new R("INVALID_ARGS","react-devtools remote bridge is incomplete.");return{serverBaseUrl:t,bearerToken:s,tenantId:o,runId:r,leaseId:a}}(s);if(!o)return t();let r=e.stateDir??process.cwd(),a=e.session??s?.session??"default",n=s?.remoteConfig??`${o.tenantId}:${o.runId}:${o.leaseId}`;await eY({projectRoot:e.cwd??process.cwd(),stateDir:r,serverBaseUrl:o.serverBaseUrl,bearerToken:o.bearerToken,bridgeScope:{tenantId:o.tenantId,runId:o.runId,leaseId:o.leaseId},session:a,profileKey:n,consumerKey:a,env:e.env??process.env});try{return await t()}finally{await eZ({projectRoot:e.cwd??process.cwd(),stateDir:r,profileKey:n,consumerKey:a})}}async function sy(e,t={}){let s=t.cwd??process.cwd(),o=t.env??process.env;return await sv(t,async()=>(await Z("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:s,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode)}function sw(e,t={}){let s=sb(t),o={...e};return s.defaultPlatform&&void 0===o.platform&&(o.platform=s.defaultPlatform),o}function sb(e){var t,s,o,r;let a,n=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new R("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(n.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??n.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(s=e.policyOverrides,o=n,r=l,(a=s?.sessionLock??s?.sessionLockConflicts??sk(o.AGENT_DEVICE_SESSION_LOCK)??sk(o.AGENT_DEVICE_SESSION_LOCK_CONFLICTS))||(s?.sessionLocked===!0||en(o.AGENT_DEVICE_SESSION_LOCKED)||r?"reject":void 0))}}function sk(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new R("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}let sI=S.map(e=>e.key),sA={sendToDaemon:er},sD=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),sS=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]);async function sx(e,t=sA){let s=O(),o=W(),r=e.includes("--debug")||e.includes("--verbose")||e.includes("-v"),a=e.includes("--json"),n=function(e){for(let t=0;t<e.length;t+=1){let s=e[t];if(s.startsWith("--session=")){let e=s.slice(10).trim();return e.length>0?e:null}if("--session"===s){let s=e[t+1]?.trim();if(s&&!s.startsWith("-"))return s;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await U({session:n,requestId:s,command:e[0],debug:r},async()=>{var n,i,c,p,u,m,f,g,h,v,y,w,b,k,I,S,$;let C,_,E,O,U,F,B;try{let t,s,o,r,a,w,b,k;n={cwd:process.cwd(),env:process.env},t=function(e){let t={json:!1,help:!1,version:!1},s=null,o=[],r=[],a=!0;for(let l=0;l<e.length;l+=1){var n,i;let c=e[l];if(a&&"--"===c){a=!1;continue}if(!a){s?o.push(c):s=eU(c);continue}let p=c.startsWith("--"),d=c.startsWith("-")&&c.length>1;if(!p&&!d){s?o.push(c):s=eU(c);continue}let[u,m]=p?e_(c):[c,void 0],f=eh.get(u);if(n=s,i=f,"react-devtools"===n&&(!i||!eR(i.key,n))){o.push(c);continue}if(!f){if(function(e,t,s){var o;if(o=s,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=ey(e);return!r||!!r.allowsExtraPositionals||0!==r.positionalArgs.length&&(t.length<r.positionalArgs.length||r.positionalArgs.some(e=>e.includes("?")))}(s,o,c)){s?o.push(c):s=c;continue}throw new R("INVALID_ARGS",`Unknown flag: ${u}`)}let g=function(e,t,s,o){if(void 0!==e.setValue){if(void 0!==s)throw new R("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==s)throw new R("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==s){if(0===s.trim().length)throw new R("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:s,consumeNext:!1}}return void 0===o||eO(o)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(o)?{value:!0,consumeNext:!1}:{value:o,consumeNext:!0}}let r=s??o;if(void 0===r||void 0===s&&eO(r))throw new R("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===s};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new R("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:r,consumeNext:void 0===s}}let a=Number(r);if(!Number.isFinite(a)||"number"==typeof e.min&&a<e.min||"number"==typeof e.max&&a>e.max)throw new R("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:Math.floor(a),consumeNext:void 0===s}}(f,u,m,e[l+1]);g.consumeNext&&(l+=1);let h=t[f.key];if(f.multiple){let e=Array.isArray(h)?[...h,g.value]:void 0===h?[g.value]:[h,g.value];t[f.key]=e}else t[f.key]=g.value;r.push({key:f.key,token:u})}return{command:s,positionals:o,flags:t,warnings:[],providedFlags:r}}(e),s=n?.env??process.env,o=n?.cwd??process.cwd(),p=t.command,r=null!==p&&(i={remoteConfig:t.flags.remoteConfig,cwd:o,env:s}).remoteConfig?{...function(e){let t={};for(let s of sI){let o=e[s];void 0!==o&&(t[s]=o)}return t}(A({configPath:i.remoteConfig,cwd:i.cwd,env:i.env}).profile),remoteConfig:i.remoteConfig}:{},b=ec((a=(c={command:t.command,cwd:o,cliFlags:t.flags,env:s}).env??process.env,w=ec({},function(e){let t={};for(let s of e)ec(t,function(e,t){let s,o;if(!d.existsSync(e)){if(t)throw new R("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{s=d.readFileSync(e,"utf8")}catch(t){throw new R("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(s)}catch(t){throw new R("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new R("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let s={};for(let[o,r]of Object.entries(e)){if("installSource"===o){s.installSource=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new R("INVALID_ARGS",`${t} installSource must be an object.`);if("github-actions-artifact"!==tI(e.type,`${t} installSource.type`))throw new R("INVALID_ARGS",`${t} installSource.type must be "github-actions-artifact".`);let{owner:s,repo:o}=tk(tI(e.repo,`${t} installSource.repo`),`${t} installSource.repo`);return tb(s,o,e.artifact,`${t} installSource.artifact`)}(r,t);continue}let e=eN.get(o);if(!e)throw new R("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new R("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);s[o]=x(eC(e),r,t,o)}return s}(o,`config file ${e}`)}(s.path,s.required));return t}((u=c.cwd,m=c.cliFlags.config,f=a,(k=m??f.AGENT_DEVICE_CONFIG)?[{path:(g=k,h=u,v=f,Q(g,{cwd:h,env:v})),required:!0}]:[{path:(y=f,l.join(ee("~",{env:y}),".agent-device","config.json")),required:!1},{path:l.resolve(u,"agent-device.json"),required:!1}]))),ec(w,function(e,t){var s,o,r;let a={};for(let n of eL.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===n.key)continue;let t=n.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(a[n.key]=(s=t.value,o=`environment variable ${t.name}`,r=t.name,x(eC(n),s,o,r)))}return a}(a,c.command))),r),C={...function(e,t){let s=t?.strictFlags??function(e){if(!e)return!1;let t=e.trim().toLowerCase();return"1"===t||"true"===t||"yes"===t||"on"===t}(process.env.AGENT_DEVICE_STRICT_FLAGS),o=[...e.warnings],r=ec({json:!1,help:!1,version:!1},t?.defaultFlags??{});ec(r,e.flags);let a=ey(e.command),n=e.providedFlags.filter(t=>!eR(t.key,e.command));if(n.length>0){var i,l;let t=n.map(e=>e.token),a=(i=e.command,l=t,i?1===l.length?`Flag ${l[0]} is not supported for command ${i}.`:`Flags ${l.join(", ")} are not supported for command ${i}.`:1===l.length?`Flag ${l[0]} requires a command that supports it.`:`Flags ${l.join(", ")} require a command that supports them.`);if(s)throw new R("INVALID_ARGS",a);for(let e of(o.push(`${a} Enable AGENT_DEVICE_STRICT_FLAGS=1 to fail fast.`),n))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eR(t,e.command)||delete r[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new R("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),a?.defaults)for(let[e,t]of Object.entries(a.defaults))void 0===r[e]&&(r[e]=t);if("batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new R("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...s}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:s,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(t,{strictFlags:n?.strictFlags,defaultFlags:b}),providedFlags:t.providedFlags}}catch(t){M({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=N(t,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});a?eP({success:!1,error:e}):eT(e,{showDetails:r}),process.exit(1);return}for(let e of C.warnings)process.stderr.write(`Warning: ${e}
431
- `);C.flags.version&&(process.stdout.write(`${o}
432
- `),process.exit(0));let j="help"===C.command,V=C.flags.help;if(j||V){j&&C.positionals.length>1&&(eT(new R("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=j?C.positionals[0]:C.command;e||(process.stdout.write(`${ek}
432
+ `)}let r=sl(s.droppedFramePercent),n=sl(s.droppedFrameCount),a=sl(s.totalFrameCount);if(void 0===r||void 0===n)return process.stdout.write(o?`Performance: ${o}
433
+ `:"Frame health: unavailable - missing dropped-frame summary\n");let i=[`dropped ${sc(r)}`];void 0!==a?i.push(`(${Math.round(n)}/${Math.round(a)} frames)`):i.push(`(${Math.round(n)} dropped frames)`);let l=sl(s.sampleWindowMs);void 0!==l&&i.push(`window ${sd(l)}`),process.stdout.write(`Frame health: ${i.join(" ")}
434
+ `),function(e){var t;let s=Array.isArray(t=e.worstWindows)?t.filter(e=>!!e&&"object"==typeof e&&!Array.isArray(e)):[];if(0!==s.length)for(let e of(process.stdout.write("Worst windows:\n"),s)){let t=function(e){let t=sl(e.startOffsetMs),s=sl(e.endOffsetMs),o=sl(e.missedDeadlineFrameCount);if(void 0===t||void 0===s||void 0===o)return;let r=sl(e.worstFrameMs),n=void 0===r?"":`, worst ${sd(r)}`;return`- +${sd(t)}-+${sd(s)}: ${Math.round(o)} missed-deadline frames${n}
435
+ `}(e);t&&process.stdout.write(t)}}(s)})(e),!0)};function sa(e){let t=e.ref??"",s=e.x,o=e.y;return!!t&&"number"==typeof s&&"number"==typeof o&&(process.stdout.write(`Tapped @${t} (${s}, ${o})
436
+ `),!0)}function si(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function sl(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function sc(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function sd(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let s=Math.round(t/1e3);if(s<60)return`${s}s`;let o=Math.floor(s/60),r=s%60;return r>0?`${o}m ${r}s`:`${o}m`}function sp(e,t){"string"==typeof t&&process.stdout.write(` ${e}: ${t}
437
+ `)}function su(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")}function sm(e){if(Array.isArray(e))for(let t of e)"string"==typeof t&&t.length>0&&process.stderr.write(`${t}
438
+ `)}let sf={[eo.boot]:sg(eo.boot,({client:e,flags:t})=>e.devices.boot({...tm(t),headless:t.headless})),[eo.push]:sg(eo.push,({client:e,positionals:t,flags:s})=>e.apps.push({...tm(s),app:sw(t[0],"push requires bundleOrPackage"),payload:sw(t[1],"push requires payloadOrJson")})),[eo.perf]:sg(eo.perf,({client:e,flags:t})=>e.observability.perf(tm(t))),[eo.click]:sg(eo.click,({client:e,positionals:t,flags:s})=>e.interactions.click({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap,button:s.clickButton})),[eo.get]:sg(eo.get,({client:e,positionals:t,flags:s})=>e.interactions.get({...function(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=e.join(" ").trim();if(!t)throw new N("INVALID_ARGS","get requires @ref or selector expression");return{selector:t}}(t.slice(1)),...sh(s),...tm(s),format:function(e){if("text"===e||"attrs"===e)return e;throw new N("INVALID_ARGS","get only supports text or attrs")}(t[0])})),[eo.replay]:sg(eo.replay,({client:e,positionals:t,flags:s})=>e.replay.run({...tm(s),path:sw(t[0],"replay requires path"),update:s.replayUpdate,env:s.replayEnv})),[eo.test]:sg(eo.test,({client:e,positionals:t,flags:s})=>(({json:s.json}).json||process.stderr.write("Running replay suite...\n"),e.replay.test({...tm(s),paths:t,update:s.replayUpdate,env:s.replayEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit}))),[eo.batch]:sg(eo.batch,({client:e,flags:t})=>e.batch.run({...tm(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})),[eo.press]:sg(eo.press,({client:e,positionals:t,flags:s})=>e.interactions.press({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap})),[eo.longPress]:sg(eo.longPress,({client:e,positionals:t,flags:s})=>e.interactions.longPress({...tm(s),x:Number(t[0]),y:Number(t[1]),durationMs:sb(t[2])})),[eo.swipe]:sg(eo.swipe,({client:e,positionals:t,flags:s})=>e.interactions.swipe({...tm(s),from:{x:Number(t[0]),y:Number(t[1])},to:{x:Number(t[2]),y:Number(t[3])},durationMs:sb(t[4]),count:s.count,pauseMs:s.pauseMs,pattern:s.pattern})),[eo.focus]:sg(eo.focus,({client:e,positionals:t,flags:s})=>e.interactions.focus({...tm(s),x:Number(t[0]),y:Number(t[1])})),[eo.type]:sg(eo.type,({client:e,positionals:t,flags:s})=>e.interactions.type({...tm(s),text:t.join(" "),delayMs:s.delayMs})),[eo.fill]:sg(eo.fill,({client:e,positionals:t,flags:s})=>e.interactions.fill({...function(e){if(e[0]?.startsWith("@")){let t=e.length>=3?e.slice(2).join(" "):e.slice(1).join(" ");return{ref:e[0],label:e.length>=3?e[1]:void 0,text:t}}let t=en(e,{preferTrailingValue:!0});return t?{selector:t.selectorExpression,text:t.rest.join(" ")}:{x:Number(e[0]),y:Number(e[1]),text:e.slice(2).join(" ")}}(t),...sh(s),...tm(s),delayMs:s.delayMs})),[eo.scroll]:sg(eo.scroll,({client:e,positionals:t,flags:s})=>e.interactions.scroll({...tm(s),direction:function(e){if("up"===e||"down"===e||"left"===e||"right"===e)return e;throw new N("INVALID_ARGS",`Unknown direction: ${String(e)}`)}(t[0]),amount:sb(t[1]),pixels:s.pixels})),[eo.pinch]:sg(eo.pinch,({client:e,positionals:t,flags:s})=>e.interactions.pinch({...tm(s),scale:Number(t[0]),x:sb(t[1]),y:sb(t[2])})),[eo.triggerAppEvent]:sg(eo.triggerAppEvent,({client:e,positionals:t,flags:s})=>e.apps.triggerEvent({...tm(s),event:sw(t[0],"trigger-app-event requires event"),payload:t[1]?function(e,t){try{let t=JSON.parse(e);if(t&&"object"==typeof t&&!Array.isArray(t))return t}catch{}throw new N("INVALID_ARGS",`${t} must be a JSON object`)}(t[1],"trigger-app-event payload"):void 0})),[eo.record]:sg(eo.record,({client:e,positionals:t,flags:s})=>e.recording.record({...tm(s),action:sy(t[0],"record"),path:t[1],fps:s.fps,quality:s.quality,hideTouches:s.hideTouches})),[eo.trace]:sg(eo.trace,({client:e,positionals:t,flags:s})=>e.recording.trace({...tm(s),action:sy(t[0],"trace"),path:t[1]})),[eo.logs]:sg(eo.logs,({client:e,positionals:t,flags:s})=>e.observability.logs({...tm(s),action:function(e){if(void 0!==e){if("path"===e||"start"===e||"stop"===e||"doctor"===e||"mark"===e||"clear"===e)return e;throw new N("INVALID_ARGS","logs requires path, start, stop, doctor, mark, or clear")}}(t[0]),message:t.slice(1).join(" ")||void 0,restart:s.restart})),[eo.network]:sg(eo.network,({client:e,positionals:t,flags:s})=>e.observability.network({...tm(s),action:function(e){if(void 0!==e){if("dump"===e||"log"===e)return e;throw new N("INVALID_ARGS","network requires dump or log")}}(t[0]),limit:sb(t[1]),include:s.networkInclude??function(e){if(void 0!==e){if("summary"===e||"headers"===e||"body"===e||"all"===e)return e;throw new N("INVALID_ARGS","network include mode must be summary, headers, body, or all")}}(t[2])})),[eo.find]:sg(eo.find,({client:e,positionals:t,flags:s})=>{var o;return e.interactions.find({...function(e){let t=function(e){if("text"===e||"label"===e||"value"===e||"role"===e||"id"===e)return e}(e[0]),s=void 0!==t,o=s?e[1]:e[0],r=s?2:1,n=e[r];if(void 0===n)return{locator:t,query:sw(o,"find requires query")};if("get"===n){let s=e[r+1];if("text"===s)return{locator:t,query:sw(o,"find requires query"),action:"getText"};if("attrs"===s)return{locator:t,query:sw(o,"find requires query"),action:"getAttrs"};throw new N("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:sw(o,"find requires query"),action:"wait",timeoutMs:sb(e[r+1])};if("fill"===n||"type"===n)return{locator:t,query:sw(o,"find requires query"),action:n,value:e.slice(r+1).join(" ")};if("click"===n||"focus"===n||"exists"===n)return{locator:t,query:sw(o,"find requires query"),action:n};throw new N("INVALID_ARGS",`Unsupported find action: ${n}`)}(t),...{depth:(o=s).snapshotDepth,raw:o.snapshotRaw},...tm(s),first:s.findFirst,last:s.findLast})}),[eo.is]:sg(eo.is,({client:e,positionals:t,flags:s})=>e.interactions.is({...function(e){let t=e[0],s=en(e.slice(1),{preferTrailingValue:"text"===t});if(!s)throw new N("INVALID_ARGS","is requires a selector expression");if("text"===t)return{predicate:t,selector:s.selectorExpression,value:s.rest.join(" ")};if("visible"===t||"hidden"===t||"exists"===t||"editable"===t||"selected"===t)return{predicate:t,selector:s.selectorExpression};throw new N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text")}(t),...sh(s),...tm(s)})),[eo.settings]:sg(eo.settings,({client:e,positionals:t,flags:s})=>e.settings.update(function(e,t){let s=tm(t),o=e[0],r=e[1];if(("wifi"===o||"airplane"===o||"location"===o||"animations"===o)&&("on"===r||"off"===r)||"appearance"===o&&("light"===r||"dark"===r||"toggle"===r)||("faceid"===o||"touchid"===o)&&("match"===r||"nonmatch"===r||"enroll"===r||"unenroll"===r)||"fingerprint"===o&&("match"===r||"nonmatch"===r))return{...s,setting:o,state:r};if("permission"===o&&("grant"===r||"deny"===r||"reset"===r))return{...s,setting:o,state:r,permission:function(e){switch(e){case"camera":case"microphone":case"photos":case"contacts":case"contacts-limited":case"notifications":case"calendar":case"location":case"location-always":case"media-library":case"motion":case"reminders":case"siri":case"accessibility":case"screen-recording":case"input-monitoring":return e;default:throw new N("INVALID_ARGS","settings permission requires a permission target.")}}(e[2]),mode:function(e){if(void 0===e||"full"===e||"limited"===e)return e;throw new N("INVALID_ARGS","settings permission mode must be full or limited.")}(e[3])};throw new N("INVALID_ARGS","Invalid settings arguments.")}(t,s)))};function sg(e,t){return async({positionals:s,flags:o,client:r})=>{let n=await t({client:r,positionals:s,flags:o}),a=function(e,t,s,o){if(s.json){var r,n,a;return r=e,n=s,a=o,r===eo.test?se({suite:a,json:!0,reportJunit:n.reportJunit}):(eP({success:!0,data:a}),0)}if(e===eo.test)return se({suite:o,verbose:s.verbose,reportJunit:s.reportJunit});let i=sn[e];if(i?.({positionals:t,flags:s,data:o}))return 0;let l=G(o);return l&&process.stdout.write(`${l}
439
+ `),0}(e,s,o,n);return 0!==a&&process.exit(a),!0}}function sh(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function sv(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=en(e);return t?{selector:t.selectorExpression}:{x:Number(e[0]),y:Number(e[1])}}function sy(e,t){if("start"===e||"stop"===e)return e;throw new N("INVALID_ARGS",`${t} requires start|stop`)}function sw(e,t){if(void 0===e||""===e)throw new N("INVALID_ARGS",t);return e}function sb(e){return void 0===e?void 0:Number(e)}let sk={...{session:th,[eo.devices]:tv,[eo.apps]:tk,"ensure-simulator":tw,metro:tb,install:tS,reinstall:tx,"install-from-source":t$,connect:tZ,disconnect:tX,connection:tQ,auth:t5,open:tN,close:tR,[eo.snapshot]:t8,[eo.screenshot]:t4,[eo.diff]:t6},...t7,...sf};async function sA(e){let t=sk[e.command];return!!t&&await t(e)}function sI(e,t,s){return s||(e.push(t),"")}async function sD(e,t,s){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let s=[],o={serverBaseUrl:sI(s,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:sI(s,"metroBearerToken",e.metroBearerToken),tenantId:sI(s,"tenant",e.tenant),runId:sI(s,"runId",e.runId),leaseId:sI(s,"leaseId",e.leaseId)};if(s.length>0)throw new N("INVALID_ARGS",`react-devtools remote bridge requires ${s.join(", ")}.`,{missing:s});return o}(o);if(!r)return s();let n=t.stateDir??process.cwd(),a=t.session??o?.session??"default",i=o?.remoteConfig??`${r.tenantId}:${r.runId}:${r.leaseId}`;if("stop"===e[0])try{return await s()}finally{await eZ({projectRoot:t.cwd??process.cwd(),stateDir:n,profileKey:i,consumerKey:a})}return await eY({projectRoot:t.cwd??process.cwd(),stateDir:n,serverBaseUrl:r.serverBaseUrl,bearerToken:r.bearerToken,bridgeScope:{tenantId:r.tenantId,runId:r.runId,leaseId:r.leaseId},session:a,profileKey:i,consumerKey:a,env:t.env??process.env}),await s()}async function sS(e,t={}){let s=t.cwd??process.cwd(),o=t.env??process.env,r=await sD(e,t,async()=>(await Z("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:s,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var n,a=t.flags;return 0!==r&&"wait"===(n=e)[0]&&n.includes("--connected")&&"ios-instance"===a?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.\n"),r}function sx(e,t={}){let s=s$(t),o={...e};return s.defaultPlatform&&void 0===o.platform&&(o.platform=s.defaultPlatform),o}function s$(e){var t,s,o,r;let n,a=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new N("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(a.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??a.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(s=e.policyOverrides,o=a,r=l,(n=s?.sessionLock??s?.sessionLockConflicts??sC(o.AGENT_DEVICE_SESSION_LOCK)??sC(o.AGENT_DEVICE_SESSION_LOCK_CONFLICTS))||(s?.sessionLocked===!0||ea(o.AGENT_DEVICE_SESSION_LOCKED)||r?"reject":void 0))}}function sC(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new N("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}let sL={sendToDaemon:er},sN=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),sR=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]);async function s_(e,t=sL){let s=O(),o=W(),r=e.includes("--debug")||e.includes("--verbose")||e.includes("-v"),n=e.includes("--json"),a=function(e){for(let t=0;t<e.length;t+=1){let s=e[t];if(s.startsWith("--session=")){let e=s.slice(10).trim();return e.length>0?e:null}if("--session"===s){let s=e[t+1]?.trim();if(s&&!s.startsWith("-"))return s;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await U({session:a,requestId:s,command:e[0],debug:r},async()=>{var a,i,c,d,u,m,f,g,h,v,y,w,b,k,A,S,$;let R,_,E,O,U,F,B;try{let t,s,o,r,n,w,b,k;a={cwd:process.cwd(),env:process.env},t=function(e){let t={json:!1,help:!1,version:!1},s=null,o=[],r=[],n=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(n&&"--"===c){n=!1;continue}if(!n){s?o.push(c):s=eU(c);continue}let d=c.startsWith("--"),p=c.startsWith("-")&&c.length>1;if(!d&&!p){s?o.push(c):s=eU(c);continue}let[u,m]=d?e_(c):[c,void 0],f=eh.get(u);if(a=s,i=f,"react-devtools"===a&&(!i||!eN(i.key,a))){o.push(c);continue}if(!f){if(function(e,t,s){var o;if(o=s,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=ey(e);return!r||!!r.allowsExtraPositionals||0!==r.positionalArgs.length&&(t.length<r.positionalArgs.length||r.positionalArgs.some(e=>e.includes("?")))}(s,o,c)){s?o.push(c):s=c;continue}throw new N("INVALID_ARGS",`Unknown flag: ${u}`)}let g=function(e,t,s,o){if(void 0!==e.setValue){if(void 0!==s)throw new N("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==s)throw new N("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==s){if(0===s.trim().length)throw new N("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:s,consumeNext:!1}}return void 0===o||eO(o)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(o)?{value:!0,consumeNext:!1}:{value:o,consumeNext:!0}}let r=s??o;if(void 0===r||void 0===s&&eO(r))throw new N("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===s};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new N("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:r,consumeNext:void 0===s}}let n=Number(r);if(!Number.isFinite(n)||"number"==typeof e.min&&n<e.min||"number"==typeof e.max&&n>e.max)throw new N("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:Math.floor(n),consumeNext:void 0===s}}(f,u,m,e[l+1]);g.consumeNext&&(l+=1);let h=t[f.key];if(f.multiple){let e=Array.isArray(h)?[...h,g.value]:void 0===h?[g.value]:[h,g.value];t[f.key]=e}else t[f.key]=g.value;r.push({key:f.key,token:u})}return{command:s,positionals:o,flags:t,warnings:[],providedFlags:r}}(e),s=a?.env??process.env,o=a?.cwd??process.cwd(),d=t.command,r=null!==d&&(i={remoteConfig:t.flags.remoteConfig,cwd:o,env:s}).remoteConfig?{...te(I({configPath:i.remoteConfig,cwd:i.cwd,env:i.env}).profile),remoteConfig:i.remoteConfig}:{},b=ec((n=(c={command:t.command,cwd:o,cliFlags:t.flags,env:s}).env??process.env,w=ec({},function(e){let t={};for(let s of e)ec(t,function(e,t){let s,o;if(!p.existsSync(e)){if(t)throw new N("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{s=p.readFileSync(e,"utf8")}catch(t){throw new N("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(s)}catch(t){throw new N("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new N("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let s={};for(let[o,r]of Object.entries(e)){if("installSource"===o){s.installSource=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new N("INVALID_ARGS",`${t} installSource must be an object.`);if("github-actions-artifact"!==tD(e.type,`${t} installSource.type`))throw new N("INVALID_ARGS",`${t} installSource.type must be "github-actions-artifact".`);let{owner:s,repo:o}=tI(tD(e.repo,`${t} installSource.repo`),`${t} installSource.repo`);return tA(s,o,e.artifact,`${t} installSource.artifact`)}(r,t);continue}let e=eL.get(o);if(!e)throw new N("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new N("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);s[o]=x(eR(e),r,t,o)}return s}(o,`config file ${e}`)}(s.path,s.required));return t}((u=c.cwd,m=c.cliFlags.config,f=n,(k=m??f.AGENT_DEVICE_CONFIG)?[{path:(g=k,h=u,v=f,Q(g,{cwd:h,env:v})),required:!0}]:[{path:(y=f,l.join(ee("~",{env:y}),".agent-device","config.json")),required:!1},{path:l.resolve(u,"agent-device.json"),required:!1}]))),ec(w,function(e,t){var s,o,r;let n={};for(let a of eC.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===a.key)continue;let t=a.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(n[a.key]=(s=t.value,o=`environment variable ${t.name}`,r=t.name,x(eR(a),s,o,r)))}return n}(n,c.command))),r),R={...function(e,t){let s=t?.strictFlags??function(e){if(!e)return!1;let t=e.trim().toLowerCase();return"1"===t||"true"===t||"yes"===t||"on"===t}(process.env.AGENT_DEVICE_STRICT_FLAGS),o=[...e.warnings],r=ec({json:!1,help:!1,version:!1},t?.defaultFlags??{});ec(r,e.flags);let n=ey(e.command),a=e.providedFlags.filter(t=>!eN(t.key,e.command));if(a.length>0){var i,l;let t=a.map(e=>e.token),n=(i=e.command,l=t,i?1===l.length?`Flag ${l[0]} is not supported for command ${i}.`:`Flags ${l.join(", ")} are not supported for command ${i}.`:1===l.length?`Flag ${l[0]} requires a command that supports it.`:`Flags ${l.join(", ")} require a command that supports them.`);if(s)throw new N("INVALID_ARGS",n);for(let e of(o.push(`${n} Enable AGENT_DEVICE_STRICT_FLAGS=1 to fail fast.`),a))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eN(t,e.command)||delete r[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new N("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),n?.defaults)for(let[e,t]of Object.entries(n.defaults))void 0===r[e]&&(r[e]=t);if("batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new N("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...s}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:s,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(t,{strictFlags:a?.strictFlags,defaultFlags:b}),providedFlags:t.providedFlags}}catch(t){M({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=L(t,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});n?eP({success:!1,error:e}):eT(e,{showDetails:r}),process.exit(1);return}for(let e of R.warnings)process.stderr.write(`Warning: ${e}
440
+ `);R.flags.version&&(process.stdout.write(`${o}
441
+ `),process.exit(0));let j="help"===R.command,V=R.flags.help;if(j||V){j&&R.positionals.length>1&&(eT(new N("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=j?R.positionals[0]:R.command;e||(process.stdout.write(`${ek}
433
442
  `),process.exit(0));let t=function(e){var t,s;let o,r=(o=eu[e])?`${o.body}
434
443
 
435
444
  Related:
436
445
  agent-device help command list and global flags
437
446
  agent-device help <command> command-specific flags
438
447
  agent-device help workflow normal app automation loop
439
- `:null;if(r)return r;let a=ey(e);if(!a)return null;let n=(t=e,(s=a).usageOverride?s.usageOverride:[t,...s.positionalArgs.map(eb),...s.allowedFlags.flatMap(e=>(ev.get(e)??[]).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`)].join(" ")),i=eI(new Set(a.allowedFlags)),l=eI(ef),c=[];return i.length>0&&c.push(eA("Command flags:",i)),c.push(eA("Global flags:",l)),`agent-device ${n}
448
+ `:null;if(r)return r;let n=ey(e);if(!n)return null;let a=(t=e,(s=n).usageOverride?s.usageOverride:[t,...s.positionalArgs.map(eb),...s.allowedFlags.flatMap(e=>(ev.get(e)??[]).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`)].join(" ")),i=eA(new Set(n.allowedFlags)),l=eA(ef),c=[];return i.length>0&&c.push(eI("Command flags:",i)),c.push(eI("Global flags:",l)),`agent-device ${a}
440
449
 
441
- ${a.helpDescription}
450
+ ${n.helpDescription}
442
451
 
443
452
  Usage:
444
- agent-device ${n}
453
+ agent-device ${a}
445
454
 
446
455
  ${c.join("\n\n")}
447
- `}(eU(e));t&&(process.stdout.write(t),process.exit(0)),eT(new R("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${ek}
448
- `),process.exit(1)}C.command||(process.stdout.write(`${ek}
449
- `),process.exit(1));let{command:G,positionals:q}=C,H=new Set(C.providedFlags.map(e=>e.key));try{E=(_=sb({policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session})).lockPolicy?{...C.flags}:sw(C.flags,{policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session}),O=K(E.stateDir),U=E.session??"default",w={command:G,explicitFlagKeys:H,stateDir:O.baseDir,session:U,remoteConfig:E.remoteConfig},B=(F="connect"===w.command||"connection"===w.command?null:function(e){let t=e.validateRemoteConfigHash??!0,s=e.remoteConfig?D({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=eX(e)??(e.allowActiveFallback?e8({stateDir:e.stateDir}):null);if(!o||s&&o.remoteConfigPath!==s)return null;if(t&&e2(o.remoteConfigPath)!==o.remoteConfigHash)throw new R("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return A({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(o,e);return{runtime:o.runtime,flags:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:w.stateDir,session:w.session,remoteConfig:w.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!w.explicitFlagKeys.has("session")&&(!w.remoteConfig||"disconnect"===w.command),validateRemoteConfigHash:"disconnect"!==w.command}))?function(e,t,s){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(s.has(e)||(o[e]=r));return o}(E,F.flags,H):E}catch(t){let e=N(L(t),{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});C.flags.json?eP({success:!1,error:e}):eT(e,{showDetails:C.flags.verbose}),process.exit(1);return}let J=null;try{let e;if("react-devtools"===G){let e=await sy(q,{flags:B,stateDir:O.baseDir,session:B.session??U,cwd:process.cwd(),env:process.env});process.exit(e);return}el({command:G,currentVersion:o,stateDir:O.baseDir,flags:B});let r=F?.runtime,a=(e,t)=>({session:e.session??U,requestId:s,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,runtime:t,lockPolicy:_.lockPolicy,lockPlatform:_.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===G){if(q.length>0)throw new R("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t="";if(e.steps)t=e.steps;else if(e.stepsFile)try{t=d.readFileSync(e.stepsFile,"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new R("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}return ei(t)}(E)}if(b=G,"auth"!==b&&"connection"!==b&&(B=(await tT({command:G,flags:B,stateDir:O.baseDir,env:process.env})).flags),B.remoteConfig&&(k=G,!sS.has(k))){let s=es(a(B,r),{transport:t.sendToDaemon}),o=await tt({command:G,flags:B,client:s,runtime:r,batchSteps:e,forceRuntimePrepare:function(e){for(let t of sD)if(e.has(t))return!0;return!1}(H)});B=o.flags,r=o.runtime}I={command:G,flags:B,runtime:r,explicitFlagKeys:H,hadConnectionDefaults:!!F},!("open"===I.command&&!I.runtime&&!I.flags.bundleUrl&&!I.flags.metroHost&&!I.flags.metroPort&&!I.flags.remoteConfig&&!I.hadConnectionDefaults&&((S=I.explicitFlagKeys).has("daemonBaseUrl")||S.has("daemonTransport")||S.has("tenant")||S.has("sessionIsolation")||S.has("runId")||S.has("leaseId")||S.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n");let n=B.daemonBaseUrl;J=!B.verbose||B.json||n?null:function(e){try{let t=0,s=!1,o=setInterval(()=>{if(!s&&d.existsSync(e))try{let s=d.statSync(e);if(s.size<t&&(t=0),s.size<=t)return;let o=d.openSync(e,"r");try{let e=Buffer.alloc(s.size-t);d.readSync(o,e,0,e.length,t),t=s.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{d.closeSync(o)}}catch{}},200);return()=>{s=!0,clearInterval(o)}}catch{return null}}(O.logPath);let i=es(a(B,r),{transport:t.sendToDaemon});if("batch"===G){if(!e)throw new R("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,flags:_.lockPolicy&&void 0===E.platform?{...e.flags??{}}:sw(e.flags??{},{policyOverrides:B,configuredPlatform:B.platform,configuredSession:B.session,inheritedPlatform:B.platform})}));if(await sh({command:G,positionals:q,flags:{...B,batchSteps:t},client:i}))return}else if("runtime"===G)throw new R("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await sh({command:G,positionals:q,flags:B,client:i}))return;throw new R("INVALID_ARGS",`Unknown command: ${G}`)}catch(s){let e=L(s),t=N(e,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});if("close"===G&&"COMMAND_FAILED"===($=e).code&&($.details?.kind==="daemon_startup_failed"||$.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof $.details?.infoPath||"string"==typeof $.details?.lockPath))){B.json&&eP({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(B.json)eP({success:!1,error:t});else if(eT(t,{showDetails:B.verbose}),B.verbose)try{let e=O.logPath;if(d.existsSync(e)){let t=d.readFileSync(e,"utf8").split("\n"),s=t.slice(Math.max(0,t.length-200)).join("\n");s.trim().length>0&&process.stderr.write(`
456
+ `}(eU(e));t&&(process.stdout.write(t),process.exit(0)),eT(new N("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${ek}
457
+ `),process.exit(1)}R.command||(process.stdout.write(`${ek}
458
+ `),process.exit(1));let{command:G,positionals:q}=R,K=new Set(R.providedFlags.map(e=>e.key));try{E=(_=s$({policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session})).lockPolicy?{...R.flags}:sx(R.flags,{policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session}),O=H(E.stateDir),U=E.session??"default",w={command:G,explicitFlagKeys:K,stateDir:O.baseDir,session:U,remoteConfig:E.remoteConfig,hasResolvedSession:void 0!==E.session},B=(F="connect"===w.command||"connection"===w.command?null:function(e){let t=e.validateRemoteConfigHash??!0,s=e.remoteConfig?D({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=eX(e)??(e.allowActiveFallback?e8({stateDir:e.stateDir}):null);if(!o||s&&o.remoteConfigPath!==s)return null;if(t&&e2(o.remoteConfigPath)!==o.remoteConfigHash)throw new N("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return I({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(o,e);return{runtime:o.runtime,flags:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:w.stateDir,session:w.session,remoteConfig:w.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!w.explicitFlagKeys.has("session")&&(!w.remoteConfig||"disconnect"===w.command||!w.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==w.command}))?function(e,t,s){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(s.has(e)||(o[e]=r));return o}(E,F.flags,K):E}catch(t){let e=L(C(t),{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});R.flags.json?eP({success:!1,error:e}):eT(e,{showDetails:R.flags.verbose}),process.exit(1);return}let J=null;try{let e;if("react-devtools"===G){let e=await sS(q,{flags:B,stateDir:O.baseDir,session:B.session??U,cwd:process.cwd(),env:process.env});process.exit(e);return}el({command:G,currentVersion:o,stateDir:O.baseDir,flags:B});let r=F?.runtime,n=(e,t)=>({session:e.session??U,requestId:s,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,runtime:t,lockPolicy:_.lockPolicy,lockPlatform:_.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===G){if(q.length>0)throw new N("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t="";if(e.steps)t=e.steps;else if(e.stepsFile)try{t=p.readFileSync(e.stepsFile,"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new N("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}return ei(t)}(E)}if(b=G,"auth"!==b&&"connection"!==b&&(B=(await t_({command:G,flags:B,stateDir:O.baseDir,env:process.env})).flags),B.remoteConfig&&(k=G,!sR.has(k))){let s=es(n(B,r),{transport:t.sendToDaemon}),o=await to({command:G,flags:B,client:s,runtime:r,batchSteps:e,forceRuntimePrepare:function(e){for(let t of sN)if(e.has(t))return!0;return!1}(K)});B=o.flags,r=o.runtime}A={command:G,flags:B,runtime:r,explicitFlagKeys:K,hadConnectionDefaults:!!F},!("open"===A.command&&!A.runtime&&!A.flags.bundleUrl&&!A.flags.metroHost&&!A.flags.metroPort&&!A.flags.remoteConfig&&!A.hadConnectionDefaults&&((S=A.explicitFlagKeys).has("daemonBaseUrl")||S.has("daemonTransport")||S.has("tenant")||S.has("sessionIsolation")||S.has("runId")||S.has("leaseId")||S.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n");let a=B.daemonBaseUrl;J=!B.verbose||B.json||a?null:function(e){try{let t=0,s=!1,o=setInterval(()=>{if(!s&&p.existsSync(e))try{let s=p.statSync(e);if(s.size<t&&(t=0),s.size<=t)return;let o=p.openSync(e,"r");try{let e=Buffer.alloc(s.size-t);p.readSync(o,e,0,e.length,t),t=s.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{p.closeSync(o)}}catch{}},200);return()=>{s=!0,clearInterval(o)}}catch{return null}}(O.logPath);let i=es(n(B,r),{transport:t.sendToDaemon});if("batch"===G){if(!e)throw new N("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,flags:_.lockPolicy&&void 0===E.platform?{...e.flags??{}}:sx(e.flags??{},{policyOverrides:B,configuredPlatform:B.platform,configuredSession:B.session,inheritedPlatform:B.platform})}));if(await sA({command:G,positionals:q,flags:{...B,batchSteps:t},client:i}))return}else if("runtime"===G)throw new N("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await sA({command:G,positionals:q,flags:B,client:i}))return;throw new N("INVALID_ARGS",`Unknown command: ${G}`)}catch(s){let e=C(s),t=L(e,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});if("close"===G&&"COMMAND_FAILED"===($=e).code&&($.details?.kind==="daemon_startup_failed"||$.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof $.details?.infoPath||"string"==typeof $.details?.lockPath))){B.json&&eP({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(B.json)eP({success:!1,error:t});else if(eT(t,{showDetails:B.verbose}),B.verbose)try{let e=O.logPath;if(p.existsSync(e)){let t=p.readFileSync(e,"utf8").split("\n"),s=t.slice(Math.max(0,t.length-200)).join("\n");s.trim().length>0&&process.stderr.write(`
450
459
  [daemon log]
451
460
  ${s}
452
- `)}}catch{}J&&J(),process.exit(1)}finally{J&&J()}})}p(process.argv[1]??"").href===import.meta.url&&sx(process.argv.slice(2)).catch(e=>{eT(N(L(e)),{showDetails:!0}),process.exit(1)}),sx(process.argv.slice(2));
461
+ `)}}catch{}J&&J(),process.exit(1)}finally{J&&J()}})}d(process.argv[1]??"").href===import.meta.url&&s_(process.argv.slice(2)).catch(e=>{eT(L(C(e)),{showDetails:!0}),process.exit(1)}),s_(process.argv.slice(2));