agent-device 0.16.2 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.2.apk → agent-device-android-multitouch-helper-0.16.4.apk} +0 -0
  2. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.4.apk.sha256 +1 -0
  3. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.2.manifest.json → agent-device-android-multitouch-helper-0.16.4.manifest.json} +4 -4
  4. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.4.apk +0 -0
  5. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.4.apk.sha256 +1 -0
  6. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.2.manifest.json → agent-device-android-snapshot-helper-0.16.4.manifest.json} +6 -6
  7. package/dist/src/1393.js +1 -0
  8. package/dist/src/1769.js +7 -7
  9. package/dist/src/221.js +6 -4
  10. package/dist/src/6277.js +2 -2
  11. package/dist/src/7519.js +1 -1
  12. package/dist/src/7599.js +3 -0
  13. package/dist/src/9542.js +1 -1
  14. package/dist/src/android-adb.js +1 -1
  15. package/dist/src/android-snapshot-helper.d.ts +10 -1
  16. package/dist/src/android-snapshot-helper.js +1 -1
  17. package/dist/src/cli.js +15 -13
  18. package/dist/src/index.d.ts +2 -0
  19. package/dist/src/internal/daemon.js +51 -51
  20. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/AppIcon.appiconset/logo.jpg +0 -0
  21. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/Logo.imageset/logo.jpg +0 -0
  22. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +0 -4
  23. package/package.json +1 -1
  24. package/server.json +2 -2
  25. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.2.apk.sha256 +0 -1
  26. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.2.apk +0 -0
  27. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.2.apk.sha256 +0 -1
  28. package/dist/src/3622.js +0 -3
  29. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -14
  30. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/Assets.xcassets/AppIcon.appiconset/logo-tinted.jpg +0 -0
  31. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/Assets.xcassets/Contents.json +0 -6
