agent-device 0.17.6 → 0.17.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +3 -3
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.6.apk → agent-device-android-multitouch-helper-0.17.8.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.8.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.6.manifest.json → agent-device-android-multitouch-helper-0.17.8.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.6.apk → agent-device-android-snapshot-helper-0.17.8.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.8.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.6.manifest.json → agent-device-android-snapshot-helper-0.17.8.manifest.json} +6 -6
  8. package/dist/src/2133.js +1 -1
  9. package/dist/src/2577.js +1 -0
  10. package/dist/src/2948.js +1 -1
  11. package/dist/src/4291.js +1 -2
  12. package/dist/src/4428.js +3 -3
  13. package/dist/src/4723.js +1 -1
  14. package/dist/src/5910.js +2 -0
  15. package/dist/src/6311.js +18 -18
  16. package/dist/src/7244.js +1 -1
  17. package/dist/src/8184.js +1 -1
  18. package/dist/src/8358.js +4 -0
  19. package/dist/src/9581.js +22 -1
  20. package/dist/src/9722.js +36 -36
  21. package/dist/src/9873.js +1 -1
  22. package/dist/src/9919.js +5 -5
  23. package/dist/src/android-adb.d.ts +1 -1
  24. package/dist/src/batch.d.ts +1 -1
  25. package/dist/src/cli-help.js +140 -30
  26. package/dist/src/cli-output.js +4 -4
  27. package/dist/src/cli.js +28 -17
  28. package/dist/src/contracts.d.ts +1 -1
  29. package/dist/src/index.d.ts +7 -4
  30. package/dist/src/interaction.js +1 -1
  31. package/dist/src/internal/bin.js +1 -1
  32. package/dist/src/provider.js +1 -0
  33. package/dist/src/record-trace-recording.js +3 -3
  34. package/dist/src/remote-config.d.ts +1 -1
  35. package/dist/src/selector-runtime.js +1 -1
  36. package/dist/src/selectors.d.ts +2 -2
  37. package/dist/src/session.js +8 -8
  38. package/dist/src/snapshot.js +1 -1
  39. package/dist/src/web.js +1 -0
  40. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +6 -6
  41. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +1 -1
  42. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +9 -5
  43. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +0 -2
  44. package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +44 -8
  45. package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +59 -16
  46. package/ios-runner/RUNNER_PROTOCOL.md +1 -1
  47. package/package.json +5 -2
  48. package/server.json +2 -2
  49. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.6.apk.sha256 +0 -1
  50. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.6.apk.sha256 +0 -1
  51. package/dist/src/2892.js +0 -4
  52. package/dist/src/5299.js +0 -1
