agent-device 0.17.1 → 0.17.3
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.1.apk → agent-device-android-multitouch-helper-0.17.3.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.3.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.1.manifest.json → agent-device-android-multitouch-helper-0.17.3.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.1.apk → agent-device-android-snapshot-helper-0.17.3.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.3.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.1.manifest.json → agent-device-android-snapshot-helper-0.17.3.manifest.json} +6 -6
- package/dist/src/123.js +1 -0
- package/dist/src/1231.js +1 -1
- package/dist/src/1352.js +1 -1
- package/dist/src/221.js +2 -2
- package/dist/src/2403.js +3 -0
- package/dist/src/2415.js +36 -30
- package/dist/src/4778.js +1 -1
- package/dist/src/5611.js +1 -0
- package/dist/src/5827.js +1 -0
- package/dist/src/6088.js +1 -0
- package/dist/src/6133.js +1 -0
- package/dist/src/7556.js +1 -1
- package/dist/src/7847.js +1 -1
- package/dist/src/8806.js +3 -3
- package/dist/src/9010.js +1 -0
- package/dist/src/9238.js +3 -3
- package/dist/src/9471.js +1 -1
- package/dist/src/9542.js +6 -3
- package/dist/src/9616.js +2 -0
- package/dist/src/9818.js +1 -1
- package/dist/src/android-adb.d.ts +12 -6
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +15 -8
- package/dist/src/android.js +5 -5
- package/dist/src/apple.js +1 -1
- package/dist/src/apps.js +10 -10
- package/dist/src/args.js +53 -14
- package/dist/src/batch.d.ts +16 -4
- package/dist/src/batch.js +1 -1
- package/dist/src/cli-output.js +29 -0
- package/dist/src/cli.js +17 -42
- package/dist/src/command-surface.js +1 -1
- package/dist/src/contracts.d.ts +80 -4
- package/dist/src/contracts.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.d.ts +3 -1
- package/dist/src/generic.js +7 -7
- package/dist/src/index.d.ts +250 -79
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/png-worker.d.ts +26 -0
- package/dist/src/internal/png-worker.js +1 -0
- package/dist/src/metro.d.ts +3 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace-recording.js +3 -3
- package/dist/src/remote-config.d.ts +33 -7
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +17 -3
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session.js +8 -11
- package/dist/src/snapshot.js +2 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +14 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +297 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +328 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +121 -172
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +153 -5
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +171 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -10
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +64 -18
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +200 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +406 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +82 -169
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +425 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +77 -6
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +10 -1
- package/ios-runner/README.md +5 -5
- package/ios-runner/RUNNER_PROTOCOL.md +0 -1
- package/package.json +8 -5
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.1.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.1.apk.sha256 +0 -1
- package/dist/src/1998.js +0 -1
- package/dist/src/2805.js +0 -1
- package/dist/src/4057.js +0 -1
- package/dist/src/5310.js +0 -1
- package/dist/src/5792.js +0 -1
- package/dist/src/6085.js +0 -1
- package/dist/src/6232.js +0 -1
- package/dist/src/7455.js +0 -1
- package/dist/src/8020.js +0 -1
- package/dist/src/8502.js +0 -1
- package/dist/src/8699.js +0 -1
- package/dist/src/940.js +0 -1
- package/dist/src/9404.js +0 -1
- package/dist/src/9533.js +0 -1
- package/dist/src/command-metadata.js +0 -1
- /package/dist/src/{1393.js → 3675.js} +0 -0
package/dist/src/args.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{listCliCommandNames as e}from"./
|
|
1
|
+
import{listCliCommandNames as e}from"./6088.js";import{getCliCommandSchema as t,getCommandSchema as o,applyCommandDefaults as a}from"./1352.js";import{parseSourceValue as s,buildPrimaryEnvVarName as n}from"./1010.js";import{AppError as r}from"./9152.js";import{GLOBAL_FLAG_KEYS as i,getFlagDefinition as l,getFlagDefinitions as c}from"./6133.js";function d(e,t){for(let[o,a]of Object.entries(t))void 0!==a&&(e[o]=a);return e}let p=[{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"}],u=["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."],f=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],h=[{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"}],m=["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"],g={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
|
|
|
@@ -47,7 +47,7 @@ Snapshots and refs:
|
|
|
47
47
|
Off-screen summaries are scroll hints; use scroll, not swipe, then snapshot -i.
|
|
48
48
|
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.
|
|
49
49
|
Truncated text/input previews: do not use get text first; expand with snapshot -s @ref (for example snapshot -s @e7), then read the scoped output.
|
|
50
|
-
Rare iOS accessibility gaps: if a row ref is shown disabled/hittable:false and press @ref reports success but no UI change, or a horizontal tab/filter bar is collapsed into one composite/seekbar with no child refs, run agent-device snapshot -i
|
|
50
|
+
Rare iOS accessibility gaps: if a row ref is shown disabled/hittable:false and press @ref reports success but no UI change, or a horizontal tab/filter bar is collapsed into one composite/seekbar with no child refs, run agent-device snapshot -i --json to read rects, compute the target center, press x y, then diff snapshot -i. Coordinates are fallback-only; document why you used them.
|
|
51
51
|
|
|
52
52
|
Selectors:
|
|
53
53
|
Use selectors as positional targets: id="field-email" or label="Allow".
|
|
@@ -66,7 +66,7 @@ Text entry:
|
|
|
66
66
|
Empty replacement is not a supported clear-field command: do not plan fill <target> "" or fill <target> ''. Prefer a visible clear/reset control; if the app exposes none, report the tool gap instead of inventing a clear command.
|
|
67
67
|
Debounced field with no result selector: agent-device wait 1000. Keyboard read-only: keyboard status/get. Blocked control: try keyboard dismiss when supported.
|
|
68
68
|
On iOS, prefer keyboard dismiss before manually pressing visible Done; the runner can use safe native keyboard controls and still reports unsupported layouts explicitly. If it returns UNSUPPORTED_OPERATION, prefer a visible app dismiss control, or use back --system only when system navigation is an acceptable side effect.
|
|
69
|
-
|
|
69
|
+
Use plain fill/type first for ordinary login and form fields. If an iOS debounced or search-as-you-type field actually drops characters, or must receive incremental updates, retry with --delay-ms before trying clipboard paste; --delay-ms intentionally paces character entry.
|
|
70
70
|
iOS Allow Paste prompt cannot be exercised under XCUITest. To test paste-driven app behavior, prefill first with agent-device clipboard write "some text"; test the system prompt manually.
|
|
71
71
|
Android Gboard handwriting/stylus UI can capture text in an IME-owned input instead of the app field. If fill reports that input was captured by the keyboard/IME, use the diagnostic targetInput/actualInput details, inspect keyboard status/get if needed, and switch or disable handwriting outside the command plan before retrying. Do not keep retrying fill/type against the same field while the IME owns focus.
|
|
72
72
|
Android text entry is owned by agent-device: provider-native text injection when available, then chunk-safe ASCII shell input. Do not switch to raw adb, clipboard, or paste as an agent fallback. If non-ASCII is unsupported in the current backend, report the tool/device gap.
|
|
@@ -114,7 +114,7 @@ Validation and evidence:
|
|
|
114
114
|
If task says snapshot, use snapshot. If it asks visual evidence, use screenshot.
|
|
115
115
|
Icon/tappable visual proof: screenshot --overlay-refs. Flag is --overlay-refs.
|
|
116
116
|
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.
|
|
117
|
-
Startup/CPU/memory/frame first pass: perf metrics --json (bare perf and metrics are aliases). Focused frame/jank health: perf frames --json. Replay maintenance: replay -u ./flow.ad.
|
|
117
|
+
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
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.
|
|
119
119
|
Stable known flow: batch ./steps.json, not workflow batch.
|
|
120
120
|
Inline batch JSON example:
|
|
@@ -176,6 +176,18 @@ Network:
|
|
|
176
176
|
Use this instead of logs path when the question is request/response metadata.
|
|
177
177
|
network log is a supported alias, but network dump --include headers is the clearest plan form. Do not write network log headers.
|
|
178
178
|
|
|
179
|
+
Crash symbolication:
|
|
180
|
+
Crash routing:
|
|
181
|
+
Use logs when you need the lead-up timeline before a failure.
|
|
182
|
+
Use debug symbols when you have crash.ips/crash.log plus a matching dSYM/build directory and need the failing frame.
|
|
183
|
+
Use Xcode/LLDB when you need live state, breakpoints, variables, memory, or stepping.
|
|
184
|
+
Use debug symbols when you already have an Apple crash artifact and local dSYMs and need the failing code path, not a full log dump:
|
|
185
|
+
agent-device debug symbols --artifact crash.log --dsym MyApp.dSYM --out crash-symbolicated.log
|
|
186
|
+
agent-device debug symbols --artifact crash.ips --search-path ./build --out crash-symbolicated.ips
|
|
187
|
+
debug is intentionally narrow. Do not use it for logs, network evidence, performance samples, recordings, traces, or React Native internals.
|
|
188
|
+
Apple support matches crash Binary Images / IPS usedImages UUIDs against dwarfdump --uuid output from .dSYM bundles, then writes a symbolicated artifact path and compact crash report: app/thread, exception or termination, top symbolicated frames, and first-frame finding. This is better than pasting crash logs because it keeps agent context small while preserving the artifact on disk for inspection.
|
|
189
|
+
Android Java/R8 mapping.txt and native ndk-stack/addr2line symbolication are not in this first debug symbols workflow; capture crash evidence with logs and use the Android toolchain externally for now.
|
|
190
|
+
|
|
179
191
|
Alerts:
|
|
180
192
|
Native and platform dialogs:
|
|
181
193
|
agent-device alert wait 3000
|
|
@@ -197,6 +209,33 @@ Diagnostics and traces:
|
|
|
197
209
|
agent-device press 'id="load-diagnostics"'
|
|
198
210
|
agent-device trace stop ./traces/diagnostics.trace
|
|
199
211
|
The trace path is positional. Do not use --path for trace start or trace stop.
|
|
212
|
+
Use perf xctrace only for Apple native CPU/profile or Animation Hitches artifacts:
|
|
213
|
+
agent-device perf cpu profile start --kind xctrace --template "Time Profiler" --out ./artifacts/app.trace
|
|
214
|
+
agent-device perf cpu profile stop --kind xctrace --out ./artifacts/app.trace
|
|
215
|
+
agent-device perf cpu profile report --kind xctrace --out ./artifacts/app-profile.json
|
|
216
|
+
agent-device perf trace start --kind xctrace --template "Animation Hitches" --out ./artifacts/hitches.trace
|
|
217
|
+
agent-device perf trace stop --kind xctrace --out ./artifacts/hitches.trace
|
|
218
|
+
perf xctrace returns artifact paths and compact metadata only. Do not dump .trace contents into context.
|
|
219
|
+
For Android native CPU/trace evidence, use perf artifacts instead of raw adb/simpleperf/perfetto output:
|
|
220
|
+
agent-device perf cpu profile start --kind simpleperf --out /tmp/cpu.perf.data
|
|
221
|
+
agent-device perf cpu profile stop --kind simpleperf
|
|
222
|
+
agent-device perf cpu profile report --kind simpleperf --out /tmp/cpu-report.json
|
|
223
|
+
agent-device perf trace start --kind perfetto --out /tmp/app.perfetto-trace
|
|
224
|
+
agent-device perf trace stop --kind perfetto
|
|
225
|
+
Treat native perf output as the agent evidence: for example, state=stopped, outPath=/tmp/app.perfetto-trace, sizeBytes=5392410, method=adb-shell-perfetto. The 5.3 MB raw trace stays in the artifact.
|
|
226
|
+
|
|
227
|
+
Memory diagnostics:
|
|
228
|
+
Use perf memory when the symptom is leak/growth/OOM suspicion and you need agent-readable evidence.
|
|
229
|
+
agent-device perf memory sample --json
|
|
230
|
+
agent-device perf memory snapshot --kind android-hprof --out ./artifacts/app.hprof
|
|
231
|
+
agent-device perf memory snapshot --kind memgraph --out ./artifacts/app.memgraph
|
|
232
|
+
Example sample shape:
|
|
233
|
+
{"metrics":{"memory":{"available":true,"totalPssKb":562958,"totalRssKb":570304,"topConsumers":[{"name":"Dalvik Heap","pssKb":213456}]}}}
|
|
234
|
+
Example default snapshot output:
|
|
235
|
+
Memory artifact (android-hprof): /tmp/app.hprof (42MB)
|
|
236
|
+
Prefer perf memory sample over raw dumpsys/leaks output for first-pass agent diagnosis: it keeps arrays bounded, preserves the same memory source as perf metrics, and returns only memory data instead of startup/CPU/frame noise.
|
|
237
|
+
Prefer perf memory snapshot over printing heap/memgraph data: snapshots return path, size, kind, method, and support metadata while the large artifact stays on disk for external inspection.
|
|
238
|
+
Unsupported platforms return artifact.available=false with reason/hint; do not pretend a heap or memgraph was captured.
|
|
200
239
|
|
|
201
240
|
Stabilizers:
|
|
202
241
|
Android animation-sensitive flows:
|
|
@@ -449,37 +488,37 @@ Rules:
|
|
|
449
488
|
Prefer refs for exploration and selectors for deterministic replay.
|
|
450
489
|
Use logs, network, screenshot --overlay-refs, trace, perf metrics, perf frames, or react-devtools only when they add evidence to a specific issue.
|
|
451
490
|
Never delete screenshots, videos, traces, or report artifacts during a session.
|
|
452
|
-
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function v(e){let t=e.endsWith("?"),o=t?e.slice(0,-1):e;return t?`[${o}]`:`<${o}>`}function
|
|
491
|
+
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function v(e){let t=e.endsWith("?"),o=t?e.slice(0,-1):e;return t?`[${o}]`:`<${o}>`}function b(e){return c().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function w(e,t){return y(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function y(e,t){if(0===t.length)return`${e}
|
|
453
492
|
(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 k(e,t){return 0===t.length?`${e}
|
|
454
|
-
(none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let x=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),
|
|
493
|
+
(none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let x=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),A=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),I=function(){let o=new Map;for(let e of c()){let t=o.get(e.key);t?t.push(e):o.set(e.key,[e])}let a=new Map;for(let e of i)a.set(e,new Set(["*"]));for(let o of e())for(let e of t(o).allowedFlags??[]){let t=a.get(e);t&&t.has("*")||(t?t.add(o):a.set(e,new Set([o])))}return[...o.entries()].map(([e,t])=>({key:e,flagDefinitions:t,config:{enabled:!x.has(e),key:e},env:{names:A.has(e)?[]:[n(e)]},supportsCommand(t){let o=a.get(e);return!!o&&(!!o.has("*")||!!t&&o.has(t))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),R=new Map(I.map(e=>[e.key,e]));function S(e){return R.get(e)}function U(e){return I.filter(t=>t.config.enabled&&t.supportsCommand(e))}function N(e,t){return S(e)?.supportsCommand(t)??!1}function D(e,t,o,a){return s(function(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let o=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===o.type){let t=o.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...o,setValue:void 0,enumValues:t}}return o}(e),t,o,a)}function E(e){let t={json:!1,help:!1,version:!1},a=null,s=[],n=[],i=!0;for(let u=0;u<e.length;u+=1){var c,d,p;let f=e[u];if(i&&"--"===f){i=!1;continue}if(!i){a?s.push(f):a=P(f);continue}let h=f.startsWith("--"),m=f.startsWith("-")&&f.length>1;if(!h&&!m){a?s.push(f):a=P(f);continue}let[g,v]=h?O(f):[f,void 0];if(c=a,"-c"===g&&("snapshot"===c||"diff"===c))continue;let b=l(g);if(d=a,p=b,"react-devtools"===d&&(!p||!N(p.key,d))){s.push(f);continue}if(!b){if(function(e,t,a){var s;if(s=a,!/^-\d+(\.\d+)?$/.test(s)||!e)return!1;let n=o(e);if(!n||n.allowsExtraPositionals)return!0;let r=n.positionalArgs??[];return 0!==r.length&&(t.length<r.length||r.some(e=>e.includes("?")))}(a,s,f)){a?s.push(f):a=f;continue}throw new r("INVALID_ARGS",`Unknown flag: ${g}`)}let w=function(e,t,o,a){if(void 0!==e.setValue){if(void 0!==o)throw new r("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==o)throw new r("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==o){if(0===o.trim().length)throw new r("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:o,consumeNext:!1}}return void 0===a||L(a)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(a)?{value:!0,consumeNext:!1}:{value:a,consumeNext:!0}}let s=o??a;if(void 0===s||void 0===o&&L(s))throw new r("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:s,consumeNext:void 0===o};if("enum"===e.type){if(!e.enumValues?.includes(s))throw new r("INVALID_ARGS",`Invalid ${_(t)}: ${s}`);return{value:s,consumeNext:void 0===o}}let n=Number(s);if(!Number.isFinite(n)||"number"==typeof e.min&&n<e.min||"number"==typeof e.max&&n>e.max)throw new r("INVALID_ARGS",`Invalid ${_(t)}: ${s}`);return{value:Math.floor(n),consumeNext:void 0===o}}(b,g,v,e[u+1]);w.consumeNext&&(u+=1);let y=t[b.key];if(b.multiple){let e=Array.isArray(y)?[...y,w.value]:void 0===y?[w.value]:[y,w.value];t[b.key]=e}else t[b.key]=w.value;n.push({key:b.key,token:g})}return{command:a,positionals:s,flags:t,warnings:[],providedFlags:n}}function C(e,t){let o=t?.strictFlags??!0,s=[...e.warnings],n=d({json:!1,help:!1,version:!1},t?.defaultFlags??{});d(n,e.flags);let i=e.providedFlags.filter(t=>!N(t.key,e.command));if(i.length>0){var l,c;let t=i.map(e=>e.token),a=(l=e.command,c=t,l?1===c.length?`Flag ${c[0]} is not supported for command ${l}.`:`Flags ${c.join(", ")} are not supported for command ${l}.`:1===c.length?`Flag ${c[0]} requires a command that supports it.`:`Flags ${c.join(", ")} require a command that supports them.`);if(o)throw new r("INVALID_ARGS",a);for(let e of(s.push(a),i))delete n[e.key]}for(let t of Object.keys(n))void 0!==n[t]&&(N(t,e.command)||delete n[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new r("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),a(e.command,n),"batch"===e.command&&1!=+!!n.steps+ +!!n.stepsFile)throw new r("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...o}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:o,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:n,warnings:s})}function O(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function _(e){return e.replace(/^-+/,"")}function L(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?O(e):[e,void 0];return void 0!==l(t)}function T(){let o,a,s,n,r,l,c,d;return o=`agent-device <command> [args] [--json]
|
|
455
494
|
|
|
456
495
|
CLI to control iOS and Android devices for AI agents.
|
|
457
|
-
`,a=y("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,l,c;return a=e,s=t,i=(r=(n=o).endsWith("?"))?n.slice(0,-1):n,c=(l=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${a} ${i}`),r?l?`[${i}]`:c?i:`[${i}]`:c?i:`<${i}>`});return[e,...o].join(" ")}(e,o)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),
|
|
496
|
+
`,a=y("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,l,c;return a=e,s=t,i=(r=(n=o).endsWith("?"))?n.slice(0,-1):n,c=(l=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${a} ${i}`),r?l?`[${i}]`:c?i:`[${i}]`:c?i:`<${i}>`});return[e,...o].join(" ")}(e,o)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),s=w("Flags:",b(i)),n=k("Agent Quickstart:",u),r=y("Agent Workflows:",p),l=k("Configuration:",f),c=y("Environment:",h),d=k("Examples:",m),`${o}
|
|
458
497
|
${a}
|
|
459
498
|
|
|
499
|
+
${s}
|
|
500
|
+
|
|
460
501
|
${n}
|
|
461
502
|
|
|
462
503
|
${r}
|
|
463
504
|
|
|
464
|
-
${i}
|
|
465
|
-
|
|
466
505
|
${l}
|
|
467
506
|
|
|
468
507
|
${c}
|
|
469
508
|
|
|
470
509
|
${d}
|
|
471
|
-
`}function
|
|
510
|
+
`}function M(e){return function(e){var t,a;let s,n=(s=g[e])?`${s.body}
|
|
472
511
|
|
|
473
512
|
Related:
|
|
474
513
|
agent-device help command list and global flags
|
|
475
514
|
agent-device help <command> command-specific flags
|
|
476
515
|
agent-device help workflow normal app automation loop
|
|
477
|
-
`:null;if(
|
|
516
|
+
`:null;if(n)return n;let r=o(e);if(!r)return null;let l=(t=e,(a=r).usageOverride?a.usageOverride:[t,...(a.positionalArgs??[]).map(v),...(a.allowedFlags??[]).flatMap(e=>{var t;return(t=e,c().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),d=b(new Set(r.allowedFlags??[])),p=b(i),u=[];return d.length>0&&u.push(w("Command flags:",d)),u.push(w("Global flags:",p)),`agent-device ${l}
|
|
478
517
|
|
|
479
|
-
${
|
|
518
|
+
${r.helpDescription}
|
|
480
519
|
|
|
481
520
|
Usage:
|
|
482
|
-
agent-device ${
|
|
521
|
+
agent-device ${l}
|
|
483
522
|
|
|
484
523
|
${u.join("\n\n")}
|
|
485
|
-
`}(
|
|
524
|
+
`}(P(e))}function P(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}export{T as usage,C as finalizeParsedArgs,U as getConfigurableOptionSpecs,S as getOptionSpec,d as mergeDefinedFlags,D as parseOptionValueFromSource,E as parseRawArgs,M as usageForCommand};
|
package/dist/src/batch.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare type BatchStepResult = {
|
|
|
22
22
|
|
|
23
23
|
export declare function buildBatchStepFlags(parentFlags: BatchFlags | Record<string, unknown> | undefined, stepFlags: DaemonBatchStep['flags'] | Record<string, unknown> | undefined): BatchFlags;
|
|
24
24
|
|
|
25
|
+
declare const DAEMON_LOCK_POLICIES: readonly ["reject", "strip"];
|
|
26
|
+
|
|
25
27
|
declare type DaemonArtifact = {
|
|
26
28
|
field: string;
|
|
27
29
|
artifactId?: string;
|
|
@@ -66,7 +68,7 @@ declare type DaemonInstallSource = {
|
|
|
66
68
|
artifactName: string;
|
|
67
69
|
}));
|
|
68
70
|
|
|
69
|
-
declare type DaemonLockPolicy =
|
|
71
|
+
declare type DaemonLockPolicy = (typeof DAEMON_LOCK_POLICIES)[number];
|
|
70
72
|
|
|
71
73
|
declare type DaemonRequest = {
|
|
72
74
|
token?: string;
|
|
@@ -88,7 +90,7 @@ declare type DaemonRequestMeta = {
|
|
|
88
90
|
leaseId?: string;
|
|
89
91
|
leaseTtlMs?: number;
|
|
90
92
|
leaseBackend?: LeaseBackend;
|
|
91
|
-
sessionIsolation?:
|
|
93
|
+
sessionIsolation?: SessionIsolationMode;
|
|
92
94
|
uploadedArtifactId?: string;
|
|
93
95
|
clientArtifactPaths?: Record<string, string>;
|
|
94
96
|
installSource?: DaemonInstallSource;
|
|
@@ -96,7 +98,7 @@ declare type DaemonRequestMeta = {
|
|
|
96
98
|
materializedPathRetentionMs?: number;
|
|
97
99
|
materializationId?: string;
|
|
98
100
|
lockPolicy?: DaemonLockPolicy;
|
|
99
|
-
lockPlatform?:
|
|
101
|
+
lockPlatform?: PlatformSelector;
|
|
100
102
|
requestProgress?: 'replay-test';
|
|
101
103
|
};
|
|
102
104
|
|
|
@@ -116,7 +118,9 @@ export declare const DEFAULT_BATCH_MAX_STEPS = 100;
|
|
|
116
118
|
|
|
117
119
|
export declare const INHERITED_PARENT_FLAG_KEYS: readonly ["platform", "target", "device", "udid", "serial", "verbose", "out"];
|
|
118
120
|
|
|
119
|
-
declare
|
|
121
|
+
declare const LEASE_BACKENDS: readonly ["ios-simulator", "ios-instance", "android-instance"];
|
|
122
|
+
|
|
123
|
+
declare type LeaseBackend = (typeof LEASE_BACKENDS)[number];
|
|
120
124
|
|
|
121
125
|
export declare type NormalizedBatchStep = {
|
|
122
126
|
command: string;
|
|
@@ -125,8 +129,16 @@ export declare type NormalizedBatchStep = {
|
|
|
125
129
|
runtime?: unknown;
|
|
126
130
|
};
|
|
127
131
|
|
|
132
|
+
declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "apple"];
|
|
133
|
+
|
|
134
|
+
declare type PlatformSelector = (typeof PLATFORM_SELECTORS)[number];
|
|
135
|
+
|
|
128
136
|
export declare function runBatch(req: BatchRequest, sessionName: string, invoke: BatchInvoke): Promise<DaemonResponse>;
|
|
129
137
|
|
|
138
|
+
declare const SESSION_ISOLATION_MODES: readonly ["none", "tenant"];
|
|
139
|
+
|
|
140
|
+
declare type SessionIsolationMode = (typeof SESSION_ISOLATION_MODES)[number];
|
|
141
|
+
|
|
130
142
|
declare type SessionRuntimeHints = {
|
|
131
143
|
platform?: 'ios' | 'android';
|
|
132
144
|
metroHost?: string;
|
package/dist/src/batch.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var _=100;export{BATCH_BLOCKED_COMMANDS,INHERITED_PARENT_FLAG_KEYS
|
|
1
|
+
var _=100;export{BATCH_BLOCKED_COMMANDS,INHERITED_PARENT_FLAG_KEYS}from"./6088.js";export{buildBatchStepFlags,runBatch,validateAndNormalizeBatchSteps}from"./1231.js";export{_ as DEFAULT_BATCH_MAX_STEPS};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import e from"node:path";import{styleText as t}from"node:util";import{buildMobileSnapshotPresentation as n,serializeOpenResult as r,serializeSnapshotResult as i,serializeSessionListEntry as o,readCommandMessage as a,serializeDeployResult as s,serializeCloseResult as u,displayNodeLabel as l,serializeInstallFromSourceResult as d,serializeDevice as f}from"./6133.js";import{normalizeError as p,AppError as c}from"./9152.js";import{buildSnapshotDisplayLines as h,formatSnapshotLine as $}from"./5827.js";function g(e){return({result:t})=>e(t)}let m=g(y);function y(e){return{data:e,text:a(e)}}function x(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function v(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}let b={batch:g(function(e){let t="number"==typeof e.total?e.total:0,n="number"==typeof e.executed?e.executed:0,r="number"==typeof e.totalDurationMs?e.totalDurationMs:void 0,i=[`Batch completed: ${n}/${t} steps${void 0!==r?` in ${r}ms`:""}`];for(let t of Array.isArray(e.results)?e.results:[]){let e=function(e){let t=x(e);if(!t)return;let n="number"==typeof t.step?t.step:void 0,r="string"==typeof t.command?t.command:"step",i=!1!==t.ok,o=function(e,t,n){var r;return t?a(x(e.data))??n:(r=x(e.error),("string"==typeof r?.message&&r.message.length>0?r.message:null)??n)}(t,i,r),s=void 0!==n?`${n}. `:"- ",u="number"==typeof t.durationMs?t.durationMs:void 0,l=void 0!==u?` (${u}ms)`:"";return`${s}${i?"OK":"FAILED"} ${o}${l}`}(t);e&&i.push(e)}return{data:e,text:i.join("\n")}})};function w(e){return e.width>0&&e.height>0}function C(e,t){return!!e&&!!t&&e.x>=t.x-2&&e.y>=t.y-2&&e.x+e.width<=t.x+t.width+2&&e.y+e.height<=t.y+t.height+2}function M(e){return"number"!=typeof e.parentIndex}function S(e){let t=(e.type??"").toLowerCase(),n=(e.identifier??"").trim().toLowerCase();return t.includes("edittext")||t.includes("textfield")||"composer"===n}function k(e){let t=(e.type??"").toLowerCase();return t.includes("scroll")||t.includes("list")||t.includes("recyclerview")}function P(e){var t;let n=l(e);if(!n||n!==e.identifier?.trim()||(t=n,!/^[\w.]+:id\/[\w.-]+$/i.test(t)))return n;let r=(e.type??"").toLowerCase();return r.includes("view")||r.includes("layout")||r.includes("image")||r.includes("list")||r.includes("recyclerview")||r.includes("collection")?"":n}function I(e){let t=e.trim().replace(/\s+/g," ").toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function N(e,t){let n=[],r=[t];for(;r.length>0;){let t=r.pop();for(let i of e)i.parentIndex===t&&(n.push(i),r.push(i.index))}return n}function j(e,t,n){let r=[t];for(;r.length>0;){let t=r.pop();if(!n.has(t))for(let i of(n.add(t),e))i.parentIndex!==t||n.has(i.index)||r.push(i.index)}}let A=["button","switch","checkbox","radio"],O=["button","image","textview","view"];function F(e){if(!0===e.hittable||S(e))return!1;let t=(e.type??"").toLowerCase();return t.includes("text")||t.includes("image")||t.includes("icon")}function B(e){if(!e.rect||!w(e.rect)||M(e)||S(e))return!1;let t=(e.type??"").toLowerCase();return"text"===t||L(t,O)}function T(e,t){let n=D(e);return D(t)>n?t:e}function D(e){let t=(e.type??"").toLowerCase(),n=0;return L(t,A)?n+=100:t.includes("image")?n+=30:t.includes("textview")||"text"===t?n+=20:t.includes("view")&&(n+=10),!0===e.hittable&&(n+=20),!1!==e.enabled&&(n+=5),n}function L(e,t){return t.some(t=>e.includes(t))}function R(e){process.stdout.write(`${JSON.stringify(e,null,2)}
|
|
2
|
+
`)}function H(e,t={}){let n=e instanceof c?p(e):e;process.stderr.write(`Error (${n.code}): ${n.message}
|
|
3
|
+
`),n.hint&&process.stderr.write(`Hint: ${n.hint}
|
|
4
|
+
`),n.diagnosticId&&process.stderr.write(`Diagnostic ID: ${n.diagnosticId}
|
|
5
|
+
`),n.logPath&&process.stderr.write(`Diagnostics Log: ${n.logPath}
|
|
6
|
+
`),t.showDetails&&n.details&&process.stderr.write(`${JSON.stringify(n.details,null,2)}
|
|
7
|
+
`)}function K(e){return e&&e.summaryLines.length>0?`
|
|
8
|
+
${e.summaryLines.join("\n")}`:""}function _(e){var n;let r=!0===e.baselineInitialized,i=e.summary??{},o=Q(i.additions),a=Q(i.removals),s=Q(i.unchanged),u=Y(),l=V(e),d=l.length>0?`${l.join("\n")}
|
|
9
|
+
`:"";if(r)return`${d}Baseline initialized (${s} lines).
|
|
10
|
+
`;let f=(function(e){if(0===e.length)return e;let t=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>"added"===e.kind||"removed"===e.kind).map(e=>e.index);if(0===t.length)return e;let n=Array(e.length).fill(!1);for(let r of t){let t=Math.max(0,r-1),i=Math.min(e.length-1,r+1);for(let e=t;e<=i;e+=1)n[e]=!0}return e.filter((e,t)=>n[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let n="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=n.startsWith(" ")?`+${n}`:`+ ${n}`;return u?t("green",e):e}if("removed"===e.kind){let e=n.startsWith(" ")?`-${n}`:`- ${n}`;return u?t("red",e):e}return u?t("dim",n):n}),p=f.length>0?`${f.join("\n")}
|
|
11
|
+
`:"";if(!u)return`${d}${p}${o} additions, ${a} removals, ${s} unchanged
|
|
12
|
+
`;let c=`${(n=String(o),t("green",n))} additions, ${t("red",String(a))} removals, ${t("dim",String(s))} unchanged`;return`${d}${p}${c}
|
|
13
|
+
`}function z(e){var n,r,i,o;let a,s,u,l,d=Y(),f=!0===e.match,p=e.dimensionMismatch,c=[];return c.push(...function(e,n){if(!0===e.match){let e=n?function(e,n){return t(n,e)}("✓","green"):"✓";return[`${e} Screenshots match.`]}let r=e.dimensionMismatch,i=n?function(e,n){return t(n,e)}("✗","red"):"✗";if(r){let e=r.expected,t=r.actual;return[`${i} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let o=Q(e.differentPixels),a=Q(e.mismatchPercentage),s=0===a&&o>0?"<0.01":String(a),u=`${s}% pixels differ`;return[`${i} ${n?function(e,n){return t(n,e)}(u,"red"):u}`]}(e,d)),c.push(...function(e,n,r){if(n)return[];let i=[];if(e.diffPath){let n=q(e.diffPath),o=r?function(e,n){return t(n,e)}("Diff image:","dim"):"Diff image:",a=r?function(e,n){return t(n,e)}(n,"green"):n;i.push(` ${o} ${a}`)}if(e.currentOverlayPath){let n=q(e.currentOverlayPath),o=r?function(e,n){return t(n,e)}("Current overlay:","dim"):"Current overlay:",a=r?function(e,n){return t(n,e)}(n,"green"):n,s=Q(e.currentOverlayRefCount),u=s>0?` (${s} refs)`:"";i.push(` ${o} ${a}${u}`)}return i}(e,f,d)),f||p||(c.push(...(n=e,r=d,a=Q(n.differentPixels),s=Q(n.totalPixels),u=r?function(e,n){return t(n,e)}(String(a),"red"):String(a),[` ${u} different / ${s} total pixels`])),c.push(...(i=e,o=d,0===(l=function(e){let t=[];for(let n of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),n=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${n}`}(n.texts)} dx=${U(n.xRange)}px dy=${U(n.yRange)}px`);let n=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);n.length>0&&t.push(`non-text controls: ${n.map(E).join("; ")}`);let r=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return r.length>0&&t.push(`non-text boundaries: ${r.map(E).join("; ")}`),t.slice(0,6)}(i)).length?[]:[` ${G("Hints:",o)}`,...l.map(e=>` - ${e}`)])),c.push(...function(e,t){let n=Array.isArray(e.regions)?e.regions:[];if(0===n.length)return[];let r=[` ${G("Changed regions:",t)}`];for(let e of n.slice(0,5))r.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),n=e.rect,r=[` ${e.index}. ${e.location} x=${n.x} y=${n.y} ${n.width}x${n.height}, ${t}% of diff, change=${e.dominantChange}`],i=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);i&&r.push(` ${i}`);let o=e.currentOverlayMatches?.[0];if(o){let e=o.label?` "${o.label}"`:"";r.push(` overlaps @${o.ref}${e}, ${o.regionCoveragePercentage}% of region`)}return r}(e));return r}(e,d)),c.push(...function(e,t){let n=e.ocr?.matches??[];if(0===n.length)return[];let r=n.slice(0,8),i=[` ${G(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${r.length}/${n.length}; px):`,t)}`,` ${G("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of r.entries()){let n=t.delta;i.push(` ${e+1} | ${JSON.stringify(t.text)} | ${J(n.x)},${J(n.y)} | ${J(n.width)},${J(n.height)} | ${W(t.baselineRect)} | ${W(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return i}(e,d)),c.push(...function(e,t){let n=e.nonTextDeltas??[];if(0===n.length)return[];let r=n.slice(0,8),i=[` ${G(`Non-text visual deltas (showing ${r.length}/${n.length}; px):`,t)}`,` ${G("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of r)i.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${W(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return i}(e,d))),`${c.join("\n")}
|
|
14
|
+
`}function W(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function J(e){return e>0?`+${e}`:String(e)}function E(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",n=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${n}`}function U(e){return e.min===e.max?J(e.min):`${J(e.min)}..${J(e.max)}`}function q(t){let n=process.cwd(),r=e.relative(n,t);return""!==r&&(r.startsWith("..")||e.isAbsolute(r))?t:""===r?".":`.${e.sep}${r}`}function Q(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function Y(){let e=process.env.FORCE_COLOR;return"string"==typeof e?"0"!==e:"string"!=typeof process.env.NO_COLOR&&!!process.stdout.isTTY}function G(e,n){return n?t("dim",e):e}function V(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function X(e,t){var n;let r="scroll-area"===(n=e.type)||"list"===n||"collection"===n||"table"===n?n:null;if(!r)return[];let i=[];if(e.node.hiddenContentAbove&&"below"!==t&&i.push(`[content above ${r} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&i.push(`[content below ${r} hidden]`),0===i.length)return[];let o=" ".repeat(e.depth+1);return i.map(e=>`${o}${e}`)}let Z={debug:g(function(e){let t=[e.outPath,e.message];for(let n of(t.push(...function(e){let t=e.crash,n=[`Crash: ${t.appName??"unknown app"}${void 0===t.crashedThread?"":` thread ${t.crashedThread}`}`];for(let e of(t.bundleId&&n.push(`Bundle: ${t.bundleId}`),t.exceptionType&&n.push(`Exception: ${t.exceptionType}`),t.terminationReason&&n.push(`Termination: ${t.terminationReason}`),t.topFrames))n.push(`Frame ${e.index}: ${e.image} ${e.symbol??e.address}`);for(let e of t.findings)n.push(`Finding: ${e}`);return n}(e)),e.matchedImages))t.push(`Matched: ${n.name} ${n.uuid}${n.arch?` ${n.arch}`:""}`);for(let n of e.warnings??[])t.push(`Warning: ${n}`);return{data:e,text:t.join("\n")}})};function ee(e){let t=e.ref??"",n=e.x,r=e.y;return t&&"number"==typeof n&&"number"==typeof r?{data:e,text:`Tapped @${t} (${n}, ${r})`}:y(e)}let et={click:g(ee),press:g(ee),get:({input:e,result:t})=>{var n;let r;return r=(n={result:t,format:e.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)}:y(r)},is:g(function(e){return{data:e,text:`Passed: is ${e.predicate??"assertion"}`}}),find:g(function(e){return"string"==typeof e.text?{data:e,text:e.text}:"boolean"==typeof e.found?{data:e,text:`Found: ${e.found}`}:e.node?{data:e,text:JSON.stringify(e.node,null,2)}:y(e)})};function en(e){return y(s(e))}let er={boot:g(function(e){let t=e.platform??"unknown",n=e.device??e.id??"unknown";return{data:e,text:`Boot ready: ${n} (${t})`}}),shutdown:g(function(e){let t=e.platform??"unknown",n=e.device??e.id??"unknown",r=e.shutdown,i=!!r&&"object"==typeof r&&"success"in r&&!0===r.success;return{data:e,text:`${i?"Shutdown":"Shutdown failed"}: ${n} (${t})`}}),devices:g(function(e){return{data:{devices:e.map(f)},text:e.map(ei).join("\n")}}),apps:({input:e,result:t})=>{var n;return{data:{apps:(n={result:t,appsFilter:e.appsFilter}).result},stderr:"all"===n.appsFilter?"Showing all apps, including system apps.\n":"Showing user-installed apps. Use --all to include system apps.\n",text:n.result.length>0?n.result.join("\n"):"all"===n.appsFilter?"No apps found.":"No user-installed apps found."}},session:g(function(e){if("stateDir"in e)return{data:e,text:e.stateDir};let t={sessions:e.sessions.map(o)};return{data:t,text:JSON.stringify(t,null,2)}}),open:g(function(e){let t=r(e),n=[a(t)].filter(e=>!!e);return"string"==typeof t.sessionStateDir&&n.push(`Session state: ${t.sessionStateDir}`),{data:t,text:n.join("\n")||null}}),close:g(function(e){return y(u(e))}),install:g(en),reinstall:g(en),"install-from-source":g(function(e){return y(d(e))}),prepare:m};function ei(e){let t=e.kind?` ${e.kind}`:"",n=e.target?` target=${e.target}`:"",r="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${n})${r}`}let eo={logs:g(function(e){var t;return{data:e,text:"string"==typeof e.path?e.path:"",stderr:el([es(e,["active","state","backend","sizeBytes"]),(t=e,["started","stopped","marked","cleared","restarted","removedRotatedFiles"].map(e=>{var n,r;return n=e,!0===(r=t[e])?`${n}=true`:"number"==typeof r?`${n}=${r}`:""}).filter(Boolean).join(" ")||void 0),"string"==typeof e.hint?e.hint:void 0,eu(e.notes)])}}),network:g(function(e){let t=[],n="string"==typeof e.path?e.path:"";n&&t.push(n);let r=Array.isArray(e.entries)?e.entries:[];if(0===r.length)t.push("No recent HTTP(s) entries found.");else for(let e of r)t.push(...function(e){let t=x(e)??{},n="string"==typeof t.method?t.method:"HTTP",r="string"==typeof t.url?t.url:"<unknown-url>",i="number"==typeof t.status?` status=${t.status}`:"",o="string"==typeof t.timestamp?`${t.timestamp} `:"",a="number"==typeof t.durationMs?` durationMs=${t.durationMs}`:"",s=[`${o}${n} ${r}${i}${a}`];return ea(s,"headers",t.headers),ea(s,"request",t.requestBody),ea(s,"response",t.responseBody),s}(e));return{data:e,text:t.join("\n"),stderr:el([es(e,["active","state","backend","include","scannedLines","matchedLines"]),eu(e.notes)])}})};function ea(e,t,n){"string"==typeof n&&e.push(` ${t}: ${n}`)}function es(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")||void 0}function eu(e){if(!Array.isArray(e))return;let t=e.filter(e=>"string"==typeof e&&e.length>0);return t.length>0?t.join("\n"):void 0}function el(e){return e.filter(e=>!!e).join("\n")||void 0}let ed={perf:g(function(e){return{data:e,text:function(e){var t,n,r,i;let o,a="xctrace"===(t=e).kind?function(e){var t,n,r,i,o;let a="string"==typeof e.perf?e.perf:void 0,s="string"==typeof(t=e).outPath?t.outPath:"string"==typeof t.reportPath?t.reportPath:void 0;if(a&&s&&"xctrace"===e.kind){let t;return n=s,r="string"==typeof e.mode?e.mode:"capture",i=a,o=e.template,t=[n,`Perf ${r}: ${i}`],"string"==typeof o&&t.push(`Template: ${o}`),t.join("\n")}}(t):function(e){var t;let n,r,i,o=(n=ef((t=e).action),r=ef(t.kind),i=ef(t.type),n&&r&&i?{action:n,kind:r,type:i}:void 0);if(o){let t;return`Perf ${o.action}: ${o.kind} ${o.type}${(t=ef(e.state))?` state=${t}`:""}${function(e){let t=ef(e.outPath);if(!t)return"";let n=ec(e.sizeBytes);return`
|
|
15
|
+
${t}${void 0!==n?` (${eg(n)})`:""}`}(e)}${function(e){let t=x(e.summary),n=x(t?.frameHealth);if(!n||!0!==n.available)return"";let r=ec(n.droppedFramePercent),i=ec(n.droppedFrameCount),o=ec(n.totalFrameCount);return void 0===r||void 0===i||void 0===o?"":`
|
|
16
|
+
Trace frame health: dropped ${eh(r)} (${Math.round(i)}/${Math.round(o)} frames)`}(e)}`}}(t);if(a)return a;let s=x(e.artifact);if(s)return function(e){let t="string"==typeof e.kind?e.kind:"memory";if(!1===e.available){let n="string"==typeof e.reason&&e.reason.length>0?e.reason:"not available";return`Memory artifact (${t}): unavailable - ${n}`}let n="string"==typeof e.path?e.path:void 0,r=ec(e.sizeBytes),i=void 0===r?"":` (${eg(r)})`;return n?`Memory artifact (${t}): ${n}${i}`:`Memory artifact (${t}): captured${i}`}(s);let u=x(e.metrics),l=x(u?.fps),d=(n=u,(o=[function(e){if(e?.available!==!0)return;let t=ec(e.usagePercent);return void 0!==t?`CPU ${eh(t)}`:void 0}(x(n?.cpu)),function(e){let t;if(e?.available!==!0)return;let n=ec(e.residentMemoryKb)??ec(e.totalPssKb)??ec(e.totalRssKb);return void 0!==n?`memory ${t=n/1024,`${t>=10?Math.round(t):t.toFixed(1)}MB`}`:void 0}(x(n?.memory))].filter(e=>!!e)).length>0?o.join(", "):void 0);if(!l)return ep(d,"missing frame metric");if(!1===l.available){return ep(d,"string"==typeof(r=l).reason&&r.reason.length>0?r.reason:"not available")}let f=function(e){let t=ec(e.droppedFramePercent),n=ec(e.droppedFrameCount);if(void 0!==t&&void 0!==n){var r,i,o;return[`dropped ${eh(t)}`,(r=n,void 0!==(i=ec(e.totalFrameCount))?`(${Math.round(r)}/${Math.round(i)} frames)`:`(${Math.round(r)} dropped frames)`),void 0!==(o=ec(e.sampleWindowMs))?`window ${e$(o)}`:""].filter(Boolean).join(" ")}}(l);if(!f)return ep(d,"missing dropped-frame summary");let p=[`Frame health: ${f}`],c=(Array.isArray(i=l.worstWindows)?i.filter(v):[]).flatMap(e=>{let t=function(e){let t=ec(e.startOffsetMs),n=ec(e.endOffsetMs),r=ec(e.missedDeadlineFrameCount);if(void 0===t||void 0===n||void 0===r)return;let i=ec(e.worstFrameMs),o=void 0===i?"":`, worst ${e$(i)}`;return`- +${e$(t)}-+${e$(n)}: ${Math.round(r)} missed-deadline frames${o}`}(e);return t?[t]:[]});return c.length>0&&p.push("Worst windows:",...c),p.join("\n")}(e)}})};function ef(e){return"string"==typeof e?e:void 0}function ep(e,t){return e?`Performance: ${e}`:`Frame health: unavailable - ${t}`}function ec(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function eh(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function e$(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let n=Math.round(t/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60),i=n%60;return i>0?`${r}m ${i}s`:`${r}m`}function eg(e){if(e<1024)return`${Math.round(e)}B`;let t=e/1024;if(t<1024)return`${t>=10?Math.round(t):t.toFixed(1)}KB`;let n=t/1024;return`${n>=10?Math.round(n):n.toFixed(1)}MB`}let em={record:g(function(e){let t,n="string"==typeof e.outPath?e.outPath:"",r=Array.isArray(t=e.chunks)?t.flatMap(e=>e&&"object"==typeof e?"number"!=typeof e.index||"string"!=typeof e.path?[]:[{index:e.index,path:e.path}]:[]):[];if(r.length<=1){var i,o;let t;return{data:e,text:(i=e,t=[],(o=n)&&t.push(o),"string"==typeof i.sessionStateDir&&t.push(`Session state: ${i.sessionStateDir}`),"string"==typeof i.warning&&t.push(`Warning: ${i.warning}`),"string"==typeof i.overlayWarning&&t.push(`Overlay warning: ${i.overlayWarning}`),t.join("\n"))}}let a=["Recording chunks:"];for(let e of r)a.push(` ${e.index}: ${e.path}`);return"string"==typeof e.telemetryPath&&a.push(`Telemetry: ${e.telemetryPath}`),"string"==typeof e.warning&&a.push(`Warning: ${e.warning}`),"string"==typeof e.overlayWarning&&a.push(`Overlay warning: ${e.overlayWarning}`),{data:e,text:a.join("\n")}})},ey={appstate:g(function(e){return{data:e,text:function(e){if("ios"===e.platform){let t=[`Foreground app: ${e.appName??e.appBundleId??"unknown"}`];return e.appBundleId&&t.push(`Bundle: ${e.appBundleId}`),e.source&&t.push(`Source: ${e.source}`),t.join("\n")}if("android"===e.platform){let t=[`Foreground app: ${e.package??"unknown"}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join("\n")}return null}(e)}}),back:m,home:m,rotate:m,"app-switcher":m,keyboard:g(function(e){if("android"===e.platform&&"status"===e.action){var t;let n=[`Keyboard visible: ${!0===e.visible?"yes":"no"}`,`Input type: ${e.type??e.inputType??"unknown"}`,`Input owner: ${e.inputOwner??"unknown"}`];return e.inputMethodPackage&&n.push(`Input method: ${e.inputMethodPackage}`),e.focusedPackage&&n.push(`Focused package: ${e.focusedPackage}`),e.focusedResourceId&&n.push(`Focused resource: ${e.focusedResourceId}`),n.push(`Next action: ${(t=e.visible,"ime"===e.inputOwner?"Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.":!0===t?"Keyboard is visible and focused input appears app-owned; fill/type can proceed.":"Keyboard is hidden; focus an app field before type, or use fill with a concrete target.")}`),{data:e,text:n.join("\n")}}return y(e)}),clipboard:g(function(e){return"read"===e.action?{data:e,text:e.text}:y(e)})},ex={...er,snapshot:({input:e,result:t})=>{var r;let o;return{data:o=i((r={result:t,raw:e.raw,interactiveOnly:e.interactiveOnly,scope:e.scope,depth:e.depth}).result),jsonData:function(e){let{unchanged:t,...n}=e;return n}(o),text:function(e,t={}){var r,i,o,a;let s,u,d,f,p,c=e.nodes,g=Array.isArray(c)?c:[],m="string"==typeof e.backend?e.backend:void 0,y=function(e,t,n){let r;if(n.raw||!((r=e.androidSnapshot)&&"object"==typeof r&&"android-helper"===r.backend))return{nodes:t,filteredCount:0};let i=function(e){var t,n;if(0===e.length)return e;let r=new Set,i=new Map,o=new Map(e.map(e=>[e.index,e]));(function(e,t){for(let n of e)!n.rect||w(n.rect)||M(n)||j(e,n.index,t)})(e,r),function(e,t,n,r){for(let i of e){if(n.has(i.index)||i.rect||M(i))continue;let o=function(e,t,n){let r=e;for(;"number"==typeof r.parentIndex;){let e=t.get(r.parentIndex);if(!e)break;if(n(e))return e;r=e}return null}(i,t,k);o&&function(e,t,n){if(!n)return;let r=e.get(t.index)??t;e.set(t.index,{...r,hiddenContentAbove:!0===r.hiddenContentAbove||"above"===n||void 0,hiddenContentBelow:!0===r.hiddenContentBelow||"below"===n||void 0})}(r,o,function(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&w(t.rect)).map(e=>e.index);return 0===n.length?null:e.index<Math.min(...n)?"above":e.index>Math.max(...n)?"below":null}(i,e)),j(e,i.index,n)}}(e,o,r,i);for(let n of e){if(r.has(n.index)||!(!0===(t=n).hittable&&!S(t)&&t.rect&&w(t.rect)&&0===P(t).trim().length))continue;let o=function(e,t,n){let r=[],i=[],o=new Set;for(let a of e){if(n.has(a.index)||!F(a)||!C(a.rect,t.rect))continue;let e=P(a).trim().replace(/\s+/g," "),s=I(e);i.push(a.index),!e||!s||o.has(s)||(o.add(s),r.push(e))}return{label:r.join(", "),removableIndexes:i}}(N(e,n.index),n,r);if(o.label)for(let t of(i.set(n.index,{...n,...i.get(n.index),label:o.label}),o.removableIndexes))j(e,t,r)}for(let t of e){if(r.has(t.index)||!(!0===(n=t).hittable&&!S(n)&&n.rect&&w(n.rect)&&I(P(n))))continue;let i=I(P(t));if(!i)continue;let o=N(e,t.index).filter(e=>!r.has(e.index)&&function(e,t,n){if(!B(t)||!C(t.rect,e.rect))return!1;let r=I(P(t));return!!(r&&n!==r&&n.includes(r))}(t,e,i));for(let t of o.filter(F))j(e,t.index,r);let a=o.filter(e=>!F(e)),s=new Set(a.map(e=>I(P(e))).filter(e=>!!e));if(!(a.length<2)&&!(s.size<2))for(let t of a)j(e,t.index,r)}let a=new Map;for(let t of e){if(r.has(t.index)||!B(t))continue;let n=I(P(t));if(!n)continue;let o=a.get(n);if(o&&function(e,t,n){var r,i,o,a;return!n.has(e.index)&&(r=e.rect,i=t.rect,!r||!i||Math.abs(r.y+r.height/2-(i.y+i.height/2))<=Math.max(r.height,i.height,1))&&(o=e,a=t,(o.parentIndex===a.parentIndex?3>=Math.abs(o.index-a.index):o.parentIndex!==a.index&&a.parentIndex!==o.index&&1>=Math.abs((o.depth??0)-(a.depth??0))&&2>=Math.abs(o.index-a.index))||function(e,t){let n=e.parentIndex===t.index?t:t.parentIndex===e.index?e:null,r=n?.index===e.index?t:n?.index===t.index?e:null;return!!n&&!!r&&T(n,r).index===n.index}(e,t))}(o,t,r)){let s=function(e,t,n,r,i){var o,a,s;let u=T(t,n),l=u.index===t.index?n:t,d=(l.type??"").toLowerCase().includes("image")?"has image":null,f=i.get(u.index)??u,p=i.get(l.index)?.presentationHints??l.presentationHints;return i.set(u.index,{...f,presentationHints:(o=f.presentationHints,a=p,s=d,[...new Set([...Array.isArray(o)?o:[],...Array.isArray(a)?a:[],...s?[s]:[]])])}),j(e,l.index,r),i.get(u.index)??u}(e,o,t,r,i);a.set(n,s);continue}a.set(n,t)}return e.filter(e=>!r.has(e.index)).map(e=>i.get(e.index)??e)}(t);return{nodes:i,filteredCount:t.length-i.length}}(e,g,t),x=(s="string"==typeof(r=e).appName?r.appName:void 0,u="string"==typeof r.appBundleId?r.appBundleId:void 0,d=[],s&&d.push(`Page: ${s}`),u&&d.push(`App: ${u}`),d.length>0?`${d.join("\n")}
|
|
17
|
+
`:""),v=function(e,t,n,r={nodes:t,filteredCount:0}){let i=V(e);if(!e.snapshotQuality){let e=function(e,t){if(!0===t.scoped||!0===t.depthLimited||e.length>3)return null;let n=1===e.length?"node":"nodes";return`Hint: sparse accessibility snapshot returned ${e.length} ${n}; snapshot state is invalid or unavailable for this screen. Use plain screenshot, not screenshot --overlay-refs, as visual truth. If screenshot shows the Home Screen or another app, run open for this app again first. Then navigate away with coordinates if needed and retry snapshot -i on the next screen.`}(t,n);e&&i.push(e)}!n.raw&&r.filteredCount>0&&i.push(`Collapsed ${r.filteredCount} Android helper node${1===r.filteredCount?"":"s"} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let o=r.filteredCount>0?r.nodes:t;return!n.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??"").toLowerCase(),r=function(e){var t;let n=e.trim().replace(/\s+/g," ").toLowerCase();return!n||(t=n,/\S+@\S+\.\S+/.test(t))?null:n}(l(n));if(!r)continue;let i=`${e}|${r}`,o=t.get(i)??[];o.push(n),t.set(i,o)}let n=0;for(let e of t.values())!(e.length<=1)&&function(e){for(let r=0;r<e.length;r+=1)for(let i=r+1;i<e.length;i+=1){var t,n;if(t=e[r]?.rect,n=e[i]?.rect,!t||!n||!(t.x+t.width<=n.x+.5||n.x+n.width<=t.x+.5||t.y+t.height<=n.y+.5||n.y+n.height<=t.y+.5))return!0}return!1}(e)&&(n+=e.length);return n>=8}(o)&&i.push("Warning: possible repeated nav subtree detected."),i}(e,g,t,y),b=v.length>0?`${v.join("\n")}
|
|
18
|
+
`:"",A=t.raw?null:(f=e.unchanged)&&"object"==typeof f?"number"!=typeof f.ageMs||"number"!=typeof f.nodeCount?null:{ageMs:f.ageMs,nodeCount:f.nodeCount,interactiveOnly:!0===f.interactiveOnly||void 0,scope:"string"==typeof f.scope?f.scope:void 0}:null;if(A){let e;return`${x}${b}${e=function(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${(Math.round(e/100)/10).toFixed(1)}s`;let t=e/6e4;return t<60?`${(Math.round(10*t)/10).toFixed(1)}m`:`${(Math.round(t/60*10)/10).toFixed(1)}h`}((i=A).ageMs),i.scope?`Scoped snapshot unchanged for scope "${i.scope}" since previous read ${e} ago.
|
|
19
|
+
Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`:i.interactiveOnly?`Interactive snapshot unchanged since previous read ${e} ago.
|
|
20
|
+
${i.nodeCount} visible nodes are unchanged. Previous @e refs are still valid. Use find/get/is for a targeted query, or --force-full to re-emit.`:`Snapshot unchanged since previous read ${e} ago.
|
|
21
|
+
Refs from the previous snapshot are still valid. Use --force-full to re-emit the tree, or use find/get/is for a targeted query.`}
|
|
22
|
+
`}let O=t.raw||"macos-helper"===m?null:n(y.nodes),D=!!e.truncated,L=O?.nodes??g,R=t.raw||"macos-helper"===m?null:function(e,t,n,r,i=0){let o,a=(o=e.visibility)&&"object"==typeof o&&"boolean"==typeof o.partial&&"number"==typeof o.visibleNodeCount&&"number"==typeof o.totalNodeCount&&Array.isArray(o.reasons)?{partial:o.partial,visibleNodeCount:o.visibleNodeCount,totalNodeCount:o.totalNodeCount,reasons:o.reasons.filter(e=>"string"==typeof e)}:null;if(0===i&&a)return a;let s=(t?.hiddenCount??0)+i,u=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return s>0?{partial:!0,visibleNodeCount:n,totalNodeCount:Math.max(r,a?.totalNodeCount??r),reasons:[...new Set([...a?.reasons??[],"offscreen-nodes"])]}:a||(u?{partial:!0,visibleNodeCount:n,totalNodeCount:n,reasons:[]}:null)}(e,O,L.length,g.length,y.filteredCount),H=(o=g.length,a=R,p=D?" (truncated)":"",a?.partial?a.totalNodeCount>a.visibleNodeCount?`Snapshot: ${a.visibleNodeCount} visible nodes (${a.totalNodeCount} total)${p}`:`Snapshot: ${a.visibleNodeCount} visible nodes${p}`:`Snapshot: ${o} nodes${p}`);return 0===g.length?`${x}${H}
|
|
23
|
+
${b}`:t.raw?`${x}${H}
|
|
24
|
+
${b}${g.map(e=>JSON.stringify(e)).join("\n")}
|
|
25
|
+
`:t.flatten?`${x}${H}
|
|
26
|
+
${b}${h(L,{summarizeTextSurfaces:!0}).flatMap(e=>[$(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...X({...e,depth:0})]).join("\n")}${K(O)}
|
|
27
|
+
`:`${x}${H}
|
|
28
|
+
${b}${(function(e){let t=[],n=[],r=new Map(e.map(e=>[e.node.index,e.node])),i=e=>{for(var i,o,a;n.length>0&&(!e||(i=e,o=n[n.length-1],a=r,!function(e,t,n){let r=e;for(;"number"==typeof r.parentIndex;){if(r.parentIndex===t.index)return!0;let e=n.get(r.parentIndex);if(!e)break;r=e}return!1}(i.node,o.node,a)&&i.depth<=o.depth));)t.push(...X(n.pop(),"below"))};for(let r of e)i(r),t.push(r.text),t.push(...X(r,"above")),r.node.hiddenContentBelow&&n.push(r);return i(),t})(h(L,{summarizeTextSurfaces:!0})).join("\n")}${K(O)}
|
|
29
|
+
`}(o,{raw:r.raw,flatten:r.interactiveOnly,scoped:"string"==typeof r.scope&&r.scope.trim().length>0,depthLimited:"number"==typeof r.depth})}},wait:m,alert:m,...ey,...et,...eo,...ed,...Z,...b,...em,metro:({input:e,result:t})=>{var n;return{data:(n={result:t,action:e.action}).result,text:"reload"===n.action?`Reloaded React Native apps via ${n.result.reloadUrl}`:JSON.stringify(n.result,null,2)}}};function ev(e){return ex[e.name]?.({input:e.input??{},result:e.result})}export{ev as formatCliOutput,z as formatScreenshotDiffText,_ as formatSnapshotDiffText,H as printHumanError,R as printJson};
|