package/dist/src/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- import e from"node:path";import{styleText as t}from"node:util";import{pathToFileURL as n}from"node:url";import o from"node:fs";import r from"node:crypto";import{interactionCliReaders as s,serializeSessionListEntry as a,serializeSnapshotResult as i,gestureCliReaders as l,observabilityCliReaders as c,serializeCloseResult as d,parseInstallSourceConfig as u,listCliCommandNames as p,readVersion as f,captureCliReaders as m,serializeOpenResult as h,replayCliReaders as g,serializeDeployResult as v,readCommandMessage as w,resolveDaemonPaths as y,appCliReaders as b,commonInputFromFlags as I,serializeInstallFromSourceResult as x,selectorCliReaders as A,serializeDevice as $,systemCliReaders as k}from"./6277.js";import{buildMobileSnapshotPresentation as S,formatSnapshotLine as C,GLOBAL_FLAG_KEYS as D,getFlagDefinition as N,createAgentDevice as R,getCliCommandSchema as U,getCommandSchema as _,applyCommandDefaults as E,displayNodeLabel as P,localCommandPolicy as O,getFlagDefinitions as L,buildSnapshotDisplayLines as T}from"./7519.js";import{resolveRemoteConfigProfile as M,resolveRemoteConfigPath as B,REMOTE_CONFIG_FIELD_SPECS as j,parseSourceValue as F,buildPrimaryEnvVarName as G}from"./208.js";import{asAppError as V,normalizeError as H,AppError as K}from"./9152.js";import{ensureCompanionTunnel as q,stopCompanionTunnel as z}from"./1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as J}from"./2301.js";import{createRequestId as W,withDiagnosticsScope as Z,getDiagnosticsMeta as X,flushDiagnosticsToSessionFile as Y,emitDiagnostic as Q}from"./3622.js";import{stopMetroTunnel as ee}from"./metro.js";import{runCmdStreaming as et,runCmd as en}from"./9818.js";import{listCommandNames as eo,isCommandName as er,runCommand as es}from"./89.js";import{resolveUserPath as ea,expandUserHomePath as ei}from"./3267.js";import{createLocalArtifactAdapter as el}from"./7719.js";import{createAgentDeviceClient as ec,sendToDaemon as ed}from"./9542.js";import{maybeRunUpgradeNotifier as eu}from"./113.js";function ep(e,t){for(let[n,o]of Object.entries(t))void 0!==o&&(e[n]=o);return e}let ef=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, alerts, diagnostics, and traces"},{label:"help react-native",description:"React Native app automation hazards, overlays, Metro, and routing"},{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"}],em=["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 refreshes current interactive refs only.","Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Anti-pattern: snapshot -i followed by snapshot -i | grep ...; prior refs stay valid until app state changes, and --force-full is the explicit full re-read.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","React Native apps: read help react-native for Metro, DevTools routing, and RN-specific blockers; use react-native dismiss-overlay for LogBox/RedBox overlays.","Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability.",'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.',"Android IME capture: if fill says input was captured by the keyboard/IME, inspect keyboard state and switch/disable handwriting before retrying; do not loop fill/type.","Run mutating commands serially against one session; parallelize only read-only commands or separate sessions.","Before taking over a shared device, run session list and reuse the active session name when one already owns the device.","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: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known.","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" and structured "input"; legacy "positionals"/"flags" steps still run in CLI but are deprecated until the next major version.',"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."],eh=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],eg=[{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"}],ev=["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"],ew={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
1
+ import e from"node:path";import{styleText as t}from"node:util";import{pathToFileURL as n}from"node:url";import o from"node:fs";import r from"node:crypto";import{interactionCliReaders as s,serializeSessionListEntry as a,serializeSnapshotResult as i,gestureCliReaders as l,observabilityCliReaders as c,serializeCloseResult as d,parseInstallSourceConfig as u,listCliCommandNames as p,readVersion as f,captureCliReaders as m,serializeOpenResult as h,replayCliReaders as g,serializeDeployResult as v,readCommandMessage as w,resolveDaemonPaths as y,appCliReaders as b,commonInputFromFlags as I,serializeInstallFromSourceResult as x,selectorCliReaders as A,serializeDevice as $,systemCliReaders as k}from"./6277.js";import{buildMobileSnapshotPresentation as S,formatSnapshotLine as C,GLOBAL_FLAG_KEYS as D,getFlagDefinition as N,createAgentDevice as R,getCliCommandSchema as U,getCommandSchema as _,applyCommandDefaults as E,displayNodeLabel as P,localCommandPolicy as L,getFlagDefinitions as O,buildSnapshotDisplayLines as T}from"./7519.js";import{resolveRemoteConfigProfile as M,resolveRemoteConfigPath as B,REMOTE_CONFIG_FIELD_SPECS as j,parseSourceValue as F,buildPrimaryEnvVarName as G}from"./208.js";import{asAppError as V,normalizeError as H,AppError as K}from"./9152.js";import{ensureCompanionTunnel as q,stopCompanionTunnel as z}from"./1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as J}from"./2301.js";import{createRequestId as W,withDiagnosticsScope as Z,getDiagnosticsMeta as X,flushDiagnosticsToSessionFile as Y,emitDiagnostic as Q}from"./7599.js";import{stopMetroTunnel as ee}from"./metro.js";import{runCmdStreaming as et,runCmd as en}from"./9818.js";import{listCommandNames as eo,isCommandName as er,runCommand as es}from"./89.js";import{resolveUserPath as ea,expandUserHomePath as ei}from"./3267.js";import{createLocalArtifactAdapter as el}from"./7719.js";import{createAgentDeviceClient as ec,sendToDaemon as ed}from"./9542.js";import{maybeRunUpgradeNotifier as eu}from"./113.js";function ep(e,t){for(let[n,o]of Object.entries(t))void 0!==o&&(e[n]=o);return e}let ef=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, alerts, diagnostics, and traces"},{label:"help react-native",description:"React Native app automation hazards, overlays, Metro, and routing"},{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"}],em=["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 refreshes current interactive refs only.","Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Anti-pattern: snapshot -i followed by snapshot -i | grep ...; prior refs stay valid until app state changes, and --force-full is the explicit full re-read.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","React Native apps: read help react-native for Metro, DevTools routing, and RN-specific blockers; use react-native dismiss-overlay for LogBox/RedBox overlays.","Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability.",'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.',"Android IME capture: if fill says input was captured by the keyboard/IME, inspect keyboard state and switch/disable handwriting before retrying; do not loop fill/type.","Run mutating commands serially against one session; parallelize only read-only commands or separate sessions.","Before taking over a shared device, run session list and reuse the active session name when one already owns the device.","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: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known.","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" and structured "input"; legacy "positionals"/"flags" steps still run in CLI but are deprecated until the next major version.',"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."],eh=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],eg=[{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"}],ev=["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"],ew={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
 
@@ -279,6 +279,8 @@ React Native dev loop:
279
279
  agent-device find "Home"
280
280
  Do not use agent-device reload. Use open --relaunch for native startup reset.
281
281
  Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability. For app/package launches, use help react-native if the app cannot reach local Metro.
282
+ Verify Metro from the same host context that owns Metro. If a sandboxed shell cannot curl localhost:8081/status but an unrestricted host shell can, Metro is running and the sandbox probe is not authoritative.
283
+ adb reverse only affects Android device-to-host traffic. It does not prove host-to-Metro reachability, and it does not fix a redbox caused by a stale or wrong Metro/app state.
282
284
  Expo Go/dev clients are host shells. Use provided project URLs, verify with snapshot -i after opening, and ask instead of inventing app ids or URLs. Help workflow owns the full Expo URL command shapes.
283
285
 
284
286
  Overlays and busy RN UIs:
@@ -411,9 +413,9 @@ Rules:
411
413
  Prefer refs for exploration and selectors for deterministic replay.
412
414
  Use logs, network, screenshot --overlay-refs, trace, perf, or react-devtools only when they add evidence to a specific issue.
413
415
  Never delete screenshots, videos, traces, or report artifacts during a session.
414
- Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function ey(e){let t=e.endsWith("?"),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function eb(e){return L().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function eI(e,t){return ex(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function ex(e,t){if(0===t.length)return`${e}
416
+ Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function ey(e){let t=e.endsWith("?"),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function eb(e){return O().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function eI(e,t){return ex(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function ex(e,t){if(0===t.length)return`${e}
415
417
  (none)`;let n=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(n)}${e.description}`);return o.join("\n")}function eA(e,t){return 0===t.length?`${e}
416
- (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let e$=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),ek=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),eS=function(){let e=new Map;for(let t of L()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of D)t.set(e,new Set(["*"]));for(let e of p())for(let n of U(e).allowedFlags??[]){let o=t.get(n);o&&o.has("*")||(o?o.add(e):t.set(n,new Set([e])))}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,config:{enabled:!e$.has(e),key:e},env:{names:ek.has(e)?[]:[G(e)]},supportsCommand(n){let o=t.get(e);return!!o&&(!!o.has("*")||!!n&&o.has(n))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eC=new Map(eS.map(e=>[e.key,e]));function eD(e,t){return eC.get(e)?.supportsCommand(t)??!1}function eN(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let n=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===n.type){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...n,setValue:void 0,enumValues:t}}return n}function eR(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eU(e){return e.replace(/^-+/,"")}function e_(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?eR(e):[e,void 0];return void 0!==N(t)}function eE(){let e,t,n,o,r,s,a,i;return e=`agent-device <command> [args] [--json]
418
+ (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let e$=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),ek=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),eS=function(){let e=new Map;for(let t of O()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of D)t.set(e,new Set(["*"]));for(let e of p())for(let n of U(e).allowedFlags??[]){let o=t.get(n);o&&o.has("*")||(o?o.add(e):t.set(n,new Set([e])))}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,config:{enabled:!e$.has(e),key:e},env:{names:ek.has(e)?[]:[G(e)]},supportsCommand(n){let o=t.get(e);return!!o&&(!!o.has("*")||!!n&&o.has(n))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eC=new Map(eS.map(e=>[e.key,e]));function eD(e,t){return eC.get(e)?.supportsCommand(t)??!1}function eN(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let n=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===n.type){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...n,setValue:void 0,enumValues:t}}return n}function eR(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eU(e){return e.replace(/^-+/,"")}function e_(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?eR(e):[e,void 0];return void 0!==N(t)}function eE(){let e,t,n,o,r,s,a,i;return e=`agent-device <command> [args] [--json]
417
419
 
418
420
  CLI to control iOS and Android devices for AI agents.
419
421
  `,t=ex("Commands:",p().map(e=>{let t=U(e);return{name:e,schema:t,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let n=(t.positionalArgs??[]).map(n=>{var o,r,s;let a,i,l,c;return o=e,r=t,i=(a=(s=n).endsWith("?"))?s.slice(0,-1):s,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,...n].join(" ")}(e,t)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),n=eI("Flags:",eb(D)),o=eA("Agent Quickstart:",em),r=ex("Agent Workflows:",ef),s=eA("Configuration:",eh),a=ex("Environment:",eg),i=eA("Examples:",ev),`${e}
@@ -430,7 +432,7 @@ ${s}
430
432
  ${a}
431
433
 
432
434
  ${i}
433
- `}function eP(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eO(e){return e.width>0&&e.height>0}function eL(e,t){return!!e&&!!t&&e.x>=t.x-2&&e.y>=t.y-2&&e.x+e.width<=t.x+t.width+2&&e.y+e.height<=t.y+t.height+2}function eT(e){return"number"!=typeof e.parentIndex}function eM(e){let t=(e.type??"").toLowerCase(),n=(e.identifier??"").trim().toLowerCase();return t.includes("edittext")||t.includes("textfield")||"composer"===n}function eB(e){let t=(e.type??"").toLowerCase();return t.includes("scroll")||t.includes("list")||t.includes("recyclerview")}function ej(e){var t;let n=P(e);if(!n||n!==e.identifier?.trim()||(t=n,!/^[\w.]+:id\/[\w.-]+$/i.test(t)))return n;let o=(e.type??"").toLowerCase();return o.includes("view")||o.includes("layout")||o.includes("image")||o.includes("list")||o.includes("recyclerview")||o.includes("collection")?"":n}function eF(e){let t=e.trim().replace(/\s+/g," ").toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function eG(e,t){let n=[],o=[t];for(;o.length>0;){let t=o.pop();for(let r of e)r.parentIndex===t&&(n.push(r),o.push(r.index))}return n}function eV(e,t,n){let o=[t];for(;o.length>0;){let t=o.pop();if(!n.has(t))for(let r of(n.add(t),e))r.parentIndex!==t||n.has(r.index)||o.push(r.index)}}let eH=["button","switch","checkbox","radio"],eK=["button","image","textview","view"];function eq(e){if(!0===e.hittable||eM(e))return!1;let t=(e.type??"").toLowerCase();return t.includes("text")||t.includes("image")||t.includes("icon")}function ez(e){if(!e.rect||!eO(e.rect)||eT(e)||eM(e))return!1;let t=(e.type??"").toLowerCase();return"text"===t||eZ(t,eK)}function eJ(e,t){let n=eW(e);return eW(t)>n?t:e}function eW(e){let t=(e.type??"").toLowerCase(),n=0;return eZ(t,eH)?n+=100:t.includes("image")?n+=30:t.includes("textview")||"text"===t?n+=20:t.includes("view")&&(n+=10),!0===e.hittable&&(n+=20),!1!==e.enabled&&(n+=5),n}function eZ(e,t){return t.some(t=>e.includes(t))}function eX(e){process.stdout.write(`${JSON.stringify(e,null,2)}
435
+ `}function eP(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eL(e){return e.width>0&&e.height>0}function eO(e,t){return!!e&&!!t&&e.x>=t.x-2&&e.y>=t.y-2&&e.x+e.width<=t.x+t.width+2&&e.y+e.height<=t.y+t.height+2}function eT(e){return"number"!=typeof e.parentIndex}function eM(e){let t=(e.type??"").toLowerCase(),n=(e.identifier??"").trim().toLowerCase();return t.includes("edittext")||t.includes("textfield")||"composer"===n}function eB(e){let t=(e.type??"").toLowerCase();return t.includes("scroll")||t.includes("list")||t.includes("recyclerview")}function ej(e){var t;let n=P(e);if(!n||n!==e.identifier?.trim()||(t=n,!/^[\w.]+:id\/[\w.-]+$/i.test(t)))return n;let o=(e.type??"").toLowerCase();return o.includes("view")||o.includes("layout")||o.includes("image")||o.includes("list")||o.includes("recyclerview")||o.includes("collection")?"":n}function eF(e){let t=e.trim().replace(/\s+/g," ").toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function eG(e,t){let n=[],o=[t];for(;o.length>0;){let t=o.pop();for(let r of e)r.parentIndex===t&&(n.push(r),o.push(r.index))}return n}function eV(e,t,n){let o=[t];for(;o.length>0;){let t=o.pop();if(!n.has(t))for(let r of(n.add(t),e))r.parentIndex!==t||n.has(r.index)||o.push(r.index)}}let eH=["button","switch","checkbox","radio"],eK=["button","image","textview","view"];function eq(e){if(!0===e.hittable||eM(e))return!1;let t=(e.type??"").toLowerCase();return t.includes("text")||t.includes("image")||t.includes("icon")}function ez(e){if(!e.rect||!eL(e.rect)||eT(e)||eM(e))return!1;let t=(e.type??"").toLowerCase();return"text"===t||eZ(t,eK)}function eJ(e,t){let n=eW(e);return eW(t)>n?t:e}function eW(e){let t=(e.type??"").toLowerCase(),n=0;return eZ(t,eH)?n+=100:t.includes("image")?n+=30:t.includes("textview")||"text"===t?n+=20:t.includes("view")&&(n+=10),!0===e.hittable&&(n+=20),!1!==e.enabled&&(n+=5),n}function eZ(e,t){return t.some(t=>e.includes(t))}function eX(e){process.stdout.write(`${JSON.stringify(e,null,2)}
434
436
  `)}function eY(e,t={}){let n=e instanceof K?H(e):e;process.stderr.write(`Error (${n.code}): ${n.message}
435
437
  `),n.hint&&process.stderr.write(`Hint: ${n.hint}
436
438
  `),n.diagnosticId&&process.stderr.write(`Diagnostic ID: ${n.diagnosticId}
@@ -443,13 +445,13 @@ ${e.summaryLines.join("\n")}`:""}function e0(e){return`x=${e.x},y=${e.y},w=${e.w
443
445
  ${w}
444
446
 
445
447
  Waiting for approval for 10 minutes...
446
- `);let y=await tL({cloudBaseUrl:l,deviceCode:c.deviceCode,expiresIn:c.expiresIn,interval:c.interval,fetchImpl:t.io?.fetch,now:t.io?.now}),b=y.cliSession?.refreshCredential??y.cliSession?.refreshToken;if(!tV(y.accessToken)||!tV(b))throw new K("UNAUTHORIZED","Device authorization did not return CLI credentials.");let I=new Date(t.io?.now?.()??Date.now()).toISOString(),x={version:1,id:y.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:l,workspaceId:y.cliSession?.workspaceId,accountId:y.cliSession?.accountId,name:y.cliSession?.name,refreshCredential:b,createdAt:I,expiresAt:y.cliSession?.expiresAt};return function(t){let n=tE(t.stateDir);o.mkdirSync(e.dirname(n),{recursive:!0,mode:448}),o.writeFileSync(n,`${JSON.stringify(t.session,null,2)}
447
- `,{mode:384});try{o.chmodSync(n,384)}catch{}}({stateDir:t.stateDir,session:x}),{accessToken:y.accessToken,expiresAt:y.expiresAt,session:x}}function t_(e){let t=tE(e.stateDir);if(!o.existsSync(t))return null;try{let e=JSON.parse(o.readFileSync(t,"utf8"));if(1!==e.version||!tV(e.id)||!tV(e.cloudBaseUrl)||!tV(e.refreshCredential)||!tV(e.createdAt))return null;return e}catch{return null}}function tE(t){return e.join(t,"auth","cli-session.json")}async function tP(e){let t=t_({stateDir:e.stateDir});return!t||tG(t.expiresAt,e.io?.now)?null:{accessToken:(await tO({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:tB(e.env,t.cloudBaseUrl)}}async function tO(e){let t=tB(e.env,e.session.cloudBaseUrl),n=await tT({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(tV(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};if("revoked"===n.status||"revoked"===n.error)throw new K("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error});throw new K("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error})}async function tL(e){let t=e.now??Date.now,n=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+n,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tT({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tV(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 K("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tH(r)}throw new K("TIMEOUT","Device authorization expired before approval.")}async function tT(e){let t=e.fetchImpl??fetch,n=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 n.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new K("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${n.status}).`,{status:n.status},e instanceof Error?e:void 0)}if(!n.ok)throw new K("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:n.status,response:r});return r}function tM(e,t){let n=tB(t);return new K("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",n).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tB(e,t){let n=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(n).toString().replace(/\/+$/,"")}catch(e){throw new K("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:n},e instanceof Error?e:void 0)}}async function tj(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let n=process.platform;try{"darwin"===n?await en("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===n?await en("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await en("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tF(t,`Open this URL on your machine:
448
+ `);let y=await tO({cloudBaseUrl:l,deviceCode:c.deviceCode,expiresIn:c.expiresIn,interval:c.interval,fetchImpl:t.io?.fetch,now:t.io?.now}),b=y.cliSession?.refreshCredential??y.cliSession?.refreshToken;if(!tV(y.accessToken)||!tV(b))throw new K("UNAUTHORIZED","Device authorization did not return CLI credentials.");let I=new Date(t.io?.now?.()??Date.now()).toISOString(),x={version:1,id:y.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:l,workspaceId:y.cliSession?.workspaceId,accountId:y.cliSession?.accountId,name:y.cliSession?.name,refreshCredential:b,createdAt:I,expiresAt:y.cliSession?.expiresAt};return function(t){let n=tE(t.stateDir);o.mkdirSync(e.dirname(n),{recursive:!0,mode:448}),o.writeFileSync(n,`${JSON.stringify(t.session,null,2)}
449
+ `,{mode:384});try{o.chmodSync(n,384)}catch{}}({stateDir:t.stateDir,session:x}),{accessToken:y.accessToken,expiresAt:y.expiresAt,session:x}}function t_(e){let t=tE(e.stateDir);if(!o.existsSync(t))return null;try{let e=JSON.parse(o.readFileSync(t,"utf8"));if(1!==e.version||!tV(e.id)||!tV(e.cloudBaseUrl)||!tV(e.refreshCredential)||!tV(e.createdAt))return null;return e}catch{return null}}function tE(t){return e.join(t,"auth","cli-session.json")}async function tP(e){let t=t_({stateDir:e.stateDir});return!t||tG(t.expiresAt,e.io?.now)?null:{accessToken:(await tL({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:tB(e.env,t.cloudBaseUrl)}}async function tL(e){let t=tB(e.env,e.session.cloudBaseUrl),n=await tT({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(tV(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};if("revoked"===n.status||"revoked"===n.error)throw new K("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error});throw new K("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error})}async function tO(e){let t=e.now??Date.now,n=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+n,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tT({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tV(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 K("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tH(r)}throw new K("TIMEOUT","Device authorization expired before approval.")}async function tT(e){let t=e.fetchImpl??fetch,n=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 n.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new K("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${n.status}).`,{status:n.status},e instanceof Error?e:void 0)}if(!n.ok)throw new K("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:n.status,response:r});return r}function tM(e,t){let n=tB(t);return new K("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",n).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tB(e,t){let n=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(n).toString().replace(/\/+$/,"")}catch(e){throw new K("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:n},e instanceof Error?e:void 0)}}async function tj(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let n=process.platform;try{"darwin"===n?await en("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===n?await en("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await en("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tF(t,`Open this URL on your machine:
448
450
  ${e}
449
451
  `)}}function tF(e,t){(e?.stderr??process.stderr).write(t)}function tG(e,t){if(!e)return!1;let n=Date.parse(e);return!Number.isFinite(n)||n<=(t?.()??Date.now())}function tV(e){return"string"==typeof e&&e.trim().length>0}async function tH(e){await new Promise(t=>setTimeout(t,e))}async function tK(t){let n=await tR({stateDir:t.stateDir,flags:t.flags,env:t.env,io:{env:t.env,fetch:t.fetchImpl}}),s=await tq({cloudBaseUrl:n.cloudBaseUrl,accessToken:n.accessToken,fetchImpl:t.fetchImpl}),a=function(e){try{return M(e)}catch(n){let t=V(n);throw new K("COMMAND_FAILED","Cloud connection profile returned invalid remote config.",{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(t){var n;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,n])=>[t,e(n)])):t}(t.profile),a=e.join(t.stateDir,"remote-connections","generated");o.mkdirSync(a,{recursive:!0,mode:448});let i=e.join(a,`cloud-${(n=s,r.createHash("sha256").update(JSON.stringify(n)).digest("hex").slice(0,16))}.json`);o.writeFileSync(i,`${JSON.stringify(s,null,2)}
450
452
  `,{mode:384});try{o.chmodSync(i,384)}catch{}return i}({stateDir:t.stateDir,profile:s}),cwd:t.cwd,env:t.env});return{flags:{...th(a.profile),...t.flags,remoteConfig:a.resolvedPath,daemonAuthToken:n.accessToken},remoteConfigPath:a.resolvedPath}}async function tq(e){let t=e.fetchImpl??fetch,n=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)}),o=await n.text(),r={};if(o.trim())try{r=JSON.parse(o)}catch(e){throw new K("COMMAND_FAILED",`Cloud connection profile endpoint returned invalid JSON (${n.status}).`,{status:n.status},e instanceof Error?e:void 0)}if(!n.ok)throw new K("UNAUTHORIZED","Cloud connection profile endpoint rejected the request.",{status:n.status,response:r});var s=r;if(!s||"object"!=typeof s||Array.isArray(s))throw new K("COMMAND_FAILED","Cloud connection profile response is invalid.");let a=s.connection;if(!a||"object"!=typeof a)throw new K("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 K("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(i).length)throw new K("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return i}throw new K("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}function tz(e,t,n){var o;if(e.json)return void eX({success:!0,data:t});let r=n?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
451
- `))}let tJ=async({flags:e,client:t})=>{var n,o,s,a;let i=y(e.stateDir).baseDir,l=e.remoteConfig?function(e){if(!e.remoteConfig)throw new K("INVALID_ARGS","connect requires --remote-config <path>.");let t=M({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tK({flags:e,stateDir:i,cwd:process.cwd(),env:process.env}),c=l.flags,d=c.tenant,u=c.runId;if(!d)throw new K("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!u)throw new K("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!c.daemonBaseUrl)throw new K("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let p=c.session?null:td({stateDir:i}),f=c.session??p?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${r.randomBytes(3).toString("hex")}`;if(!to({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${r.randomBytes(2).toString("hex")}`}(i),m=ti(l.remoteConfigPath),h=ts(c),g=p?.session===f?p:to({stateDir:i,session:f});if(g&&(n=g,o={flags:c,session:f,remoteConfigPath:l.remoteConfigPath,remoteConfigHash:m,desiredLeaseBackend:tA(c),daemon:h},n.remoteConfigPath!==o.remoteConfigPath||n.remoteConfigHash!==o.remoteConfigHash||n.session!==o.session||n.tenant!==o.flags.tenant||n.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&n.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&n.platform!==o.flags.platform||void 0!==o.flags.target&&n.target!==o.flags.target||(s=n.daemon,a=o.daemon,(s?.baseUrl??void 0)!==(a?.baseUrl??void 0)||(s?.transport??void 0)!==(a?.transport??void 0)||(s?.serverMode??void 0)!==(a?.serverMode??void 0)))&&!c.force)throw new K("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:f,remoteConfig:g.remoteConfigPath});let v=new Date().toISOString(),w={version:1,session:f,remoteConfigPath:l.remoteConfigPath,remoteConfigHash:m,daemon:h,tenant:d,runId:u,leaseId:g&&!c.force?g.leaseId:void 0,leaseBackend:g&&!c.force?g.leaseBackend:tA(c),platform:c.platform??(g&&!c.force?g.platform:void 0),target:c.target??(g&&!c.force?g.target:void 0),runtime:g&&!c.force?g.runtime:void 0,metro:g&&!c.force?g.metro:void 0,connectedAt:g&&!c.force?g.connectedAt:v,updatedAt:v};tr({stateDir:i,state:w}),g&&c.force&&(await tb(g.metro),await tI({stateDir:i,state:g}),await tx(t,g));let b=tX(w),I=function(e,t){if(!t.runtime&&(t$(e)||tQ(t.remoteConfigPath)))return tY(t.remoteConfigPath)}(c,w);return tz(c,t0(w,I),()=>[`Connected remote session "${f}" tenant "${d}" run "${u}" ${w.leaseId?`lease ${w.leaseId}`:"lease pending"}`,b?.message,I?.message].filter(e=>!!e).join("\n")),!0},tW=async({flags:e,client:t})=>{let n=e.session??"default",o=y(e.stateDir).baseDir,r=to({stateDir:o,session:n})??(e.session?null:td({stateDir:o}));if(!r)return tz(e,{connected:!1,session:n},()=>`No remote connection for "${n}".`),!0;let s=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tb(r.metro),await tI({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 ta({stateDir:o,session:s}),tz(e,{connected:!1,session:s,released:a},()=>`Disconnected remote session "${s}".`),!0},tZ=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new K("INVALID_ARGS","connection accepts only: status");let n=t.session??"default",o=y(t.stateDir).baseDir,r=to({stateDir:o,session:n})??(t.session?null:td({stateDir:o}));if(!r)return tz(t,{connected:!1,session:n},()=>`No remote connection for "${n}".`),!0;let s=tX(r),a=function(e){if(!e.runtime&&tQ(e.remoteConfigPath))return tY(e.remoteConfigPath)}(r);return tz(t,t0(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",s?.message,a?.message].filter(e=>!!e).join("\n")),!0};function tX(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 tY(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 tQ(e){try{let t=M({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function t0(e,t){let n=tX(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 r.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...n?{leasePreparation:n}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t1=async({positionals:e,flags:t})=>{let n=e[0]??"status",r=y(t.stateDir).baseDir;if("status"===n){var s;let e,n=(e=t_({stateDir:(s={stateDir:r}).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:tG(e.expiresAt,s.now)}:{authenticated:!1,source:"none"};return tz(t,n,()=>{var e;return(e=n).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"===n){let e=await tU({stateDir:r,flags:t,commandLabel:"agent-device auth login"});return tz(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"===n){let e,n=(e=tE({stateDir:r}.stateDir),!!o.existsSync(e)&&(o.rmSync(e,{force:!0}),!0));return tz(t,{authenticated:!1,removed:n},()=>n?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new K("INVALID_ARGS","auth accepts only: status, login, logout")};function t2(e){return t8(v(e))}function t3(e){let t=e.ref??"",n=e.x,o=e.y;return t&&"number"==typeof n&&"number"==typeof o?{data:e,text:`Tapped @${t} (${n}, ${o})`}:t8(e)}function t8(e){return{data:e,text:w(e)}}function t5(e){let t=e.kind?` ${e.kind}`:"",n=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${n})${o}`}function t4(e,t,n){"string"==typeof n&&e.push(` ${t}: ${n}`)}function t6(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")||void 0}function t7(e){if(!Array.isArray(e))return;let t=e.filter(e=>"string"==typeof e&&e.length>0);return t.length>0?t.join("\n"):void 0}function t9(e){return e.filter(e=>!!e).join("\n")||void 0}function ne(e,t){return e?`Performance: ${e}`:`Frame health: unavailable - ${t}`}function nt(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function nn(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function no(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function nr(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let n=Math.round(t/1e3);if(n<60)return`${n}s`;let o=Math.floor(n/60),r=n%60;return r>0?`${o}m ${r}s`:`${o}m`}function ns(e){return({result:t})=>e(t)}let na=ns(function(e){return t8(e)}),ni={boot:ns(function(e){let t=e.platform??"unknown",n=e.device??e.id??"unknown";return{data:e,text:`Boot ready: ${n} (${t})`}}),click:ns(t3),press:ns(t3),batch:ns(function(e){let t="number"==typeof e.total?e.total:0,n="number"==typeof e.executed?e.executed:0,o="number"==typeof e.totalDurationMs?e.totalDurationMs:void 0,r=[`Batch completed: ${n}/${t} steps${void 0!==o?` in ${o}ms`:""}`];for(let t of Array.isArray(e.results)?e.results:[]){let e=function(e){let t=nt(e);if(!t)return;let n="number"==typeof t.step?t.step:void 0,o="string"==typeof t.command?t.command:"step",r=!1!==t.ok,s=function(e,t,n){var o;return t?w(nt(e.data))??n:(o=nt(e.error),("string"==typeof o?.message&&o.message.length>0?o.message:null)??n)}(t,r,o),a=void 0!==n?`${n}. `:"- ",i="number"==typeof t.durationMs?t.durationMs:void 0,l=void 0!==i?` (${i}ms)`:"";return`${a}${r?"OK":"FAILED"} ${s}${l}`}(t);e&&r.push(e)}return{data:e,text:r.join("\n")}}),devices:ns(function(e){return{data:{devices:e.map($)},text:e.map(t5).join("\n")}}),apps:({input:e,result:t})=>{var n;return{data:{apps:(n={result:t,appsFilter:e.appsFilter}).result},stderr:"all"===n.appsFilter?"Showing all apps, including system apps.\n":"Showing user-installed apps. Use --all to include system apps.\n",text:n.result.length>0?n.result.join("\n"):"all"===n.appsFilter?"No apps found.":"No user-installed apps found."}},session:ns(function(e){let t={sessions:e.sessions.map(a)};return{data:t,text:JSON.stringify(t,null,2)}}),open:ns(function(e){return t8(h(e))}),close:ns(function(e){return t8(d(e))}),install:ns(t2),reinstall:ns(t2),"install-from-source":ns(function(e){return t8(x(e))}),snapshot:({input:e,result:t})=>{var n;let o;return{data:o=i((n={result:t,raw:e.raw,interactiveOnly:e.interactiveOnly}).result),jsonData:function(e){let{unchanged:t,...n}=e;return n}(o),text:function(e,t={}){var n,o,r,s;let a,i,l,c,d,u=e.nodes,p=Array.isArray(u)?u:[],f="string"==typeof e.backend?e.backend:void 0,m=function(e,t,n){let o;if(n.raw||!((o=e.androidSnapshot)&&"object"==typeof o&&"android-helper"===o.backend))return{nodes:t,filteredCount:0};let r=function(e){var t,n;if(0===e.length)return e;let o=new Set,r=new Map,s=new Map(e.map(e=>[e.index,e]));(function(e,t){for(let n of e)!n.rect||eO(n.rect)||eT(n)||eV(e,n.index,t)})(e,o),function(e,t,n,o){for(let r of e){if(n.has(r.index)||r.rect||eT(r))continue;let s=function(e,t,n){let o=e;for(;"number"==typeof o.parentIndex;){let e=t.get(o.parentIndex);if(!e)break;if(n(e))return e;o=e}return null}(r,t,eB);s&&function(e,t,n){if(!n)return;let o=e.get(t.index)??t;e.set(t.index,{...o,hiddenContentAbove:!0===o.hiddenContentAbove||"above"===n||void 0,hiddenContentBelow:!0===o.hiddenContentBelow||"below"===n||void 0})}(o,s,function(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&eO(t.rect)).map(e=>e.index);return 0===n.length?null:e.index<Math.min(...n)?"above":e.index>Math.max(...n)?"below":null}(r,e)),eV(e,r.index,n)}}(e,s,o,r);for(let n of e){if(o.has(n.index)||!(!0===(t=n).hittable&&!eM(t)&&t.rect&&eO(t.rect)&&0===ej(t).trim().length))continue;let s=function(e,t,n){let o=[],r=[],s=new Set;for(let a of e){if(n.has(a.index)||!eq(a)||!eL(a.rect,t.rect))continue;let e=ej(a).trim().replace(/\s+/g," "),i=eF(e);r.push(a.index),!e||!i||s.has(i)||(s.add(i),o.push(e))}return{label:o.join(", "),removableIndexes:r}}(eG(e,n.index),n,o);if(s.label)for(let t of(r.set(n.index,{...n,...r.get(n.index),label:s.label}),s.removableIndexes))eV(e,t,o)}for(let t of e){if(o.has(t.index)||!(!0===(n=t).hittable&&!eM(n)&&n.rect&&eO(n.rect)&&eF(ej(n))))continue;let r=eF(ej(t));if(!r)continue;let s=eG(e,t.index).filter(e=>!o.has(e.index)&&function(e,t,n){if(!ez(t)||!eL(t.rect,e.rect))return!1;let o=eF(ej(t));return!!(o&&n!==o&&n.includes(o))}(t,e,r));for(let t of s.filter(eq))eV(e,t.index,o);let a=s.filter(e=>!eq(e)),i=new Set(a.map(e=>eF(ej(e))).filter(e=>!!e));if(!(a.length<2)&&!(i.size<2))for(let t of a)eV(e,t.index,o)}let a=new Map;for(let t of e){if(o.has(t.index)||!ez(t))continue;let n=eF(ej(t));if(!n)continue;let s=a.get(n);if(s&&function(e,t,n){var o,r,s,a;return!n.has(e.index)&&(o=e.rect,r=t.rect,!o||!r||Math.abs(o.y+o.height/2-(r.y+r.height/2))<=Math.max(o.height,r.height,1))&&(s=e,a=t,(s.parentIndex===a.parentIndex?3>=Math.abs(s.index-a.index):s.parentIndex!==a.index&&a.parentIndex!==s.index&&1>=Math.abs((s.depth??0)-(a.depth??0))&&2>=Math.abs(s.index-a.index))||function(e,t){let n=e.parentIndex===t.index?t:t.parentIndex===e.index?e:null,o=n?.index===e.index?t:n?.index===t.index?e:null;return!!n&&!!o&&eJ(n,o).index===n.index}(e,t))}(s,t,o)){let i=function(e,t,n,o,r){var s,a,i;let l=eJ(t,n),c=l.index===t.index?n:t,d=(c.type??"").toLowerCase().includes("image")?"has image":null,u=r.get(l.index)??l,p=r.get(c.index)?.presentationHints??c.presentationHints;return r.set(l.index,{...u,presentationHints:(s=u.presentationHints,a=p,i=d,[...new Set([...Array.isArray(s)?s:[],...Array.isArray(a)?a:[],...i?[i]:[]])])}),eV(e,c.index,o),r.get(l.index)??l}(e,s,t,o,r);a.set(n,i);continue}a.set(n,t)}return e.filter(e=>!o.has(e.index)).map(e=>r.get(e.index)??e)}(t);return{nodes:r,filteredCount:t.length-r.length}}(e,p,t),h=(a="string"==typeof(n=e).appName?n.appName:void 0,i="string"==typeof n.appBundleId?n.appBundleId:void 0,l=[],a&&l.push(`Page: ${a}`),i&&l.push(`App: ${i}`),l.length>0?`${l.join("\n")}
452
- `:""),g=function(e,t,n,o={nodes:t,filteredCount:0}){let r=e7(e);!n.raw&&o.filteredCount>0&&r.push(`Collapsed ${o.filteredCount} Android helper node${1===o.filteredCount?"":"s"} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let s=o.filteredCount>0?o.nodes:t;return!n.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??"").toLowerCase(),o=function(e){var t;let n=e.trim().replace(/\s+/g," ").toLowerCase();return!n||(t=n,/\S+@\S+\.\S+/.test(t))?null:n}(P(n));if(!o)continue;let r=`${e}|${o}`,s=t.get(r)??[];s.push(n),t.set(r,s)}let n=0;for(let e of t.values())!(e.length<=1)&&function(e){for(let o=0;o<e.length;o+=1)for(let r=o+1;r<e.length;r+=1){var t,n;if(t=e[o]?.rect,n=e[r]?.rect,!t||!n||!(t.x+t.width<=n.x+.5||n.x+n.width<=t.x+.5||t.y+t.height<=n.y+.5||n.y+n.height<=t.y+.5))return!0}return!1}(e)&&(n+=e.length);return n>=8}(s)&&r.push("Warning: possible repeated nav subtree detected."),r}(e,p,t,m),v=g.length>0?`${g.join("\n")}
453
+ `))}let tJ=async({flags:e,client:t})=>{var n,o,s,a;let i=y(e.stateDir).baseDir,l=e.remoteConfig?function(e){if(!e.remoteConfig)throw new K("INVALID_ARGS","connect requires --remote-config <path>.");let t=M({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tK({flags:e,stateDir:i,cwd:process.cwd(),env:process.env}),c=l.flags,d=c.tenant,u=c.runId;if(!d)throw new K("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!u)throw new K("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!c.daemonBaseUrl)throw new K("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let p=c.session?null:td({stateDir:i}),f=c.session??p?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${r.randomBytes(3).toString("hex")}`;if(!to({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${r.randomBytes(2).toString("hex")}`}(i),m=ti(l.remoteConfigPath),h=ts(c),g=p?.session===f?p:to({stateDir:i,session:f});if(g&&(n=g,o={flags:c,session:f,remoteConfigPath:l.remoteConfigPath,remoteConfigHash:m,desiredLeaseBackend:tA(c),daemon:h},n.remoteConfigPath!==o.remoteConfigPath||n.remoteConfigHash!==o.remoteConfigHash||n.session!==o.session||n.tenant!==o.flags.tenant||n.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&n.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&n.platform!==o.flags.platform||void 0!==o.flags.target&&n.target!==o.flags.target||(s=n.daemon,a=o.daemon,(s?.baseUrl??void 0)!==(a?.baseUrl??void 0)||(s?.transport??void 0)!==(a?.transport??void 0)||(s?.serverMode??void 0)!==(a?.serverMode??void 0)))&&!c.force)throw new K("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:f,remoteConfig:g.remoteConfigPath});let v=new Date().toISOString(),w={version:1,session:f,remoteConfigPath:l.remoteConfigPath,remoteConfigHash:m,daemon:h,tenant:d,runId:u,leaseId:g&&!c.force?g.leaseId:void 0,leaseBackend:g&&!c.force?g.leaseBackend:tA(c),platform:c.platform??(g&&!c.force?g.platform:void 0),target:c.target??(g&&!c.force?g.target:void 0),runtime:g&&!c.force?g.runtime:void 0,metro:g&&!c.force?g.metro:void 0,connectedAt:g&&!c.force?g.connectedAt:v,updatedAt:v};tr({stateDir:i,state:w}),g&&c.force&&(await tb(g.metro),await tI({stateDir:i,state:g}),await tx(t,g));let b=tX(w),I=function(e,t){if(!t.runtime&&(t$(e)||tQ(t.remoteConfigPath)))return tY(t.remoteConfigPath)}(c,w);return tz(c,t0(w,I),()=>[`Connected remote session "${f}" tenant "${d}" run "${u}" ${w.leaseId?`lease ${w.leaseId}`:"lease pending"}`,b?.message,I?.message].filter(e=>!!e).join("\n")),!0},tW=async({flags:e,client:t})=>{let n=e.session??"default",o=y(e.stateDir).baseDir,r=to({stateDir:o,session:n})??(e.session?null:td({stateDir:o}));if(!r)return tz(e,{connected:!1,session:n},()=>`No remote connection for "${n}".`),!0;let s=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tb(r.metro),await tI({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 ta({stateDir:o,session:s}),tz(e,{connected:!1,session:s,released:a},()=>`Disconnected remote session "${s}".`),!0},tZ=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new K("INVALID_ARGS","connection accepts only: status");let n=t.session??"default",o=y(t.stateDir).baseDir,r=to({stateDir:o,session:n})??(t.session?null:td({stateDir:o}));if(!r)return tz(t,{connected:!1,session:n},()=>`No remote connection for "${n}".`),!0;let s=tX(r),a=function(e){if(!e.runtime&&tQ(e.remoteConfigPath))return tY(e.remoteConfigPath)}(r);return tz(t,t0(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",s?.message,a?.message].filter(e=>!!e).join("\n")),!0};function tX(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 tY(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 tQ(e){try{let t=M({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function t0(e,t){let n=tX(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 r.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...n?{leasePreparation:n}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t1=async({positionals:e,flags:t})=>{let n=e[0]??"status",r=y(t.stateDir).baseDir;if("status"===n){var s;let e,n=(e=t_({stateDir:(s={stateDir:r}).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:tG(e.expiresAt,s.now)}:{authenticated:!1,source:"none"};return tz(t,n,()=>{var e;return(e=n).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"===n){let e=await tU({stateDir:r,flags:t,commandLabel:"agent-device auth login"});return tz(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"===n){let e,n=(e=tE({stateDir:r}.stateDir),!!o.existsSync(e)&&(o.rmSync(e,{force:!0}),!0));return tz(t,{authenticated:!1,removed:n},()=>n?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new K("INVALID_ARGS","auth accepts only: status, login, logout")};function t2(e){return t8(v(e))}function t3(e){let t=e.ref??"",n=e.x,o=e.y;return t&&"number"==typeof n&&"number"==typeof o?{data:e,text:`Tapped @${t} (${n}, ${o})`}:t8(e)}function t8(e){return{data:e,text:w(e)}}function t5(e){let t=e.kind?` ${e.kind}`:"",n=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${n})${o}`}function t4(e,t,n){"string"==typeof n&&e.push(` ${t}: ${n}`)}function t6(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")||void 0}function t7(e){if(!Array.isArray(e))return;let t=e.filter(e=>"string"==typeof e&&e.length>0);return t.length>0?t.join("\n"):void 0}function t9(e){return e.filter(e=>!!e).join("\n")||void 0}function ne(e,t){return e?`Performance: ${e}`:`Frame health: unavailable - ${t}`}function nt(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function nn(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function no(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function nr(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let n=Math.round(t/1e3);if(n<60)return`${n}s`;let o=Math.floor(n/60),r=n%60;return r>0?`${o}m ${r}s`:`${o}m`}function ns(e){return({result:t})=>e(t)}let na=ns(function(e){return t8(e)}),ni={boot:ns(function(e){let t=e.platform??"unknown",n=e.device??e.id??"unknown";return{data:e,text:`Boot ready: ${n} (${t})`}}),click:ns(t3),press:ns(t3),batch:ns(function(e){let t="number"==typeof e.total?e.total:0,n="number"==typeof e.executed?e.executed:0,o="number"==typeof e.totalDurationMs?e.totalDurationMs:void 0,r=[`Batch completed: ${n}/${t} steps${void 0!==o?` in ${o}ms`:""}`];for(let t of Array.isArray(e.results)?e.results:[]){let e=function(e){let t=nt(e);if(!t)return;let n="number"==typeof t.step?t.step:void 0,o="string"==typeof t.command?t.command:"step",r=!1!==t.ok,s=function(e,t,n){var o;return t?w(nt(e.data))??n:(o=nt(e.error),("string"==typeof o?.message&&o.message.length>0?o.message:null)??n)}(t,r,o),a=void 0!==n?`${n}. `:"- ",i="number"==typeof t.durationMs?t.durationMs:void 0,l=void 0!==i?` (${i}ms)`:"";return`${a}${r?"OK":"FAILED"} ${s}${l}`}(t);e&&r.push(e)}return{data:e,text:r.join("\n")}}),devices:ns(function(e){return{data:{devices:e.map($)},text:e.map(t5).join("\n")}}),apps:({input:e,result:t})=>{var n;return{data:{apps:(n={result:t,appsFilter:e.appsFilter}).result},stderr:"all"===n.appsFilter?"Showing all apps, including system apps.\n":"Showing user-installed apps. Use --all to include system apps.\n",text:n.result.length>0?n.result.join("\n"):"all"===n.appsFilter?"No apps found.":"No user-installed apps found."}},session:ns(function(e){let t={sessions:e.sessions.map(a)};return{data:t,text:JSON.stringify(t,null,2)}}),open:ns(function(e){return t8(h(e))}),close:ns(function(e){return t8(d(e))}),install:ns(t2),reinstall:ns(t2),"install-from-source":ns(function(e){return t8(x(e))}),snapshot:({input:e,result:t})=>{var n;let o;return{data:o=i((n={result:t,raw:e.raw,interactiveOnly:e.interactiveOnly,scope:e.scope,depth:e.depth}).result),jsonData:function(e){let{unchanged:t,...n}=e;return n}(o),text:function(e,t={}){var n,o,r,s;let a,i,l,c,d,u=e.nodes,p=Array.isArray(u)?u:[],f="string"==typeof e.backend?e.backend:void 0,m=function(e,t,n){let o;if(n.raw||!((o=e.androidSnapshot)&&"object"==typeof o&&"android-helper"===o.backend))return{nodes:t,filteredCount:0};let r=function(e){var t,n;if(0===e.length)return e;let o=new Set,r=new Map,s=new Map(e.map(e=>[e.index,e]));(function(e,t){for(let n of e)!n.rect||eL(n.rect)||eT(n)||eV(e,n.index,t)})(e,o),function(e,t,n,o){for(let r of e){if(n.has(r.index)||r.rect||eT(r))continue;let s=function(e,t,n){let o=e;for(;"number"==typeof o.parentIndex;){let e=t.get(o.parentIndex);if(!e)break;if(n(e))return e;o=e}return null}(r,t,eB);s&&function(e,t,n){if(!n)return;let o=e.get(t.index)??t;e.set(t.index,{...o,hiddenContentAbove:!0===o.hiddenContentAbove||"above"===n||void 0,hiddenContentBelow:!0===o.hiddenContentBelow||"below"===n||void 0})}(o,s,function(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&eL(t.rect)).map(e=>e.index);return 0===n.length?null:e.index<Math.min(...n)?"above":e.index>Math.max(...n)?"below":null}(r,e)),eV(e,r.index,n)}}(e,s,o,r);for(let n of e){if(o.has(n.index)||!(!0===(t=n).hittable&&!eM(t)&&t.rect&&eL(t.rect)&&0===ej(t).trim().length))continue;let s=function(e,t,n){let o=[],r=[],s=new Set;for(let a of e){if(n.has(a.index)||!eq(a)||!eO(a.rect,t.rect))continue;let e=ej(a).trim().replace(/\s+/g," "),i=eF(e);r.push(a.index),!e||!i||s.has(i)||(s.add(i),o.push(e))}return{label:o.join(", "),removableIndexes:r}}(eG(e,n.index),n,o);if(s.label)for(let t of(r.set(n.index,{...n,...r.get(n.index),label:s.label}),s.removableIndexes))eV(e,t,o)}for(let t of e){if(o.has(t.index)||!(!0===(n=t).hittable&&!eM(n)&&n.rect&&eL(n.rect)&&eF(ej(n))))continue;let r=eF(ej(t));if(!r)continue;let s=eG(e,t.index).filter(e=>!o.has(e.index)&&function(e,t,n){if(!ez(t)||!eO(t.rect,e.rect))return!1;let o=eF(ej(t));return!!(o&&n!==o&&n.includes(o))}(t,e,r));for(let t of s.filter(eq))eV(e,t.index,o);let a=s.filter(e=>!eq(e)),i=new Set(a.map(e=>eF(ej(e))).filter(e=>!!e));if(!(a.length<2)&&!(i.size<2))for(let t of a)eV(e,t.index,o)}let a=new Map;for(let t of e){if(o.has(t.index)||!ez(t))continue;let n=eF(ej(t));if(!n)continue;let s=a.get(n);if(s&&function(e,t,n){var o,r,s,a;return!n.has(e.index)&&(o=e.rect,r=t.rect,!o||!r||Math.abs(o.y+o.height/2-(r.y+r.height/2))<=Math.max(o.height,r.height,1))&&(s=e,a=t,(s.parentIndex===a.parentIndex?3>=Math.abs(s.index-a.index):s.parentIndex!==a.index&&a.parentIndex!==s.index&&1>=Math.abs((s.depth??0)-(a.depth??0))&&2>=Math.abs(s.index-a.index))||function(e,t){let n=e.parentIndex===t.index?t:t.parentIndex===e.index?e:null,o=n?.index===e.index?t:n?.index===t.index?e:null;return!!n&&!!o&&eJ(n,o).index===n.index}(e,t))}(s,t,o)){let i=function(e,t,n,o,r){var s,a,i;let l=eJ(t,n),c=l.index===t.index?n:t,d=(c.type??"").toLowerCase().includes("image")?"has image":null,u=r.get(l.index)??l,p=r.get(c.index)?.presentationHints??c.presentationHints;return r.set(l.index,{...u,presentationHints:(s=u.presentationHints,a=p,i=d,[...new Set([...Array.isArray(s)?s:[],...Array.isArray(a)?a:[],...i?[i]:[]])])}),eV(e,c.index,o),r.get(l.index)??l}(e,s,t,o,r);a.set(n,i);continue}a.set(n,t)}return e.filter(e=>!o.has(e.index)).map(e=>r.get(e.index)??e)}(t);return{nodes:r,filteredCount:t.length-r.length}}(e,p,t),h=(a="string"==typeof(n=e).appName?n.appName:void 0,i="string"==typeof n.appBundleId?n.appBundleId:void 0,l=[],a&&l.push(`Page: ${a}`),i&&l.push(`App: ${i}`),l.length>0?`${l.join("\n")}
454
+ `:""),g=function(e,t,n,o={nodes:t,filteredCount:0}){let r=e7(e),s=function(e,t){if(!0===t.scoped||!0===t.depthLimited||e.length>3)return null;let n=1===e.length?"node":"nodes";return`Hint: sparse accessibility snapshot returned ${e.length} ${n}. The app may expose limited accessibility metadata; run screenshot --overlay-refs for visual context.`}(t,n);s&&r.push(s),!n.raw&&o.filteredCount>0&&r.push(`Collapsed ${o.filteredCount} Android helper node${1===o.filteredCount?"":"s"} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let a=o.filteredCount>0?o.nodes:t;return!n.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??"").toLowerCase(),o=function(e){var t;let n=e.trim().replace(/\s+/g," ").toLowerCase();return!n||(t=n,/\S+@\S+\.\S+/.test(t))?null:n}(P(n));if(!o)continue;let r=`${e}|${o}`,s=t.get(r)??[];s.push(n),t.set(r,s)}let n=0;for(let e of t.values())!(e.length<=1)&&function(e){for(let o=0;o<e.length;o+=1)for(let r=o+1;r<e.length;r+=1){var t,n;if(t=e[o]?.rect,n=e[r]?.rect,!t||!n||!(t.x+t.width<=n.x+.5||n.x+n.width<=t.x+.5||t.y+t.height<=n.y+.5||n.y+n.height<=t.y+.5))return!0}return!1}(e)&&(n+=e.length);return n>=8}(a)&&r.push("Warning: possible repeated nav subtree detected."),r}(e,p,t,m),v=g.length>0?`${g.join("\n")}
453
455
  `:"",w=t.raw?null:(c=e.unchanged)&&"object"==typeof c?"number"!=typeof c.ageMs||"number"!=typeof c.nodeCount?null:{ageMs:c.ageMs,nodeCount:c.nodeCount,interactiveOnly:!0===c.interactiveOnly||void 0,scope:"string"==typeof c.scope?c.scope:void 0}:null;if(w){let e;return`${h}${v}${e=function(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(Math.round(e/100)/10).toFixed(1)}s`;let t=e/6e4;return t<60?`${(Math.round(10*t)/10).toFixed(1)}m`:`${(Math.round(t/60*10)/10).toFixed(1)}h`}((o=w).ageMs),o.scope?`Scoped snapshot unchanged for scope "${o.scope}" since previous read ${e} ago.
454
456
  Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`:o.interactiveOnly?`Interactive snapshot unchanged since previous read ${e} ago.
455
457
  ${o.nodeCount} visible nodes are unchanged. Previous @e refs are still valid. Use find/get/is for a targeted query, or --force-full to re-emit.`:`Snapshot unchanged since previous read ${e} ago.
@@ -461,12 +463,12 @@ ${v}${p.map(e=>JSON.stringify(e)).join("\n")}
461
463
  ${v}${T(I,{summarizeTextSurfaces:!0}).flatMap(e=>[C(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...e9({...e,depth:0})]).join("\n")}${eQ(y)}
462
464
  `:`${h}${A}
463
465
  ${v}${(function(e){let t=[],n=[],o=new Map(e.map(e=>[e.node.index,e.node])),r=e=>{for(var r,s,a;n.length>0&&(!e||(r=e,s=n[n.length-1],a=o,!function(e,t,n){let o=e;for(;"number"==typeof o.parentIndex;){if(o.parentIndex===t.index)return!0;let e=n.get(o.parentIndex);if(!e)break;o=e}return!1}(r.node,s.node,a)&&r.depth<=s.depth));)t.push(...e9(n.pop(),"below"))};for(let o of e)r(o),t.push(o.text),t.push(...e9(o,"above")),o.node.hiddenContentBelow&&n.push(o);return r(),t})(T(I,{summarizeTextSurfaces:!0})).join("\n")}${eQ(y)}
464
- `}(o,{raw:n.raw,flatten:n.interactiveOnly})}},wait:na,alert:na,appstate:ns(function(e){return{data:e,text: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}(e)}}),back:na,home:na,rotate:na,"app-switcher":na,keyboard:ns(function(e){if("android"===e.platform&&"status"===e.action){var t;let n=[`Keyboard visible: ${!0===e.visible?"yes":"no"}`,`Input type: ${e.type??e.inputType??"unknown"}`,`Input owner: ${e.inputOwner??"unknown"}`];return e.inputMethodPackage&&n.push(`Input method: ${e.inputMethodPackage}`),e.focusedPackage&&n.push(`Focused package: ${e.focusedPackage}`),e.focusedResourceId&&n.push(`Focused resource: ${e.focusedResourceId}`),n.push(`Next action: ${(t=e.visible,"ime"===e.inputOwner?"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.":!0===t?"Keyboard is visible and focused input appears app-owned; fill/type can proceed.":"Keyboard is hidden; focus an app field before type, or use fill with a concrete target.")}`),{data:e,text:n.join("\n")}}return t8(e)}),clipboard:ns(function(e){return"read"===e.action?{data:e,text:e.text}:t8(e)}),get:({input:e,result:t})=>{var n;let o;return o=(n={result:t,format:e.format}).result,"text"===n.format?{data:o,text:"string"==typeof o.text?o.text:""}:"attrs"===n.format?{data:o,text:JSON.stringify(o.node??{},null,2)}:t8(o)},is:ns(function(e){return{data:e,text:`Passed: is ${e.predicate??"assertion"}`}}),find:ns(function(e){return"string"==typeof e.text?{data:e,text:e.text}:"boolean"==typeof e.found?{data:e,text:`Found: ${e.found}`}:e.node?{data:e,text:JSON.stringify(e.node,null,2)}:t8(e)}),perf:ns(function(e){return{data:e,text:function(e){var t,n,o;let r,s=nt(e.metrics),a=nt(s?.fps),i=(t=s,(r=[function(e){if(e?.available!==!0)return;let t=nn(e.usagePercent);return void 0!==t?`CPU ${no(t)}`:void 0}(nt(t?.cpu)),function(e){let t;if(e?.available!==!0)return;let n=nn(e.residentMemoryKb)??nn(e.totalPssKb)??nn(e.totalRssKb);return void 0!==n?`memory ${t=n/1024,`${t>=10?Math.round(t):t.toFixed(1)}MB`}`:void 0}(nt(t?.memory))].filter(e=>!!e)).length>0?r.join(", "):void 0);if(!a)return ne(i,"missing frame metric");if(!1===a.available){return ne(i,"string"==typeof(n=a).reason&&n.reason.length>0?n.reason:"not available")}let l=function(e){let t=nn(e.droppedFramePercent),n=nn(e.droppedFrameCount);if(void 0!==t&&void 0!==n){var o,r,s;return[`dropped ${no(t)}`,(o=n,void 0!==(r=nn(e.totalFrameCount))?`(${Math.round(o)}/${Math.round(r)} frames)`:`(${Math.round(o)} dropped frames)`),void 0!==(s=nn(e.sampleWindowMs))?`window ${nr(s)}`:""].filter(Boolean).join(" ")}}(a);if(!l)return ne(i,"missing dropped-frame summary");let c=[`Frame health: ${l}`],d=(Array.isArray(o=a.worstWindows)?o.filter(e=>!!e&&"object"==typeof e&&!Array.isArray(e)):[]).flatMap(e=>{let t=function(e){let t=nn(e.startOffsetMs),n=nn(e.endOffsetMs),o=nn(e.missedDeadlineFrameCount);if(void 0===t||void 0===n||void 0===o)return;let r=nn(e.worstFrameMs),s=void 0===r?"":`, worst ${nr(r)}`;return`- +${nr(t)}-+${nr(n)}: ${Math.round(o)} missed-deadline frames${s}`}(e);return t?[t]:[]});return d.length>0&&c.push("Worst windows:",...d),c.join("\n")}(e)}}),logs:ns(function(e){var t;return{data:e,text:"string"==typeof e.path?e.path:"",stderr:t9([t6(e,["active","state","backend","sizeBytes"]),(t=e,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(e=>{var n,o;return n=e,!0===(o=t[e])?`${n}=true`:"number"==typeof o?`${n}=${o}`:""}).filter(Boolean).join(" ")||void 0),"string"==typeof e.hint?e.hint:void 0,t7(e.notes)])}}),network:ns(function(e){let t=[],n="string"==typeof e.path?e.path:"";n&&t.push(n);let o=Array.isArray(e.entries)?e.entries:[];if(0===o.length)t.push("No recent HTTP(s) entries found.");else for(let e of o)t.push(...function(e){let t=nt(e)??{},n="string"==typeof t.method?t.method:"HTTP",o="string"==typeof t.url?t.url:"<unknown-url>",r="number"==typeof t.status?` status=${t.status}`:"",s="string"==typeof t.timestamp?`${t.timestamp} `:"",a="number"==typeof t.durationMs?` durationMs=${t.durationMs}`:"",i=[`${s}${n} ${o}${r}${a}`];return t4(i,"headers",t.headers),t4(i,"request",t.requestBody),t4(i,"response",t.responseBody),i}(e));return{data:e,text:t.join("\n"),stderr:t9([t6(e,["active","state","backend","include","scannedLines","matchedLines"]),t7(e.notes)])}}),record:ns(function(e){return{data:e,text:"string"==typeof e.outPath?e.outPath:""}}),metro:({input:e,result:t})=>{var n;return{data:(n={result:t,action:e.action}).result,text:"reload"===n.action?`Reloaded React Native apps via ${n.result.reloadUrl}`:JSON.stringify(n.result,null,2)}}},nl={...b,...m,...s,...l,...A,...c,...g,...k,metro:function(e,t){let n=(e[0]??"").toLowerCase();if("prepare"!==n&&"reload"!==n)throw new K("INVALID_ARGS","metro requires a subcommand: prepare or reload");if("reload"===n)return{action:n,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs};if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new K("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");return{action:n,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}},batch:(e,t)=>({...I(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})};async function nc(e){return(await nd(e)).result}async function nd(e){var t,n,o,r;let s=(t=e.command,n=e.positionals,o=e.flags,nl[t](n,o)),a=await es(e.client,e.command,s);return{result:a,cliOutput:(r={name:e.command,input:s,result:a},ni[r.name]?.({input:r.input??{},result:r.result}))}}let nu=async({positionals:e,flags:t,client:n})=>{let o=await nc({client:n,command:"screenshot",positionals:e,flags:t});return tz(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},np=async({positionals:e,flags:n,client:o})=>{var r;if("snapshot"===e[0]){let r=await nc({client:o,command:"diff",positionals:e,flags:n});return tz(n,r,()=>(function(e){var n;let o=!0===e.baselineInitialized,r=e.summary??{},s=e5(r.additions),a=e5(r.removals),i=e5(r.unchanged),l=e4(),c=e7(e),d=c.length>0?`${c.join("\n")}
466
+ `}(o,{raw:n.raw,flatten:n.interactiveOnly,scoped:"string"==typeof n.scope&&n.scope.trim().length>0,depthLimited:"number"==typeof n.depth})}},wait:na,alert:na,appstate:ns(function(e){return{data:e,text: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}(e)}}),back:na,home:na,rotate:na,"app-switcher":na,keyboard:ns(function(e){if("android"===e.platform&&"status"===e.action){var t;let n=[`Keyboard visible: ${!0===e.visible?"yes":"no"}`,`Input type: ${e.type??e.inputType??"unknown"}`,`Input owner: ${e.inputOwner??"unknown"}`];return e.inputMethodPackage&&n.push(`Input method: ${e.inputMethodPackage}`),e.focusedPackage&&n.push(`Focused package: ${e.focusedPackage}`),e.focusedResourceId&&n.push(`Focused resource: ${e.focusedResourceId}`),n.push(`Next action: ${(t=e.visible,"ime"===e.inputOwner?"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.":!0===t?"Keyboard is visible and focused input appears app-owned; fill/type can proceed.":"Keyboard is hidden; focus an app field before type, or use fill with a concrete target.")}`),{data:e,text:n.join("\n")}}return t8(e)}),clipboard:ns(function(e){return"read"===e.action?{data:e,text:e.text}:t8(e)}),get:({input:e,result:t})=>{var n;let o;return o=(n={result:t,format:e.format}).result,"text"===n.format?{data:o,text:"string"==typeof o.text?o.text:""}:"attrs"===n.format?{data:o,text:JSON.stringify(o.node??{},null,2)}:t8(o)},is:ns(function(e){return{data:e,text:`Passed: is ${e.predicate??"assertion"}`}}),find:ns(function(e){return"string"==typeof e.text?{data:e,text:e.text}:"boolean"==typeof e.found?{data:e,text:`Found: ${e.found}`}:e.node?{data:e,text:JSON.stringify(e.node,null,2)}:t8(e)}),perf:ns(function(e){return{data:e,text:function(e){var t,n,o;let r,s=nt(e.metrics),a=nt(s?.fps),i=(t=s,(r=[function(e){if(e?.available!==!0)return;let t=nn(e.usagePercent);return void 0!==t?`CPU ${no(t)}`:void 0}(nt(t?.cpu)),function(e){let t;if(e?.available!==!0)return;let n=nn(e.residentMemoryKb)??nn(e.totalPssKb)??nn(e.totalRssKb);return void 0!==n?`memory ${t=n/1024,`${t>=10?Math.round(t):t.toFixed(1)}MB`}`:void 0}(nt(t?.memory))].filter(e=>!!e)).length>0?r.join(", "):void 0);if(!a)return ne(i,"missing frame metric");if(!1===a.available){return ne(i,"string"==typeof(n=a).reason&&n.reason.length>0?n.reason:"not available")}let l=function(e){let t=nn(e.droppedFramePercent),n=nn(e.droppedFrameCount);if(void 0!==t&&void 0!==n){var o,r,s;return[`dropped ${no(t)}`,(o=n,void 0!==(r=nn(e.totalFrameCount))?`(${Math.round(o)}/${Math.round(r)} frames)`:`(${Math.round(o)} dropped frames)`),void 0!==(s=nn(e.sampleWindowMs))?`window ${nr(s)}`:""].filter(Boolean).join(" ")}}(a);if(!l)return ne(i,"missing dropped-frame summary");let c=[`Frame health: ${l}`],d=(Array.isArray(o=a.worstWindows)?o.filter(e=>!!e&&"object"==typeof e&&!Array.isArray(e)):[]).flatMap(e=>{let t=function(e){let t=nn(e.startOffsetMs),n=nn(e.endOffsetMs),o=nn(e.missedDeadlineFrameCount);if(void 0===t||void 0===n||void 0===o)return;let r=nn(e.worstFrameMs),s=void 0===r?"":`, worst ${nr(r)}`;return`- +${nr(t)}-+${nr(n)}: ${Math.round(o)} missed-deadline frames${s}`}(e);return t?[t]:[]});return d.length>0&&c.push("Worst windows:",...d),c.join("\n")}(e)}}),logs:ns(function(e){var t;return{data:e,text:"string"==typeof e.path?e.path:"",stderr:t9([t6(e,["active","state","backend","sizeBytes"]),(t=e,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(e=>{var n,o;return n=e,!0===(o=t[e])?`${n}=true`:"number"==typeof o?`${n}=${o}`:""}).filter(Boolean).join(" ")||void 0),"string"==typeof e.hint?e.hint:void 0,t7(e.notes)])}}),network:ns(function(e){let t=[],n="string"==typeof e.path?e.path:"";n&&t.push(n);let o=Array.isArray(e.entries)?e.entries:[];if(0===o.length)t.push("No recent HTTP(s) entries found.");else for(let e of o)t.push(...function(e){let t=nt(e)??{},n="string"==typeof t.method?t.method:"HTTP",o="string"==typeof t.url?t.url:"<unknown-url>",r="number"==typeof t.status?` status=${t.status}`:"",s="string"==typeof t.timestamp?`${t.timestamp} `:"",a="number"==typeof t.durationMs?` durationMs=${t.durationMs}`:"",i=[`${s}${n} ${o}${r}${a}`];return t4(i,"headers",t.headers),t4(i,"request",t.requestBody),t4(i,"response",t.responseBody),i}(e));return{data:e,text:t.join("\n"),stderr:t9([t6(e,["active","state","backend","include","scannedLines","matchedLines"]),t7(e.notes)])}}),record:ns(function(e){return{data:e,text:"string"==typeof e.outPath?e.outPath:""}}),metro:({input:e,result:t})=>{var n;return{data:(n={result:t,action:e.action}).result,text:"reload"===n.action?`Reloaded React Native apps via ${n.result.reloadUrl}`:JSON.stringify(n.result,null,2)}}},nl={...b,...m,...s,...l,...A,...c,...g,...k,metro:function(e,t){let n=(e[0]??"").toLowerCase();if("prepare"!==n&&"reload"!==n)throw new K("INVALID_ARGS","metro requires a subcommand: prepare or reload");if("reload"===n)return{action:n,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs};if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new K("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");return{action:n,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}},batch:(e,t)=>({...I(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})};async function nc(e){return(await nd(e)).result}async function nd(e){var t,n,o,r;let s=(t=e.command,n=e.positionals,o=e.flags,nl[t](n,o)),a=await es(e.client,e.command,s);return{result:a,cliOutput:(r={name:e.command,input:s,result:a},ni[r.name]?.({input:r.input??{},result:r.result}))}}let nu=async({positionals:e,flags:t,client:n})=>{let o=await nc({client:n,command:"screenshot",positionals:e,flags:t});return tz(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},np=async({positionals:e,flags:n,client:o})=>{var r;if("snapshot"===e[0]){let r=await nc({client:o,command:"diff",positionals:e,flags:n});return tz(n,r,()=>(function(e){var n;let o=!0===e.baselineInitialized,r=e.summary??{},s=e5(r.additions),a=e5(r.removals),i=e5(r.unchanged),l=e4(),c=e7(e),d=c.length>0?`${c.join("\n")}
465
467
  `:"";if(o)return`${d}Baseline initialized (${i} lines).
466
468
  `;let u=(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 n=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)n[e]=!0}return e.filter((e,t)=>n[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let n="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=n.startsWith(" ")?`+${n}`:`+ ${n}`;return l?t("green",e):e}if("removed"===e.kind){let e=n.startsWith(" ")?`-${n}`:`- ${n}`;return l?t("red",e):e}return l?t("dim",n):n}),p=u.length>0?`${u.join("\n")}
467
469
  `:"";if(!l)return`${d}${p}${s} additions, ${a} removals, ${i} unchanged
468
470
  `;let f=`${(n=String(s),t("green",n))} additions, ${t("red",String(a))} removals, ${t("dim",String(i))} unchanged`;return`${d}${p}${f}
469
- `})(r)),!0}if("screenshot"!==e[0])return!1;let s=n.baseline;if(!s||"string"!=typeof s)throw new K("INVALID_ARGS","diff screenshot requires --baseline <path>");let a=ea(s),i="string"==typeof n.out?ea(n.out):void 0,l=e[1];if(e.length>2)throw new K("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let c=R({backend:(r=o,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(n),captureScreenshot:async(e,t,n)=>{let o=await r.capture.screenshot({path:t,session:e.session,overlayRefs:n?.overlayRefs,fullscreen:n?.fullscreen,stabilize:n?.stabilize,surface:n?.surface});return{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}}}}),artifacts:el(),sessions:{get:e=>({name:e}),set:()=>{}},policy:O()}),d=await c.capture.diffScreenshot({session:n.session,baseline:{kind:"path",path:a},current:l?{kind:"path",path:ea(l)}:{kind:"live"},...i?{out:{kind:"path",path:i}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(n.threshold),overlayRefs:n.overlayRefs,surface:n.surface});return tz(n,d,()=>{var e,n,o,r;let s,a,i,l,c,u,p,f;return s=e4(),a=!0===d.match,i=d.dimensionMismatch,(l=[]).push(...function(e,n){if(!0===e.match){let e=n?t("green","✓"):"✓";return[`${e} Screenshots match.`]}let o=e.dimensionMismatch,r=n?t("red","✗"):"✗";if(o){let e=o.expected,t=o.actual;return[`${r} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let s=e5(e.differentPixels),a=e5(e.mismatchPercentage),i=0===a&&s>0?"<0.01":String(a),l=`${i}% pixels differ`;return[`${r} ${n?t("red",l):l}`]}(d,s)),l.push(...function(e,n,o){if(n)return[];let r=[];if(e.diffPath){let n=e8(e.diffPath),s=o?t("dim","Diff image:"):"Diff image:",a=o?t("green",n):n;r.push(` ${s} ${a}`)}if(e.currentOverlayPath){let n=e8(e.currentOverlayPath),s=o?t("dim","Current overlay:"):"Current overlay:",a=o?t("green",n):n,i=e5(e.currentOverlayRefCount),l=i>0?` (${i} refs)`:"";r.push(` ${s} ${a}${l}`)}return r}(d,a,s)),a||i||(l.push(...(e=d,n=s,c=e5(e.differentPixels),u=e5(e.totalPixels),p=n?t("red",String(c)):String(c),[` ${p} different / ${u} total pixels`])),l.push(...(o=d,r=s,0===(f=function(e){let t=[];for(let n 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)),n=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${n}`}(n.texts)} dx=${e3(n.xRange)}px dy=${e3(n.yRange)}px`);let n=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);n.length>0&&t.push(`non-text controls: ${n.map(e2).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(e2).join("; ")}`),t.slice(0,6)}(o)).length?[]:[` ${e6("Hints:",r)}`,...f.map(e=>` - ${e}`)])),l.push(...function(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(0===n.length)return[];let o=[` ${e6("Changed regions:",t)}`];for(let e of n.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),n=e.rect,o=[` ${e.index}. ${e.location} x=${n.x} y=${n.y} ${n.width}x${n.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 s=e.currentOverlayMatches?.[0];if(s){let e=s.label?` "${s.label}"`:"";o.push(` overlaps @${s.ref}${e}, ${s.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,s)),l.push(...function(e,t){let n=e.ocr?.matches??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let n=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${e1(n.x)},${e1(n.y)} | ${e1(n.width)},${e1(n.height)} | ${e0(t.baselineRect)} | ${e0(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,s)),l.push(...function(e,t){let n=e.nonTextDeltas??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`Non-text visual deltas (showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("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} | ${e0(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,s))),`${l.join("\n")}
471
+ `})(r)),!0}if("screenshot"!==e[0])return!1;let s=n.baseline;if(!s||"string"!=typeof s)throw new K("INVALID_ARGS","diff screenshot requires --baseline <path>");let a=ea(s),i="string"==typeof n.out?ea(n.out):void 0,l=e[1];if(e.length>2)throw new K("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let c=R({backend:(r=o,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(n),captureScreenshot:async(e,t,n)=>{let o=await r.capture.screenshot({path:t,session:e.session,overlayRefs:n?.overlayRefs,fullscreen:n?.fullscreen,stabilize:n?.stabilize,surface:n?.surface});return{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}}}}),artifacts:el(),sessions:{get:e=>({name:e}),set:()=>{}},policy:L()}),d=await c.capture.diffScreenshot({session:n.session,baseline:{kind:"path",path:a},current:l?{kind:"path",path:ea(l)}:{kind:"live"},...i?{out:{kind:"path",path:i}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(n.threshold),overlayRefs:n.overlayRefs,surface:n.surface});return tz(n,d,()=>{var e,n,o,r;let s,a,i,l,c,u,p,f;return s=e4(),a=!0===d.match,i=d.dimensionMismatch,(l=[]).push(...function(e,n){if(!0===e.match){let e=n?t("green","✓"):"✓";return[`${e} Screenshots match.`]}let o=e.dimensionMismatch,r=n?t("red","✗"):"✗";if(o){let e=o.expected,t=o.actual;return[`${r} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let s=e5(e.differentPixels),a=e5(e.mismatchPercentage),i=0===a&&s>0?"<0.01":String(a),l=`${i}% pixels differ`;return[`${r} ${n?t("red",l):l}`]}(d,s)),l.push(...function(e,n,o){if(n)return[];let r=[];if(e.diffPath){let n=e8(e.diffPath),s=o?t("dim","Diff image:"):"Diff image:",a=o?t("green",n):n;r.push(` ${s} ${a}`)}if(e.currentOverlayPath){let n=e8(e.currentOverlayPath),s=o?t("dim","Current overlay:"):"Current overlay:",a=o?t("green",n):n,i=e5(e.currentOverlayRefCount),l=i>0?` (${i} refs)`:"";r.push(` ${s} ${a}${l}`)}return r}(d,a,s)),a||i||(l.push(...(e=d,n=s,c=e5(e.differentPixels),u=e5(e.totalPixels),p=n?t("red",String(c)):String(c),[` ${p} different / ${u} total pixels`])),l.push(...(o=d,r=s,0===(f=function(e){let t=[];for(let n 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)),n=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${n}`}(n.texts)} dx=${e3(n.xRange)}px dy=${e3(n.yRange)}px`);let n=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);n.length>0&&t.push(`non-text controls: ${n.map(e2).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(e2).join("; ")}`),t.slice(0,6)}(o)).length?[]:[` ${e6("Hints:",r)}`,...f.map(e=>` - ${e}`)])),l.push(...function(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(0===n.length)return[];let o=[` ${e6("Changed regions:",t)}`];for(let e of n.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),n=e.rect,o=[` ${e.index}. ${e.location} x=${n.x} y=${n.y} ${n.width}x${n.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 s=e.currentOverlayMatches?.[0];if(s){let e=s.label?` "${s.label}"`:"";o.push(` overlaps @${s.ref}${e}, ${s.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,s)),l.push(...function(e,t){let n=e.ocr?.matches??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let n=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${e1(n.x)},${e1(n.y)} | ${e1(n.width)},${e1(n.height)} | ${e0(t.baselineRect)} | ${e0(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,s)),l.push(...function(e,t){let n=e.nonTextDeltas??[];if(0===n.length)return[];let o=n.slice(0,8),r=[` ${e6(`Non-text visual deltas (showing ${o.length}/${n.length}; px):`,t)}`,` ${e6("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} | ${e0(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,s))),`${l.join("\n")}
470
472
  `}),!0};function nf(e){var t;let n=e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";for(let r of(process.stdout.write(`FAIL ${e.file}${n}${o}
471
473
  `),process.stdout.write(` ${e.error?.message??"Unknown test failure"}
472
474
  `),t=e,[t.error?.hint?`hint: ${t.error.hint}`:"",t.artifactsDir?`artifacts: ${t.artifactsDir}`:"",t.error?.logPath?`log: ${t.error.logPath}`:"",t.error?.diagnosticId?`diagnostic: ${t.error.diagnosticId}`:""].filter(Boolean)))process.stdout.write(` ${r}
@@ -475,7 +477,7 @@ ${v}${(function(e){let t=[],n=[],o=new Map(e.map(e=>[e.node.index,e.node])),r=e=
475
477
  `),"skipped"===e.status&&process.stdout.write(` ${e.message??"skipped"}
476
478
  `)}(t);else{for(let t of e.failures)nf(t);for(let e of n)!function(e){let t=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FLAKY ${e.file} after ${e.attempts} attempts${t}
477
479
  `)}(e)}let o="number"==typeof e.durationMs?e.durationMs:void 0,r=n.length>0?`, ${n.length} flaky`:"";return process.stdout.write(`Test summary: ${e.passed} passed, ${e.failed} failed${r}${void 0!==o?` in ${o}ms`:""}
478
- `),+(e.failed>0)}(n,{verbose:s})}({suite:c,verbose:l.verbose,json:l.json,reportJunit:l.reportJunit}):(tz(l,c,()=>w(c)),0));return 0!==u&&process.exit(u),!0})]})),nx={connect:tJ,disconnect:tW,connection:tZ,auth:t1,screenshot:nu,diff:np,...nb,...nI};async function nA(e){let t=nx[e.command];if(!t)return!1;let n={...e.flags};return E(e.command,n),await t({...e,flags:n})}function n$(e,t,n){return n||(e.push(t),"")}async function nk(e,t,n){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let n=[],o={serverBaseUrl:n$(n,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:n$(n,"metroBearerToken",e.metroBearerToken),tenantId:n$(n,"tenant",e.tenant),runId:n$(n,"runId",e.runId),leaseId:n$(n,"leaseId",e.leaseId)};if(n.length>0)throw new K("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});return o}(o);if(!r)return n();let s=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 n()}finally{await tn({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await tt({projectRoot:t.cwd??process.cwd(),stateDir:s,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 n()}async function nS(e,t={}){let n=t.cwd??process.cwd(),o=t.env??process.env,r=await nk(e,t,async()=>(await et("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==r&&"wait"===(s=e)[0]&&s.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 nC(e,t={}){let n=nD(t),o={...e};return n.defaultPlatform&&void 0===o.platform&&(o.platform=n.defaultPlatform),o}function nD(e){var t,n,o,r;let s,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 K("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:(n=e.policyOverrides,o=a,r=l,(s=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new K("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(o.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||r?"reject":void 0))}}let nN={sendToDaemon:ed},nR=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nU=new Set(["connect","connection","close","disconnect","metro","session"]);async function n_(t,n=nN){let r=W(),s=f(),a=t.includes("--debug")||t.includes("--verbose")||t.includes("-v"),i=t.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith("--session=")){let e=n.slice(10).trim();return e.length>0?e:null}if("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(t)??process.env.AGENT_DEVICE_SESSION??"default";await Z({session:l,requestId:r,command:t[0],debug:a},async()=>{var l,c,d,p,f,m,h,g,v,w,b,I,x,A,$,k,S;let C,R,U,P,O,T,j;try{let n,r,s,a,i,y,I,x;l={cwd:process.cwd(),env:process.env},n=function(e){let t={json:!1,help:!1,version:!1},n=null,o=[],r=[],s=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(s&&"--"===c){s=!1;continue}if(!s){n?o.push(c):n=eP(c);continue}let d=c.startsWith("--"),u=c.startsWith("-")&&c.length>1;if(!d&&!u){n?o.push(c):n=eP(c);continue}let[p,f]=d?eR(c):[c,void 0],m=N(p);if(a=n,i=m,"react-devtools"===a&&(!i||!eD(i.key,a))){o.push(c);continue}if(!m){if(function(e,t,n){var o;if(o=n,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=_(e);if(!r||r.allowsExtraPositionals)return!0;let s=r.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(n,o,c)){n?o.push(c):n=c;continue}throw new K("INVALID_ARGS",`Unknown flag: ${p}`)}let h=function(e,t,n,o){if(void 0!==e.setValue){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new K("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===o||e_(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=n??o;if(void 0===r||void 0===n&&e_(r))throw new K("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:r,consumeNext:void 0===n}}let s=Number(r);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:Math.floor(s),consumeNext:void 0===n}}(m,p,f,e[l+1]);h.consumeNext&&(l+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:void 0===g?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;r.push({key:m.key,token:p})}return{command:n,positionals:o,flags:t,warnings:[],providedFlags:r}}(t),r=l?.env??process.env,s=l?.cwd??process.cwd(),p=n.command,a=null!==p&&(c={remoteConfig:n.flags.remoteConfig,cwd:s,env:r}).remoteConfig?{...th(M({configPath:c.remoteConfig,cwd:c.cwd,env:c.env}).profile),remoteConfig:c.remoteConfig}:{},I=ep((i=(d={command:n.command,cwd:s,cliFlags:n.flags,env:r}).env??process.env,y=ep({},function(e){let t={};for(let n of e)ep(t,function(e,t){let n,r;if(!o.existsSync(e)){if(t)throw new K("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{n=o.readFileSync(e,"utf8")}catch(t){throw new K("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{r=JSON.parse(n)}catch(t){throw new K("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!r||"object"!=typeof r||Array.isArray(r))throw new K("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[o,r]of Object.entries(e)){if("installSource"===o){n.installSource=u(r,t);continue}let e=eC.get(o);if(!e)throw new K("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new K("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);n[o]=F(eN(e),r,t,o)}return n}(r,`config file ${e}`)}(n.path,n.required));return t}((f=d.cwd,m=d.cliFlags.config,h=i,(x=m??h.AGENT_DEVICE_CONFIG)?[{path:(g=x,v=f,w=h,ea(g,{cwd:v,env:w})),required:!0}]:[{path:(b=h,e.join(ei("~",{env:b}),".agent-device","config.json")),required:!1},{path:e.resolve(f,"agent-device.json"),required:!1}]))),ep(y,function(e,t){var n,o,r;let s={};for(let a of eS.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&&(s[a.key]=(n=t.value,o=`environment variable ${t.name}`,r=t.name,F(eN(a),n,o,r)))}return s}(i,d.command))),a),C={...function(e,t){let n=t?.strictFlags??!0,o=[...e.warnings],r=ep({json:!1,help:!1,version:!1},t?.defaultFlags??{});ep(r,e.flags);let s=e.providedFlags.filter(t=>!eD(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new K("INVALID_ARGS",l);for(let e of(o.push(l),s))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eD(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 K("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),E(e.command,r),"batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new K("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,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(n,{strictFlags:l?.strictFlags,defaultFlags:I}),providedFlags:n.providedFlags}}catch(t){Q({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=H(t,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});i?eX({success:!1,error:e}):eY(e,{showDetails:a}),process.exit(1);return}for(let e of C.warnings)process.stderr.write(`Warning: ${e}
480
+ `),+(e.failed>0)}(n,{verbose:s})}({suite:c,verbose:l.verbose,json:l.json,reportJunit:l.reportJunit}):(tz(l,c,()=>w(c)),0));return 0!==u&&process.exit(u),!0})]})),nx={connect:tJ,disconnect:tW,connection:tZ,auth:t1,screenshot:nu,diff:np,...nb,...nI};async function nA(e){let t=nx[e.command];if(!t)return!1;let n={...e.flags};return E(e.command,n),await t({...e,flags:n})}function n$(e,t,n){return n||(e.push(t),"")}async function nk(e,t,n){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let n=[],o={serverBaseUrl:n$(n,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:n$(n,"metroBearerToken",e.metroBearerToken),tenantId:n$(n,"tenant",e.tenant),runId:n$(n,"runId",e.runId),leaseId:n$(n,"leaseId",e.leaseId)};if(n.length>0)throw new K("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});return o}(o);if(!r)return n();let s=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 n()}finally{await tn({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await tt({projectRoot:t.cwd??process.cwd(),stateDir:s,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 n()}async function nS(e,t={}){let n=t.cwd??process.cwd(),o=t.env??process.env,r=await nk(e,t,async()=>(await et("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==r&&"wait"===(s=e)[0]&&s.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 nC(e,t={}){let n=nD(t),o={...e};return n.defaultPlatform&&void 0===o.platform&&(o.platform=n.defaultPlatform),o}function nD(e){var t,n,o,r;let s,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 K("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:(n=e.policyOverrides,o=a,r=l,(s=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new K("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(o.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||r?"reject":void 0))}}let nN={sendToDaemon:ed},nR=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nU=new Set(["connect","connection","close","disconnect","metro","session"]);async function n_(t,n=nN){let r=W(),s=f(),a=t.includes("--debug")||t.includes("--verbose")||t.includes("-v"),i=t.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith("--session=")){let e=n.slice(10).trim();return e.length>0?e:null}if("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(t)??process.env.AGENT_DEVICE_SESSION??"default";await Z({session:l,requestId:r,command:t[0],debug:a},async()=>{var l,c,d,p,f,m,h,g,v,w,b,I,x,A,$,k,S;let C,R,U,P,L,T,j;try{let n,r,s,a,i,y,I,x;l={cwd:process.cwd(),env:process.env},n=function(e){let t={json:!1,help:!1,version:!1},n=null,o=[],r=[],s=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(s&&"--"===c){s=!1;continue}if(!s){n?o.push(c):n=eP(c);continue}let d=c.startsWith("--"),u=c.startsWith("-")&&c.length>1;if(!d&&!u){n?o.push(c):n=eP(c);continue}let[p,f]=d?eR(c):[c,void 0],m=N(p);if(a=n,i=m,"react-devtools"===a&&(!i||!eD(i.key,a))){o.push(c);continue}if(!m){if(function(e,t,n){var o;if(o=n,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=_(e);if(!r||r.allowsExtraPositionals)return!0;let s=r.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(n,o,c)){n?o.push(c):n=c;continue}throw new K("INVALID_ARGS",`Unknown flag: ${p}`)}let h=function(e,t,n,o){if(void 0!==e.setValue){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new K("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new K("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===o||e_(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=n??o;if(void 0===r||void 0===n&&e_(r))throw new K("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:r,consumeNext:void 0===n}}let s=Number(r);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new K("INVALID_ARGS",`Invalid ${eU(t)}: ${r}`);return{value:Math.floor(s),consumeNext:void 0===n}}(m,p,f,e[l+1]);h.consumeNext&&(l+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:void 0===g?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;r.push({key:m.key,token:p})}return{command:n,positionals:o,flags:t,warnings:[],providedFlags:r}}(t),r=l?.env??process.env,s=l?.cwd??process.cwd(),p=n.command,a=null!==p&&(c={remoteConfig:n.flags.remoteConfig,cwd:s,env:r}).remoteConfig?{...th(M({configPath:c.remoteConfig,cwd:c.cwd,env:c.env}).profile),remoteConfig:c.remoteConfig}:{},I=ep((i=(d={command:n.command,cwd:s,cliFlags:n.flags,env:r}).env??process.env,y=ep({},function(e){let t={};for(let n of e)ep(t,function(e,t){let n,r;if(!o.existsSync(e)){if(t)throw new K("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{n=o.readFileSync(e,"utf8")}catch(t){throw new K("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{r=JSON.parse(n)}catch(t){throw new K("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!r||"object"!=typeof r||Array.isArray(r))throw new K("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[o,r]of Object.entries(e)){if("installSource"===o){n.installSource=u(r,t);continue}let e=eC.get(o);if(!e)throw new K("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new K("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);n[o]=F(eN(e),r,t,o)}return n}(r,`config file ${e}`)}(n.path,n.required));return t}((f=d.cwd,m=d.cliFlags.config,h=i,(x=m??h.AGENT_DEVICE_CONFIG)?[{path:(g=x,v=f,w=h,ea(g,{cwd:v,env:w})),required:!0}]:[{path:(b=h,e.join(ei("~",{env:b}),".agent-device","config.json")),required:!1},{path:e.resolve(f,"agent-device.json"),required:!1}]))),ep(y,function(e,t){var n,o,r;let s={};for(let a of eS.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&&(s[a.key]=(n=t.value,o=`environment variable ${t.name}`,r=t.name,F(eN(a),n,o,r)))}return s}(i,d.command))),a),C={...function(e,t){let n=t?.strictFlags??!0,o=[...e.warnings],r=ep({json:!1,help:!1,version:!1},t?.defaultFlags??{});ep(r,e.flags);let s=e.providedFlags.filter(t=>!eD(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new K("INVALID_ARGS",l);for(let e of(o.push(l),s))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eD(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 K("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),E(e.command,r),"batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new K("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,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(n,{strictFlags:l?.strictFlags,defaultFlags:I}),providedFlags:n.providedFlags}}catch(t){Q({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=H(t,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});i?eX({success:!1,error:e}):eY(e,{showDetails:a}),process.exit(1);return}for(let e of C.warnings)process.stderr.write(`Warning: ${e}
479
481
  `);C.flags.version&&(process.stdout.write(`${s}
480
482
  `),process.exit(0));let G="help"===C.command,q=C.flags.help;if(G||q){G&&C.positionals.length>1&&(eY(new K("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=G?C.positionals[0]:C.command;e||(process.stdout.write(`${eE()}
481
483
  `),process.exit(0));let t=function(e){var t,n;let o,r=(o=ew[e])?`${o.body}
@@ -484,7 +486,7 @@ Related:
484
486
  agent-device help command list and global flags
485
487
  agent-device help <command> command-specific flags
486
488
  agent-device help workflow normal app automation loop
487
- `:null;if(r)return r;let s=_(e);if(!s)return null;let a=(t=e,(n=s).usageOverride?n.usageOverride:[t,...(n.positionalArgs??[]).map(ey),...(n.allowedFlags??[]).flatMap(e=>{var t;return(t=e,L().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),i=eb(new Set(s.allowedFlags??[])),l=eb(D),c=[];return i.length>0&&c.push(eI("Command flags:",i)),c.push(eI("Global flags:",l)),`agent-device ${a}
489
+ `:null;if(r)return r;let s=_(e);if(!s)return null;let a=(t=e,(n=s).usageOverride?n.usageOverride:[t,...(n.positionalArgs??[]).map(ey),...(n.allowedFlags??[]).flatMap(e=>{var t;return(t=e,O().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),i=eb(new Set(s.allowedFlags??[])),l=eb(D),c=[];return i.length>0&&c.push(eI("Command flags:",i)),c.push(eI("Global flags:",l)),`agent-device ${a}
488
490
 
489
491
  ${s.helpDescription}
490
492
 
@@ -494,7 +496,7 @@ Usage:
494
496
  ${c.join("\n\n")}
495
497
  `}(eP(e));t&&(process.stdout.write(t),process.exit(0)),eY(new K("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${eE()}
496
498
  `),process.exit(1)}C.command||(process.stdout.write(`${eE()}
497
- `),process.exit(1));let{command:z,positionals:J}=C,W=new Set(C.providedFlags.map(e=>e.key));try{U=(R=nD({policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session})).lockPolicy?{...C.flags}:nC(C.flags,{policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session}),P=y(U.stateDir),O=U.session??"default",I={command:z,explicitFlagKeys:W,stateDir:P.baseDir,session:O,remoteConfig:U.remoteConfig,hasResolvedSession:void 0!==U.session},j=(T="connect"===I.command||"connection"===I.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?B({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=to(e)??(e.allowActiveFallback?td({stateDir:e.stateDir}):null);if(!o||n&&o.remoteConfigPath!==n)return null;if(t&&ti(o.remoteConfigPath)!==o.remoteConfigHash)throw new K("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 M({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:I.stateDir,session:I.session,remoteConfig:I.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!I.explicitFlagKeys.has("session")&&(!I.remoteConfig||"disconnect"===I.command||!I.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==I.command}))?function(e,t,n){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(n.has(e)||(o[e]=r));return o}(U,T.flags,W):U}catch(t){let e=H(V(t),{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});C.flags.json?eX({success:!1,error:e}):eY(e,{showDetails:C.flags.verbose}),process.exit(1);return}let Z=null;try{let e;if("react-devtools"===z){let e=await nS(J,{flags:j,stateDir:P.baseDir,session:j.session??O,cwd:process.cwd(),env:process.env});process.exit(e);return}eu({command:z,currentVersion:s,stateDir:P.baseDir,flags:j});let t=T?.runtime,a=(e,t)=>({session:e.session??O,requestId:r,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:R.lockPolicy,lockPlatform:R.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===z){if(J.length>0)throw new K("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t,n,r,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=o.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new K("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{r=JSON.parse(i)}catch{throw new K("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(r)||0===r.length)throw new K("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=r,t=!1,n=a.map((e,n)=>{var o,r,s,a,i,l;let c;if(o=e,null!==o&&"object"==typeof o&&!Array.isArray(o)&&"input"in o&&!("positionals"in o)&&!("flags"in o))return e;let d=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,o=t;let r=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(r.length>0)throw new K("INVALID_ARGS",`Batch step ${o} has unknown legacy field(s): ${r.join(", ")}.`);let s=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new K("INVALID_ARGS",`Batch step ${t} requires command.`);if(er(n))return n;throw new K("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new K("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===e.runtime?{}:{runtime:e.runtime}}}(e,n+1);return t=!0,c=(s=(r=d).command,a=r.positionals??[],l=r.flags,i={json:!1,help:!1,version:!1,...l},nl[s](a,i)),{command:r.command,input:c,...void 0===r.runtime?{}:{runtime:r.runtime}}}),t&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),n}(U)}if(x=z,"auth"!==x&&"connection"!==x&&(j=(await tD({command:z,flags:j,stateDir:P.baseDir,env:process.env})).flags),j.remoteConfig&&(A=z,!nU.has(A))){let o=ec(a(j,t),{transport:n.sendToDaemon}),r=await tw({command:z,flags:j,client:o,runtime:t,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nR)if(e.has(t))return!0;return!1}(W)});j=r.flags,t=r.runtime}$={command:z,flags:j,runtime:t,explicitFlagKeys:W,hadConnectionDefaults:!!T},!("open"===$.command&&!$.runtime&&!$.flags.bundleUrl&&!$.flags.metroHost&&!$.flags.metroPort&&!$.flags.remoteConfig&&!$.hadConnectionDefaults&&((k=$.explicitFlagKeys).has("daemonBaseUrl")||k.has("daemonTransport")||k.has("tenant")||k.has("sessionIsolation")||k.has("runId")||k.has("leaseId")||k.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 i=j.daemonBaseUrl;Z=!j.verbose||j.json||i?null:function(e){try{let t=o.existsSync(e)?o.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&o.existsSync(e))try{let n=o.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=o.openSync(e,"r");try{let e=Buffer.alloc(n.size-t);o.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{o.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}(P.logPath);let l=ec(a(j,t),{transport:function(e){let{command:t,flags:n,transport:o}=e;return"test"!==t||n.json?o:async e=>await o({...e,meta:{...e.meta,requestProgress:"replay-test"}})}({command:z,flags:j,transport:n.sendToDaemon})});if("batch"===z){if(!e)throw new K("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:R.lockPolicy&&void 0===U.platform?{...e.input}:nC(e.input,{policyOverrides:j,configuredPlatform:j.platform,configuredSession:j.session,inheritedPlatform:j.platform})}));if(await nA({command:z,positionals:J,flags:{...j,batchSteps:t},client:l}))return}else if("runtime"===z)throw new K("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 nA({command:z,positionals:J,flags:j,client:l}))return;throw new K("INVALID_ARGS",`Unknown command: ${z}`)}catch(n){let e=V(n),t=H(e,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});if("close"===z&&"COMMAND_FAILED"===(S=e).code&&(S.details?.kind==="daemon_startup_failed"||S.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof S.details?.infoPath||"string"==typeof S.details?.lockPath))){j.json&&eX({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(j.json)eX({success:!1,error:t});else if(eY(t,{showDetails:j.verbose}),j.verbose)try{let e=P.logPath;if(o.existsSync(e)){let t=o.readFileSync(e,"utf8").split("\n"),n=t.slice(Math.max(0,t.length-200)).join("\n");n.trim().length>0&&process.stderr.write(`
499
+ `),process.exit(1));let{command:z,positionals:J}=C,W=new Set(C.providedFlags.map(e=>e.key));try{U=(R=nD({policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session})).lockPolicy?{...C.flags}:nC(C.flags,{policyOverrides:C.flags,configuredPlatform:C.flags.platform,configuredSession:C.flags.session}),P=y(U.stateDir),L=U.session??"default",I={command:z,explicitFlagKeys:W,stateDir:P.baseDir,session:L,remoteConfig:U.remoteConfig,hasResolvedSession:void 0!==U.session},j=(T="connect"===I.command||"connection"===I.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?B({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=to(e)??(e.allowActiveFallback?td({stateDir:e.stateDir}):null);if(!o||n&&o.remoteConfigPath!==n)return null;if(t&&ti(o.remoteConfigPath)!==o.remoteConfigHash)throw new K("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 M({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:I.stateDir,session:I.session,remoteConfig:I.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!I.explicitFlagKeys.has("session")&&(!I.remoteConfig||"disconnect"===I.command||!I.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==I.command}))?function(e,t,n){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(n.has(e)||(o[e]=r));return o}(U,T.flags,W):U}catch(t){let e=H(V(t),{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});C.flags.json?eX({success:!1,error:e}):eY(e,{showDetails:C.flags.verbose}),process.exit(1);return}let Z=null;try{let e;if("react-devtools"===z){let e=await nS(J,{flags:j,stateDir:P.baseDir,session:j.session??L,cwd:process.cwd(),env:process.env});process.exit(e);return}eu({command:z,currentVersion:s,stateDir:P.baseDir,flags:j});let t=T?.runtime,a=(e,t)=>({session:e.session??L,requestId:r,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:R.lockPolicy,lockPlatform:R.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===z){if(J.length>0)throw new K("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t,n,r,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=o.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new K("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{r=JSON.parse(i)}catch{throw new K("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(r)||0===r.length)throw new K("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=r,t=!1,n=a.map((e,n)=>{var o,r,s,a,i,l;let c;if(o=e,null!==o&&"object"==typeof o&&!Array.isArray(o)&&"input"in o&&!("positionals"in o)&&!("flags"in o))return e;let d=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,o=t;let r=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(r.length>0)throw new K("INVALID_ARGS",`Batch step ${o} has unknown legacy field(s): ${r.join(", ")}.`);let s=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new K("INVALID_ARGS",`Batch step ${t} requires command.`);if(er(n))return n;throw new K("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new K("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!e||"object"!=typeof e||Array.isArray(e))throw new K("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===e.runtime?{}:{runtime:e.runtime}}}(e,n+1);return t=!0,c=(s=(r=d).command,a=r.positionals??[],l=r.flags,i={json:!1,help:!1,version:!1,...l},nl[s](a,i)),{command:r.command,input:c,...void 0===r.runtime?{}:{runtime:r.runtime}}}),t&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),n}(U)}if(x=z,"auth"!==x&&"connection"!==x&&(j=(await tD({command:z,flags:j,stateDir:P.baseDir,env:process.env})).flags),j.remoteConfig&&(A=z,!nU.has(A))){let o=ec(a(j,t),{transport:n.sendToDaemon}),r=await tw({command:z,flags:j,client:o,runtime:t,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nR)if(e.has(t))return!0;return!1}(W)});j=r.flags,t=r.runtime}$={command:z,flags:j,runtime:t,explicitFlagKeys:W,hadConnectionDefaults:!!T},!("open"===$.command&&!$.runtime&&!$.flags.bundleUrl&&!$.flags.metroHost&&!$.flags.metroPort&&!$.flags.remoteConfig&&!$.hadConnectionDefaults&&((k=$.explicitFlagKeys).has("daemonBaseUrl")||k.has("daemonTransport")||k.has("tenant")||k.has("sessionIsolation")||k.has("runId")||k.has("leaseId")||k.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 i=j.daemonBaseUrl;Z=!j.verbose||j.json||i?null:function(e){try{let t=o.existsSync(e)?o.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&o.existsSync(e))try{let n=o.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=o.openSync(e,"r");try{let e=Buffer.alloc(n.size-t);o.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{o.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}(P.logPath);let l=ec(a(j,t),{transport:function(e){let{command:t,flags:n,transport:o}=e;return"test"!==t||n.json?o:async e=>await o({...e,meta:{...e.meta,requestProgress:"replay-test"}})}({command:z,flags:j,transport:n.sendToDaemon})});if("batch"===z){if(!e)throw new K("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:R.lockPolicy&&void 0===U.platform?{...e.input}:nC(e.input,{policyOverrides:j,configuredPlatform:j.platform,configuredSession:j.session,inheritedPlatform:j.platform})}));if(await nA({command:z,positionals:J,flags:{...j,batchSteps:t},client:l}))return}else if("runtime"===z)throw new K("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 nA({command:z,positionals:J,flags:j,client:l}))return;throw new K("INVALID_ARGS",`Unknown command: ${z}`)}catch(n){let e=V(n),t=H(e,{diagnosticId:X().diagnosticId,logPath:Y({force:!0})??void 0});if("close"===z&&"COMMAND_FAILED"===(S=e).code&&(S.details?.kind==="daemon_startup_failed"||S.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof S.details?.infoPath||"string"==typeof S.details?.lockPath))){j.json&&eX({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(j.json)eX({success:!1,error:t});else if(eY(t,{showDetails:j.verbose}),j.verbose)try{let e=P.logPath;if(o.existsSync(e)){let t=o.readFileSync(e,"utf8").split("\n"),n=t.slice(Math.max(0,t.length-200)).join("\n");n.trim().length>0&&process.stderr.write(`
498
500
  [daemon log]
499
501
  ${n}
500
502
  `)}}catch{}Z&&Z(),process.exit(1)}finally{Z&&Z()}})}n(process.argv[1]??"").href===import.meta.url&&n_(process.argv.slice(2)).catch(e=>{eY(H(V(e)),{showDetails:!0}),process.exit(1)});export{n_ as runCli};
@@ -212,6 +212,8 @@ declare type AndroidSnapshotBackendMetadata = {
212
212
  backend: 'android-helper' | 'uiautomator-dump';
213
213
  helperVersion?: string;
214
214
  helperApiVersion?: string;
215
+ helperTransport?: 'instrumentation' | 'persistent-session';
216
+ helperSessionReused?: boolean;
215
217
  fallbackReason?: string;
216
218
  installReason?: 'missing' | 'outdated' | 'forced' | 'current' | 'skipped';
217
219
  waitForIdleTimeoutMs?: number;