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.
- package/README.md +3 -3
- 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
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.8.apk.sha256 +1 -0
- 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
- 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
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.8.apk.sha256 +1 -0
- 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
- package/dist/src/2133.js +1 -1
- package/dist/src/2577.js +1 -0
- package/dist/src/2948.js +1 -1
- package/dist/src/4291.js +1 -2
- package/dist/src/4428.js +3 -3
- package/dist/src/4723.js +1 -1
- package/dist/src/5910.js +2 -0
- package/dist/src/6311.js +18 -18
- package/dist/src/7244.js +1 -1
- package/dist/src/8184.js +1 -1
- package/dist/src/8358.js +4 -0
- package/dist/src/9581.js +22 -1
- package/dist/src/9722.js +36 -36
- package/dist/src/9873.js +1 -1
- package/dist/src/9919.js +5 -5
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/batch.d.ts +1 -1
- package/dist/src/cli-help.js +140 -30
- package/dist/src/cli-output.js +4 -4
- package/dist/src/cli.js +28 -17
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/index.d.ts +7 -4
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/provider.js +1 -0
- package/dist/src/record-trace-recording.js +3 -3
- package/dist/src/remote-config.d.ts +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +2 -2
- package/dist/src/session.js +8 -8
- package/dist/src/snapshot.js +1 -1
- package/dist/src/web.js +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +6 -6
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +9 -5
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +0 -2
- package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +44 -8
- package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +59 -16
- package/ios-runner/RUNNER_PROTOCOL.md +1 -1
- package/package.json +5 -2
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.6.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.6.apk.sha256 +0 -1
- package/dist/src/2892.js +0 -4
- package/dist/src/5299.js +0 -1
package/dist/src/cli-help.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as
|
|
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
|
|
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.
|
|
275
|
-
2.
|
|
276
|
-
3.
|
|
277
|
-
4.
|
|
278
|
-
5.
|
|
279
|
-
6.
|
|
280
|
-
7.
|
|
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
|
-
|
|
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.`},
|
|
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("?"),
|
|
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
|
-
`,
|
|
495
|
-
${
|
|
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
|
-
${
|
|
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
|
|
509
|
-
(none)`;let
|
|
510
|
-
(none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function v(e){var t,
|
|
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(
|
|
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
|
-
${
|
|
628
|
+
${u.join("\n\n")}`:"";return`agent-device ${c}
|
|
519
629
|
|
|
520
|
-
|
|
521
|
-
agent-device ${d}
|
|
630
|
+
${i.helpDescription}
|
|
522
631
|
|
|
523
|
-
|
|
632
|
+
Usage:
|
|
633
|
+
agent-device ${c}${m}
|
|
524
634
|
`}export{v as buildCommandUsageText,u as buildUsageText};
|
package/dist/src/cli-output.js
CHANGED
|
@@ -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
|
|
2
|
-
${e}${void 0!==n?` (${
|
|
3
|
-
Trace frame health: dropped ${
|
|
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,...
|
|
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};
|