@@ -1,4 +1,4 @@
1
- import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as a}from"./9581.js";import{getFlagDefinitions as o,GLOBAL_FLAG_KEYS as s}from"./9873.js";let n=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, perf memory, 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 physical-device",description:"Connected phone/tablet setup and iOS signing prerequisites"},{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"}],r=["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.","Implicit default sessions are scoped to the current worktree; use --session only when intentionally sharing a named session.","Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.","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 --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: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.","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."],i=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],l=[{label:"AGENT_DEVICE_SESSION",description:"Explicit 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"}],d=["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"],c={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
1
+ import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as o}from"./9581.js";import{getFlagDefinitions as a,GLOBAL_FLAG_KEYS as s}from"./9873.js";let n=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, perf memory, 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 physical-device",description:"Connected phone/tablet setup and iOS signing prerequisites"},{label:"help remote",description:"Remote/cloud config, tenants, leases, and local service tunnels"},{label:"help web",description:"Minimal browser sessions through agent-browser"},{label:"help macos",description:"Desktop, frontmost-app, and menu bar surfaces"},{label:"help dogfood",description:"Exploratory QA report workflow"}],r=["Planning output contract: when asked to plan commands, output command lines only: no prose, numbering, Markdown fences, pipes, or shell helpers.","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 use open "Expo Go" <url> --platform ios, then snapshot -i --platform ios to verify project UI. Do not use plain snapshot or snapshot --diff for this recovery check. 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.","Implicit default sessions are scoped to the current worktree; if a prompt names a Session, include --session <name> on every command in that flow.","Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.","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. Do not use tap; use press or click.","Raw coordinates are fallback-only: use snapshot -i --json rects when iOS refs no-op or child refs are missing, then verify the action with diff snapshot -i or snapshot --diff.","Sparse or AX-unavailable snapshot: use screenshot for visual truth, press the visible coordinate to leave the bad screen, then retry AX with snapshot -i.","macOS context menus use click <ref> --button secondary, then snapshot -i. Longpress is for mobile hold gestures, not macOS secondary-click menus.","Remote workflow profiles use --remote-config on operational commands. Do not substitute --config; --config only loads CLI defaults.",'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.","Web browser sessions: read help web; first slice is web setup if needed -> web doctor -> open <url> --platform web -> snapshot -i -> click/fill/get/is/find/wait/screenshot -> close.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.","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."],i=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],c=[{label:"AGENT_DEVICE_SESSION",description:"Explicit 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"}],l=["agent-device open Settings --platform ios","agent-device open https://example.com --platform web","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"],d={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
 
@@ -7,13 +7,14 @@ Core loop:
7
7
 
8
8
  Command shape:
9
9
  Plans should use agent-device commands, not raw platform tools, pseudo commands, package-manager aliases, or helper prose.
10
+ If the user asks for a command plan, final output should be command lines only: no intro sentence, numbered list, Markdown fence, shell pipe, grep/head/tail helper, or explanatory bullets.
10
11
  Put subcommand first, then positionals, then flags:
11
12
  agent-device open com.example.app --session checkout --platform android --relaunch
12
13
  agent-device record start ./checkout.mp4 --session checkout
13
14
  Snapshot refs look like @e12. After snapshot -i, use the exact @eN ref from that output.
14
15
  If the exact ref is not known yet, first output snapshot -i, then use a concrete example shape like press @e12 in the next command; do not write @<ref>, @ref, @Label_Name, or @eN placeholders.
15
16
  Close means agent-device close. App-owned back means back; system back means back --system.
16
- Taps are press or click. Gestures use swipe, longpress, or gesture <pan|fling|swipe|pinch|rotate|transform>. Use gesture swipe left|right for reliable in-page horizontal swipes, and gesture swipe right-edge for left-edge navigation/back gestures. Android swipe, pinch, rotate, and transform use provider-native touch injection when available, then the bundled touch helper. iOS simulator transform uses private XCTest synthesis for a continuous two-finger pan/scale/rotation path; otherwise it reports UNSUPPORTED_OPERATION.
17
+ Taps are press or click; tap is not a command. Gestures use swipe, longpress, or gesture <pan|fling|swipe|pinch|rotate|transform>. Use gesture swipe left|right for reliable in-page horizontal swipes, and gesture swipe right-edge for left-edge navigation/back gestures. Android swipe, pinch, rotate, and transform use provider-native touch injection when available, then the bundled touch helper. iOS simulator transform uses private XCTest synthesis for a continuous two-finger pan/scale/rotation path; otherwise it reports UNSUPPORTED_OPERATION.
17
18
 
18
19
  Bootstrap:
19
20
  agent-device devices --platform ios
@@ -41,8 +42,9 @@ Snapshots and refs:
41
42
  [off-screen below] 4 items: "Privacy", "About" -> scroll down, then snapshot -i; those are hints, not refs.
42
43
  Re-snapshot after navigation, submit, typing/fill, modal/list/reload/dynamic changes when you need new refs.
43
44
  Anti-pattern: snapshot -i followed by snapshot -i | grep ...
44
- Refs from the first snapshot remain valid until you press, fill, type, scroll, go back, wait for async UI, or otherwise change app state.
45
+ Refs from the first snapshot remain valid until you press, click, fill, type, scroll, go back, wait for async UI, or otherwise change app state.
45
46
  After a mutation, prefer a known selector/label directly (for example press 'label="Send"') because interaction commands refresh interactive state internally. If you need to discover the new control, use snapshot -i, or snapshot -i -s "Composer" when a stable container label/id can scope the refresh.
47
+ If typing/fill opened the keyboard or changed layout and the next target has no stable selector, run snapshot -i, use the fresh ref, then verify with wait/find or diff snapshot -i.
46
48
  For a targeted query, use find/get/is. If you truly need the full tree again, pass --force-full.
47
49
  Off-screen summaries are scroll hints; use scroll, not swipe, then snapshot -i.
48
50
  Missing target in a long list: use a short manual scroll + snapshot loop with a max attempt count. If a named target is summarized as off-screen below/above, use scroll down/up, then snapshot -i; do not use scroll bottom/top because the target may appear before the absolute list edge. Use scroll bottom/top only when the task explicitly asks for the list edge. Edge scrolls verify hidden content with snapshots and stop when no matching hidden content remains.
@@ -104,18 +106,29 @@ Navigation and gestures:
104
106
  agent-device gesture rotate 35 200 420
105
107
  agent-device gesture transform 200 420 80 -40 2 35 700
106
108
  iOS simulator transform uses private XCTest synthesis for a continuous two-finger pan/scale/rotation path; verify app metrics instead of assuming requested values map exactly to recognizer output.
107
- Android transform injects a geometric two-finger path; app recognizers may report non-exact pan/scale/rotation. For Android combined transforms, verify qualitative state such as "pan changed yes" / "pinch changed yes" / "rotate changed yes" unless the app explicitly promises exact centroid metrics.
109
+ Android transform injects a geometric two-finger path; app recognizers may report non-exact pan/scale/rotation. For Android combined transforms, verify semantic app state or coarse per-component effects instead of exact numeric deltas unless the app explicitly exposes stable metrics.
110
+ agent-device gesture transform 200 420 80 -40 2 35 700 --platform android
111
+ agent-device wait text "pan changed yes" 3000 --platform android
112
+ agent-device wait text "pinch changed yes" 3000 --platform android
113
+ agent-device wait text "rotate changed yes" 3000 --platform android
108
114
  If Android needs exact app-state values, prefer isolated gesture pan, gesture pinch, or gesture rotate commands over one combined transform.
115
+ macOS context menus are secondary clicks, not long presses:
116
+ agent-device click @e66 --button secondary --platform macos
117
+ agent-device snapshot -i --platform macos
109
118
 
110
119
  Validation and evidence:
111
120
  Nearby mutation diff: agent-device diff snapshot -i.
112
121
  Expected text/selector verification must include the exact text or selector via wait, is, get, or find; bare screenshots/snapshots are insufficient for named expectations.
122
+ When an action is only a means to reveal or reach an expected target, do not stop at the action itself. Follow it with exact target verification using the id, selector, or text named by the task.
113
123
  Prefer provided testIDs/ids/selectors for verification; use visible text when no durable selector is provided.
114
124
  If task says snapshot, use snapshot. If it asks visual evidence, use screenshot.
115
125
  Icon/tappable visual proof: screenshot --overlay-refs. Flag is --overlay-refs.
116
126
  If snapshot returns a sparse/AX-unavailable state, refs are not reliable. Use plain screenshot, not screenshot --overlay-refs, navigate with coordinates if needed, then retry snapshot -i after reaching another screen; the AX failure may be screen-specific.
127
+ agent-device screenshot
128
+ agent-device press 124 817
129
+ agent-device snapshot -i
117
130
  Startup/CPU/memory/frame first pass: perf metrics --json (bare perf and metrics are aliases). Focused frame/jank health: perf frames --json. Memory-only sample: perf memory sample --json returns compact JSON with bounded top offenders. Heap/memgraph artifact escalation: perf memory snapshot --out heap.artifact; use --kind android-hprof on Android or --kind memgraph on supported Apple simulator/macOS app sessions. Android native profiling: perf cpu profile start|stop|report --kind simpleperf --out <path>; Android native traces: perf trace start|stop --kind perfetto --out <path>. Artifact collectors return compact state/path/size metadata only; raw heap/profile/trace files stay on disk. Treat native perf output as the agent evidence: for example, a Perfetto stop can return state=stopped, outPath=/tmp/app.perfetto-trace, sizeBytes=5392410, and method=adb-shell-perfetto while the 5.3 MB raw trace stays in the artifact. This is better than raw dumps for agents because it is stable, bounded, and keeps large artifacts out of context. heapprofd is deferred until Perfetto plumbing is available. Replay maintenance: replay -u ./flow.ad.
118
- Recording: record start/stop. By default, stop burns touch overlays into the video; use record start --hide-touches for the fastest raw recording. Android adb screenrecord has a 180s platform limit, so longer Android recordings are returned as multiple MP4 chunks. For gesture-heavy iOS simulator proof videos, prefer --hide-touches because overlay timing depends on a stable runner session while gestures are executing. Tracing: trace start ./trace.log, trace stop ./trace.log. Paths are positional.
131
+ Recording: record start/stop. Use --max-size to cap the longest edge and --quality medium|high to choose output quality across Android and Apple targets. By default, stop burns touch overlays into the video; use record start --hide-touches for the fastest raw recording. Android adb screenrecord has a 180s platform limit, so longer Android recordings are returned as multiple MP4 chunks. For gesture-heavy iOS simulator proof videos, prefer --hide-touches because overlay timing depends on a stable runner session while gestures are executing. Tracing: trace start ./trace.log, trace stop ./trace.log. Paths are positional.
119
132
  Stable known flow: batch ./steps.json, not workflow batch.
120
133
  Inline batch JSON example:
121
134
  agent-device batch --steps '[{"command":"open","input":{"app":"settings"}},{"command":"wait","input":{"kind":"duration","durationMs":100}}]'
@@ -125,7 +138,24 @@ Validation and evidence:
125
138
  Debug logs: logs clear --restart, logs mark, reproduce, then logs path; do not split clear/restart into separate stop/start commands.
126
139
  Network headers: network dump --include headers; do not write network log headers.
127
140
  Remote/cloud: connect to discover a cloud profile, or connect --remote-config ./remote-config.json for a local profile; then open, snapshot, disconnect.
141
+ Web: agent-device uses a managed, pinned agent-browser backend as an implementation detail. Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow; use agent-browser directly for standalone web automation. Run agent-device web setup before first use, then agent-device web doctor for backend health checks. Web automation requires Node 24+.
142
+ agent-device web setup
143
+ agent-device web doctor
144
+ agent-device open https://example.com --platform web
145
+ agent-device snapshot -i --platform web
146
+ agent-device get text @e2 --platform web
147
+ agent-device is visible 'label="Welcome"' --platform web
148
+ agent-device find text "Welcome" exists --platform web
149
+ agent-device click @e12 --platform web
150
+ agent-device fill @e13 "qa@example.com" --platform web
151
+ agent-device wait text "Welcome" 3000 --platform web
152
+ agent-device network dump 25 --include headers --platform web
153
+ agent-device screenshot ./artifacts/web-home.png --platform web
154
+ agent-device close --platform web
155
+ Minimal web support is for browser sessions with open, snapshot, find, get, is, click/press, fill/type, wait, network dump, screenshot, close, and replay over those commands. Use agent-browser directly for browser-specific features that agent-device does not surface, such as tab/devtools management, advanced page scripting, network routing/HAR, or raw browser debugging.
128
156
  macOS menu bar: open ... --platform macos --surface menubar; snapshot -i --platform macos --surface menubar.
157
+ Maestro full-suite validation on explicit connected devices uses one test command with a comma-separated --device list and --shard-all. Use --shard-split only when splitting suite entries across devices:
158
+ agent-device test ./e2e/maestro --maestro --device udid1,emulator-5554 --shard-all 2
129
159
 
130
160
  React Native dev loop:
131
161
  JS-only change with Metro connected:
@@ -137,6 +167,7 @@ React Native dev loop:
137
167
  Expo Go is a host shell. Use a provided project URL instead of inventing a bundle id; if no URL is provided but a target/app name is provided, open that target and do not inspect project files to find one. On iOS, prefer host + URL when the host shell is known because direct URL open can report success while leaving the runner/shell focused; verify with snapshot -i after opening:
138
168
  agent-device open "Expo Go" exp://127.0.0.1:8081 --platform ios
139
169
  agent-device snapshot -i --platform ios
170
+ If recovery follows a runner/shell splash screen, use snapshot -i --platform ios; do not substitute plain snapshot or snapshot --diff.
140
171
  There is no open-url command; use open with the URL target or host + URL form.
141
172
  Direct iOS URL open remains valid when no host shell is known, but verify that the app UI loaded:
142
173
  agent-device open exp://127.0.0.1:8081 --platform ios
@@ -250,9 +281,9 @@ React Native internals:
250
281
  Use this for React Native performance/profiling and internals that the accessibility tree cannot expose: components, props, state, hooks, ownership, slow renders, and rerenders.
251
282
 
252
283
  Core commands:
284
+ agent-device react-devtools status
253
285
  agent-device react-devtools start
254
286
  agent-device react-devtools stop
255
- agent-device react-devtools status
256
287
  agent-device react-devtools wait --connected
257
288
  agent-device react-devtools wait --component <ComponentName>
258
289
  agent-device react-devtools count
@@ -271,17 +302,18 @@ Core commands:
271
302
  agent-device react-devtools profile diff before.json after.json --limit 10
272
303
 
273
304
  Profiling loop:
274
- 1. Verify the app is connected: react-devtools status, then wait --connected if needed.
275
- 2. If correlating with logs or network, run logs clear --restart before the first logs mark.
276
- 3. Start profiling immediately before the interaction.
277
- 4. Drive the interaction with normal agent-device commands and mark before/after the repro when timing matters.
278
- 5. Stop profiling.
279
- 6. Make one bounded first-pass survey: profile stop for the summary, profile slow --limit 5 once, profile rerenders --limit 5 once, and profile timeline --limit 20 only when commit timing matters.
280
- 7. Use profile report @cN for targeted render causes and changed props/state/hooks; use get component @cN for current props/state/hooks.
305
+ 1. Run agent-device react-devtools status first. Use start only if status reports the React DevTools helper is not running; start is not a connection check.
306
+ 2. Always run agent-device react-devtools wait --connected after status and before profiling so the app, not just the helper, is attached.
307
+ 3. If correlating with logs or network, run logs clear --restart before the first logs mark.
308
+ 4. Start profiling immediately before the interaction.
309
+ 5. Drive the interaction with normal agent-device commands and mark before/after the repro when timing matters.
310
+ 6. Stop profiling.
311
+ 7. Make one bounded first-pass survey: profile stop for the summary, profile slow --limit 5 once, profile rerenders --limit 5 once, and profile timeline --limit 20 only when commit timing matters.
312
+ 8. Use profile report @cN for targeted render causes and changed props/state/hooks; use get component @cN for current props/state/hooks.
281
313
 
282
314
  Rules:
283
315
  Every React DevTools command is an agent-device subcommand: agent-device react-devtools ...
284
- Do not write agent-devtools, agent-react-devtools, or bare react-devtools commands in final command plans.
316
+ Do not write agent-devtools, agent-react-devtools, or bare react-devtools commands in final command plans. Every profiling and survey line must begin with agent-device react-devtools.
285
317
  Start with get tree --depth 3 or find <name>; use find --exact when fuzzy results are noisy.
286
318
  @c refs reset after reload/remount. After reload, wait --connected and inspect again.
287
319
  Keep the profile window narrow; unrelated navigation makes render data noisy.
@@ -327,15 +359,35 @@ React Native dev loop:
327
359
  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.
328
360
  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.
329
361
  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.
362
+ Multiple local worktrees can reuse one native iOS simulator build by running each worktree's Metro on a different port and opening the same installed app on different simulators with explicit runtime hints:
363
+ agent-device open "React Navigation Example" --platform ios --device "iPhone 17" --session rn-a --metro-host 127.0.0.1 --metro-port 8081 --relaunch
364
+ agent-device open "React Navigation Example" --platform ios --device "iPhone 17 Pro" --session rn-b --metro-host 127.0.0.1 --metro-port 8082 --relaunch
365
+ iOS simulator opens write React Native's per-simulator debug server settings before launch, so those ports do not conflict across simulators. Use separate sessions/devices, close both sessions when done, and rebuild only for native changes or dependency changes that affect the binary. One simulator cannot run two copies of the same bundle id.
330
366
  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.
331
367
 
332
368
  Overlays and busy RN UIs:
333
- If snapshot reports a React Native warning/error overlay, handle it before interacting with the app: run agent-device react-native dismiss-overlay. The command sends the safe LogBox/RedBox action and verifies the overlay is gone with a fresh post-dismiss snapshot.
369
+ If snapshot reports a React Native warning/error overlay, handle it before interacting with the app: run agent-device react-native dismiss-overlay. The command sends the safe LogBox/RedBox action and verifies the overlay is gone with a fresh post-dismiss snapshot -i.
334
370
  If the command reports the overlay is still visible, use screenshot --overlay-refs for visual evidence and report the overlay instead of pressing warning/error text manually.
335
371
  Do not manually press warning/error text bodies, collapsed banner bodies, full-screen warning parents, or broad LogBox/RedBox refs. The dismiss-overlay command owns the narrow LogBox/RedBox targeting policy.
336
372
  Report the overlay in the final summary. Use screenshot --overlay-refs before dismissing only if visual evidence is required.
373
+ Minimal overlay continuation:
374
+ agent-device snapshot -i
375
+ agent-device react-native dismiss-overlay
376
+ agent-device snapshot -i
377
+ agent-device press 'id="submit-order"'
378
+ Do not use a plain snapshot after dismiss-overlay when the next step needs current refs; use snapshot -i.
379
+ When overlay evidence and React diagnostics are required before continuing, keep the sequence explicit:
380
+ agent-device snapshot -i
381
+ agent-device screenshot --overlay-refs
382
+ agent-device react-devtools errors
383
+ agent-device react-native dismiss-overlay
384
+ agent-device snapshot -i
385
+ agent-device press 'id="submit-order"'
337
386
  If snapshot times out because the UI never becomes idle, Android accessibility may be blocked by busy or continuously changing app UI. After that timeout, use screenshot as visual truth instead of repeatedly retrying snapshots.
338
387
  If iOS snapshot reports AX unavailable or returns only a sparse root, the current screen's accessibility state is invalid. Use plain screenshot as visual truth, coordinate navigation to leave the bad screen, then take a fresh snapshot -i before returning to selector/@ref commands.
388
+ agent-device screenshot
389
+ agent-device press 124 817
390
+ agent-device snapshot -i
339
391
  Android runtime permission dialogs and native alerts are handled by alert wait/accept/dismiss. If alert reports no alert, treat the visible surface as app-owned UI and use snapshot -i plus press by label/ref.
340
392
 
341
393
  React DevTools routing:
@@ -344,8 +396,15 @@ React DevTools routing:
344
396
  If React DevTools cannot connect, report status and continue with logs, network, perf metrics, screenshot, and trace evidence instead of blocking the whole flow.
345
397
 
346
398
  Slow-flow investigation:
347
- Keep one session, open the app, and snapshot -i.
348
- Use help react-devtools for the narrow React profile window.
399
+ Keep one session, open the app first, and snapshot -i before interacting.
400
+ Start React Native slow-flow plans with this ordered scaffold:
401
+ agent-device open "Agent Device Tester" --platform android
402
+ agent-device snapshot -i
403
+ agent-device react-devtools status
404
+ agent-device react-devtools wait --connected
405
+ If the task says to open the app, include the open command even when it also describes the current screen.
406
+ Use help react-devtools for the narrow React profile window. Profiling plans need both status and wait --connected before profile start.
407
+ Check status before wait/profile. Do not substitute react-devtools start for status; start launches the helper, while status reports connection state.
349
408
  Use help debugging for logs clear --restart, logs mark, network dump --include headers, perf metrics --json, traces, and runtime failure evidence.
350
409
  For 15-20s async work, use wait with the exact expected text or selector instead of repeated snapshots.
351
410
  Report React render offenders separately from network/backend waits and device frame/CPU/memory findings.`},"physical-device":{summary:"Connected phone/tablet setup and iOS signing prerequisites",body:`agent-device help physical-device
@@ -395,10 +454,22 @@ Script flow, per-command config:
395
454
  agent-device snapshot --remote-config ./remote-config.json
396
455
  agent-device disconnect --remote-config ./remote-config.json
397
456
 
457
+ Direct proxy flow for a remote Mac:
458
+ On the Mac with simulator/device access:
459
+ agent-device proxy --port 4310
460
+ cloudflared tunnel --url http://127.0.0.1:4310
461
+ On the remote client:
462
+ agent-device devices --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
463
+ agent-device devices
464
+
398
465
  Rules:
399
466
  connect and disconnect are top-level commands. Do not write agent-device remote connect or agent-device remote disconnect.
400
467
  Use connect without --remote-config when the cloud control plane owns the connection profile.
401
468
  Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
469
+ Use agent-device proxy for direct tunnel access to a Mac you control. Copy the printed daemon base URL and daemon auth token; do not use agent-device auth for this direct proxy flow.
470
+ For repeated direct proxy commands, store daemonBaseUrl and daemonAuthToken in normal agent-device.json CLI config. Keep platform selection on each command or workflow. Do not use --remote-config unless you are using the tenant/run/lease remote connection flow.
471
+ Keep the proxy token secret. Anyone with the token can control the proxied daemon.
472
+ Do not use --config as a remote profile flag. --config loads CLI defaults; --remote-config selects remote daemon/profile settings.
402
473
  For self-contained scripts, pass the same --remote-config to every operational command, including disconnect; a preceding connect is optional but not required.
403
474
  For remote artifact installs, use install-from-source <url> or install-from-source --github-actions-artifact org/repo:artifact; do not download CI artifacts locally first.
404
475
  After connect, let the active remote connection supply runtime hints.
@@ -431,7 +502,46 @@ Rules:
431
502
  Context menus are not ambient UI: secondary-click a visible target, then re-snapshot and use the new menu-item refs.
432
503
  Do not let iOS simulator-set scoping hide macOS desktop targets.
433
504
  Prefer refs/selectors over raw coordinates.
434
- macOS snapshot rects are window-space; use current refs or overlay refs instead of guessing coordinates.`},dogfood:{summary:"Exploratory QA workflow with reproducible evidence",body:`agent-device help dogfood
505
+ macOS snapshot rects are window-space; use current refs or overlay refs instead of guessing coordinates.`},web:{summary:"Minimal browser workflow with the managed web backend",body:`agent-device help web
506
+
507
+ Use --platform web only for the minimal browser command loop exposed through agent-device.
508
+
509
+ Dependency:
510
+ agent-device uses a managed, pinned agent-browser backend for browser mechanics. agent-device owns command/session/replay integration, selectors/refs at the command surface, and artifact routing; agent-browser owns browser launch, page control, screenshots, and browser-specific behavior.
511
+ Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow. Use agent-browser directly for standalone web automation.
512
+ Before first use, set up and verify the managed backend:
513
+ agent-device web setup
514
+ agent-device web doctor
515
+ Web automation requires Node 24+.
516
+
517
+ Planning rule:
518
+ For web command plans, output only agent-device command lines. Do not add prose, numbering, Markdown fences, shell pipes, or agent-browser commands unless the task is explicitly standalone browser automation outside agent-device.
519
+
520
+ First-slice loop:
521
+ agent-device web setup
522
+ agent-device web doctor
523
+ agent-device open https://example.com --platform web
524
+ agent-device snapshot -i --platform web
525
+ agent-device get text @e2 --platform web
526
+ agent-device is visible 'label="Welcome"' --platform web
527
+ agent-device find text "Welcome" exists --platform web
528
+ agent-device click @e12 --platform web
529
+ agent-device fill @e13 "qa@example.com" --platform web
530
+ agent-device wait text "Welcome" 3000 --platform web
531
+ agent-device network dump 25 --include headers --platform web
532
+ agent-device screenshot ./artifacts/web-home.png --platform web
533
+ agent-device close --platform web
534
+
535
+ Supported in agent-device web sessions:
536
+ open <url>, snapshot -i, get text/attrs, is visible/exists/text, find text/selector, click/press @ref or selector, fill/type @ref or selector, wait text/selector, network dump, screenshot, close, and replay scripts made from those commands.
537
+
538
+ Out of scope for agent-device web support:
539
+ Browser runtime debugging, tabs/windows/devtools control, network routing/interception/HAR, storage/cookie management, arbitrary page scripting, downloads/uploads, multi-page orchestration, and agent-browser-specific diagnostics. Use agent-browser directly for those browser-specific workflows.
540
+
541
+ Rules:
542
+ Do not claim web e2e CI exists unless a project workflow explicitly provides it.
543
+ Do not use native mobile or desktop setup commands such as boot, apps, install, settings, alert, keyboard, perf, logs, or react-devtools for --platform web.
544
+ Keep browser plans session-scoped: open a URL, inspect refs, act on refs/selectors, verify with wait/get/is/snapshot, capture screenshot only when visual evidence is needed, then close.`},dogfood:{summary:"Exploratory QA workflow with reproducible evidence",body:`agent-device help dogfood
435
545
 
436
546
  Use this when asked to dogfood, exploratory test, bug hunt, QA, or find issues in an app.
437
547
 
@@ -488,13 +598,13 @@ Rules:
488
598
  Prefer refs for exploration and selectors for deterministic replay.
489
599
  Use logs, network, screenshot --overlay-refs, trace, perf metrics, perf frames, or react-devtools only when they add evidence to a specific issue.
490
600
  Never delete screenshots, videos, traces, or report artifacts during a session.
491
- Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function p(e){let t=e.endsWith("?"),a=t?e.slice(0,-1):e;return t?`[${a}]`:`<${a}>`}function u(){let a,o,c,p,u,v,b,w;return a=`agent-device <command> [args] [--json]
601
+ Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function p(e){let t=e.endsWith("?"),o=t?e.slice(0,-1):e;return t?`[${o}]`:`<${o}>`}function u(){let o,a,d,p,u,v,b,w;return o=`agent-device <command> [args] [--json]
492
602
 
493
603
  CLI to control iOS and Android devices for AI agents.
494
- `,o=m("Commands:",e().map(e=>{let a=t(e);return{name:e,schema:a,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let a=(t.positionalArgs??[]).map(a=>{var o,s,n;let r,i,l,d;return o=e,s=t,i=(r=(n=a).endsWith("?"))?n.slice(0,-1):n,d=(l=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${o} ${i}`),r?l?`[${i}]`:d?i:`[${i}]`:d?i:`<${i}>`});return[e,...a].join(" ")}(e,a)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),c=f("Flags:",h(s)),p=g("Agent Quickstart:",r),u=m("Agent Workflows:",n),v=g("Configuration:",i),b=m("Environment:",l),w=g("Examples:",d),`${a}
495
- ${o}
604
+ `,a=m("Commands:",e().map(e=>{let o=t(e);return{name:e,schema:o,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let o=(t.positionalArgs??[]).map(o=>{var a,s,n;let r,i,c,l;return a=e,s=t,i=(r=(n=o).endsWith("?"))?n.slice(0,-1):n,l=(c=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${a} ${i}`),r?c?`[${i}]`:l?i:`[${i}]`:l?i:`<${i}>`});return[e,...o].join(" ")}(e,o)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),d=f("Global Flags:",h(s)),p=g("Agent Quickstart:",r),u=m("Agent Workflows:",n),v=g("Configuration:",i),b=m("Environment:",c),w=g("Examples:",l),`${o}
605
+ ${a}
496
606
 
497
- ${c}
607
+ ${d}
498
608
 
499
609
  ${p}
500
610
 
@@ -505,20 +615,20 @@ ${v}
505
615
  ${b}
506
616
 
507
617
  ${w}
508
- `}function h(e){return o().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function f(e,t){return m(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function m(e,t){if(0===t.length)return`${e}
509
- (none)`;let a=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(a)}${e.description}`);return o.join("\n")}function g(e,t){return 0===t.length?`${e}
510
- (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function v(e){var t,n;let r,i=(r=c[e])?`${r.body}
618
+ `}function h(e){return a().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function f(e,t){return m(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function m(e,t){if(0===t.length)return`${e}
619
+ (none)`;let o=Math.max(...t.map(e=>e.label.length))+2,a=[e];for(let e of t)a.push(` ${e.label.padEnd(o)}${e.description}`);return a.join("\n")}function g(e,t){return 0===t.length?`${e}
620
+ (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function v(e){var t,s;let n,r=(n=d[e])?`${n.body}
511
621
 
512
622
  Related:
513
623
  agent-device help command list and global flags
514
624
  agent-device help <command> command-specific flags
515
625
  agent-device help workflow normal app automation loop
516
- `:null;if(i)return i;let l=a(e);if(!l)return null;let d=(t=e,(n=l).usageOverride?n.usageOverride:[t,...(n.positionalArgs??[]).map(p),...(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(" ")),u=h(new Set(l.allowedFlags??[])),m=h(s),g=[];return u.length>0&&g.push(f("Command flags:",u)),g.push(f("Global flags:",m)),`agent-device ${d}
626
+ `:null;if(r)return r;let i=o(e);if(!i)return null;let c=(t=e,(s=i).usageOverride?s.usageOverride:[t,...(s.positionalArgs??[]).map(p),...(s.allowedFlags??[]).flatMap(e=>{var t;return(t=e,a().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),l=h(new Set(i.allowedFlags??[])),u=[];l.length>0&&u.push(f("Command flags:",l));let m=u.length>0?`
517
627
 
518
- ${l.helpDescription}
628
+ ${u.join("\n\n")}`:"";return`agent-device ${c}
519
629
 
520
- Usage:
521
- agent-device ${d}
630
+ ${i.helpDescription}
522
631
 
523
- ${g.join("\n\n")}
632
+ Usage:
633
+ agent-device ${c}${m}
524
634
  `}export{v as buildCommandUsageText,u as buildUsageText};
@@ -1,4 +1,4 @@
1
- import{serializeOpenResult as t,serializeSnapshotResult as e,serializeSessionListEntry as n,readCommandMessage as r,serializeDeployResult as o,serializeCloseResult as a,serializeInstallFromSourceResult as i,serializeDevice as s}from"./9873.js";import{formatSnapshotText as u}from"./6311.js";function d(t){return({result:e})=>t(e)}let p=d(l);function l(t){return{data:t,text:r(t)}}function f(t){return t&&"object"==typeof t&&!Array.isArray(t)?t:void 0}function c(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}let m={batch:d(function(t){let e="number"==typeof t.total?t.total:0,n="number"==typeof t.executed?t.executed:0,o="number"==typeof t.totalDurationMs?t.totalDurationMs:void 0,a=[`Batch completed: ${n}/${e} steps${void 0!==o?` in ${o}ms`:""}`];for(let e of Array.isArray(t.results)?t.results:[]){let t=function(t){let e=f(t);if(!e)return;let n="number"==typeof e.step?e.step:void 0,o="string"==typeof e.command?e.command:"step",a=!1!==e.ok,i=function(t,e,n){var o;return e?r(f(t.data))??n:(o=f(t.error),("string"==typeof o?.message&&o.message.length>0?o.message:null)??n)}(e,a,o),s=void 0!==n?`${n}. `:"- ",u="number"==typeof e.durationMs?e.durationMs:void 0,d=void 0!==u?` (${u}ms)`:"";return`${s}${a?"OK":"FAILED"} ${i}${d}`}(e);t&&a.push(t)}return{data:t,text:a.join("\n")}})},$={debug:d(function(t){let e=[t.outPath,t.message];for(let n of(e.push(...function(t){let e=t.crash,n=[`Crash: ${e.appName??"unknown app"}${void 0===e.crashedThread?"":` thread ${e.crashedThread}`}`];for(let t of(e.bundleId&&n.push(`Bundle: ${e.bundleId}`),e.exceptionType&&n.push(`Exception: ${e.exceptionType}`),e.terminationReason&&n.push(`Termination: ${e.terminationReason}`),e.topFrames))n.push(`Frame ${t.index}: ${t.image} ${t.symbol??t.address}`);for(let t of e.findings)n.push(`Finding: ${t}`);return n}(t)),t.matchedImages))e.push(`Matched: ${n.name} ${n.uuid}${n.arch?` ${n.arch}`:""}`);for(let n of t.warnings??[])e.push(`Warning: ${n}`);return{data:t,text:e.join("\n")}})};function h(t){let e=t.ref??"",n=t.x,r=t.y;return e&&"number"==typeof n&&"number"==typeof r?{data:t,text:`Tapped @${e} (${n}, ${r})`}:l(t)}let y={click:d(h),press:d(h),get:({input:t,result:e})=>{var n;let r;return r=(n={result:e,format:t.format}).result,"text"===n.format?{data:r,text:"string"==typeof r.text?r.text:""}:"attrs"===n.format?{data:r,text:JSON.stringify(r.node??{},null,2)}:l(r)},is:d(function(t){return{data:t,text:`Passed: is ${t.predicate??"assertion"}`}}),find:d(function(t){return"string"==typeof t.text?{data:t,text:t.text}:"boolean"==typeof t.found?{data:t,text:`Found: ${t.found}`}:t.node?{data:t,text:JSON.stringify(t.node,null,2)}:l(t)})};function g(t){return l(o(t))}let v={boot:d(function(t){let e=t.platform??"unknown",n=t.device??t.id??"unknown";return{data:t,text:`Boot ready: ${n} (${e})`}}),shutdown:d(function(t){let e=t.platform??"unknown",n=t.device??t.id??"unknown",r=t.shutdown,o=!!r&&"object"==typeof r&&"success"in r&&!0===r.success;return{data:t,text:`${o?"Shutdown":"Shutdown failed"}: ${n} (${e})`}}),devices:d(function(t){return{data:{devices:t.map(s)},text:t.map(b).join("\n")}}),apps:({input:t,result:e})=>{var n;return{data:{apps:(n={result:e,appsFilter:t.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:d(function(t){if("stateDir"in t)return{data:t,text:t.stateDir};let e={sessions:t.sessions.map(n)};return{data:e,text:JSON.stringify(e,null,2)}}),open:d(function(e){let n=t(e),o=[r(n)].filter(t=>!!t);return"string"==typeof n.sessionStateDir&&o.push(`Session state: ${n.sessionStateDir}`),{data:n,text:o.join("\n")||null}}),close:d(function(t){return l(a(t))}),install:d(g),reinstall:d(g),"install-from-source":d(function(t){return l(i(t))}),prepare:p};function b(t){let e=t.kind?` ${t.kind}`:"",n=t.target?` target=${t.target}`:"",r="boolean"==typeof t.booted?` booted=${t.booted}`:"";return`${t.name} (${t.platform}${e}${n})${r}`}let x={logs:d(function(t){var e;let n="string"==typeof t.path?t.path:"";return{data:t,text:n,stderr:F([M(t,["active","state","backend","sizeBytes"]),(e=t,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(t=>{var n,r;return n=t,!0===(r=e[t])?`${n}=true`:"number"==typeof r?`${n}=${r}`:""}).filter(Boolean).join(" ")||void 0),"string"==typeof t.hint?t.hint:void 0,k(t.notes)])}}),network:d(function(t){let e=[],n="string"==typeof t.path?t.path:"";n&&e.push(n);let r=Array.isArray(t.entries)?t.entries:[];if(0===r.length)e.push("No recent HTTP(s) entries found.");else for(let t of r)e.push(...function(t){let e=f(t)??{},n="string"==typeof e.method?e.method:"HTTP",r="string"==typeof e.url?e.url:"<unknown-url>",o="number"==typeof e.status?` status=${e.status}`:"",a="string"==typeof e.timestamp?`${e.timestamp} `:"",i="number"==typeof e.durationMs?` durationMs=${e.durationMs}`:"",s=[`${a}${n} ${r}${o}${i}`];return w(s,"headers",e.headers),w(s,"request",e.requestBody),w(s,"response",e.responseBody),s}(t));return{data:t,text:e.join("\n"),stderr:F([M(t,["active","state","backend","include","scannedLines","matchedLines"]),k(t.notes)])}})};function w(t,e,n){"string"==typeof n&&t.push(` ${e}: ${n}`)}function M(t,e){return e.map(e=>void 0!==t[e]&&null!==t[e]?`${e}=${t[e]}`:"").filter(Boolean).join(" ")||void 0}function k(t){if(!Array.isArray(t))return;let e=t.filter(t=>"string"==typeof t&&t.length>0);return e.length>0?e.join("\n"):void 0}function F(t){return t.filter(t=>!!t).join("\n")||void 0}let P={perf:d(function(t){return{data:t,text:function(t){var e,n,r,o;let a,i="xctrace"===(e=t).kind?function(t){var e,n,r,o,a;let i="string"==typeof t.perf?t.perf:void 0,s="string"==typeof(e=t).outPath?e.outPath:"string"==typeof e.reportPath?e.reportPath:void 0;if(i&&s&&"xctrace"===t.kind){let e;return n=s,r="string"==typeof t.mode?t.mode:"capture",o=i,a=t.template,e=[n,`Perf ${r}: ${o}`],"string"==typeof a&&e.push(`Template: ${a}`),e.join("\n")}}(e):function(t){var e;let n,r,o,a=(n=j((e=t).action),r=j(e.kind),o=j(e.type),n&&r&&o?{action:n,kind:r,type:o}:void 0);if(a){let e;return`Perf ${a.action}: ${a.kind} ${a.type}${(e=j(t.state))?` state=${e}`:""}${function(t){let e=j(t.outPath);if(!e)return"";let n=S(t.sizeBytes);return`
2
- ${e}${void 0!==n?` (${N(n)})`:""}`}(t)}${function(t){let e=f(t.summary),n=f(e?.frameHealth);if(!n||!0!==n.available)return"";let r=S(n.droppedFramePercent),o=S(n.droppedFrameCount),a=S(n.totalFrameCount);return void 0===r||void 0===o||void 0===a?"":`
3
- Trace frame health: dropped ${A(r)} (${Math.round(o)}/${Math.round(a)} frames)`}(t)}`}}(e);if(i)return i;let s=f(t.artifact);if(s)return function(t){let e="string"==typeof t.kind?t.kind:"memory";if(!1===t.available){let n="string"==typeof t.reason&&t.reason.length>0?t.reason:"not available";return`Memory artifact (${e}): unavailable - ${n}`}let n="string"==typeof t.path?t.path:void 0,r=S(t.sizeBytes),o=void 0===r?"":` (${N(r)})`;return n?`Memory artifact (${e}): ${n}${o}`:`Memory artifact (${e}): captured${o}`}(s);let u=f(t.metrics),d=f(u?.fps),p=(n=u,(a=[function(t){if(t?.available!==!0)return;let e=S(t.usagePercent);return void 0!==e?`CPU ${A(e)}`:void 0}(f(n?.cpu)),function(t){let e;if(t?.available!==!0)return;let n=S(t.residentMemoryKb)??S(t.totalPssKb)??S(t.totalRssKb);return void 0!==n?`memory ${e=n/1024,`${e>=10?Math.round(e):e.toFixed(1)}MB`}`:void 0}(f(n?.memory))].filter(t=>!!t)).length>0?a.join(", "):void 0);if(!d)return B(p,"missing frame metric");if(!1===d.available){return B(p,"string"==typeof(r=d).reason&&r.reason.length>0?r.reason:"not available")}let l=function(t){let e=S(t.droppedFramePercent),n=S(t.droppedFrameCount);if(void 0!==e&&void 0!==n){var r,o,a;return[`dropped ${A(e)}`,(r=n,void 0!==(o=S(t.totalFrameCount))?`(${Math.round(r)}/${Math.round(o)} frames)`:`(${Math.round(r)} dropped frames)`),void 0!==(a=S(t.sampleWindowMs))?`window ${I(a)}`:""].filter(Boolean).join(" ")}}(d);if(!l)return B(p,"missing dropped-frame summary");let m=[`Frame health: ${l}`],$=(Array.isArray(o=d.worstWindows)?o.filter(c):[]).flatMap(t=>{let e=function(t){let e=S(t.startOffsetMs),n=S(t.endOffsetMs),r=S(t.missedDeadlineFrameCount);if(void 0===e||void 0===n||void 0===r)return;let o=S(t.worstFrameMs),a=void 0===o?"":`, worst ${I(o)}`;return`- +${I(e)}-+${I(n)}: ${Math.round(r)} missed-deadline frames${a}`}(t);return e?[e]:[]});return $.length>0&&m.push("Worst windows:",...$),m.join("\n")}(t)}})};function j(t){return"string"==typeof t?t:void 0}function B(t,e){return t?`Performance: ${t}`:`Frame health: unavailable - ${e}`}function S(t){return"number"==typeof t&&Number.isFinite(t)?t:void 0}function A(t){return`${Number.isInteger(t)?t:t.toFixed(1)}%`}function I(t){let e=Math.max(0,Math.round(t));if(e<1e3)return`${e}ms`;let n=Math.round(e/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60),o=n%60;return o>0?`${r}m ${o}s`:`${r}m`}function N(t){if(t<1024)return`${Math.round(t)}B`;let e=t/1024;if(e<1024)return`${e>=10?Math.round(e):e.toFixed(1)}KB`;let n=e/1024;return`${n>=10?Math.round(n):n.toFixed(1)}MB`}let O={record:d(function(t){let e,n="string"==typeof t.outPath?t.outPath:"",r=Array.isArray(e=t.chunks)?e.flatMap(t=>t&&"object"==typeof t?"number"!=typeof t.index||"string"!=typeof t.path?[]:[{index:t.index,path:t.path}]:[]):[];if(r.length<=1){var o,a;let e;return{data:t,text:(o=t,e=[],(a=n)&&e.push(a),"string"==typeof o.sessionStateDir&&e.push(`Session state: ${o.sessionStateDir}`),"string"==typeof o.warning&&e.push(`Warning: ${o.warning}`),"string"==typeof o.overlayWarning&&e.push(`Overlay warning: ${o.overlayWarning}`),e.join("\n"))}}let i=["Recording chunks:"];for(let t of r)i.push(` ${t.index}: ${t.path}`);return"string"==typeof t.telemetryPath&&i.push(`Telemetry: ${t.telemetryPath}`),"string"==typeof t.warning&&i.push(`Warning: ${t.warning}`),"string"==typeof t.overlayWarning&&i.push(`Overlay warning: ${t.overlayWarning}`),{data:t,text:i.join("\n")}})},T={appstate:d(function(t){return{data:t,text:function(t){if("ios"===t.platform){let e=[`Foreground app: ${t.appName??t.appBundleId??"unknown"}`];return t.appBundleId&&e.push(`Bundle: ${t.appBundleId}`),t.source&&e.push(`Source: ${t.source}`),e.join("\n")}if("android"===t.platform){let e=[`Foreground app: ${t.package??"unknown"}`];return t.activity&&e.push(`Activity: ${t.activity}`),e.join("\n")}return null}(t)}}),back:p,home:p,rotate:p,"app-switcher":p,keyboard:d(function(t){if("android"===t.platform&&"status"===t.action){var e;let n=[`Keyboard visible: ${!0===t.visible?"yes":"no"}`,`Input type: ${t.type??t.inputType??"unknown"}`,`Input owner: ${t.inputOwner??"unknown"}`];return t.inputMethodPackage&&n.push(`Input method: ${t.inputMethodPackage}`),t.focusedPackage&&n.push(`Focused package: ${t.focusedPackage}`),t.focusedResourceId&&n.push(`Focused resource: ${t.focusedResourceId}`),n.push(`Next action: ${(e=t.visible,"ime"===t.inputOwner?"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.":!0===e?"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:t,text:n.join("\n")}}return l(t)}),clipboard:d(function(t){return"read"===t.action?{data:t,text:t.text}:l(t)})},D={...v,snapshot:({input:t,result:n})=>{var r;let o;return{data:o=e((r={result:n,raw:t.raw,interactiveOnly:t.interactiveOnly,scope:t.scope,depth:t.depth}).result),jsonData:function(t){let{unchanged:e,...n}=t;return n}(o),stderr:r.result.snapshotDiagnostics?.warning?`${r.result.snapshotDiagnostics.warning}
4
- `:void 0,text:u(o,{raw:r.raw,flatten:r.interactiveOnly,scoped:"string"==typeof r.scope&&r.scope.trim().length>0,depthLimited:"number"==typeof r.depth})}},wait:p,alert:p,...T,...y,...x,...P,...$,...m,...O,metro:({input:t,result:e})=>{var n;return{data:(n={result:e,action:t.action}).result,text:"reload"===n.action?`Reloaded React Native apps via ${n.result.reloadUrl}`:JSON.stringify(n.result,null,2)}}};function C(t){return D[t.name]?.({input:t.input??{},result:t.result})}export{C as formatCliOutput};
1
+ import{serializeOpenResult as t,serializeSnapshotResult as e,serializeSessionListEntry as n,readCommandMessage as r,serializeDeployResult as o,serializeCloseResult as a,serializeInstallFromSourceResult as i,serializeDevice as s}from"./9873.js";import{formatSnapshotText as u}from"./6311.js";function d(t){return({result:e})=>t(e)}let p=d(l);function l(t){return{data:t,text:r(t)}}function f(t){return t&&"object"==typeof t&&!Array.isArray(t)?t:void 0}function c(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}let h={batch:d(function(t){let e="number"==typeof t.total?t.total:0,n="number"==typeof t.executed?t.executed:0,o="number"==typeof t.totalDurationMs?t.totalDurationMs:void 0,a=[`Batch completed: ${n}/${e} steps${void 0!==o?` in ${o}ms`:""}`];for(let e of Array.isArray(t.results)?t.results:[]){let t=function(t){let e=f(t);if(!e)return;let n="number"==typeof e.step?e.step:void 0,o="string"==typeof e.command?e.command:"step",a=!1!==e.ok,i=function(t,e,n){var o;return e?r(f(t.data))??n:(o=f(t.error),("string"==typeof o?.message&&o.message.length>0?o.message:null)??n)}(e,a,o),s=void 0!==n?`${n}. `:"- ",u="number"==typeof e.durationMs?e.durationMs:void 0,d=void 0!==u?` (${u}ms)`:"";return`${s}${a?"OK":"FAILED"} ${i}${d}`}(e);t&&a.push(t)}return{data:t,text:a.join("\n")}})},$={debug:d(function(t){let e=[t.outPath,t.message];for(let n of(e.push(...function(t){let e=t.crash,n=[`Crash: ${e.appName??"unknown app"}${void 0===e.crashedThread?"":` thread ${e.crashedThread}`}`];for(let t of(e.bundleId&&n.push(`Bundle: ${e.bundleId}`),e.exceptionType&&n.push(`Exception: ${e.exceptionType}`),e.terminationReason&&n.push(`Termination: ${e.terminationReason}`),e.topFrames))n.push(`Frame ${t.index}: ${t.image} ${t.symbol??t.address}`);for(let t of e.findings)n.push(`Finding: ${t}`);return n}(t)),t.matchedImages))e.push(`Matched: ${n.name} ${n.uuid}${n.arch?` ${n.arch}`:""}`);for(let n of t.warnings??[])e.push(`Warning: ${n}`);return{data:t,text:e.join("\n")}})};function m(t){let e=t.ref??"",n=t.x,r=t.y;return e&&"number"==typeof n&&"number"==typeof r?{data:t,text:`Tapped @${e} (${n}, ${r})`}:l(t)}let y={click:d(m),press:d(m),get:({input:t,result:e})=>{var n;let r;return r=(n={result:e,format:t.format}).result,"text"===n.format?{data:r,text:"string"==typeof r.text?r.text:""}:"attrs"===n.format?{data:r,text:JSON.stringify(r.node??{},null,2)}:l(r)},is:d(function(t){return{data:t,text:`Passed: is ${t.predicate??"assertion"}`}}),find:d(function(t){return"string"==typeof t.text?{data:t,text:t.text}:"boolean"==typeof t.found?{data:t,text:`Found: ${t.found}`}:t.node?{data:t,text:JSON.stringify(t.node,null,2)}:l(t)})};function g(t){return l(o(t))}let v={boot:d(function(t){let e=t.platform??"unknown",n=t.device??t.id??"unknown";return{data:t,text:`Boot ready: ${n} (${e})`}}),shutdown:d(function(t){let e=t.platform??"unknown",n=t.device??t.id??"unknown",r=t.shutdown,o=!!r&&"object"==typeof r&&"success"in r&&!0===r.success;return{data:t,text:`${o?"Shutdown":"Shutdown failed"}: ${n} (${e})`}}),devices:d(function(t){return{data:{devices:t.map(s)},text:t.map(b).join("\n")}}),apps:({input:t,result:e})=>{var n;return{data:{apps:(n={result:e,appsFilter:t.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:d(function(t){if("stateDir"in t)return{data:t,text:t.stateDir};let e={sessions:t.sessions.map(n)};return{data:e,text:JSON.stringify(e,null,2)}}),open:d(function(e){let n=t(e),o=[r(n)].filter(t=>!!t);return"string"==typeof n.sessionStateDir&&o.push(`Session state: ${n.sessionStateDir}`),{data:n,text:o.join("\n")||null}}),close:d(function(t){return l(a(t))}),install:d(g),reinstall:d(g),"install-from-source":d(function(t){return l(i(t))}),prepare:p};function b(t){let e=t.kind?` ${t.kind}`:"",n=t.target?` target=${t.target}`:"",r="boolean"==typeof t.booted?` booted=${t.booted}`:"";return`${t.name} (${t.platform}${e}${n})${r}`}let x={logs:d(function(t){var e;let n="string"==typeof t.path?t.path:"";return{data:t,text:n,stderr:P([k(t,["active","state","backend","sizeBytes"]),(e=t,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(t=>{var n,r;return n=t,!0===(r=e[t])?`${n}=true`:"number"==typeof r?`${n}=${r}`:""}).filter(Boolean).join(" ")||void 0),"string"==typeof t.hint?t.hint:void 0,F(t.notes)])}}),network:d(function(t){let e=[],n="string"==typeof t.path?t.path:"";n&&e.push(n);let r=Array.isArray(t.entries)?t.entries:[];if(0===r.length)e.push("No recent HTTP(s) entries found.");else for(let t of r)e.push(...function(t){let e=f(t)??{},n="string"==typeof e.method?e.method:"HTTP",r="string"==typeof e.url?e.url:"<unknown-url>",o="number"==typeof e.status?` status=${e.status}`:"",a="string"==typeof e.timestamp?`${e.timestamp} `:"",i="number"==typeof e.durationMs?` durationMs=${e.durationMs}`:"",s=[`${a}${n} ${r}${o}${i}`],u="string"==typeof e.headers;return M(s,"headers",e.headers),u||(w(s,"request headers",e.requestHeaders),w(s,"response headers",e.responseHeaders)),M(s,"request",e.requestBody),M(s,"response",e.responseBody),s}(t));return{data:t,text:e.join("\n"),stderr:P([k(t,["active","state","backend","include","scannedLines","matchedLines"]),F(t.notes)])}})};function w(t,e,n){let r=f(n);r&&0!==Object.keys(r).length&&t.push(` ${e}: ${JSON.stringify(r)}`)}function M(t,e,n){"string"==typeof n&&t.push(` ${e}: ${n}`)}function k(t,e){return e.map(e=>void 0!==t[e]&&null!==t[e]?`${e}=${t[e]}`:"").filter(Boolean).join(" ")||void 0}function F(t){if(!Array.isArray(t))return;let e=t.filter(t=>"string"==typeof t&&t.length>0);return e.length>0?e.join("\n"):void 0}function P(t){return t.filter(t=>!!t).join("\n")||void 0}let j={perf:d(function(t){return{data:t,text:function(t){var e,n,r,o;let a,i="xctrace"===(e=t).kind?function(t){var e,n,r,o,a;let i="string"==typeof t.perf?t.perf:void 0,s="string"==typeof(e=t).outPath?e.outPath:"string"==typeof e.reportPath?e.reportPath:void 0;if(i&&s&&"xctrace"===t.kind){let e;return n=s,r="string"==typeof t.mode?t.mode:"capture",o=i,a=t.template,e=[n,`Perf ${r}: ${o}`],"string"==typeof a&&e.push(`Template: ${a}`),e.join("\n")}}(e):function(t){var e;let n,r,o,a=(n=S((e=t).action),r=S(e.kind),o=S(e.type),n&&r&&o?{action:n,kind:r,type:o}:void 0);if(a){let e;return`Perf ${a.action}: ${a.kind} ${a.type}${(e=S(t.state))?` state=${e}`:""}${function(t){let e=S(t.outPath);if(!e)return"";let n=A(t.sizeBytes);return`
2
+ ${e}${void 0!==n?` (${I(n)})`:""}`}(t)}${function(t){let e=f(t.summary),n=f(e?.frameHealth);if(!n||!0!==n.available)return"";let r=A(n.droppedFramePercent),o=A(n.droppedFrameCount),a=A(n.totalFrameCount);return void 0===r||void 0===o||void 0===a?"":`
3
+ Trace frame health: dropped ${O(r)} (${Math.round(o)}/${Math.round(a)} frames)`}(t)}`}}(e);if(i)return i;let s=f(t.artifact);if(s)return function(t){let e="string"==typeof t.kind?t.kind:"memory";if(!1===t.available){let n="string"==typeof t.reason&&t.reason.length>0?t.reason:"not available";return`Memory artifact (${e}): unavailable - ${n}`}let n="string"==typeof t.path?t.path:void 0,r=A(t.sizeBytes),o=void 0===r?"":` (${I(r)})`;return n?`Memory artifact (${e}): ${n}${o}`:`Memory artifact (${e}): captured${o}`}(s);let u=f(t.metrics),d=f(u?.fps),p=(n=u,(a=[function(t){if(t?.available!==!0)return;let e=A(t.usagePercent);return void 0!==e?`CPU ${O(e)}`:void 0}(f(n?.cpu)),function(t){let e;if(t?.available!==!0)return;let n=A(t.residentMemoryKb)??A(t.totalPssKb)??A(t.totalRssKb);return void 0!==n?`memory ${e=n/1024,`${e>=10?Math.round(e):e.toFixed(1)}MB`}`:void 0}(f(n?.memory))].filter(t=>!!t)).length>0?a.join(", "):void 0);if(!d)return B(p,"missing frame metric");if(!1===d.available){return B(p,"string"==typeof(r=d).reason&&r.reason.length>0?r.reason:"not available")}let l=function(t){let e=A(t.droppedFramePercent),n=A(t.droppedFrameCount);if(void 0!==e&&void 0!==n){var r,o,a;return[`dropped ${O(e)}`,(r=n,void 0!==(o=A(t.totalFrameCount))?`(${Math.round(r)}/${Math.round(o)} frames)`:`(${Math.round(r)} dropped frames)`),void 0!==(a=A(t.sampleWindowMs))?`window ${N(a)}`:""].filter(Boolean).join(" ")}}(d);if(!l)return B(p,"missing dropped-frame summary");let h=[`Frame health: ${l}`],$=(Array.isArray(o=d.worstWindows)?o.filter(c):[]).flatMap(t=>{let e=function(t){let e=A(t.startOffsetMs),n=A(t.endOffsetMs),r=A(t.missedDeadlineFrameCount);if(void 0===e||void 0===n||void 0===r)return;let o=A(t.worstFrameMs),a=void 0===o?"":`, worst ${N(o)}`;return`- +${N(e)}-+${N(n)}: ${Math.round(r)} missed-deadline frames${a}`}(t);return e?[e]:[]});return $.length>0&&h.push("Worst windows:",...$),h.join("\n")}(t)}})};function S(t){return"string"==typeof t?t:void 0}function B(t,e){return t?`Performance: ${t}`:`Frame health: unavailable - ${e}`}function A(t){return"number"==typeof t&&Number.isFinite(t)?t:void 0}function O(t){return`${Number.isInteger(t)?t:t.toFixed(1)}%`}function N(t){let e=Math.max(0,Math.round(t));if(e<1e3)return`${e}ms`;let n=Math.round(e/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60),o=n%60;return o>0?`${r}m ${o}s`:`${r}m`}function I(t){if(t<1024)return`${Math.round(t)}B`;let e=t/1024;if(e<1024)return`${e>=10?Math.round(e):e.toFixed(1)}KB`;let n=e/1024;return`${n>=10?Math.round(n):n.toFixed(1)}MB`}let T={record:d(function(t){let e,n="string"==typeof t.outPath?t.outPath:"",r=Array.isArray(e=t.chunks)?e.flatMap(t=>t&&"object"==typeof t?"number"!=typeof t.index||"string"!=typeof t.path?[]:[{index:t.index,path:t.path}]:[]):[];if(r.length<=1){var o,a;let e;return{data:t,text:(o=t,e=[],(a=n)&&e.push(a),"string"==typeof o.sessionStateDir&&e.push(`Session state: ${o.sessionStateDir}`),"string"==typeof o.warning&&e.push(`Warning: ${o.warning}`),"string"==typeof o.overlayWarning&&e.push(`Overlay warning: ${o.overlayWarning}`),e.join("\n"))}}let i=["Recording chunks:"];for(let t of r)i.push(` ${t.index}: ${t.path}`);return"string"==typeof t.telemetryPath&&i.push(`Telemetry: ${t.telemetryPath}`),"string"==typeof t.warning&&i.push(`Warning: ${t.warning}`),"string"==typeof t.overlayWarning&&i.push(`Overlay warning: ${t.overlayWarning}`),{data:t,text:i.join("\n")}})},D={appstate:d(function(t){return{data:t,text:function(t){if("ios"===t.platform){let e=[`Foreground app: ${t.appName??t.appBundleId??"unknown"}`];return t.appBundleId&&e.push(`Bundle: ${t.appBundleId}`),t.source&&e.push(`Source: ${t.source}`),e.join("\n")}if("android"===t.platform){let e=[`Foreground app: ${t.package??"unknown"}`];return t.activity&&e.push(`Activity: ${t.activity}`),e.join("\n")}return null}(t)}}),back:p,home:p,rotate:p,"app-switcher":p,keyboard:d(function(t){if("android"===t.platform&&"status"===t.action){var e;let n=[`Keyboard visible: ${!0===t.visible?"yes":"no"}`,`Input type: ${t.type??t.inputType??"unknown"}`,`Input owner: ${t.inputOwner??"unknown"}`];return t.inputMethodPackage&&n.push(`Input method: ${t.inputMethodPackage}`),t.focusedPackage&&n.push(`Focused package: ${t.focusedPackage}`),t.focusedResourceId&&n.push(`Focused resource: ${t.focusedResourceId}`),n.push(`Next action: ${(e=t.visible,"ime"===t.inputOwner?"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.":!0===e?"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:t,text:n.join("\n")}}return l(t)}),clipboard:d(function(t){return"read"===t.action?{data:t,text:t.text}:l(t)})},C={...v,snapshot:({input:t,result:n})=>{var r;let o;return{data:o=e((r={result:n,raw:t.raw,interactiveOnly:t.interactiveOnly,scope:t.scope,depth:t.depth}).result),jsonData:function(t){let{unchanged:e,...n}=t;return n}(o),stderr:r.result.snapshotDiagnostics?.warning?`${r.result.snapshotDiagnostics.warning}
4
+ `:void 0,text:u(o,{raw:r.raw,flatten:r.interactiveOnly,scoped:"string"==typeof r.scope&&r.scope.trim().length>0,depthLimited:"number"==typeof r.depth})}},wait:p,alert:p,...D,...y,...x,...j,...$,...h,...T,metro:({input:t,result:e})=>{var n;return{data:(n={result:e,action:t.action}).result,text:"reload"===n.action?`Reloaded React Native apps via ${n.result.reloadUrl}`:JSON.stringify(n.result,null,2)}}};function K(t){return C[t.name]?.({input:t.input??{},result:t.result})}export{K as formatCliOutput};