agent-device 0.21.6 → 0.21.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.6.apk → agent-device-android-ime-helper-0.21.8.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.6.manifest.json → agent-device-android-ime-helper-0.21.8.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.apk → agent-device-android-snapshot-helper-0.21.8.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.manifest.json → agent-device-android-snapshot-helper-0.21.8.manifest.json} +6 -6
  7. package/apple/macos-helper/Package.swift +16 -1
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +47 -0
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +320 -0
  10. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +66 -13
  11. package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickDelivery.swift +116 -0
  12. package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickSchedule.swift +61 -0
  13. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +30 -0
  14. package/apple/macos-helper/Tests/AgentDeviceMacOSInputTests/MouseClickScheduleTests.swift +58 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +4 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -2
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +25 -12
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +56 -1
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -108
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +241 -0
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +29 -0
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +46 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +85 -26
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +134 -117
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +1 -3
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +25 -4
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -1
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +3 -0
  31. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +197 -0
  32. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +30 -4
  33. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +0 -81
  34. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +1 -9
  35. package/dist/src/absence-observation-errors.js +1 -1
  36. package/dist/src/adapter.js +1 -1
  37. package/dist/src/adb-executor.js +2 -2
  38. package/dist/src/adb-failure.js +1 -1
  39. package/dist/src/adb-transport.js +1 -1
  40. package/dist/src/adb.js +1 -1
  41. package/dist/src/agent-browser-lifecycle.js +1 -1
  42. package/dist/src/agent-browser-process-record.js +1 -1
  43. package/dist/src/agent-browser-provider.js +1 -1
  44. package/dist/src/agent-browser-tool.js +1 -1
  45. package/dist/src/agent-device-client.js +2 -2
  46. package/dist/src/ai-sdk.js +1 -1
  47. package/dist/src/alert-runtime.js +1 -1
  48. package/dist/src/android-adb.d.ts +29 -2
  49. package/dist/src/android-adb.js +1 -1
  50. package/dist/src/android-input-ownership.js +1 -1
  51. package/dist/src/android.js +1 -1
  52. package/dist/src/app-catalog.js +1 -1
  53. package/dist/src/app-deployment-resolution.js +1 -1
  54. package/dist/src/app-helpers.js +1 -1
  55. package/dist/src/app-inventory.js +1 -1
  56. package/dist/src/app-launch.js +2 -2
  57. package/dist/src/app-lifecycle.js +2 -2
  58. package/dist/src/app-lifecycle2.js +2 -2
  59. package/dist/src/app-log-files.js +1 -1
  60. package/dist/src/app-log-runtime2.js +3 -3
  61. package/dist/src/app-resolution.js +2 -2
  62. package/dist/src/app-state.js +1 -1
  63. package/dist/src/apple-runner-platform.js +1 -1
  64. package/dist/src/application-lifecycle-interaction.js +1 -1
  65. package/dist/src/archive.js +1 -1
  66. package/dist/src/artifact-download.js +1 -1
  67. package/dist/src/auth-session.js +1 -1
  68. package/dist/src/auth.js +1 -1
  69. package/dist/src/back-mode.js +1 -1
  70. package/dist/src/backend-snapshot-options.js +1 -1
  71. package/dist/src/boot-diagnostics.js +1 -1
  72. package/dist/src/capture-disclosure.js +1 -0
  73. package/dist/src/capture.js +1 -1
  74. package/dist/src/cli-config.js +1 -1
  75. package/dist/src/cli-help.js +18 -2
  76. package/dist/src/cli-output.js +1 -1
  77. package/dist/src/cli.js +4 -4
  78. package/dist/src/click-button.js +1 -1
  79. package/dist/src/client-metro.js +1 -1
  80. package/dist/src/client-types.d.ts +65 -3
  81. package/dist/src/clipboard-shell-response.js +1 -0
  82. package/dist/src/command-schema.js +1 -1
  83. package/dist/src/command-tools.js +4 -2
  84. package/dist/src/command.js +1 -1
  85. package/dist/src/config.js +1 -1
  86. package/dist/src/connection-runtime.js +1 -1
  87. package/dist/src/connection.js +1 -1
  88. package/dist/src/contracts.d.ts +1 -1
  89. package/dist/src/contracts.js +1 -1
  90. package/dist/src/daemon-client-lifecycle.js +1 -1
  91. package/dist/src/daemon.js +1 -1
  92. package/dist/src/debug-symbols-facade.js +1 -1
  93. package/dist/src/device-boot.js +1 -1
  94. package/dist/src/device-claim-inspection.js +1 -1
  95. package/dist/src/device-claim-rule.js +2 -1
  96. package/dist/src/device-input-state.d.ts +5 -5
  97. package/dist/src/device-inventory-context.js +1 -1
  98. package/dist/src/device-rotation.js +1 -1
  99. package/dist/src/device-selection-resolver.js +1 -1
  100. package/dist/src/device-session.js +1 -1
  101. package/dist/src/device-shell.js +1 -0
  102. package/dist/src/device.js +1 -1
  103. package/dist/src/device2.js +1 -1
  104. package/dist/src/devicectl.js +1 -0
  105. package/dist/src/diagnostics.js +1 -1
  106. package/dist/src/dispatch-resolve.js +1 -1
  107. package/dist/src/display-inventory.js +1 -0
  108. package/dist/src/doctor-facade.js +1 -1
  109. package/dist/src/doctor2.js +1 -1
  110. package/dist/src/durable-resource.js +1 -1
  111. package/dist/src/engine-eval-script.js +1 -1
  112. package/dist/src/error.js +1 -1
  113. package/dist/src/exec.js +1 -1
  114. package/dist/src/file.js +1 -1
  115. package/dist/src/find.js +1 -1
  116. package/dist/src/finders.js +1 -1
  117. package/dist/src/format.js +2 -1
  118. package/dist/src/generic.js +1 -1
  119. package/dist/src/gesture-admission.js +1 -1
  120. package/dist/src/gesture-plan.js +1 -1
  121. package/dist/src/gesture-runtime.js +1 -1
  122. package/dist/src/harmonyos.js +1 -1
  123. package/dist/src/hdc.js +1 -1
  124. package/dist/src/helper.js +2 -2
  125. package/dist/src/host.js +1 -0
  126. package/dist/src/human-control-contract.js +1 -1
  127. package/dist/src/human-control.js +1 -1
  128. package/dist/src/index.d.ts +1 -1
  129. package/dist/src/index.js +1 -1
  130. package/dist/src/input-actions.js +1 -1
  131. package/dist/src/input-actions2.js +1 -1
  132. package/dist/src/install-artifact-facade.js +1 -1
  133. package/dist/src/install-source-network-transport.js +1 -1
  134. package/dist/src/install-source2.js +1 -1
  135. package/dist/src/interaction-positionals.js +1 -1
  136. package/dist/src/interaction-ref-policy.js +1 -1
  137. package/dist/src/interaction.js +1 -1
  138. package/dist/src/interaction2.js +1 -1
  139. package/dist/src/interactor-operation-binding.js +1 -0
  140. package/dist/src/interactor-operation-catalog.js +1 -1
  141. package/dist/src/interactor.js +4 -5
  142. package/dist/src/interactor2.js +1 -1
  143. package/dist/src/interactors.js +1 -1
  144. package/dist/src/internal/bin.js +1 -1
  145. package/dist/src/internal/daemon.js +2 -2
  146. package/dist/src/internal/png-worker.d.ts +9 -1
  147. package/dist/src/internal/png-worker.js +1 -1
  148. package/dist/src/internal/run-script-http-child.js +1 -1
  149. package/dist/src/inventory.js +4 -4
  150. package/dist/src/inventory2.js +1 -1
  151. package/dist/src/inventory3.js +2 -2
  152. package/dist/src/inventory5.js +1 -1
  153. package/dist/src/ios-snapshot-acquisition.js +1 -1
  154. package/dist/src/ios-snapshot-runtime.js +1 -1
  155. package/dist/src/ios-target-activation.js +1 -0
  156. package/dist/src/lease-context.js +1 -1
  157. package/dist/src/lease-scope.js +1 -1
  158. package/dist/src/lease.js +1 -1
  159. package/dist/src/limrun-download-file.js +1 -0
  160. package/dist/src/limrun-runtime-dependencies.js +1 -1
  161. package/dist/src/limrun.d.ts +10 -4
  162. package/dist/src/linux.js +1 -1
  163. package/dist/src/local-interactor-operation-set.js +1 -1
  164. package/dist/src/location-coordinates.js +1 -1
  165. package/dist/src/macos-facade.js +1 -1
  166. package/dist/src/managed-device-scope.js +1 -1
  167. package/dist/src/mechanics.js +17 -16
  168. package/dist/src/mobile-snapshot-semantics.js +1 -1
  169. package/dist/src/multitouch-support.js +1 -1
  170. package/dist/src/observation.js +2 -2
  171. package/dist/src/output-common.js +5 -2
  172. package/dist/src/parameterized-recorded-fill.js +1 -1
  173. package/dist/src/perf-facade.js +2 -2
  174. package/dist/src/perf-runtime-operation-builder.js +1 -1
  175. package/dist/src/perf-runtime-plan.js +1 -1
  176. package/dist/src/perf.js +1 -1
  177. package/dist/src/physical-device-control.js +1 -1
  178. package/dist/src/platform-request-scope.js +1 -1
  179. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  180. package/dist/src/platform-runtime-host.js +1 -1
  181. package/dist/src/platform-runtime-managed-owner.js +1 -1
  182. package/dist/src/platform-runtime-open-target.js +1 -1
  183. package/dist/src/platform-runtime-operation-host.js +4 -4
  184. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  185. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  186. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  187. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  188. package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
  189. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  190. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
  191. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  192. package/dist/src/platform-runtime-unavailable.js +1 -1
  193. package/dist/src/platform-runtime.js +1 -1
  194. package/dist/src/platform-runtime2.js +1 -1
  195. package/dist/src/png-crop-bytes.js +1 -1
  196. package/dist/src/png-worker-client.js +1 -0
  197. package/dist/src/png.js +1 -1
  198. package/dist/src/prepare-kind.js +1 -1
  199. package/dist/src/provider-session-ownership.js +1 -1
  200. package/dist/src/provider-webdriver.js +1 -1
  201. package/dist/src/proxy.js +1 -1
  202. package/dist/src/quality-warnings.js +1 -1
  203. package/dist/src/react-native.js +1 -1
  204. package/dist/src/record-runtime.js +1 -1
  205. package/dist/src/record-trace.js +1 -1
  206. package/dist/src/rect-center.js +1 -1
  207. package/dist/src/register-builtins.js +1 -1
  208. package/dist/src/registry.js +35 -35
  209. package/dist/src/remote-config2.js +1 -1
  210. package/dist/src/replay-divergence.js +1 -1
  211. package/dist/src/replay.js +1 -1
  212. package/dist/src/reporting.js +1 -1
  213. package/dist/src/request-admission.js +1 -1
  214. package/dist/src/request-cancel.js +1 -1
  215. package/dist/src/request-runtime-binding.js +1 -1
  216. package/dist/src/result-serialization.js +1 -1
  217. package/dist/src/retry.js +1 -1
  218. package/dist/src/runner-cache-metadata.js +2 -2
  219. package/dist/src/runner-client.js +1 -1
  220. package/dist/src/runner-contract.js +3 -0
  221. package/dist/src/runner-dev-tools-security.js +1 -0
  222. package/dist/src/runner-device-readiness.js +1 -0
  223. package/dist/src/runner-disposal.js +1 -1
  224. package/dist/src/runner-operations-facade.js +1 -1
  225. package/dist/src/runner-presentation.js +1 -1
  226. package/dist/src/runner.js +1 -1
  227. package/dist/src/runtime-transport-hints.js +1 -1
  228. package/dist/src/runtime.js +3 -3
  229. package/dist/src/runtime10.js +1 -1
  230. package/dist/src/runtime2.js +4 -4
  231. package/dist/src/runtime3.js +1 -1
  232. package/dist/src/runtime4.js +5 -5
  233. package/dist/src/runtime5.js +1 -1
  234. package/dist/src/runtime6.js +1 -1
  235. package/dist/src/runtime7.js +1 -1
  236. package/dist/src/runtime8.js +1 -1
  237. package/dist/src/runtime9.js +1 -1
  238. package/dist/src/screen-recording-admission-ledger.js +1 -0
  239. package/dist/src/screen-recording-completion.js +1 -1
  240. package/dist/src/screen-recording-options.js +1 -1
  241. package/dist/src/screen-recording-resource-recovery.js +1 -1
  242. package/dist/src/screen-recording-transport.js +1 -0
  243. package/dist/src/screenshot-density.js +1 -1
  244. package/dist/src/screenshot-image.js +1 -0
  245. package/dist/src/screenshot-runtime.js +1 -1
  246. package/dist/src/screenshot.js +1 -1
  247. package/dist/src/screenshot3.js +1 -1
  248. package/dist/src/script.js +1 -1
  249. package/dist/src/scroll-command.js +1 -1
  250. package/dist/src/scroll-gesture.js +1 -1
  251. package/dist/src/sdk-batch-runner.js +2 -2
  252. package/dist/src/sdk-batch.js +2 -2
  253. package/dist/src/sdk-contracts.d.ts +76 -1
  254. package/dist/src/sdk-contracts.js +2 -2
  255. package/dist/src/sdk-device.js +1 -1
  256. package/dist/src/sdk-finders.d.ts +1 -1
  257. package/dist/src/sdk-finders.js +1 -1
  258. package/dist/src/sdk-io.js +1 -1
  259. package/dist/src/sdk-remote-config.js +1 -1
  260. package/dist/src/sdk-selectors.d.ts +29 -3
  261. package/dist/src/sdk-selectors.js +1 -1
  262. package/dist/src/selection.js +0 -0
  263. package/dist/src/selector-runtime.js +1 -1
  264. package/dist/src/selectors.js +1 -1
  265. package/dist/src/semantic-index.js +1 -1
  266. package/dist/src/server.js +1 -1
  267. package/dist/src/session-allocation.js +1 -1
  268. package/dist/src/session-observation.js +1 -1
  269. package/dist/src/session-routing.js +1 -1
  270. package/dist/src/session-runtime-admission.js +1 -1
  271. package/dist/src/session-snapshot.js +1 -1
  272. package/dist/src/session-store.js +3 -3
  273. package/dist/src/session2.js +4 -5
  274. package/dist/src/settings.js +1 -1
  275. package/dist/src/simctl-facade.js +1 -1
  276. package/dist/src/simctl.js +1 -1
  277. package/dist/src/simulator-boot.js +1 -1
  278. package/dist/src/simulator-facade.js +1 -1
  279. package/dist/src/simulator.js +1 -1
  280. package/dist/src/snapshot-capture-annotations.js +1 -1
  281. package/dist/src/snapshot-diagnostics.js +1 -1
  282. package/dist/src/snapshot-quality-backend-capabilities.js +1 -1
  283. package/dist/src/snapshot-runtime-binding.js +1 -1
  284. package/dist/src/snapshot-runtime.js +1 -1
  285. package/dist/src/snapshot-state.js +1 -1
  286. package/dist/src/snapshot.js +1 -1
  287. package/dist/src/snapshot2.js +1 -1
  288. package/dist/src/snapshot3.js +1 -1
  289. package/dist/src/snapshot4.js +1 -1
  290. package/dist/src/src.js +1 -1
  291. package/dist/src/src4.js +1 -1
  292. package/dist/src/src7.js +1 -1
  293. package/dist/src/src8.js +2 -2
  294. package/dist/src/stop-sequence.js +1 -1
  295. package/dist/src/string-enum.js +1 -1
  296. package/dist/src/takeover.js +1 -1
  297. package/dist/src/text-entry-focus.js +1 -1
  298. package/dist/src/tool-provider.js +1 -1
  299. package/dist/src/tool-provider2.js +1 -1
  300. package/dist/src/touch-runtime.js +1 -1
  301. package/dist/src/transport.js +1 -1
  302. package/dist/src/tree.js +1 -1
  303. package/dist/src/tv-remote.js +1 -1
  304. package/dist/src/type-text-runtime.js +1 -1
  305. package/dist/src/verified-file.js +1 -1
  306. package/dist/src/video.js +1 -1
  307. package/dist/src/viewport.js +1 -1
  308. package/dist/src/web.js +1 -1
  309. package/dist/src/web2.js +1 -1
  310. package/dist/src/webdriver-source.js +1 -1
  311. package/dist/src/window-state.js +1 -1
  312. package/package.json +4 -1
  313. package/server.json +2 -2
  314. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.6.apk.sha256 +0 -1
  315. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.6.apk.sha256 +0 -1
  316. package/dist/src/session-target-evidence.js +0 -1
  317. package/dist/src/vars.js +0 -2
@@ -1,38 +1,38 @@
1
- import{C as e,S as t,_ as n,h as r,t as i,u as a,v as o}from"./sdk-contracts.js";import{d as s,f as c,i as l,l as ee,n as te,p as ne,t as re,u as ie}from"./capture.js";import{D as ae,c as oe,d as se,f as ce,g as u,l as le,o as ue,p as de,s as fe,u as pe}from"./sdk-batch-runner.js";import{t as me}from"./viewport.js";import{r as he,t as ge}from"./sdk-device.js";import{i as _e,s as ve}from"./lease-scope.js";import{Dn as ye,Nr as be,Or as xe,Tn as Se,Wr as Ce,ar as we,fr as Te,i as Ee,in as De,jn as Oe,m as ke,nn as Ae,or as je,p as Me,s as Ne,sr as Pe,ur as Fe,vr as Ie}from"./sdk-batch.js";import{n as Le}from"./recording-export-quality.js";import{i as Re,r as ze,s as Be,t as Ve}from"./back-mode.js";import{a as He,n as Ue,o as We,r as Ge,s as Ke}from"./scroll-gesture.js";import{E as qe,T as Je,b as Ye,v as Xe,w as Ze}from"./script.js";import{a as Qe,i as $e,r as et}from"./vars.js";import{n as tt,r as nt,t as rt}from"./format.js";import{n as d,t as it}from"./catalog.js";import{a as at}from"./sdk-remote-config.js";import{t as ot}from"./session.js";import{a as st,c as ct,d as lt,f as ut,g as dt,h as ft,i as pt,l as mt,n as ht,o as gt,p as _t,s as vt,t as yt,u as bt}from"./observability.js";import{n as xt,t as St}from"./success-text.js";import{a as Ct,i as wt,n as Tt,o as f,r as p}from"./output-common.js";import{t as Et}from"./alert-contract.js";import{a as Dt,c as Ot,i as kt,l as At,o as jt,r as Mt,t as Nt}from"./location-coordinates.js";import{t as Pt}from"./snapshot-quality-backend-capabilities.js";import{a as Ft,d as It,f as Lt,l as Rt,t as zt,u as Bt}from"./absence-observation-errors.js";import{t as Vt}from"./mobile-snapshot-semantics.js";import{t as Ht}from"./click-button.js";import{n as Ut}from"./scroll-command.js";import{n as Wt,t as Gt}from"./interaction-positionals.js";import{t as Kt}from"./app-inventory.js";import"./device.js";import{a as qt,t as Jt}from"./device-rotation.js";import"./app-inventory-contract.js";import{t as Yt}from"./prepare-kind.js";import{n as Xt,t as Zt}from"./path-resolution.js";import"./file.js";import{n as Qt,r as $t,s as en,t as tn}from"./tv-remote.js";import m from"node:path";import nn from"node:fs";const rn=[`path`,`start`,`stop`,`doctor`,`mark`,`clear`],an=new Set(ze().map(e=>e.key));function on(e){let t=_e(e);return ae({stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,...ve(t),provider:e.provider,providerSessionId:e.providerSessionId,providerApp:e.providerApp,providerOsVersion:e.providerOsVersion,providerProject:e.providerProject,providerBuild:e.providerBuild,providerSessionName:e.providerSessionName,providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp,awsProjectArn:e.awsProjectArn,awsDeviceArn:e.awsDeviceArn,awsAppArn:e.awsAppArn,awsRegion:e.awsRegion,awsInteractionMode:e.awsInteractionMode,sessionIsolation:e.sessionIsolation,platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,iosXctestrunFile:e.iosXctestrunFile,iosXctestDerivedDataPath:e.iosXctestDerivedDataPath,iosXctestEnvDir:e.iosXctestEnvDir,androidDeviceAllowlist:e.androidDeviceAllowlist,surface:e.surface,activity:e.activity,launchConsole:e.launchConsole,launchArgs:e.launchArgs,relaunch:e.relaunch,shutdown:e.shutdown,saveScript:e.saveScript,deviceHub:e.deviceHub,testIme:e.testIme,noRecord:e.noRecord,recordAs:e.recordAs,record:e.record,backMode:e.backMode,metroHost:e.metroHost,metroPort:e.metroPort,bundleUrl:e.bundleUrl,launchUrl:e.launchUrl,...n(e,a),...ee(e),appsFilter:e.appsFilter,kind:e.kind,out:e.out,count:e.count,fps:e.fps,quality:e.quality,hideTouches:e.hideTouches,recordingScope:e.recordingScope,intervalMs:e.intervalMs,delayMs:e.delayMs,durationMs:e.durationMs,holdMs:e.holdMs,jitterPx:e.jitterPx,pixels:e.pixels,until:e.until,doubleTap:e.doubleTap,verify:e.verify,settle:e.settle,settleQuietMs:e.settleQuietMs,clickButton:e.clickButton,pauseMs:e.pauseMs,pattern:e.pattern,headless:e.headless,restart:e.restart,replayUpdate:e.replayUpdate,replayBackend:e.replayBackend,replayEnv:e.replayEnv,replayShellEnv:e.replayShellEnv,replayScriptSource:e.replayScriptSource,replayScriptSources:e.replayScriptSources,replayFrom:e.replayFrom,replayPlanDigest:e.replayPlanDigest,replayKeepSession:e.replayKeepSession,failFast:e.failFast,timeoutMs:e.timeoutMs,retries:e.retries,recordVideo:e.recordVideo,artifactsDir:e.artifactsDir,shardAll:e.shardAll,shardSplit:e.shardSplit,findFirst:e.findFirst,findLast:e.findLast,networkInclude:e.networkInclude,batchOnError:e.batchOnError,batchMaxSteps:e.batchMaxSteps,batchSteps:e.batchSteps,verbose:e.debug})}function sn(e,t){return{...on(e),...t}}function cn(e,t){let n=e.inputSchema.properties;if(!n)return{};let r={},i=t;for(let e of Object.keys(n)){if(!an.has(e))continue;let t=i[e];ln(t)&&(r[e]=t)}return r}function ln(e){return typeof e==`boolean`||typeof e==`number`||typeof e==`string`}function un(e){return{kind:`operator`,source:e}}function dn(e,t){return`${e} is not accepted as a tool argument. ${fn(e,t)}`}function fn(e,t){if(`operatorPath`in t)return t.operatorPath;let n=`for the process serving these tools.`,r=(t.envFlagKeys??[e]).map(at).join(` or `);return r===``?`Set ${e} in ~/.agent-device/config.json ${n}`:`Set the ${r} environment variable${t.operatorConfig?` (or ${e} in ~/.agent-device/config.json)`:``} ${n}`}function pn(t){if(t==null)return{};if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected object arguments.`);return t}function mn(t,n){let r=t[n];if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be an object.`);return r}function hn(t,n){let r=t[n];if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`Expected ${n} to be a non-empty string.`);return r}function gn(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`string`)throw new e(`INVALID_ARGS`,`Expected ${n} to be a string.`);return r}}function h(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`Expected ${n} to be a non-empty string.`);return r}}function _n(t,n){let r=t[n];if(typeof r!=`number`||!Number.isFinite(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be a finite number.`);return r}function vn(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected ${n} to be a boolean.`);return r}}function yn(t,n,r){let i=t[n];if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected ${n} to be one of: ${r.join(`, `)}.`);return i}function bn(t,n,r){let i=t[n];if(i!==void 0){if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected ${n} to be one of: ${r.join(`, `)}.`);return i}}function xn(t,n){let r=t[n];if(r!==void 0){if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be an object.`);return r}}function Sn(t,n){let r=t[n];if(r!==void 0){if(!Array.isArray(r)||r.some(e=>typeof e!=`string`))throw new e(`INVALID_ARGS`,`Expected ${n} to be an array of strings.`);return r}}function Cn(t,n,r,i){let a=new Set(n),o=Object.keys(t).filter(e=>!a.has(e));if(o.length>0)throw new e(`INVALID_ARGS`,`${r} has unknown field(s): ${o.join(`, `)}.`,i===void 0?void 0:{hint:i})}function g(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}const wn=un({operatorConfig:!0}),Tn={session:{schema:{type:`string`,description:`Agent-device session name.`},read:e=>h(e,`session`),flagKey:`session`,flagIn:[`input`]},platform:{schema:{type:`string`,enum:he,description:`Platform selector used to resolve a device.`},read:e=>bn(e,`platform`,he),flagKey:`platform`,flagIn:[`input`,`selection`]},deviceTarget:{schema:{type:`string`,enum:ge,description:`Device target form. Maps to the CLI --target flag.`},read:jn,clientKey:`target`,flagKey:`target`,flagIn:[`input`,`selection`]},target:{schema:{type:`string`,enum:ge,description:`Alias for deviceTarget on commands without a UI target field. Interaction commands reserve target for the UI element.`}},device:{schema:{type:`string`,description:`Device name selector (a UDID belongs in udid, a serial in serial).`},read:e=>h(e,`device`),flagKey:`device`,flagIn:[`input`,`selection`]},udid:{schema:{type:`string`,description:`Apple device or simulator UDID; the selector that pins one device when several share a name.`},read:e=>h(e,`udid`),flagKey:`udid`,flagIn:[`input`,`selection`]},serial:{schema:{type:`string`,description:`Android, HarmonyOS, or Vega VVD serial selector.`},read:e=>h(e,`serial`),flagKey:`serial`,flagIn:[`input`,`selection`]},iosSimulatorDeviceSet:{schema:{type:`string`,description:`iOS simulator device-set path used for device resolution.`},read:e=>h(e,`iosSimulatorDeviceSet`),audience:un({envFlagKeys:[],operatorConfig:!0}),flagKey:`iosSimulatorDeviceSet`,flagIn:[`input`,`selection`]},iosXctestrunFile:{schema:{type:`string`,description:`Externally built iOS XCTest runner .xctestrun artifact path.`},read:e=>h(e,`iosXctestrunFile`),audience:wn,flagKey:`iosXctestrunFile`,flagIn:[`input`]},iosXctestDerivedDataPath:{schema:{type:`string`,description:`Derived data path for external iOS XCTest runner execution.`},read:e=>h(e,`iosXctestDerivedDataPath`),audience:wn,flagKey:`iosXctestDerivedDataPath`,flagIn:[`input`]},iosXctestEnvDir:{schema:{type:`string`,description:`Writable directory for iOS XCTest runner env overlays.`},read:e=>h(e,`iosXctestEnvDir`),audience:wn,flagKey:`iosXctestEnvDir`,flagIn:[`input`]},androidDeviceAllowlist:{schema:{type:`string`,description:`Android serial allowlist used for device resolution.`},read:e=>h(e,`androidDeviceAllowlist`),flagKey:`androidDeviceAllowlist`,flagIn:[`input`,`selection`]},noRecord:{read:e=>vn(e,`noRecord`),flagKey:`noRecord`,flagIn:[`input`,`selection`]},daemonBaseUrl:{schema:{type:`string`,description:`Remote daemon base URL.`},read:e=>h(e,`daemonBaseUrl`),audience:wn},daemonAuthToken:{schema:{type:`string`,description:`Remote daemon auth token.`},read:e=>h(e,`daemonAuthToken`),audience:wn},tenant:{schema:{type:`string`,description:`Remote tenant identifier.`},read:e=>h(e,`tenant`)},runId:{schema:{type:`string`,description:`Lease run identifier.`},read:e=>h(e,`runId`)},leaseId:{schema:{type:`string`,description:`Existing lease identifier.`},read:e=>h(e,`leaseId`)},cwd:{schema:{type:`string`,description:`Working directory for command execution.`},read:e=>h(e,`cwd`),audience:un({operatorPath:`Start the process serving these tools in the desired working directory, or pass absolute paths.`})},debug:{schema:{type:`boolean`,description:`Enable debug diagnostics.`},read:e=>vn(e,`debug`)}},En=Object.entries(Tn),Dn=Object.fromEntries(En.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function On(){return Object.fromEntries(En.flatMap(([e,t])=>t.schema?[[e,t.schema]]:[]))}function kn(e,t={}){let n={};for(let[r,i]of En)i.read&&(n[r]=i.read(e,t));return n}function _(e){let t={};for(let[n,r]of En)r.read&&(t[r.clientKey??n]=e[n]);return g(t)}function An(e,t){let n={};for(let[r,i]of En){if(i.flagIn===void 0||!i.flagIn.includes(t))continue;let a=t===`selection`?i.clientKey??r:r;n[a]=e[i.flagKey]}return n}function jn(t,n){let r=bn(t,`deviceTarget`,ge);if(n.readTargetAlias===!1||t.target===void 0)return r;let i=bn(t,`target`,ge);if(r!==void 0&&i!==r)throw new e(`INVALID_ARGS`,`Expected target alias to match deviceTarget when both are set.`);return r??i}function v(e,t){return n=>y(e,t?t(n):[],n)}function y(e,t,n,r){return{command:e,positionals:t,...r?{input:r}:{},options:Mn(n)}}function Mn(e){let t=Nn(e.deviceTarget??e.target);if(t===void 0&&e.target===void 0)return e;let{target:n,...r}=e;return t===void 0?r:{...r,target:t}}function Nn(e){return e===`mobile`||e===`tv`||e===`desktop`?e:void 0}function b(e){return g(An(e,`input`))}function Pn(e){return g({record:e.record})}function Fn(e){return An(e,`selection`)}function In(e){return g({depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw})}function Ln(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function Rn(e){return g({settle:e.settle,settleQuietMs:e.settleQuietMs,timeoutMs:e.timeoutMs})}function zn(e){return g({count:e.count,intervalMs:e.intervalMs,holdMs:e.holdMs,jitterPx:e.jitterPx,doubleTap:e.doubleTap})}function Bn(e){if(`ref`in e&&e.ref!==void 0)return g({kind:`ref`,ref:e.ref,label:e.label});if(`selector`in e&&e.selector!==void 0)return{kind:`selector`,selector:e.selector};let t=e;return{kind:`point`,x:t.x,y:t.y}}function Vn(t){let n=Un(t);if(typeof n.ref==`string`)return[n.ref,...Gn(n.label)];if(typeof n.selector==`string`)return[n.selector];if(n.kind===`point`||n.x!==void 0||n.y!==void 0)return[String(Wn(n.x,`x`)),String(Wn(n.y,`y`))];throw new e(`INVALID_ARGS`,`interaction requires @ref, selector, or point target`)}function Hn(t){let n=Un(t);if(typeof n.ref==`string`)return[n.ref,...Gn(n.label)];if(typeof n.selector==`string`)return[n.selector];throw new e(`INVALID_ARGS`,`element command requires @ref or selector target`)}function Un(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected target object.`);let n=t,r=n.target;return r&&typeof r==`object`&&!Array.isArray(r)?r:n}function Wn(t,n){if(typeof t!=`number`||!Number.isFinite(t))throw new e(`INVALID_ARGS`,`point target requires numeric ${n}.`);return t}function Gn(e){return typeof e==`string`&&e.length>0?[e]:[]}function Kn(t){let n=je(t);if(!n.ok)throw new e(n.code,n.message);return`ref`in n?{ref:n.ref,label:Xn(t.slice(1))}:{selector:n.selector}}function qn(t){let n=Pe(t);if(!n.ok)throw new e(n.code,n.message);return n.format}function Jn(t,n={}){let r=Ie(t,n);if(!r)throw new e(`INVALID_ARGS`,we);return r}function Yn(t,n){try{let e=JSON.parse(t);if(e&&typeof e==`object`&&!Array.isArray(e))return e}catch{}throw new e(`INVALID_ARGS`,`${n} must be a JSON object`)}function Xn(e){return e.join(` `).trim()||void 0}function x(...e){return new Set(e)}function S(e,t){return e!==void 0&&t.has(e)}function Zn(e){return e===void 0||e.trim()===``?!1:Number.isFinite(Number(e))}function Qn(t,n){if(t===void 0)return;let r=Number(t);if(Number.isFinite(r))return r;throw new e(`INVALID_ARGS`,`${n} must be a finite number.`)}function $n(e){return e===void 0?void 0:Number(e)}function C(e){return e===void 0?[]:[e]}function w(e){return e===void 0?[]:[String(e)]}function T(t,n){if(t===void 0||t===``)throw new e(`INVALID_ARGS`,n);return t}function E(t,n){if(typeof t!=`string`||t.length===0)throw new e(`INVALID_ARGS`,n);return t}function er(e){return rr(e.description,e.cliDetail)}function tr(e){return rr(e.description,e.mcpDetail)}function nr(e,t){return{...e,description:t}}function rr(e,t){return t?`${e} ${t}`:e}function D(e){let t=nr(e.text,e.metadata.description),n=t.mcpDetail?{mcpDetail:t.mcpDetail}:{},r={...e.metadata,...n},i={name:r.name,description:r.description,inputSchema:r.inputSchema,...n,invoke:async(t,n)=>await e.run(t,r.readInput(n))};return{name:e.name,metadata:r,definition:i,cliSchema:{...e.cliSchema,text:t},cliReader:e.cliReader,daemonWriter:e.daemonWriter,cliOutputFormatter:e.cliOutputFormatter,text:t}}function O(e){let t={},n={},r={},i={};for(let a of e.commands)ir(t,`CLI schema`,a.name,a.cliSchema),ir(n,`CLI reader`,a.name,a.cliReader),a.daemonWriter&&ir(r,`daemon writer`,a.name,a.daemonWriter),a.cliOutputFormatter&&ir(i,`CLI output formatter`,a.name,a.cliOutputFormatter);return{name:e.name,clientSurface:e.clientSurface,metadata:e.commands.map(e=>e.metadata),definitions:e.commands.map(e=>e.definition),cliSchemas:t,cliReaders:n,daemonWriters:r,cliOutputFormatters:i}}function ir(e,t,n,r){if(Object.hasOwn(e,n))throw Error(`Duplicate command family ${t}: ${n}`);e[n]=r}function ar(e){let t=[`Batch completed: ${e.executed}/${e.total} steps in ${e.totalDurationMs}ms`];for(let n of e.results)t.push(sr(n));return{data:e,text:t.join(`
2
- `)}}const or={batch:f(ar)};function sr(e){let t=St(e.data)??e.command;return`${e.step}. OK ${t} (${e.durationMs}ms)`}function cr(e){return e}const lr=[`ref`,`selector`,`point`];function ur(e,t=[]){return{type:`object`,properties:{...On(),...e},...t.length>0?{required:t}:{},additionalProperties:!1}}function dr(e){return{type:`object`,description:e,properties:{x:{type:`number`},y:{type:`number`}},required:[`x`,`y`],additionalProperties:!1}}function fr(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function k(e){return{type:`string`,...e?{description:e}:{}}}function pr(e,t={}){return{type:`number`,...e?{description:e}:{},...t.min===void 0?{}:{minimum:t.min},...t.max===void 0?{}:{maximum:t.max}}}function mr(e){return{type:`integer`,...e?{description:e}:{}}}function hr(e){return{type:`boolean`,...e?{description:e}:{}}}function gr(e){return{type:`array`,items:{type:`string`},...e?{description:e}:{}}}function _r(e){return{type:`object`,additionalProperties:!0,...e?{description:e}:{}}}function A(e){return{...e,required:!0}}function j(e,t={}){return L(k(e),t.allowEmpty===!0?gn:h)}function vr(t){return{schema:{type:`null`},required:!1,audience:{kind:`retired`,message:t},read:(n,r)=>{if(Object.hasOwn(n,r))throw new e(`INVALID_ARGS`,t)}}}function yr(e,t){return{...e,audience:{kind:`operator`,source:t}}}function M(e,t={}){return L(pr(e,t),(e,n)=>de(e,n,t))}function N(e,t={}){return L(Vr(e,t),(e,n)=>ce(e,n,t))}function P(e){return L(hr(e),vn)}function br(e){return Sr(xr(e))}function xr(e){let[t,...n]=Re(e).filter(e=>e.inputDescription!==void 0);if(!t)throw Error(`Flag ${e} declares no inputDescription; optionField cannot derive a field`);if(n.length>0)throw Error(`Flag ${e} declares inputDescription more than once`);return t}function Sr(e){let t=e.inputDescription,n={min:e.min,max:e.max};switch(e.type){case`boolean`:return P(t);case`int`:return N(t,n);case`number`:return M(t,n);case`string`:return j(t);case`enum`:return F(Cr(e),t);case`booleanOrString`:throw Error(`Flag ${e.key} is booleanOrString; declare its field shape explicitly with jsonSchemaField`)}}function Cr(e){let t=e.enumValues;if(!t)throw Error(`Flag ${e.key} is an enum with no enumValues`);return t}function F(e,t){return L(fr(e,t),(t,n)=>bn(t,n,e))}function wr(e){return L(_r(e),xn)}function Tr(e){return L(gr(e),Sn)}function I(e){return L(e,(e,t)=>e[t])}function Er(e,t){return L(e,t)}function Dr(){return L(Gr(),(e,t)=>e[t]===void 0?void 0:Pr(e,t))}function Or(){return L(Kr(),(e,t)=>e[t]===void 0?void 0:Fr(e,t))}function kr(e){return L(dr(e),(e,t)=>e[t]===void 0?void 0:Ir(e,t))}function Ar(){return{depth:N(`Snapshot traversal depth.`,{min:0}),scope:j(`Snapshot scope selector used before resolution.`),raw:P(`Use raw snapshot data during selector resolution.`)}}function jr(){return{count:N(`Number of press/click repetitions.`,{min:1}),intervalMs:N(`Delay between repeated press/click actions.`,{min:0}),holdMs:N(`Hold duration for each action.`,{min:0}),jitterPx:N(`Randomization radius in pixels.`,{min:0}),doubleTap:P(`Request a double-tap action.`)}}function Mr(e){return ur(Hr(e),Ur(e))}function Nr(t,n){let r=pn(t),i=Object.fromEntries(Object.entries(n).flatMap(([t,n])=>{let i=n.read(r,t);if(n.required&&i===void 0)throw new e(`INVALID_ARGS`,`Expected ${t} to be set.`);return i===void 0?[]:[[t,i]]})),a=kn(r,{readTargetAlias:!Object.hasOwn(n,`target`)});return g({...a,..._(a),...i})}function Pr(e,t){let n=mn(e,t),r=yn(n,`kind`,lr);switch(r){case`ref`:return{kind:r,ref:hn(n,`ref`),label:h(n,`label`)};case`selector`:return{kind:r,selector:hn(n,`selector`)};case`point`:return{kind:r,x:_n(n,`x`),y:_n(n,`y`)}}}function Fr(e,t){let n=mn(e,t),r=yn(n,`kind`,[`ref`,`selector`]);return r===`ref`?{kind:r,ref:hn(n,`ref`),label:h(n,`label`)}:{kind:r,selector:hn(n,`selector`)}}function Ir(e,t){let n=mn(e,t);return{x:_n(n,`x`),y:_n(n,`y`)}}function Lr(e){switch(e.kind){case`ref`:return{ref:e.ref,label:e.label};case`selector`:return{selector:e.selector};case`point`:return{x:e.x,y:e.y}}}function Rr(e){switch(e.kind){case`ref`:return{ref:e.ref,label:e.label};case`selector`:return{selector:e.selector}}}function zr(e){return{count:e.count,intervalMs:e.intervalMs,holdMs:e.holdMs,jitterPx:e.jitterPx,doubleTap:e.doubleTap}}function Br(e){return{depth:e.depth,scope:e.scope,raw:e.raw}}function L(e,t){return{schema:e,required:!1,read:t}}function Vr(e,t){return{...mr(e),...t.min===void 0?{}:{minimum:t.min},...t.max===void 0?{}:{maximum:t.max}}}function Hr(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e.audience?.kind!==`retired`).map(([e,t])=>[e,t.schema]))}function Ur(e){return Object.entries(e).flatMap(([e,t])=>t.required?[e]:[])}function Wr(e){return Object.fromEntries(Object.entries(e).flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]))}function Gr(){return{oneOf:[...qr(),{type:`object`,properties:{kind:{type:`string`,const:`point`},x:{type:`number`},y:{type:`number`}},required:[`kind`,`x`,`y`],additionalProperties:!1}],description:`UI target. This is separate from deviceTarget, which selects the device form.`}}function Kr(){return{oneOf:qr(),description:`UI element target by snapshot ref or selector expression.`}}function qr(){return[{type:`object`,properties:{kind:{type:`string`,const:`ref`},ref:{type:`string`,description:`Snapshot element ref such as @e12.`},label:{type:`string`,description:`Optional human label for the ref.`}},required:[`kind`,`ref`],additionalProperties:!1},{type:`object`,properties:{kind:{type:`string`,const:`selector`},selector:{type:`string`,description:`Agent-device selector expression.`}},required:[`kind`,`selector`],additionalProperties:!1}]}function R(e,t,n,r){return cr({name:e,description:t,inputSchema:Mr(n),readInput:r?.readInput??(e=>Nr(e,n)),inputAudience:Wr(n)})}function Jr(e=Ee){let t=Yr(e);return R(`batch`,`Execute multiple commands in one daemon request.`,t,{readInput:e=>Zr(e,t)})}function Yr(e){return{steps:A(Er({type:`array`,description:`Structured batch steps. Each step uses a command name and the same input object as that command tool.`,items:Xr(e)},(t,n)=>Qr(t[n],e))),onError:F([`stop`],`Batch failure policy.`),maxSteps:N(`Maximum number of steps accepted for this batch.`,{min:1,max:1e3}),out:j(`Optional output path for command artifacts.`)}}function Xr(e){return{type:`object`,properties:{command:{type:`string`,enum:e,description:`Command name to run with structured input.`},input:{type:`object`,additionalProperties:!0,commandInputFor:`command`,description:`Structured command input for the nested command. Use the matching MCP tool schema for this object.`},runtime:{type:`object`,additionalProperties:!0,description:`Optional per-step runtime payload.`}},required:[`command`,`input`],additionalProperties:!1}}function Zr(t,n){let r=Nr(t,n),i=r.maxSteps??100;if(!oe(i))throw new e(`INVALID_ARGS`,`Invalid batch maxSteps: ${String(r.maxSteps)}`);return fe(r.steps.length,i),{...r}}function Qr(t,n){if(!Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected steps to be an array.`);return t.map((e,t)=>$r(e,t+1,n))}function $r(e,t,n){let r=se(e,t);return Cn(r,[`command`,`input`,`runtime`],`Batch step ${t}`,ue),{command:ei(r,t,n),input:pe(r,t),...ti(r,t)}}function ei(t,n,r){if(r===Ee)return Ne(t.command,n);let i=t.command;if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected command to be one of: ${r.join(`, `)}.`);return i}function ti(e,t){let n=le(e.runtime,t);return n===void 0?{}:{runtime:n}}function ni(e){return async t=>y(d.batch,[],{...t,batchSteps:await ri(t.steps,e),batchOnError:t.onError,batchMaxSteps:t.maxSteps})}async function ri(t,n){if(!Array.isArray(t)||t.length===0)throw new e(`INVALID_ARGS`,`batch requires a non-empty steps array.`);let r=[];for(let[e,i]of t.entries())r.push(await ii(i,e+1,n));return r}async function ii(e,t,n){let r=se(e,t),i=ai(r,t),a=pe(r,t),o=le(r.runtime,t),s=await n(i,a,t);return{command:s.command,positionals:s.positionals,...s.input?{input:s.input}:{},flags:sn(s.options,s.metadataFlags),runtime:o??s.options.runtime}}function ai(e,t){return Ne(e.command,t)}const oi=Jr(),si={usageOverride:`batch [--steps <json> | --steps-file <path>]`,usageFlags:[],listUsageOverride:`batch --steps <json> | --steps-file <path>`,allowedFlags:[`steps`,`stepsFile`,`batchOnError`,`batchMaxSteps`,`out`]},ci=(e,t)=>({...b(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out}),li=[{command:`snapshot`,input:{interactiveOnly:!0}},{command:`press`,input:{target:{kind:`ref`,ref:`@e12`},settle:!0}},{command:`fill`,input:{target:{kind:`selector`,selector:`id="field-email"`},text:`qa@example.com`}}];function ui(){return`${[`Each step is {"command":"<name>","input":{...}}, and input is that command's structured input object rather than its terminal spelling: a CLI positional becomes a named field (target, text, direction) and a CLI flag becomes a camelCase key (--settle -> "settle":true, -i -> "interactiveOnly":true). There is no positional step form; args, argv, positionals, and flags are not step fields. agent-device help <command> lists arguments in CLI spelling only. The examples below carry the structured spelling; over MCP, the command tool schema states it in full.`,`Steps run serially in one daemon request against the same session, in order. Mutating UI verbs are included (press, click, fill, longpress, scroll, back), which is where the round-trip saving is; --on-error stop halts at the first failing step.`,`Available through batch: ${[...Ee].sort().join(`, `)}.`,`Every other command is excluded: batch and replay never nest, and session, daemon, connection, and host tooling commands own lifecycle a batch request cannot carry. Run those on their own.`].join(` `)}\n\nExamples:\n${[` agent-device batch --steps '${JSON.stringify(li)}'`,` agent-device batch --steps-file ./steps.json --json`].join(`
3
- `)}`}const di=O({name:`batch`,clientSurface:!1,commands:[D({name:`batch`,text:{summary:`Run multiple commands`,cliDetail:ui()},metadata:oi,run:(e,t)=>e.batch.run(fi(t)),cliSchema:si,cliReader:ci,cliOutputFormatter:or.batch})]});function fi(e){return{..._(e),steps:e.steps,onError:e.onError,maxSteps:e.maxSteps,out:e.out}}const pi=`alert`,mi=D({name:pi,text:{summary:`Inspect, accept, or dismiss a platform alert`},metadata:R(pi,`Inspect, wait for, accept, or dismiss a platform alert. Use get before acting when the alert content matters; accept and dismiss change the active alert state. Each iOS XCTest execution activates once, then only observes. Inspect again after an unconfirmed action; never assume a timeout means nothing happened.`,{action:F(Et),timeoutMs:N()}),run:(e,t)=>e.command.alert(t),cliSchema:{usageOverride:`alert [get|accept|dismiss|wait] [timeout]`,positionalArgs:[`action?`,`timeout?`]},cliReader:(e,t)=>({...b(t),...gi(e)}),daemonWriter:v(d.alert,e=>hi(e)),cliOutputFormatter:p});function hi(e){return[e.action??`get`,...w(e.timeoutMs)]}function gi(t){if(t.length>2)throw new e(`INVALID_ARGS`,`alert accepts at most action and timeout arguments.`);return g({action:_i(t[0]),timeoutMs:Qn(t[1],`alert timeout`)})}function _i(t){let n=t?.toLowerCase();if(n===void 0||n===`get`||n===`accept`||n===`dismiss`||n===`wait`)return n;throw new e(`INVALID_ARGS`,`alert action must be get, accept, dismiss, or wait.`)}function z(...e){return e}const vi=z(`snapshotInteractiveOnly`,`snapshotDepth`,`snapshotScope`,`snapshotRaw`),B=z(`snapshotDepth`,`snapshotScope`,`snapshotRaw`),yi=z(`metroProjectRoot`,`kind`,`metroKind`,`metroPublicBaseUrl`,`metroProxyBaseUrl`,`metroBearerToken`,`metroPreparePort`,`metroListenHost`,`metroStatusHost`,`metroStartupTimeoutMs`,`metroProbeTimeoutMs`,`metroRuntimeFile`,`metroNoReuseExisting`,`metroNoInstallDeps`),bi=z(`metroHost`,`metroPort`,`bundleUrl`),xi=z(`count`,`intervalMs`,`holdMs`,`jitterPx`,`doubleTap`),Si=z(`settle`,`settleQuietMs`,`timeoutMs`),Ci=z(`replayUpdate`,`replayEnv`),wi=z(`remoteConfig`,`stateDir`,`daemonBaseUrl`,`daemonAuthToken`,`daemonTransport`,`daemonServerMode`,`tenant`,`sessionIsolation`,`runId`,`leaseId`,`leaseBackend`,`sessionLock`,`platform`,`target`,`device`,`providerApp`,`providerOsVersion`,`providerProject`,`providerBuild`,`providerSessionName`,`providerDeviceOrientation`,`providerGeoLocation`,`providerTimezone`,`providerAppiumVersion`,`providerLanguage`,`providerLocale`,`providerNetworkProfile`,`providerCustomNetwork`,`providerNoResignApp`,`awsProjectArn`,`awsDeviceArn`,`awsAppArn`,`awsRegion`,`awsInteractionMode`,`udid`,`serial`,`iosSimulatorDeviceSet`,`iosXctestrunFile`,`iosXctestDerivedDataPath`,`iosXctestEnvDir`,`androidDeviceAllowlist`,`session`,`noRecord`),Ti=new Set([`platform`,`device`,`udid`,`serial`,`session`]),Ei=new Set([`json`,`config`,`help`,`version`,`verbose`,`cost`,`responseLevel`]),Di=`diff`,Oi=D({name:Di,text:{summary:`Diff snapshot or screenshot`,cliDetail:`Screenshot --threshold is a per-pixel RGB tolerance: 0 requires exact colors and 1 ignores color differences; image dimensions must still match. Live iOS simulator screenshot diffs normalize status-bar chrome by default; use screenshot --normalize-status-bar when capturing reusable baselines.`},metadata:R(Di,`Compare accessibility snapshots or screenshots to identify UI changes. Use snapshot comparisons for semantic tree changes and screenshot comparisons for pixel differences.`,{kind:A(I({type:`string`,const:`snapshot`})),out:j(),interactiveOnly:P(),depth:N(),scope:j(),raw:P()}),run:(e,t)=>e.capture.diff(t),cliSchema:{usageOverride:`diff snapshot | diff screenshot --baseline <path> [current.png] [--out <diff.png>] [--threshold <0-1>] [--overlay-refs]`,usageFlags:[],positionalArgs:[`kind`,`current?`],allowedFlags:[...vi,`baseline`,`threshold`,`out`,`overlayRefs`]},cliReader:(t,n)=>{if(t[0]!==`snapshot`)throw new e(`INVALID_ARGS`,`Only diff snapshot is available through this parser.`);return{...b(n),kind:`snapshot`,out:n.out,interactiveOnly:n.snapshotInteractiveOnly,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw}},daemonWriter:v(d.diff,e=>[E(e.kind,`diff requires kind`)])}),ki=`screenshot`,Ai=D({name:ki,text:{summary:`Capture a screenshot`,cliDetail:`Web defaults to the viewport; use --fullscreen, --full, or -f for the entire page. iOS simulators default to 1x logical-point output; use --pixel-density to request a different screenshot density. macOS app sessions default to the app window; use --fullscreen for full desktop, --scale to downscale, --crop-on <selector> to crop the capture to the frame the selector resolves on the same screen (currently iOS simulators and Android emulators), --overlay-refs to annotate current refs, --normalize-status-bar for deterministic iOS simulator chrome, or --no-stabilize for low-latency Android capture loops.`},metadata:R(ki,`Capture a screenshot of the active app or web session. Choose the capture scope, density, size, or annotations through the corresponding input fields when needed.`,{path:j(`Output path.`),cropOn:j(`Selector expression; the capture is cropped to the frame the selector resolves on the same screen.`),overlayRefs:P(),pixelDensity:N(`Output screenshot pixel density in pixels per logical point.`,{min:1}),fullscreen:P(),scale:M(`Screenshot scale factor.`,l),maxSize:vr(re.migration.screenshot),stabilize:P(),normalizeStatusBar:P(),surface:F(ot)}),run:(e,t)=>e.capture.screenshot(t),cliSchema:{positionalArgs:[`path?`],allowedFlags:te},cliReader:(e,t)=>({...b(t),path:e[0]??t.out,...s(t)}),daemonWriter:e=>(c(`screenshot`,e),ne(e),y(d.screenshot,C(e.path),{...e,...ie(e)}))}),ji=`settings`,Mi=R(ji,`Change supported operating-system settings, animation scales, appearance, or app permissions on the selected target. Platform support varies by setting and action.`,{setting:A(j()),state:A(j()),app:j(),latitude:M(),longitude:M(),permission:j(),mode:F([...jt])}),Ni={usageOverride:At,listUsageOverride:`settings [area] [options]`,positionalArgs:[`setting`,`state`,`target?`,`mode?`]},Pi=(e,t)=>Li(e,t),Fi=v(d.settings,e=>Ri(e)),Ii=D({name:ji,text:{summary:`Change OS settings and app permissions`,cliDetail:`macOS supports only settings appearance <light|dark|toggle> and settings ${Ot}; wifi|airplane|location|animations remain unsupported on macOS. Mobile permission actions use the active session app. On Android, deny|reset of a permission the app currently holds kills a running app; the response reports priorGrantState (granted|not_granted|unknown) and warns for granted and unknown, with open <app> --relaunch to restore it. Permission changes require a resolvable foreground user and fail without mutating if adb cannot report one. Android settings airplane on|off is applied by the connectivity service (Android 11+) and reports the airplaneMode that service holds; older builds fail without changing device state. settings reset-keychain clear is iOS-simulator-only and resets the whole simulator keychain, not just the selected app: simctl exposes no per-app keychain reset, so every app on that simulator loses its keychain-backed credentials (e.g. Firebase auth). clear-app-state does not touch the keychain, so a full fresh-install reset needs both; relaunch the app afterward to observe the signed-out state.`},metadata:Mi,run:(e,t)=>e.settings.update(t),cliSchema:Ni,cliReader:Pi,daemonWriter:Fi,cliOutputFormatter:wt});function Li(t,n){let r=Fn(n),i=t[0],a=t[1];if(S(i,Vi)&&S(a,Hi))return{...r,setting:i,state:a};if(i===`location`&&a===`set`)return{...r,setting:i,state:a,latitude:Nt(t[2],`latitude`),longitude:Nt(t[3],`longitude`)};if(i===`appearance`&&S(a,Ui)||S(i,Wi)&&S(a,Gi)||i===`fingerprint`&&S(a,Ki))return{...r,setting:i,state:a};if(i===`permission`&&S(a,Ji))return{...r,setting:i,state:a,permission:zi(t[2]),mode:Bi(t[3])};if(i===`clear-app-state`){let e=a===`clear`?t[2]:a;return{...r,setting:i,state:`clear`,app:e}}if(i===`reset-keychain`&&a===`clear`&&t.length===2)return{...r,setting:i,state:a};throw new e(`INVALID_ARGS`,`Invalid settings arguments.`)}function Ri(e){return e.setting===`clear-app-state`?[e.setting,...C(e.app)]:e.setting===`location`&&e.state===`set`?[e.setting,e.state,String(e.latitude),String(e.longitude)]:e.setting===`permission`?[e.setting,e.state,e.permission,...C(e.mode)]:[e.setting,e.state]}function zi(t){if(S(t,Yi))return t;throw new e(`INVALID_ARGS`,`settings permission requires a permission target.`)}function Bi(t){if(t===void 0||S(t,qi))return t;throw new e(`INVALID_ARGS`,`settings permission mode must be full or limited.`)}const Vi=x(`wifi`,`airplane`,`location`,`animations`),Hi=x(`on`,`off`),Ui=x(`light`,`dark`,`toggle`),Wi=x(`faceid`,`touchid`),Gi=x(`match`,`nonmatch`,`enroll`,`unenroll`),Ki=x(`match`,`nonmatch`),qi=x(...jt),Ji=x(...Dt),Yi=x(...kt,...Mt);function Xi(e){if(!Array.isArray(e)||e.length===0)return e;let t=be(e);return e.map(e=>{let n=Zi(e,t,e=>e.label),r=Zi(e,t,e=>e.identifier),i=typeof e.label==`string`&&e.label.length>=24&&e.label===n,a=typeof e.identifier==`string`&&e.identifier.length>=24&&e.identifier===r;if(!i&&!a)return e;let o={...e};return i&&(delete o.label,o.inheritsLabel=!0),a&&(delete o.identifier,o.inheritsIdentifier=!0),o})}function Zi(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0;for(;r;){let e=n(r);if(typeof e==`string`&&e.length>0)return e;r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}}function Qi(e){return e.width>0&&e.height>0}function $i(e,t){return!e||!t?!1: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 ea(e,t){if(!e||!t)return!0;let n=e.y+e.height/2,r=t.y+t.height/2;return Math.abs(n-r)<=Math.max(e.height,t.height,1)}function ta(e){return typeof e.parentIndex!=`number`}function na(e){let t=(e.type??``).toLowerCase(),n=(e.identifier??``).trim().toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)||n===`composer`}function ra(e){let t=(e.type??``).toLowerCase();return t.includes(`scroll`)||t.includes(`list`)||t.includes(`recyclerview`)}function V(e){let t=xe(e);if(!t||t!==e.identifier?.trim()||!aa(t))return t;let n=(e.type??``).toLowerCase();return n.includes(`view`)||n.includes(`layout`)||n.includes(`image`)||n.includes(`list`)||n.includes(`recyclerview`)||n.includes(`collection`)?``:t}function ia(e){let t=e.trim().replaceAll(/\s+/g,` `).toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function aa(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function oa(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){let e=t.get(r.parentIndex);if(!e)return null;if(n(e))return e;r=e}return null}function sa(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 ca(e,t,n){let r=[t];for(;r.length>0;){let t=r.pop();if(!n.has(t)){n.add(t);for(let i of e)i.parentIndex!==t||n.has(i.index)||r.push(i.index)}}}const la=[`button`,`switch`,`checkbox`,`radio`],ua=[`button`,`image`,`textview`,`view`];function da(e,t,n){for(let r of e){if(t.has(r.index)||!ma(r))continue;let i=ha(sa(e,r.index),r,t);if(i.label){n.set(r.index,{...r,...n.get(r.index),label:i.label});for(let n of i.removableIndexes)ca(e,n,t)}}}function fa(e,t,n){let r=new Map;for(let i of e){if(t.has(i.index)||!Ca(i))continue;let a=ia(V(i));if(!a)continue;let o=r.get(a);if(o&&ba(o,i,t)){let s=xa(e,o,i,t,n);r.set(a,s);continue}r.set(a,i)}}function pa(e,t){for(let n of e){if(t.has(n.index)||!va(n))continue;let r=ia(V(n));if(!r)continue;let i=sa(e,n.index).filter(e=>!t.has(e.index)&&ya(n,e,r));for(let n of i.filter(_a))ca(e,n.index,t);let a=i.filter(e=>!_a(e)),o=new Set(a.map(e=>ia(V(e))).filter(e=>!!e));if(!(a.length<2||o.size<2))for(let n of a)ca(e,n.index,t)}}function ma(e){return e.hittable===!0&&!na(e)&&!!(e.rect&&Qi(e.rect))&&V(e).trim().length===0}function ha(e,t,n){let r=[],i=[],a=new Set;for(let o of e){if(n.has(o.index)||!ga(o,e)||!$i(o.rect,t.rect))continue;let s=V(o).trim().replaceAll(/\s+/g,` `),c=ia(s);i.push(o.index),!(!s||!c||a.has(c))&&(a.add(c),r.push(s))}return{label:r.join(`, `),removableIndexes:i}}function ga(e,t){if(_a(e))return!0;let n=(e.type??``).toLowerCase();return e.hittable!==!0&&!na(e)&&n.includes(`view`)&&V(e).trim().length>0&&!t.some(t=>t.parentIndex===e.index)}function _a(e){if(e.hittable===!0||na(e))return!1;let t=(e.type??``).toLowerCase();return t.includes(`text`)||t.includes(`image`)||t.includes(`icon`)}function va(e){return e.hittable===!0&&!na(e)&&!!(e.rect&&Qi(e.rect))&&!!ia(V(e))}function ya(e,t,n){if(!Ca(t)||!$i(t.rect,e.rect))return!1;let r=ia(V(t));return!!(r&&n!==r&&n.includes(r))}function ba(e,t,n){return!n.has(e.index)&&ea(e.rect,t.rect)&&(Oa(e,t)||Da(e,t))}function xa(e,t,n,r,i){let a=wa(t,n),o=a.index===t.index?n:t,s=(o.type??``).toLowerCase().includes(`image`)?`has image`:null,c=i.get(a.index)??a,l=i.get(o.index)?.presentationHints??o.presentationHints;return i.set(a.index,{...c,presentationHints:Sa(c.presentationHints,l,s)}),ca(e,o.index,r),i.get(a.index)??a}function Sa(e,t,n){return[...new Set([...Array.isArray(e)?e:[],...Array.isArray(t)?t:[],...n?[n]:[]])]}function Ca(e){if(!e.rect||!Qi(e.rect)||ta(e)||na(e))return!1;let t=(e.type??``).toLowerCase();return t===`text`||Ea(t,ua)}function wa(e,t){let n=Ta(e);return Ta(t)>n?t:e}function Ta(e){let t=(e.type??``).toLowerCase(),n=0;return Ea(t,la)?n+=100:t.includes(`image`)?n+=30:t.includes(`textview`)||t===`text`?n+=20:t.includes(`view`)&&(n+=10),e.hittable===!0&&(n+=20),e.enabled!==!1&&(n+=5),n}function Ea(e,t){return t.some(t=>e.includes(t))}function Da(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?!1:wa(n,r).index===n.index}function Oa(e,t){return e.parentIndex===t.parentIndex?Math.abs(e.index-t.index)<=3:e.parentIndex===t.index||t.parentIndex===e.index?!1:Math.abs((e.depth??0)-(t.depth??0))<=1&&Math.abs(e.index-t.index)<=2}function ka(e,t,n){if(n.raw||!Aa(e))return{nodes:t,filteredCount:0};let r=ja(t);return{nodes:r,filteredCount:t.length-r.length}}function Aa(e){let t=e.androidSnapshot;return!t||typeof t!=`object`?!1:t.backend===`android-helper`}function ja(e){if(e.length===0)return e;let t=new Set,n=new Map,r=new Map(e.map(e=>[e.index,e]));return Ma(e,t),Na(e,r,t,n),da(e,t,n),pa(e,t),fa(e,t,n),e.filter(e=>!t.has(e.index)).map(e=>n.get(e.index)??e)}function Ma(e,t){for(let n of e)!n.rect||Qi(n.rect)||ta(n)||ca(e,n.index,t)}function Na(e,t,n,r){for(let i of e){if(n.has(i.index)||i.rect||ta(i))continue;let a=oa(i,t,ra);a&&Fa(r,a,Pa(i,e)),ca(e,i.index,n)}}function Pa(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&Qi(t.rect)).map(e=>e.index);return n.length===0?null:e.index<Math.min(...n)?`above`:e.index>Math.max(...n)?`below`:null}function Fa(e,t,n){if(!n)return;let r=e.get(t.index)??t;e.set(t.index,{...r,hiddenContentAbove:r.hiddenContentAbove===!0||n===`above`||void 0,hiddenContentBelow:r.hiddenContentBelow===!0||n===`below`||void 0})}function Ia(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??``).toLowerCase(),r=La(xe(n));if(!r)continue;let i=`${e}|${r}`,a=t.get(i)??[];a.push(n),t.set(i,a)}let n=0;for(let e of t.values())e.length<=1||!za(e)||(n+=e.length);return n>=8}function La(e){let t=e.trim().replaceAll(/\s+/g,` `).toLowerCase();return!t||Ra(t)?null:t}function Ra(e){return/\S+@\S+\.\S+/.test(e)}function za(e){for(let t=0;t<e.length;t+=1)for(let n=t+1;n<e.length;n+=1)if(Ba(e[t]?.rect,e[n]?.rect))return!0;return!1}function Ba(e,t){if(!e||!t)return!0;let n=.5;return!(e.x+e.width<=t.x+n||t.x+t.width<=e.x+n||e.y+e.height<=t.y+n||t.y+t.height<=e.y+n)}function Va(e,n={}){let i=e.nodes,a=Array.isArray(i)?i:[],o=r(e.backend)?e.backend:void 0,s=t(o),c=ka(e,a,n),l=Ga(e),ee=eo(e,a,n,c),te=ee.length>0?`${ee.join(`
4
- `)}\n`:``,ne=n.raw?null:Ha(e);if(ne)return`${l}${te}${Ua(ne)}\n`;let re=n.raw||!s?null:Vt(c.nodes),ie=!!e.truncated,ae=re?.nodes??a,oe=n.raw||!s?null:Za(e,re,ae.length,a.length,c.filteredCount),se=Ka(a.length,oe,ie);return a.length===0?`${l}${se}\n${te}`:n.raw?`${l}${se}\n${te}${qa(a)}\n`:n.flatten?`${l}${se}\n${te}${Ja(ae)}${Xa(re)}\n`:`${l}${se}\n${te}${Ya(ae)}${Xa(re)}\n`}function Ha(e){let t=e.unchanged;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.ageMs!=`number`||typeof n.nodeCount!=`number`?null:{ageMs:n.ageMs,nodeCount:n.nodeCount,interactiveOnly:n.interactiveOnly===!0||void 0,scope:typeof n.scope==`string`?n.scope:void 0}}function Ua(e){let t=Wa(e.ageMs);return e.scope?[`Scoped snapshot unchanged for scope "${e.scope}" since previous read ${t} ago.`,`Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`].join(`
1
+ import{D as e,E as t,S as n,p as r,t as i,x as a,y as o}from"./sdk-contracts.js";import{d as s,f as c,i as ee,l as te,n as ne,p as re,t as ie,u as ae}from"./capture.js";import{O as oe,c as se,d as ce,f as le,g as l,l as ue,o as de,p as fe,s as pe,u as me}from"./sdk-batch-runner.js";import{t as he}from"./viewport.js";import{r as ge,t as _e}from"./sdk-device.js";import{i as ve,s as ye}from"./lease-scope.js";import{Ar as be,Dn as xe,Fr as Se,Kr as Ce,Nn as we,br as Te,cr as Ee,fr as De,i as Oe,in as ke,kn as Ae,lr as je,m as Me,mr as Ne,on as Pe,p as Fe,s as Ie,sr as Le}from"./sdk-batch.js";import{n as Re}from"./recording-export-quality.js";import{i as ze,r as Be,s as Ve,t as He}from"./back-mode.js";import{a as Ue,n as We,o as Ge,r as Ke,s as qe}from"./scroll-gesture.js";import{E as Je,T as Ye,b as Xe,v as Ze,w as Qe}from"./script.js";import{c as $e,n as et,o as tt,r as nt,s as rt,t as it}from"./format.js";import{n as u,t as at}from"./catalog.js";import{a as ot}from"./sdk-remote-config.js";import{t as st}from"./session.js";import{a as ct,c as lt,d as ut,f as dt,g as ft,h as pt,i as mt,l as ht,n as gt,o as _t,p as vt,s as yt,t as bt,u as xt}from"./observability.js";import{n as St,t as Ct}from"./success-text.js";import{a as d,i as wt,n as f,r as p}from"./output-common.js";import{t as Tt}from"./alert-contract.js";import{a as Et,c as Dt,i as Ot,l as kt,o as At,r as jt,t as Mt}from"./location-coordinates.js";import{t as Nt}from"./snapshot-quality-backend-capabilities.js";import{a as Pt,d as Ft,f as It,l as Lt,t as Rt,u as zt}from"./absence-observation-errors.js";import{t as Bt}from"./mobile-snapshot-semantics.js";import{t as Vt}from"./click-button.js";import{n as Ht}from"./scroll-command.js";import{n as Ut,t as Wt}from"./interaction-positionals.js";import{t as Gt}from"./app-inventory.js";import"./device.js";import{c as Kt,i as qt,l as Jt,r as Yt,t as Xt}from"./device-rotation.js";import"./app-inventory-contract.js";import{t as Zt}from"./prepare-kind.js";import{n as Qt,t as $t}from"./path-resolution.js";import"./file.js";import{n as en,r as tn,s as nn,t as rn}from"./tv-remote.js";import m from"node:path";import h from"node:fs";const an=[`path`,`start`,`stop`,`doctor`,`mark`,`clear`],on=new Set(Be().map(e=>e.key));function sn(e){let t=ve(e);return oe({stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,...ye(t),provider:e.provider,providerSessionId:e.providerSessionId,providerApp:e.providerApp,providerOsVersion:e.providerOsVersion,providerProject:e.providerProject,providerBuild:e.providerBuild,providerSessionName:e.providerSessionName,providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp,awsProjectArn:e.awsProjectArn,awsDeviceArn:e.awsDeviceArn,awsAppArn:e.awsAppArn,awsRegion:e.awsRegion,awsInteractionMode:e.awsInteractionMode,sessionIsolation:e.sessionIsolation,platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,iosXctestrunFile:e.iosXctestrunFile,iosXctestDerivedDataPath:e.iosXctestDerivedDataPath,iosXctestEnvDir:e.iosXctestEnvDir,androidDeviceAllowlist:e.androidDeviceAllowlist,surface:e.surface,activity:e.activity,launchConsole:e.launchConsole,launchArgs:e.launchArgs,relaunch:e.relaunch,shutdown:e.shutdown,saveScript:e.saveScript,deviceHub:e.deviceHub,testIme:e.testIme,noRecord:e.noRecord,recordAs:e.recordAs,record:e.record,backMode:e.backMode,metroHost:e.metroHost,metroPort:e.metroPort,bundleUrl:e.bundleUrl,launchUrl:e.launchUrl,...a(e,r),...te(e),appsFilter:e.appsFilter,kind:e.kind,out:e.out,count:e.count,fps:e.fps,quality:e.quality,hideTouches:e.hideTouches,recordingScope:e.recordingScope,intervalMs:e.intervalMs,delayMs:e.delayMs,durationMs:e.durationMs,holdMs:e.holdMs,jitterPx:e.jitterPx,pixels:e.pixels,until:e.until,doubleTap:e.doubleTap,verify:e.verify,settle:e.settle,settleQuietMs:e.settleQuietMs,clickButton:e.clickButton,pauseMs:e.pauseMs,pattern:e.pattern,headless:e.headless,restart:e.restart,replayUpdate:e.replayUpdate,replayBackend:e.replayBackend,replayEnv:e.replayEnv,replayShellEnv:e.replayShellEnv,replayScriptSource:e.replayScriptSource,replayScriptSources:e.replayScriptSources,replayFrom:e.replayFrom,replayPlanDigest:e.replayPlanDigest,replayKeepSession:e.replayKeepSession,failFast:e.failFast,timeoutMs:e.timeoutMs,retries:e.retries,recordVideo:e.recordVideo,artifactsDir:e.artifactsDir,shardAll:e.shardAll,shardSplit:e.shardSplit,findFirst:e.findFirst,findLast:e.findLast,networkInclude:e.networkInclude,batchOnError:e.batchOnError,batchMaxSteps:e.batchMaxSteps,batchSteps:e.batchSteps,verbose:e.debug})}function cn(e,t){return{...sn(e),...t}}function ln(e,t){let n=e.inputSchema.properties;if(!n)return{};let r={},i=t;for(let e of Object.keys(n)){if(!on.has(e))continue;let t=i[e];un(t)&&(r[e]=t)}return r}function un(e){return typeof e==`boolean`||typeof e==`number`||typeof e==`string`}function dn(e){return{kind:`operator`,source:e}}function fn(e,t){return`${e} is not accepted as a tool argument. ${pn(e,t)}`}function pn(e,t){if(`operatorPath`in t)return t.operatorPath;let n=`for the process serving these tools.`,r=(t.envFlagKeys??[e]).map(ot).join(` or `);return r===``?`Set ${e} in ~/.agent-device/config.json ${n}`:`Set the ${r} environment variable${t.operatorConfig?` (or ${e} in ~/.agent-device/config.json)`:``} ${n}`}function mn(t){if(t==null)return{};if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected object arguments.`);return t}function hn(t,n){let r=t[n];if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be an object.`);return r}function gn(t,n){let r=t[n];if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`Expected ${n} to be a non-empty string.`);return r}function _n(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`string`)throw new e(`INVALID_ARGS`,`Expected ${n} to be a string.`);return r}}function g(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`Expected ${n} to be a non-empty string.`);return r}}function vn(t,n){let r=t[n];if(typeof r!=`number`||!Number.isFinite(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be a finite number.`);return r}function yn(t,n){let r=t[n];if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected ${n} to be a boolean.`);return r}}function bn(t,n,r){let i=t[n];if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected ${n} to be one of: ${r.join(`, `)}.`);return i}function xn(t,n,r){let i=t[n];if(i!==void 0){if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected ${n} to be one of: ${r.join(`, `)}.`);return i}}function Sn(t,n){let r=t[n];if(r!==void 0){if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`Expected ${n} to be an object.`);return r}}function Cn(t,n){let r=t[n];if(r!==void 0){if(!Array.isArray(r)||r.some(e=>typeof e!=`string`))throw new e(`INVALID_ARGS`,`Expected ${n} to be an array of strings.`);return r}}function wn(t,n,r,i){let a=new Set(n),o=Object.keys(t).filter(e=>!a.has(e));if(o.length>0)throw new e(`INVALID_ARGS`,`${r} has unknown field(s): ${o.join(`, `)}.`,i===void 0?void 0:{hint:i})}function _(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}const Tn=dn({operatorConfig:!0}),En={session:{schema:{type:`string`,description:`Agent-device session name.`},read:e=>g(e,`session`),flagKey:`session`,flagIn:[`input`]},platform:{schema:{type:`string`,enum:ge,description:`Platform selector used to resolve a device.`},read:e=>xn(e,`platform`,ge),flagKey:`platform`,flagIn:[`input`,`selection`]},deviceTarget:{schema:{type:`string`,enum:_e,description:`Device target form. Maps to the CLI --target flag.`},read:Mn,clientKey:`target`,flagKey:`target`,flagIn:[`input`,`selection`]},target:{schema:{type:`string`,enum:_e,description:`Alias for deviceTarget on commands without a UI target field. Interaction commands reserve target for the UI element.`}},device:{schema:{type:`string`,description:`Device name selector (a UDID belongs in udid, a serial in serial).`},read:e=>g(e,`device`),flagKey:`device`,flagIn:[`input`,`selection`]},udid:{schema:{type:`string`,description:`Apple device or simulator UDID; the selector that pins one device when several share a name.`},read:e=>g(e,`udid`),flagKey:`udid`,flagIn:[`input`,`selection`]},serial:{schema:{type:`string`,description:`Android, HarmonyOS, or Vega VVD serial selector.`},read:e=>g(e,`serial`),flagKey:`serial`,flagIn:[`input`,`selection`]},iosSimulatorDeviceSet:{schema:{type:`string`,description:`iOS simulator device-set path used for device resolution.`},read:e=>g(e,`iosSimulatorDeviceSet`),audience:dn({envFlagKeys:[],operatorConfig:!0}),flagKey:`iosSimulatorDeviceSet`,flagIn:[`input`,`selection`]},iosXctestrunFile:{schema:{type:`string`,description:`Externally built iOS XCTest runner .xctestrun artifact path.`},read:e=>g(e,`iosXctestrunFile`),audience:Tn,flagKey:`iosXctestrunFile`,flagIn:[`input`]},iosXctestDerivedDataPath:{schema:{type:`string`,description:`Derived data path for external iOS XCTest runner execution.`},read:e=>g(e,`iosXctestDerivedDataPath`),audience:Tn,flagKey:`iosXctestDerivedDataPath`,flagIn:[`input`]},iosXctestEnvDir:{schema:{type:`string`,description:`Writable directory for iOS XCTest runner env overlays.`},read:e=>g(e,`iosXctestEnvDir`),audience:Tn,flagKey:`iosXctestEnvDir`,flagIn:[`input`]},androidDeviceAllowlist:{schema:{type:`string`,description:`Android serial allowlist used for device resolution.`},read:e=>g(e,`androidDeviceAllowlist`),flagKey:`androidDeviceAllowlist`,flagIn:[`input`,`selection`]},noRecord:{read:e=>yn(e,`noRecord`),flagKey:`noRecord`,flagIn:[`input`,`selection`]},daemonBaseUrl:{schema:{type:`string`,description:`Remote daemon base URL.`},read:e=>g(e,`daemonBaseUrl`),audience:Tn},daemonAuthToken:{schema:{type:`string`,description:`Remote daemon auth token.`},read:e=>g(e,`daemonAuthToken`),audience:Tn},tenant:{schema:{type:`string`,description:`Remote tenant identifier.`},read:e=>g(e,`tenant`)},runId:{schema:{type:`string`,description:`Lease run identifier.`},read:e=>g(e,`runId`)},leaseId:{schema:{type:`string`,description:`Existing lease identifier.`},read:e=>g(e,`leaseId`)},cwd:{schema:{type:`string`,description:`Working directory for command execution.`},read:e=>g(e,`cwd`),audience:dn({operatorPath:`Start the process serving these tools in the desired working directory, or pass absolute paths.`})},debug:{schema:{type:`boolean`,description:`Enable debug diagnostics.`},read:e=>yn(e,`debug`)}},Dn=Object.entries(En),On=Object.fromEntries(Dn.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function kn(){return Object.fromEntries(Dn.flatMap(([e,t])=>t.schema?[[e,t.schema]]:[]))}function An(e,t={}){let n={};for(let[r,i]of Dn)i.read&&(n[r]=i.read(e,t));return n}function v(e){let t={};for(let[n,r]of Dn)r.read&&(t[r.clientKey??n]=e[n]);return _(t)}function jn(e,t){let n={};for(let[r,i]of Dn){if(i.flagIn===void 0||!i.flagIn.includes(t))continue;let a=t===`selection`?i.clientKey??r:r;n[a]=e[i.flagKey]}return n}function Mn(t,n){let r=xn(t,`deviceTarget`,_e);if(n.readTargetAlias===!1||t.target===void 0)return r;let i=xn(t,`target`,_e);if(r!==void 0&&i!==r)throw new e(`INVALID_ARGS`,`Expected target alias to match deviceTarget when both are set.`);return r??i}function y(e,t){return n=>b(e,t?t(n):[],n)}function b(e,t,n,r){return{command:e,positionals:t,...r?{input:r}:{},options:Nn(n)}}function Nn(e){let t=Pn(e.deviceTarget??e.target);if(t===void 0&&e.target===void 0)return e;let{target:n,...r}=e;return t===void 0?r:{...r,target:t}}function Pn(e){return e===`mobile`||e===`tv`||e===`desktop`?e:void 0}function x(e){return _(jn(e,`input`))}function Fn(e){return _({record:e.record})}function In(e){return jn(e,`selection`)}function Ln(e){return _({depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw})}function Rn(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function zn(e){return _({settle:e.settle,settleQuietMs:e.settleQuietMs,timeoutMs:e.timeoutMs})}function Bn(e){return _({count:e.count,intervalMs:e.intervalMs,holdMs:e.holdMs,jitterPx:e.jitterPx,doubleTap:e.doubleTap})}function Vn(e){if(`ref`in e&&e.ref!==void 0)return _({kind:`ref`,ref:e.ref,label:e.label});if(`selector`in e&&e.selector!==void 0)return{kind:`selector`,selector:e.selector};let t=e;return{kind:`point`,x:t.x,y:t.y}}function Hn(t){let n=Wn(t);if(typeof n.ref==`string`)return[n.ref,...Kn(n.label)];if(typeof n.selector==`string`)return[n.selector];if(n.kind===`point`||n.x!==void 0||n.y!==void 0)return[String(Gn(n.x,`x`)),String(Gn(n.y,`y`))];throw new e(`INVALID_ARGS`,`interaction requires @ref, selector, or point target`)}function Un(t){let n=Wn(t);if(typeof n.ref==`string`)return[n.ref,...Kn(n.label)];if(typeof n.selector==`string`)return[n.selector];throw new e(`INVALID_ARGS`,`element command requires @ref or selector target`)}function Wn(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected target object.`);let n=t,r=n.target;return r&&typeof r==`object`&&!Array.isArray(r)?r:n}function Gn(t,n){if(typeof t!=`number`||!Number.isFinite(t))throw new e(`INVALID_ARGS`,`point target requires numeric ${n}.`);return t}function Kn(e){return typeof e==`string`&&e.length>0?[e]:[]}function qn(t){let n=Ee(t);if(!n.ok)throw new e(n.code,n.message);return`ref`in n?{ref:n.ref,label:Zn(t.slice(1))}:{selector:n.selector}}function Jn(t){let n=je(t);if(!n.ok)throw new e(n.code,n.message);return n.format}function Yn(t,n={}){let r=Te(t,n);if(!r)throw new e(`INVALID_ARGS`,Le);return r}function Xn(t,n){try{let e=JSON.parse(t);if(e&&typeof e==`object`&&!Array.isArray(e))return e}catch{}throw new e(`INVALID_ARGS`,`${n} must be a JSON object`)}function Zn(e){return e.join(` `).trim()||void 0}function S(...e){return new Set(e)}function C(e,t){return e!==void 0&&t.has(e)}function Qn(e){return e===void 0||e.trim()===``?!1:Number.isFinite(Number(e))}function $n(t,n){if(t===void 0)return;let r=Number(t);if(Number.isFinite(r))return r;throw new e(`INVALID_ARGS`,`${n} must be a finite number.`)}function er(e){return e===void 0?void 0:Number(e)}function w(e){return e===void 0?[]:[e]}function T(e){return e===void 0?[]:[String(e)]}function E(t,n){if(t===void 0||t===``)throw new e(`INVALID_ARGS`,n);return t}function D(t,n){if(typeof t!=`string`||t.length===0)throw new e(`INVALID_ARGS`,n);return t}function tr(e){return ir(e.description,e.cliDetail)}function nr(e){return ir(e.description,e.mcpDetail)}function rr(e,t){return{...e,description:t}}function ir(e,t){return t?`${e} ${t}`:e}function ar(e){return e}const or=[`ref`,`selector`,`point`];function sr(e,t=[]){return{type:`object`,properties:{...kn(),...e},...t.length>0?{required:t}:{},additionalProperties:!1}}function cr(e){return{type:`object`,description:e,properties:{x:{type:`number`},y:{type:`number`}},required:[`x`,`y`],additionalProperties:!1}}function lr(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function ur(e){return{type:`string`,...e?{description:e}:{}}}function dr(e,t={}){return{type:`number`,...e?{description:e}:{},...t.min===void 0?{}:{minimum:t.min},...t.max===void 0?{}:{maximum:t.max}}}function fr(e){return{type:`integer`,...e?{description:e}:{}}}function pr(e){return{type:`boolean`,...e?{description:e}:{}}}function mr(e){return{type:`array`,items:{type:`string`},...e?{description:e}:{}}}function hr(e){return{type:`object`,additionalProperties:!0,...e?{description:e}:{}}}function O(e){return{...e,required:!0}}function k(e,t={}){return I(ur(e),t.allowEmpty===!0?_n:g)}function gr(t){return{schema:{type:`null`},required:!1,audience:{kind:`retired`,message:t},read:(n,r)=>{if(Object.hasOwn(n,r))throw new e(`INVALID_ARGS`,t)}}}function _r(e,t){return{...e,audience:{kind:`operator`,source:t}}}function A(e,t={}){return I(dr(e,t),(e,n)=>fe(e,n,t))}function j(e,t={}){return I(Rr(e,t),(e,n)=>le(e,n,t))}function M(e){return I(pr(e),yn)}function vr(e){return br(yr(e))}function yr(e){let[t,...n]=ze(e).filter(e=>e.inputDescription!==void 0);if(!t)throw Error(`Flag ${e} declares no inputDescription; optionField cannot derive a field`);if(n.length>0)throw Error(`Flag ${e} declares inputDescription more than once`);return t}function br(e){let t=e.inputDescription,n={min:e.min,max:e.max};switch(e.type){case`boolean`:return M(t);case`int`:return j(t,n);case`number`:return A(t,n);case`string`:return k(t);case`enum`:return N(xr(e),t);case`booleanOrString`:throw Error(`Flag ${e.key} is booleanOrString; declare its field shape explicitly with jsonSchemaField`)}}function xr(e){let t=e.enumValues;if(!t)throw Error(`Flag ${e.key} is an enum with no enumValues`);return t}function N(e,t){return I(lr(e,t),(t,n)=>xn(t,n,e))}function Sr(e){return I(hr(e),Sn)}function Cr(e){return I(mr(e),Cn)}function P(e){return I(e,(e,t)=>e[t])}function wr(e,t){return I(e,t)}function Tr(){return I(Hr(),(e,t)=>e[t]===void 0?void 0:jr(e,t))}function Er(){return I(Ur(),(e,t)=>e[t]===void 0?void 0:Mr(e,t))}function Dr(e){return I(cr(e),(e,t)=>e[t]===void 0?void 0:Nr(e,t))}function F(){return{depth:j(`Snapshot traversal depth.`,{min:0}),scope:k(`Snapshot scope selector used before resolution.`),raw:M(`Use raw snapshot data during selector resolution.`)}}function Or(){return{count:j(`Number of press/click repetitions.`,{min:1}),intervalMs:j(`Delay between repeated press/click actions.`,{min:0}),holdMs:j(`Hold duration for each action.`,{min:0}),jitterPx:j(`Randomization radius in pixels.`,{min:0}),doubleTap:M(`Request a double-tap action.`)}}function kr(e){return sr(zr(e),Br(e))}function Ar(t,n){let r=mn(t),i=Object.fromEntries(Object.entries(n).flatMap(([t,n])=>{let i=n.read(r,t);if(n.required&&i===void 0)throw new e(`INVALID_ARGS`,`Expected ${t} to be set.`);return i===void 0?[]:[[t,i]]})),a=An(r,{readTargetAlias:!Object.hasOwn(n,`target`)});return _({...a,...v(a),...i})}function jr(e,t){let n=hn(e,t),r=bn(n,`kind`,or);switch(r){case`ref`:return{kind:r,ref:gn(n,`ref`),label:g(n,`label`)};case`selector`:return{kind:r,selector:gn(n,`selector`)};case`point`:return{kind:r,x:vn(n,`x`),y:vn(n,`y`)}}}function Mr(e,t){let n=hn(e,t),r=bn(n,`kind`,[`ref`,`selector`]);return r===`ref`?{kind:r,ref:gn(n,`ref`),label:g(n,`label`)}:{kind:r,selector:gn(n,`selector`)}}function Nr(e,t){let n=hn(e,t);return{x:vn(n,`x`),y:vn(n,`y`)}}function Pr(e){switch(e.kind){case`ref`:return{ref:e.ref,label:e.label};case`selector`:return{selector:e.selector};case`point`:return{x:e.x,y:e.y}}}function Fr(e){switch(e.kind){case`ref`:return{ref:e.ref,label:e.label};case`selector`:return{selector:e.selector}}}function Ir(e){return{count:e.count,intervalMs:e.intervalMs,holdMs:e.holdMs,jitterPx:e.jitterPx,doubleTap:e.doubleTap}}function Lr(e){return{depth:e.depth,scope:e.scope,raw:e.raw}}function I(e,t){return{schema:e,required:!1,read:t}}function Rr(e,t){return{...fr(e),...t.min===void 0?{}:{minimum:t.min},...t.max===void 0?{}:{maximum:t.max}}}function zr(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e.audience?.kind!==`retired`).map(([e,t])=>[e,t.schema]))}function Br(e){return Object.entries(e).flatMap(([e,t])=>t.required?[e]:[])}function Vr(e){return Object.fromEntries(Object.entries(e).flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]))}function Hr(){return{oneOf:[...Wr(),{type:`object`,properties:{kind:{type:`string`,const:`point`},x:{type:`number`},y:{type:`number`}},required:[`kind`,`x`,`y`],additionalProperties:!1}],description:`UI target. This is separate from deviceTarget, which selects the device form.`}}function Ur(){return{oneOf:Wr(),description:`UI element target by snapshot ref or selector expression.`}}function Wr(){return[{type:`object`,properties:{kind:{type:`string`,const:`ref`},ref:{type:`string`,description:`Snapshot element ref such as @e12.`},label:{type:`string`,description:`Optional human label for the ref.`}},required:[`kind`,`ref`],additionalProperties:!1},{type:`object`,properties:{kind:{type:`string`,const:`selector`},selector:{type:`string`,description:`Agent-device selector expression.`}},required:[`kind`,`selector`],additionalProperties:!1}]}function L(e,t,n,r){return ar({name:e,description:t,inputSchema:kr(n),readInput:r?.readInput??(e=>Ar(e,n)),inputAudience:Vr(n),...r?.parseableOutput?{parseableOutput:!0}:{}})}function R(e){let t=rr(e.text,e.metadata.description),n=t.mcpDetail?{mcpDetail:t.mcpDetail}:{},r={...e.metadata,...n},i={name:r.name,description:r.description,inputSchema:r.inputSchema,...n,invoke:async(t,n)=>await e.run(t,r.readInput(n))};return{name:e.name,metadata:r,definition:i,cliSchema:{...e.cliSchema,text:t},cliReader:e.cliReader,daemonWriter:e.daemonWriter,cliOutputFormatter:e.cliOutputFormatter,text:t}}function Gr(e){return R({name:e.name,text:e.text,metadata:L(e.name,e.description,{}),run:e.run,cliSchema:{},cliReader:(e,t)=>x(t),daemonWriter:y(e.name),cliOutputFormatter:e.cliOutputFormatter})}function z(e){let t={},n={},r={},i={};for(let a of e.commands)Kr(t,`CLI schema`,a.name,a.cliSchema),Kr(n,`CLI reader`,a.name,a.cliReader),a.daemonWriter&&Kr(r,`daemon writer`,a.name,a.daemonWriter),a.cliOutputFormatter&&Kr(i,`CLI output formatter`,a.name,a.cliOutputFormatter);return{name:e.name,clientSurface:e.clientSurface,metadata:e.commands.map(e=>e.metadata),definitions:e.commands.map(e=>e.definition),cliSchemas:t,cliReaders:n,daemonWriters:r,cliOutputFormatters:i}}function Kr(e,t,n,r){if(Object.hasOwn(e,n))throw Error(`Duplicate command family ${t}: ${n}`);e[n]=r}function qr(e){let t=[`Batch completed: ${e.executed}/${e.total} steps in ${e.totalDurationMs}ms`];for(let n of e.results)t.push(Yr(n));return{data:e,text:t.join(`
2
+ `)}}const Jr={batch:d(qr)};function Yr(e){let t=Ct(e.data)??e.command;return`${e.step}. OK ${t} (${e.durationMs}ms)`}function Xr(e=Oe){let t=Zr(e);return L(`batch`,`Execute multiple commands in one daemon request.`,t,{readInput:e=>$r(e,t)})}function Zr(e){return{steps:O(wr({type:`array`,description:`Structured batch steps. Each step uses a command name and the same input object as that command tool.`,items:Qr(e)},(t,n)=>ei(t[n],e))),onError:N([`stop`],`Batch failure policy.`),maxSteps:j(`Maximum number of steps accepted for this batch.`,{min:1,max:1e3}),out:k(`Optional output path for command artifacts.`)}}function Qr(e){return{type:`object`,properties:{command:{type:`string`,enum:e,description:`Command name to run with structured input.`},input:{type:`object`,additionalProperties:!0,commandInputFor:`command`,description:`Structured command input for the nested command. Use the matching MCP tool schema for this object.`},runtime:{type:`object`,additionalProperties:!0,description:`Optional per-step runtime payload.`}},required:[`command`,`input`],additionalProperties:!1}}function $r(t,n){let r=Ar(t,n),i=r.maxSteps??100;if(!se(i))throw new e(`INVALID_ARGS`,`Invalid batch maxSteps: ${String(r.maxSteps)}`);return pe(r.steps.length,i),{...r}}function ei(t,n){if(!Array.isArray(t))throw new e(`INVALID_ARGS`,`Expected steps to be an array.`);return t.map((e,t)=>ti(e,t+1,n))}function ti(e,t,n){let r=ce(e,t);return wn(r,[`command`,`input`,`runtime`],`Batch step ${t}`,de),{command:ni(r,t,n),input:me(r,t),...ri(r,t)}}function ni(t,n,r){if(r===Oe)return Ie(t.command,n);let i=t.command;if(typeof i!=`string`||!r.includes(i))throw new e(`INVALID_ARGS`,`Expected command to be one of: ${r.join(`, `)}.`);return i}function ri(e,t){let n=ue(e.runtime,t);return n===void 0?{}:{runtime:n}}function ii(e){return async t=>b(u.batch,[],{...t,batchSteps:await ai(t.steps,e),batchOnError:t.onError,batchMaxSteps:t.maxSteps})}async function ai(t,n){if(!Array.isArray(t)||t.length===0)throw new e(`INVALID_ARGS`,`batch requires a non-empty steps array.`);let r=[];for(let[e,i]of t.entries())r.push(await oi(i,e+1,n));return r}async function oi(e,t,n){let r=ce(e,t),i=si(r,t),a=me(r,t),o=ue(r.runtime,t),s=await n(i,a,t);return{command:s.command,positionals:s.positionals,...s.input?{input:s.input}:{},flags:cn(s.options,s.metadataFlags),runtime:o??s.options.runtime}}function si(e,t){return Ie(e.command,t)}const ci=Xr(),li={usageOverride:`batch [--steps <json> | --steps-file <path>]`,usageFlags:[],listUsageOverride:`batch --steps <json> | --steps-file <path>`,allowedFlags:[`steps`,`stepsFile`,`batchOnError`,`batchMaxSteps`,`out`]},ui=(e,t)=>({...x(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out}),di=[{command:`snapshot`,input:{interactiveOnly:!0}},{command:`press`,input:{target:{kind:`ref`,ref:`@e12`},settle:!0}},{command:`fill`,input:{target:{kind:`selector`,selector:`id="field-email"`},text:`qa@example.com`}}];function fi(){return`${[`Each step is {"command":"<name>","input":{...}}, and input is that command's structured input object rather than its terminal spelling: a CLI positional becomes a named field (target, text, direction) and a CLI flag becomes a camelCase key (--settle -> "settle":true, -i -> "interactiveOnly":true). There is no positional step form; args, argv, positionals, and flags are not step fields. agent-device help <command> lists arguments in CLI spelling only. The examples below carry the structured spelling; over MCP, the command tool schema states it in full.`,`Steps run serially in one daemon request against the same session, in order. Mutating UI verbs are included (press, click, fill, longpress, scroll, back), which is where the round-trip saving is; --on-error stop halts at the first failing step.`,`Available through batch: ${[...Oe].sort().join(`, `)}.`,`Every other command is excluded: batch and replay never nest, and session, daemon, connection, and host tooling commands own lifecycle a batch request cannot carry. Run those on their own.`].join(` `)}\n\nExamples:\n${[` agent-device batch --steps '${JSON.stringify(di)}'`,` agent-device batch --steps-file ./steps.json --json`].join(`
3
+ `)}`}const pi=z({name:`batch`,clientSurface:!1,commands:[R({name:`batch`,text:{summary:`Run multiple commands`,cliDetail:fi()},metadata:ci,run:(e,t)=>e.batch.run(mi(t)),cliSchema:li,cliReader:ui,cliOutputFormatter:Jr.batch})]});function mi(e){return{...v(e),steps:e.steps,onError:e.onError,maxSteps:e.maxSteps,out:e.out}}const hi=`alert`,gi=R({name:hi,text:{summary:`Inspect, accept, or dismiss a platform alert`},metadata:L(hi,`Inspect, wait for, accept, or dismiss a platform alert. Use get before acting when the alert content matters; accept and dismiss change the active alert state. Each iOS XCTest execution activates once, then only observes. Inspect again after an unconfirmed action; never assume a timeout means nothing happened.`,{action:N(Tt),timeoutMs:j()}),run:(e,t)=>e.command.alert(t),cliSchema:{usageOverride:`alert [get|accept|dismiss|wait] [timeout]`,positionalArgs:[`action?`,`timeout?`]},cliReader:(e,t)=>({...x(t),...vi(e)}),daemonWriter:y(u.alert,e=>_i(e)),cliOutputFormatter:p});function _i(e){return[e.action??`get`,...T(e.timeoutMs)]}function vi(t){if(t.length>2)throw new e(`INVALID_ARGS`,`alert accepts at most action and timeout arguments.`);return _({action:yi(t[0]),timeoutMs:$n(t[1],`alert timeout`)})}function yi(t){let n=t?.toLowerCase();if(n===void 0||n===`get`||n===`accept`||n===`dismiss`||n===`wait`)return n;throw new e(`INVALID_ARGS`,`alert action must be get, accept, dismiss, or wait.`)}function B(...e){return e}const bi=B(`snapshotInteractiveOnly`,`snapshotDepth`,`snapshotScope`,`snapshotRaw`),V=B(`snapshotDepth`,`snapshotScope`,`snapshotRaw`),xi=B(`metroProjectRoot`,`kind`,`metroKind`,`metroPublicBaseUrl`,`metroProxyBaseUrl`,`metroBearerToken`,`metroPreparePort`,`metroListenHost`,`metroStatusHost`,`metroStartupTimeoutMs`,`metroProbeTimeoutMs`,`metroRuntimeFile`,`metroNoReuseExisting`,`metroNoInstallDeps`),Si=B(`metroHost`,`metroPort`,`bundleUrl`),Ci=B(`count`,`intervalMs`,`holdMs`,`jitterPx`,`doubleTap`),wi=B(`settle`,`settleQuietMs`,`timeoutMs`),Ti=B(`replayUpdate`,`replayEnv`),Ei=B(`remoteConfig`,`stateDir`,`daemonBaseUrl`,`daemonAuthToken`,`daemonTransport`,`daemonServerMode`,`tenant`,`sessionIsolation`,`runId`,`leaseId`,`leaseBackend`,`sessionLock`,`platform`,`target`,`device`,`providerApp`,`providerOsVersion`,`providerProject`,`providerBuild`,`providerSessionName`,`providerDeviceOrientation`,`providerGeoLocation`,`providerTimezone`,`providerAppiumVersion`,`providerLanguage`,`providerLocale`,`providerNetworkProfile`,`providerCustomNetwork`,`providerNoResignApp`,`awsProjectArn`,`awsDeviceArn`,`awsAppArn`,`awsRegion`,`awsInteractionMode`,`udid`,`serial`,`iosSimulatorDeviceSet`,`iosXctestrunFile`,`iosXctestDerivedDataPath`,`iosXctestEnvDir`,`androidDeviceAllowlist`,`session`,`noRecord`),Di=new Set([`platform`,`device`,`udid`,`serial`,`session`]),Oi=new Set([`json`,`config`,`help`,`version`,`verbose`,`cost`,`responseLevel`]),ki=`diff`,Ai=R({name:ki,text:{summary:`Diff snapshot or screenshot`,cliDetail:`Screenshot --threshold is a per-pixel RGB tolerance: 0 requires exact colors and 1 ignores color differences; image dimensions must still match. Both screenshot inputs are decoded from their bytes, so a baseline or current image may be PNG or JPEG, and the diff image is always PNG. JPEG is lossy, so keep --threshold above 0 whenever either input is JPEG. Live iOS simulator screenshot diffs normalize status-bar chrome by default; use screenshot --normalize-status-bar when capturing reusable baselines.`},metadata:L(ki,`Compare accessibility snapshots or screenshots to identify UI changes. Use snapshot comparisons for semantic tree changes and screenshot comparisons for pixel differences.`,{kind:O(P({type:`string`,const:`snapshot`})),out:k(),interactiveOnly:M(),depth:j(),scope:k(),raw:M()}),run:(e,t)=>e.capture.diff(t),cliSchema:{usageOverride:`diff snapshot | diff screenshot --baseline <path> [current.png] [--out <diff.png>] [--threshold <0-1>] [--overlay-refs]`,usageFlags:[],positionalArgs:[`kind`,`current?`],allowedFlags:[...bi,`baseline`,`threshold`,`out`,`overlayRefs`]},cliReader:(t,n)=>{if(t[0]!==`snapshot`)throw new e(`INVALID_ARGS`,`Only diff snapshot is available through this parser.`);return{...x(n),kind:`snapshot`,out:n.out,interactiveOnly:n.snapshotInteractiveOnly,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw}},daemonWriter:y(u.diff,e=>[D(e.kind,`diff requires kind`)])}),ji=`screenshot`,Mi=R({name:ji,text:{summary:`Capture a screenshot`,cliDetail:`Web defaults to the viewport; use --fullscreen, --full, or -f for the entire page. iOS simulators default to 1x logical-point output; use --pixel-density to request a different screenshot density. macOS app sessions default to the app window; use --fullscreen for full desktop, --scale to downscale, --crop-on <selector> to crop the capture to the frame the selector resolves on the same screen (currently iOS simulators and Android emulators), --overlay-refs to annotate current refs, --normalize-status-bar for deterministic iOS simulator chrome, or --no-stabilize for low-latency Android capture loops.`},metadata:L(ji,`Capture a screenshot of the active app or web session. Choose the capture scope, density, size, or annotations through the corresponding input fields when needed.`,{path:k(`Output path.`),cropOn:k(`Selector expression; the capture is cropped to the frame the selector resolves on the same screen.`),overlayRefs:M(),pixelDensity:j(`Output screenshot pixel density in pixels per logical point.`,{min:1}),fullscreen:M(),scale:A(`Screenshot scale factor.`,ee),maxSize:gr(ie.migration.screenshot),stabilize:M(),normalizeStatusBar:M(),surface:N(st)}),run:(e,t)=>e.capture.screenshot(t),cliSchema:{positionalArgs:[`path?`],allowedFlags:ne},cliReader:(e,t)=>({...x(t),path:e[0]??t.out,...s(t)}),daemonWriter:e=>(c(`screenshot`,e),re(e),b(u.screenshot,w(e.path),{...e,...ae(e)}))}),Ni=`settings`,Pi=L(Ni,`Change supported operating-system settings, animation scales, appearance, or app permissions on the selected target. Platform support varies by setting and action.`,{setting:O(k()),state:O(k()),app:k(),latitude:A(),longitude:A(),permission:k(),mode:N([...At])}),Fi={usageOverride:kt,listUsageOverride:`settings [area] [options]`,positionalArgs:[`setting`,`state`,`target?`,`mode?`]},Ii=(e,t)=>zi(e,t),Li=y(u.settings,e=>Bi(e)),Ri=R({name:Ni,text:{summary:`Change OS settings and app permissions`,cliDetail:`macOS supports only settings appearance <light|dark|toggle> and settings ${Dt}; wifi|airplane|location|animations remain unsupported on macOS. Mobile permission actions use the active session app. On Android, deny|reset of a permission the app currently holds kills a running app; the response reports priorGrantState (granted|not_granted|unknown) and warns for granted and unknown, with open <app> --relaunch to restore it. Permission changes require a resolvable foreground user and fail without mutating if adb cannot report one. Android settings airplane on|off is applied by the connectivity service (Android 11+) and reports the airplaneMode that service holds; older builds fail without changing device state. settings reset-keychain clear is iOS-simulator-only and resets the whole simulator keychain, not just the selected app: simctl exposes no per-app keychain reset, so every app on that simulator loses its keychain-backed credentials (e.g. Firebase auth). clear-app-state does not touch the keychain, so a full fresh-install reset needs both; relaunch the app afterward to observe the signed-out state.`},metadata:Pi,run:(e,t)=>e.settings.update(t),cliSchema:Fi,cliReader:Ii,daemonWriter:Li,cliOutputFormatter:p});function zi(t,n){let r=In(n),i=t[0],a=t[1];if(C(i,Ui)&&C(a,Wi))return{...r,setting:i,state:a};if(i===`location`&&a===`set`)return{...r,setting:i,state:a,latitude:Mt(t[2],`latitude`),longitude:Mt(t[3],`longitude`)};if(i===`appearance`&&C(a,Gi)||C(i,Ki)&&C(a,qi)||i===`fingerprint`&&C(a,Ji))return{...r,setting:i,state:a};if(i===`permission`&&C(a,Xi))return{...r,setting:i,state:a,permission:Vi(t[2]),mode:Hi(t[3])};if(i===`clear-app-state`){let e=a===`clear`?t[2]:a;return{...r,setting:i,state:`clear`,app:e}}if(i===`reset-keychain`&&a===`clear`&&t.length===2)return{...r,setting:i,state:a};throw new e(`INVALID_ARGS`,`Invalid settings arguments.`)}function Bi(e){return e.setting===`clear-app-state`?[e.setting,...w(e.app)]:e.setting===`location`&&e.state===`set`?[e.setting,e.state,String(e.latitude),String(e.longitude)]:e.setting===`permission`?[e.setting,e.state,e.permission,...w(e.mode)]:[e.setting,e.state]}function Vi(t){if(C(t,Zi))return t;throw new e(`INVALID_ARGS`,`settings permission requires a permission target.`)}function Hi(t){if(t===void 0||C(t,Yi))return t;throw new e(`INVALID_ARGS`,`settings permission mode must be full or limited.`)}const Ui=S(`wifi`,`airplane`,`location`,`animations`),Wi=S(`on`,`off`),Gi=S(`light`,`dark`,`toggle`),Ki=S(`faceid`,`touchid`),qi=S(`match`,`nonmatch`,`enroll`,`unenroll`),Ji=S(`match`,`nonmatch`),Yi=S(...At),Xi=S(...Et),Zi=S(...Ot,...jt);function Qi(e){if(!Array.isArray(e)||e.length===0)return e;let t=Se(e);return e.map(e=>{let n=$i(e,t,e=>e.label),r=$i(e,t,e=>e.identifier),i=typeof e.label==`string`&&e.label.length>=24&&e.label===n,a=typeof e.identifier==`string`&&e.identifier.length>=24&&e.identifier===r;if(!i&&!a)return e;let o={...e};return i&&(delete o.label,o.inheritsLabel=!0),a&&(delete o.identifier,o.inheritsIdentifier=!0),o})}function $i(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0;for(;r;){let e=n(r);if(typeof e==`string`&&e.length>0)return e;r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}}function ea(e){return e.width>0&&e.height>0}function ta(e,t){return!e||!t?!1: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 na(e,t){if(!e||!t)return!0;let n=e.y+e.height/2,r=t.y+t.height/2;return Math.abs(n-r)<=Math.max(e.height,t.height,1)}function ra(e){return typeof e.parentIndex!=`number`}function ia(e){let t=(e.type??``).toLowerCase(),n=(e.identifier??``).trim().toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)||n===`composer`}function aa(e){let t=(e.type??``).toLowerCase();return t.includes(`scroll`)||t.includes(`list`)||t.includes(`recyclerview`)}function H(e){let t=be(e);if(!t||t!==e.identifier?.trim()||!sa(t))return t;let n=(e.type??``).toLowerCase();return n.includes(`view`)||n.includes(`layout`)||n.includes(`image`)||n.includes(`list`)||n.includes(`recyclerview`)||n.includes(`collection`)?``:t}function oa(e){let t=e.trim().replaceAll(/\s+/g,` `).toLowerCase();return!t||/^(true|false|\d+)$/.test(t)?null:t}function sa(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function ca(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){let e=t.get(r.parentIndex);if(!e)return null;if(n(e))return e;r=e}return null}function la(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 ua(e,t,n){let r=[t];for(;r.length>0;){let t=r.pop();if(!n.has(t)){n.add(t);for(let i of e)i.parentIndex!==t||n.has(i.index)||r.push(i.index)}}}const da=[`button`,`switch`,`checkbox`,`radio`],fa=[`button`,`image`,`textview`,`view`];function pa(e,t,n){for(let r of e){if(t.has(r.index)||!ga(r))continue;let i=_a(la(e,r.index),r,t);if(i.label){n.set(r.index,{...r,...n.get(r.index),label:i.label});for(let n of i.removableIndexes)ua(e,n,t)}}}function ma(e,t,n){let r=new Map;for(let i of e){if(t.has(i.index)||!Ta(i))continue;let a=oa(H(i));if(!a)continue;let o=r.get(a);if(o&&Sa(o,i,t)){let s=Ca(e,o,i,t,n);r.set(a,s);continue}r.set(a,i)}}function ha(e,t){for(let n of e){if(t.has(n.index)||!ba(n))continue;let r=oa(H(n));if(!r)continue;let i=la(e,n.index).filter(e=>!t.has(e.index)&&xa(n,e,r));for(let n of i.filter(ya))ua(e,n.index,t);let a=i.filter(e=>!ya(e)),o=new Set(a.map(e=>oa(H(e))).filter(e=>!!e));if(!(a.length<2||o.size<2))for(let n of a)ua(e,n.index,t)}}function ga(e){return e.hittable===!0&&!ia(e)&&!!(e.rect&&ea(e.rect))&&H(e).trim().length===0}function _a(e,t,n){let r=[],i=[],a=new Set;for(let o of e){if(n.has(o.index)||!va(o,e)||!ta(o.rect,t.rect))continue;let s=H(o).trim().replaceAll(/\s+/g,` `),c=oa(s);i.push(o.index),!(!s||!c||a.has(c))&&(a.add(c),r.push(s))}return{label:r.join(`, `),removableIndexes:i}}function va(e,t){if(ya(e))return!0;let n=(e.type??``).toLowerCase();return e.hittable!==!0&&!ia(e)&&n.includes(`view`)&&H(e).trim().length>0&&!t.some(t=>t.parentIndex===e.index)}function ya(e){if(e.hittable===!0||ia(e))return!1;let t=(e.type??``).toLowerCase();return t.includes(`text`)||t.includes(`image`)||t.includes(`icon`)}function ba(e){return e.hittable===!0&&!ia(e)&&!!(e.rect&&ea(e.rect))&&!!oa(H(e))}function xa(e,t,n){if(!Ta(t)||!ta(t.rect,e.rect))return!1;let r=oa(H(t));return!!(r&&n!==r&&n.includes(r))}function Sa(e,t,n){return!n.has(e.index)&&na(e.rect,t.rect)&&(Aa(e,t)||ka(e,t))}function Ca(e,t,n,r,i){let a=Ea(t,n),o=a.index===t.index?n:t,s=(o.type??``).toLowerCase().includes(`image`)?`has image`:null,c=i.get(a.index)??a,ee=i.get(o.index)?.presentationHints??o.presentationHints;return i.set(a.index,{...c,presentationHints:wa(c.presentationHints,ee,s)}),ua(e,o.index,r),i.get(a.index)??a}function wa(e,t,n){return[...new Set([...Array.isArray(e)?e:[],...Array.isArray(t)?t:[],...n?[n]:[]])]}function Ta(e){if(!e.rect||!ea(e.rect)||ra(e)||ia(e))return!1;let t=(e.type??``).toLowerCase();return t===`text`||Oa(t,fa)}function Ea(e,t){let n=Da(e);return Da(t)>n?t:e}function Da(e){let t=(e.type??``).toLowerCase(),n=0;return Oa(t,da)?n+=100:t.includes(`image`)?n+=30:t.includes(`textview`)||t===`text`?n+=20:t.includes(`view`)&&(n+=10),e.hittable===!0&&(n+=20),e.enabled!==!1&&(n+=5),n}function Oa(e,t){return t.some(t=>e.includes(t))}function ka(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?!1:Ea(n,r).index===n.index}function Aa(e,t){return e.parentIndex===t.parentIndex?Math.abs(e.index-t.index)<=3:e.parentIndex===t.index||t.parentIndex===e.index?!1:Math.abs((e.depth??0)-(t.depth??0))<=1&&Math.abs(e.index-t.index)<=2}function ja(e,t,n){if(n.raw||!Ma(e))return{nodes:t,filteredCount:0};let r=Na(t);return{nodes:r,filteredCount:t.length-r.length}}function Ma(e){let t=e.androidSnapshot;return!t||typeof t!=`object`?!1:t.backend===`android-helper`}function Na(e){if(e.length===0)return e;let t=new Set,n=new Map,r=new Map(e.map(e=>[e.index,e]));return Pa(e,t),Fa(e,r,t,n),pa(e,t,n),ha(e,t),ma(e,t,n),e.filter(e=>!t.has(e.index)).map(e=>n.get(e.index)??e)}function Pa(e,t){for(let n of e)!n.rect||ea(n.rect)||ra(n)||ua(e,n.index,t)}function Fa(e,t,n,r){for(let i of e){if(n.has(i.index)||i.rect||ra(i))continue;let a=ca(i,t,aa);a&&La(r,a,Ia(i,e)),ua(e,i.index,n)}}function Ia(e,t){let n=t.filter(t=>t.parentIndex===e.parentIndex&&t.rect&&ea(t.rect)).map(e=>e.index);return n.length===0?null:e.index<Math.min(...n)?`above`:e.index>Math.max(...n)?`below`:null}function La(e,t,n){if(!n)return;let r=e.get(t.index)??t;e.set(t.index,{...r,hiddenContentAbove:r.hiddenContentAbove===!0||n===`above`||void 0,hiddenContentBelow:r.hiddenContentBelow===!0||n===`below`||void 0})}function Ra(e){if(e.length<20)return!1;let t=new Map;for(let n of e){let e=(n.type??``).toLowerCase(),r=za(be(n));if(!r)continue;let i=`${e}|${r}`,a=t.get(i)??[];a.push(n),t.set(i,a)}let n=0;for(let e of t.values())e.length<=1||!Va(e)||(n+=e.length);return n>=8}function za(e){let t=e.trim().replaceAll(/\s+/g,` `).toLowerCase();return!t||Ba(t)?null:t}function Ba(e){return/\S+@\S+\.\S+/.test(e)}function Va(e){for(let t=0;t<e.length;t+=1)for(let n=t+1;n<e.length;n+=1)if(Ha(e[t]?.rect,e[n]?.rect))return!0;return!1}function Ha(e,t){if(!e||!t)return!0;let n=.5;return!(e.x+e.width<=t.x+n||t.x+t.width<=e.x+n||e.y+e.height<=t.y+n||t.y+t.height<=e.y+n)}function Ua(e,n={}){let r=e.nodes,i=Array.isArray(r)?r:[],a=o(e.backend)?e.backend:void 0,s=t(a),c=ja(e,i,n),ee=qa(e),te=no(e,i,n,c),ne=te.length>0?`${te.join(`
4
+ `)}\n`:``,re=n.raw?null:Wa(e);if(re)return`${ee}${ne}${Ga(re)}\n`;let ie=n.raw||!s?null:Bt(c.nodes),ae=!!e.truncated,oe=ie?.nodes??i,se=n.raw||!s?null:$a(e,ie,oe.length,i.length,c.filteredCount),ce=Ja(i.length,se,ae);return i.length===0?`${ee}${ce}\n${ne}`:n.raw?`${ee}${ce}\n${ne}${Ya(i)}\n`:n.flatten?`${ee}${ce}\n${ne}${Xa(oe)}${Qa(ie)}\n`:`${ee}${ce}\n${ne}${Za(oe)}${Qa(ie)}\n`}function Wa(e){let t=e.unchanged;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.ageMs!=`number`||typeof n.nodeCount!=`number`?null:{ageMs:n.ageMs,nodeCount:n.nodeCount,interactiveOnly:n.interactiveOnly===!0||void 0,scope:typeof n.scope==`string`?n.scope:void 0}}function Ga(e){let t=Ka(e.ageMs);return e.scope?[`Scoped snapshot unchanged for scope "${e.scope}" since previous read ${t} ago.`,`Previous refs in this scope remain valid. Use find/get/is for a targeted query, or --force-full to re-emit.`].join(`
5
5
  `):e.interactiveOnly?[`Interactive snapshot unchanged since previous read ${t} ago.`,`${e.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.`].join(`
6
6
  `):[`Snapshot unchanged since previous read ${t} ago.`,`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.`].join(`
7
- `)}function Wa(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;if(t<60)return`${(Math.round(t*10)/10).toFixed(1)}m`;let n=t/60;return`${(Math.round(n*10)/10).toFixed(1)}h`}function Ga(e){let t=typeof e.appName==`string`?e.appName:void 0,n=typeof e.appBundleId==`string`?e.appBundleId:void 0,r=[];return t&&r.push(`Page: ${t}`),n&&r.push(`App: ${n}`),r.length>0?`${r.join(`
8
- `)}\n`:``}function Ka(e,t,n){let r=n?` (truncated)`:``;return t?.partial?t.totalNodeCount>t.visibleNodeCount?`Snapshot: ${t.visibleNodeCount} visible nodes (${t.totalNodeCount} total)${r}`:`Snapshot: ${t.visibleNodeCount} visible nodes${r}`:`Snapshot: ${e} nodes${r}`}function qa(e){return e.map(e=>JSON.stringify(e)).join(`
9
- `)}function Ja(e){return lo(e).join(`
10
- `)}function Ya(e){return oo(Rt(e,{summarizeTextSurfaces:!0})).join(`
11
- `)}function Xa(e){return e&&e.summaryLines.length>0?`\n${e.summaryLines.join(`
12
- `)}`:``}function Za(e,t,n,r,i=0){let a=Qa(e);if(i===0&&a)return a;let o=(t?.hiddenCount??0)+i,s=t?t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow):!1;return o>0?{partial:!0,visibleNodeCount:n,totalNodeCount:Math.max(r,a?.totalNodeCount??r),reasons:$a([...a?.reasons??[],`offscreen-nodes`])}:a||(s?{partial:!0,visibleNodeCount:n,totalNodeCount:n,reasons:[]}:null)}function Qa(e){let t=e.visibility;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.partial!=`boolean`||typeof n.visibleNodeCount!=`number`||typeof n.totalNodeCount!=`number`||!Array.isArray(n.reasons)?null:{partial:n.partial,visibleNodeCount:n.visibleNodeCount,totalNodeCount:n.totalNodeCount,reasons:n.reasons.filter(e=>typeof e==`string`)}}function $a(e){return[...new Set(e)]}function eo(e,t,n,r={nodes:t,filteredCount:0}){let i=[...ao(e),...to(e)];if(no(e)){let e=io(t,n);e&&i.push(e)}!n.raw&&r.filteredCount>0&&i.push(`Collapsed ${r.filteredCount} Android helper node${r.filteredCount===1?``:`s`} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let a=r.filteredCount>0?r.nodes:t;return!n.raw&&Ia(a)&&i.push(`Warning: possible repeated nav subtree detected.`),i}function to(e){let t=e.fallbackScreenshotPath;return typeof t==`string`&&t.length>0?[`Captured a screenshot of this screen automatically as visual truth: ${t}`]:[]}function no(e){return!e.snapshotQuality&&!ro(e)}function ro(e){let t=e.snapshotDiagnostics;if(!t||typeof t!=`object`)return!1;let n=t.stats;return!!(n&&typeof n==`object`&&n.platform===`web`)}function io(e,t){if(t.scoped===!0||t.depthLimited===!0||e.length>3)return null;let n=e.length===1?`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.`}function ao(e){return xt(e).filter(e=>e.length>0)}function oo(e){let t=[],n=[],r=new Map(e.map(e=>[e.node.index,e.node])),i=e=>{for(;n.length>0&&(!e||so(e,n.at(-1),r));)t.push(...uo(n.pop(),`below`))};for(let r of e)i(r),t.push(r.text),t.push(...uo(r,`above`)),r.node.hiddenContentBelow&&n.push(r);return i(),t}function so(e,t,n){return!co(e.node,t.node,n)&&e.depth<=t.depth}function co(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){if(r.parentIndex===t.index)return!0;let e=n.get(r.parentIndex);if(!e)return!1;r=e}return!1}function lo(e){return Rt(e,{summarizeTextSurfaces:!0}).flatMap(e=>[Lt(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...uo({...e,depth:0})])}function uo(e,t){let n=fo(e.type);if(!n)return[];let r=[];if(e.node.hiddenContentAbove&&t!==`below`&&r.push(`[content above ${n} hidden]`),e.node.hiddenContentBelow&&t!==`above`&&r.push(`[content below ${n} hidden]`),r.length===0)return[];let i=` `.repeat(e.depth+1);return r.map(e=>`${i}${e}`)}function fo(e){return e===`scroll-area`||e===`list`||e===`collection`||e===`table`?e:null}async function po(e){let{serializeSnapshotResult:t}=await import(`./result-serialization.js`).then(e=>e.t),n=t(e.raw||!Array.isArray(e.result.nodes)?e.result:{...e.result,nodes:Xi(e.result.nodes)});return{data:n,jsonData:ho(n),stderr:e.result.snapshotDiagnostics?.warning?`${e.result.snapshotDiagnostics.warning}\n`:void 0,text:Va(n,{raw:e.raw,flatten:e.interactiveOnly,scoped:typeof e.scope==`string`&&e.scope.trim().length>0,depthLimited:typeof e.depth==`number`})}}const mo={snapshot:async({input:e,result:t})=>await po({result:t,raw:e.raw,interactiveOnly:e.interactiveOnly,scope:e.scope,depth:e.depth}),wait:p,alert:p};function ho(e){let{unchanged:t,...n}=e;return n}const go=`snapshot`,_o=Object.entries(Pt).map(([e,t])=>{let n=t.knownGaps.map(e=>`known gap ${e}`);return`${e}: hittable=${t.hittable}, regular-depth=${t.regularDepth}, deep-extension=${t.deepExtension}, depth-ladder=${t.depthLadder}${n.length>0?`, ${n.join(`, `)}`:``}`}).join(`; `),vo=R(go,`Capture the accessibility tree or compare it with the previous session baseline. Use the returned refs for subsequent semantic interactions and the diff option to verify UI changes.`,{interactiveOnly:P(),depth:N(),scope:j(),raw:P(),customActions:br(`snapshotCustomActions`),forceFull:P(),timeoutMs:N(`Maximum wall-clock time for the snapshot command.`),noRecord:P(`Do not record this action.`),record:P(`Force-record this out-of-band observation into a repair-armed heal (mutually exclusive with noRecord). Authored replay steps are recorded automatically and never need this.`)}),yo={allowedFlags:[`snapshotDiff`,...vi,`snapshotCustomActions`,`snapshotForceFull`,`timeoutMs`,`record`]},bo=(e,t)=>({...b(t),...Pn(t),...o(t,a),timeoutMs:t.timeoutMs}),xo=v(d.snapshot),So=D({name:go,text:{summary:`Capture or diff the accessibility tree`,cliDetail:`Repeated equivalent unfiltered Android snapshots return a compact unchanged acknowledgement. Use --force-full to re-emit the tree; --json and --raw retain full output. For iOS raw-coordinate fallback after a no-op ref press, inspect rects with snapshot -i --json, press the rect center, then verify with diff snapshot -i or snapshot --diff. iOS backend capability contract: ${_o}.`},metadata:vo,run:(e,t)=>e.capture.snapshot(t),cliSchema:yo,cliReader:bo,daemonWriter:xo,cliOutputFormatter:mo.snapshot}),Co=[`duration`,`text`,`ref`,`selector`,`absent`,`stable`],wo=`wait`,To=D({name:wo,text:{summary:`Wait for a duration, text, selector, strict absence, or stable UI`},metadata:R(wo,`Wait for a duration, text, snapshot ref, selector to appear, selector to be strictly absent, or stable UI. Use the strict absence target when zero selector matches are required; stable waits until the UI stays quiet for the requested window.`,{kind:F(Co),durationMs:N(),text:j(),ref:j(),selector:j(),absent:j(),stable:P(),quietMs:N(),timeoutMs:N(),depth:N(),scope:j(),raw:P()}),run:(e,t)=>e.command.wait(Eo(t)),cliSchema:{usageOverride:`wait <ms>|text <text>|@ref|<selector>|absent <selector> [timeoutMs]|stable [quietMs] [timeoutMs]`,usageFlags:[],positionalArgs:[`durationOrSelector`,`timeoutMs?`],allowsExtraPositionals:!0,allowedFlags:[...B]},cliReader:(e,t)=>Do(e,t),daemonWriter:v(d.wait,e=>Ao(e)),cliOutputFormatter:p});function Eo(e){bn(e,`kind`,Co);let t={...e};return delete t.kind,t}function Do(t,n){let r=Ae(t);if(!r)throw new e(`INVALID_ARGS`,`wait requires <ms>, text <text>, @ref, <selector> [timeoutMs], absent <selector> [timeoutMs], or stable [quietMs] [timeoutMs].`);let i={...Fn(n),...Ln(n)};switch(r.kind){case`absent`:return Oo(i,r);case`sleep`:return{...i,durationMs:r.durationMs};case`text`:return ko(i,r);case`ref`:return{...i,ref:r.rawRef,...jo(r.timeoutMs)};case`stable`:return{...i,stable:!0,...Mo(r.quietMs),...jo(r.timeoutMs)};case`invalid`:throw new e(`INVALID_ARGS`,r.message);case`selector`:return{...i,selector:r.selectorExpression,...jo(r.timeoutMs)};default:return No(r)}}function Oo(e,t){let n=Ft(e);if(n)throw zt(n,`wait`);return{...e,absent:t.selectorExpression,...jo(t.timeoutMs)}}function ko(t,n){if(!n.text)throw new e(`INVALID_ARGS`,`wait requires text.`);return{...t,text:n.text,...jo(n.timeoutMs)}}function Ao(t){if([t.durationMs===void 0?void 0:`durationMs`,t.text===void 0?void 0:`text`,t.ref===void 0?void 0:`ref`,t.selector===void 0?void 0:`selector`,t.absent===void 0?void 0:`absent`,t.stable===void 0?void 0:`stable`].filter(Boolean).length!==1)throw new e(`INVALID_ARGS`,`wait command requires exactly one of durationMs, text, ref, selector, absent, or stable.`);if(t.durationMs!==void 0)return[String(t.durationMs)];let n=w(t.timeoutMs);if(t.text!==void 0)return[`text`,t.text,...n];if(t.ref!==void 0)return[t.ref,...n];if(t.absent!==void 0){let r=Ft(t);if(r)throw zt(r,`wait`);if(!De(t.absent))throw new e(`INVALID_ARGS`,`Invalid wait absent selector: ${t.absent}`);return[`absent`,t.absent,...n]}if(t.stable!==void 0){let r=w(t.quietMs);if(r.length===0&&n.length>0)throw new e(`INVALID_ARGS`,`wait stable requires quietMs before timeoutMs.`);return[`stable`,...r,...n]}let r=t.selector;if(!De(r))throw new e(`INVALID_ARGS`,`Invalid wait selector: ${r}`);return[r,...n]}function jo(e){return e===null?{}:{timeoutMs:e}}function Mo(e){return e===null?{}:{quietMs:e}}function No(e){throw Error(`Unsupported wait positional target: ${String(e)}`)}const Po=O({name:`capture`,commands:[So,Ai,Oi,To,mi,Ii]});function Fo(e){let t=[e.outPath,e.message];t.push(...Lo(e));for(let n of 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(`
13
- `)}}const Io={debug:f(Fo)};function Lo(e){let t=e.crash,n=[`Crash: ${t.appName??`unknown app`}${t.crashedThread===void 0?``:` thread ${t.crashedThread}`}`];t.bundleId&&n.push(`Bundle: ${t.bundleId}`),t.exceptionType&&n.push(`Exception: ${t.exceptionType}`),t.terminationReason&&n.push(`Termination: ${t.terminationReason}`);for(let e of 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}const Ro=`debug`,zo=O({name:`debugging`,commands:[D({name:Ro,text:{summary:`Symbolicate Apple crash artifacts`},metadata:R(Ro,`Symbolicate Apple crash artifacts with matching dSYM UUIDs. This debug namespace is intentionally narrow: use logs for app logs, network for HTTP evidence, perf for performance samples, record/trace for media and traces, and react-devtools for React Native profiles.`,{action:A(F([`symbols`])),artifact:A(j(`Apple crash artifact path (.ips, .crash, or .log).`)),dsym:j(`Path to a matching .dSYM bundle.`),searchPath:j(`Directory to scan for matching .dSYM bundles.`),out:j(`Output path for the symbolicated artifact.`)}),run:(e,t)=>e.debug.symbols(t),cliSchema:{usageOverride:`debug symbols --artifact <crash.ips|crash.log> (--dsym <App.dSYM> | --search-path <dir>) [--out <symbolicated>]`,usageFlags:[],listUsageOverride:`debug`,positionalArgs:[`symbols`],allowedFlags:[`artifact`,`dsym`,`searchPath`,`out`]},cliReader:(e,t)=>({...b(t),action:Bo(e[0]),artifact:t.artifact,dsym:t.dsym,searchPath:t.searchPath,out:t.out}),cliOutputFormatter:Io.debug})]});function Bo(t){if(t===`symbols`)return t;throw new e(`INVALID_ARGS`,`debug supports only symbols; use logs, network, perf, record, trace, or react-devtools for other diagnostics`)}const Vo=()=>P(`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot.`),Ho=()=>({settle:P(`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response. Best-effort; never fails the action.`),settleQuietMs:N(`Settle: quiet window in milliseconds (default 500).`,{min:0}),timeoutMs:N(`Settle: wait deadline in milliseconds (default 10000).`,{min:1})});function H(e){return{...ke(e)?{verify:Vo()}:{},...Me(e)?Ho():{}}}function U(e){let t=[];return ke(e)&&t.push(`verify`),Me(e)&&t.push(...Si),t}function Uo(e,t){return Me(e)?Rn(t):{}}const Wo=[`click`,`focus`,`exists`,`list`,`getText`,`getAttrs`,`wait`,`fill`,`type`],Go={click:`Activate a UI target by snapshot ref, selector, or coordinates. Prefer a ref or selector after a snapshot; use coordinates only when semantic targeting is unavailable. This can change app state; use settle or verify to confirm the result without a follow-up snapshot.`,press:`Short-press a UI target by snapshot ref, selector, or coordinates. Use longpress instead when the target requires a context-menu or hold gesture.`,fill:`Replace text in a UI input selected by snapshot ref, selector, or coordinates. Pass an empty text to clear the field. Prefer refs or selectors after snapshot; use recordAs to keep sensitive text out of a recorded replay while sending it to the live app.`,longpress:`Hold a UI target by snapshot ref, selector, or coordinates to open a context menu or perform another hold gesture. Set durationMs when the default hold duration is unsuitable.`,hover:`Move the pointer over a UI target by snapshot ref, selector, or coordinates without pressing, to reveal hover-gated UI such as row toolbars or menus. Web only; touch platforms have no hover state. Use settle to observe what the hover revealed without a follow-up snapshot.`,swipe:`Quick coordinate fling with optional repeat pattern.`,focus:`Move input focus to explicit screen coordinates without entering text. Prefer semantic interactions when a snapshot ref or selector is available; use type or fill after focus.`,type:`Append text to the currently focused input. Use fill when the existing field value should be replaced, and focus first when no input is active.`,scroll:`Scroll in a direction, or toward the top/bottom edge of scrollable content. Set until to a selector to reach an off-screen target in one command rather than a scroll-and-check loop. The optional amount is the finger-path fraction of the viewport axis, honored up to 0.8 of it; directional scrolls reduce release momentum, while app scroll physics determine the final content offset. A visible keyboard shortens the swiped band instead of being dismissed; when too little is left, the command refuses with scroll_keyboard_occludes_surface.`,get:`Read text or accessibility attributes from a snapshot ref or selector without changing the app. Use format text for visible content or attrs for the element attribute map.`,is:"Check whether a selector satisfies a UI predicate such as visible, hidden, exists, absent, editable, selected, focused, or text. `absent` passes only when one readable, complete, unscoped, full-depth accessibility capture has zero matches. Use wait when the condition may appear asynchronously.",find:`Find by text/label/value/role/id and run action`,gesture:`Perform a structured pan, fling, swipe, pinch, rotate, transform, or drag gesture. Select the gesture kind, then provide only the inputs that apply to that kind.`},Ko={target:A(Dr()),button:F(Ht,`Pointer button for platforms that support mouse buttons.`),...Ar(),...jr(),...H(`click`)},qo={target:A(Dr()),...Ar(),...jr(),...H(`press`)},Jo={target:A(Dr()),text:A(j(`Text to enter into the target. Pass "" to clear it.`,{allowEmpty:!0})),delayMs:N(`Delay between typed characters.`,{min:0}),recordAs:j("When script recording is armed, send text to the live app but publish it as ${VAR}. Use an uppercase replay variable name such as PASSWORD."),...Ar(),...H(`fill`)},Yo={target:A(Dr()),durationMs:N(`Long press duration in milliseconds.`,{min:0}),...Ar(),...H(`longpress`)},Xo={target:A(Dr()),...Ar(),...H(`hover`)},Zo={from:A(kr(`Swipe start point.`)),to:A(kr(`Swipe end point.`)),count:N(`Number of swipe repetitions.`,{min:1,max:200}),pauseMs:N(`Pause between repeated swipes.`,{min:0,max:We}),pattern:F(He)},Qo={x:A(M(`X coordinate.`)),y:A(M(`Y coordinate.`))},$o={text:A(j(`Text to type.`)),delayMs:N(`Delay between typed characters.`,{min:0})},es={direction:A(F(Ge)),amount:M(`Platform scroll amount.`),pixels:N(`Pixel scroll amount.`,{min:0}),until:j(`Repeat scroll passes until this selector is visible on screen, then stop. Not valid with the top/bottom edge directions, which carry their own stop condition.`),durationMs:N(`Scroll duration in milliseconds when the backend supports pacing.`,{min:0,max:Ut}),...H(`scroll`)},ts=()=>({noRecord:P(`Do not record this action.`),record:P(`Force-record this out-of-band observation into a repair-armed heal (mutually exclusive with noRecord). Authored replay steps are recorded automatically and never need this. On find, valid only for a read-only action.`)}),ns={format:A(F([`text`,`attrs`])),target:A(Or()),...Ar(),...ts()},rs={predicate:A(F(Ce)),selector:A(j()),value:j(),...Ar(),...ts()},is={locator:F(Se),query:A(j()),action:F(Wo),value:j(void 0,{allowEmpty:!0}),timeoutMs:N(),first:P(),last:P(),depth:N(),raw:P(),...ts()},as={kind:A(F(Je,`Gesture variant.`)),direction:F(Ue,`Fling direction.`),preset:F(Ke,`Swipe preset.`),origin:kr(`Gesture origin point.`),delta:kr(`Movement delta for pan or transform gestures.`),distance:N(`Fling distance.`,{min:0}),scale:M(`Pinch or transform scale.`),degrees:M(`Rotation in degrees.`),durationMs:N(`Pan/transform duration.`,{min:16,max:1e4}),pointerCount:N(`Pan touch pointer count (1 or 2).`,{min:1,max:2}),source:j(`Drag source @ref or selector.`),destination:j(`Drag destination @ref or selector.`),sourceHoldMs:N(`Drag activation hold duration.`,{min:1,max:1e4}),moveMs:N(`Drag movement duration.`,{min:16,max:1e4}),destinationHoldMs:N(`Hold before releasing at the destination.`,{min:0,max:1e4})},os=[W(`click`,Ko),W(`press`,qo),W(`fill`,Jo),W(`longpress`,Yo),W(`hover`,Xo),W(`swipe`,Zo),W(`focus`,Qo),W(`type`,$o),W(`scroll`,es),W(`get`,ns),W(`is`,rs),W(`find`,is),R(`gesture`,Go.gesture,as,{readInput:ss})];function ss(e){let t=pn(e);return{...kn(t),...qe(t)}}function W(e,t){return R(e,Go[e],t)}const cs={gesture:us},ls={gesture:e=>{let t=ss(e);return y(d.gesture,[],e,g(t))}};function us(e,t){return{...b(t),...Ye(e,t.pointerCount)}}const G={click:(e,t)=>({...b(t),...In(t),...zn(t),target:Bn(Wt(e)),button:t.clickButton,verify:t.verify}),press:(e,t)=>({...b(t),...In(t),...zn(t),target:Bn(Wt(e)),verify:t.verify}),longpress:(e,t)=>{let n=ds(e);return{...b(t),...In(t),target:Bn(n),durationMs:n.durationMs}},hover:(e,t)=>({...b(t),...In(t),target:Bn(Wt(e))}),swipe:(e,t)=>({...b(t),...Ze(e,{count:t.count,pauseMs:t.pauseMs,pattern:t.pattern})}),focus:(e,t)=>({...b(t),x:Number(e[0]),y:Number(e[1])}),type:(e,t)=>({...b(t),text:e.join(` `),delayMs:t.delayMs}),fill:(e,t)=>{let n=Gt(e);return{...b(t),...In(t),target:Bn(n.target),text:n.text,delayMs:t.delayMs,recordAs:t.recordAs,verify:t.verify}},scroll:(e,t)=>({...b(t),direction:hs(e[0]),amount:$n(e[1]),pixels:t.pixels,durationMs:t.durationMs,until:t.until}),get:(e,t)=>({...b(t),...Pn(t),...In(t),format:qn(e[0]),target:Bn(Kn(e.slice(1)))})},K={click:e=>y(d.click,Vn(e),{...e,clickButton:e.button}),press:v(d.press,e=>Vn(e)),longpress:v(d.longPress,e=>fs(e)),hover:v(d.hover,e=>Vn(e)),swipe:e=>(Xe(e),y(d.swipe,[],e,{from:e.from,to:e.to,count:e.count,pauseMs:e.pauseMs,pattern:e.pattern})),focus:v(d.focus,e=>[String(e.x),String(e.y)]),type:v(d.type,e=>ps(e)),fill:v(d.fill,e=>ms(e)),scroll:v(d.scroll,e=>[E(e.direction,`scroll requires direction`),...w(e.amount)]),get:v(d.get,e=>[E(e.format,`get requires format`),...Hn(e)])};function ds(e){let t=gs(e);return{...Wt(t.target),...t.durationMs===void 0?{}:{durationMs:t.durationMs}}}function fs(e){return[...Vn(e),...w(e.durationMs)]}function ps(e){return[e.text]}function ms(e){return[...Vn(e),e.text]}function hs(t){if(t===`up`||t===`down`||t===`left`||t===`right`||t===`top`||t===`bottom`)return t;throw new e(`INVALID_ARGS`,`Unknown direction: ${String(t)}`,{hint:`scroll takes a direction first, then an optional amount: scroll <up|down|left|right|top|bottom> [amount]. It takes no @ref or selector — scroll the whole viewport, then retry the target with a selector.`})}function gs(e){if(Zn(e[0])&&Zn(e[1]))return{target:e.slice(0,2),...e[2]===void 0?{}:{durationMs:Number(e[2])}};let t=e.at(-1);return e.length>1&&Zn(t)?{target:e.slice(0,-1),durationMs:Number(t)}:{target:e}}function _s(e){return({input:t,result:n})=>{let r=e({input:t,result:n});return r instanceof Promise?r.then(vs):vs(r)}}function vs(e){return{data:e.data,text:bs(e.text,e.data)}}function ys(e){let t={...e};for(let[n,r]of Object.entries(e))Me(n)&&(t[n]=_s(r));return t}function bs(e,t){let n=typeof t.warning==`string`?`\nWarning: ${t.warning}`:``;return`${e??``}${n}${xs(t.settle)}`}function xs(e){if(!e||typeof e!=`object`)return``;let t=e,n=[Ts(t),...Ss(t),...ws(t)];return t.hint&&n.push(`hint: ${t.hint}`),`\n${n.join(`
14
- `)}`}function Ss(e){let t=e.diff,n=(t?.lines??[]).map(t=>`${t.kind===`removed`?`-`:`+`} ${Cs(t,e.refsGeneration)}`);return t?.truncated&&n.push(`… changed lines truncated`),n}function Cs(e,t){let n=e.text??``,r=Ct(e.ref,t);if(!r||!e.ref)return n;let i=`@${e.ref}`;return n.startsWith(`${i} `)?`${r}${n.slice(i.length)}`:n}function ws(e){let t=e.tail??[];if(t.length===0)return[];let n=[`unchanged interactive (${t.length}):`];for(let r of t){let t=r.label?` "${r.label}"`:``,i=Ct(r.ref,e.refsGeneration)??`@${r.ref??``}`;n.push(`= ${i} [${r.role??``}]${t}`)}return e.tailTruncated&&n.push(`… more interactive elements not shown, use snapshot -i`),n}function Ts(e){let t=e.settled===!0?`settled`:`not settled`,n=e.diff?.summary;return n?`${t} after ${e.waitedMs??0}ms: +${n.additions??0} -${n.removals??0} (~${n.unchanged??0} unchanged)`:`${t} after ${e.waitedMs??0}ms`}function Es(e){let t=e.result;return e.format===`text`?{data:t,text:typeof t.text==`string`?t.text:``}:e.format===`attrs`?{data:t,text:JSON.stringify(t.node??{},null,2)}:Ms(t)}function Ds(e){let t=e,n=St(t);if(n)return{data:t,text:n};if(typeof t.text==`string`)return{data:t,text:t.text};if(Array.isArray(t.matches))return{data:t,text:Os(t.matches,t.refsGeneration)};let r=Ct(t.ref,t.refsGeneration);return r?{data:t,text:`Found: ${r}`}:typeof t.found==`boolean`?{data:t,text:`Found: ${t.found}`}:t.node?{data:t,text:JSON.stringify(t.node,null,2)}:Ms(t)}function Os(e,t){return[`${e.length} match${e.length===1?``:`es`}:`,...e.map(e=>ks(e,t))].join(`
15
- `)}function ks(e,t){let n=e.ref??``,r=n.startsWith(`@`)?n.slice(1):n,i=Ct(n,t)??`@${r}`,a=It(e.node?.type??`Element`),o=e.node?Bt(e.node,a):``;return`= ${i} [${a}]${o?` "${o}"`:``}`}function As(e){let t=e;return{data:t,text:`Passed: is ${t.predicate??`assertion`}`}}function js(e){let t=e,n=t.ref??``,r=t.x,i=t.y;return!n||typeof r!=`number`||typeof i!=`number`?Ms(t):{data:t,text:`Tapped @${n} (${r}, ${i})`}}const q=ys({click:f(js),press:f(js),fill:p,longpress:p,hover:p,scroll:p,get:({input:e,result:t})=>Es({result:t,format:e.format}),is:f(As),find:f(Ds)});function Ms(e){return Tt(e)}const Ns={find:(e,t)=>Ls(e,t),is:(e,t)=>Rs(e,t)},Ps={is:v(d.is,e=>Fs(e)),find:e=>y(d.find,Is(e),{...e,findFirst:e.first,findLast:e.last})};function Fs(e){return[e.predicate,e.selector,...e.predicate===`text`?[e.value]:[]]}function Is(e){let t=e.locator&&e.locator!==`any`?[e.locator,e.query]:[e.query];switch(e.action){case void 0:case`click`:case`focus`:case`exists`:case`list`:return e.action?[...t,e.action]:t;case`getText`:return[...t,`get`,`text`];case`getAttrs`:return[...t,`get`,`attrs`];case`wait`:return[...t,`wait`,...w(e.timeoutMs)];case`fill`:case`type`:return[...t,e.action,e.value]}}function Ls(t,n){let r={...Hs(n),...Fn(n),...Pn(n),first:n.findFirst,last:n.findLast},i=Vs(t[0]),a=i!==void 0,o=a?t[1]:t[0],s=a?2:1,c=Oe(t[s]);if(c===void 0)return{...r,locator:i,query:Us(o)};if(c===`get`){let n=t[s+1];if(n===`text`)return{...r,locator:i,query:Us(o),action:`getText`};if(n===`attrs`)return{...r,locator:i,query:Us(o),action:`getAttrs`};throw new e(`INVALID_ARGS`,`find get only supports text or attrs`)}if(c===`wait`)return{...r,locator:i,query:Us(o),action:`wait`,timeoutMs:$n(t[s+1])};if(c===`fill`||c===`type`){let n=t.slice(s+1);if(n.length===0)throw new e(`INVALID_ARGS`,c===`fill`?`find fill requires text (use "" to clear the field)`:`find type requires text`);return{...r,locator:i,query:Us(o),action:c,value:n.join(` `)}}if(c===`click`||c===`focus`||c===`exists`||c===`list`)return{...r,locator:i,query:Us(o),action:c};throw new e(`INVALID_ARGS`,`Unsupported find action: ${t[s]}`,{hint:ye})}function Rs(t,n){let r={...Ln(n),...Fn(n),...Pn(n)},i=Te(t),a=Fe(i[0]??``);if(!a.ok)throw new e(a.code,a.message,{hint:a.hint});let o=a.predicate;if(o===`absent`){let e=zs(r);if(e)throw Bs(e)}let s=Jn(i.slice(1),{preferTrailingValue:o===`text`});return o===`text`?{...r,predicate:o,selector:s.selectorExpression,value:s.rest.join(` `)}:{...r,predicate:o,selector:s.selectorExpression}}function zs(e){if(e.scope!==void 0)return`scope`;if(e.depth!==void 0)return`depth`}function Bs(t){return new e(`INVALID_ARGS`,t===`scope`?`is absent does not support --scope; it requires an unscoped capture`:`is absent does not support --depth; it requires a full-depth capture`,{command:`is`,predicate:`absent`,rejectedOption:t})}function Vs(e){if(e===`text`||e===`label`||e===`value`||e===`role`||e===`id`)return e}function Hs(e){return{depth:e.snapshotDepth,raw:e.snapshotRaw}}function Us(t){if(t===void 0||t===``)throw new e(`INVALID_ARGS`,`find requires query`);return t}const J={get:{usageOverride:`get text|attrs <@ref|selector>`,usageFlags:[],positionalArgs:[`subcommand`,`target`],allowsExtraPositionals:!0,allowedFlags:[...B,`record`]},find:{usageOverride:`find <locator|text> <action> [value] [--first|--last]`,usageFlags:[],positionalArgs:[`query`,`action`,`value?`],allowsExtraPositionals:!0,allowedFlags:[`snapshotDepth`,`snapshotRaw`,`findFirst`,`findLast`,`record`]},is:{positionalArgs:[`predicate`,`selector`,`value?`],allowsExtraPositionals:!0,allowedFlags:[...B,`record`]},click:{usageOverride:`click <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`target`],allowsExtraPositionals:!0,allowedFlags:[...xi,`clickButton`,...U(`click`),...B]},press:{usageOverride:`press <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`targetOrX`,`y?`],allowsExtraPositionals:!0,allowedFlags:[...xi,...U(`press`),...B]},longpress:{usageOverride:`longpress <x y|@ref|selector> [durationMs]`,usageFlags:[],positionalArgs:[`targetOrX`,`yOrDurationMs?`,`durationMs?`],allowsExtraPositionals:!0,allowedFlags:[...U(`longpress`),...B]},hover:{usageOverride:`hover <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`targetOrX`,`y?`],allowsExtraPositionals:!0,allowedFlags:[...U(`hover`),...B]},swipe:{positionalArgs:[`x1`,`y1`,`x2`,`y2`],allowsExtraPositionals:!0,allowedFlags:[`count`,`pauseMs`,`pattern`]},gesture:{usageOverride:`gesture <pan|fling|swipe|pinch|rotate|transform|drag> ...`,usageFlags:[],listUsageOverride:`gesture <pan|fling|swipe|pinch|rotate|transform|drag> ...`,positionalArgs:[`pan|fling|swipe|pinch|rotate|transform|drag`,`args?`],allowsExtraPositionals:!0,allowedFlags:[`pointerCount`]},focus:{positionalArgs:[`x`,`y`]},type:{positionalArgs:[`text`],allowsExtraPositionals:!0,allowedFlags:[`delayMs`]},fill:{usageOverride:`fill <x> <y> <text> | fill <@ref|selector> <text>`,usageFlags:[],positionalArgs:[`targetOrX`,`yOrText`,`text?`],allowsExtraPositionals:!0,allowedFlags:[...B,`delayMs`,`recordAs`,...U(`fill`)]},scroll:{usageOverride:`scroll <direction|top|bottom> [amount]`,usageFlags:[`until`,`pixels`,`durationMs`,`settle`],positionalArgs:[`directionOrEdge`,`amount?`],allowedFlags:[`pixels`,`durationMs`,`until`,...U(`scroll`)]}},Ws=O({name:`interaction`,clientSurface:!1,commands:[D({name:`click`,text:{summary:`Click or tap a UI target`},metadata:Y(`click`),run:(e,t)=>e.interactions.click(Gs(t)),cliSchema:J.click,cliReader:G.click,daemonWriter:K.click,cliOutputFormatter:q.click}),D({name:`press`,text:{summary:`Short-press a UI target`,cliDetail:`The hold duration is positional on longpress, not press --hold-ms.`},metadata:Y(`press`),run:(e,t)=>e.interactions.press(Ks(t)),cliSchema:J.press,cliReader:G.press,daemonWriter:K.press,cliOutputFormatter:q.press}),D({name:`fill`,text:{summary:`Replace text in a UI input`,cliDetail:`Every positional after an @ref is the replacement text, so fill @e57 good morning enters "good morning"; quote the text when the shell must preserve exact whitespace. Clear a field with an empty text argument: fill @e57 "" (the argument must be present — fill @e57 alone is a missing argument, not a clear). When visible label text also matches a non-input element, constrain the target with editable=true, for example fill 'label="Email" editable=true' "qa@example.com".`},metadata:Y(`fill`),run:(e,t)=>e.interactions.fill(qs(t)),cliSchema:J.fill,cliReader:G.fill,daemonWriter:K.fill,cliOutputFormatter:q.fill}),D({name:`longpress`,text:{summary:`Hold a UI target to open a context menu`,cliDetail:`Duration is positional, for example longpress @e12 800 or longpress 300 500 800.`},metadata:Y(`longpress`),run:(e,t)=>e.interactions.longPress(Js(t)),cliSchema:J.longpress,cliReader:G.longpress,daemonWriter:K.longpress,cliOutputFormatter:q.longpress}),D({name:`hover`,text:{summary:`Hover the pointer over a UI target (web only)`,cliDetail:`The pointer stays where hover left it: read the revealed UI (--settle or snapshot -i) and act on it before another click or hover moves the pointer away.`},metadata:Y(`hover`),run:(e,t)=>e.interactions.hover(Ys(t)),cliSchema:J.hover,cliReader:G.hover,daemonWriter:K.hover,cliOutputFormatter:q.hover}),D({name:`swipe`,text:{summary:`Fling between coordinates`},metadata:Y(`swipe`),run:(e,t)=>e.interactions.swipe(t),cliSchema:J.swipe,cliReader:G.swipe,daemonWriter:K.swipe}),D({name:`focus`,text:{summary:`Focus input at screen coordinates`},metadata:Y(`focus`),run:(e,t)=>e.interactions.focus(t),cliSchema:J.focus,cliReader:G.focus,daemonWriter:K.focus}),D({name:`type`,text:{summary:`Append text to the focused input`},metadata:Y(`type`),run:(e,t)=>e.interactions.type(t),cliSchema:J.type,cliReader:G.type,daemonWriter:K.type}),D({name:`scroll`,text:{summary:`Scroll in a direction or to an edge`},metadata:Y(`scroll`),run:(e,t)=>e.interactions.scroll(t),cliSchema:J.scroll,cliReader:G.scroll,daemonWriter:K.scroll,cliOutputFormatter:q.scroll}),D({name:`get`,text:{summary:`Read element text or attributes`},metadata:Y(`get`),run:(e,t)=>e.interactions.get(Zs(t)),cliSchema:J.get,cliReader:G.get,daemonWriter:K.get,cliOutputFormatter:q.get}),D({name:`is`,text:{summary:`Check a UI predicate on a selector`},metadata:Y(`is`),run:(e,t)=>e.interactions.is(t),cliSchema:J.is,cliReader:Ns.is,daemonWriter:Ps.is,cliOutputFormatter:q.is}),D({name:`find`,text:{summary:`Find an element and act`},metadata:Y(`find`),run:(e,t)=>e.interactions.find(t),cliSchema:J.find,cliReader:Ns.find,daemonWriter:Ps.find,cliOutputFormatter:q.find}),D({name:`gesture`,text:{summary:`Run pan, fling, swipe, pinch, rotate, transform, or drag gestures`,cliDetail:`Argument shapes: pan <x> <y> <dx> <dy> [durationMs], fling <up|down|left|right> <x> <y> [distance], swipe <left|right|left-edge|right-edge>, pinch <scale> [x] [y], rotate <degrees> [x] [y], transform <x> <y> <dx> <dy> <scale> <degrees> [durationMs], or drag <source-selector|pinned-ref> <destination-selector|pinned-ref> [sourceHoldMs] [moveMs] [destinationHoldMs]. For command plans, output only command lines. Android transform verification should use all app-observable effects, for example wait text "pan changed yes", wait text "pinch changed yes", and wait text "rotate changed yes", not exact transform values.`},metadata:Y(`gesture`),run:async(e,t)=>{switch(t.kind){case`pan`:return await e.interactions.pan(Qs(t));case`fling`:return await e.interactions.fling(ec(t));case`swipe`:return await e.interactions.swipeGesture(tc(t));case`pinch`:return await e.interactions.pinch(nc(t));case`rotate`:return await e.interactions.rotateGesture(rc(t));case`transform`:return await e.interactions.transformGesture(ic(t));case`drag`:return await e.interactions.drag($s(t))}},cliSchema:J.gesture,cliReader:cs.gesture,daemonWriter:ls.gesture})]});function Y(e){let t=os.find(t=>t.name===e);if(!t)throw Error(`Missing interaction command metadata for ${e}`);return t}function Gs(e){return{..._(e),...Lr(e.target),...Br(e),...zr(e),button:e.button,verify:e.verify,...Xs(e)}}function Ks(e){return{..._(e),...Lr(e.target),...Br(e),...zr(e),verify:e.verify,...Xs(e)}}function qs(e){return{..._(e),...Lr(e.target),...Br(e),text:e.text,delayMs:e.delayMs,recordAs:e.recordAs,verify:e.verify,...Xs(e)}}function Js(e){return{..._(e),...Lr(e.target),...Br(e),durationMs:e.durationMs,...Xs(e)}}function Ys(e){return{..._(e),...Lr(e.target),...Br(e),...Xs(e)}}function Xs(e){return{settle:e.settle,settleQuietMs:e.settleQuietMs,timeoutMs:e.timeoutMs}}function Zs(e){return{..._(e),...Rr(e.target),...Br(e),format:e.format,record:e.record}}function Qs(e){return{..._(e),x:e.origin.x,y:e.origin.y,dx:e.delta.x,dy:e.delta.y,pointerCount:e.pointerCount,durationMs:e.durationMs}}function $s(e){return{..._(e),source:e.source,destination:e.destination,sourceHoldMs:e.sourceHoldMs,moveMs:e.moveMs,destinationHoldMs:e.destinationHoldMs}}function ec(e){return{..._(e),direction:e.direction,x:e.origin.x,y:e.origin.y,distance:e.distance}}function tc(e){return{..._(e),preset:e.preset}}function nc(e){return{..._(e),scale:e.scale,x:e.origin?.x,y:e.origin?.y}}function rc(e){return{..._(e),degrees:e.degrees,x:e.origin?.x,y:e.origin?.y}}function ic(e){return{..._(e),x:e.origin.x,y:e.origin.y,dx:e.delta.x,dy:e.delta.y,scale:e.scale,degrees:e.degrees,durationMs:e.durationMs}}async function ac(e){let{serializeDevice:t}=await import(`./result-serialization.js`).then(e=>e.t);return{data:{devices:e.map(t)},text:e.map(yc).join(`
16
- `)}}async function oc(e){let{serializeDevice:t}=await import(`./result-serialization.js`).then(e=>e.t);return{data:{device:t(e.device),availableCommands:e.availableCommands},text:[`${yc(e.device)} supports ${e.availableCommands.length} commands:`,e.availableCommands.join(` `)].join(`
17
- `)}}function sc(e){return{data:{apps:e.result},stderr:e.appsFilter===`all`?`Showing all apps, including system apps.
7
+ `)}function Ka(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;if(t<60)return`${(Math.round(t*10)/10).toFixed(1)}m`;let n=t/60;return`${(Math.round(n*10)/10).toFixed(1)}h`}function qa(e){let t=typeof e.appName==`string`?e.appName:void 0,n=typeof e.appBundleId==`string`?e.appBundleId:void 0,r=[];return t&&r.push(`Page: ${t}`),n&&r.push(`App: ${n}`),r.length>0?`${r.join(`
8
+ `)}\n`:``}function Ja(e,t,n){let r=n?` (truncated)`:``;return t?.partial?t.totalNodeCount>t.visibleNodeCount?`Snapshot: ${t.visibleNodeCount} visible nodes (${t.totalNodeCount} total)${r}`:`Snapshot: ${t.visibleNodeCount} visible nodes${r}`:`Snapshot: ${e} nodes${r}`}function Ya(e){return e.map(e=>JSON.stringify(e)).join(`
9
+ `)}function Xa(e){return fo(e).join(`
10
+ `)}function Za(e){return co(Lt(e,{summarizeTextSurfaces:!0})).join(`
11
+ `)}function Qa(e){return e&&e.summaryLines.length>0?`\n${e.summaryLines.join(`
12
+ `)}`:``}function $a(e,t,n,r,i=0){let a=eo(e);if(i===0&&a)return a;let o=(t?.hiddenCount??0)+i,s=t?t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow):!1;return o>0?{partial:!0,visibleNodeCount:n,totalNodeCount:Math.max(r,a?.totalNodeCount??r),reasons:to([...a?.reasons??[],`offscreen-nodes`])}:a||(s?{partial:!0,visibleNodeCount:n,totalNodeCount:n,reasons:[]}:null)}function eo(e){let t=e.visibility;if(!t||typeof t!=`object`)return null;let n=t;return typeof n.partial!=`boolean`||typeof n.visibleNodeCount!=`number`||typeof n.totalNodeCount!=`number`||!Array.isArray(n.reasons)?null:{partial:n.partial,visibleNodeCount:n.visibleNodeCount,totalNodeCount:n.totalNodeCount,reasons:n.reasons.filter(e=>typeof e==`string`)}}function to(e){return[...new Set(e)]}function no(e,t,n,r={nodes:t,filteredCount:0}){let i=[...so(e),...ro(e)];if(io(e)){let e=oo(t,n);e&&i.push(e)}!n.raw&&r.filteredCount>0&&i.push(`Collapsed ${r.filteredCount} Android helper node${r.filteredCount===1?``:`s`} from the agent-facing text snapshot; use --raw or --json for the full hierarchy.`);let a=r.filteredCount>0?r.nodes:t;return!n.raw&&Ra(a)&&i.push(`Warning: possible repeated nav subtree detected.`),i}function ro(e){let t=e.fallbackScreenshotPath;return typeof t==`string`&&t.length>0?[`Captured a screenshot of this screen automatically as visual truth: ${t}`]:[]}function io(e){return!e.snapshotQuality&&!ao(e)}function ao(e){let t=e.snapshotDiagnostics;if(!t||typeof t!=`object`)return!1;let n=t.stats;return!!(n&&typeof n==`object`&&n.platform===`web`)}function oo(e,t){if(t.scoped===!0||t.depthLimited===!0||e.length>3)return null;let n=e.length===1?`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.`}function so(e){return St(e).filter(e=>e.length>0)}function co(e){let t=[],n=[],r=new Map(e.map(e=>[e.node.index,e.node])),i=e=>{for(;n.length>0&&(!e||lo(e,n.at(-1),r));)t.push(...po(n.pop(),`below`))};for(let r of e)i(r),t.push(r.text),t.push(...po(r,`above`)),r.node.hiddenContentBelow&&n.push(r);return i(),t}function lo(e,t,n){return!uo(e.node,t.node,n)&&e.depth<=t.depth}function uo(e,t,n){let r=e;for(;typeof r.parentIndex==`number`;){if(r.parentIndex===t.index)return!0;let e=n.get(r.parentIndex);if(!e)return!1;r=e}return!1}function fo(e){return Lt(e,{summarizeTextSurfaces:!0}).flatMap(e=>[It(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...po({...e,depth:0})])}function po(e,t){let n=mo(e.type);if(!n)return[];let r=[];if(e.node.hiddenContentAbove&&t!==`below`&&r.push(`[content above ${n} hidden]`),e.node.hiddenContentBelow&&t!==`above`&&r.push(`[content below ${n} hidden]`),r.length===0)return[];let i=` `.repeat(e.depth+1);return r.map(e=>`${i}${e}`)}function mo(e){return e===`scroll-area`||e===`list`||e===`collection`||e===`table`?e:null}async function ho(e){let{serializeSnapshotResult:t}=await import(`./result-serialization.js`).then(e=>e.t),n=t(e.raw||!Array.isArray(e.result.nodes)?e.result:{...e.result,nodes:Qi(e.result.nodes)});return{data:n,jsonData:_o(n),stderr:e.result.snapshotDiagnostics?.warning?`${e.result.snapshotDiagnostics.warning}\n`:void 0,text:Ua(n,{raw:e.raw,flatten:e.interactiveOnly,scoped:typeof e.scope==`string`&&e.scope.trim().length>0,depthLimited:typeof e.depth==`number`})}}const go={snapshot:async({input:e,result:t})=>await ho({result:t,raw:e.raw,interactiveOnly:e.interactiveOnly,scope:e.scope,depth:e.depth}),wait:p,alert:p};function _o(e){let{unchanged:t,...n}=e;return n}const vo=`snapshot`,yo=Object.entries(Nt).map(([e,t])=>{let n=t.knownGaps.map(e=>`known gap ${e}`);return`${e}: hittable=${t.hittable}, regular-depth=${t.regularDepth}, deep-extension=${t.deepExtension}, depth-ladder=${t.depthLadder}${n.length>0?`, ${n.join(`, `)}`:``}`}).join(`; `),bo=L(vo,`Capture the accessibility tree or compare it with the previous session baseline. Use the returned refs for subsequent semantic interactions and the diff option to verify UI changes.`,{interactiveOnly:M(),depth:j(),scope:k(),raw:M(),customActions:vr(`snapshotCustomActions`),forceFull:M(),timeoutMs:j(`Maximum wall-clock time for the snapshot command.`),noRecord:M(`Do not record this action.`),record:M(`Force-record this out-of-band observation into a repair-armed heal (mutually exclusive with noRecord). Authored replay steps are recorded automatically and never need this.`)}),xo={allowedFlags:[`snapshotDiff`,...bi,`snapshotCustomActions`,`snapshotForceFull`,`timeoutMs`,`record`]},So=(e,t)=>({...x(t),...Fn(t),...n(t,r),timeoutMs:t.timeoutMs}),Co=y(u.snapshot),wo=R({name:vo,text:{summary:`Capture or diff the accessibility tree`,cliDetail:`Repeated equivalent unfiltered Android snapshots return a compact unchanged acknowledgement. Use --force-full to re-emit the tree; --json and --raw retain full output. For iOS raw-coordinate fallback after a no-op ref press, inspect rects with snapshot -i --json, press the rect center, then verify with diff snapshot -i or snapshot --diff. iOS backend capability contract: ${yo}.`},metadata:bo,run:(e,t)=>e.capture.snapshot(t),cliSchema:xo,cliReader:So,daemonWriter:Co,cliOutputFormatter:go.snapshot}),To=[`duration`,`text`,`ref`,`selector`,`absent`,`stable`],Eo=`wait`,Do=R({name:Eo,text:{summary:`Wait for a duration, text, selector, strict absence, or stable UI`},metadata:L(Eo,`Wait for a duration, text, snapshot ref, selector to appear, selector to be strictly absent, or stable UI. Use the strict absence target when zero selector matches are required; stable waits until the UI stays quiet for the requested window.`,{kind:N(To),durationMs:j(),text:k(),ref:k(),selector:k(),absent:k(),stable:M(),quietMs:j(),timeoutMs:j(),depth:j(),scope:k(),raw:M()}),run:(e,t)=>e.command.wait(Oo(t)),cliSchema:{usageOverride:`wait <ms>|text <text>|@ref|<selector>|absent <selector> [timeoutMs]|stable [quietMs] [timeoutMs]`,usageFlags:[],positionalArgs:[`durationOrSelector`,`timeoutMs?`],allowsExtraPositionals:!0,allowedFlags:[...V]},cliReader:(e,t)=>ko(e,t),daemonWriter:y(u.wait,e=>Mo(e)),cliOutputFormatter:p});function Oo(e){xn(e,`kind`,To);let t={...e};return delete t.kind,t}function ko(t,n){let r=ke(t);if(!r)throw new e(`INVALID_ARGS`,`wait requires <ms>, text <text>, @ref, <selector> [timeoutMs], absent <selector> [timeoutMs], or stable [quietMs] [timeoutMs].`);let i={...In(n),...Rn(n)};switch(r.kind){case`absent`:return Ao(i,r);case`sleep`:return{...i,durationMs:r.durationMs};case`text`:return jo(i,r);case`ref`:return{...i,ref:r.rawRef,...No(r.timeoutMs)};case`stable`:return{...i,stable:!0,...Po(r.quietMs),...No(r.timeoutMs)};case`invalid`:throw new e(`INVALID_ARGS`,r.message);case`selector`:return{...i,selector:r.selectorExpression,...No(r.timeoutMs)};default:return Fo(r)}}function Ao(e,t){let n=Pt(e);if(n)throw Rt(n,`wait`);return{...e,absent:t.selectorExpression,...No(t.timeoutMs)}}function jo(t,n){if(!n.text)throw new e(`INVALID_ARGS`,`wait requires text.`);return{...t,text:n.text,...No(n.timeoutMs)}}function Mo(t){if([t.durationMs===void 0?void 0:`durationMs`,t.text===void 0?void 0:`text`,t.ref===void 0?void 0:`ref`,t.selector===void 0?void 0:`selector`,t.absent===void 0?void 0:`absent`,t.stable===void 0?void 0:`stable`].filter(Boolean).length!==1)throw new e(`INVALID_ARGS`,`wait command requires exactly one of durationMs, text, ref, selector, absent, or stable.`);if(t.durationMs!==void 0)return[String(t.durationMs)];let n=T(t.timeoutMs);if(t.text!==void 0)return[`text`,t.text,...n];if(t.ref!==void 0)return[t.ref,...n];if(t.absent!==void 0){let r=Pt(t);if(r)throw Rt(r,`wait`);if(!Pe(t.absent))throw new e(`INVALID_ARGS`,`Invalid wait absent selector: ${t.absent}`);return[`absent`,t.absent,...n]}if(t.stable!==void 0){let r=T(t.quietMs);if(r.length===0&&n.length>0)throw new e(`INVALID_ARGS`,`wait stable requires quietMs before timeoutMs.`);return[`stable`,...r,...n]}let r=t.selector;if(!Pe(r))throw new e(`INVALID_ARGS`,`Invalid wait selector: ${r}`);return[r,...n]}function No(e){return e===null?{}:{timeoutMs:e}}function Po(e){return e===null?{}:{quietMs:e}}function Fo(e){throw Error(`Unsupported wait positional target: ${String(e)}`)}const Io=z({name:`capture`,commands:[wo,Mi,Ai,Do,gi,Ri]});function Lo(e){let t=[e.outPath,e.message];t.push(...zo(e));for(let n of 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(`
13
+ `)}}const Ro={debug:d(Lo)};function zo(e){let t=e.crash,n=[`Crash: ${t.appName??`unknown app`}${t.crashedThread===void 0?``:` thread ${t.crashedThread}`}`];t.bundleId&&n.push(`Bundle: ${t.bundleId}`),t.exceptionType&&n.push(`Exception: ${t.exceptionType}`),t.terminationReason&&n.push(`Termination: ${t.terminationReason}`);for(let e of 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}const Bo=`debug`,Vo=z({name:`debugging`,commands:[R({name:Bo,text:{summary:`Symbolicate Apple crash artifacts`},metadata:L(Bo,`Symbolicate Apple crash artifacts with matching dSYM UUIDs. This debug namespace is intentionally narrow: use logs for app logs, network for HTTP evidence, perf for performance samples, record/trace for media and traces, and react-devtools for React Native profiles.`,{action:O(N([`symbols`])),artifact:O(k(`Apple crash artifact path (.ips, .crash, or .log).`)),dsym:k(`Path to a matching .dSYM bundle.`),searchPath:k(`Directory to scan for matching .dSYM bundles.`),out:k(`Output path for the symbolicated artifact.`)}),run:(e,t)=>e.debug.symbols(t),cliSchema:{usageOverride:`debug symbols --artifact <crash.ips|crash.log> (--dsym <App.dSYM> | --search-path <dir>) [--out <symbolicated>]`,usageFlags:[],listUsageOverride:`debug`,positionalArgs:[`symbols`],allowedFlags:[`artifact`,`dsym`,`searchPath`,`out`]},cliReader:(e,t)=>({...x(t),action:Ho(e[0]),artifact:t.artifact,dsym:t.dsym,searchPath:t.searchPath,out:t.out}),cliOutputFormatter:Ro.debug})]});function Ho(t){if(t===`symbols`)return t;throw new e(`INVALID_ARGS`,`debug supports only symbols; use logs, network, perf, record, trace, or react-devtools for other diagnostics`)}const Uo=()=>M(`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot.`),Wo=()=>({settle:M(`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response. Best-effort; never fails the action.`),settleQuietMs:j(`Settle: quiet window in milliseconds (default 500).`,{min:0}),timeoutMs:j(`Settle: wait deadline in milliseconds (default 10000).`,{min:1})});function U(e){return{...Me(e)?{verify:Uo()}:{},...Fe(e)?Wo():{}}}function W(e){let t=[];return Me(e)&&t.push(`verify`),Fe(e)&&t.push(...wi),t}function Go(e,t){return Fe(e)?zn(t):{}}const Ko=[`click`,`focus`,`exists`,`list`,`getText`,`getAttrs`,`wait`,`fill`,`type`],qo={click:`Activate a UI target by snapshot ref, selector, or coordinates. Prefer a ref or selector after a snapshot; use coordinates only when semantic targeting is unavailable. This can change app state; use settle or verify to confirm the result without a follow-up snapshot.`,press:`Short-press a UI target by snapshot ref, selector, or coordinates. Use longpress instead when the target requires a context-menu or hold gesture.`,fill:`Replace text in a UI input selected by snapshot ref, selector, or coordinates. Pass an empty text to clear the field. Prefer refs or selectors after snapshot; use recordAs to keep sensitive text out of a recorded replay while sending it to the live app.`,longpress:`Hold a UI target by snapshot ref, selector, or coordinates to open a context menu or perform another hold gesture. Set durationMs when the default hold duration is unsuitable.`,hover:`Move the pointer over a UI target by snapshot ref, selector, or coordinates without pressing, to reveal hover-gated UI such as row toolbars or menus. Web only; touch platforms have no hover state. Use settle to observe what the hover revealed without a follow-up snapshot.`,swipe:`Quick coordinate fling with optional repeat pattern.`,focus:`Move input focus to explicit screen coordinates without entering text. Prefer semantic interactions when a snapshot ref or selector is available; use type or fill after focus.`,type:`Append text to the currently focused input. Use fill when the existing field value should be replaced, and focus first when no input is active.`,scroll:`Scroll in a direction, or toward the top/bottom edge of scrollable content. Set until to a selector to reach an off-screen target in one command rather than a scroll-and-check loop. The optional amount is the finger-path fraction of the viewport axis, honored up to 0.8 of it; directional scrolls reduce release momentum, while app scroll physics determine the final content offset. A visible keyboard shortens the swiped band instead of being dismissed; when too little is left, the command refuses with scroll_keyboard_occludes_surface.`,get:`Read text or accessibility attributes from a snapshot ref or selector without changing the app. Use format text for visible content or attrs for the element attribute map.`,is:"Check whether a selector satisfies a UI predicate such as visible, hidden, exists, absent, editable, selected, focused, or text. `absent` passes only when one readable, complete, unscoped, full-depth accessibility capture has zero matches. Use wait when the condition may appear asynchronously.",find:`Find by text/label/value/role/id and run action`,gesture:`Perform a structured pan, fling, swipe, pinch, rotate, transform, or drag gesture. Select the gesture kind, then provide only the inputs that apply to that kind.`},Jo={target:O(Tr()),button:N(Vt,`Pointer button for platforms that support mouse buttons.`),...F(),...Or(),...U(`click`)},Yo={target:O(Tr()),...F(),...Or(),...U(`press`)},Xo={target:O(Tr()),text:O(k(`Text to enter into the target. Pass "" to clear it.`,{allowEmpty:!0})),delayMs:j(`Delay between typed characters.`,{min:0}),recordAs:k("When script recording is armed, send text to the live app but publish it as ${VAR}. Use an uppercase replay variable name such as PASSWORD."),...F(),...U(`fill`)},Zo={target:O(Tr()),durationMs:j(`Long press duration in milliseconds.`,{min:0}),...F(),...U(`longpress`)},Qo={target:O(Tr()),...F(),...U(`hover`)},$o={from:O(Dr(`Swipe start point.`)),to:O(Dr(`Swipe end point.`)),count:j(`Number of swipe repetitions.`,{min:1,max:200}),pauseMs:j(`Pause between repeated swipes.`,{min:0,max:Ge}),pattern:N(Ue)},es={x:O(A(`X coordinate.`)),y:O(A(`Y coordinate.`))},ts={text:O(k(`Text to type.`)),delayMs:j(`Delay between typed characters.`,{min:0})},ns={direction:O(N(Ke)),amount:A(`Platform scroll amount.`),pixels:j(`Pixel scroll amount.`,{min:0}),until:k(`Repeat scroll passes until this selector is visible on screen, then stop. Not valid with the top/bottom edge directions, which carry their own stop condition.`),durationMs:j(`Scroll duration in milliseconds when the backend supports pacing.`,{min:0,max:Ht}),...U(`scroll`)},rs=()=>({noRecord:M(`Do not record this action.`),record:M(`Force-record this out-of-band observation into a repair-armed heal (mutually exclusive with noRecord). Authored replay steps are recorded automatically and never need this. On find, valid only for a read-only action.`)}),is={format:O(N([`text`,`attrs`])),target:O(Er()),...F(),...rs()},as={predicate:O(N(Ce)),selector:O(k()),value:k(),...F(),...rs()},os={locator:N(xe),query:O(k()),action:N(Ko),value:k(void 0,{allowEmpty:!0}),timeoutMs:j(),first:M(),last:M(),depth:j(),raw:M(),...rs()},ss={kind:O(N(Ye,`Gesture variant.`)),direction:N(We,`Fling direction.`),preset:N(qe,`Swipe preset.`),origin:Dr(`Gesture origin point.`),delta:Dr(`Movement delta for pan or transform gestures.`),distance:j(`Fling distance.`,{min:0}),scale:A(`Pinch or transform scale.`),degrees:A(`Rotation in degrees.`),durationMs:j(`Pan/transform duration.`,{min:16,max:1e4}),pointerCount:j(`Pan touch pointer count (1 or 2).`,{min:1,max:2}),source:k(`Drag source @ref or selector.`),destination:k(`Drag destination @ref or selector.`),sourceHoldMs:j(`Drag activation hold duration.`,{min:1,max:1e4}),moveMs:j(`Drag movement duration.`,{min:16,max:1e4}),destinationHoldMs:j(`Hold before releasing at the destination.`,{min:0,max:1e4})},cs=[G(`click`,Jo),G(`press`,Yo),G(`fill`,Xo),G(`longpress`,Zo),G(`hover`,Qo),G(`swipe`,$o),G(`focus`,es),G(`type`,ts),G(`scroll`,ns),G(`get`,is,{parseableOutput:!0}),G(`is`,as),G(`find`,os,{parseableOutput:!0}),L(`gesture`,qo.gesture,ss,{readInput:ls})];function ls(e){let t=mn(e);return{...An(t),...Je(t)}}function G(e,t,n){return L(e,qo[e],t,n)}const us={gesture:fs},ds={gesture:e=>{let t=ls(e);return b(u.gesture,[],e,_(t))}};function fs(e,t){return{...x(t),...Xe(e,t.pointerCount)}}const K={click:(e,t)=>({...x(t),...Ln(t),...Bn(t),target:Vn(Ut(e)),button:t.clickButton,verify:t.verify}),press:(e,t)=>({...x(t),...Ln(t),...Bn(t),target:Vn(Ut(e)),verify:t.verify}),longpress:(e,t)=>{let n=ps(e);return{...x(t),...Ln(t),target:Vn(n),durationMs:n.durationMs}},hover:(e,t)=>({...x(t),...Ln(t),target:Vn(Ut(e))}),swipe:(e,t)=>({...x(t),...Qe(e,{count:t.count,pauseMs:t.pauseMs,pattern:t.pattern})}),focus:(e,t)=>({...x(t),x:Number(e[0]),y:Number(e[1])}),type:(e,t)=>({...x(t),text:e.join(` `),delayMs:t.delayMs}),fill:(e,t)=>{let n=Wt(e);return{...x(t),...Ln(t),target:Vn(n.target),text:n.text,delayMs:t.delayMs,recordAs:t.recordAs,verify:t.verify}},scroll:(e,t)=>({...x(t),direction:_s(e[0]),amount:er(e[1]),pixels:t.pixels,durationMs:t.durationMs,until:t.until}),get:(e,t)=>({...x(t),...Fn(t),...Ln(t),format:Jn(e[0]),target:Vn(qn(e.slice(1)))})},q={click:e=>b(u.click,Hn(e),{...e,clickButton:e.button}),press:y(u.press,e=>Hn(e)),longpress:y(u.longPress,e=>ms(e)),hover:y(u.hover,e=>Hn(e)),swipe:e=>(Ze(e),b(u.swipe,[],e,{from:e.from,to:e.to,count:e.count,pauseMs:e.pauseMs,pattern:e.pattern})),focus:y(u.focus,e=>[String(e.x),String(e.y)]),type:y(u.type,e=>hs(e)),fill:y(u.fill,e=>gs(e)),scroll:y(u.scroll,e=>[D(e.direction,`scroll requires direction`),...T(e.amount)]),get:y(u.get,e=>[D(e.format,`get requires format`),...Un(e)])};function ps(e){let t=vs(e);return{...Ut(t.target),...t.durationMs===void 0?{}:{durationMs:t.durationMs}}}function ms(e){return[...Hn(e),...T(e.durationMs)]}function hs(e){return[e.text]}function gs(e){return[...Hn(e),e.text]}function _s(t){if(t===`up`||t===`down`||t===`left`||t===`right`||t===`top`||t===`bottom`)return t;throw new e(`INVALID_ARGS`,`Unknown direction: ${String(t)}`,{hint:`scroll takes a direction first, then an optional amount: scroll <up|down|left|right|top|bottom> [amount]. It takes no @ref or selector — scroll the whole viewport, then retry the target with a selector.`})}function vs(e){if(Qn(e[0])&&Qn(e[1]))return{target:e.slice(0,2),...e[2]===void 0?{}:{durationMs:Number(e[2])}};let t=e.at(-1);return e.length>1&&Qn(t)?{target:e.slice(0,-1),durationMs:Number(t)}:{target:e}}function ys(e){return({input:t,result:n})=>{let r=e({input:t,result:n});return r instanceof Promise?r.then(bs):bs(r)}}function bs(e){return{data:e.data,text:Ss(e.text,e.data)}}function xs(e){let t={...e};for(let[n,r]of Object.entries(e))Fe(n)&&(t[n]=ys(r));return t}function Ss(e,t){return`${e??``}${Cs(t.settle)}`}function Cs(e){if(!e||typeof e!=`object`)return``;let t=e,n=[Ds(t),...ws(t),...Es(t)];return t.hint&&n.push(`hint: ${t.hint}`),`\n${n.join(`
14
+ `)}`}function ws(e){let t=e.diff,n=(t?.lines??[]).map(t=>`${t.kind===`removed`?`-`:`+`} ${Ts(t,e.refsGeneration)}`);return t?.truncated&&n.push(`… changed lines truncated`),n}function Ts(e,t){let n=e.text??``,r=wt(e.ref,t);if(!r||!e.ref)return n;let i=`@${e.ref}`;return n.startsWith(`${i} `)?`${r}${n.slice(i.length)}`:n}function Es(e){let t=e.tail??[];if(t.length===0)return[];let n=[`unchanged interactive (${t.length}):`];for(let r of t){let t=r.label?` "${r.label}"`:``,i=wt(r.ref,e.refsGeneration)??`@${r.ref??``}`;n.push(`= ${i} [${r.role??``}]${t}`)}return e.tailTruncated&&n.push(`… more interactive elements not shown, use snapshot -i`),n}function Ds(e){let t=e.settled===!0?`settled`:`not settled`,n=e.diff?.summary;return n?`${t} after ${e.waitedMs??0}ms: +${n.additions??0} -${n.removals??0} (~${n.unchanged??0} unchanged)`:`${t} after ${e.waitedMs??0}ms`}function Os(e){let t=e.result;return e.format===`attrs`?{data:t,text:JSON.stringify(t.node??{},null,2)}:{data:t,text:typeof t.text==`string`?t.text:``}}function ks(e){let t=e,n=Ct(t);if(n)return{data:t,text:n};if(typeof t.text==`string`)return{data:t,text:t.text};if(Array.isArray(t.matches))return{data:t,text:As(t.matches,t.refsGeneration)};let r=wt(t.ref,t.refsGeneration);return r?{data:t,text:`Found: ${r}`}:typeof t.found==`boolean`?{data:t,text:`Found: ${t.found}`}:t.node?{data:t,text:JSON.stringify(t.node,null,2)}:f(t)}function As(e,t){return[`${e.length} match${e.length===1?``:`es`}:`,...e.map(e=>js(e,t))].join(`
15
+ `)}function js(e,t){let n=e.ref??``,r=n.startsWith(`@`)?n.slice(1):n,i=wt(n,t)??`@${r}`,a=Ft(e.node?.type??`Element`),o=e.node?zt(e.node,a):``;return`= ${i} [${a}]${o?` "${o}"`:``}`}function Ms(e){let t=e;return{data:t,text:`Passed: is ${t.predicate??`assertion`}`}}function Ns(e){let t=e,n=t.ref??``,r=t.x,i=t.y;return!n||typeof r!=`number`||typeof i!=`number`?f(t):{data:t,text:`Tapped @${n} (${r}, ${i})`}}const J=xs({click:d(Ns),press:d(Ns),fill:p,longpress:p,hover:p,scroll:p,get:({input:e,result:t})=>Os({result:t,format:e.format===`attrs`?`attrs`:`text`}),is:d(Ms),find:d(ks)}),Ps={find:(e,t)=>Rs(e,t),is:(e,t)=>zs(e,t)},Fs={is:y(u.is,e=>Is(e)),find:e=>b(u.find,Ls(e),{...e,findFirst:e.first,findLast:e.last})};function Is(e){return[e.predicate,e.selector,...e.predicate===`text`?[e.value]:[]]}function Ls(e){let t=e.locator&&e.locator!==`any`?[e.locator,e.query]:[e.query];switch(e.action){case void 0:case`click`:case`focus`:case`exists`:case`list`:return e.action?[...t,e.action]:t;case`getText`:return[...t,`get`,`text`];case`getAttrs`:return[...t,`get`,`attrs`];case`wait`:return[...t,`wait`,...T(e.timeoutMs)];case`fill`:case`type`:return[...t,e.action,e.value]}}function Rs(t,n){let r={...Us(n),...In(n),...Fn(n),first:n.findFirst,last:n.findLast},i=Hs(t[0]),a=i!==void 0,o=a?t[1]:t[0],s=a?2:1,c=we(t[s]);if(c===void 0)return{...r,locator:i,query:Ws(o)};if(c===`get`){let n=t[s+1];if(n===`text`)return{...r,locator:i,query:Ws(o),action:`getText`};if(n===`attrs`)return{...r,locator:i,query:Ws(o),action:`getAttrs`};throw new e(`INVALID_ARGS`,`find get only supports text or attrs`)}if(c===`wait`)return{...r,locator:i,query:Ws(o),action:`wait`,timeoutMs:er(t[s+1])};if(c===`fill`||c===`type`){let n=t.slice(s+1);if(n.length===0)throw new e(`INVALID_ARGS`,c===`fill`?`find fill requires text (use "" to clear the field)`:`find type requires text`);return{...r,locator:i,query:Ws(o),action:c,value:n.join(` `)}}if(c===`click`||c===`focus`||c===`exists`||c===`list`)return{...r,locator:i,query:Ws(o),action:c};throw new e(`INVALID_ARGS`,`Unsupported find action: ${t[s]}`,{hint:Ae})}function zs(t,n){let r={...Rn(n),...In(n),...Fn(n)},i=Ne(t),a=De(i[0]??``);if(!a.ok)throw new e(a.code,a.message,{hint:a.hint});let o=a.predicate;if(o===`absent`){let e=Bs(r);if(e)throw Vs(e)}let s=Yn(i.slice(1),{preferTrailingValue:o===`text`});return o===`text`?{...r,predicate:o,selector:s.selectorExpression,value:s.rest.join(` `)}:{...r,predicate:o,selector:s.selectorExpression}}function Bs(e){if(e.scope!==void 0)return`scope`;if(e.depth!==void 0)return`depth`}function Vs(t){return new e(`INVALID_ARGS`,t===`scope`?`is absent does not support --scope; it requires an unscoped capture`:`is absent does not support --depth; it requires a full-depth capture`,{command:`is`,predicate:`absent`,rejectedOption:t})}function Hs(e){if(e===`text`||e===`label`||e===`value`||e===`role`||e===`id`)return e}function Us(e){return{depth:e.snapshotDepth,raw:e.snapshotRaw}}function Ws(t){if(t===void 0||t===``)throw new e(`INVALID_ARGS`,`find requires query`);return t}const Y={get:{usageOverride:`get text|attrs <@ref|selector>`,usageFlags:[],positionalArgs:[`subcommand`,`target`],allowsExtraPositionals:!0,allowedFlags:[...V,`record`]},find:{usageOverride:`find <locator|text> <action> [value] [--first|--last]`,usageFlags:[],positionalArgs:[`query`,`action`,`value?`],allowsExtraPositionals:!0,allowedFlags:[`snapshotDepth`,`snapshotRaw`,`findFirst`,`findLast`,`record`]},is:{positionalArgs:[`predicate`,`selector`,`value?`],allowsExtraPositionals:!0,allowedFlags:[...V,`record`]},click:{usageOverride:`click <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`target`],allowsExtraPositionals:!0,allowedFlags:[...Ci,`clickButton`,...W(`click`),...V]},press:{usageOverride:`press <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`targetOrX`,`y?`],allowsExtraPositionals:!0,allowedFlags:[...Ci,...W(`press`),...V]},longpress:{usageOverride:`longpress <x y|@ref|selector> [durationMs]`,usageFlags:[],positionalArgs:[`targetOrX`,`yOrDurationMs?`,`durationMs?`],allowsExtraPositionals:!0,allowedFlags:[...W(`longpress`),...V]},hover:{usageOverride:`hover <x y|@ref|selector>`,usageFlags:[],positionalArgs:[`targetOrX`,`y?`],allowsExtraPositionals:!0,allowedFlags:[...W(`hover`),...V]},swipe:{positionalArgs:[`x1`,`y1`,`x2`,`y2`],allowsExtraPositionals:!0,allowedFlags:[`count`,`pauseMs`,`pattern`]},gesture:{usageOverride:`gesture <pan|fling|swipe|pinch|rotate|transform|drag> ...`,usageFlags:[],listUsageOverride:`gesture <pan|fling|swipe|pinch|rotate|transform|drag> ...`,positionalArgs:[`pan|fling|swipe|pinch|rotate|transform|drag`,`args?`],allowsExtraPositionals:!0,allowedFlags:[`pointerCount`]},focus:{positionalArgs:[`x`,`y`]},type:{positionalArgs:[`text`],allowsExtraPositionals:!0,allowedFlags:[`delayMs`]},fill:{usageOverride:`fill <x> <y> <text> | fill <@ref|selector> <text>`,usageFlags:[],positionalArgs:[`targetOrX`,`yOrText`,`text?`],allowsExtraPositionals:!0,allowedFlags:[...V,`delayMs`,`recordAs`,...W(`fill`)]},scroll:{usageOverride:`scroll <direction|top|bottom> [amount]`,usageFlags:[`until`,`pixels`,`durationMs`,`settle`],positionalArgs:[`directionOrEdge`,`amount?`],allowedFlags:[`pixels`,`durationMs`,`until`,...W(`scroll`)]}},Gs=z({name:`interaction`,clientSurface:!1,commands:[R({name:`click`,text:{summary:`Click or tap a UI target`},metadata:X(`click`),run:(e,t)=>e.interactions.click(Ks(t)),cliSchema:Y.click,cliReader:K.click,daemonWriter:q.click,cliOutputFormatter:J.click}),R({name:`press`,text:{summary:`Short-press a UI target`,cliDetail:`The hold duration is positional on longpress, not press --hold-ms.`},metadata:X(`press`),run:(e,t)=>e.interactions.press(qs(t)),cliSchema:Y.press,cliReader:K.press,daemonWriter:q.press,cliOutputFormatter:J.press}),R({name:`fill`,text:{summary:`Replace text in a UI input`,cliDetail:`Every positional after an @ref is the replacement text, so fill @e57 good morning enters "good morning"; quote the text when the shell must preserve exact whitespace. Clear a field with an empty text argument: fill @e57 "" (the argument must be present — fill @e57 alone is a missing argument, not a clear). When visible label text also matches a non-input element, constrain the target with editable=true, for example fill 'label="Email" editable=true' "qa@example.com".`},metadata:X(`fill`),run:(e,t)=>e.interactions.fill(Js(t)),cliSchema:Y.fill,cliReader:K.fill,daemonWriter:q.fill,cliOutputFormatter:J.fill}),R({name:`longpress`,text:{summary:`Hold a UI target to open a context menu`,cliDetail:`Duration is positional, for example longpress @e12 800 or longpress 300 500 800.`},metadata:X(`longpress`),run:(e,t)=>e.interactions.longPress(Ys(t)),cliSchema:Y.longpress,cliReader:K.longpress,daemonWriter:q.longpress,cliOutputFormatter:J.longpress}),R({name:`hover`,text:{summary:`Hover the pointer over a UI target (web only)`,cliDetail:`The pointer stays where hover left it: read the revealed UI (--settle or snapshot -i) and act on it before another click or hover moves the pointer away.`},metadata:X(`hover`),run:(e,t)=>e.interactions.hover(Xs(t)),cliSchema:Y.hover,cliReader:K.hover,daemonWriter:q.hover,cliOutputFormatter:J.hover}),R({name:`swipe`,text:{summary:`Fling between coordinates`},metadata:X(`swipe`),run:(e,t)=>e.interactions.swipe(t),cliSchema:Y.swipe,cliReader:K.swipe,daemonWriter:q.swipe}),R({name:`focus`,text:{summary:`Focus input at screen coordinates`},metadata:X(`focus`),run:(e,t)=>e.interactions.focus(t),cliSchema:Y.focus,cliReader:K.focus,daemonWriter:q.focus}),R({name:`type`,text:{summary:`Append text to the focused input`},metadata:X(`type`),run:(e,t)=>e.interactions.type(t),cliSchema:Y.type,cliReader:K.type,daemonWriter:q.type}),R({name:`scroll`,text:{summary:`Scroll in a direction or to an edge`},metadata:X(`scroll`),run:(e,t)=>e.interactions.scroll(t),cliSchema:Y.scroll,cliReader:K.scroll,daemonWriter:q.scroll,cliOutputFormatter:J.scroll}),R({name:`get`,text:{summary:`Read element text or attributes`},metadata:X(`get`),run:(e,t)=>e.interactions.get(Qs(t)),cliSchema:Y.get,cliReader:K.get,daemonWriter:q.get,cliOutputFormatter:J.get}),R({name:`is`,text:{summary:`Check a UI predicate on a selector`},metadata:X(`is`),run:(e,t)=>e.interactions.is(t),cliSchema:Y.is,cliReader:Ps.is,daemonWriter:Fs.is,cliOutputFormatter:J.is}),R({name:`find`,text:{summary:`Find an element and act`},metadata:X(`find`),run:(e,t)=>e.interactions.find(t),cliSchema:Y.find,cliReader:Ps.find,daemonWriter:Fs.find,cliOutputFormatter:J.find}),R({name:`gesture`,text:{summary:`Run pan, fling, swipe, pinch, rotate, transform, or drag gestures`,cliDetail:`Argument shapes: pan <x> <y> <dx> <dy> [durationMs], fling <up|down|left|right> <x> <y> [distance], swipe <left|right|left-edge|right-edge>, pinch <scale> [x] [y], rotate <degrees> [x] [y], transform <x> <y> <dx> <dy> <scale> <degrees> [durationMs], or drag <source-selector|pinned-ref> <destination-selector|pinned-ref> [sourceHoldMs] [moveMs] [destinationHoldMs]. For command plans, output only command lines. Android transform verification should use all app-observable effects, for example wait text "pan changed yes", wait text "pinch changed yes", and wait text "rotate changed yes", not exact transform values.`},metadata:X(`gesture`),run:async(e,t)=>{switch(t.kind){case`pan`:return await e.interactions.pan($s(t));case`fling`:return await e.interactions.fling(tc(t));case`swipe`:return await e.interactions.swipeGesture(nc(t));case`pinch`:return await e.interactions.pinch(rc(t));case`rotate`:return await e.interactions.rotateGesture(ic(t));case`transform`:return await e.interactions.transformGesture(ac(t));case`drag`:return await e.interactions.drag(ec(t))}},cliSchema:Y.gesture,cliReader:us.gesture,daemonWriter:ds.gesture})]});function X(e){let t=cs.find(t=>t.name===e);if(!t)throw Error(`Missing interaction command metadata for ${e}`);return t}function Ks(e){return{...v(e),...Pr(e.target),...Lr(e),...Ir(e),button:e.button,verify:e.verify,...Zs(e)}}function qs(e){return{...v(e),...Pr(e.target),...Lr(e),...Ir(e),verify:e.verify,...Zs(e)}}function Js(e){return{...v(e),...Pr(e.target),...Lr(e),text:e.text,delayMs:e.delayMs,recordAs:e.recordAs,verify:e.verify,...Zs(e)}}function Ys(e){return{...v(e),...Pr(e.target),...Lr(e),durationMs:e.durationMs,...Zs(e)}}function Xs(e){return{...v(e),...Pr(e.target),...Lr(e),...Zs(e)}}function Zs(e){return{settle:e.settle,settleQuietMs:e.settleQuietMs,timeoutMs:e.timeoutMs}}function Qs(e){return{...v(e),...Fr(e.target),...Lr(e),format:e.format,record:e.record}}function $s(e){return{...v(e),x:e.origin.x,y:e.origin.y,dx:e.delta.x,dy:e.delta.y,pointerCount:e.pointerCount,durationMs:e.durationMs}}function ec(e){return{...v(e),source:e.source,destination:e.destination,sourceHoldMs:e.sourceHoldMs,moveMs:e.moveMs,destinationHoldMs:e.destinationHoldMs}}function tc(e){return{...v(e),direction:e.direction,x:e.origin.x,y:e.origin.y,distance:e.distance}}function nc(e){return{...v(e),preset:e.preset}}function rc(e){return{...v(e),scale:e.scale,x:e.origin?.x,y:e.origin?.y}}function ic(e){return{...v(e),degrees:e.degrees,x:e.origin?.x,y:e.origin?.y}}function ac(e){return{...v(e),x:e.origin.x,y:e.origin.y,dx:e.delta.x,dy:e.delta.y,scale:e.scale,degrees:e.degrees,durationMs:e.durationMs}}async function oc(e){let{serializeDevice:t}=await import(`./result-serialization.js`).then(e=>e.t);return{data:{devices:e.map(t)},text:e.map(bc).join(`
16
+ `)}}async function sc(e){let{serializeDevice:t}=await import(`./result-serialization.js`).then(e=>e.t);return{data:{device:t(e.device),availableCommands:e.availableCommands},text:[`${bc(e.device)} supports ${e.availableCommands.length} commands:`,e.availableCommands.join(` `)].join(`
17
+ `)}}function cc(e){return{data:{apps:e.result},stderr:e.appsFilter===`all`?`Showing all apps, including system apps.
18
18
  `:`Showing user-installed apps or deferred provider app assets. Use --all to include system apps on a live device.
19
19
  `,text:e.result.length>0?e.result.join(`
20
- `):e.appsFilter===`all`?`No apps found.`:`No user apps or provider app assets found.`}}async function cc(e){if(`savedScript`in e)return{data:e,text:`Published script: ${e.savedScript}\nSession remains active: ${e.session}\nActions: ${e.actionCount}`};if(`stateDir`in e)return{data:e,text:e.stateDir};let{serializeSessionListEntry:t}=await import(`./result-serialization.js`).then(e=>e.t),n={sessions:e.sessions.map(t)};return{data:n,text:JSON.stringify(n,null,2)}}async function lc(e){let{serializeOpenResult:t}=await import(`./result-serialization.js`).then(e=>e.t),n=t(e),r=[St(n)].filter(e=>!!e);typeof n.sessionStateDir==`string`&&r.push(`Session state: ${n.sessionStateDir}`);for(let t of e.warnings??[])r.push(`Warning: ${t}`);let i=await uc(e.snapshot);return i&&(n.snapshot=i.jsonData??i.data,i.text&&r.push(i.text)),{data:n,...i?.stderr?{stderr:i.stderr}:{},text:r.join(`
21
- `)||null}}async function uc(e){return!e||!Array.isArray(e.nodes)?null:await po({result:e,interactiveOnly:!0})}async function dc(e){let{serializeCloseResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return Tt(t(e))}function fc(e){if(pc(e))return{data:e,text:e.artifacts.length>0?e.artifacts.map(xc).join(`
22
- `):e.message??`No daemon artifacts available.`};let t=[e.message??`No cloud artifacts available for ${e.provider}.`],n=Sc(e);return n&&t.push(`Retry: ${n}`),{data:e,text:e.cloudArtifacts.length>0?e.cloudArtifacts.map(bc).join(`
20
+ `):e.appsFilter===`all`?`No apps found.`:`No user apps or provider app assets found.`}}async function lc(e){if(`savedScript`in e)return{data:e,text:`Published script: ${e.savedScript}\nSession remains active: ${e.session}\nActions: ${e.actionCount}`};if(`stateDir`in e)return{data:e,text:e.stateDir};let{serializeSessionListEntry:t}=await import(`./result-serialization.js`).then(e=>e.t),n={sessions:e.sessions.map(t)};return{data:n,text:JSON.stringify(n,null,2)}}async function uc(e){let{serializeOpenResult:t}=await import(`./result-serialization.js`).then(e=>e.t),n=t(e),r=[Ct(n)].filter(e=>!!e);typeof n.sessionStateDir==`string`&&r.push(`Session state: ${n.sessionStateDir}`);for(let t of e.warnings??[])r.push(`Warning: ${t}`);let i=await dc(e.snapshot);return i&&(n.snapshot=i.jsonData??i.data,i.text&&r.push(i.text)),{data:n,...i?.stderr?{stderr:i.stderr}:{},text:r.join(`
21
+ `)||null}}async function dc(e){return!e||!Array.isArray(e.nodes)?null:await ho({result:e,interactiveOnly:!0})}async function fc(e){let{serializeCloseResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return f(t(e))}function pc(e){if(mc(e))return{data:e,text:e.artifacts.length>0?e.artifacts.map(Sc).join(`
22
+ `):e.message??`No daemon artifacts available.`};let t=[e.message??`No cloud artifacts available for ${e.provider}.`],n=Cc(e);return n&&t.push(`Retry: ${n}`),{data:e,text:e.cloudArtifacts.length>0?e.cloudArtifacts.map(xc).join(`
23
23
  `):t.join(`
24
- `)}}function pc(e){return`source`in e&&e.source===`daemon`}async function mc(e){let{serializeDeployResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return Tt(t(e))}async function hc(e){let{serializeInstallFromSourceResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return Tt(t(e))}function gc(e){let t=e,n=t.platform??`unknown`;return{data:t,text:`Boot ready: ${t.device??t.id??`unknown`} (${n})`}}function _c(e){let t=e,n=t.platform??`unknown`,r=t.device??t.id??`unknown`,i=t.shutdown;return{data:t,text:`${i&&typeof i==`object`&&`success`in i&&i.success===!0?`Shutdown`:`Shutdown failed`}: ${r} (${n})`}}async function vc(e,t){let{formatDoctorCheckDetailLines:n,formatDoctorCheckSummaryLine:r}=await import(`./doctor-output.js`).then(e=>e.t),i=e,a=[`Doctor: ${typeof i.status==`string`?i.status:`unknown`}`],o=Cc(i.checks);if(t?.renderedToStderr){let e=typeof i.summary==`string`?i.summary:void 0;e&&a.push(e)}else if(o.length===0){let e=typeof i.summary==`string`?i.summary:`No blockers found.`;a.push(e)}else for(let e of o)a.push(r(e)),a.push(...n(e));return{data:i,text:a.join(`
25
- `)}}const X={boot:f(gc),shutdown:f(_c),devices:f(ac),capabilities:f(oc),doctor:({result:e,progress:t})=>vc(e,t),apps:({input:e,result:t})=>sc({result:t,appsFilter:e.appsFilter}),session:f(cc),artifacts:f(fc),open:f(lc),close:f(dc),install:f(mc),reinstall:f(mc),"install-from-source":f(hc),prepare:p,viewport:p};function yc(e){let t=e.kind?` ${e.kind}`:``,n=e.target?` target=${e.target}`:``,r=typeof e.booted==`boolean`?` booted=${e.booted}`:``,i=e.claimedBy?` claimed by session "${e.claimedBy.session}" in ${e.claimedBy.workspace}`:``;return`${e.name} (${e.platform}${t}${n})${r}${i}`}function bc(e){let t=e.url?` ${e.url}`:``,n=e.availability?` ${e.availability}`:``;return`${e.kind}: ${e.name}${n}${t}`}function xc(e){let t=e.artifactType?` (${e.artifactType})`:``;return`${e.filename}${t}: ${e.mimeType} ${e.sizeBytes} bytes id=${e.id}`}function Sc(e){if(e.providerSessionId)return`agent-device artifacts ${e.providerSessionId} --provider ${e.provider} --json`}function Cc(e){return Array.isArray(e)?e.filter(e=>!!e&&typeof e==`object`&&!Array.isArray(e)):[]}const wc=D({name:`artifacts`,text:{summary:`List daemon or cloud provider session artifacts`},metadata:R(`artifacts`,`List daemon or cloud provider artifacts for an active or completed session.`,{provider:j(`Cloud provider name, for example browserstack or aws-device-farm.`),providerSessionId:j(`Cloud provider session id or ARN.`)}),run:(e,t)=>e.sessions.artifacts(t),cliSchema:{usageOverride:`artifacts [provider-session-id]`,usageFlags:[`provider`],positionalArgs:[`provider-session-id?`],allowedFlags:[`provider`,`providerSessionId`]},cliReader:(e,t)=>({...b(t),provider:t.provider,providerSessionId:e[0]??t.providerSessionId}),daemonWriter:v(d.artifacts),cliOutputFormatter:X.artifacts});function Tc(e){let{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i}=e;if(t!==void 0||n!==void 0||r!==void 0||i!==void 0)return{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i}}function Ec(e){let{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i,...a}=e,o=Tc({metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i});return o?{...a,runtime:o}:a}const Dc=R(`apps`,`List the apps installed on the selected device. Include system or OEM apps only when they are needed as automation targets.`,{appsFilter:F([`user-installed`,`all`],`Restrict the listing to user-installed apps, or include system and OEM apps.`)}),Oc=R(`open`,`Boot the selected device when needed, then open an app, deep link, or URL in a session. Use the app or URL inputs to choose what becomes the foreground automation target.`,{app:j(`App name, bundle id, package, or URL.`),url:j(`Optional URL passed with an app shell.`),surface:F(ot,`macOS presentation surface to open: the app itself, the frontmost app, the desktop, or the menu bar.`),activity:j(`Android activity name.`),launchConsole:j(`Launch console mode.`),launchArgs:Tr(`Launch arguments forwarded verbatim to the platform launch command.`),relaunch:P(`Force relaunch.`),timeoutMs:N(`Startup budget in milliseconds. Bounds the Simulator boot wait, so a never-booted Simulator can finish its first-boot migration; omit for the default startup behavior.`,{min:1}),foreground:br(`foreground`),saveScript:I({oneOf:[hr(),k()]}),force:P(`Overwrite an existing --save-script target instead of refusing (alias: --overwrite).`),deviceHub:P(`Use Xcode Device Hub when surfacing Apple simulators.`),testIme:P(`Activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices).`),noRecord:P(`Do not record this action.`),metroHost:j(`Session-scoped Metro/debug host hint applied to the opened app.`),metroPort:N(`Session-scoped Metro/debug port hint applied to the opened app. On an emulator/simulator the host defaults to the loopback alias (Android 10.0.2.2, iOS 127.0.0.1) when --metro-host is omitted; physical devices still require an explicit --metro-host.`,{min:1,max:65535}),bundleUrl:j(`Session-scoped bundle URL hint applied to the opened app.`),launchUrl:j(`Session-scoped launch URL hint applied to the opened app.`)}),kc=R(`close`,`Close the named app, or close the active session app when app is omitted. Use shutdown only when the selected simulator or emulator should also stop.`,{app:j(`Optional app to close.`),shutdown:P(`Shutdown the session/device where supported.`),saveScript:I({oneOf:[hr(),k()]}),force:P(`Overwrite an existing --save-script target instead of refusing (alias: --overwrite).`)});function Ac(e){return Ec(e)}const jc={allowedFlags:[`appsFilter`]},Mc={positionalArgs:[`appOrUrl?`,`url?`],allowedFlags:[`activity`,`launchConsole`,`launchArgs`,`deviceHub`,`testIme`,`saveScript`,`force`,`noRecord`,`relaunch`,`foreground`,`timeoutMs`,`surface`,...bi,`launchUrl`]},Nc={positionalArgs:[`app?`],allowedFlags:[`saveScript`,`force`,`shutdown`]},Pc=(e,t)=>({...b(t),appsFilter:Kt(t.appsFilter)}),Fc=(e,t)=>({...b(t),app:e[0],url:e[1],surface:t.surface,activity:t.activity,launchConsole:t.launchConsole,launchArgs:t.launchArgs,relaunch:t.relaunch,foreground:t.foreground,timeoutMs:t.timeoutMs,saveScript:t.saveScript,force:t.force,deviceHub:t.deviceHub,testIme:t.testIme,noRecord:t.noRecord,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,launchUrl:t.launchUrl}),Ic=(e,t)=>({...b(t),app:e[0],shutdown:t.shutdown,saveScript:t.saveScript,force:t.force}),Lc=v(d.apps),Rc=v(d.open,Wc),zc=v(d.close,e=>C(e.app)),Bc=D({name:`apps`,text:{summary:`List installed apps or deferred provider app assets`,cliDetail:`Before provider allocation, lists uploaded app assets when the selected provider exposes a catalog. On a live device, defaults to user-installed apps; use --all to include system/OEM apps.`},metadata:Dc,run:(e,t)=>e.apps.list(t),cliSchema:jc,cliReader:Pc,daemonWriter:Lc,cliOutputFormatter:X.apps}),Vc=D({name:`open`,text:{summary:`Open an app, deep link or URL, save replays`,cliDetail:`Use --platform to bind URL/deep-link opens to the target platform. For iOS simulator initial stdout/stderr, put --launch-console <path> on this open command, for example agent-device open "Agent Device Tester" --platform ios --launch-console artifacts/launch-console.log. Expo Go/dev-client shells accept host + URL, for example agent-device open "Expo Go" exp://127.0.0.1:8081 --platform ios. macOS also supports --surface app|frontmost-app|desktop|menubar. --metro-host/--metro-port/--bundle-url/--launch-url set this session's Metro/debug runtime hints as part of open itself (applied to the app's dev-server prefs and recorded as the session's dev-server binding), so a fresh session has them before its first reload instead of needing a throwaway reload-first call just to seed hints; a later plain metro reload in the same session reuses whichever of these were set. A fresh open without these flags clears any leftover binding from a previous same-name session; close also clears it.`,mcpDetail:`Metro and debug runtime hints given here are recorded as the session's dev-server binding, so a later reload reuses them; a fresh open without them clears any binding left by a previous same-name session.`},metadata:Oc,run:(e,t)=>e.apps.open(Ac(t)),cliSchema:Mc,cliReader:Fc,daemonWriter:Rc,cliOutputFormatter:X.open}),Hc=D({name:`close`,text:{summary:`Close an app or end the session`},metadata:kc,run:(e,t)=>t.app?e.apps.close(t):e.sessions.close(Uc(t)),cliSchema:Nc,cliReader:Ic,daemonWriter:zc,cliOutputFormatter:X.close});function Uc(e){let{app:t,...n}=e;return n}function Wc(e){return e.app?e.url?[e.app,e.url]:[e.app]:[]}const Gc=R(`devices`,`List available devices and simulators that can be selected for automation. Use platform, device, udid, or serial inputs on later commands to target one result.`,{}),Kc=R(`capabilities`,`List the commands supported by the selected device or active session. Use device-selection inputs when checking support before a session is open.`,{}),qc=R(`boot`,`Boot or prepare the selected device or simulator so later commands can target it. The device is chosen through the device-selection inputs, not by naming it here.`,{headless:P(`Boot without showing simulator UI when supported.`)}),Jc=R(`shutdown`,`Shutdown a selected simulator or emulator.`,{}),Yc={allowedFlags:[`headless`]},Xc={},Zc={},Qc={},$c=(e,t)=>b(t),el=(e,t)=>({...b(t),headless:t.headless}),tl=v(d.devices),nl=v(d.capabilities),rl=v(d.boot),il=v(d.shutdown),al=[D({name:`devices`,text:{summary:`List available devices and simulators`},metadata:Gc,run:(e,t)=>e.devices.list(t),cliSchema:Xc,cliReader:$c,daemonWriter:tl,cliOutputFormatter:X.devices}),D({name:`capabilities`,text:{summary:`List supported commands for the selected device`,cliDetail:`Select an explicit target with --platform/--device/--udid/--serial.`},metadata:Kc,run:(e,t)=>e.devices.capabilities(t),cliSchema:Zc,cliReader:$c,daemonWriter:nl,cliOutputFormatter:X.capabilities}),D({name:`boot`,text:{summary:`Boot target device/simulator`},metadata:qc,run:(e,t)=>e.devices.boot(t),cliSchema:Yc,cliReader:el,daemonWriter:rl,cliOutputFormatter:X.boot}),D({name:`shutdown`,text:{summary:`Shutdown target simulator/emulator`},metadata:Jc,run:(e,t)=>e.devices.shutdown(t),cliSchema:Qc,cliReader:$c,daemonWriter:il,cliOutputFormatter:X.shutdown})],ol=D({name:`doctor`,text:{summary:`Diagnose device, app, dev-server, and RN/Expo readiness`,cliDetail:`Metro reachability is inferred from cwd/runtime. On iOS simulators it also warms the XCTest runner build cache in the background when missing. Pass --app to verify a target app on the one matching booted device without opening a session. Use --remote to check remote connection setup without probing local devices. Default output is compact; use --json for full checks and evidence.`,mcpDetail:`On iOS simulators it also warms the XCTest runner build cache in the background when missing, so run it before the first Apple snapshot or interaction of a session.`},metadata:R(`doctor`,`Diagnose device, app, development-server, and React Native or Expo readiness issues. Returns compact evidence for local inventory, sessions, optional app discovery, toolchains, and server reachability.`,{targetApp:j(`Installed app package/bundle id or app name to verify without opening a session.`),remote:P(`Check remote connection setup instead of local device inventory.`)}),run:(e,t)=>e.command.doctor(t),cliSchema:{usageOverride:`doctor [--platform ios|android|harmonyos|vega|macos|linux|web|apple]`,allowedFlags:[`targetApp`,`remote`]},cliReader:(e,t)=>({...b(t),targetApp:t.targetApp,remote:t.remote}),daemonWriter:v(d.doctor),cliOutputFormatter:X.doctor});function sl(t,n=`--github-actions-artifact`){let r=t.indexOf(`:`);if(r<=0||r===t.length-1)throw new e(`INVALID_ARGS`,`${n} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:i,repo:a}=ul(t.slice(0,r),n);return ll(i,a,t.slice(r+1),`${n} artifact`)}function cl(t,n){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`${n} installSource must be an object.`);let r=t;if(fl(r.type,`${n} installSource.type`)!==`github-actions-artifact`)throw new e(`INVALID_ARGS`,`${n} installSource.type must be "github-actions-artifact".`);let{owner:i,repo:a}=ul(fl(r.repo,`${n} installSource.repo`),`${n} installSource.repo`);return ll(i,a,r.artifact,`${n} installSource.artifact`)}function ll(e,t,n,r){return typeof n==`number`||ml(n)?{kind:`github-actions-artifact`,owner:e,repo:t,artifactId:pl(n,r)}:{kind:`github-actions-artifact`,owner:e,repo:t,artifactName:fl(n,r)}}function ul(t,n){let r=t.indexOf(`/`);if(r<=0||r===t.length-1||t.indexOf(`/`,r+1)!==-1)throw new e(`INVALID_ARGS`,`${n} must use owner/repo.`);let i={owner:t.slice(0,r).trim(),repo:t.slice(r+1).trim()};if(!i.owner||!i.repo)throw new e(`INVALID_ARGS`,`${n} must use owner/repo.`);return i}function dl(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}function fl(t,n){let r=dl(t);if(!r)throw new e(`INVALID_ARGS`,`${n} must be a non-empty string.`);return r}function pl(t,n){let r=typeof t==`number`?t:typeof t==`string`?Number(t):NaN;if(!Number.isInteger(r))throw new e(`INVALID_ARGS`,`${n} must be an integer.`);return r}function ml(e){return typeof e==`string`&&/^\d+$/.test(e.trim())}const hl=R(`install`,`Install an app binary from a local path. Provide an app identifier with the path when the target needs explicit app selection; use reinstall to replace an already installed app.`,{app:j(`Optional app identifier hint.`),appPath:A(j(`Path to app binary.`))}),gl=R(`reinstall`,`Replace an installed app with a binary from a local path. Use this when preserving the same app identity while installing a new build on the selected device.`,{app:A(j()),appPath:A(j(`Path to app binary.`))}),_l=R(`install-from-source`,`Install app builds from URLs, remote source specs, or CI artifacts resolved by a remote daemon.`,{source:A(I(_r(`Install source object.`))),retainPaths:P(),retentionMs:N()}),vl={usageOverride:`install <path> | install <app> <path>`,listUsageOverride:`install <path>`,positionalArgs:[`appOrPath`,`path?`]},yl={positionalArgs:[`app`,`path`]},bl={usageOverride:`install-from-source <url> | install-from-source --github-actions-artifact <owner/repo:artifact>`,usageFlags:[],listUsageOverride:`install-from-source`,positionalArgs:[`url?`],allowedFlags:[`header`,`githubActionsArtifact`,`installSource`,`retainPaths`,`retentionMs`]},xl=(e,t)=>Dl(e,t),Sl=(e,t)=>Ol(e,t),Cl=(e,t)=>({...b(t),source:jl(e,t),retainPaths:t.retainPaths,retentionMs:t.retentionMs}),wl=v(d.install,e=>kl(e.app,e.appPath)),Tl=v(d.reinstall,e=>Al(e.app,e.appPath)),El=[D({name:`install`,text:{summary:`Install an app binary from a path`},metadata:hl,run:(e,t)=>e.apps.install(t),cliSchema:vl,cliReader:xl,daemonWriter:wl,cliOutputFormatter:X.install}),D({name:`reinstall`,text:{summary:`Replace an installed app with a new build`},metadata:gl,run:(e,t)=>e.apps.reinstall(t),cliSchema:yl,cliReader:Sl,daemonWriter:Tl,cliOutputFormatter:X.reinstall}),D({name:`install-from-source`,text:{summary:`Install app builds from URLs or CI artifacts`},metadata:_l,run:(e,t)=>e.apps.installFromSource(t),cliSchema:bl,cliReader:Cl,daemonWriter:e=>y(it.installSource,[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),cliOutputFormatter:X[`install-from-source`]})];function Dl(e,t){let[n,r]=e,i=r!==void 0;return{...b(t),...i?{app:T(n,`install requires app`)}:{},appPath:T(i?r:n,`install requires path`)}}function Ol(e,t){return{...b(t),app:T(e[0],`reinstall requires app`),appPath:T(e[1],`reinstall requires path`)}}function kl(e,t){let n=E(t,`missing app path`);return typeof e==`string`&&e.length>0?[e,n]:[n]}function Al(e,t){return[E(e,`missing first positional`),E(t,`missing second positional`)]}function jl(t,n){let r=t[0]?.trim();if(t.length>1)throw new e(`INVALID_ARGS`,`install-from-source accepts either one <url> positional or --github-actions-artifact`);let i=n.githubActionsArtifact?sl(n.githubActionsArtifact):void 0,a=n.installSource;if(+!!r+ +!!i+ +!!a!=1)throw new e(`INVALID_ARGS`,`install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource`);if(!r&&n.header&&n.header.length>0)throw new e(`INVALID_ARGS`,`install-from-source --header is only supported for URL sources`);return i||a||{kind:`url`,url:r,headers:Ml(n.header)}}function Ml(t){if(!t||t.length===0)return;let n={};for(let r of t){let t=r.indexOf(`:`);if(t<=0)throw new e(`INVALID_ARGS`,`Invalid --header value "${r}". Expected "name:value".`);let i=r.slice(0,t).trim(),a=r.slice(t+1).trim();if(!i)throw new e(`INVALID_ARGS`,`Invalid --header value "${r}". Header name cannot be empty.`);n[i]=a}return n}const Nl=D({name:`prepare`,text:{summary:`Pre-warm platform helpers before automation`},metadata:R(`prepare`,`Prepare platform helper infrastructure. ios-runner builds/reuses, starts, and health-checks the XCTest runner so later Apple snapshots and interactions do not pay first-use startup cost. In JSON output, top-level buildMs/connectMs/healthCheckMs are diagnostic fields and may overlap; use timing.additiveParts for additive wall-clock phase totals. In CI, run it after boot/install and before replay/test; if replay/test starts a separate daemon, stop the prepare daemon before replay/test so it does not keep the prepared runner lease. It is not a recovery step for "runner already owned by another agent-device daemon"; stop the owning daemon on the Mac with simulator access instead. Runner build/start output is written to the session runner.log; daemon.log is for daemon lifecycle/startup issues.`,{action:A(F([`ios-runner`])),timeoutMs:N(`Maximum wall-clock time for the prepare command.`)}),run:(e,t)=>e.command.prepare(t),cliSchema:{usageOverride:`prepare ios-runner --platform ios|macos`,listUsageOverride:`prepare`,positionalArgs:[`ios-runner`],allowedFlags:[`timeoutMs`]},cliReader:(e,t)=>({...b(t),action:T(e[0],`prepare requires subcommand`),timeoutMs:t.timeoutMs}),daemonWriter:v(d.prepare,e=>[E(e.action,`prepare requires subcommand`)]),cliOutputFormatter:X.prepare}),Pl=R(`push`,`Deliver push notification payloads to an installed app.`,{app:A(j()),payload:A(I({oneOf:[k(),_r()]}))}),Fl=R(`trigger-app-event`,`Ask the app to handle an app-defined automation or test event, with an optional structured payload. Call this only for event names and payload shapes the app documents.`,{event:A(j(`Name of an app-defined automation or test event the app documents.`)),payload:Gl(`Structured payload passed to the event, in the shape the app documents for it.`)}),Il={listUsageOverride:`push`,positionalArgs:[`bundleOrPackage`,`payloadOrJson`]},Ll={usageOverride:`trigger-app-event <event> [payloadJson]`,listUsageOverride:`trigger-app-event`,positionalArgs:[`event`,`payloadJson?`]},Rl=(e,t)=>({...b(t),app:T(e[0],`push requires bundleOrPackage`),payload:T(e[1],`push requires payloadOrJson`)}),zl=(e,t)=>({...b(t),event:T(e[0],`trigger-app-event requires event`),payload:e[1]?Yn(e[1],`trigger-app-event payload`):void 0}),Bl=v(d.push,e=>Ul(e)),Vl=v(d.triggerAppEvent,e=>Wl(e)),Hl=[D({name:`push`,text:{summary:`Deliver a push notification payload`},metadata:Pl,run:(e,t)=>e.apps.push(t),cliSchema:Il,cliReader:Rl,daemonWriter:Bl}),D({name:`trigger-app-event`,text:{summary:`Invoke an app-defined automation event`},metadata:Fl,run:(e,t)=>e.apps.triggerEvent(t),cliSchema:Ll,cliReader:zl,daemonWriter:Vl})];function Ul(e){return[e.app,typeof e.payload==`string`?e.payload:JSON.stringify(e.payload)]}function Wl(e){return[e.event,...e.payload?[JSON.stringify(e.payload)]:[]]}function Gl(e){return wr(e)}const Kl=D({name:`session`,text:{summary:`List sessions, show the state dir, or publish a script`},metadata:R(`session`,`List active sessions, print the effective daemon state directory, or publish an armed open-to-destination script without closing its session`,{action:F([`list`,`state-dir`,`save-script`],`list shows active sessions; state-dir prints the daemon state directory; save-script publishes an armed recording without teardown.`),path:j(`Optional .ad output path for save-script.`),force:P(`Atomically replace an existing save-script target.`)}),run:async(e,{action:t,path:n,force:r,...i})=>{let a=t??`list`;return Jl(a,n,r),a===`state-dir`?{stateDir:await e.sessions.stateDir(i)}:a===`save-script`?await e.sessions.saveScript({...i,path:n,force:r}):{sessions:await e.sessions.list(i)}},cliSchema:{usageOverride:`session list | session state-dir | session save-script [path] [--force]`,usageFlags:[],listUsageOverride:`session`,positionalArgs:[`list|state-dir|save-script?`,`path?`],allowedFlags:[`force`]},cliReader:(e,t)=>({...b(t),action:ql(e[0]),path:e[1],force:t.force}),cliOutputFormatter:X.session});function ql(t){let n=t??`list`;if(n===`list`||n===`state-dir`||n===`save-script`)return n;throw new e(`INVALID_ARGS`,`session only supports list, state-dir, or save-script`)}function Jl(t,n,r){if(t!==`save-script`&&(n!==void 0||r===!0))throw new e(`INVALID_ARGS`,`session ${t} does not accept a path or --force; use session save-script [path] [--force] to publish a recording.`)}const Yl=D({name:`viewport`,text:{summary:`Resize the active web viewport for the current session`},metadata:R(`viewport`,`Resize the active web viewport before taking snapshots or screenshots. Useful for fixed-layout or 100vh apps where changing the viewport reveals different content.`,{width:A(N(`Viewport width in CSS pixels.`,{min:1})),height:A(N(`Viewport height in CSS pixels.`,{min:1}))}),run:(e,t)=>e.command.viewport(t),cliSchema:{positionalArgs:[`width`,`height`]},cliReader:(e,t)=>({...b(t),...me(e)}),daemonWriter:v(d.viewport,e=>{let{width:t,height:n}=e;return[String(t),String(n)]}),cliOutputFormatter:X.viewport}),Xl=O({name:`management`,commands:[...al,wc,ol,Nl,Bc,Kl,Vc,Hc,Yl,...El,...Hl]});function Zl(e){return{data:e.result,text:e.action===`reload`?`Reloaded React Native apps via ${e.result.reloadUrl}`:JSON.stringify(e.result,null,2)}}const Ql={metro:({input:e,result:t})=>Zl({result:t,action:e.action})},$l=`metro`,eu=O({name:`metro`,commands:[D({name:$l,text:{summary:`Prepare the dev server or reload apps`,cliDetail:`reload with no --metro-host/--metro-port/--bundle-url resolves against the dev server this session last bound via metro prepare or open's metro hint flags (falling back to localhost:8081 only when the session never bound one), so it never silently reloads a different project's server on the default port; pass an explicit flag to override the session hint for one call. The reload URL keeps the bound bundle URL mount prefix instead of collapsing to the host root, and when the server has no HTTP /reload route (Expo) the reload is broadcast over its /message websocket instead of trusting the app-page fallback. The binding is cleared when the session closes, and a fresh open without hint flags also clears any leftover binding from a previous same-name session. --kind expo (detected or forced) requests the virtual-entry bundle URL (.expo/.virtual-metro-entry.bundle) instead of index.bundle, since index.bundle 404s/500s against Expo dev servers in monorepos. Dependency install auto-detects the package manager from the nearest yarn.lock/pnpm-lock.yaml/bun.lock/bun.lockb/package-lock.json walking up from --project-root (bounded at the repo root), so Yarn/pnpm workspace monorepos with the lockfile at the repo root do not wrongly fall back to npm install (which fails on workspace: dependency specifiers); if install still fails, pass --no-install-deps when dependencies are already installed (for example via a monorepo root install).`,mcpDetail:`The binding is cleared when the session closes, and a fresh open without runtime hints also clears any leftover binding from a previous same-name session.`},metadata:R($l,`Prepare a React Native development server or ask connected apps to reload, using the development server this session is bound to. Provide explicit runtime inputs only to override that binding for one call.`,{action:A(F([`prepare`,`reload`])),projectRoot:j(),kind:I(k()),publicBaseUrl:j(),proxyBaseUrl:yr(j(),{operatorPath:`Configure the remote proxy in the remote-config profile or operator config for the process serving these tools.`}),bearerToken:yr(j(),{envFlagKeys:[`metroBearerToken`,`daemonAuthToken`]}),bridgeScope:I({type:`object`,additionalProperties:!0}),launchUrl:j(),port:N(),listenHost:j(),statusHost:j(),startupTimeoutMs:N(),probeTimeoutMs:N(),reuseExisting:P(),installDependenciesIfNeeded:P(),runtimeFilePath:j(),logPath:j(),metroHost:j(),metroPort:N(),bundleUrl:j(),timeoutMs:N()}),run:async(e,t)=>t.action===`prepare`?await e.metro.prepare(tu(t)):await e.metro.reload(ru(t)),cliSchema:{usageOverride:`metro prepare (--public-base-url <url> | --proxy-base-url <url>) [--project-root <path>] [--port <port>] [--kind auto|react-native|expo|repack]
26
- agent-device metro reload [--metro-host <host>] [--metro-port <port>] [--bundle-url <url>]`,usageFlags:[],listUsageOverride:`metro`,positionalArgs:[`prepare|reload`],allowedFlags:[...bi,...yi]},cliReader:(t,n)=>{let r=(t[0]??``).toLowerCase();if(r!==`prepare`&&r!==`reload`)throw new e(`INVALID_ARGS`,`metro requires a subcommand: prepare or reload`);if(r===`reload`)return{action:r,metroHost:n.metroHost,metroPort:n.metroPort,bundleUrl:n.bundleUrl,timeoutMs:n.metroProbeTimeoutMs};if(!n.metroPublicBaseUrl&&!n.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`);return{action:r,projectRoot:n.metroProjectRoot,kind:Yt(n.kind??n.metroKind),port:n.metroPreparePort,listenHost:n.metroListenHost,statusHost:n.metroStatusHost,publicBaseUrl:n.metroPublicBaseUrl,proxyBaseUrl:n.metroProxyBaseUrl,bearerToken:n.metroBearerToken,bridgeScope:n.tenant&&n.runId&&n.leaseId?{tenantId:n.tenant,runId:n.runId,leaseId:n.leaseId}:void 0,startupTimeoutMs:n.metroStartupTimeoutMs,probeTimeoutMs:n.metroProbeTimeoutMs,reuseExisting:!n.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!n.metroNoInstallDeps&&void 0,runtimeFilePath:n.metroRuntimeFile}},cliOutputFormatter:Ql.metro})]});function tu(e){return{projectRoot:e.projectRoot,kind:e.kind,publicBaseUrl:e.publicBaseUrl,proxyBaseUrl:e.proxyBaseUrl,bearerToken:e.bearerToken,bridgeScope:e.bridgeScope??nu(e),port:e.port,listenHost:e.listenHost,statusHost:e.statusHost,startupTimeoutMs:e.startupTimeoutMs,probeTimeoutMs:e.probeTimeoutMs,reuseExisting:e.reuseExisting,installDependenciesIfNeeded:e.installDependenciesIfNeeded,runtimeFilePath:e.runtimeFilePath}}function nu(e){return e.tenant&&e.runId&&e.leaseId?{tenantId:e.tenant,runId:e.runId,leaseId:e.leaseId}:void 0}function ru(e){return{metroHost:e.metroHost,metroPort:e.metroPort,bundleUrl:e.bundleUrl,timeoutMs:e.timeoutMs}}function iu(e,t){return e.includes(t)}function au(t,n,r={}){let i=n===void 0?void 0:r.normalize?.(n)??n;if(i!==void 0&&iu(t,i))return i;let a=typeof r.message==`function`?r.message(n):r.message;throw new e(`INVALID_ARGS`,a??`Invalid value: ${n}. Use ${t.join(`|`)}.`)}const ou=[`started`,`stopped`,`marked`,`cleared`,`restarted`,`removedRotatedFiles`];function su(e){return{data:e,text:e.path,stderr:Fu([Nu(e,[`active`,`state`,`backend`,`sizeBytes`]),Tu(e),e.hint,Pu(e.notes)])}}function cu(e){let t=e.events??[];return{data:e,text:t.length>0?fu(t):`No session events found.`,stderr:Fu([Nu(e,[`path`,`cursor`,`nextCursor`,`limit`])])}}function lu(e){let t=[],n=e.entries??[];if(e.path&&t.push(e.path),n.length===0)t.push(`No recent HTTP(s) entries found.`);else for(let e of n)t.push(...Au(e));return{data:e,text:t.join(`
27
- `),stderr:Fu([Nu(e,[`active`,`state`,`backend`,`include`,`scannedLines`,`matchedLines`]),Pu(e.notes)])}}function uu(e){return{data:e,text:[`Audio probe: ${String(e.state??`stopped`)} heard=${String(e.heard===!0)}`,wu(`rmsDbfs`,e.rmsDbfs),wu(`peakDbfs`,e.peakDbfs)].filter(e=>!!e).join(`
28
- `),stderr:Fu([Nu(e,[`active`,`backend`,`source`,`durationMs`,`elapsedMs`,`bucketMs`,`sampleCount`,`sourceCount`,`mediaElementCount`]),Pu(e.notes)])}}const du={logs:f(su),events:f(cu),network:f(lu),audio:f(uu)};function fu(e){let t=e.map(pu),n=Math.min(Math.max(...t.map(e=>e.label.length),5),32);return t.map(e=>mu(e,n)).join(`
29
- `)}function pu(e){return{timestamp:hu(e.ts),label:gu(e),summary:_u(e)}}function mu(e,t){let n=e.label.padEnd(t),r=e.timestamp?`${e.timestamp} ${n}`:n.trimEnd();return e.summary?`${r} ${e.summary}`:r.trimEnd()}function hu(e){return e?e.replace(`T`,` `):``}function gu(e){let t=e.command??`command`;switch(e.kind){case`request.started`:return`start ${t}`;case`request.finished`:return Du([e.status===`error`?`error`:`ok`,t,Cu(ku(e.details?.durationMs))]);case`action.recorded`:return`action ${t}`;default:return Du([e.kind??`event`,e.command])}}function _u(e){let t=vu(e.summary,e);return`${t}${yu(e,t)}`.trim()}function vu(e,t){let n=e?.trim()??``,r=t.command??``;return t.kind===`request.started`&&n===`Started ${r}`||t.kind===`request.finished`&&n===`Finished ${r}`?``:n}function yu(e,t){if(e.kind!==`action.recorded`)return``;let n=e.details;if(!n)return``;let r=[bu(n,t),Su(ku(n.textLength))].filter(e=>!!e);return r.length>0?` (${r.join(`, `)})`:``}function bu(e,t){let n=Ou(e.ref)??Ou(e.selector)??xu(e);if(!(!n||t.includes(n)))return`target=${n}`}function xu(e){let t=ku(e.x),n=ku(e.y);return t===void 0||n===void 0?void 0:`(${t}, ${n})`}function Su(e){return e===void 0?void 0:`text=${e} chars`}function Cu(e){return e===void 0?void 0:`${Math.round(e)}ms`}function wu(e,t){if(!Array.isArray(t))return;let n=t.filter(e=>typeof e==`number`&&Number.isFinite(e));return n.length>0?`${e}: [${n.join(`, `)}]`:void 0}function Tu(e){return ou.map(t=>Eu(t,e[t])).filter(Boolean).join(` `)||void 0}function Eu(e,t){return t==null?``:`${e}=${t}`}function Du(e){return e.filter(e=>!!e).join(` `)}function Ou(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function ku(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function Au(e){let t=e.method??`HTTP`,n=e.url??`<unknown-url>`,r=e.status===void 0?``:` status=${e.status}`,i=e.timestamp?`${e.timestamp} `:``,a=e.durationMs===void 0?``:` durationMs=${e.durationMs}`,o=[`${i}${t} ${n}${`pathUnavailable`in e&&e.pathUnavailable?` (request path not logged)`:``}${r}${a}`];return e.headers?Mu(o,`headers`,e.headers):(ju(o,`request headers`,e.requestHeaders),ju(o,`response headers`,e.responseHeaders)),Mu(o,`request`,e.requestBody),Mu(o,`response`,e.responseBody),o}function ju(e,t,n){!n||Object.keys(n).length===0||e.push(` ${t}: ${JSON.stringify(n)}`)}function Mu(e,t,n){n!==void 0&&e.push(` ${t}: ${n}`)}function Nu(e,t){return t.map(t=>e[t]!==void 0&&e[t]!==null?`${t}=${e[t]}`:``).filter(Boolean).join(` `)||void 0}function Pu(e){let t=e?.filter(e=>e.length>0)??[];return t.length>0?t.join(`
30
- `):void 0}function Fu(e){return e.filter(e=>!!e).join(`
31
- `)||void 0}const Iu=`logs`,Lu=`events`,Ru=`network`,zu=`audio`,Bu=[`dump`,`log`],Vu=[`probe`],Hu=[`start`,`status`,`stop`],Uu=R(Iu,`Session app log info, start/stop streaming, diagnostics, and markers`,{action:F(rn),message:j(),restart:P()}),Wu=R(Lu,`Read the daemon-owned session event timeline as paged JSON-friendly entries`,{limit:N(),cursor:j()}),Gu=R(Ru,`Dump recent HTTP(s) traffic parsed from the session app log`,{action:F(Bu),limit:N(),include:F(i)}),Ku=R(zu,`Measure browser or host-rendered simulator/emulator audio as compact dBFS buckets. Start a probe before requesting its status or stopping it.`,{action:F(Vu),probeAction:F(Hu),durationMs:N(`Probe duration in milliseconds.`),bucketMs:N(`Audio level bucket size in milliseconds.`)}),qu=O({name:`observability`,commands:[D({name:Iu,text:{summary:`Manage session app logs`},metadata:Uu,run:(e,t)=>e.observability.logs(t),cliSchema:{usageOverride:`logs path | logs start | logs stop | logs clear [--restart] | logs doctor | logs mark [message...]`,usageFlags:[],positionalArgs:[`path|start|stop|clear|doctor|mark`,`message?`],allowsExtraPositionals:!0,allowedFlags:[`restart`]},cliReader:(e,t)=>({...b(t),action:Qu(e[0]),message:e.slice(1).join(` `)||void 0,restart:t.restart}),daemonWriter:v(Iu,e=>Ju(e)),cliOutputFormatter:du.logs}),D({name:Lu,text:{summary:`Read session event timeline`},metadata:Wu,run:(e,t)=>e.observability.events(t),cliSchema:{usageOverride:`events [limit] [cursor]`,listUsageOverride:`events`,positionalArgs:[`limit?`,`cursor?`]},cliReader:(e,t)=>({...b(t),limit:e[0]?.trim()?$n(e[0]):void 0,cursor:e[1]}),daemonWriter:e=>y(Lu,Yu(e),e),cliOutputFormatter:du.events}),D({name:Ru,text:{summary:`Inspect HTTP(S) traffic from session logs`},metadata:Gu,run:(e,t)=>e.observability.network(t),cliSchema:{usageOverride:`network dump [limit] [summary|headers|body|all] [--include summary|headers|body|all] | network log [limit] [summary|headers|body|all] [--include summary|headers|body|all]`,usageFlags:[],listUsageOverride:`network`,positionalArgs:[`dump|log`,`limit?`,`include?`],allowedFlags:[`networkInclude`]},cliReader:(e,t)=>({...b(t),action:$u(e[0]),limit:$n(e[1]),include:t.networkInclude??ed(e[2])}),daemonWriter:e=>y(Ru,Xu(e),{...e,networkInclude:e.include}),cliOutputFormatter:du.network}),D({name:zu,text:{summary:`Probe audio levels`},metadata:Ku,run:(e,t)=>e.observability.audio(t),cliSchema:{usageOverride:`audio probe start [durationSeconds] [bucketMs] | audio probe status | audio probe stop`,listUsageOverride:`audio`,positionalArgs:[`probe`,`start|status|stop`,`durationSeconds?`,`bucketMs?`]},cliReader:(e,t)=>({...b(t),action:td(e[0]),probeAction:nd(e[1]),durationMs:rd(e[2]),bucketMs:$n(e[3])}),daemonWriter:e=>y(zu,Zu(e),e),cliOutputFormatter:du.audio})]});function Ju(e){return[e.action??`path`,...C(e.message)]}function Yu(e){return e.cursor===void 0?w(e.limit):[e.limit===void 0?``:String(e.limit),e.cursor]}function Xu(e){return[...e.action?[e.action]:[],...w(e.limit)]}function Zu(e){return[e.action??`probe`,e.probeAction??`status`,...w(e.durationMs),...w(e.bucketMs)]}function Qu(e){if(e!==void 0)return au(rn,e,{message:`logs requires path, start, stop, doctor, mark, or clear`})}function $u(t){if(t!==void 0){if(t===`dump`||t===`log`)return t;throw new e(`INVALID_ARGS`,`network requires dump or log`)}}function ed(e){if(e!==void 0)return au(i,e,{message:`network include must be summary, headers, body, or all`})}function td(e){if(e!==void 0)return au(Vu,e,{message:`audio requires probe`})}function nd(e){if(e!==void 0)return au(Hu,e,{message:`audio probe requires start, status, or stop`})}function rd(e){let t=$n(e);return t===void 0?void 0:Math.round(t*1e3)}function id(e){let t=e;return{data:t,text:od(t)}}const ad={perf:f(id)};function od(e){return pd(e)??sd(e)}function sd(e){let t=u(e.artifact)?e.artifact:void 0;return t?fd(t):cd(u(e.metrics)?e.metrics:void 0)}function cd(e){return u(e?.fps)?ud(e):ld(e)??`Memory: unavailable - missing memory metric`}function ld(e){let t=u(e?.memory)?e.memory:void 0;if(!t)return;if(t.available===!1)return`Memory: unavailable - ${wd(t)}`;let n=Ad(t);return n?`Performance: ${n}`:`Memory: unavailable - missing memory metric`}function ud(e){let t=u(e?.fps)?e.fps:void 0;if(!t)return Cd(`missing frame metric`);if(t.available===!1)return Cd(wd(t));let n=Td(t);return n?dd(t,n):Cd(`missing dropped-frame summary`)}function dd(e,t){let n=[`Frame health: ${t}`],r=Od(e);return r.length>0&&n.push(`Worst windows:`,...r),n.join(`
32
- `)}function fd(e){let t=typeof e.kind==`string`?e.kind:`memory`;if(e.available===!1)return`Memory artifact (${t}): unavailable - ${typeof e.reason==`string`&&e.reason.length>0?e.reason:`not available`}`;let n=typeof e.path==`string`?e.path:void 0,r=Q(e.sizeBytes),i=r===void 0?``:` (${Pd(r)})`;return n?`Memory artifact (${t}): ${n}${i}`:`Memory artifact (${t}): captured${i}`}function pd(e){return e.kind===`xctrace`?md(e):vd(e)}function md(e){let t=typeof e.perf==`string`?e.perf:void 0,n=gd(e);if(!t||!n||e.kind!==`xctrace`)return;let r=_d(n,typeof e.mode==`string`?e.mode:`capture`,t,e.template),i=hd(e);return i.length>0?`${r}\nTop CPU self time:\n${i.join(`
33
- `)}`:r}function hd(e){let t=u(e.summary)?e.summary:void 0;return Array.isArray(t?.topFunctions)?t.topFunctions.slice(0,5).flatMap(e=>{if(!u(e))return[];let t=Z(e.symbol),n=Q(e.selfSamplePercent);if(!t||n===void 0)return[];let r=Z(e.binary);return[`- ${jd(n)} ${t}${r?` (${r})`:``}`]}):[]}function gd(e){return typeof e.outPath==`string`?e.outPath:typeof e.reportPath==`string`?e.reportPath:void 0}function _d(e,t,n,r){let i=[e,`Perf ${t}: ${n}`];return typeof r==`string`&&i.push(`Template: ${r}`),i.join(`
34
- `)}function vd(e){let t=yd(e);if(!t)return;let n=`Perf ${t.action}: ${t.kind} ${t.type}${bd(e)}${xd(e)}${Sd(e)}`,r=hd(e);return r.length>0?`${n}\nTop CPU self time:\n${r.join(`
35
- `)}`:n}function yd(e){let t=Z(e.action),n=Z(e.kind),r=Z(e.type);return t&&n&&r?{action:t,kind:n,type:r}:void 0}function bd(e){let t=Z(e.state);return t?` state=${t}`:``}function xd(e){let t=Z(e.outPath);if(!t)return``;let n=Q(e.sizeBytes);return`\n${t}${n===void 0?``:` (${Pd(n)})`}`}function Z(e){return typeof e==`string`?e:void 0}function Sd(e){let t=u(e.summary)?e.summary:void 0,n=u(t?.frameHealth)?t.frameHealth:void 0;if(!n||n.available!==!0)return``;let r=Q(n.droppedFramePercent),i=Q(n.droppedFrameCount),a=Q(n.totalFrameCount);return r===void 0||i===void 0||a===void 0?``:`\nTrace frame health: dropped ${jd(r)} (${Math.round(i)}/${Math.round(a)} frames)`}function Cd(e){return`Frame health: unavailable - ${e}`}function wd(e){return typeof e.reason==`string`&&e.reason.length>0?e.reason:`not available`}function Td(e){let t=Q(e.droppedFramePercent),n=Q(e.droppedFrameCount);if(t!==void 0&&n!==void 0)return[`dropped ${jd(t)}`,Ed(n,Q(e.totalFrameCount)),Dd(Q(e.sampleWindowMs))].filter(Boolean).join(` `)}function Ed(e,t){return t===void 0?`(${Math.round(e)} dropped frames)`:`(${Math.round(e)}/${Math.round(t)} frames)`}function Dd(e){return e===void 0?``:`window ${Md(e)}`}function Od(e){return Array.isArray(e.worstWindows)?e.worstWindows.flatMap(e=>{if(!u(e))return[];let t=kd(e);return t?[t]:[]}):[]}function kd(e){let t=Q(e.startOffsetMs),n=Q(e.endOffsetMs),r=Q(e.missedDeadlineFrameCount);if(t===void 0||n===void 0||r===void 0)return;let i=Q(e.worstFrameMs),a=i===void 0?``:`, worst ${Md(i)}`;return`- +${Md(t)}-+${Md(n)}: ${Math.round(r)} missed-deadline frames${a}`}function Ad(e){if(e?.available!==!0)return;let t=Q(e.residentMemoryKb)??Q(e.totalPssKb)??Q(e.totalRssKb);return t===void 0?void 0:`memory ${Nd(t)}`}function Q(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function jd(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function Md(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 Nd(e){let t=e/1024;return`${t>=10?Math.round(t):t.toFixed(1)}MB`}function Pd(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`}const Fd=`perf`,Id=O({name:`perf`,commands:[D({name:Fd,text:{summary:`Check frames, memory, or native profiles`,cliDetail:`Use perf frames for bounded frame-health evidence and perf memory sample for a compact process-memory reading. On iOS simulators and macOS, process sampling and captures target the resolved app executable and exclude other copies with the same name. Apple xctrace and Android Simpleperf/Perfetto captures keep raw artifacts on disk; report produces bounded agent-readable evidence. For React render internals, use agent-device react-devtools.`,mcpDetail:`For CPU profiles, start and stop write the raw artifact while report writes a compact summary; request the report when the task needs readable native CPU evidence. Profiling output is evidence only: compact state, artifact path, and size.`},metadata:R(Fd,`Collect frame health, memory diagnostics, and platform profiling artifacts with compact agent-readable summaries.`,{area:A(F(gt)),subject:F(bt),action:F(ht),kind:F(ct),template:j(`xctrace template name, for example Time Profiler.`),out:j(`Output artifact path.`),tracePath:j(`Existing .trace path to report, defaults to the latest session trace.`)}),run:(e,t)=>e.observability.perf(t),cliSchema:{usageOverride:`perf frames --json
24
+ `)}}function mc(e){return`source`in e&&e.source===`daemon`}async function hc(e){let{serializeDeployResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return f(t(e))}async function gc(e){let{serializeInstallFromSourceResult:t}=await import(`./result-serialization.js`).then(e=>e.t);return f(t(e))}function _c(e){let t=e,n=t.platform??`unknown`;return{data:t,text:`Boot ready: ${t.device??t.id??`unknown`} (${n})`}}function vc(e){let t=e,n=t.platform??`unknown`,r=t.device??t.id??`unknown`,i=t.shutdown;return{data:t,text:`${i&&typeof i==`object`&&`success`in i&&i.success===!0?`Shutdown`:`Shutdown failed`}: ${r} (${n})`}}async function yc(e,t){let{formatDoctorCheckDetailLines:n,formatDoctorCheckSummaryLine:r}=await import(`./doctor-output.js`).then(e=>e.t),i=e,a=[`Doctor: ${typeof i.status==`string`?i.status:`unknown`}`],o=wc(i.checks);if(t?.renderedToStderr){let e=typeof i.summary==`string`?i.summary:void 0;e&&a.push(e)}else if(o.length===0){let e=typeof i.summary==`string`?i.summary:`No blockers found.`;a.push(e)}else for(let e of o)a.push(r(e)),a.push(...n(e));return{data:i,text:a.join(`
25
+ `)}}const Z={boot:d(_c),shutdown:d(vc),devices:d(oc),capabilities:d(sc),doctor:({result:e,progress:t})=>yc(e,t),apps:({input:e,result:t})=>cc({result:t,appsFilter:e.appsFilter}),session:d(lc),artifacts:d(pc),open:d(uc),close:d(fc),install:d(hc),reinstall:d(hc),"install-from-source":d(gc),prepare:p,viewport:p};function bc(e){let t=e.kind?` ${e.kind}`:``,n=e.target?` target=${e.target}`:``,r=typeof e.booted==`boolean`?` booted=${e.booted}`:``,i=e.claimedBy?` claimed by session "${e.claimedBy.session}" in ${e.claimedBy.workspace}`:``;return`${e.name} (${e.platform}${t}${n})${r}${i}`}function xc(e){let t=e.url?` ${e.url}`:``,n=e.availability?` ${e.availability}`:``;return`${e.kind}: ${e.name}${n}${t}`}function Sc(e){let t=e.artifactType?` (${e.artifactType})`:``;return`${e.filename}${t}: ${e.mimeType} ${e.sizeBytes} bytes id=${e.id}`}function Cc(e){if(e.providerSessionId)return`agent-device artifacts ${e.providerSessionId} --provider ${e.provider} --json`}function wc(e){return Array.isArray(e)?e.filter(e=>!!e&&typeof e==`object`&&!Array.isArray(e)):[]}const Tc=R({name:`artifacts`,text:{summary:`List daemon or cloud provider session artifacts`},metadata:L(`artifacts`,`List daemon or cloud provider artifacts for an active or completed session.`,{provider:k(`Cloud provider name, for example browserstack or aws-device-farm.`),providerSessionId:k(`Cloud provider session id or ARN.`)}),run:(e,t)=>e.sessions.artifacts(t),cliSchema:{usageOverride:`artifacts [provider-session-id]`,usageFlags:[`provider`],positionalArgs:[`provider-session-id?`],allowedFlags:[`provider`,`providerSessionId`]},cliReader:(e,t)=>({...x(t),provider:t.provider,providerSessionId:e[0]??t.providerSessionId}),daemonWriter:y(u.artifacts),cliOutputFormatter:Z.artifacts});function Ec(e){let{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i}=e;if(t!==void 0||n!==void 0||r!==void 0||i!==void 0)return{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i}}function Dc(e){let{metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i,...a}=e,o=Ec({metroHost:t,metroPort:n,bundleUrl:r,launchUrl:i});return o?{...a,runtime:o}:a}const Oc=L(`apps`,`List the apps installed on the selected device. Include system or OEM apps only when they are needed as automation targets.`,{appsFilter:N([`user-installed`,`all`],`Restrict the listing to user-installed apps, or include system and OEM apps.`)}),kc=L(`open`,`Boot the selected device when needed, then open an app, deep link, or URL in a session. Use the app or URL inputs to choose what becomes the foreground automation target.`,{app:k(`App name, bundle id, package, or URL.`),url:k(`Optional URL passed with an app shell.`),surface:N(st,`macOS presentation surface to open: the app itself, the frontmost app, the desktop, or the menu bar.`),activity:k(`Android activity name.`),launchConsole:k(`Launch console mode.`),launchArgs:Cr(`Launch arguments forwarded verbatim to the platform launch command.`),relaunch:M(`Force relaunch.`),timeoutMs:j(`Startup budget in milliseconds. Bounds the Simulator boot wait, so a never-booted Simulator can finish its first-boot migration; omit for the default startup behavior.`,{min:1}),waitMs:vr(`waitMs`),foreground:vr(`foreground`),saveScript:P({oneOf:[pr(),ur()]}),force:M(`Overwrite an existing --save-script target instead of refusing (alias: --overwrite).`),deviceHub:M(`Use Xcode Device Hub when surfacing Apple simulators.`),testIme:M(`Activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices).`),noRecord:M(`Do not record this action.`),metroHost:k(`Session-scoped Metro/debug host hint applied to the opened app.`),metroPort:j(`Session-scoped Metro/debug port hint applied to the opened app. On an emulator/simulator the host defaults to the loopback alias (Android 10.0.2.2, iOS 127.0.0.1) when --metro-host is omitted; physical devices still require an explicit --metro-host.`,{min:1,max:65535}),bundleUrl:k(`Session-scoped bundle URL hint applied to the opened app.`),launchUrl:k(`Session-scoped launch URL hint applied to the opened app.`)}),Ac=L(`close`,`Close the named app, or close the active session app when app is omitted. Use shutdown only when the selected simulator or emulator should also stop.`,{app:k(`Optional app to close.`),shutdown:M(`Shutdown the session/device where supported.`),saveScript:P({oneOf:[pr(),ur()]}),force:M(`Overwrite an existing --save-script target instead of refusing (alias: --overwrite).`)});function jc(e){return Dc(e)}const Mc={allowedFlags:[`appsFilter`]},Nc={positionalArgs:[`appOrUrl?`,`url?`],allowedFlags:[`activity`,`launchConsole`,`launchArgs`,`deviceHub`,`testIme`,`saveScript`,`force`,`noRecord`,`relaunch`,`foreground`,`timeoutMs`,`waitMs`,`surface`,...Si,`launchUrl`]},Pc={positionalArgs:[`app?`],allowedFlags:[`saveScript`,`force`,`shutdown`]},Fc=(e,t)=>({...x(t),appsFilter:Gt(t.appsFilter)}),Ic=(e,t)=>({...x(t),app:e[0],url:e[1],surface:t.surface,activity:t.activity,launchConsole:t.launchConsole,launchArgs:t.launchArgs,relaunch:t.relaunch,foreground:t.foreground,timeoutMs:t.timeoutMs,waitMs:t.waitMs,saveScript:t.saveScript,force:t.force,deviceHub:t.deviceHub,testIme:t.testIme,noRecord:t.noRecord,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,launchUrl:t.launchUrl}),Lc=(e,t)=>({...x(t),app:e[0],shutdown:t.shutdown,saveScript:t.saveScript,force:t.force}),Rc=y(u.apps),zc=y(u.open,Gc),Bc=y(u.close,e=>w(e.app)),Vc=R({name:`apps`,text:{summary:`List installed apps or deferred provider app assets`,cliDetail:`Before provider allocation, lists uploaded app assets when the selected provider exposes a catalog. On a live device, defaults to user-installed apps; use --all to include system/OEM apps.`},metadata:Oc,run:(e,t)=>e.apps.list(t),cliSchema:Mc,cliReader:Fc,daemonWriter:Rc,cliOutputFormatter:Z.apps}),Hc=R({name:`open`,text:{summary:`Open an app, deep link or URL, save replays`,cliDetail:`Use --platform to bind URL/deep-link opens to the target platform. For iOS simulator initial stdout/stderr, put --launch-console <path> on this open command, for example agent-device open "Agent Device Tester" --platform ios --launch-console artifacts/launch-console.log. Expo Go/dev-client shells accept host + URL, for example agent-device open "Expo Go" exp://127.0.0.1:8081 --platform ios. macOS also supports --surface app|frontmost-app|desktop|menubar. --metro-host/--metro-port/--bundle-url/--launch-url set this session's Metro/debug runtime hints as part of open itself (applied to the app's dev-server prefs and recorded as the session's dev-server binding), so a fresh session has them before its first reload instead of needing a throwaway reload-first call just to seed hints; a later plain metro reload in the same session reuses whichever of these were set. A fresh open without these flags clears any leftover binding from a previous same-name session; close also clears it. A device another session is holding refuses at once; add --wait <ms> to block up to that budget for it and only then fail with DEVICE_IN_USE naming the owning session.`,mcpDetail:`Metro and debug runtime hints given here are recorded as the session's dev-server binding, so a later reload reuses them; a fresh open without them clears any binding left by a previous same-name session.`},metadata:kc,run:(e,t)=>e.apps.open(jc(t)),cliSchema:Nc,cliReader:Ic,daemonWriter:zc,cliOutputFormatter:Z.open}),Uc=R({name:`close`,text:{summary:`Close an app or end the session`},metadata:Ac,run:(e,t)=>t.app?e.apps.close(t):e.sessions.close(Wc(t)),cliSchema:Pc,cliReader:Lc,daemonWriter:Bc,cliOutputFormatter:Z.close});function Wc(e){let{app:t,...n}=e;return n}function Gc(e){return e.app?e.url?[e.app,e.url]:[e.app]:[]}const Kc=L(`devices`,`List available devices and simulators that can be selected for automation. Use platform, device, udid, or serial inputs on later commands to target one result.`,{}),qc=L(`capabilities`,`List the commands supported by the selected device or active session. Use device-selection inputs when checking support before a session is open.`,{}),Jc=L(`boot`,`Boot or prepare the selected device or simulator so later commands can target it. The device is chosen through the device-selection inputs, not by naming it here.`,{headless:M(`Boot without showing simulator UI when supported.`)}),Yc=L(`shutdown`,`Shutdown a selected simulator or emulator.`,{}),Xc={allowedFlags:[`headless`]},Zc={},Qc={},$c={},el=(e,t)=>x(t),tl=(e,t)=>({...x(t),headless:t.headless}),nl=y(u.devices),rl=y(u.capabilities),il=y(u.boot),al=y(u.shutdown),ol=[R({name:`devices`,text:{summary:`List available devices and simulators`},metadata:Kc,run:(e,t)=>e.devices.list(t),cliSchema:Zc,cliReader:el,daemonWriter:nl,cliOutputFormatter:Z.devices}),R({name:`capabilities`,text:{summary:`List supported commands for the selected device`,cliDetail:`Select an explicit target with --platform/--device/--udid/--serial.`},metadata:qc,run:(e,t)=>e.devices.capabilities(t),cliSchema:Qc,cliReader:el,daemonWriter:rl,cliOutputFormatter:Z.capabilities}),R({name:`boot`,text:{summary:`Boot target device/simulator`},metadata:Jc,run:(e,t)=>e.devices.boot(t),cliSchema:Xc,cliReader:tl,daemonWriter:il,cliOutputFormatter:Z.boot}),R({name:`shutdown`,text:{summary:`Shutdown target simulator/emulator`},metadata:Yc,run:(e,t)=>e.devices.shutdown(t),cliSchema:$c,cliReader:el,daemonWriter:al,cliOutputFormatter:Z.shutdown})],sl=R({name:`doctor`,text:{summary:`Diagnose device, app, dev-server, and RN/Expo readiness`,cliDetail:`Metro reachability is inferred from cwd/runtime. On iOS simulators it also warms the XCTest runner build cache in the background when missing. Pass --app to verify a target app on the one matching booted device without opening a session. Use --remote to check remote connection setup without probing local devices. Default output is compact; use --json for full checks and evidence.`,mcpDetail:`On iOS simulators it also warms the XCTest runner build cache in the background when missing, so run it before the first Apple snapshot or interaction of a session.`},metadata:L(`doctor`,`Diagnose device, app, development-server, and React Native or Expo readiness issues. Returns compact evidence for local inventory, sessions, optional app discovery, toolchains, and server reachability.`,{targetApp:k(`Installed app package/bundle id or app name to verify without opening a session.`),remote:M(`Check remote connection setup instead of local device inventory.`)}),run:(e,t)=>e.command.doctor(t),cliSchema:{usageOverride:`doctor [--platform ios|android|harmonyos|vega|macos|linux|web|apple]`,allowedFlags:[`targetApp`,`remote`]},cliReader:(e,t)=>({...x(t),targetApp:t.targetApp,remote:t.remote}),daemonWriter:y(u.doctor),cliOutputFormatter:Z.doctor});function cl(t,n=`--github-actions-artifact`){let r=t.indexOf(`:`);if(r<=0||r===t.length-1)throw new e(`INVALID_ARGS`,`${n} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:i,repo:a}=dl(t.slice(0,r),n);return ul(i,a,t.slice(r+1),`${n} artifact`)}function ll(t,n){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`${n} installSource must be an object.`);let r=t;if(pl(r.type,`${n} installSource.type`)!==`github-actions-artifact`)throw new e(`INVALID_ARGS`,`${n} installSource.type must be "github-actions-artifact".`);let{owner:i,repo:a}=dl(pl(r.repo,`${n} installSource.repo`),`${n} installSource.repo`);return ul(i,a,r.artifact,`${n} installSource.artifact`)}function ul(e,t,n,r){return typeof n==`number`||hl(n)?{kind:`github-actions-artifact`,owner:e,repo:t,artifactId:ml(n,r)}:{kind:`github-actions-artifact`,owner:e,repo:t,artifactName:pl(n,r)}}function dl(t,n){let r=t.indexOf(`/`);if(r<=0||r===t.length-1||t.indexOf(`/`,r+1)!==-1)throw new e(`INVALID_ARGS`,`${n} must use owner/repo.`);let i={owner:t.slice(0,r).trim(),repo:t.slice(r+1).trim()};if(!i.owner||!i.repo)throw new e(`INVALID_ARGS`,`${n} must use owner/repo.`);return i}function fl(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}function pl(t,n){let r=fl(t);if(!r)throw new e(`INVALID_ARGS`,`${n} must be a non-empty string.`);return r}function ml(t,n){let r=typeof t==`number`?t:typeof t==`string`?Number(t):NaN;if(!Number.isInteger(r))throw new e(`INVALID_ARGS`,`${n} must be an integer.`);return r}function hl(e){return typeof e==`string`&&/^\d+$/.test(e.trim())}const gl=L(`install`,`Install an app binary from a local path. Provide an app identifier with the path when the target needs explicit app selection; use reinstall to replace an already installed app.`,{app:k(`Optional app identifier hint.`),appPath:O(k(`Path to app binary.`))}),_l=L(`reinstall`,`Replace an installed app with a binary from a local path. Use this when preserving the same app identity while installing a new build on the selected device.`,{app:O(k()),appPath:O(k(`Path to app binary.`))}),vl=L(`install-from-source`,`Install app builds from URLs, remote source specs, or CI artifacts resolved by a remote daemon.`,{source:O(P(hr(`Install source object.`))),retainPaths:M(),retentionMs:j()}),yl={usageOverride:`install <path> | install <app> <path>`,listUsageOverride:`install <path>`,positionalArgs:[`appOrPath`,`path?`]},bl={positionalArgs:[`app`,`path`]},xl={usageOverride:`install-from-source <url> | install-from-source --github-actions-artifact <owner/repo:artifact>`,usageFlags:[],listUsageOverride:`install-from-source`,positionalArgs:[`url?`],allowedFlags:[`header`,`githubActionsArtifact`,`installSource`,`retainPaths`,`retentionMs`]},Sl=(e,t)=>Ol(e,t),Cl=(e,t)=>kl(e,t),wl=(e,t)=>({...x(t),source:Ml(e,t),retainPaths:t.retainPaths,retentionMs:t.retentionMs}),Tl=y(u.install,e=>Al(e.app,e.appPath)),El=y(u.reinstall,e=>jl(e.app,e.appPath)),Dl=[R({name:`install`,text:{summary:`Install an app binary from a path`},metadata:gl,run:(e,t)=>e.apps.install(t),cliSchema:yl,cliReader:Sl,daemonWriter:Tl,cliOutputFormatter:Z.install}),R({name:`reinstall`,text:{summary:`Replace an installed app with a new build`},metadata:_l,run:(e,t)=>e.apps.reinstall(t),cliSchema:bl,cliReader:Cl,daemonWriter:El,cliOutputFormatter:Z.reinstall}),R({name:`install-from-source`,text:{summary:`Install app builds from URLs or CI artifacts`},metadata:vl,run:(e,t)=>e.apps.installFromSource(t),cliSchema:xl,cliReader:wl,daemonWriter:e=>b(at.installSource,[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),cliOutputFormatter:Z[`install-from-source`]})];function Ol(e,t){let[n,r]=e,i=r!==void 0;return{...x(t),...i?{app:E(n,`install requires app`)}:{},appPath:E(i?r:n,`install requires path`)}}function kl(e,t){return{...x(t),app:E(e[0],`reinstall requires app`),appPath:E(e[1],`reinstall requires path`)}}function Al(e,t){let n=D(t,`missing app path`);return typeof e==`string`&&e.length>0?[e,n]:[n]}function jl(e,t){return[D(e,`missing first positional`),D(t,`missing second positional`)]}function Ml(t,n){let r=t[0]?.trim();if(t.length>1)throw new e(`INVALID_ARGS`,`install-from-source accepts either one <url> positional or --github-actions-artifact`);let i=n.githubActionsArtifact?cl(n.githubActionsArtifact):void 0,a=n.installSource;if(+!!r+ +!!i+ +!!a!=1)throw new e(`INVALID_ARGS`,`install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource`);if(!r&&n.header&&n.header.length>0)throw new e(`INVALID_ARGS`,`install-from-source --header is only supported for URL sources`);return i||a||{kind:`url`,url:r,headers:Nl(n.header)}}function Nl(t){if(!t||t.length===0)return;let n={};for(let r of t){let t=r.indexOf(`:`);if(t<=0)throw new e(`INVALID_ARGS`,`Invalid --header value "${r}". Expected "name:value".`);let i=r.slice(0,t).trim(),a=r.slice(t+1).trim();if(!i)throw new e(`INVALID_ARGS`,`Invalid --header value "${r}". Header name cannot be empty.`);n[i]=a}return n}const Pl=R({name:`prepare`,text:{summary:`Pre-warm platform helpers before automation`},metadata:L(`prepare`,`Prepare platform helper infrastructure. ios-runner builds/reuses, starts, and health-checks the XCTest runner so later Apple snapshots and interactions do not pay first-use startup cost. In JSON output, top-level buildMs/connectMs/healthCheckMs are diagnostic fields and may overlap; use timing.additiveParts for additive wall-clock phase totals. In CI, run it after boot/install and before replay/test; if replay/test starts a separate daemon, stop the prepare daemon before replay/test so it does not keep the prepared runner lease. It is not a recovery step for "runner already owned by another agent-device daemon"; stop the owning daemon on the Mac with simulator access instead. Runner build/start output is written to the session runner.log; daemon.log is for daemon lifecycle/startup issues.`,{action:O(N([`ios-runner`])),timeoutMs:j(`Maximum wall-clock time for the prepare command.`)}),run:(e,t)=>e.command.prepare(t),cliSchema:{usageOverride:`prepare ios-runner --platform ios|macos`,listUsageOverride:`prepare`,positionalArgs:[`ios-runner`],allowedFlags:[`timeoutMs`]},cliReader:(e,t)=>({...x(t),action:E(e[0],`prepare requires subcommand`),timeoutMs:t.timeoutMs}),daemonWriter:y(u.prepare,e=>[D(e.action,`prepare requires subcommand`)]),cliOutputFormatter:Z.prepare}),Fl=L(`push`,`Deliver push notification payloads to an installed app.`,{app:O(k()),payload:O(P({oneOf:[ur(),hr()]}))}),Il=L(`trigger-app-event`,`Ask the app to handle an app-defined automation or test event, with an optional structured payload. Call this only for event names and payload shapes the app documents.`,{event:O(k(`Name of an app-defined automation or test event the app documents.`)),payload:Kl(`Structured payload passed to the event, in the shape the app documents for it.`)}),Ll={listUsageOverride:`push`,positionalArgs:[`bundleOrPackage`,`payloadOrJson`]},Rl={usageOverride:`trigger-app-event <event> [payloadJson]`,listUsageOverride:`trigger-app-event`,positionalArgs:[`event`,`payloadJson?`]},zl=(e,t)=>({...x(t),app:E(e[0],`push requires bundleOrPackage`),payload:E(e[1],`push requires payloadOrJson`)}),Bl=(e,t)=>({...x(t),event:E(e[0],`trigger-app-event requires event`),payload:e[1]?Xn(e[1],`trigger-app-event payload`):void 0}),Vl=y(u.push,e=>Wl(e)),Hl=y(u.triggerAppEvent,e=>Gl(e)),Ul=[R({name:`push`,text:{summary:`Deliver a push notification payload`},metadata:Fl,run:(e,t)=>e.apps.push(t),cliSchema:Ll,cliReader:zl,daemonWriter:Vl}),R({name:`trigger-app-event`,text:{summary:`Invoke an app-defined automation event`},metadata:Il,run:(e,t)=>e.apps.triggerEvent(t),cliSchema:Rl,cliReader:Bl,daemonWriter:Hl})];function Wl(e){return[e.app,typeof e.payload==`string`?e.payload:JSON.stringify(e.payload)]}function Gl(e){return[e.event,...e.payload?[JSON.stringify(e.payload)]:[]]}function Kl(e){return Sr(e)}const ql=R({name:`session`,text:{summary:`List sessions, show the state dir, or publish a script`},metadata:L(`session`,`List active sessions, print the effective daemon state directory, or publish an armed open-to-destination script without closing its session`,{action:N([`list`,`state-dir`,`save-script`],`list shows active sessions; state-dir prints the daemon state directory; save-script publishes an armed recording without teardown.`),path:k(`Optional .ad output path for save-script.`),force:M(`Atomically replace an existing save-script target.`)}),run:async(e,{action:t,path:n,force:r,...i})=>{let a=t??`list`;return Yl(a,n,r),a===`state-dir`?{stateDir:await e.sessions.stateDir(i)}:a===`save-script`?await e.sessions.saveScript({...i,path:n,force:r}):{sessions:await e.sessions.list(i)}},cliSchema:{usageOverride:`session list | session state-dir | session save-script [path] [--force]`,usageFlags:[],listUsageOverride:`session`,positionalArgs:[`list|state-dir|save-script?`,`path?`],allowedFlags:[`force`]},cliReader:(e,t)=>({...x(t),action:Jl(e[0]),path:e[1],force:t.force}),cliOutputFormatter:Z.session});function Jl(t){let n=t??`list`;if(n===`list`||n===`state-dir`||n===`save-script`)return n;throw new e(`INVALID_ARGS`,`session only supports list, state-dir, or save-script`)}function Yl(t,n,r){if(t!==`save-script`&&(n!==void 0||r===!0))throw new e(`INVALID_ARGS`,`session ${t} does not accept a path or --force; use session save-script [path] [--force] to publish a recording.`)}const Xl=R({name:`viewport`,text:{summary:`Resize the active web viewport for the current session`},metadata:L(`viewport`,`Resize the active web viewport before taking snapshots or screenshots. Useful for fixed-layout or 100vh apps where changing the viewport reveals different content.`,{width:O(j(`Viewport width in CSS pixels.`,{min:1})),height:O(j(`Viewport height in CSS pixels.`,{min:1}))}),run:(e,t)=>e.command.viewport(t),cliSchema:{positionalArgs:[`width`,`height`]},cliReader:(e,t)=>({...x(t),...he(e)}),daemonWriter:y(u.viewport,e=>{let{width:t,height:n}=e;return[String(t),String(n)]}),cliOutputFormatter:Z.viewport}),Zl=z({name:`management`,commands:[...ol,Tc,sl,Pl,Vc,ql,Hc,Uc,Xl,...Dl,...Ul]});function Ql(e){return{data:e.result,text:e.action===`reload`?`Reloaded React Native apps via ${e.result.reloadUrl}`:JSON.stringify(e.result,null,2)}}const $l={metro:({input:e,result:t})=>Ql({result:t,action:e.action})},eu=`metro`,tu=z({name:`metro`,commands:[R({name:eu,text:{summary:`Prepare the dev server or reload apps`,cliDetail:`reload with no --metro-host/--metro-port/--bundle-url resolves against the dev server this session last bound via metro prepare or open's metro hint flags (falling back to localhost:8081 only when the session never bound one), so it never silently reloads a different project's server on the default port; pass an explicit flag to override the session hint for one call. The reload URL keeps the bound bundle URL mount prefix instead of collapsing to the host root, and when the server has no HTTP /reload route (Expo) the reload is broadcast over its /message websocket instead of trusting the app-page fallback. The binding is cleared when the session closes, and a fresh open without hint flags also clears any leftover binding from a previous same-name session. --kind expo (detected or forced) requests the virtual-entry bundle URL (.expo/.virtual-metro-entry.bundle) instead of index.bundle, since index.bundle 404s/500s against Expo dev servers in monorepos. Dependency install auto-detects the package manager from the nearest yarn.lock/pnpm-lock.yaml/bun.lock/bun.lockb/package-lock.json walking up from --project-root (bounded at the repo root), so Yarn/pnpm workspace monorepos with the lockfile at the repo root do not wrongly fall back to npm install (which fails on workspace: dependency specifiers); if install still fails, pass --no-install-deps when dependencies are already installed (for example via a monorepo root install).`,mcpDetail:`The binding is cleared when the session closes, and a fresh open without runtime hints also clears any leftover binding from a previous same-name session.`},metadata:L(eu,`Prepare a React Native development server or ask connected apps to reload, using the development server this session is bound to. Provide explicit runtime inputs only to override that binding for one call.`,{action:O(N([`prepare`,`reload`])),projectRoot:k(),kind:P(ur()),publicBaseUrl:k(),proxyBaseUrl:_r(k(),{operatorPath:`Configure the remote proxy in the remote-config profile or operator config for the process serving these tools.`}),bearerToken:_r(k(),{envFlagKeys:[`metroBearerToken`,`daemonAuthToken`]}),bridgeScope:P({type:`object`,additionalProperties:!0}),launchUrl:k(),port:j(),listenHost:k(),statusHost:k(),startupTimeoutMs:j(),probeTimeoutMs:j(),reuseExisting:M(),installDependenciesIfNeeded:M(),runtimeFilePath:k(),logPath:k(),metroHost:k(),metroPort:j(),bundleUrl:k(),timeoutMs:j()}),run:async(e,t)=>t.action===`prepare`?await e.metro.prepare(nu(t)):await e.metro.reload(iu(t)),cliSchema:{usageOverride:`metro prepare (--public-base-url <url> | --proxy-base-url <url>) [--project-root <path>] [--port <port>] [--kind auto|react-native|expo|repack]
26
+ agent-device metro reload [--metro-host <host>] [--metro-port <port>] [--bundle-url <url>]`,usageFlags:[],listUsageOverride:`metro`,positionalArgs:[`prepare|reload`],allowedFlags:[...Si,...xi]},cliReader:(t,n)=>{let r=(t[0]??``).toLowerCase();if(r!==`prepare`&&r!==`reload`)throw new e(`INVALID_ARGS`,`metro requires a subcommand: prepare or reload`);if(r===`reload`)return{action:r,metroHost:n.metroHost,metroPort:n.metroPort,bundleUrl:n.bundleUrl,timeoutMs:n.metroProbeTimeoutMs};if(!n.metroPublicBaseUrl&&!n.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`);return{action:r,projectRoot:n.metroProjectRoot,kind:Zt(n.kind??n.metroKind),port:n.metroPreparePort,listenHost:n.metroListenHost,statusHost:n.metroStatusHost,publicBaseUrl:n.metroPublicBaseUrl,proxyBaseUrl:n.metroProxyBaseUrl,bearerToken:n.metroBearerToken,bridgeScope:n.tenant&&n.runId&&n.leaseId?{tenantId:n.tenant,runId:n.runId,leaseId:n.leaseId}:void 0,startupTimeoutMs:n.metroStartupTimeoutMs,probeTimeoutMs:n.metroProbeTimeoutMs,reuseExisting:!n.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!n.metroNoInstallDeps&&void 0,runtimeFilePath:n.metroRuntimeFile}},cliOutputFormatter:$l.metro})]});function nu(e){return{projectRoot:e.projectRoot,kind:e.kind,publicBaseUrl:e.publicBaseUrl,proxyBaseUrl:e.proxyBaseUrl,bearerToken:e.bearerToken,bridgeScope:e.bridgeScope??ru(e),port:e.port,listenHost:e.listenHost,statusHost:e.statusHost,startupTimeoutMs:e.startupTimeoutMs,probeTimeoutMs:e.probeTimeoutMs,reuseExisting:e.reuseExisting,installDependenciesIfNeeded:e.installDependenciesIfNeeded,runtimeFilePath:e.runtimeFilePath}}function ru(e){return e.tenant&&e.runId&&e.leaseId?{tenantId:e.tenant,runId:e.runId,leaseId:e.leaseId}:void 0}function iu(e){return{metroHost:e.metroHost,metroPort:e.metroPort,bundleUrl:e.bundleUrl,timeoutMs:e.timeoutMs}}function au(e,t){return e.includes(t)}function ou(t,n,r={}){let i=n===void 0?void 0:r.normalize?.(n)??n;if(i!==void 0&&au(t,i))return i;let a=typeof r.message==`function`?r.message(n):r.message;throw new e(`INVALID_ARGS`,a??`Invalid value: ${n}. Use ${t.join(`|`)}.`)}const su=[`started`,`stopped`,`marked`,`cleared`,`restarted`,`removedRotatedFiles`];function cu(e){return{data:e,text:e.path,stderr:Iu([Pu(e,[`active`,`state`,`backend`,`sizeBytes`]),Eu(e),e.hint,Fu(e.notes)])}}function lu(e){let t=e.events??[];return{data:e,text:t.length>0?pu(t):`No session events found.`,stderr:Iu([Pu(e,[`path`,`cursor`,`nextCursor`,`limit`])])}}function uu(e){let t=[],n=e.entries??[];if(e.path&&t.push(e.path),n.length===0)t.push(`No recent HTTP(s) entries found.`);else for(let e of n)t.push(...ju(e));return{data:e,text:t.join(`
27
+ `),stderr:Iu([Pu(e,[`active`,`state`,`backend`,`include`,`scannedLines`,`matchedLines`]),Fu(e.notes)])}}function du(e){return{data:e,text:[`Audio probe: ${String(e.state??`stopped`)} heard=${String(e.heard===!0)}`,Tu(`rmsDbfs`,e.rmsDbfs),Tu(`peakDbfs`,e.peakDbfs)].filter(e=>!!e).join(`
28
+ `),stderr:Iu([Pu(e,[`active`,`backend`,`source`,`durationMs`,`elapsedMs`,`bucketMs`,`sampleCount`,`sourceCount`,`mediaElementCount`]),Fu(e.notes)])}}const fu={logs:d(cu),events:d(lu),network:d(uu),audio:d(du)};function pu(e){let t=e.map(mu),n=Math.min(Math.max(...t.map(e=>e.label.length),5),32);return t.map(e=>hu(e,n)).join(`
29
+ `)}function mu(e){return{timestamp:gu(e.ts),label:_u(e),summary:vu(e)}}function hu(e,t){let n=e.label.padEnd(t),r=e.timestamp?`${e.timestamp} ${n}`:n.trimEnd();return e.summary?`${r} ${e.summary}`:r.trimEnd()}function gu(e){return e?e.replace(`T`,` `):``}function _u(e){let t=e.command??`command`;switch(e.kind){case`request.started`:return`start ${t}`;case`request.finished`:return Ou([e.status===`error`?`error`:`ok`,t,wu(Au(e.details?.durationMs))]);case`action.recorded`:return`action ${t}`;default:return Ou([e.kind??`event`,e.command])}}function vu(e){let t=yu(e.summary,e);return`${t}${bu(e,t)}`.trim()}function yu(e,t){let n=e?.trim()??``,r=t.command??``;return t.kind===`request.started`&&n===`Started ${r}`||t.kind===`request.finished`&&n===`Finished ${r}`?``:n}function bu(e,t){if(e.kind!==`action.recorded`)return``;let n=e.details;if(!n)return``;let r=[xu(n,t),Cu(Au(n.textLength))].filter(e=>!!e);return r.length>0?` (${r.join(`, `)})`:``}function xu(e,t){let n=ku(e.ref)??ku(e.selector)??Su(e);if(!(!n||t.includes(n)))return`target=${n}`}function Su(e){let t=Au(e.x),n=Au(e.y);return t===void 0||n===void 0?void 0:`(${t}, ${n})`}function Cu(e){return e===void 0?void 0:`text=${e} chars`}function wu(e){return e===void 0?void 0:`${Math.round(e)}ms`}function Tu(e,t){if(!Array.isArray(t))return;let n=t.filter(e=>typeof e==`number`&&Number.isFinite(e));return n.length>0?`${e}: [${n.join(`, `)}]`:void 0}function Eu(e){return su.map(t=>Du(t,e[t])).filter(Boolean).join(` `)||void 0}function Du(e,t){return t==null?``:`${e}=${t}`}function Ou(e){return e.filter(e=>!!e).join(` `)}function ku(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function Au(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function ju(e){let t=e.method??`HTTP`,n=e.url??`<unknown-url>`,r=e.status===void 0?``:` status=${e.status}`,i=e.timestamp?`${e.timestamp} `:``,a=e.durationMs===void 0?``:` durationMs=${e.durationMs}`,o=[`${i}${t} ${n}${`pathUnavailable`in e&&e.pathUnavailable?` (request path not logged)`:``}${r}${a}`];return e.headers?Nu(o,`headers`,e.headers):(Mu(o,`request headers`,e.requestHeaders),Mu(o,`response headers`,e.responseHeaders)),Nu(o,`request`,e.requestBody),Nu(o,`response`,e.responseBody),o}function Mu(e,t,n){!n||Object.keys(n).length===0||e.push(` ${t}: ${JSON.stringify(n)}`)}function Nu(e,t,n){n!==void 0&&e.push(` ${t}: ${n}`)}function Pu(e,t){return t.map(t=>e[t]!==void 0&&e[t]!==null?`${t}=${e[t]}`:``).filter(Boolean).join(` `)||void 0}function Fu(e){let t=e?.filter(e=>e.length>0)??[];return t.length>0?t.join(`
30
+ `):void 0}function Iu(e){return e.filter(e=>!!e).join(`
31
+ `)||void 0}const Lu=`logs`,Ru=`events`,zu=`network`,Bu=`audio`,Vu=[`dump`,`log`],Hu=[`probe`],Uu=[`start`,`status`,`stop`],Wu=L(Lu,`Session app log info, start/stop streaming, diagnostics, and markers`,{action:N(an),message:k(),restart:M()}),Gu=L(Ru,`Read the daemon-owned session event timeline as paged JSON-friendly entries`,{limit:j(),cursor:k()}),Ku=L(zu,`Dump recent HTTP(s) traffic parsed from the session app log`,{action:N(Vu),limit:j(),include:N(i)}),qu=L(Bu,`Measure browser or host-rendered simulator/emulator audio as compact dBFS buckets. Start a probe before requesting its status or stopping it.`,{action:N(Hu),probeAction:N(Uu),durationMs:j(`Probe duration in milliseconds.`),bucketMs:j(`Audio level bucket size in milliseconds.`)}),Ju=z({name:`observability`,commands:[R({name:Lu,text:{summary:`Manage session app logs`},metadata:Wu,run:(e,t)=>e.observability.logs(t),cliSchema:{usageOverride:`logs path | logs start | logs stop | logs clear [--restart] | logs doctor | logs mark [message...]`,usageFlags:[],positionalArgs:[`path|start|stop|clear|doctor|mark`,`message?`],allowsExtraPositionals:!0,allowedFlags:[`restart`]},cliReader:(e,t)=>({...x(t),action:$u(e[0]),message:e.slice(1).join(` `)||void 0,restart:t.restart}),daemonWriter:y(Lu,e=>Yu(e)),cliOutputFormatter:fu.logs}),R({name:Ru,text:{summary:`Read session event timeline`},metadata:Gu,run:(e,t)=>e.observability.events(t),cliSchema:{usageOverride:`events [limit] [cursor]`,listUsageOverride:`events`,positionalArgs:[`limit?`,`cursor?`]},cliReader:(e,t)=>({...x(t),limit:e[0]?.trim()?er(e[0]):void 0,cursor:e[1]}),daemonWriter:e=>b(Ru,Xu(e),e),cliOutputFormatter:fu.events}),R({name:zu,text:{summary:`Inspect HTTP(S) traffic from session logs`},metadata:Ku,run:(e,t)=>e.observability.network(t),cliSchema:{usageOverride:`network dump [limit] [summary|headers|body|all] [--include summary|headers|body|all] | network log [limit] [summary|headers|body|all] [--include summary|headers|body|all]`,usageFlags:[],listUsageOverride:`network`,positionalArgs:[`dump|log`,`limit?`,`include?`],allowedFlags:[`networkInclude`]},cliReader:(e,t)=>({...x(t),action:ed(e[0]),limit:er(e[1]),include:t.networkInclude??td(e[2])}),daemonWriter:e=>b(zu,Zu(e),{...e,networkInclude:e.include}),cliOutputFormatter:fu.network}),R({name:Bu,text:{summary:`Probe audio levels`},metadata:qu,run:(e,t)=>e.observability.audio(t),cliSchema:{usageOverride:`audio probe start [durationSeconds] [bucketMs] | audio probe status | audio probe stop`,listUsageOverride:`audio`,positionalArgs:[`probe`,`start|status|stop`,`durationSeconds?`,`bucketMs?`]},cliReader:(e,t)=>({...x(t),action:nd(e[0]),probeAction:rd(e[1]),durationMs:id(e[2]),bucketMs:er(e[3])}),daemonWriter:e=>b(Bu,Qu(e),e),cliOutputFormatter:fu.audio})]});function Yu(e){return[e.action??`path`,...w(e.message)]}function Xu(e){return e.cursor===void 0?T(e.limit):[e.limit===void 0?``:String(e.limit),e.cursor]}function Zu(e){return[...e.action?[e.action]:[],...T(e.limit)]}function Qu(e){return[e.action??`probe`,e.probeAction??`status`,...T(e.durationMs),...T(e.bucketMs)]}function $u(e){if(e!==void 0)return ou(an,e,{message:`logs requires path, start, stop, doctor, mark, or clear`})}function ed(t){if(t!==void 0){if(t===`dump`||t===`log`)return t;throw new e(`INVALID_ARGS`,`network requires dump or log`)}}function td(e){if(e!==void 0)return ou(i,e,{message:`network include must be summary, headers, body, or all`})}function nd(e){if(e!==void 0)return ou(Hu,e,{message:`audio requires probe`})}function rd(e){if(e!==void 0)return ou(Uu,e,{message:`audio probe requires start, status, or stop`})}function id(e){let t=er(e);return t===void 0?void 0:Math.round(t*1e3)}function ad(e){let t=e;return{data:t,text:sd(t)}}const od={perf:d(ad)};function sd(e){return md(e)??cd(e)}function cd(e){let t=l(e.artifact)?e.artifact:void 0;return t?pd(t):ld(l(e.metrics)?e.metrics:void 0)}function ld(e){return l(e?.fps)?dd(e):ud(e)??`Memory: unavailable - missing memory metric`}function ud(e){let t=l(e?.memory)?e.memory:void 0;if(!t)return;if(t.available===!1)return`Memory: unavailable - ${Ed(t)}`;let n=Md(t);return n?`Performance: ${n}`:`Memory: unavailable - missing memory metric`}function dd(e){let t=l(e?.fps)?e.fps:void 0;if(!t)return Td(`missing frame metric`);if(t.available===!1)return Td(Ed(t));let n=Dd(t);return n?fd(t,n):Td(`missing dropped-frame summary`)}function fd(e,t){let n=[`Frame health: ${t}`],r=Ad(e);return r.length>0&&n.push(`Worst windows:`,...r),n.join(`
32
+ `)}function pd(e){let t=typeof e.kind==`string`?e.kind:`memory`;if(e.available===!1)return`Memory artifact (${t}): unavailable - ${typeof e.reason==`string`&&e.reason.length>0?e.reason:`not available`}`;let n=typeof e.path==`string`?e.path:void 0,r=Q(e.sizeBytes),i=r===void 0?``:` (${Id(r)})`;return n?`Memory artifact (${t}): ${n}${i}`:`Memory artifact (${t}): captured${i}`}function md(e){return e.kind===`xctrace`?hd(e):yd(e)}function hd(e){let t=typeof e.perf==`string`?e.perf:void 0,n=_d(e);if(!t||!n||e.kind!==`xctrace`)return;let r=vd(n,typeof e.mode==`string`?e.mode:`capture`,t,e.template),i=gd(e);return i.length>0?`${r}\nTop CPU self time:\n${i.join(`
33
+ `)}`:r}function gd(e){let t=l(e.summary)?e.summary:void 0;return Array.isArray(t?.topFunctions)?t.topFunctions.slice(0,5).flatMap(e=>{if(!l(e))return[];let t=Cd(e.symbol),n=Q(e.selfSamplePercent);if(!t||n===void 0)return[];let r=Cd(e.binary);return[`- ${Nd(n)} ${t}${r?` (${r})`:``}`]}):[]}function _d(e){return typeof e.outPath==`string`?e.outPath:typeof e.reportPath==`string`?e.reportPath:void 0}function vd(e,t,n,r){let i=[e,`Perf ${t}: ${n}`];return typeof r==`string`&&i.push(`Template: ${r}`),i.join(`
34
+ `)}function yd(e){let t=bd(e);if(!t)return;let n=`Perf ${t.action}: ${t.kind} ${t.type}${xd(e)}${Sd(e)}${wd(e)}`,r=gd(e);return r.length>0?`${n}\nTop CPU self time:\n${r.join(`
35
+ `)}`:n}function bd(e){let t=Cd(e.action),n=Cd(e.kind),r=Cd(e.type);return t&&n&&r?{action:t,kind:n,type:r}:void 0}function xd(e){let t=Cd(e.state);return t?` state=${t}`:``}function Sd(e){let t=Cd(e.outPath);if(!t)return``;let n=Q(e.sizeBytes);return`\n${t}${n===void 0?``:` (${Id(n)})`}`}function Cd(e){return typeof e==`string`?e:void 0}function wd(e){let t=l(e.summary)?e.summary:void 0,n=l(t?.frameHealth)?t.frameHealth:void 0;if(!n||n.available!==!0)return``;let r=Q(n.droppedFramePercent),i=Q(n.droppedFrameCount),a=Q(n.totalFrameCount);return r===void 0||i===void 0||a===void 0?``:`\nTrace frame health: dropped ${Nd(r)} (${Math.round(i)}/${Math.round(a)} frames)`}function Td(e){return`Frame health: unavailable - ${e}`}function Ed(e){return typeof e.reason==`string`&&e.reason.length>0?e.reason:`not available`}function Dd(e){let t=Q(e.droppedFramePercent),n=Q(e.droppedFrameCount);if(t!==void 0&&n!==void 0)return[`dropped ${Nd(t)}`,Od(n,Q(e.totalFrameCount)),kd(Q(e.sampleWindowMs))].filter(Boolean).join(` `)}function Od(e,t){return t===void 0?`(${Math.round(e)} dropped frames)`:`(${Math.round(e)}/${Math.round(t)} frames)`}function kd(e){return e===void 0?``:`window ${Pd(e)}`}function Ad(e){return Array.isArray(e.worstWindows)?e.worstWindows.flatMap(e=>{if(!l(e))return[];let t=jd(e);return t?[t]:[]}):[]}function jd(e){let t=Q(e.startOffsetMs),n=Q(e.endOffsetMs),r=Q(e.missedDeadlineFrameCount);if(t===void 0||n===void 0||r===void 0)return;let i=Q(e.worstFrameMs),a=i===void 0?``:`, worst ${Pd(i)}`;return`- +${Pd(t)}-+${Pd(n)}: ${Math.round(r)} missed-deadline frames${a}`}function Md(e){if(e?.available!==!0)return;let t=Q(e.residentMemoryKb)??Q(e.totalPssKb)??Q(e.totalRssKb);return t===void 0?void 0:`memory ${Fd(t)}`}function Q(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function Nd(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function Pd(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 Fd(e){let t=e/1024;return`${t>=10?Math.round(t):t.toFixed(1)}MB`}function Id(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`}const Ld=`perf`,Rd=z({name:`perf`,commands:[R({name:Ld,text:{summary:`Check frames, memory, or native profiles`,cliDetail:`Use perf frames for bounded frame-health evidence and perf memory sample for a compact process-memory reading. On iOS simulators and macOS, process sampling and captures target the resolved app executable and exclude other copies with the same name. Apple xctrace and Android Simpleperf/Perfetto captures keep raw artifacts on disk; report produces bounded agent-readable evidence. For React render internals, use agent-device react-devtools.`,mcpDetail:`For CPU profiles, start and stop write the raw artifact while report writes a compact summary; request the report when the task needs readable native CPU evidence. Profiling output is evidence only: compact state, artifact path, and size.`},metadata:L(Ld,`Collect frame health, memory diagnostics, and platform profiling artifacts with compact agent-readable summaries.`,{area:O(N(_t)),subject:N(xt),action:N(gt),kind:N(lt),template:k(`xctrace template name, for example Time Profiler.`),out:k(`Output artifact path.`),tracePath:k(`Existing .trace path to report, defaults to the latest session trace.`)}),run:(e,t)=>e.observability.perf(t),cliSchema:{usageOverride:`perf frames --json
36
36
  agent-device perf memory sample --json
37
37
  agent-device perf memory snapshot [--kind android-hprof|memgraph] [--out <path>]
38
38
  agent-device perf cpu profile start --kind xctrace [--template <name>] --out <profile.trace>
@@ -44,9 +44,9 @@ import{C as e,S as t,_ as n,h as r,t as i,u as a,v as o}from"./sdk-contracts.js"
44
44
  agent-device perf cpu profile report --kind simpleperf --out <cpu-report.json>
45
45
  agent-device perf trace start|stop --kind perfetto [--out <path>]
46
46
 
47
- Aggregate perf was removed in 0.21. Use one of the explicit forms above.`,usageFlags:[],listUsageOverride:`perf`,positionalArgs:[`area`,`subjectOrAction?`,`action?`],allowedFlags:[`kind`,`perfTemplate`,`out`]},cliReader:(e,t)=>({...b(t),...zd(e,{kind:Gd(t.kind),template:t.perfTemplate,out:t.out})}),daemonWriter:v(Fd,e=>Ld(e)),cliOutputFormatter:ad.perf})]});function Ld(e){let t=e.area;return t===`cpu`?Rd([...C(t),...C(e.subject),...C(e.action),...C(e.kind)],e):t===`trace`?Rd([...C(t),...C(e.action),...C(e.kind)],e):[...C(t),...C(e.action)]}function Rd(e,t){let n=[...e];return(t.template||t.out||t.tracePath)&&n.push(t.template??``),(t.out||t.tracePath)&&n.push(t.out??``),t.tracePath&&n.push(t.tracePath),n}function zd(e,t={}){let n=Vd(e[0]);if(n===`cpu`)return{area:n,subject:Ud(e[1]),action:Hd(e[2]),kind:Wd(t.kind),template:t.template,out:t.out};if(n===`trace`)return{area:n,action:Hd(e[1]),kind:Wd(t.kind),template:t.template,out:t.out};let r=Hd(e[1]),i=Wd(t.kind);return Bd(n,r,i,t.out),{area:n,action:r,kind:i,out:t.out}}function Bd(t,n,r,i){if(t===`frames`){if(r!==void 0)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(i!==void 0)throw new e(`INVALID_ARGS`,`--out is only supported with perf memory snapshot, perf cpu profile, or perf trace`)}if(t===`memory`){if(n!==`snapshot`&&r!==void 0)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(n!==`snapshot`&&i!==void 0)throw new e(`INVALID_ARGS`,`--out is only supported with perf memory snapshot`)}}function Vd(t){let n=t?.toLowerCase();if(dt(n))throw new e(`INVALID_ARGS`,pt);if(ut(n))return n;throw new e(`INVALID_ARGS`,st)}function Hd(t){if(t===void 0)return;let n=t.toLowerCase();if(lt(n))return n;throw new e(`INVALID_ARGS`,yt)}function Ud(t){let n=t?.toLowerCase();if(n!==void 0&&ft(n))return n;throw new e(`INVALID_ARGS`,mt)}function Wd(t){if(t===void 0)return;let n=t.toLowerCase();if(_t(n))return n;throw new e(`INVALID_ARGS`,vt)}function Gd(e){return typeof e==`string`?Wd(e):void 0}const Kd=`react-native`,qd=O({name:`react-native`,commands:[D({name:Kd,text:{summary:`Run React Native automation helpers`},metadata:R(Kd,`Run supported React Native automation helpers. Use dismiss-overlay to close a visible development error overlay before continuing normal UI automation.`,{action:A(F([`dismiss-overlay`]))}),run:(e,t)=>e.command.reactNative(t),cliSchema:{usageOverride:`react-native dismiss-overlay`,listUsageOverride:`react-native dismiss-overlay`,positionalArgs:[`dismiss-overlay`]},cliReader:(e,t)=>({...b(t),action:Jd(e[0])}),daemonWriter:v(Kd,e=>[E(e.action,`react-native requires action`)])})]});function Jd(t){if(t===`dismiss-overlay`)return t;throw new e(`INVALID_ARGS`,`react-native supports only: dismiss-overlay`)}function Yd(e){let t=e,n=typeof t.outPath==`string`?t.outPath:``,r=Qd(t);if(r.length<=1)return{data:t,text:Zd(t,n)};let i=[`Recording chunks:`];for(let e of r)i.push(` ${e.index}: ${e.path}`);return typeof t.telemetryPath==`string`&&i.push(`Telemetry: ${t.telemetryPath}`),typeof t.warning==`string`&&i.push(`Warning: ${t.warning}`),typeof t.overlayWarning==`string`&&i.push(`Overlay warning: ${t.overlayWarning}`),{data:t,text:i.join(`
48
- `)}}const Xd={record:f(Yd)};function Zd(e,t){let n=[];return t&&n.push(t),typeof e.sessionStateDir==`string`&&n.push(`Session state: ${e.sessionStateDir}`),typeof e.warning==`string`&&n.push(`Warning: ${e.warning}`),typeof e.overlayWarning==`string`&&n.push(`Overlay warning: ${e.overlayWarning}`),n.join(`
49
- `)}function Qd(e){let t=e.chunks;return Array.isArray(t)?t.flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.index!=`number`||typeof t.path!=`string`?[]:[{index:t.index,path:t.path}]}):[]}const $d=`record`,ef=`trace`,tf=[`start`,`stop`],nf=R($d,`Start or stop a screen recording for the active app session or, where supported, the selected device. Long Android recordings can return multiple video artifacts; HarmonyOS supports whole-screen recording on physical devices.`,{action:A(F(tf)),path:j(),fps:N(),maxSize:vr(re.migration.record),quality:F(Le),hideTouches:P(),recordingScope:F(Be)}),rf=R(ef,`Start or stop trace-log capture and return the resulting artifact when capture ends. Use the same artifact path for the matching start and stop requests when an explicit path is required.`,{action:A(F(tf)),path:j()}),af={usageOverride:`record start [path] [--scope <app|device|system>] [--fps <n>] [--quality <medium|high>] [--hide-touches] | record stop`,usageFlags:[],listUsageOverride:`record start [path] | record stop`,positionalArgs:[`start|stop`,`path?`],allowedFlags:[`recordingScope`,`fps`,`quality`,`hideTouches`]},of={usageOverride:`trace start <path> | trace stop <path>`,listUsageOverride:`trace start <path> | trace stop <path>`,positionalArgs:[`start|stop`,`path?`]},sf=(e,t)=>({...b(t),action:mf(e[0],$d),path:e[1],fps:t.fps,quality:t.quality,hideTouches:t.hideTouches,recordingScope:t.recordingScope}),cf=(e,t)=>({...b(t),action:mf(e[0],ef),path:e[1]}),lf=v($d,e=>pf(e)),uf=e=>(c(`record`,e),lf(e)),df=v(ef,e=>pf(e)),ff=O({name:`recording`,commands:[D({name:$d,text:{summary:`Start or stop screen recording`,cliDetail:`The default --scope app requires an active app session from open <app>; use --scope device/system to explicitly request whole-screen recording where the selected backend supports it. Android record start publishes a durable device manifest, recordings longer than the 180s adb screenrecord limit are returned as multiple MP4 chunks while the daemon stays alive, and daemon-restart recovery uses only manifest-owned chunks. Android screenrecord encodes a frame only when the screen changes, so a clip can end at the last frame the recorder encoded instead of at record stop; durationMs is host wall clock from record start until the export finished, and capturedDurationMs reports the video timeline when it can be measured, with a warning naming how much of the window that video covers. An Android manifest left by an unreachable recording is retired on the next start once its recorders are proven gone; one still owned refuses with non-retriable DEVICE_IN_USE and reason native_recovery_evidence_open naming the session to run record stop for, and a recorder that is still writing an artifact refuses with DEVICE_IN_USE and reason native_recording_artifact_claimed, which clears itself once that recorder ends at the 180s limit. HarmonyOS supports whole-screen recording on physical devices only: use --scope device/system; --fps, --quality, and --hide-touches are unsupported. Use --quality to choose medium or high export quality on supported backends. An iOS simulator host recording lock returns non-retriable DEVICE_IN_USE with reason apple_simulator_recording_busy. Stop the recording in its owning session; if a dead recorder left the host locked, ask the host operator to restart the CoreSimulator stream service. A record stop that cannot produce its export keeps what a retry reads back — on Android the device-side artifact and the native manifest — leaves the recording manifest of that session open, and returns its own error, so retry record stop in that session; only closing the session disposes them. Every stopped recording also reports what became of its recorder and of the file that recorder writes to: recorder is confirmed, or lost when the session holding it died, and nativePathDisposition is retirable while that file still owes a removal or retired once its removal was verified. Both are optional disclosures, not failures; ADR 0024 declares further states (unconfirmed, pending) for the steps that gain those probes, and no stop reports them yet.`},metadata:nf,run:(e,t)=>e.recording.record(t),cliSchema:af,cliReader:sf,daemonWriter:uf,cliOutputFormatter:Xd.record}),D({name:ef,text:{summary:`Start or stop trace capture`,cliDetail:`Pass that path as the same positional argument to start and stop.`},metadata:rf,run:(e,t)=>e.recording.trace(t),cliSchema:of,cliReader:cf,daemonWriter:df})]});function pf(e){return[e.action,...C(e.path)]}function mf(t,n){if(t===`start`||t===`stop`)return t;throw new e(`INVALID_ARGS`,`${n} requires start|stop`)}const hf=2097152;async function gf(e){let t=Xt(e.inputPath,{cwd:e.cwd}),n=vf(t,e.inputPath);if(nt(t,e.replayBackend)!==`maestro`)return _f(t,{[t]:n},e.inputPath);let{collectMaestroFlowSources:r}=await import(`./src8.js`).then(e=>e.t);return _f(t,r({entryPath:t,entrySource:n,env:e.env,readSource:yf}),e.inputPath)}function _f(e,t,n){return bf(t,n),{entry:e,files:t}}function vf(t,n){try{return nn.readFileSync(t,`utf8`)}catch(r){throw new e(`INVALID_ARGS`,`replay script not found on this machine: ${n}`,{path:t,hint:`Replay scripts are read by the client and sent to the daemon, so the path must resolve where you ran the command.`},r instanceof Error?r:void 0)}}function yf(e){try{return nn.readFileSync(e,`utf8`)}catch{return}}function bf(t,n){let r=Object.values(t).reduce((e,t)=>e+Buffer.byteLength(t,`utf8`),0);if(!(r<=2097152))throw new e(`INVALID_ARGS`,`replay script sources for ${n} total ${r} bytes, over the ${hf}-byte limit; split the flow or drop unused runFlow includes.`,{limitBytes:hf,totalBytes:r})}const xf=/[*?[\]{}]/;function Sf(e){let t=e.replayBackend===`maestro`?new Set([`.yaml`,`.yml`,`.ad`]):new Set([`.ad`]),n=[],r=[];for(let i of e.inputs){let a=Cf(i,e.cwd,t);if(a.source===`file`){n.push(...a.paths);continue}r.push(a.source===`directory`?Of(a.paths):Ef(a.paths))}return Of([...n,...r.flat()])}function Cf(t,n,r){let i=Xt(t,{cwd:n});if(nn.existsSync(i)){let e=nn.statSync(i);return e.isDirectory()?{paths:Tf(i,r),source:`directory`}:e.isFile()?(wf(t,i,r),{paths:[i],source:`file`}):{paths:[],source:`file`}}if(!kf(t))throw new e(`INVALID_ARGS`,`test input not found: ${t}`);return{source:`glob`,paths:nn.globSync(Zt(t),{cwd:n}).map(e=>m.isAbsolute(e)?e:m.resolve(n,e)).filter(e=>r.has(m.extname(e).toLowerCase())&&Af(e))}}function wf(t,n,r){if(!r.has(m.extname(n).toLowerCase()))throw rt(n)&&!r.has(`.yaml`)?new e(`INVALID_ARGS`,tt(`test`,t)):new e(`INVALID_ARGS`,`test does not support this file type: ${t}`)}function Tf(e,t){let n=[],r=nn.opendirSync(e);try{let i;for(;(i=r.readSync())!==null;){let r=m.join(e,i.name);i.isDirectory()?n.push(...Tf(r,t)):i.isFile()&&t.has(m.extname(i.name).toLowerCase())&&n.push(r)}}finally{r.closeSync()}return n}function Ef(e){return e.map(e=>m.normalize(e)).sort((e,t)=>{let n=Df(e)-Df(t);return n===0?e.localeCompare(t):n})}function Df(e){return+(m.extname(e).toLowerCase()===`.ad`)}function Of(e){return[...new Set(e.map(e=>m.normalize(e)))]}function kf(e){return xf.test(e)}function Af(e){try{return nn.statSync(e).isFile()}catch{return!1}}const jf=`replay`,Mf=`test`,Nf=R(jf,`Run a recorded automation script, including compatible Maestro YAML flows. A script without a terminal close leaves its session active for subsequent automation.`,{path:A(j()),update:P(),backend:j(),maestro:P(),env:Tr(),metroHost:j(`Metro/debug host hint inherited by replay-opened sessions.`),metroPort:N(`Metro/debug port hint inherited by replay-opened sessions.`),bundleUrl:j(`Bundle URL hint inherited by replay-opened sessions.`),resumeFrom:N(),resumePlanDigest:j(),keepSession:P(`Leave the session active by suppressing exactly an authored terminal close in native .ad.`),timeoutMs:N(`Maximum wall-clock duration for the replay request.`),saveScript:I({oneOf:[hr(),k()]}),force:P()}),Pf=R(Mf,`Run one or more replay scripts as a serial test suite`,{paths:A(Tr()),update:P(),backend:j(),maestro:P(),env:Tr(),metroHost:j(`Metro/debug host hint inherited by each test session.`),metroPort:N(`Metro/debug port hint inherited by each test session.`),bundleUrl:j(`Bundle URL hint inherited by each test session.`),failFast:P(),timeoutMs:N(),retries:N(),recordVideo:P(),artifactsDir:j(),shardAll:N(),shardSplit:N()}),Ff={usageOverride:`replay <path> | replay export <file.ad> [--out <path>]`,usageFlags:[],positionalArgs:[`path`],allowsExtraPositionals:!0,allowedFlags:[`replayMaestro`,...Ci,...bi,`replayFrom`,`replayPlanDigest`,`replayKeepSession`,`timeoutMs`,`out`,`saveScript`,`force`],flagDescriptionOverrides:{saveScript:`Arm a repair transaction from this replay (ADR 0012): recording starts at step 1, and the healed script commits when the repair-armed session tears down (close, close --save-script, or idle-reap). Independent of the open/close authoring arm-on-open. Optional custom output path.`}},If={usageOverride:`test <path-or-glob>...`,usageFlags:[],listUsageOverride:`test <path-or-glob>...`,positionalArgs:[`pathOrGlob`],allowsExtraPositionals:!0,allowedFlags:[`replayMaestro`,...Ci,...bi,`failFast`,`timeoutMs`,`retries`,`recordVideo`,`artifactsDir`,`reporter`,`reportJunit`,`shardAll`,`shardSplit`]},Lf=O({name:`replay`,commands:[D({name:jf,text:{summary:`Replay a recorded session or Maestro flow`,cliDetail:`For Maestro YAML compatibility flows, use replay <flow.yaml> --maestro and keep the target binding such as --platform ios on the replay command. A script with no terminal close leaves its session (and daemon) running until you close it or it idle-reaps — no different from a session opened interactively. For native .ad scripts, --keep-session suppresses exactly an authored terminal close so you can continue interactively. replay export <file.ad> converts compatible actions to Maestro YAML locally, including app switches with explicit launchApp.appId targets, deep links (including tel: and mailto:) as openLink, and home as pressKey: Home.`},metadata:Nf,run:(e,t)=>e.replay.run(Ec(t)),cliSchema:Ff,cliReader:(e,t)=>({...b(t),path:T(e[0],`replay requires path`),update:t.replayUpdate,backend:t.replayMaestro?`maestro`:void 0,env:t.replayEnv,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,resumeFrom:t.replayFrom,resumePlanDigest:t.replayPlanDigest,keepSession:t.replayKeepSession,timeoutMs:t.timeoutMs,saveScript:t.saveScript,force:t.force}),daemonWriter:async e=>{let t=E(e.path,`replay requires path`),n=Bf(e),r=Hf(process.env);return y(jf,[t],{...e,replayUpdate:e.update,replayBackend:n,replayEnv:e.env,replayShellEnv:r,replayScriptSource:await gf({inputPath:t,cwd:zf(e),replayBackend:n,env:Rf(e,r)}),replayFrom:e.resumeFrom,replayPlanDigest:e.resumePlanDigest,replayKeepSession:e.keepSession,saveScript:e.saveScript})},cliOutputFormatter:wt}),D({name:Mf,text:{summary:`Run replay test suites`,cliDetail:`Relative globs are expanded on the caller from its working directory, whose name is treated literally. Quote glob inputs to defer expansion to test. Copied diagnostic artifacts receive numbered filenames when needed to preserve other artifacts, replay sources, timing traces, and attempt manifests. JUnit reports (--reporter junit:<path>) replace characters forbidden by XML 1.0 with U+FFFD and preserve legal Unicode and whitespace. JSON and other reporters retain the original suite values. Custom reporter getExitCode hooks must return an integer from 0 to 255 or undefined; the highest valid code wins and cannot lower a failing suite's exit code.`},metadata:Pf,run:(e,t)=>e.replay.test(Ec(t)),cliSchema:If,cliReader:(e,t)=>({...b(t),paths:e,update:t.replayUpdate,backend:t.replayMaestro?`maestro`:void 0,env:t.replayEnv,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,failFast:t.failFast,timeoutMs:t.timeoutMs,retries:t.retries,recordVideo:t.recordVideo,artifactsDir:t.artifactsDir,shardAll:t.shardAll,shardSplit:t.shardSplit}),daemonWriter:async e=>{let t=e.paths??[],n=Bf(e),r=zf(e),i=Hf(process.env),a=Rf(e,i);return y(Mf,t,{...Vf(e),replayUpdate:e.update,replayBackend:n,replayEnv:e.env,replayShellEnv:i,replayScriptSources:await Promise.all(Sf({inputs:t,cwd:r,replayBackend:n}).map(async e=>await gf({inputPath:e,cwd:r,replayBackend:n,env:a})))})}})]});function Rf(e,t){return{...et(t),...$e(Qe(e.env))}}function zf(e){return typeof e.cwd==`string`&&e.cwd.length>0?e.cwd:process.cwd()}function Bf(e){return e.backend??(e.maestro===!0?`maestro`:void 0)}function Vf(e){let t={...e};return delete t.reporter,delete t.reportJunit,t}function Hf(e){let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&n.startsWith(`AD_VAR_`)&&(t[n]=r);return t}function Uf(e){return{data:e,text:Kf(e)}}function Wf(e){if(e.platform===`android`&&e.action===`status`){let t=[`Keyboard visible: ${e.visible===!0?`yes`:`no`}`,`Input type: ${e.type??e.inputType??`unknown`}`,`Input owner: ${e.inputOwner??`unknown`}`];return e.inputMethodPackage&&t.push(`Input method: ${e.inputMethodPackage}`),e.focusedPackage&&t.push(`Focused package: ${e.focusedPackage}`),e.focusedResourceId&&t.push(`Focused resource: ${e.focusedResourceId}`),t.push(`Next action: ${qf(e.visible,e.inputOwner)}`),{data:e,text:t.join(`
50
- `)}}return Tt(e)}function Gf(e){return e.action===`read`?{data:e,text:e.text}:Tt(e)}const $=ys({appstate:f(Uf),back:p,home:p,orientation:p,"app-switcher":p,keyboard:f(Wf),clipboard:f(Gf),"tv-remote":p});function Kf(e){if(e.platform===`ios`){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(`
47
+ Aggregate perf was removed in 0.21. Use one of the explicit forms above.`,usageFlags:[],listUsageOverride:`perf`,positionalArgs:[`area`,`subjectOrAction?`,`action?`],allowedFlags:[`kind`,`perfTemplate`,`out`]},cliReader:(e,t)=>({...x(t),...Vd(e,{kind:qd(t.kind),template:t.perfTemplate,out:t.out})}),daemonWriter:y(Ld,e=>zd(e)),cliOutputFormatter:od.perf})]});function zd(e){let t=e.area;return t===`cpu`?Bd([...w(t),...w(e.subject),...w(e.action),...w(e.kind)],e):t===`trace`?Bd([...w(t),...w(e.action),...w(e.kind)],e):[...w(t),...w(e.action)]}function Bd(e,t){let n=[...e];return(t.template||t.out||t.tracePath)&&n.push(t.template??``),(t.out||t.tracePath)&&n.push(t.out??``),t.tracePath&&n.push(t.tracePath),n}function Vd(e,t={}){let n=Ud(e[0]);if(n===`cpu`)return{area:n,subject:Gd(e[1]),action:Wd(e[2]),kind:Kd(t.kind),template:t.template,out:t.out};if(n===`trace`)return{area:n,action:Wd(e[1]),kind:Kd(t.kind),template:t.template,out:t.out};let r=Wd(e[1]),i=Kd(t.kind);return Hd(n,r,i,t.out),{area:n,action:r,kind:i,out:t.out}}function Hd(t,n,r,i){if(t===`frames`){if(r!==void 0)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(i!==void 0)throw new e(`INVALID_ARGS`,`--out is only supported with perf memory snapshot, perf cpu profile, or perf trace`)}if(t===`memory`){if(n!==`snapshot`&&r!==void 0)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(n!==`snapshot`&&i!==void 0)throw new e(`INVALID_ARGS`,`--out is only supported with perf memory snapshot`)}}function Ud(t){let n=t?.toLowerCase();if(ft(n))throw new e(`INVALID_ARGS`,mt);if(dt(n))return n;throw new e(`INVALID_ARGS`,ct)}function Wd(t){if(t===void 0)return;let n=t.toLowerCase();if(ut(n))return n;throw new e(`INVALID_ARGS`,bt)}function Gd(t){let n=t?.toLowerCase();if(n!==void 0&&pt(n))return n;throw new e(`INVALID_ARGS`,ht)}function Kd(t){if(t===void 0)return;let n=t.toLowerCase();if(vt(n))return n;throw new e(`INVALID_ARGS`,yt)}function qd(e){return typeof e==`string`?Kd(e):void 0}const Jd=`react-native`,Yd=z({name:`react-native`,commands:[R({name:Jd,text:{summary:`Run React Native automation helpers`},metadata:L(Jd,`Run supported React Native automation helpers. Use dismiss-overlay to close a visible development error overlay before continuing normal UI automation.`,{action:O(N([`dismiss-overlay`]))}),run:(e,t)=>e.command.reactNative(t),cliSchema:{usageOverride:`react-native dismiss-overlay`,listUsageOverride:`react-native dismiss-overlay`,positionalArgs:[`dismiss-overlay`]},cliReader:(e,t)=>({...x(t),action:Xd(e[0])}),daemonWriter:y(Jd,e=>[D(e.action,`react-native requires action`)])})]});function Xd(t){if(t===`dismiss-overlay`)return t;throw new e(`INVALID_ARGS`,`react-native supports only: dismiss-overlay`)}function Zd(e){let t=e,n=typeof t.outPath==`string`?t.outPath:``,r=ef(t);if(r.length<=1)return{data:t,text:$d(t,n)};let i=[`Recording chunks:`];for(let e of r)i.push(` ${e.index}: ${e.path}`);return typeof t.telemetryPath==`string`&&i.push(`Telemetry: ${t.telemetryPath}`),typeof t.warning==`string`&&i.push(`Warning: ${t.warning}`),typeof t.overlayWarning==`string`&&i.push(`Overlay warning: ${t.overlayWarning}`),{data:t,text:i.join(`
48
+ `)}}const Qd={record:d(Zd)};function $d(e,t){let n=[];return t&&n.push(t),typeof e.sessionStateDir==`string`&&n.push(`Session state: ${e.sessionStateDir}`),typeof e.warning==`string`&&n.push(`Warning: ${e.warning}`),typeof e.overlayWarning==`string`&&n.push(`Overlay warning: ${e.overlayWarning}`),n.join(`
49
+ `)}function ef(e){let t=e.chunks;return Array.isArray(t)?t.flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.index!=`number`||typeof t.path!=`string`?[]:[{index:t.index,path:t.path}]}):[]}const tf=`record`,nf=`trace`,rf=[`start`,`stop`],af=L(tf,`Start or stop a screen recording for the active app session or, where supported, the selected device. Long Android recordings can return multiple video artifacts; HarmonyOS supports whole-screen recording on physical devices.`,{action:O(N(rf)),path:k(),fps:j(),maxSize:gr(ie.migration.record),quality:N(Re),hideTouches:M(),recordingScope:N(Ve)},{parseableOutput:!0}),of=L(nf,`Start or stop trace-log capture and return the resulting artifact when capture ends. Use the same artifact path for the matching start and stop requests when an explicit path is required.`,{action:O(N(rf)),path:k()}),sf={usageOverride:`record start [path] [--scope <app|device|system>] [--fps <n>] [--quality <medium|high>] [--hide-touches] | record stop`,usageFlags:[],listUsageOverride:`record start [path] | record stop`,positionalArgs:[`start|stop`,`path?`],allowedFlags:[`recordingScope`,`fps`,`quality`,`hideTouches`]},cf={usageOverride:`trace start <path> | trace stop <path>`,listUsageOverride:`trace start <path> | trace stop <path>`,positionalArgs:[`start|stop`,`path?`]},lf=(e,t)=>({...x(t),action:gf(e[0],tf),path:e[1],fps:t.fps,quality:t.quality,hideTouches:t.hideTouches,recordingScope:t.recordingScope}),uf=(e,t)=>({...x(t),action:gf(e[0],nf),path:e[1]}),df=y(tf,e=>hf(e)),ff=e=>(c(`record`,e),df(e)),pf=y(nf,e=>hf(e)),mf=z({name:`recording`,commands:[R({name:tf,text:{summary:`Start or stop screen recording`,cliDetail:`The default --scope app requires an active app session from open <app>; use --scope device/system to explicitly request whole-screen recording where the selected backend supports it. Android record start publishes a durable device manifest, recordings longer than the 180s adb screenrecord limit are returned as multiple MP4 chunks while the daemon stays alive, and daemon-restart recovery uses only manifest-owned chunks. Android screenrecord encodes a frame only when the screen changes, so a clip can end at the last frame the recorder encoded instead of at record stop; durationMs is host wall clock from record start until the export finished, and capturedDurationMs reports the video timeline when it can be measured, with a warning naming how much of the window that video covers. An Android manifest left by an unreachable recording is retired on the next start once its recorders are proven gone; one still owned refuses with non-retriable DEVICE_IN_USE and reason native_recovery_evidence_open naming the session to run record stop for, and a recorder that is still writing an artifact refuses with DEVICE_IN_USE and reason native_recording_artifact_claimed, which clears itself once that recorder ends at the 180s limit. HarmonyOS supports whole-screen recording on physical devices only: use --scope device/system; --fps, --quality, and --hide-touches are unsupported. Use --quality to choose medium or high export quality on supported backends. An iOS simulator host recording lock returns non-retriable DEVICE_IN_USE with reason apple_simulator_recording_busy. Stop the recording in its owning session; if a dead recorder left the host locked, ask the host operator to restart the CoreSimulator stream service. A record stop that cannot produce its export keeps what a retry reads back — on Android the device-side artifact and the native manifest — leaves the recording manifest of that session open, and returns its own error, so retry record stop in that session; only closing the session disposes them. Every stopped recording also reports what became of its recorder and of the file that recorder writes to: recorder is confirmed, or lost when the session holding it died, and nativePathDisposition is retirable while that file still owes a removal or retired once its removal was verified. Both are optional disclosures, not failures; ADR 0024 declares further states (unconfirmed, pending) for the steps that gain those probes, and no stop reports them yet.`},metadata:af,run:(e,t)=>e.recording.record(t),cliSchema:sf,cliReader:lf,daemonWriter:ff,cliOutputFormatter:Qd.record}),R({name:nf,text:{summary:`Start or stop trace capture`,cliDetail:`Pass that path as the same positional argument to start and stop.`},metadata:of,run:(e,t)=>e.recording.trace(t),cliSchema:cf,cliReader:uf,daemonWriter:pf})]});function hf(e){return[e.action,...w(e.path)]}function gf(t,n){if(t===`start`||t===`stop`)return t;throw new e(`INVALID_ARGS`,`${n} requires start|stop`)}const _f=2097152;async function vf(e){let t=Qt(e.inputPath,{cwd:e.cwd}),n=bf(t,e.inputPath);if(nt(t,e.replayBackend)!==`maestro`)return yf(t,{[t]:n},e.inputPath);let{collectMaestroFlowSources:r}=await import(`./src8.js`).then(e=>e.t);return yf(t,r({entryPath:t,entrySource:n,env:e.env,readSource:xf}),e.inputPath)}function yf(e,t,n){return Sf(t,n),{entry:e,files:t}}function bf(t,n){try{return h.readFileSync(t,`utf8`)}catch(r){throw new e(`INVALID_ARGS`,`replay script not found on this machine: ${n}`,{path:t,hint:`Replay scripts are read by the client and sent to the daemon, so the path must resolve where you ran the command.`},r instanceof Error?r:void 0)}}function xf(e){try{return h.readFileSync(e,`utf8`)}catch{return}}function Sf(t,n){let r=Object.values(t).reduce((e,t)=>e+Buffer.byteLength(t,`utf8`),0);if(!(r<=2097152))throw new e(`INVALID_ARGS`,`replay script sources for ${n} total ${r} bytes, over the ${_f}-byte limit; split the flow or drop unused runFlow includes.`,{limitBytes:_f,totalBytes:r})}const Cf=/[*?[\]{}]/;function wf(e){let t=e.replayBackend===`maestro`?new Set([`.yaml`,`.yml`,`.ad`]):new Set([`.ad`]),n=[],r=[];for(let i of e.inputs){let a=Tf(i,e.cwd,t);if(a.source===`file`){n.push(...a.paths);continue}r.push(a.source===`directory`?Af(a.paths):Of(a.paths))}return Af([...n,...r.flat()])}function Tf(t,n,r){let i=Qt(t,{cwd:n});if(h.existsSync(i)){let e=h.statSync(i);return e.isDirectory()?{paths:Df(i,r),source:`directory`}:e.isFile()?(Ef(t,i,r),{paths:[i],source:`file`}):{paths:[],source:`file`}}if(!jf(t))throw new e(`INVALID_ARGS`,`test input not found: ${t}`);return{source:`glob`,paths:h.globSync($t(t),{cwd:n}).map(e=>m.isAbsolute(e)?e:m.resolve(n,e)).filter(e=>r.has(m.extname(e).toLowerCase())&&Mf(e))}}function Ef(t,n,r){if(!r.has(m.extname(n).toLowerCase()))throw it(n)&&!r.has(`.yaml`)?new e(`INVALID_ARGS`,et(`test`,t)):new e(`INVALID_ARGS`,`test does not support this file type: ${t}`)}function Df(e,t){let n=[],r=h.opendirSync(e);try{let i;for(;(i=r.readSync())!==null;){let r=m.join(e,i.name);i.isDirectory()?n.push(...Df(r,t)):i.isFile()&&t.has(m.extname(i.name).toLowerCase())&&n.push(r)}}finally{r.closeSync()}return n}function Of(e){return e.map(e=>m.normalize(e)).sort((e,t)=>{let n=kf(e)-kf(t);return n===0?e.localeCompare(t):n})}function kf(e){return+(m.extname(e).toLowerCase()===`.ad`)}function Af(e){return[...new Set(e.map(e=>m.normalize(e)))]}function jf(e){return Cf.test(e)}function Mf(e){try{return h.statSync(e).isFile()}catch{return!1}}const Nf=`replay`,Pf=`test`,Ff=L(Nf,`Run a recorded automation script, including compatible Maestro YAML flows. A script without a terminal close leaves its session active for subsequent automation.`,{path:O(k()),update:M(),backend:k(),maestro:M(),env:Cr(),metroHost:k(`Metro/debug host hint inherited by replay-opened sessions.`),metroPort:j(`Metro/debug port hint inherited by replay-opened sessions.`),bundleUrl:k(`Bundle URL hint inherited by replay-opened sessions.`),resumeFrom:j(),resumePlanDigest:k(),keepSession:M(`Leave the session active by suppressing exactly an authored terminal close in native .ad.`),timeoutMs:j(`Maximum wall-clock duration for the replay request.`),saveScript:P({oneOf:[pr(),ur()]}),force:M()}),If=L(Pf,`Run one or more replay scripts as a serial test suite`,{paths:O(Cr()),update:M(),backend:k(),maestro:M(),env:Cr(),metroHost:k(`Metro/debug host hint inherited by each test session.`),metroPort:j(`Metro/debug port hint inherited by each test session.`),bundleUrl:k(`Bundle URL hint inherited by each test session.`),failFast:M(),timeoutMs:j(),retries:j(),recordVideo:M(),artifactsDir:k(),shardAll:j(),shardSplit:j()}),Lf={usageOverride:`replay <path> | replay export <file.ad> [--out <path>]`,usageFlags:[],positionalArgs:[`path`],allowsExtraPositionals:!0,allowedFlags:[`replayMaestro`,...Ti,...Si,`replayFrom`,`replayPlanDigest`,`replayKeepSession`,`timeoutMs`,`out`,`saveScript`,`force`],flagDescriptionOverrides:{saveScript:`Arm a repair transaction from this replay (ADR 0012): recording starts at step 1, and the healed script commits when the repair-armed session tears down (close, close --save-script, or idle-reap). Independent of the open/close authoring arm-on-open. Optional custom output path.`}},Rf={usageOverride:`test <path-or-glob>...`,usageFlags:[],listUsageOverride:`test <path-or-glob>...`,positionalArgs:[`pathOrGlob`],allowsExtraPositionals:!0,allowedFlags:[`replayMaestro`,...Ti,...Si,`failFast`,`timeoutMs`,`retries`,`recordVideo`,`artifactsDir`,`reporter`,`reportJunit`,`shardAll`,`shardSplit`]},zf=z({name:`replay`,commands:[R({name:Nf,text:{summary:`Replay a recorded session or Maestro flow`,cliDetail:`For Maestro YAML compatibility flows, use replay <flow.yaml> --maestro and keep the target binding such as --platform ios on the replay command. A script with no terminal close leaves its session (and daemon) running until you close it or it idle-reaps — no different from a session opened interactively. For native .ad scripts, --keep-session suppresses exactly an authored terminal close so you can continue interactively. replay export <file.ad> converts compatible actions to Maestro YAML locally, including app switches with explicit launchApp.appId targets, deep links (including tel: and mailto:) as openLink, and home as pressKey: Home.`},metadata:Ff,run:(e,t)=>e.replay.run(Dc(t)),cliSchema:Lf,cliReader:(e,t)=>({...x(t),path:E(e[0],`replay requires path`),update:t.replayUpdate,backend:t.replayMaestro?`maestro`:void 0,env:t.replayEnv,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,resumeFrom:t.replayFrom,resumePlanDigest:t.replayPlanDigest,keepSession:t.replayKeepSession,timeoutMs:t.timeoutMs,saveScript:t.saveScript,force:t.force}),daemonWriter:async e=>{let t=D(e.path,`replay requires path`),n=Hf(e),r=Wf(process.env);return b(Nf,[t],{...e,replayUpdate:e.update,replayBackend:n,replayEnv:e.env,replayShellEnv:r,replayScriptSource:await vf({inputPath:t,cwd:Vf(e),replayBackend:n,env:Bf(e,r)}),replayFrom:e.resumeFrom,replayPlanDigest:e.resumePlanDigest,replayKeepSession:e.keepSession,saveScript:e.saveScript})},cliOutputFormatter:p}),R({name:Pf,text:{summary:`Run replay test suites`,cliDetail:`Relative globs are expanded on the caller from its working directory, whose name is treated literally. Quote glob inputs to defer expansion to test. Copied diagnostic artifacts receive numbered filenames when needed to preserve other artifacts, replay sources, timing traces, and attempt manifests. JUnit reports (--reporter junit:<path>) replace characters forbidden by XML 1.0 with U+FFFD and preserve legal Unicode and whitespace. JSON and other reporters retain the original suite values. Custom reporter getExitCode hooks must return an integer from 0 to 255 or undefined; the highest valid code wins and cannot lower a failing suite's exit code.`},metadata:If,run:(e,t)=>e.replay.test(Dc(t)),cliSchema:Rf,cliReader:(e,t)=>({...x(t),paths:e,update:t.replayUpdate,backend:t.replayMaestro?`maestro`:void 0,env:t.replayEnv,metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,failFast:t.failFast,timeoutMs:t.timeoutMs,retries:t.retries,recordVideo:t.recordVideo,artifactsDir:t.artifactsDir,shardAll:t.shardAll,shardSplit:t.shardSplit}),daemonWriter:async e=>{let t=e.paths??[],n=Hf(e),r=Vf(e),i=Wf(process.env),a=Bf(e,i);return b(Pf,t,{...Uf(e),replayUpdate:e.update,replayBackend:n,replayEnv:e.env,replayShellEnv:i,replayScriptSources:await Promise.all(wf({inputs:t,cwd:r,replayBackend:n}).map(async e=>await vf({inputPath:e,cwd:r,replayBackend:n,env:a})))})}})]});function Bf(e,t){return{...tt(t),...rt($e(e.env))}}function Vf(e){return typeof e.cwd==`string`&&e.cwd.length>0?e.cwd:process.cwd()}function Hf(e){return e.backend??(e.maestro===!0?`maestro`:void 0)}function Uf(e){let t={...e};return delete t.reporter,delete t.reportJunit,t}function Wf(e){let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&n.startsWith(`AD_VAR_`)&&(t[n]=r);return t}function Gf(e){return{data:e,text:Jf(e)}}function Kf(e){if(e.platform===`android`&&e.action===`status`){let t=[`Keyboard visible: ${e.visible===!0?`yes`:`no`}`,`Input type: ${e.type??e.inputType??`unknown`}`,`Input owner: ${e.inputOwner??`unknown`}`];return e.inputMethodPackage&&t.push(`Input method: ${e.inputMethodPackage}`),e.focusedPackage&&t.push(`Focused package: ${e.focusedPackage}`),e.focusedResourceId&&t.push(`Focused resource: ${e.focusedResourceId}`),t.push(`Next action: ${Yf(e.visible,e.inputOwner)}`),{data:e,text:t.join(`
50
+ `)}}return f(e)}function qf(e){return e.action===`read`?{data:e,text:e.text}:f(e)}const $=xs({appstate:d(Gf),back:p,home:p,orientation:p,fold:p,"app-switcher":p,"action-button":p,keyboard:d(Kf),clipboard:d(qf),"tv-remote":p});function Jf(e){if(e.platform===`ios`){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(`
51
51
  `)}if(e.platform===`android`){let t=[`Foreground app: ${e.package??`unknown`}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join(`
52
- `)}return null}function qf(e,t){return t===`ime`?`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`:e===!0?`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.`}const Jf=`appstate`,Yf=`back`,Xf=`home`,Zf=`orientation`,Qf=`app-switcher`,$f=`keyboard`,ep=`clipboard`,tp=`tv-remote`,np=[`read`,`write`],rp=[`status`,`dismiss`,`enter`,`return`],ip=R(Jf,`Show foreground app/activity`,{}),ap=R(Yf,`Navigate back in the app or through system navigation. Use in-app for the app navigation stack and system when the platform back behavior is required.`,{mode:F(Ve),...H(Yf)}),op=R(Xf,`Send the selected device to its home screen. This leaves the app session open but moves the foreground away from the app.`,{}),sp=R(Zf,`Set device orientation on iOS and Android`,{orientation:A(F(Jt))}),cp=R(Qf,`Open the device app switcher to inspect or change foreground apps. This changes the visible system UI and may move focus away from the current app.`,{}),lp=R($f,`Inspect Android keyboard visibility/type or press/dismiss the device keyboard. To hide the keyboard, use keyboard dismiss. It taps the keyboard dismiss/hide key when one is exposed, verifies the keyboard closed, and reports UNSUPPORTED_OPERATION when no dismiss key exists — background taps are never attempted.`,{action:F(rp)}),up=R(ep,`Read the current device clipboard text, or replace its contents with the given text.`,{action:A(F(np)),text:j()}),dp=R(tp,`Press or long-press a TV remote or D-pad button on Android TV, tvOS, or Vega OS. Choose the button and optional hold duration through the input fields. The aliases ok, center, and enter all map to select.`,{button:A(F(tn)),durationMs:N(`Press duration in milliseconds. tvOS and Vega OS use the exact hold duration; Android TV maps any positive value to an ADB longpress (${en(`android`)}).`,{min:0})}),fp={},pp={usageOverride:`back [--in-app|--system] [--settle]`,usageFlags:[],allowedFlags:[`backMode`,...U(Yf)]},mp={},hp={},gp={usageOverride:`orientation <portrait|portrait-upside-down|landscape-left|landscape-right>`,positionalArgs:[`orientation`]},_p={usageOverride:`keyboard [status|get|dismiss|enter|return]`,positionalArgs:[`action?`]},vp={usageOverride:`clipboard read | clipboard write <text>`,listUsageOverride:`clipboard read | clipboard write <text>`,positionalArgs:[`read|write`,`text?`],allowsExtraPositionals:!0},yp={usageOverride:`tv-remote [press|longpress] ${Qt}`,listUsageOverride:`tv-remote press|longpress <button> [--duration-ms <ms>]`,positionalArgs:[`press|longpress?`,`button`],allowedFlags:[`durationMs`]},bp=(e,t)=>b(t),xp=(e,t)=>b(t),Sp=(e,t)=>b(t),Cp=(e,t)=>({...b(t),mode:t.backMode}),wp=(e,t)=>({...b(t),orientation:qt(e[0])}),Tp=(e,t)=>({...b(t),...zp(e)}),Ep=(e,t)=>({...b(t),...Bp(e)}),Dp=(e,t)=>({...b(t),...Vp(e,t.durationMs)}),Op=v(Jf),kp=e=>y(Yf,[],{...e,backMode:Lp(e.mode)}),Ap=v(Xf),jp=v(Zf,e=>[E(e.orientation,`orientation requires orientation`)]),Mp=v(Qf),Np=v($f,e=>C(e.action)),Pp=v(ep,e=>Rp(e)),Fp=v(tp,e=>[E(e.button,`tv-remote requires button`)]),Ip=O({name:`system`,commands:[D({name:Jf,text:{summary:`Show the foreground app and activity`},metadata:ip,run:(e,t)=>e.command.appState(t),cliSchema:fp,cliReader:bp,daemonWriter:Op,cliOutputFormatter:$.appstate}),D({name:Yf,text:{summary:`Navigate back in the app or system`},metadata:ap,run:(e,t)=>e.command.back(t),cliSchema:pp,cliReader:Cp,daemonWriter:kp,cliOutputFormatter:$.back}),D({name:Xf,text:{summary:`Go to the device home screen`},metadata:op,run:(e,t)=>e.command.home(t),cliSchema:mp,cliReader:xp,daemonWriter:Ap,cliOutputFormatter:$.home}),D({name:Zf,text:{summary:`Set device orientation`},metadata:sp,run:(e,t)=>e.command.orientation(t),cliSchema:gp,cliReader:wp,daemonWriter:jp,cliOutputFormatter:$.orientation}),D({name:Qf,text:{summary:`Open the device app switcher`},metadata:cp,run:(e,t)=>e.command.appSwitcher(t),cliSchema:hp,cliReader:Sp,daemonWriter:Mp,cliOutputFormatter:$[`app-switcher`]}),D({name:$f,text:{summary:`Inspect, press, or dismiss the device keyboard`},metadata:lp,run:(e,t)=>e.command.keyboard(t),cliSchema:_p,cliReader:Tp,daemonWriter:Np,cliOutputFormatter:$.keyboard}),D({name:ep,text:{summary:`Read or write device clipboard text`},metadata:up,run:(e,t)=>e.command.clipboard(t),cliSchema:vp,cliReader:Ep,daemonWriter:Pp,cliOutputFormatter:$.clipboard}),D({name:tp,text:{summary:`Press a TV remote/D-pad button`,cliDetail:`longpress holds for 500ms by default; --duration-ms overrides the preset.`},metadata:dp,run:(e,t)=>e.command.tvRemote(t),cliSchema:yp,cliReader:Dp,daemonWriter:Fp,cliOutputFormatter:$[`tv-remote`]})]});function Lp(e){return e===`in-app`||e===`system`?e:void 0}function Rp(e){return e.action===`read`?[`read`]:[`write`,e.text]}function zp(t){if(t.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one action argument.`);return g({action:Hp(t[0])})}function Bp(t){let n=t[0]?.toLowerCase();if(n!==`read`&&n!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write.`);if(n===`read`){if(t.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments.`);return{action:n}}if(t.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text.`);return{action:n,text:t.slice(1).join(` `)}}function Vp(t,n){let r=t[0]?.toLowerCase(),i=r===`press`||r===`longpress`?t.slice(1):t;if(i.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button: ${tn.join(`, `)}.`);let a=n??(r===`longpress`?500:void 0);return g({button:$t(i[0]),durationMs:a})}function Hp(t){let n=t?.toLowerCase();if(n===`get`)return`status`;if(n===void 0||n===`status`||n===`dismiss`||n===`enter`||n===`return`)return n;throw new e(`INVALID_ARGS`,`keyboard action must be status, get, dismiss, enter, or return.`)}const Up=[Ws,Xl,Po,Ip,qd,Lf,qu,Id,zo,ff,eu,di];function Wp(){return Up.flatMap(e=>[...e.metadata])}function Gp(){return Up.flatMap(e=>[...e.definitions])}function Kp(){return Xp(`cliSchemas`)}function qp(){return Xp(`cliReaders`)}function Jp(){return Xp(`daemonWriters`)}function Yp(){return Xp(`cliOutputFormatters`)}function Xp(e){let t={};for(let n of Up){let r=n[e];if(r)for(let[n,i]of Object.entries(r)){if(Object.hasOwn(t,n))throw Error(`Duplicate ${String(e)} command family entry: ${n}`);t[n]=i}}return t}export{dn as C,un as S,cn as T,k as _,Gp as a,Dn as b,Uo as c,Ti as d,Ei as f,_r as g,hr as h,Jp as i,ao as l,ni as m,qp as n,Wp as o,yi as p,Kp as r,cl as s,Yp as t,wi as u,er as v,sn as w,Cn as x,tr as y};
52
+ `)}return null}function Yf(e,t){return t===`ime`?`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`:e===!0?`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.`}const Xf=`back`,Zf=`orientation`,Qf=`fold`,$f=`keyboard`,ep=`clipboard`,tp=`tv-remote`,np=[`read`,`write`],rp=[`status`,`dismiss`,`enter`,`return`],ip=L(Xf,`Navigate back in the app or through system navigation. Use in-app for the app navigation stack and system when the platform back behavior is required.`,{mode:N(He),...U(Xf)}),ap=L(Zf,`Set device orientation on iOS and Android`,{orientation:O(N(Xt))}),op=L(Qf,`Fold or unfold a foldable iPhone simulator (iPhone Duo) into the closed, half-open, or open pose by pressing the pose control in Xcode Device Hub, then read the hinge angle back from CoreDevice to confirm it. A pose change moves the app to a different panel with a different point size, so every ref and coordinate from before it is stale: re-snapshot after this command. Simulator-only; the device window must be open in Device Hub and the host needs Accessibility permission.`,{pose:O(N(Yt,`The hinge pose to reach: closed lights the outer panel; half-open (Device Hub Book) and open light the inner panel.`))}),sp=L($f,`Inspect Android keyboard visibility/type or press/dismiss the device keyboard. To hide the keyboard, use keyboard dismiss. It taps the keyboard dismiss/hide key when one is exposed, verifies the keyboard closed, and reports UNSUPPORTED_OPERATION when no dismiss key exists — background taps are never attempted.`,{action:N(rp)}),cp=L(ep,`Read the current device clipboard text, or replace its contents with the given text. Android runs both through the clipboard service shell command, and a build that implements none (Android 16 does not) refuses with UNSUPPORTED_OPERATION rather than reporting an empty clipboard.`,{action:O(N(np)),text:k()},{parseableOutput:!0}),lp=L(tp,`Press or long-press a TV remote or D-pad button on Android TV, tvOS, or Vega OS. Choose the button and optional hold duration through the input fields. The aliases ok, center, and enter all map to select.`,{button:O(N(rn)),durationMs:j(`Press duration in milliseconds. tvOS and Vega OS use the exact hold duration; Android TV maps any positive value to an ADB longpress (${nn(`android`)}).`,{min:0})}),up={usageOverride:`back [--in-app|--system] [--settle]`,usageFlags:[],allowedFlags:[`backMode`,...W(Xf)]},dp={usageOverride:`orientation <portrait|portrait-upside-down|landscape-left|landscape-right>`,positionalArgs:[`orientation`]},fp={usageOverride:`fold <${qt}>`,positionalArgs:[`pose`]},pp={usageOverride:`keyboard [status|get|dismiss|enter|return]`,positionalArgs:[`action?`]},mp={usageOverride:`clipboard read | clipboard write <text>`,listUsageOverride:`clipboard read | clipboard write <text>`,positionalArgs:[`read|write`,`text?`],allowsExtraPositionals:!0},hp={usageOverride:`tv-remote [press|longpress] ${en}`,listUsageOverride:`tv-remote press|longpress <button> [--duration-ms <ms>]`,positionalArgs:[`press|longpress?`,`button`],allowedFlags:[`durationMs`]},gp=(e,t)=>({...x(t),mode:t.backMode}),_p=(e,t)=>({...x(t),orientation:Kt(e[0])}),vp=(e,t)=>({...x(t),pose:Jt(e[0])}),yp=(e,t)=>({...x(t),...zp(e)}),bp=(e,t)=>({...x(t),...Bp(e)}),xp=(e,t)=>({...x(t),...Vp(e,t.durationMs)}),Sp=e=>b(Xf,[],{...e,backMode:Lp(e.mode)}),Cp=y(Zf,e=>[D(e.orientation,`orientation requires orientation`)]),wp=y(Qf,e=>[D(e.pose,`fold requires pose`)]),Tp=y($f,e=>w(e.action)),Ep=y(ep,e=>Rp(e)),Dp=y(tp,e=>[D(e.button,`tv-remote requires button`)]),Op=Gr({name:`appstate`,description:`Show foreground app/activity (Android; iOS answers per command)`,text:{summary:`Show the foreground app and activity`},run:(e,t)=>e.command.appState(t),cliOutputFormatter:$.appstate}),kp=R({name:Xf,text:{summary:`Navigate back in the app or system`},metadata:ip,run:(e,t)=>e.command.back(t),cliSchema:up,cliReader:gp,daemonWriter:Sp,cliOutputFormatter:$.back}),Ap=Gr({name:`home`,description:`Send the selected device to its home screen. This leaves the app session open but moves the foreground away from the app.`,text:{summary:`Go to the device home screen`},run:(e,t)=>e.command.home(t),cliOutputFormatter:$.home}),jp=R({name:Zf,text:{summary:`Set device orientation`},metadata:ap,run:(e,t)=>e.command.orientation(t),cliSchema:dp,cliReader:_p,daemonWriter:Cp,cliOutputFormatter:$.orientation}),Mp=R({name:Qf,text:{summary:`Fold or unfold a foldable iPhone simulator`,cliDetail:`iPhone Duo simulators only. Presses the pose control in Xcode Device Hub and confirms the hinge angle through CoreDevice; refs and coordinates do not survive a pose change.`},metadata:op,run:(e,t)=>e.command.fold(t),cliSchema:fp,cliReader:vp,daemonWriter:wp,cliOutputFormatter:$.fold}),Np=Gr({name:`app-switcher`,description:`Open the device app switcher to inspect or change foreground apps. This changes the visible system UI and may move focus away from the current app.`,text:{summary:`Open the device app switcher`},run:(e,t)=>e.command.appSwitcher(t),cliOutputFormatter:$[`app-switcher`]}),Pp=R({name:$f,text:{summary:`Inspect, press, or dismiss the device keyboard`},metadata:sp,run:(e,t)=>e.command.keyboard(t),cliSchema:pp,cliReader:yp,daemonWriter:Tp,cliOutputFormatter:$.keyboard}),Fp=R({name:ep,text:{summary:`Read or write device clipboard text`},metadata:cp,run:(e,t)=>e.command.clipboard(t),cliSchema:mp,cliReader:bp,daemonWriter:Ep,cliOutputFormatter:$.clipboard}),Ip=z({name:`system`,commands:[Op,kp,Ap,jp,Mp,Np,Gr({name:`action-button`,description:`Press the iPhone or iPad Action Button once. The press is dispatched without activating the session app and nothing is re-observed afterwards, so the app keeps the state the press found. What the system does with the press is not observed by this command: Simulators run no Shortcuts or App Intents, so delivery to an assigned Shortcut is verifiable only on a physical iPhone.`,text:{summary:`Press the iPhone or iPad Action Button`,cliDetail:`iPhone and iPad only. The runner asks the device for the button and reports unsupported when that model has none.`},run:(e,t)=>e.command.actionButton(t),cliOutputFormatter:$[`action-button`]}),Pp,Fp,R({name:tp,text:{summary:`Press a TV remote/D-pad button`,cliDetail:`longpress holds for 500ms by default; --duration-ms overrides the preset.`},metadata:lp,run:(e,t)=>e.command.tvRemote(t),cliSchema:hp,cliReader:xp,daemonWriter:Dp,cliOutputFormatter:$[`tv-remote`]})]});function Lp(e){return e===`in-app`||e===`system`?e:void 0}function Rp(e){return e.action===`read`?[`read`]:[`write`,e.text]}function zp(t){if(t.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one action argument.`);return _({action:Hp(t[0])})}function Bp(t){let n=t[0]?.toLowerCase();if(n!==`read`&&n!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write.`);if(n===`read`){if(t.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments.`);return{action:n}}if(t.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text.`);return{action:n,text:t.slice(1).join(` `)}}function Vp(t,n){let r=t[0]?.toLowerCase(),i=r===`press`||r===`longpress`?t.slice(1):t;if(i.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button: ${rn.join(`, `)}.`);let a=n??(r===`longpress`?500:void 0);return _({button:tn(i[0]),durationMs:a})}function Hp(t){let n=t?.toLowerCase();if(n===`get`)return`status`;if(n===void 0||n===`status`||n===`dismiss`||n===`enter`||n===`return`)return n;throw new e(`INVALID_ARGS`,`keyboard action must be status, get, dismiss, enter, or return.`)}const Up=[Gs,Zl,Io,Ip,Yd,zf,Ju,Rd,Vo,mf,tu,pi];function Wp(){return Up.flatMap(e=>[...e.metadata])}function Gp(){return Up.flatMap(e=>[...e.definitions])}function Kp(){return Xp(`cliSchemas`)}function qp(){return Xp(`cliReaders`)}function Jp(){return Xp(`daemonWriters`)}function Yp(){return Xp(`cliOutputFormatters`)}function Xp(e){let t={};for(let n of Up){let r=n[e];if(r)for(let[n,i]of Object.entries(r)){if(Object.hasOwn(t,n))throw Error(`Duplicate ${String(e)} command family entry: ${n}`);t[n]=i}}return t}export{fn as C,dn as S,ln as T,ur as _,Gp as a,On as b,Go as c,Di as d,Oi as f,hr as g,pr as h,Jp as i,so as l,ii as m,qp as n,Wp as o,xi as p,Kp as r,ll as s,Yp as t,Ei as u,tr as v,cn as w,wn as x,nr as y};