agent-device 0.21.22 → 0.21.24

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 (273) hide show
  1. package/README.md +6 -6
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.22.apk → agent-device-android-ime-helper-0.21.24.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.24.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.22.manifest.json → agent-device-android-ime-helper-0.21.24.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.22.manifest.json → agent-device-android-snapshot-helper-0.21.24.manifest.json} +6 -6
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +12 -6
  9. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/RectResponseTests.swift +21 -0
  10. package/apple/snapshot-bridge/README.md +9 -7
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +56 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +14 -5
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +12 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +1 -1
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +29 -5
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +34 -10
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +19 -5
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +3 -3
  20. package/dist/src/adapter.js +1 -1
  21. package/dist/src/adb.js +1 -1
  22. package/dist/src/agent-browser-lifecycle.js +1 -1
  23. package/dist/src/agent-browser-process-record.js +1 -1
  24. package/dist/src/agent-browser-provider.js +1 -1
  25. package/dist/src/agent-device-client.js +2 -2
  26. package/dist/src/alert-runtime.js +1 -1
  27. package/dist/src/alert.js +1 -1
  28. package/dist/src/android-adb.d.ts +3 -2
  29. package/dist/src/android-input-ownership.js +1 -1
  30. package/dist/src/app-backend.js +1 -1
  31. package/dist/src/app-inventory.d.ts +4 -0
  32. package/dist/src/app-launch.js +1 -1
  33. package/dist/src/app-lifecycle.js +1 -1
  34. package/dist/src/app-log-reconnect.js +1 -1
  35. package/dist/src/app-log-runtime2.js +3 -3
  36. package/dist/src/app-resolution.js +2 -2
  37. package/dist/src/app-state-runtime.d.ts +15 -0
  38. package/dist/src/apple-runner-platform.js +1 -1
  39. package/dist/src/application-lifecycle-interaction.js +1 -1
  40. package/dist/src/aws-device-farm-connection.js +1 -0
  41. package/dist/src/back-mode.js +1 -1
  42. package/dist/src/backend-snapshot-options.js +1 -1
  43. package/dist/src/browserstack-connection.js +1 -0
  44. package/dist/src/browserstack-device-features.js +1 -0
  45. package/dist/src/browserstack.js +1 -0
  46. package/dist/src/cache.js +1 -1
  47. package/dist/src/cli-config.js +1 -1
  48. package/dist/src/cli-help.js +35 -19
  49. package/dist/src/cli-runner.js +1 -1
  50. package/dist/src/cli.js +3 -4
  51. package/dist/src/client-companion-tunnel.js +1 -0
  52. package/dist/src/client-metro-companion.js +1 -1
  53. package/dist/src/client-metro.js +1 -1
  54. package/dist/src/client-options.js +3 -3
  55. package/dist/src/client-types.d.ts +7 -5
  56. package/dist/src/cloud-artifacts.d.ts +9 -2
  57. package/dist/src/code-signature-cache.js +1 -1
  58. package/dist/src/command-metadata.js +1 -1
  59. package/dist/src/command-schema.js +1 -1
  60. package/dist/src/command-tools.js +2 -2
  61. package/dist/src/connection-runtime.js +1 -1
  62. package/dist/src/connection-verification.js +1 -0
  63. package/dist/src/connection.js +5 -5
  64. package/dist/src/contracts.d.ts +1 -1
  65. package/dist/src/daemon-client-lease-beat.js +1 -1
  66. package/dist/src/daemon-client-lifecycle.js +1 -1
  67. package/dist/src/daemon-client-transport.js +1 -1
  68. package/dist/src/daemon-http.js +1 -1
  69. package/dist/src/daemon-policy-file.js +1 -1
  70. package/dist/src/daemon-registration-owner.js +1 -1
  71. package/dist/src/device-claim-inspection.js +1 -1
  72. package/dist/src/device-input-state.d.ts +2 -15
  73. package/dist/src/device-readiness-runtime.js +1 -1
  74. package/dist/src/device-selection-resolver.js +1 -1
  75. package/dist/src/device-session.js +3 -1
  76. package/dist/src/device.js +1 -1
  77. package/dist/src/device2.js +1 -1
  78. package/dist/src/device3.js +1 -1
  79. package/dist/src/dispatch-resolve.js +3 -3
  80. package/dist/src/doctor-facade.js +1 -1
  81. package/dist/src/durable-capture-resource.js +1 -1
  82. package/dist/src/durable-resource.js +1 -1
  83. package/dist/src/exec.js +1 -1
  84. package/dist/src/file.js +1 -1
  85. package/dist/src/find.js +1 -1
  86. package/dist/src/finders.js +1 -1
  87. package/dist/src/format.js +2 -1
  88. package/dist/src/gesture-admission.js +1 -1
  89. package/dist/src/gesture-plan-types.d.ts +2 -5
  90. package/dist/src/gesture-runtime.js +1 -1
  91. package/dist/src/helper.js +2 -2
  92. package/dist/src/human-control.js +1 -1
  93. package/dist/src/ime-rebind.js +1 -0
  94. package/dist/src/ime-settings-record.js +1 -0
  95. package/dist/src/ime-state.js +1 -0
  96. package/dist/src/index.d.ts +3 -3
  97. package/dist/src/input-actions.js +1 -1
  98. package/dist/src/input-actions2.js +1 -1
  99. package/dist/src/install-source2.js +1 -1
  100. package/dist/src/instance-client.js +1 -1
  101. package/dist/src/interaction-positionals.js +1 -1
  102. package/dist/src/interaction-ref-policy.js +1 -1
  103. package/dist/src/interaction.js +1 -1
  104. package/dist/src/interaction2.js +1 -1
  105. package/dist/src/interactor.js +5 -5
  106. package/dist/src/interactors.js +1 -1
  107. package/dist/src/internal/bin.js +1 -1
  108. package/dist/src/internal/daemon.js +1 -1
  109. package/dist/src/inventory2.js +1 -1
  110. package/dist/src/ios-client.js +4 -4
  111. package/dist/src/ios-snapshot-acquisition.js +1 -1
  112. package/dist/src/ios-snapshot-engine.js +1 -1
  113. package/dist/src/ios-snapshot-runtime.js +1 -1
  114. package/dist/src/launch-confirmation.js +1 -1
  115. package/dist/src/lease-scope.js +1 -1
  116. package/dist/src/lease.js +1 -1
  117. package/dist/src/limrun.d.ts +4 -555
  118. package/dist/src/load.js +1 -1
  119. package/dist/src/local-interactor-operation-set.js +1 -1
  120. package/dist/src/log-stream.js +33 -0
  121. package/dist/src/managed-device-scope.js +1 -1
  122. package/dist/src/manifest.js +1 -0
  123. package/dist/src/mechanics.js +16 -16
  124. package/dist/src/mobile-snapshot-semantics.js +1 -1
  125. package/dist/src/node-http.js +1 -0
  126. package/dist/src/observation.js +1 -2
  127. package/dist/src/overlay.js +3 -3
  128. package/dist/src/owner-identity.js +3 -3
  129. package/dist/src/perf-facade.js +1 -1
  130. package/dist/src/perf-runtime-plan.js +1 -1
  131. package/dist/src/perf-target.js +1 -1
  132. package/dist/src/physical-device-control.js +1 -1
  133. package/dist/src/platform-request-scope.js +1 -1
  134. package/dist/src/platform-runtime-app-log-process.js +1 -1
  135. package/dist/src/platform-runtime-open-target.js +1 -1
  136. package/dist/src/platform-runtime-operation-host.js +4 -4
  137. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  138. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  139. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  140. package/dist/src/platform-runtime-unavailable.js +1 -1
  141. package/dist/src/platform-runtime.js +1 -1
  142. package/dist/src/platform-runtime2.js +1 -1
  143. package/dist/src/plugin.js +1 -0
  144. package/dist/src/plugins/webdriver.d.ts +111 -0
  145. package/dist/src/plugins/webdriver.js +1 -0
  146. package/dist/src/plugins.d.ts +2 -1
  147. package/dist/src/plugins2.js +1 -1
  148. package/dist/src/process-exit.js +1 -1
  149. package/dist/src/process.js +1 -1
  150. package/dist/src/provider-credential-fingerprint.js +1 -1
  151. package/dist/src/provider-device-admission.js +1 -1
  152. package/dist/src/provider-device-runtime.d.ts +556 -0
  153. package/dist/src/provider-policy.js +1 -0
  154. package/dist/src/provider-profile-fields.js +1 -1
  155. package/dist/src/provider-webdriver.js +1 -2
  156. package/dist/src/providers.js +1 -1
  157. package/dist/src/proxy.js +2 -2
  158. package/dist/src/react-devtools.js +2 -0
  159. package/dist/src/react-native.js +1 -1
  160. package/dist/src/record-runtime.js +1 -1
  161. package/dist/src/record-trace.js +1 -1
  162. package/dist/src/recording.js +1 -1
  163. package/dist/src/registry.js +24 -24
  164. package/dist/src/remote-bridge.js +1 -0
  165. package/dist/src/remote-config-core.js +1 -0
  166. package/dist/src/remote-config.js +1 -1
  167. package/dist/src/remote-config2.js +1 -1
  168. package/dist/src/remote-connection-state.js +1 -0
  169. package/dist/src/replay.js +2 -2
  170. package/dist/src/request-admission.js +1 -1
  171. package/dist/src/request-runtime-binding.js +1 -1
  172. package/dist/src/result-serialization.js +1 -1
  173. package/dist/src/retry.js +1 -1
  174. package/dist/src/retry2.js +1 -0
  175. package/dist/src/runner-artifact-manifest.js +1 -1
  176. package/dist/src/runner-cache-metadata.js +2 -3
  177. package/dist/src/runner-cache-retention.js +1 -0
  178. package/dist/src/runner-cache-trim.js +1 -0
  179. package/dist/src/runner-client.js +1 -1
  180. package/dist/src/runner-dev-tools-security.js +1 -1
  181. package/dist/src/runner-device-readiness.js +1 -1
  182. package/dist/src/runner-device-set.js +1 -0
  183. package/dist/src/runner-disposal.js +1 -1
  184. package/dist/src/runner-error-classification.js +1 -1
  185. package/dist/src/runner-exchange.js +1 -1
  186. package/dist/src/runner-lease.js +1 -0
  187. package/dist/src/runner-operations-facade.js +1 -1
  188. package/dist/src/runner-session-types.js +1 -1
  189. package/dist/src/runner-start-budget.js +1 -1
  190. package/dist/src/runner-toolchain-probe.js +2 -0
  191. package/dist/src/runner.js +1 -1
  192. package/dist/src/runtime-deployment.js +1 -0
  193. package/dist/src/runtime.js +1 -1
  194. package/dist/src/runtime10.js +1 -2
  195. package/dist/src/runtime11.js +2 -0
  196. package/dist/src/runtime2.js +2 -5
  197. package/dist/src/runtime3.js +5 -1
  198. package/dist/src/runtime4.js +1 -5
  199. package/dist/src/runtime5.js +5 -1
  200. package/dist/src/runtime6.js +1 -1
  201. package/dist/src/runtime7.js +1 -1
  202. package/dist/src/runtime8.js +1 -1
  203. package/dist/src/runtime9.js +1 -1
  204. package/dist/src/screen-recording-transport.js +1 -1
  205. package/dist/src/screenshot-density.js +1 -1
  206. package/dist/src/screenshot-overlay-draw.js +1 -1
  207. package/dist/src/screenshot3.js +2 -2
  208. package/dist/src/script.js +1 -1
  209. package/dist/src/scroll-gesture.js +1 -1
  210. package/dist/src/sdk-batch.js +2 -2
  211. package/dist/src/sdk-contracts.d.ts +25 -33
  212. package/dist/src/sdk-contracts.js +2 -2
  213. package/dist/src/sdk-device.js +1 -1
  214. package/dist/src/sdk-finders.d.ts +1 -1
  215. package/dist/src/sdk-finders.js +1 -1
  216. package/dist/src/sdk-remote-config.d.ts +4 -0
  217. package/dist/src/sdk-remote-config.js +1 -1
  218. package/dist/src/sdk-selectors.d.ts +1 -1
  219. package/dist/src/sdk-selectors.js +1 -1
  220. package/dist/src/selection.js +0 -0
  221. package/dist/src/selector-pipeline-policy.js +1 -1
  222. package/dist/src/selector-runtime.js +1 -1
  223. package/dist/src/selectors.js +1 -1
  224. package/dist/src/server.js +2 -2
  225. package/dist/src/session-snapshot.js +1 -1
  226. package/dist/src/session2.js +5 -5
  227. package/dist/src/simctl.js +1 -1
  228. package/dist/src/simulator-boot.js +1 -1
  229. package/dist/src/simulator-state.js +1 -1
  230. package/dist/src/simulator.js +1 -1
  231. package/dist/src/snapshot-capture-annotations.js +1 -1
  232. package/dist/src/snapshot-desktop-projection.js +1 -1
  233. package/dist/src/snapshot-private-evidence.js +1 -0
  234. package/dist/src/snapshot-runtime-binding.js +1 -1
  235. package/dist/src/snapshot-runtime.js +1 -1
  236. package/dist/src/snapshot-state.js +1 -1
  237. package/dist/src/snapshot4.js +1 -1
  238. package/dist/src/src2.js +1 -1
  239. package/dist/src/src3.js +1 -1
  240. package/dist/src/src4.js +1 -1
  241. package/dist/src/src5.js +1 -1
  242. package/dist/src/src6.js +1 -1
  243. package/dist/src/src7.js +1 -1
  244. package/dist/src/src8.js +20 -20
  245. package/dist/src/store.js +1 -1
  246. package/dist/src/target-evidence.js +1 -1
  247. package/dist/src/text-entry-focus.js +1 -1
  248. package/dist/src/tool-provider2.js +1 -1
  249. package/dist/src/touch-runtime2.js +1 -1
  250. package/dist/src/tree.js +1 -1
  251. package/dist/src/type-text-runtime.js +1 -1
  252. package/dist/src/video.js +1 -1
  253. package/package.json +24 -16
  254. package/server.json +2 -2
  255. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.22.apk.sha256 +0 -1
  256. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk +0 -0
  257. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk.sha256 +0 -1
  258. package/dist/src/capabilities.js +0 -1
  259. package/dist/src/compatibility-policy.js +0 -1
  260. package/dist/src/daemon-artifacts.js +0 -1
  261. package/dist/src/device-claim-rule.js +0 -1
  262. package/dist/src/human-control-contract.js +0 -1
  263. package/dist/src/prepare-kind.js +0 -1
  264. package/dist/src/provider-device-runtimes.js +0 -1
  265. package/dist/src/screen-recording-admission-ledger.js +0 -1
  266. package/dist/src/screenshot-runtime.js +0 -1
  267. package/dist/src/session-routing.js +0 -1
  268. package/dist/src/session-runtime-admission.js +0 -1
  269. package/dist/src/session-stream.js +0 -27
  270. package/dist/src/timeouts.js +0 -1
  271. package/dist/src/touch-reference-frame.js +0 -1
  272. package/dist/src/vars.js +0 -2
  273. package/dist/src/viewport.js +0 -1
@@ -0,0 +1,2 @@
1
+ import{H as e,I as t,K as n,P as r}from"./sdk-contracts.js";import{i}from"./recording-export-quality.js";import{C as a,E as o,O as s,T as c,a as l,b as u,i as d,o as f,r as p,t as ee,w as te,x as m,y as h}from"./runtime.js";import{r as g}from"./success-text.js";import{n as ne,t as re}from"./app-inventory.js";import"./app-inventory-contract.js";import{j as ie}from"./owner-identity.js";import{l as ae}from"./exec.js";import"./file.js";import{r as oe}from"./tv-remote.js";import"./command.js";import{r as se}from"./version.js";import{t as ce}from"./keyboard-actions.js";import{i as le}from"./quality-warnings.js";import{r as _}from"./png.js";import{i as ue}from"./png-worker-client.js";import{t as de}from"./png-size.js";import{i as v,n as fe,r as pe}from"./screenshot-overlay-draw.js";import{t as me}from"./png-encode.js";import{r as y}from"./artifact-paths.js";import{t as he}from"./mp4-duration.js";import{c as b,o as ge,r as _e,s as ve}from"./video.js";import x from"node:fs";import ye from"node:os";import S from"node:path";function C(e,t){if(e!==void 0)return w(e,t)}function w(e,t){let n=e?.trim();if(!n)throw new r(`INVALID_ARGS`,`${t} must be a non-empty string`);return n}const be=async(e,t={})=>{if(!e.backend.listDevices)throw new r(`UNSUPPORTED_OPERATION`,`admin.devices is not supported by this backend`);return{kind:`adminDevices`,devices:await e.backend.listDevices(m(e,t),t.filter)}},xe=async(e,t={})=>{if(!e.backend.bootDevice)throw new r(`UNSUPPORTED_OPERATION`,`admin.boot is not supported by this backend`);let n=ke(t.target),i=await e.backend.bootDevice(m(e,t),n),a=u(i);return{kind:`deviceBooted`,...n?{target:n}:{},...a?{backendResult:a}:{},...g(`Booted device`)}},Se=async(e,t={})=>{if(!e.backend.shutdownDevice)throw new r(`UNSUPPORTED_OPERATION`,`admin.shutdown is not supported by this backend`);let n=ke(t.target),i=await e.backend.shutdownDevice(m(e,t),n),a=u(i);return{kind:`deviceShutdown`,...n?{target:n}:{},...a?{backendResult:a}:{},...g(`Shutdown device`)}},Ce=async(e,t)=>await T(e,t,`install`),we=async(e,t)=>await T(e,t,`reinstall`),Te=async(e,t)=>await T(e,t,`installFromSource`);async function T(e,t,n){let i=n===`reinstall`?`reinstallApp`:`installApp`,a=e.backend[i];if(!a)throw new r(`UNSUPPORTED_OPERATION`,`admin.${n} is not supported by this backend`);let o=`app`in t&&t.app!==void 0?w(t.app,`app`):void 0;if(n!==`installFromSource`&&!o)throw new r(`INVALID_ARGS`,`admin.${n} requires app`);let s=m(e,t),c=await Ee(e,s,t.source);try{let t=await a.call(e.backend,s,{...o?{app:o}:{},source:c.source});return Ae(n,o,c.source,t)}finally{await c.cleanup?.()}}async function Ee(e,t,n){let r=await De(e,E(n));try{return{source:E(e.backend.resolveInstallSource?await e.backend.resolveInstallSource(t,r.source):r.source),...r.cleanup?{cleanup:r.cleanup}:{}}}catch(e){if(r.cleanup)try{await r.cleanup()}catch{}throw e}}async function De(e,t){if(t.kind===`url`)return{source:t};let n=await d(e,t,{usage:`admin.install`,field:`source`});return{source:{kind:`path`,path:n.path},...n.cleanup?{cleanup:n.cleanup}:{}}}function E(e){if(!e||typeof e!=`object`)throw new r(`INVALID_ARGS`,`install source is required`);if(e.kind===`path`)return{kind:`path`,path:w(e.path,`source.path`)};if(e.kind===`uploadedArtifact`)return{kind:`uploadedArtifact`,id:w(e.id,`source.id`)};if(e.kind===`url`){let t=w(e.url,`source.url`);return Oe(t),{kind:`url`,url:t}}throw new r(`INVALID_ARGS`,`install source kind must be path, uploadedArtifact, or url`)}function Oe(e){let t;try{t=new URL(e)}catch{throw new r(`INVALID_ARGS`,`Invalid install source URL: ${e}`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new r(`INVALID_ARGS`,`Install source URL must use http or https`)}function ke(e){if(!e)return;let t=C(e.id,`target.id`),n=C(e.name,`target.name`),r={...t?{id:t}:{},...n?{name:n}:{},...e.platform?{platform:e.platform}:{},...e.target?{target:e.target}:{},...e.headless===void 0?{}:{headless:e.headless}};return Object.keys(r).length>0?r:void 0}function Ae(e,t,n,r){let i=u(r),a=e===`reinstall`?`appReinstalled`:e===`installFromSource`?`appInstalledFromSource`:`appInstalled`,o=D(r,`appName`),s=D(r,`appId`),c=D(r,`bundleId`),l=D(r,`packageName`),d=D(r,`launchTarget`),f=D(r,`installablePath`),p=D(r,`archivePath`);return{kind:a,...t?{app:t}:{},source:n,...s?{appId:s}:{},...o?{appName:o}:{},...c?{bundleId:c}:{},...l?{packageName:l}:{},...d?{launchTarget:d}:{},...f?{installablePath:f}:{},...p?{archivePath:p}:{},...i?{backendResult:i}:{},...g(`${e===`reinstall`?`Reinstalled`:`Installed`}: ${o??d??t??je(n)}`)}}function D(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function je(e){return e.kind===`path`?e.path:e.kind===`uploadedArtifact`?e.id:e.url}const Me=/^[A-Za-z0-9_.:-]{1,64}$/,Ne=async(e,t)=>{if(!e.backend.openApp)throw new r(`UNSUPPORTED_OPERATION`,`apps.open is not supported by this backend`);let n=ze(t),i=await e.backend.openApp(k(e,t),n,{launchArgs:t.launchArgs,relaunch:t.relaunch}),a=u(i);return{kind:`appOpened`,target:n,relaunch:t.relaunch===!0,...a?{backendResult:a}:{},...g(`Opened: ${Ve(n)}`)}},Pe=async(e,t={})=>{if(!e.backend.closeApp)throw new r(`UNSUPPORTED_OPERATION`,`apps.close is not supported by this backend`);let n=C(t.app,`app`),i=await e.backend.closeApp(k(e,t),n),a=u(i);return{kind:`appClosed`,...n?{app:n}:{},...a?{backendResult:a}:{},...g(n?`Closed: ${n}`:`Closed app`)}},Fe=async(e,t={})=>{if(!e.backend.listApps)throw new r(`UNSUPPORTED_OPERATION`,`apps.list is not supported by this backend`);return{kind:`appsList`,apps:await e.backend.listApps(k(e,t),re(t.filter))}},Ie=async(e,t)=>{if(!e.backend.getAppState)throw new r(`UNSUPPORTED_OPERATION`,`apps.state is not supported by this backend`);let n=w(t.app,`app`);return{kind:`appState`,app:n,state:await e.backend.getAppState(k(e,t),n)}},Le=async(e,t)=>{if(!e.backend.pushFile)throw new r(`UNSUPPORTED_OPERATION`,`apps.push is not supported by this backend`);let n=w(t.app,`app`),i=await He(e,t.input);try{let r=await e.backend.pushFile(k(e,t),i.backendInput,n),a=u(r);return{kind:`appPushed`,app:n,inputKind:i.inputKind,...a?{backendResult:a}:{},...g(`Pushed to ${n}`)}}finally{await i.cleanup?.()}},Re=async(e,t)=>{if(!e.backend.triggerAppEvent)throw new r(`UNSUPPORTED_OPERATION`,`apps.triggerEvent is not supported by this backend`);let n=Ue(t.name);We(t.payload,`apps.triggerEvent payload for "${n}"`);let i=await e.backend.triggerAppEvent(k(e,t),{name:n,...t.payload?{payload:t.payload}:{}}),a=u(i);return{kind:`appEventTriggered`,name:n,...t.payload?{payload:t.payload}:{},...a?{backendResult:a}:{},...g(`Triggered app event: ${n}`)}};function ze(e){let t=C(e.app,`app`),n=C(e.appId,`appId`),i=C(e.bundleId,`bundleId`),a=C(e.packageName,`packageName`),o=C(e.url,`url`),s=C(e.activity,`activity`),c={...t?{app:t}:{},...n?{appId:n}:{},...i?{bundleId:i}:{},...a?{packageName:a}:{},...o?{url:o}:{},...s?{activity:s}:{}};if(!Be(c))throw new r(`INVALID_ARGS`,`apps.open requires app, appId, bundleId, packageName, url, or activity`);return c}function Be(e){return!!(e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity)}function Ve(e){return e.app??e.appId??e.bundleId??e.packageName??e.url??e.activity??`app`}async function He(e,t){if(!t||typeof t!=`object`)throw new r(`INVALID_ARGS`,`apps.push requires an input`);if(t.kind===`json`)return O(t.payload,`apps.push JSON payload`,8192),{backendInput:{kind:`json`,payload:t.payload},inputKind:`json`};let n=await d(e,t,{usage:`apps.push`,field:`input`});return{backendInput:{kind:`file`,path:n.path},inputKind:`file`,...n.cleanup?{cleanup:n.cleanup}:{}}}function Ue(e){let t=w(e,`name`);if(!Me.test(t))throw new r(`INVALID_ARGS`,`Invalid apps.triggerEvent name: ${t}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});return t}function We(e,t){e!==void 0&&O(e,t,8192)}function O(e,t,n){if(Ge(e,t),Buffer.byteLength(Ke(e,t),`utf8`)>n)throw new r(`INVALID_ARGS`,`${t} exceeds ${n} bytes`)}function Ge(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new r(`INVALID_ARGS`,`${t} must be a JSON object`)}function Ke(e,t){try{let n=JSON.stringify(e);if(typeof n!=`string`)throw new r(`INVALID_ARGS`,`${t} must be JSON-serializable`);return n}catch{throw new r(`INVALID_ARGS`,`${t} must be JSON-serializable`)}}function k(e,t){return{session:t.session,requestId:t.requestId,signal:t.signal??e.signal,metadata:t.metadata}}const A={open:Ne,close:Pe,list:Fe,state:Ie,push:Le,triggerEvent:Re},qe={devices:be,boot:xe,shutdown:Se,install:Ce,reinstall:we,installFromSource:Te};function Je(e){return{...h(A,e),list:(t={})=>A.list(e,{...t,filter:ne(t.filter)})}}const Ye=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,Xe=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function j(e){let t=!1,n=e;return n=n.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,n)=>(t=!0,`${String(n)}=[REDACTED]`)),n=n.replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,n,r,i)=>(t=!0,`${String(n)}[REDACTED]${String(i)}`)),n=n.replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,n)=>(t=!0,`${String(n)}[REDACTED]`)),n=n.replaceAll(Xe,()=>(t=!0,`[REDACTED]`)),n=Qe(n,()=>{t=!0}),{value:n,redacted:t}}function Ze(e){try{let t=new URL(e),n=$e(t);return(t.username||t.password)&&(t.username=`REDACTED`,t.password=`REDACTED`,n=!0),{value:t.toString(),redacted:n}}catch{return}}function Qe(e,t){return/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(e)?e.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let n=Ze(e);return n?(n.redacted&&t(),n.value):e}):e}function $e(e){let t=!1;for(let n of Array.from(e.searchParams.keys()))Ye.test(n)&&(e.searchParams.set(n,`[REDACTED]`),t=!0);return t}const M=2048,N=4096,P=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i;function et(e){let t=e.redacted===!0;return{kind:`diagnosticsLogs`,entries:e.entries.map(e=>{let n=z(e.message,N),r=L(e.metadata);return t||=n.redacted||r.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.level?{level:e.level}:{},message:n.value??``,...e.source?{source:e.source}:{},...r.value?{metadata:r.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function tt(e,t){let n=e.redacted===!0;return{kind:`diagnosticsNetwork`,entries:e.entries.map(e=>{let r=e.url?rt(e.url):void 0,i=t===`headers`||t===`all`?F(e.requestHeaders):void 0,a=t===`headers`||t===`all`?F(e.responseHeaders):void 0,o=t===`body`||t===`all`?I(e.requestBody):void 0,s=t===`body`||t===`all`?I(e.responseBody):void 0,c=L(e.metadata);return n||=(r?.redacted??!1)||(i?.redacted??!1)||(a?.redacted??!1)||(o?.redacted??!1)||(s?.redacted??!1)||c.redacted,{...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...r?{url:r.value}:{},...e.status===void 0?{}:{status:e.status},...e.durationMs===void 0?{}:{durationMs:e.durationMs},...i?.value?{requestHeaders:i.value}:{},...a?.value?{responseHeaders:a.value}:{},...o?.value===void 0?{}:{requestBody:o.value},...s?.value===void 0?{}:{responseBody:s.value},...c.value?{metadata:c.value}:{}}}),...e.nextCursor?{nextCursor:e.nextCursor}:{},...e.timeWindow?{timeWindow:e.timeWindow}:{},...e.backend?{backend:e.backend}:{},redacted:n,...e.notes?{notes:e.notes}:{}}}function nt(e){let t=e.redacted===!0;return{kind:`diagnosticsPerf`,metrics:e.metrics.map(e=>{let n=z(e.message,N),r=L(e.metadata);return t||=n.redacted||r.redacted,{name:e.name,...e.value===void 0?{}:{value:e.value},...e.unit?{unit:e.unit}:{},...e.status?{status:e.status}:{},...n.value===void 0?{}:{message:n.value},...r.value?{metadata:r.value}:{}}}),...e.startedAt?{startedAt:e.startedAt}:{},...e.endedAt?{endedAt:e.endedAt}:{},...e.backend?{backend:e.backend}:{},redacted:t,...e.notes?{notes:e.notes}:{}}}function F(e){if(!e)return{redacted:!1};let t=!1,n={};for(let[r,i]of Object.entries(e))if(P.test(r))n[r]=`[REDACTED]`,t=!0;else{let e=z(i,M);n[r]=e.value??``,t||=e.redacted}return{value:n,redacted:t}}function rt(e){return Ze(e)??z(e,M)}function I(e){return e===void 0?{redacted:!1}:it(e)??z(e,M)}function it(e){try{let t=R(JSON.parse(e),j);return B(JSON.stringify(t.value),M,t.redacted)}catch{return}}function L(e){return R(e,e=>z(e,M))}function R(e,t){if(e===void 0)return{redacted:!1};if(typeof e==`string`)return t(e);if(!e||typeof e!=`object`)return{value:e,redacted:!1};if(Array.isArray(e)){let n=!1;return{value:e.map(e=>{let r=R(e,t);return n||=r.redacted,r.value}),redacted:n}}let n=!1,r={};for(let[i,a]of Object.entries(e)){if(P.test(i)){r[i]=`[REDACTED]`,n=!0;continue}let e=R(a,t);r[i]=e.value,n||=e.redacted}return{value:r,redacted:n}}function z(e,t){if(e===void 0)return{redacted:!1};let n=j(e);return B(n.value,t,n.redacted)}function B(e,t,n){if(e===void 0)return{redacted:n};let r=e;return r.length>t&&(r=`${r.slice(0,t)}...[truncated]`,n=!0),{value:r,redacted:n}}const at=async(e,t={})=>{if(!e.backend.readLogs)throw new r(`UNSUPPORTED_OPERATION`,`diagnostics.logs is not supported by this backend`);return et(await e.backend.readLogs(await V(e,t),ct(t)))},ot=async(e,t={})=>{if(!e.backend.dumpNetwork)throw new r(`UNSUPPORTED_OPERATION`,`diagnostics.network is not supported by this backend`);let n=lt(t);return tt(await e.backend.dumpNetwork(await V(e,t),n),n.include??`summary`)},st=async(e,t={})=>{if(!e.backend.measurePerf)throw new r(`UNSUPPORTED_OPERATION`,`diagnostics.perf is not supported by this backend`);return nt(await e.backend.measurePerf(await V(e,t),ut(t)))};async function V(e,t){let n=m(e,t),r=t.session?await e.sessions.get(t.session):void 0;return{...n,...t.appId??r?.appId?{appId:t.appId??r?.appId}:{},...t.appBundleId??r?.appBundleId?{appBundleId:t.appBundleId??r?.appBundleId}:{}}}function ct(e){return{...H(e,100,500,`logs limit`),...e.levels===void 0?{}:{levels:W(e.levels,`levels`)},...e.search===void 0?{}:{search:w(e.search,`search`)},...e.source===void 0?{}:{source:w(e.source,`source`)}}}function lt(e){return{...H(e,25,200,`network limit`),include:dt(e.include)}}function ut(e){return{...U(e),...e.sampleMs===void 0?{}:{sampleMs:s(e.sampleMs,`sampleMs`,100,6e4)},...e.metrics===void 0?{}:{metrics:W(e.metrics,`metrics`,20)}}}function H(e,t,n,r){return{...U(e),...e.cursor===void 0?{}:{cursor:w(e.cursor,`cursor`)},limit:e.limit===void 0?t:s(e.limit,r,1,n)}}function U(e){return{...e.since===void 0?{}:{since:w(e.since,`since`)},...e.until===void 0?{}:{until:w(e.until,`until`)}}}function dt(e){if(e===void 0)return`summary`;if(e===`summary`||e===`headers`||e===`body`||e===`all`)return e;throw new r(`INVALID_ARGS`,`network include must be summary, headers, body, or all`)}function W(e,t,n=50){if(!Array.isArray(e))throw new r(`INVALID_ARGS`,`${t} must be an array of strings`);if(e.length>n)throw new r(`INVALID_ARGS`,`${t} must contain at most ${n} entries`);return e.map((e,n)=>w(e,`${t}[${n}]`))}const ft={logs:at,network:ot,perf:st},G=`contact_sheet_frame_extraction_failed`,K=`contact_sheet_no_frames`;function q(e=process.platform){if(e!==`darwin`)throw new r(`UNSUPPORTED_OPERATION`,`Contact sheets can only be built on macOS hosts, which is where the frame decoder runs`,{reason:`contact_sheet_unsupported_host`,hostPlatform:e,hint:`Run this command on the macOS host that recorded the clip, or read the video artifact itself.`})}async function pt(e){if(q(e.hostPlatform??process.platform),e.timesMs.length===0)throw new r(`COMMAND_FAILED`,`Contact sheet sampling requested no frames`,{reason:K,videoPath:e.videoPath});Q(e.signal);let t=await vt(e);Q(e.signal);let n;try{n=await ae(t,[`--input`,e.videoPath,`--output-dir`,e.scratchDir,`--times`,e.timesMs.join(`,`),`--max-width`,String(e.maxWidth)],{timeoutMs:9e4,env:ge(),allowFailure:!0,...e.signal===void 0?{}:{signal:e.signal}})}catch(t){X(t,e.videoPath,`Failed to run the frame decoder`)}if(n.exitCode!==0)throw new r(`COMMAND_FAILED`,`Failed to extract frames from the recording: ${_t(n.stderr)||`exit ${n.exitCode}`}`,{reason:G,videoPath:e.videoPath,exitCode:n.exitCode});let i=mt(n.stdout,e.videoPath,e.scratchDir,e.timesMs.length);if(i.frames.length===0)throw new r(`COMMAND_FAILED`,`The recording returned no decodable frames for a contact sheet`,{reason:K,videoPath:e.videoPath,skippedSampleCount:i.skippedSampleCount});return i}function mt(e,t,n,r){let i;try{i=JSON.parse(e)}catch(e){throw Y(t,`invalid manifest: ${String(e)}`)}let a=Z(i).frames;if(!Array.isArray(a))throw Y(t,`manifest has no frames array`);let o=Z(i).skipped;if(a.length>r)throw Y(t,`returned ${a.length} frames for ${r} requested samples`);let s=a.flatMap(e=>{let r=Z(e),i=ht(r.path),a=gt(r.actualTimeMs);if(i===void 0||a===void 0||a<0)throw Y(t,`frame entry is missing a path or presentation time`);let o=S.resolve(n,S.basename(i));return x.existsSync(o)?[{requestedTimeMs:gt(r.requestedTimeMs)??a,actualTimeMs:a,path:o}]:[]});return{frames:s.sort((e,t)=>e.actualTimeMs-t.actualTimeMs),skippedSampleCount:Math.max(Array.isArray(o)?o.length:0,r-s.length)}}function J(e,t,n){return new r(`COMMAND_FAILED`,e,{reason:G,videoPath:t},n)}function Y(e,t){return J(`Frame extraction returned an unreadable manifest: ${t}`,e)}function X(t,i,a){throw n(t)||t instanceof r&&t.code===`COMMAND_FAILED`&&t.details?.reason?t:J(`${a} for ${i}: ${e(t)}`,i,t)}function Z(e){return typeof e==`object`&&e?e:{}}function ht(e){return typeof e==`string`&&e!==``?e:void 0}function gt(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function _t(e){return(e.trim().split(`
2
+ `).pop()??``).trim()}async function vt(e){try{return await ve({sourcePath:b(`recording-frames.swift`,se()),extraSourcePaths:[b(`RecordingExportSupport.swift`,se())],cacheName:`recording-frames`,timeoutMs:12e4})}catch(t){X(t,e.videoPath,`Could not build the frame decoder`)}}function Q(e){if(e?.aborted)throw t()}function yt(e,t){if(e===void 0||!Number.isFinite(e)||e<0)throw new r(`COMMAND_FAILED`,`Cannot plan a contact sheet: the video timeline of ${t} could not be read`,{reason:`contact_sheet_duration_unknown`,videoPath:t,hint:`Retry once the recording finished finalizing; a clip whose container is still being written has no readable duration.`});if(e<=250)return{durationMs:e,timesMs:e>0?[0,Math.round(e)]:[0]};let n=Math.min(48,Math.floor(e/250)+1),i=e/(n-1);return{durationMs:e,timesMs:Array.from({length:n},(e,t)=>Math.round(t*i))}}const bt=[360,320,280,240,200,160],xt=[255,255,255,255],St=[17,24,39,255],$=pe(2)+8;function Ct(e){let{cells:t}=e;if(t.length===0)throw new r(`COMMAND_FAILED`,`Contact sheet has no cells to render`);let n=Tt(t[0].image.height/Math.max(1,t[0].image.width),t.length,e),i=Ot(n.width,n.height,St);return t.forEach((e,t)=>{let r=t%n.columns,a=Math.floor(t/n.columns);wt(i,8+r*(n.cellWidth+8),8+a*($+n.cellHeight+8),e,n.cellWidth,n.cellHeight)}),{bytes:me(i.data,n.width,n.height,4),width:n.width,height:n.height,cellWidth:n.cellWidth}}function wt(e,t,n,r,i,a){fe(e,{x:t+4,y:n+4,text:jt(r.timeMs),color:xt,scale:2}),kt(e,le(At(r.image),i,a),t,n+$)}function Tt(e,t,n){let i=Et(e,t,n.maxPixels);if(i)return i;let a=Dt(e,t,160);throw new r(`COMMAND_FAILED`,`Contact sheet would be ${a.width*a.height} pixels, above the configured maxImagePixels limit of ${n.maxPixels}`,{reason:`contact_sheet_pixel_budget_exceeded`,cellCount:n.cells.length,maxPixels:n.maxPixels,hint:`Shorten the recording or raise the command policy maxImagePixels limit.`})}function Et(e,t,n){for(let r of bt){let i=Dt(e,t,r);if(i.width*i.height<=n)return i}}function Dt(e,t,n){let r=Math.min(4,t),i=Math.ceil(t/r),a=Math.max(1,Math.round(n*e));return{columns:r,cellWidth:n,cellHeight:a,width:16+r*n+(r-1)*8,height:16+i*($+a)+(i-1)*8}}function Ot(e,t,n){let r=new _.PNG({width:e,height:t});for(let i=0;i<t;i+=1)for(let t=0;t<e;t+=1)v(r,t,i,n);return r}function kt(e,t,n,r){for(let i=0;i<t.height;i+=1)for(let a=0;a<t.width;a+=1){let o=(i*t.width+a)*4;v(e,n+a,r+i,[t.data[o],t.data[o+1],t.data[o+2],t.data[o+3]])}}function At(e){let t=new _.PNG({width:e.width,height:e.height});return Buffer.from(e.data.buffer,e.data.byteOffset,e.data.byteLength).copy(t.data),t}function jt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=Math.floor(e%1e3);return`${[n,r,i].map(e=>String(e).padStart(2,`0`)).join(`:`)}.${String(a).padStart(3,`0`)}`}function Mt(e,t){if(e.width!==t.width||e.height!==t.height)return{status:`dimension_mismatch`};let n=e.width*e.height;if(n===0)return{status:`compared`,changedPixelRatio:0};if(e.data.length!==t.data.length)return{status:`dimension_mismatch`};let r=0;for(let n=0;n+3<e.data.length;n+=4)(e.data[n]!==t.data[n]||e.data[n+1]!==t.data[n+1]||e.data[n+2]!==t.data[n+2])&&(r+=1);return{status:`compared`,changedPixelRatio:r/n}}function Nt(e,t=.02,n=24){let r=[],i;for(let n of e){let e=i?Ft(i,n.image):1;e<t||(r.push({timeMs:n.timeMs,changedPixelRatio:e,image:n.image}),i=n.image)}Pt(r,e);let a=r.length>n?It(r,n):r;return{cells:a,keptCellCount:r.length,thinned:a.length<r.length}}function Pt(e,t){let n=t.at(-1);if(!n)return;let r=e.at(-1);!r||r.timeMs===n.timeMs||e.push({timeMs:n.timeMs,changedPixelRatio:Ft(r.image,n.image),image:n.image})}function Ft(e,t){let n=Mt(e,t);return n.status===`compared`?n.changedPixelRatio:1}function It(e,t){if(t<=1)return[e.at(-1)];let n=(e.length-1)/(t-1);return Array.from({length:t},(t,r)=>e[Math.round(r*n)])}async function Lt(e){q(e.hostPlatform??process.platform);let t=S.resolve(e.videoPath),n=S.resolve(e.outputPath??y(t));Bt(t,n);let i=await _e(t);if(i!==`mp4`)throw new r(`INVALID_ARGS`,i===`webm`?`Contact sheets need an MP4 recording; ${t} is WebM, whose frames this decoder does not read`:`Contact sheets need an MP4 recording; ${t} is not a readable MP4`,{reason:`contact_sheet_container_unsupported`,videoPath:t,container:i??`unknown`,hint:`Re-record on a backend that exports MP4, or pass the MP4 artifact the recording produced.`});let a=yt(he(t),t),o=x.mkdtempSync(S.join(ye.tmpdir(),`agent-device-contact-sheet-`));try{let r=await pt({videoPath:t,scratchDir:o,timesMs:a.timesMs,maxWidth:360,hostPlatform:e.hostPlatform??process.platform,...e.signal===void 0?{}:{signal:e.signal}}),i=await Rt(r.frames,e.maxPixels);zt(e.signal);let s=Nt(i,e.changedPixelThreshold??.02),c=Ct({cells:s.cells,maxPixels:e.maxPixels});return Gt(n,c.bytes),{path:n,videoPath:t,durationMs:a.durationMs,width:c.width,height:c.height,sampledFrameCount:a.timesMs.length,decodedFrameCount:r.frames.length,skippedSampleCount:r.skippedSampleCount,changedPixelThreshold:e.changedPixelThreshold??.02,cells:s.cells.map(Ut),...Wt(s,r)}}finally{x.rmSync(o,{recursive:!0,force:!0})}}async function Rt(e,t){let n=[];for(let i of e){let e=await de(i.path);if(e.width>360)throw new r(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}px-wide frame when the sheet asked for 360px cells`,{reason:G,framePath:i.path,frameWidth:e.width,frameWidthLimit:360});if(e.width*e.height>t)throw new r(`COMMAND_FAILED`,`Frame extraction returned a ${e.width}x${e.height} frame, above the ${t}-pixel budget for the whole sheet`,{reason:G,framePath:i.path,framePixels:e.width*e.height,maxPixels:t});let a=await ue(x.readFileSync(i.path),`recording frame`);n.push({timeMs:i.actualTimeMs,image:a})}return n}function zt(e){if(e?.aborted)throw t()}function Bt(e,t){if(Vt(e,t)??t===e)throw new r(`INVALID_ARGS`,`A contact sheet cannot be written over the recording it describes: ${t}`,{reason:`contact_sheet_output_collides_with_input`,videoPath:e,outputPath:t,hint:`Choose a different --out path, or omit it to write beside the recording.`})}function Vt(e,t){let n=Ht(e),r=Ht(t);if(n!==void 0&&r!==void 0)return n.dev===r.dev&&n.ino===r.ino}function Ht(e){try{return x.statSync(e)}catch{return}}function Ut(e){return{timeMs:e.timeMs,changedPixelRatio:e.changedPixelRatio}}function Wt(e,t){let n=[];return t.skippedSampleCount>0&&n.push(`${t.skippedSampleCount} sample times returned no frame, so the sheet covers less of the recording than it asked for`),e.thinned&&n.push(`${e.keptCellCount} changes were found and 24 cells are printed, so the sheet thins evenly across the recording instead of showing every change`),n.length===0?{}:{warning:n.join(`; `)}}function Gt(e,t){try{x.mkdirSync(S.dirname(e),{recursive:!0}),ie({destination:e,contents:t})}catch(t){throw new r(`COMMAND_FAILED`,`Failed to write the contact sheet to ${e}: ${t instanceof Error?t.message:String(t)}`,{reason:`contact_sheet_output_write_failed`,outputPath:e})}}const Kt=async(e,t)=>{if(!t.video)throw new r(`INVALID_ARGS`,`record contact-sheet requires a recording to read`);Jt(t.changedPixelThreshold);let n=await d(e,t.video,{usage:`record contact-sheet`,field:`video`}),i;try{let r=qt(t,t.video,n.path);i=await p(e,r,{field:`path`,ext:`.png`,artifactType:`screen-recording-contact-sheet`});let a=await Lt({videoPath:n.path,outputPath:i.path,maxPixels:e.policy.maxImagePixels,...t.changedPixelThreshold===void 0?{}:{changedPixelThreshold:t.changedPixelThreshold},signal:t.signal??e.signal}),o=await i.publish();return{...a,path:Yt(a.path,o),...o?{artifact:o}:{}}}catch(e){throw await i?.cleanup?.(),e}finally{await n.cleanup?.()}};function qt(e,t,n){if(e.out)return e.out;if(t.kind===`path`)return{kind:`path`,path:S.resolve(y(t.path||n))};throw new r(`INVALID_ARGS`,`record contact-sheet needs an output path when the recording is an uploaded artifact`,{hint:"Pass --out <sheet.png> (CLI) or `out` (Node) to name where the sheet is written."})}function Jt(e){if(e!==void 0&&(!Number.isFinite(e)||e<0||e>1))throw new r(`INVALID_ARGS`,`record contact-sheet needs a changedPixelThreshold between 0 and 1, got ${e}`,{reason:`contact_sheet_threshold_invalid`,changedPixelThreshold:e,hint:`Omit it to use the calibrated default, or pass a share of the frame between 0 and 1.`})}function Yt(e,t){return t?t.kind===`localPath`?t.path:t.clientPath??e:e}const Xt=async(e,t)=>{let n=tn(t.action,`record`),i=n===`start`?e.backend.startRecording:e.backend.stopRecording;if(!i)throw new r(`UNSUPPORTED_OPERATION`,`record ${n} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`path`,ext:`.mp4`,artifactType:`screen-recording`}):void 0;try{let r=Qt(t,a?.path);return nn(n,await i.call(e.backend,m(e,t),r),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}},Zt=async(e,t)=>{let n=tn(t.action,`trace`),i=n===`start`?e.backend.startTrace:e.backend.stopTrace;if(!i)throw new r(`UNSUPPORTED_OPERATION`,`trace ${n} is not supported by this backend`);let a=t.out?await p(e,t.out,{field:`outPath`,ext:`.trace`,artifactType:`trace-log`}):void 0;try{let r=a?.path?{outPath:a.path}:{};return rn(n,await i.call(e.backend,m(e,t),r),await a?.publish())}catch(e){throw await a?.cleanup?.(),e}};function Qt(e,t){let n={};t&&(n.outPath=t);let r=$t(e.fps);r!==void 0&&(n.fps=r);let i=en(e.quality);return i!==void 0&&(n.quality=i),e.hideTouches!==void 0&&(n.showTouches=e.hideTouches!==!0),n}function $t(e){return e===void 0?void 0:s(e,`fps`,1,60)}function en(e){if(e===void 0)return;let t=i(e);if(t===void 0)throw new r(`INVALID_ARGS`,`quality must be one of: medium, high (legacy numeric values 5-10 are accepted)`);return t}function tn(e,t){if(e===`start`||e===`stop`)return e;throw new r(`INVALID_ARGS`,`${t} action must be start or stop`)}function nn(e,t,n){return{...typeof t.path==`string`?{path:t.path}:{},...typeof t.telemetryPath==`string`?{telemetryPath:t.telemetryPath}:{},...typeof t.warning==`string`?{warning:t.warning}:{},...an(e,t,n,{startKind:`recordingStarted`,stopKind:`recordingStopped`,startMessage:`Recording started`,stopMessage:`Recording stopped`})}}function rn(e,t,n){return{...typeof t.outPath==`string`?{outPath:t.outPath}:{},...an(e,t,n,{startKind:`traceStarted`,stopKind:`traceStopped`,startMessage:`Trace started`,stopMessage:`Trace stopped`})}}function an(e,t,n,r){return{kind:e===`start`?r.startKind:r.stopKind,action:e,...n?{artifact:n}:{},backendResult:t,...g(e===`start`?r.startMessage:r.stopMessage)}}const on={record:Xt,trace:Zt,contactSheet:Kt},sn=async(e,t={})=>{if(!e.backend.pressBack)throw new r(`UNSUPPORTED_OPERATION`,`system.back is not supported by this backend`);let n=t.mode??`in-app`;if(n!==`in-app`&&n!==`system`)throw new r(`INVALID_ARGS`,`system.back mode must be in-app or system`);let i=await e.backend.pressBack(m(e,t),{mode:n}),a=u(i);return{kind:`systemBack`,mode:n,...a?{backendResult:a}:{},...g(`Back`)}},cn=async(e,t={})=>{if(!e.backend.pressHome)throw new r(`UNSUPPORTED_OPERATION`,`system.home is not supported by this backend`);let n=await e.backend.pressHome(m(e,t)),i=u(n);return{kind:`systemHome`,...i?{backendResult:i}:{},...g(`Home`)}},ln=async(e,t)=>{if(!e.backend.pressTvRemote)throw new r(`UNSUPPORTED_OPERATION`,`system.tvRemote is not supported by this backend`);let n=oe(t.button),i=t.durationMs===void 0?void 0:s(t.durationMs,`durationMs`,0,1e4),a=await e.backend.pressTvRemote(m(e,t),{button:n,...i===void 0?{}:{durationMs:i}}),o=u(a);return{kind:`tvRemotePressed`,button:n,...i===void 0?{}:{durationMs:i},...o?{backendResult:o}:{},...g(`Pressed TV remote ${n}`)}},un=async(e,t)=>{if(!e.backend.setOrientation)throw new r(`UNSUPPORTED_OPERATION`,`system.orientation is not supported by this backend`);let n=gn(t.orientation),i=await e.backend.setOrientation(m(e,t),n),a=u(i);return{kind:`systemOrientationSet`,orientation:n,...a?{backendResult:a}:{},...g(`Rotated to ${n}`)}},dn=async(e,t={})=>{if(!e.backend.setKeyboard)throw new r(`UNSUPPORTED_OPERATION`,`system.keyboard is not supported by this backend`);let n=t.action??`status`;if(!ce(n))throw new r(`INVALID_ARGS`,`system.keyboard action must be status, get, dismiss, enter, or return`);let i=await e.backend.setKeyboard(m(e,t),{action:n}),a=u(i),o=Tn(i)?i:{};return n===`enter`||n===`return`?vn(o,a):n===`dismiss`?yn(n,o,a):xn(n,o,a)},fn=async(e,t)=>{if(t.action===`read`){if(!e.backend.getClipboard)throw new r(`UNSUPPORTED_OPERATION`,`system.clipboard read is not supported by this backend`);let n=await e.backend.getClipboard(m(e,t));return{kind:`clipboardText`,action:`read`,text:typeof n==`string`?n:n.text}}if(t.action!==`write`)throw new r(`INVALID_ARGS`,`system.clipboard action must be read or write`);if(!e.backend.setClipboard)throw new r(`UNSUPPORTED_OPERATION`,`system.clipboard write is not supported by this backend`);if(typeof t.text!=`string`)throw new r(`INVALID_ARGS`,`system.clipboard write requires text`);let n=await e.backend.setClipboard(m(e,t),t.text),i=u(n);return{kind:`clipboardUpdated`,action:`write`,textLength:Array.from(t.text).length,...i?{backendResult:i}:{},...g(`Clipboard updated`)}},pn=async(e,t={})=>{if(!e.backend.openSettings)throw new r(`UNSUPPORTED_OPERATION`,`system.settings is not supported by this backend`);let n=C(t.target,`target`),i=await e.backend.openSettings(m(e,t),n),a=u(i);return{kind:`settingsOpened`,...n?{target:n}:{},...a?{backendResult:a}:{},...g(n?`Opened settings: ${n}`:`Opened settings`)}},mn=async(e,t={})=>{if(!e.backend.handleAlert)throw new r(`UNSUPPORTED_OPERATION`,`system.alert is not supported by this backend`);let n=t.action??`get`;if(n!==`get`&&n!==`accept`&&n!==`dismiss`&&n!==`wait`)throw new r(`INVALID_ARGS`,`system.alert action must be get, accept, dismiss, or wait`);let i=t.timeoutMs===void 0?void 0:s(t.timeoutMs,`timeoutMs`,0,12e4);return _n(n,await e.backend.handleAlert(m(e,t),n,{timeoutMs:i}))},hn=async(e,t={})=>{if(!e.backend.openAppSwitcher)throw new r(`UNSUPPORTED_OPERATION`,`system.appSwitcher is not supported by this backend`);let n=await e.backend.openAppSwitcher(m(e,t)),i=u(n);return{kind:`appSwitcherOpened`,...i?{backendResult:i}:{},...g(`Opened app switcher`)}};function gn(e){switch(e){case`portrait`:case`portrait-upside-down`:case`landscape-left`:case`landscape-right`:return e;default:throw new r(`INVALID_ARGS`,`system.orientation must be portrait, portrait-upside-down, landscape-left, or landscape-right`)}}function _n(e,t){return e===`get`?Sn(t):e===`wait`?Cn(t):wn(e,t)}function vn(e,t){return{kind:`keyboardEnterPressed`,action:`enter`,state:e,...t?{backendResult:t}:{},...g(`Keyboard enter pressed`)}}function yn(e,t,n){return{kind:`keyboardDismissed`,action:e,state:t,...n?{backendResult:n}:{},...g(bn(t))}}function bn(e){return e.dismissed===!1?`Keyboard already hidden`:e.mechanism===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`}function xn(e,t,n){return{kind:`keyboardState`,action:e,state:t,...n?{backendResult:n}:{}}}function Sn(e){if(e.kind!==`alertStatus`)throw new r(`COMMAND_FAILED`,`system.alert get returned an invalid backend result`);return{kind:`alertStatus`,action:`get`,alert:e.alert}}function Cn(e){if(e.kind!==`alertWait`)throw new r(`COMMAND_FAILED`,`system.alert wait returned an invalid backend result`);return{kind:`alertWait`,action:`wait`,alert:e.alert,...e.waitedMs===void 0?{}:{waitedMs:e.waitedMs},...e.timedOut===void 0?{}:{timedOut:e.timedOut},...g(e.alert?`Alert visible`:`Alert wait timed out`)}}function wn(e,t){if(t.kind!==`alertHandled`)throw new r(`COMMAND_FAILED`,`system.alert ${e} returned an invalid backend result`);return{kind:`alertHandled`,action:e,handled:t.handled,...t.alert?{alert:t.alert}:{},...t.button?{button:t.button}:{},...g(t.handled?`Alert ${e}ed`:`No alert handled`)}}function Tn(e){return!!(e&&typeof e==`object`)}const En={back:sn,home:cn,orientation:un,keyboard:dn,clipboard:fn,settings:pn,alert:mn,appSwitcher:hn,tvRemote:ln};function Dn(e){return{capture:ee(e),selectors:f(e),interactions:l(e),system:h(En,e),apps:Je(e),admin:h(qe,e),recording:h(on,e),observability:h(ft,e)}}function On(e){let t=a(e);return{...t,...Dn(t)}}export{On as createAgentDevice,te as createMemorySessionStore,c as localCommandPolicy,o as restrictedCommandPolicy};
@@ -1,5 +1,2 @@
1
- import{J as e,P as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{j as r}from"./sdk-device.js";import{Xt as i,nn as a}from"./sdk-batch.js";import{n as o}from"./device-shell.js";import{n as s,t as c}from"./android-snapshot-quality.js";import{i as l,n as u}from"./recording-stop-observation.js";import{n as d,r as f,t as p}from"./application-lifecycle-runtime.js";import{A as m,B as h,C as g,D as ee,G as te,H as ne,I as re,J as ie,N as ae,V as oe,d as se,h as ce,n as le,o as ue,s as de,v as fe,w as pe,x as me,z as he}from"./alert-runtime.js";import{n as ge}from"./audio-probe-runtime.js";import{n as _e}from"./perf-runtime.js";import{i as ve}from"./touch-runtime.js";import{a as ye,n as be}from"./durable-resource.js";import{n as xe}from"./async-lifecycle.js";import{i as Se,l as Ce,n as we,r as Te,t as Ee}from"./src7.js";import{n as De}from"./screen-recording-completion.js";import{a as _,c as Oe,n as ke,o as Ae,s as je,t as Me}from"./device-readiness-runtime.js";import{n as Ne}from"./screen-recording-runtime.js";import{readAndroidAppStateWithExecutor as Pe}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as Fe}from"./clipboard-shell-response.js";import{i as Ie,t as Le}from"./gesture-admission.js";import{t as Re}from"./local-interactor-operation-set.js";import{a as ze,i as v,n as y,r as Be,t as Ve}from"./perf-runtime-operation-builder.js";import{t as He}from"./app-log-runtime.js";import{t as Ue}from"./mp4-duration.js";import{n as b,r as We}from"./managed-device-scope.js";import{a as Ge,i as Ke,n as qe,o as Je}from"./application-lifecycle-interaction.js";import x from"node:path";function Ye(e){return Ae(e)?Object.freeze({available:!0}):e.kind===`emulator`?Object.freeze({available:!1,reason:`unsupported-device-backend`,hint:`audio probe capture requires a macOS host.`}):Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`audio probe capture is supported for Android emulators on macOS hosts.`})}function Xe(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...Ve({platform:`Android`,expectedProfileKind:`simpleperf`,start:async e=>await t().start(n,r,e),reattach:async e=>await t().reattach(n,e),cleanup:async e=>await t().cleanup(n,e),writeProfileReport:async e=>await t().writeProfileReport(n,e)}),perfFrames:async({appId:e})=>({metric:e?await v(t().sampleFrames(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-gfxinfo-framestats`,description:`Rendered-frame health from the current adb shell dumpsys gfxinfo <package> framestats window. Dropped frames use Android gfxinfo janky-frame/frame-deadline data when available; this is not video recording FPS.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`since previous Android gfxinfo reset or app process start`,resetsAfterRead:!0,relatedActionsLimit:12}}),perfMemorySample:async({appId:e})=>({metric:e?await v(t().sampleMemory(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-meminfo`,description:`Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.`,unit:`kB`,topConsumerLimit:5}}),perfMemorySnapshot:async({appId:e,kind:r,outPath:i,artifactsDir:a})=>{let o=r??`android-hprof`,s=Ze();if(o!==`android-hprof`)return ze(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Be();let c=i??x.join(a,`memory-android-hprof-${Qe()}.hprof`);return{artifact:await t().captureMemorySnapshot(n,e,c),support:s,sampling:{method:`adb-shell-am-dumpheap`,description:`Java heap dump captured with adb shell am dumpheap, pulled to a local artifact path.`,defaultKind:`android-hprof`,artifactOnly:!0}}}})}function Ze(){return{platform:`android`,defaultKind:`android-hprof`,androidHprof:!0,memgraph:!1,heapprofd:!1,heapprofdDecision:`Deferred until Android Perfetto/heapprofd plumbing is available in the perf trace slice.`}}function Qe(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function $e(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new t(`INVALID_ARGS`,`Invalid Android package name for logs: ${e}`)}const S=Object.freeze({resourceKind:He,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!tt(e.outputPath)||!tt(e.pidPath)?{status:`invalid`,message:`Invalid Android app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:e.transport,outputPath:e.outputPath,pidPath:e.pidPath})}});function et(e){let t=S.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return be({resourceKind:He,sessionId:e.sessionId,device:{id:e.device.id,family:`android`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:ye(S,t.descriptor)})}function tt(e){return typeof e==`string`&&e.trim().length>0}function nt(e){return Te(e,{family:`android`,backend:`android`,label:`Android`,codec:S,startUnavailableHint:`The selected Android transport cannot start a background adb logcat stream.`,cleanupFailureMessage:`Android app-log cleanup did not settle every owned resource`,doctor:async({host:e,device:t,signal:n},r)=>await rt(e,t.id,r,n),validateStart:({input:e})=>$e(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await Se(e,it(t.id,n.appBundleId),r),command:e=>({kind:`android-adb`,serial:t.id,args:[`logcat`,`-v`,`time`,`--pid`,e],options:{allowFailure:!0}})}),descriptor:({artifacts:e,transport:t})=>({transport:t.mode===`transport-composed`?`android-logcat-transport-composed`:`android-logcat-local`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>et({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function rt(e,t,n,r){let i={};return i.adbAvailable=await Oe(async()=>je(await e.commands.run({executable:`adb`,args:o(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(i.androidPidVisible=await Oe(async()=>!!await Se(e,it(t,n),r),r)),{backend:`android`,checks:i,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function it(e,t){return{executable:`adb`,args:o(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function at(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=we(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await st(e,t,n,r);if(s&&n.appBundleId){$e(n.appBundleId);let c=await lt(e,t,n.appBundleId,r);if(c){let e=we(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=Ee(e,a,n.maxEntries),o.push(s.reason===`stale-active`?`Session app log stream was still bound to prior Android PID ${s.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`))}}return n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&o.length===0&&o.push(`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):o.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`),a.dump.entries.length===0&&o.push(`No HTTP(s) entries were found in recent session app logs.`),Object.freeze({source:`app-log`,backend:`android`,dump:a.dump,notes:Object.freeze(o)})}async function ot(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function st(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=ct(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await ut(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function ct(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function lt(e,t,n,r){let i=await ut(e,t.id,n,r),a=await ot(e,{executable:`adb`,args:[`-s`,t.id,`logcat`,`-d`,`-v`,`time`,`-t`,`4000`],allowFailure:!0,timeoutMs:3e3},r);if(!a||a.exitCode!==0||!a.stdout.trim())return;let o=dt(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
2
- `).filter(e=>{if(!e.trim())return!1;if(e.includes(n))return!0;let t=/\(\s*(\d+)\)\s*:/.exec(e)?.[1];return!!(t&&s.has(t))}).join(`
3
- `);return c.trim()?{text:c,pids:o}:void 0}async function ut(e,t,n,r){let i=await ot(e,{executable:`adb`,args:o(`adb`,`shell`,[`pidof`,n],[`-s`,t]),allowFailure:!0},r);if(!i)return;let a=i.stdout.trim().split(/\s+/)[0];return a&&/^\d+$/.test(a)?a:void 0}function dt(e,t,n){let r=new Set(n?[n]:[]),i=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),a=[RegExp(`\\bStart proc\\s+(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`\\b(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`${i}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,`i`),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${i}`,`i`)];for(let n of e.split(`
4
- `))if(n.includes(t))for(let e of a){let t=e.exec(n)?.[1];t&&/^\d+$/.test(t)&&r.add(t)}return Object.freeze([...r])}function C(e,t){if(t===1)return e;let n=x.parse(e);return x.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}const ft=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,pt=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function mt(e){return _t(e)&&vt(e)&&yt(e)}function ht(e){if(!w(e))return!1;let t=e;return bt(t)&&xt(t)&&St(t)&&Ct(t)&&(t.completion===void 0||At(t))}function gt(e,t){return jt(e,t)&&Mt(e,t.outputPath,t.clientOutputPath)}function _t(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&pt.test(e.manifestPath)&&typeof e.outputPath==`string`}function vt(e){return Pt(e.clientOutputPath)&&_(e)}function yt(e){return Nt(e.transportMode)}function bt(e){return e.version===1&&e.resourceKind===`screen-recording`&&typeof e.fenceToken==`string`&&Number.isInteger(e.fenceGeneration)&&typeof e.sessionId==`string`&&typeof e.deviceId==`string`&&Number.isFinite(e.startedAt)}function xt(e){return typeof e.outputPath==`string`&&Pt(e.clientOutputPath)&&_(e)}function St(e){return Nt(e.transportMode)&&(e.pendingRemotePath===void 0||Ft(e.pendingRemotePath))}function Ct(e){return Array.isArray(e.chunks)&&e.chunks.every(wt)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||Tt(e.completion))}function wt(e,t){if(!w(e))return!1;let n=e;return n.index===t+1&&Ft(n.remotePath)&&It(n.remotePid)&&It(n.remoteStartTime)}function Tt(e){if(!w(e))return!1;let t=e;return Dt(t)&&Ot(t)&&Et(t)&&(t.chunks===void 0||t.chunks.every(kt))}function Et(e){return(e.stopObservation===void 0||u(e.stopObservation))&&(e.nativePathDisposition===void 0||l(e.nativePathDisposition))}function Dt(e){return typeof e.backend==`string`&&typeof e.outPath==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)&&Number.isFinite(e.startedAt)&&Number.isFinite(e.completedAt)&&(e.capturedDurationMs===void 0||Number.isFinite(e.capturedDurationMs))}function Ot(e){return _(e)}function kt(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function At(e){let t=e.completion;return t!==void 0&&jt(t,e)&&t.startedAt===e.startedAt&&Mt(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function jt(e,t){return e.backend===`adb screenrecord`&&e.outPath===t.outputPath&&e.clientOutPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&Lt(e.activeSessionApp,t.activeSessionApp)}function Mt(e,t,n,r=e.chunks===void 0?1:e.chunks.length){return r===1?e.chunks===void 0:e.chunks?.length===r&&e.chunks.every((e,r)=>e.path===C(t,r+1)&&e.clientOutPath===(n===void 0?void 0:C(n,r+1)))}function w(e){return typeof e==`object`&&!!e}function Nt(e){return e===`local`||e===`transport-composed`}function Pt(e){return e===void 0||typeof e==`string`}function Ft(e){return typeof e==`string`&&ft.test(e)}function It(e){return typeof e==`string`&&/^\d+$/.test(e)}function Lt(e,t){return JSON.stringify(e)===JSON.stringify(t)}const T=Object.freeze({resourceKind:Ne,version:1,encode:e=>({...e}),decode:e=>mt(e)?{status:`decoded`,descriptor:Object.freeze({backend:`adb-screenrecord`,manifestPath:e.manifestPath,outputPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutputPath:e.clientOutputPath},scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,transportMode:e.transportMode,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...e.exportQuality===void 0?{}:{exportQuality:e.exportQuality},...e.fps===void 0?{}:{fps:e.fps}})}:{status:`invalid`,message:`Invalid Android screen-recording descriptor`}});function E(e,t,n,r,i,a=`local`){return Object.freeze({version:1,resourceKind:`screen-recording`,fenceToken:t.fence.token,fenceGeneration:t.fence.generation,sessionId:t.sessionId,deviceId:e.id,startedAt:n,outputPath:t.outputPath,...t.clientOutputPath===void 0?{}:{clientOutputPath:t.clientOutputPath},scope:t.scope,showTouches:t.showTouches,recordOnlySession:t.recordOnlySession,...t.activeSessionApp===void 0?{}:{activeSessionApp:t.activeSessionApp},...t.exportQuality===void 0?{}:{exportQuality:t.exportQuality},...t.fps===void 0?{}:{fps:t.fps},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Rt(e,t){return Object.freeze({...e,completion:t})}function D(e){try{let t=e&&JSON.parse(e);return ht(t)?t:void 0}catch{return}}function zt(e,t,n){return e.deviceId===t.id&&e.deviceId===n.device.id&&e.fenceToken===n.fence.token&&e.fenceGeneration===n.fence.generation&&e.sessionId===n.sessionId}function Bt(e,t){return e.outputPath===t.outputPath&&e.clientOutputPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&JSON.stringify(e.activeSessionApp)===JSON.stringify(t.activeSessionApp)&&e.exportQuality===t.exportQuality&&e.fps===t.fps&&e.transportMode===t.transportMode&&(e.completion===void 0||gt(e.completion,t))}function O(e){switch(e){case`missing`:case`ownership-lost`:case`foreign-writer`:return!0;case`owned-alive`:case`uncertain`:return!1}}function Vt(e){switch(e){case`missing`:case`ownership-lost`:return!0;case`foreign-writer`:case`owned-alive`:case`uncertain`:return!1}}const Ht=1e4,k=1e3;var A=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function j(e,t=Date.now()){return[...new Set(e?[e,`/sdcard`,`/data/local/tmp`]:[`/sdcard`,`/data/local/tmp`])].map(e=>`${e}/agent-device-recording-${t}.mp4`)}async function Ut(e,t,n,r){let i;try{if(i=(await e.start({remotePath:t,quality:n.exportQuality??`medium`},r)).process,!/^\d+$/.test(i.pid)||!/^\d+$/.test(i.startTime)||i.remotePath!==t)throw Error(`Android screenrecord returned an invalid process identity`);if(!await Yt(e,t,i,r))throw Error(`Android screenrecord did not begin producing frames`);return{index:1,remotePath:t,remotePid:i.pid,remoteStartTime:i.startTime}}catch(t){throw i&&Wt(i)&&!await Xt(e,i)?new A(t):r?.aborted?r.reason:t}}function Wt(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function M(e,t){let n=t.at(-1),r=!1,i;for(let a of[...t].reverse())try{let t=await P(e,a);a===n&&(r=t)}catch(e){i??=e}if(i)throw i;return r}async function Gt(e,t){for(let n of t){let t;for(let r=0;r<3;r+=1){let i=await e.size(n.remotePath);if(typeof i==`number`&&i>0&&i===t)break;if(t=typeof i==`number`&&i>0?i:void 0,r===2)throw Error(`Android recording artifact is not stable: ${n.remotePath}`);await new Promise(e=>setTimeout(e,250))}}}async function Kt(e,t,n){for(let[r,i]of t.entries())await Zt(e,i.remotePath,C(n,r+1))}async function N(e,t){let n;for(let r of t)try{if(!await e.remove(r.remotePath))throw Error(`failed to remove Android recording artifact: ${r.remotePath}`)}catch(e){n??=e}if(n)throw n}async function qt(e,t){for(let n of t)if(await e.exists(n.remotePath)!==!1)return`retirable`;return`retired`}async function Jt(e,t){try{await M(e,t)}finally{await N(e,t)}}async function Yt(e,t,n,r){for(let i=0;i<3;i+=1){if(r?.throwIfAborted(),await e.exists(t,r)===!0)return!0;if(await e.inspect(n,r)!==`owned-alive`)return!1;i<2&&await new Promise(e=>setTimeout(e,250))}return!0}async function Xt(e,t){try{let n=await e.stop(t,{force:!0});return(n===`stopped`||n===`already-missing`)&&await e.remove(t.remotePath)}catch{return!1}}async function P(e,t){if(!t)return!1;let n={pid:t.remotePid,remotePath:t.remotePath,startTime:t.remoteStartTime},r=await e.stop(n);if(r===`already-missing`)return!0;if(r===`ownership-lost`)throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.remotePid}`);if(await Qt(e,n))return!1;let i=await e.stop(n,{force:!0});if(i===`stopped`||i===`already-missing`)return!1;throw Error(`failed to stop Android screenrecord pid ${t.remotePid}`)}async function Zt(e,t,n){for(let r=0;r<3;r+=1){let i=await e.pullPlayable({remotePath:t,outputPath:n});if(i.exitCode===0&&i.playable)return;r+1<3&&await $t(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function Qt(e,t){for(let n=0;n<=Ht;n+=k){let r=await e.inspect(t);if(r===`missing`)return!0;if(O(r))throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.pid}`);n<Ht&&await $t(k)}return!1}function $t(e){return new Promise(t=>setTimeout(t,e))}async function F(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function I(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}async function en(e,t){let n=(await tn(e)).flatMap(n=>nn(n,t,e.mode));for(let t of n)await an(e,t.evidence,t.manifestPath)}async function tn(e){return await Promise.all(j(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function nn(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw cn(e.manifestPath,e.read.message);let r=D(e.read.contents);if(r===void 0)throw ln(e.manifestPath);if(r.transportMode!==n)throw un(e.manifestPath,r,n);if(!rn(r,t))throw dn(e.manifestPath,r,t);return[{manifestPath:e.manifestPath,evidence:r}]}function rn(e,t){return e.completion!==void 0||e.deviceId!==t.id}async function an(e,t,n){if(await on(e,t),await N(e,t.chunks),await sn(e,t),await I(e,n),(await e.readManifest(n)).status!==`missing`)throw mn(n)}async function on(e,t){for(let n of t.chunks){let t=await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime});if(!Vt(t))throw t===`uncertain`?hn(n.remotePath):fn(n.remotePath,t===`owned-alive`?`named-recorder`:`other-recorder`)}let n=t.pendingRemotePath;if(n===void 0)return;let r=await e.probeRunningWriters(n);if(r.writers.length>0)throw fn(n,`other-recorder`);if(!r.conclusive)throw hn(n)}async function sn(e,t){let n=t.pendingRemotePath;if(n!==void 0&&!await e.remove(n))throw pn(n)}function cn(e,n){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unavailable: ${e}`,{reason:`native_recovery_evidence_unavailable`,manifestPath:e,hint:`Confirm the device is online and its storage readable, then run record start again.`},Error(n))}function ln(e){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unreadable: ${e}`,{reason:`native_recovery_evidence_unreadable`,manifestPath:e,hint:L(e)})}function un(e,n,r){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence was written by the ${n.transportMode} transport, not this ${r} one: ${e}`,{reason:`native_recovery_evidence_transport_mismatch`,manifestPath:e,evidenceTransportMode:n.transportMode,hint:L(e)})}function dn(e,n,r){return new t(`DEVICE_IN_USE`,`Android screenrecord native recovery evidence already exists: ${e} (open recording of session "${n.sessionId}" on ${r.id})`,{reason:`native_recovery_evidence_open`,manifestPath:e,sessionId:n.sessionId,retriable:!1,hint:`Run record stop --session ${n.sessionId} to retire it, or close that session. If it is already closed, ${L(e)}`})}function fn(e,n){let r=n===`named-recorder`;return new t(`DEVICE_IN_USE`,`Android screenrecord recovery evidence is retained: ${r?`its recorder`:`another recorder`} is writing ${e}`,{reason:`native_recording_artifact_claimed`,remotePath:e,writer:n,...r?{retriable:!1}:{},hint:r?`Run record stop for the session that owns that recording before starting another.`:`Android ends any recorder after 180 seconds. Run record start again once that recorder has stopped.`})}function pn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence could not remove ${e}`,{reason:`native_recording_artifact_removal_failed`,remotePath:e,hint:`Confirm the device is online and run record start again.`})}function mn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence removal could not be confirmed: ${e}`,{reason:`native_recovery_evidence_retirement_unconfirmed`,manifestPath:e,hint:`Run record start again; the marker is retired from the beginning.`})}function hn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence cannot be safely retired: ${e}`,{reason:`native_recording_recorder_unproven`,remotePath:e,hint:`Confirm the device is online and run record start again.`})}function L(e){return`no recording session can retire this marker; remove it on the device with \`adb shell rm -f ${e}\`.`}async function gn(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await en(t,n),await o();let s;for(let e of j(void 0)){let o=t.manifestPathFor(e);await F(t,o,E(n,r,i,[],e,t.mode),a);let c,l;try{l=Date.now(),c=await Ut(t,e,r,a)}catch(e){if(a.aborted)throw await _n(t,o,e),a.reason;await bn(t,o,e),s=e;continue}try{await F(t,o,E(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await vn(t,o,c),e}return{chunk:c,manifestPath:o,startedAtMs:l}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function _n(e,t,n){n instanceof A||await I(e,t).catch(()=>{})}async function vn(e,t,n){try{await Jt(e,[n])}catch{return}await I(e,t).catch(()=>{})}async function yn(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of j(s)){await F(t,o,E(n,r,i,a,e,t.mode));try{return await Ut(t,e,r)}catch(e){if(e instanceof A)throw e;try{await F(t,o,E(n,r,i,a,void 0,t.mode))}catch{throw new A(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function bn(e,t,n){if(n instanceof A)throw n;try{await I(e,t)}catch{throw new A(n)}}function xn(e,t){return Object.freeze({backend:`adb screenrecord`,outPath:e.outputPath,...e.clientOutputPath?{clientOutPath:e.clientOutputPath}:{},startedAt:t,scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,...e.activeSessionApp?{activeSessionApp:e.activeSessionApp}:{},...e.exportQuality?{exportQuality:e.exportQuality}:{},...e.fps===void 0?{}:{fps:e.fps},gestureEvents:[]})}function Sn(e){let t=Cn(e.chunkPaths);if(t===void 0)return{};let n=e.stoppedAtMs-e.startedAtMs;return n-t<2e3?{capturedDurationMs:t}:{capturedDurationMs:t,idleTailWarning:`Android screenrecord encodes a frame only when the screen changes, so this video ends at the last frame it encoded: it covers ${wn(t)}s of the ${wn(n)}s recording window.`}}function Cn(e){let t=0;for(let n of e){let e=Ue(n);if(e===void 0)return;t+=e}return t}function wn(e){return(e/1e3).toFixed(1)}async function Tn(e){let{host:t,transport:n,evidence:r,recording:i,startedAtMs:a,progress:o}=e,s=e.reachedLimit===!0;return await An(e,await ke({snapshot:i,progress:o,steps:{stop:async()=>(s=await M(n,r.chunks)||s,await Gt(n,r.chunks),{observation:{recorder:`confirmed`},...s?{warning:`Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video.`}:{}}),collect:e=>Kt(n,r.chunks,e),finalize:({collectedPath:e,exportPath:n,stoppedAtMs:o})=>En({host:t,evidence:r,recording:i,startedAtMs:a,stoppedAtMs:o,collectedPath:e,exportPath:n}),discard:e=>On(t,e,r.chunks.length)}}))}async function En(e){let{host:t,evidence:n,recording:r,collectedPath:i,exportPath:a}=e,o=jn({collectedPath:i,exportPath:a,exportClientPath:r.clientOutPath,count:n.chunks.length}),s=o.length>1,c;try{await Dn(t,o),c=await t.screenRecording.finalize.complete({outputPath:a,showTouches:!s&&r.showTouches,gestureEvents:r.gestureEvents,exportQuality:r.exportQuality??`medium`,...r.fps===void 0?{}:{fps:r.fps},targetLabel:`Android recording`})}catch(e){for(let{served:e}of o)await t.screenRecording.outputs.remove(e.path);throw e}let l=Sn({chunkPaths:o.map(({collected:e})=>e.path),startedAtMs:e.startedAtMs,stoppedAtMs:e.stoppedAtMs});return kn({finalization:c,captured:l,recording:r,chunked:s,files:o})}async function Dn(e,t){for(let{collected:n,served:r}of t)await e.screenRecording.outputs.copy({from:n.path,to:r.path})}async function On(e,t,n){for(let r=1;r<=n;r+=1)await e.screenRecording.outputs.remove(C(t,r))}function kn(e){let{finalization:t,captured:n,recording:r,chunked:i,files:a}=e,o=[t.warning,...i?[`Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks.`]:[],n.idleTailWarning].filter(e=>e!==void 0&&e.length>0);return{...t.telemetryPath===void 0?{}:{telemetryPath:t.telemetryPath},...o.length===0?{}:{warning:o.join(` `)},...i&&r.showTouches&&r.gestureEvents.length>0?{overlayWarning:`touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry`}:{},...n.capturedDurationMs===void 0?{}:{capturedDurationMs:n.capturedDurationMs},...i?{chunks:a.map(e=>e.served)}:{},nativePathDisposition:`retirable`}}async function An(e,t){let{transport:n,evidence:r,manifestPath:i}=e;return await F(n,i,Rt(r,t.result)),await N(n,r.chunks),{status:`completed`,result:{...t.result,nativePathDisposition:await qt(n,r.chunks)}}}function jn(e){return Object.freeze(Array.from({length:e.count},(t,n)=>({collected:Object.freeze({index:n+1,path:C(e.collectedPath,n+1)}),served:Object.freeze({index:n+1,path:C(e.exportPath,n+1),...e.exportClientPath===void 0?{}:{clientOutPath:C(e.exportClientPath,n+1)}})})))}async function Mn(e,t,n){try{let r=t.pendingRemotePath;if(await M(e,[...t.chunks,...await Nn(e,t)]),await N(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await I(e,n),{status:`cleaned`}}catch(e){return Pn(e)}}async function Nn(e,t){let n=t.pendingRemotePath;if(n===void 0)return[];let r=await e.probeRunningWriters(n);if(!r.conclusive)throw Error(`cannot list every recorder writing Android artifact: ${n}`);return r.writers.map((e,r)=>({index:t.chunks.length+1+r,remotePath:n,remotePid:e.pid,remoteStartTime:e.startTime}))}function Pn(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function Fn(e){let{transport:t,device:n,envelope:r,descriptor:i}=e;if(i.transportMode!==t.mode)return{status:`transport-unavailable`};let a=await t.readManifest(i.manifestPath);if(a.status===`unavailable`)return{status:`transport-unavailable`};let o=a.status===`read`?D(a.contents):void 0;return o&&zt(o,n,r)&&Bt(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function In(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=D(t.contents);return n&&Ln(n,e)?n:void 0}function Ln(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function Rn(e){let{host:t,transport:n,device:r,input:i}=e,a=T.decode(i.envelope.descriptor.body);if(a.status!==`decoded`)return R(`descriptor-invalid`);let o=await Fn({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await Bn({host:t,transport:n,device:r,input:i,descriptor:a.descriptor,evidence:o.evidence}):R(o.status===`transport-unavailable`?`transport-not-reattachable`:`ownership-fence-lost`)}async function zn(e){let t=T.decode(e.input.envelope.descriptor.body);if(t.status!==`decoded`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await Fn({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await Mn(e.transport,n.evidence,t.descriptor.manifestPath):n.status===`transport-unavailable`?{status:`cleanup-pending`,reason:`owner-unavailable`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function Bn(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0){let e=await Vn(n,o);return e.status===`terminal`?{status:`completed`,result:{...o.completion,nativePathDisposition:e.nativePathDisposition}}:R(`ownership-fence-lost`,`Android recording completed evidence still names a live or unverifiable recorder.`)}if(o.pendingRemotePath!==void 0)return R(`transport-not-reattachable`,`Android recording launch was interrupted before its process identity was committed.`);let s=o.chunks.at(-1);if(!s)return{status:`missing`};let c=await n.inspect({pid:s.remotePid,remotePath:s.remotePath,startTime:s.remoteStartTime});if(c!==`owned-alive`&&await n.exists(s.remotePath)===!1)return R(`transport-not-reattachable`,`Android recording process ended before its artifact could be recovered.`);let l=Hn(i.envelope.sessionId,i.envelope.fence,a),u=!1;return{status:`active`,handle:De(xn(l,o.startedAt),{finish:async(e,r)=>{let i=await Tn({host:t,transport:n,evidence:o,manifestPath:a.manifestPath,recording:e,startedAtMs:o.startedAt,reachedLimit:O(c),progress:r});return u=!0,i},forceCleanup:async()=>u?{status:`cleaned`}:await zn({transport:n,device:r,input:i})})}}async function Vn(e,t){try{for(let n of t.chunks)if(!O(await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime})))return{status:`retained`};return{status:`terminal`,nativePathDisposition:await qt(e,t.chunks)}}catch{return{status:`retained`}}}function Hn(e,t,n){return{sessionId:e,outputPath:n.outputPath,...n.clientOutputPath===void 0?{}:{clientOutputPath:n.clientOutputPath},scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:!1,recordOnlySession:n.recordOnlySession,...n.activeSessionApp===void 0?{}:{activeSessionApp:n.activeSessionApp},...n.exportQuality===void 0?{}:{exportQuality:n.exportQuality},...n.fps===void 0?{}:{fps:n.fps},fence:t}}function R(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function Un(e){let{host:t,device:n,owner:r,signal:i}=e,a=await t.screenRecording.android.resolve(n);return Object.freeze({screenRecordingStart:async e=>await Wn({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await Rn({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await zn({transport:a,device:n,input:e})})}async function Wn(e){let{host:t,transport:n,device:i,owner:a,input:o,signal:s}=e;s.throwIfAborted();let c=Date.now(),l=await gn({transport:n,device:i,input:o,startedAt:c,signal:s,prepareOutput:async()=>await t.screenRecording.outputs.prepare(o.outputPath)}),u=l.manifestPath,d=[l.chunk],f,p,m,h=!1,g=()=>{f=setTimeout(()=>{p=ee().catch(e=>{m=e})},17e4),f.unref?.()},ee=async()=>{let e=d.at(-1);if(!e)throw Error(`Android recording has no active chunk`);let t=!1,r;try{r=await yn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:x.posix.dirname(e.remotePath)})}catch(a){await P(n,e),t=!0;try{r=await yn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:x.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:a}}let a=[...d,{...r,index:d.length+1}];try{await F(n,u,E(i,o,c,a,void 0,n.mode))}catch(a){if(await Jt(n,[r]).catch(()=>{}),t)await F(n,u,E(i,o,c,d,r.remotePath,n.mode)).catch(()=>{});else try{await F(n,u,E(i,o,c,d,void 0,n.mode))}catch{await P(n,e).catch(()=>{}),await F(n,u,E(i,o,c,d,r.remotePath,n.mode)).catch(()=>{})}throw a}d=a,t||await P(n,e),g()};g();let te=De(xn(o,c),{finish:async(e,r)=>{if(f&&clearTimeout(f),await p,m)throw m;let a=await Tn({host:t,transport:n,evidence:E(i,o,c,d,void 0,n.mode),manifestPath:u,recording:e,startedAtMs:l.startedAtMs,progress:r});return h=!0,a},forceCleanup:async()=>{if(f&&clearTimeout(f),h)return{status:`cleaned`};try{await p}catch(e){m=e}let e=await In({transport:n,deviceId:i.id,sessionId:o.sessionId,fence:o.fence,manifestPath:u});return e?await Mn(n,e,u):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new xe(te),envelope:be({resourceKind:Ne,sessionId:o.sessionId,device:r(i),owner:a,fence:o.fence,lifecycle:`open`,descriptor:ye(T,{backend:`adb-screenrecord`,manifestPath:u,outputPath:o.outputPath,...o.clientOutputPath===void 0?{}:{clientOutputPath:o.clientOutputPath},scope:o.scope,showTouches:o.showTouches,recordOnlySession:o.recordOnlySession,...o.activeSessionApp===void 0?{}:{activeSessionApp:o.activeSessionApp},...o.exportQuality===void 0?{}:{exportQuality:o.exportQuality},...o.fps===void 0?{}:{fps:o.fps},transportMode:n.mode})})})}const Gn=1e3;async function z(e,t,n,r){return r.throwIfAborted(),await We(t)?{...t,booted:!0}:t.kind===`emulator`&&(t.booted!==!0||!B(t))?await Kn(e,t,n,r):(t.booted!==!0&&await Xn(e,t.id,Qn(e,n),r),{...t,booted:!0})}async function Kn(e,t,n,r){await qn(e);let i=$n(n),a=Qn(e,n),o=Jn(await e.deviceReadiness.androidEmulator.discover(i,r),t.name,n.serial),s=B(o)?o:void 0,c=s?void 0:e.deviceReadiness.androidEmulator.launch(o.name,n.headless);try{let t=s??await Yn(e,o.name,i,n.serial,a,r);return await Xn(e,t.id,a,r),{...(await e.deviceReadiness.androidEmulator.discover(i,r)).find(e=>e.id===t.id)??t,name:o.name,booted:!0}}catch(t){throw c!==void 0&&r.aborted&&await e.deviceReadiness.androidEmulator.terminate(c),r.throwIfAborted(),t}}async function qn(e){if(await e.toolchains.prepare(`android`),!await e.commands.which(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await e.commands.which(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`)}function Jn(e,n,r){let i=er(e,n,r);if(i)return i;throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${n}`,{requestedAvdName:n,availableAvds:e.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."})}async function Yn(e,t,n,r,i,a){for(;e.clock.now()<i;){let i=er(await e.deviceReadiness.androidEmulator.discover(n,a),t,r);if(i&&B(i))return i;await e.clock.sleep(Gn,a)}throw Zn(`Android emulator did not appear in time`,{avdName:t,serial:r})}async function Xn(e,t,n,r){for(;e.clock.now()<n;){if((await e.commands.run({executable:`adb`,args:o(`adb`,`shell`,[`getprop`,`sys.boot_completed`],[`-s`,t]),allowFailure:!0,timeoutMs:Math.min(1e4,Math.max(1e3,n-e.clock.now()))},r)).stdout.trim()===`1`)return;await e.clock.sleep(Gn,r)}throw Zn(`Android device failed to finish booting`,{serial:t})}function Zn(e,n){return new t(`COMMAND_FAILED`,e,{...n,reason:Me,hint:`The emulator keeps booting in the background. Retry once it is up, or pass a larger --timeout.`})}function Qn(e,t){return t.deadlineAtMs??e.clock.now()+12e4}function $n(e){return{platform:`android`,kind:`emulator`,...e.serial?{serial:e.serial}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}}}function er(e,t,n){let r=tr(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&tr(e.name)===r&&(!n||!B(e)||e.id===n))}function B(e){return e.id.startsWith(`emulator-`)}function tr(e){return e.toLowerCase().replaceAll(`_`,` `).replaceAll(/\s+/g,` `).trim()}async function nr(e,t,n){try{let r=await e.snapshot({appBundleId:t,signal:n,transient:{settleBy:Date.now()+6e3}});return{observation:`androidSnapshot`in r&&r.androidSnapshot?.systemSurfaceOnly===!0?`unobservable`:`observable`}}catch(e){return n.throwIfAborted(),c(e)?{observation:`unobservable`}:{observation:`probe-failed`,failure:rr(e)}}}function rr(t){let n=e(t),r=s(n)??n.details?.reason,{code:i}=n;return typeof r==`string`?{source:`capture`,code:i,reason:r}:{source:`capture`,code:i}}function ir(e){let{host:t,device:n,signal:r}=e,i=qe({device:n,signal:r,resolveInteractor:t.localInteractors.resolve});return Object.freeze({resolveOpenTarget:async e=>await t.androidApplications.resolveOpenTarget(n,e),prepareApplicationOpen:async e=>{await z(t,n,{headless:!1,deadlineAtMs:e.execution.startupDeadlineAtMs},r)},openApplication:async e=>await ar(t,i,e),applyRuntimeHints:async e=>await t.androidApplications.applyRuntimeHints(n,e),clearRuntimeHints:async e=>await t.androidApplications.clearRuntimeHints(n,e),closeApplication:async e=>{e.ensureReady&&await z(t,n,{headless:!1},r),await Ge({device:n,interactor:await i.resolveInteractor(e.execution,e.appBundleId),positionals:e.positionals})},finalizeApplicationClose:async e=>{await t.androidApplications.restoreTestIme(n,{stateDir:e.stateDir});let i=e.shutdownTarget&&n.kind===`emulator`?await t.deviceShutdown.android.shutdownTarget(n,r):void 0;return i===void 0?{}:{shutdown:i}},prepareAppleRunner:sr,configureProviderPortReverse:sr})}async function ar(e,n,r){let i={};if(r.relaunch&&r.target){let e=Date.now();await Ge({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:[r.appBundleId??r.target]}),i.relaunchCloseDurationMs=V(e)}if(f(r.runtimeHints)){if(!r.applyRuntimeHints)throw new t(`COMMAND_FAILED`,`Runtime hint operation was not admitted for this open.`,{reason:`runtime-hints-operation-missing`});let e=Date.now();await r.applyRuntimeHints({appId:r.appBundleId,values:r.runtimeHints}),i.runtimeHintsDurationMs=V(e)}let a=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:r.positionals,appBundleId:r.appBundleId,execution:r.execution}),i.openDispatchDurationMs=V(a),r.enableTestIme&&await e.androidApplications.activateTestIme(n.device,{stateDir:r.stateDir});let o=Ke(r);if(o){let e=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor({...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0},r.appBundleId),positionals:[o],appBundleId:r.appBundleId,execution:{...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0}}),i.launchUrlDurationMs=V(e)}else i.launchUrlDurationMs=0;let s=await e.androidApplications.inferOpenedAppBundleId(n.device,r.target,r.appBundleId);s&&await e.androidApplications.resetFramePerfStats(n.device,s);let c=Date.now();return Object.assign(i,await or(n,r,s)),i.postOpenSettleDurationMs=V(c),{appBundleId:s,timing:i}}async function or(e,t,r){if(!t.target||n(t.target))return{};if(!r)return{postOpenObservation:`app-unidentified`};let i=await nr(await e.resolveInteractor(t.execution,r),r,e.signal);return i.observation===`probe-failed`?{postOpenObservation:`probe-failed`,postOpenObservationFailure:i.failure}:{postOpenObservation:i.observation}}function V(e){return Math.max(0,Date.now()-e)}async function sr(){throw new t(`UNSUPPORTED_OPERATION`,`This lifecycle operation is unavailable for Android.`)}async function H(e,t,n,r,i){U(n);let a=r?void 0:await W(e,t,i);if(x.extname(n).toLowerCase()===`.aab`?await dr(e,t,n,i):K(await e.androidTools.installPackage(t,n,{replace:!0},i),`adb install failed`),r)return r;let o=[...await W(e,t,i)].filter(e=>!a?.has(e));return o.length===1?o[0]:void 0}function U(e){if(b()&&x.extname(e).toLowerCase()===`.aab`)throw new t(`UNSUPPORTED_OPERATION`,`Managed Android deployment does not support app bundles.`,{reason:`managed-bundle-install-unavailable`,hint:`Install an APK on this managed device.`})}async function cr(e,t,n,r){let i=await G(e,t,[`uninstall`,n],r);if(i.exitCode===0)return;let a=`${i.stdout}\n${i.stderr}`.toLowerCase();a.includes(`unknown package`)||a.includes(`not installed`)||K(i,`adb uninstall failed for ${n}`)}async function lr(e,n,r,i){let a=r.payload,s=typeof a.action==`string`&&a.action.trim()?a.action.trim():`${r.appId}.TEST_PUSH`,c=[`am`,`broadcast`,`-a`,s,`-p`,r.appId];typeof a.receiver==`string`&&a.receiver.trim()&&c.push(`-n`,a.receiver.trim());let l=a.extras??{};if(typeof l!=`object`||!l||Array.isArray(l))throw new t(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=0;for(let[e,t]of Object.entries(l))e&&(fr(c,e,t),u+=1);return K(await G(e,n,o(`adb`,`shell`,c),i),`adb push broadcast failed`),{action:s,extrasCount:u}}function ur(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(/[._-]+/).map(e=>e.trim().toLowerCase()).filter(Boolean),r=[...n].reverse().find(e=>!t.has(e))??n.at(-1)??e;return r.charAt(0).toUpperCase()+r.slice(1)}async function dr(e,n,r,i){if(await e.androidTools.installBundle(n,r,`universal`,i))return;let a=await e.commands.which(`bundletool`),o=e.androidDeployment.bundletoolJar;if(!a&&!o)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR.`);let s=a?`bundletool`:`java`,c=a?[]:[`-jar`,o],l=await e.temporaryFiles.create({prefix:`agent-device-aab-`,suffix:`.apks`}),u=l.path;try{K(await e.commands.run({executable:s,args:[...c,`build-apks`,`--bundle`,r,`--output`,u,`--mode`,`universal`]},i),`bundletool build-apks failed`),K(await e.commands.run({executable:s,args:[...c,`install-apks`,`--apks`,u,`--device-id`,n.id]},i),`bundletool install-apks failed`)}finally{await l[Symbol.asyncDispose]()}}async function W(e,t,n){let r=await G(e,t,o(`adb`,`shell`,[`pm`,`list`,`packages`]),n);return K(r,`adb package inventory failed`),new Set(r.stdout.split(`
5
- `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}function fr(e,n,r){if(typeof r==`string`)e.push(`--es`,n,r);else if(typeof r==`boolean`)e.push(`--ez`,n,String(r));else if(typeof r==`number`&&Number.isFinite(r))e.push(Number.isInteger(r)?`--ei`:`--ef`,n,String(r));else throw new t(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}async function G(e,t,n,r,i=15e3){return await e.androidTools.runAdb(t,n,{timeoutMs:i,allowFailure:!0},r)}function K(e,n){if(e.exitCode===0)return;let r={stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode};throw new t(`COMMAND_FAILED`,n,r)}const pr=Object.freeze({available:!0});function mr(e){let t=vr(e);return Object.freeze({deployApp:t,materializeAppSource:t,deployMaterializedApp:t,sendPushNotification:t})}function hr(e){let{host:t,device:n,signal:r}=e;return mr(n).deployApp.available?Object.freeze({deployApp:async e=>await gr(t,n,e,r),materializeAppSource:async e=>await t.androidDeployment.prepareArtifact(e,{signal:r}),deployMaterializedApp:async e=>await _r(t,n,e,r),sendPushNotification:async e=>await lr(t,n,e,r)}):Object.freeze({})}async function gr(e,t,n,r){if(n.replaceExisting)return await e.androidDeployment.withInvalidatedAppResolutionCache(t,async()=>{let i;try{b()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),U(i.installablePath)),t.booted!==!0&&await z(e,t,{headless:!1},r);let a=await e.androidDeployment.resolveAppPackage(t,n.app);return await cr(e,t,a,r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),await H(e,t,i.installablePath,void 0,r),{packageName:a,launchTarget:a}}finally{await i?.cleanup()}});let i;try{b()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r}),U(i.installablePath)),t.booted!==!0&&await z(e,t,{headless:!1},r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r});let a=await H(e,t,i.installablePath,i.packageName,r);return a?{packageName:a,appName:ur(a),launchTarget:a}:{}}finally{await i?.cleanup()}}async function _r(e,n,r,i){let a=await H(e,n,r.artifact.installablePath,r.artifact.packageName,i);if(!a)throw new t(`COMMAND_FAILED`,`Installed Android app identity could not be resolved from the artifact or device state`);return{packageName:a,appName:ur(a),launchTarget:a}}function vr(e){return e.kind===`emulator`||e.kind===`device`?pr:Object.freeze({available:!1,reason:`unsupported-device-kind`})}const q=i(`android`),J=Object.freeze({available:!0}),yr=Object.freeze({available:!1,reason:`unsupported-device-kind`}),br=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`focus is supported on Android emulators and physical devices.`}),xr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`keyboard actions are supported on Android emulators and physical devices.`}),Sr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`}),Cr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Android has no key event for this system button.`}),wr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`fold drives the hinge of a foldable iPhone simulator; the Android emulator posture control is not driven by agent-device yet.`}),Tr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Headless boot is supported only for Android emulators.`}),Er=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Android appstate is supported only for Android emulators and devices.`}),Dr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Apple runner preparation is supported only for Apple targets.`}),Or=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`open is supported only for Android emulators and devices.`}),kr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`close is supported only for Android emulators and devices.`}),Ar=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Runtime hints are supported only for Android emulators and devices.`}),jr=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Port reverse is supported only by an owning provider runtime.`}),Mr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`shutdown is supported only for Apple simulators and Android emulators.`}),Nr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`screenshot is supported only for Android emulators and devices.`}),Y=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`snapshot is supported only for Android emulators and devices.`}),Pr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Re-run without --actions, or target an iOS simulator.`}),Fr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`viewport resizes web targets only (--platform web).`}),Ir=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`the stateless audio page probe is a web-session operation; Android targets use the host capture.`});function Lr(e){let t=Rr(e),n=zr(e),r=Br(e);return p({resolveOpenTarget:t,prepareApplicationOpen:t,openApplication:t,applyRuntimeHints:r,clearRuntimeHints:r,closeApplication:n,finalizeApplicationClose:n,prepareAppleRunner:Dr,configureProviderPortReverse:jr})}function Rr(e){return e.kind===`emulator`||e.kind===`device`?J:Or}function zr(e){return e.kind===`emulator`||e.kind===`device`?J:kr}function Br(e){return e.kind===`emulator`||e.kind===`device`?J:Ar}const X=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Gestures are supported on Android emulators and physical devices.`}),Vr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Le}),Hr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ie});function Ur(e,t){return e.kind===`simulator`?X:e.target===`tv`?t:J}function Z(e){return e.kind===`simulator`?X:J}function Q(e){return e.kind===`simulator`?br:J}const $=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:Fe}),Wr=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Could not determine whether this Android build supports a shell clipboard: the adb probe did not complete. Retry once the device is reachable.`});async function Gr(e,t){let n=e.androidTools?.probeClipboardShellSupport;return n?await n.call(e.androidTools,t):`probe-failed`}const Kr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`});function qr(e){return e.kind!==`simulator`&&e.target===`tv`?J:Kr}function Jr(e){let t=nt(e),n=new Map,r=async t=>{if(t.kind===`simulator`)return $;let r=n.get(t.id)??await Gr(e,t);return r!==`probe-failed`&&n.set(t.id,r),r===`supported`?J:r===`unsupported`?$:Wr},i=async e=>{let n=await t.inspectFacts(e),i=mr(e),a=await r(e);return Object.freeze({device:n.device,operations:{...n.operations,...i,appState:e.kind===`simulator`?Er:J,networkDump:J,screenRecordingStart:J,screenRecordingReattach:J,screenRecordingCleanup:J,...te({capture:e.kind===`simulator`?Y:J,customActions:Pr,withoutActiveApp:e.kind===`simulator`?Y:J}),...ie({capture:e.kind===`simulator`?Nr:J}),...oe({findText:Y}),...h({setViewport:Fr}),...he({focus:Q(e)}),...re({unsupported:X,plan:Z(e),directionalFling:Z(e),multiTouch:Ur(e,Vr),targetAuthoredDrag:Ur(e,Hr),viewport:Z(e)}),...ae({scroll:Z(e)}),...m({type:Q(e)}),...ve({unsupported:br,tap:Q(e),longPress:Q(e),hover:Sr,fill:Q(e)}),...ee({readTextAtPoint:e.kind===`simulator`?yr:J}),...pe({back:Q(e)}),...se({unsupported:Cr,home:Q(e),appSwitcher:Q(e)}),setFoldPose:wr,...de({triggerAppEvent:Q(e)}),...ue({setSetting:Q(e),readSetting:Q(e)}),...le({read:Q(e),wait:Q(e),accept:Q(e),dismiss:Q(e)}),...g({orientation:Q(e)}),...me({tvRemote:qr(e)}),...fe({unsupported:xr,status:Q(e),dismiss:Q(e),enter:Q(e)}),...ce({unsupported:a.available?$:a,read:a,write:a}),...ge({capture:Ye(e),query:Ir}),..._e({frames:Q(e),memorySample:Q(e),memorySnapshot:Q(e),nativeCapture:Q(e),profileReport:Q(e)}),ensureReady:J,bootTarget:J,bootTargetHeadless:e.kind===`emulator`?J:Tr,listApps:J,...Lr(e),shutdownTarget:e.kind===`emulator`?J:Mr}})};return Object.freeze({owner:q,ownsDevice:e=>e.platform===`android`,inspectFacts:i,bind:async n=>{let r=await t.bind(n),o=await i(n.device),s=await Un({host:e,device:n.device,owner:q,signal:n.scope.signal});return Object.freeze({device:r.device,owner:q,facts:o,operations:Object.freeze({...r.operations,...hr({host:e,device:n.device,signal:n.scope.signal}),...o.operations.appState.available?{appState:async()=>{n.scope.signal.throwIfAborted();let{runAndroidAdb:e}=await import(`./adb.js`).then(e=>e.t);return await Pe(async(t,r)=>await e(n.device,t,{...r,signal:n.scope.signal}),n.scope.signal)}}:{},networkDump:async t=>await at(e,n.device,t,n.scope.signal),...s,...a(o.operations.audioProbeStart,()=>Ce({host:e.audioProbe.hostCapture,device:n.device,owner:q})),...a(o.operations.perfFrames,()=>Xe({resolveHost:()=>e.perf.android,device:n.device,owner:q})),...Yr(e,n,o),ensureReady:async t=>await z(e,n.device,{...t,headless:!1},n.scope.signal),bootTarget:async t=>await z(e,n.device,{...t,headless:!1},n.scope.signal),...o.operations.bootTargetHeadless.available?{bootTargetHeadless:async t=>await z(e,n.device,{...t,headless:!0},n.scope.signal)}:{},listApps:async e=>{n.scope.signal.throwIfAborted();let{listAndroidApps:t}=await import(`./app-lifecycle.js`).then(e=>e.t);return(await t(e.device,e.filter)).map(e=>({id:e.package,name:e.name}))},...d(ir({host:e,device:n.device,signal:n.scope.signal}),o.operations),...o.operations.shutdownTarget.available?{shutdownTarget:async()=>await e.deviceShutdown.android.shutdownTarget(n.device,n.scope.signal)}:{}}),[Symbol.asyncDispose]:async()=>await r[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}function Yr(e,t,n){let r={device:t.device,signal:t.scope.signal,resolveInteractor:e.localInteractors.resolve};return{...n.operations.captureSnapshot.available?ne(r):{},...Re({...r,facts:n.operations,pause:async n=>await e.clock.sleep(n,t.scope.signal)})}}export{Jr as createAndroidPlatformRuntime};
1
+ import{r as e}from"./rolldown-runtime.js";import{H as t,P as n}from"./sdk-contracts.js";import{o as r}from"./sdk-device.js";import{$t as i}from"./sdk-batch.js";import{d as a}from"./scroll-gesture.js";import{c as o}from"./sdk-remote-config.js";import"./device.js";import{c as s,l as c}from"./device-rotation.js";import{a as l,i as u,o as d,r as f,s as ee,t as te}from"./runtime-deployment.js";import{t as p}from"./webdriver-source.js";import m from"node:fs";import h from"node:path";import ne,{readFile as re,stat as g}from"node:fs/promises";import{setTimeout as _}from"node:timers/promises";function v(e){return{provider:e.provider,providerSessionId:e.providerSessionId,status:e.artifacts.length>0?`ready`:`pending`,cloudArtifacts:e.artifacts,...e.artifacts.length>0?{}:{message:e.pendingMessage}}}function y(e){return{provider:e.provider,providerSessionId:e.providerSessionId,status:`unavailable`,cloudArtifacts:[],message:e.error instanceof Error?e.error.message:String(e.error)}}function b(e,t,n,r,i,a){let o=n[r],s=typeof o==`string`?o.trim():``;if(s.length!==0)return{provider:e,providerSessionId:t,kind:i,name:a,url:s,availability:`ready`}}function x(e){return{"x-agent-device-client":`agent-device-cli`,"x-agent-device-version":e}}async function S(e,r){try{await r()}catch(r){e instanceof n&&(e.details={...e.details,cleanupError:t(r)})}}function C(e){return`Basic ${Buffer.from(`${e.username}:${e.accessKey}`).toString(`base64`)}`}function ie(e){let t=0;for(;t<e.length&&e.charCodeAt(t)===47;)t+=1;return t===0?e:e.slice(t)}function ae(e){let t=e.length-1;for(;t>=0&&e.charCodeAt(t)===47;)--t;return t===e.length-1?e:e.slice(0,t+1)}function oe(e,t){let n=new URL(e);return n.pathname=`${ae(n.pathname)}/${t}`,n}function se(e){if(e.pathname.endsWith(`/`))return e;let t=new URL(e);return t.pathname=`${t.pathname}/`,t}async function ce(e,t,r){if(!(await g(e).catch(()=>void 0))?.isFile())throw new n(`INVALID_ARGS`,`${r.service} can only upload a regular app file: ${e}`,{provider:r.provider,appPath:e,hint:`Use an existing .ipa, .apk, or .aab file, or a .zip of the iOS simulator .app bundle.`});let i=new FormData;return i.set(t,new Blob([await re(e)]),h.basename(e)),i}async function le(e,t,r){let i=await fetch(t.endpoint,{method:`POST`,headers:{...x(t.clientVersion),Authorization:C(t.auth)},body:e,signal:r}),a=await T(i),o=t.readAppReference(a)?.trim();if(!i.ok||!o)throw new n(`COMMAND_FAILED`,`${t.service} app upload failed.`,{status:i.status,response:a});return o}function ue(e){return async({appPath:t,options:n,signal:r})=>({appReference:await e(t,r),bundleId:n?.appIdentifierHint,packageName:n?.packageNameHint,launchTarget:n?.appIdentifierHint??n?.packageNameHint})}async function de(e){let{app:t}=e,r=e.parseReference(t);if(r!==void 0)return r;if(/^https?:\/\//i.test(t))return t;let i=h.resolve(e.cwd??process.cwd(),t);if(!m.existsSync(i))throw new n(`INVALID_ARGS`,`${e.service} --provider-app must be ${e.referenceLabel}, URL, or existing local app path.`,{providerApp:t});return await e.uploadFile(i,e.signal)}const w=15e3;async function fe(e,t){let{service:r,unauthorizedHint:i,networkHint:a}=t.hints,o=`Retry connect or check the ${r} service status.`;try{let a=await fetch(e,{headers:{...x(t.clientVersion),...t.auth?{Authorization:C(t.auth)}:{}},signal:AbortSignal.timeout(w)});if(!a.ok){let e=a.status===401||a.status===403;throw new n(e?`UNAUTHORIZED`:`COMMAND_FAILED`,`${r} rejected connection verification.`,{status:a.status,hint:e?i:o})}let s=await T(a);if(s===void 0)throw new n(`COMMAND_FAILED`,`${r} connection verification answer was not JSON.`,{status:a.status,hint:o});return s}catch(e){throw e instanceof n?e:new n(`COMMAND_FAILED`,`${r} connection verification failed.`,{hint:a},e)}}async function pe(e,t){let r,i;try{r=await fetch(e,{headers:{...x(t.clientVersion),Authorization:C(t.auth)},signal:AbortSignal.timeout(w)}),i=await T(r)}catch(e){throw new n(`COMMAND_FAILED`,`${t.service} session details lookup failed.`,{hint:`Check network access to the ${t.service} API, then retry.`},e)}let a=i&&typeof i==`object`&&!Array.isArray(i)?i:void 0;if(!r.ok||!a)throw new n(`COMMAND_FAILED`,`${t.service} session details lookup failed.`,{status:r.status,response:i});return a}async function T(e){let t=await e.text();if(t.length!==0)try{return JSON.parse(t)}catch{return}}function me(e,t){let n=e=>e.replace(/(?:\.0)+$/,``);return n(e)===n(t)}function he(e,t){let r=o.find(e=>e===t);if(r)return r;throw new n(`INVALID_ARGS`,`Invalid ${e.flag} value: ${t}.`,{hint:`Use ${o.join(`|`)}.`,flag:e.flag,capability:e.capability})}function ge(e,t){if(e)return e;throw new n(`INVALID_ARGS`,`${t} lease allocation requires provider profile flags on the request.`)}function _e(e,t){let r=e.flags?.platform;if(r===`android`||r===`ios`)return r;throw new n(`INVALID_ARGS`,`${t} requires --platform ios|android.`)}function ve(e,t,r){let i=E(e,t);if(i)return i;throw new n(`INVALID_ARGS`,r)}function E(e,t){let n=e.flags?.[t];return typeof n==`string`&&n.length>0?n:void 0}function D(e,t,r){let i=e[t];if(i?.trim())return i;throw new n(`INVALID_ARGS`,`${r} requires ${t} in the environment.`)}function O(e,t){if(e.platform===`android`||e.platform===`ios`)return e.platform;throw new n(`INVALID_ARGS`,`connect ${t} requires --platform ios|android.`)}function k(e,t,r){if(e?.trim())return e;throw new n(`INVALID_ARGS`,`connect ${t} requires ${r}.`)}function A(e,t,r){let i=h.resolve(t,e);if(m.statSync(i,{throwIfNoEntry:!1})?.isFile())return i;throw new n(`INVALID_ARGS`,`${r} app file not found: ${i}`)}const j=`webdriver_request_timeout`;function M(e){return e instanceof n&&e.details?.reason===j}function N(e){return{dispatched:e}}const P=`webdriver_connect_refused`,F=`webdriver_request_interrupted`,ye=new Set([`ECONNREFUSED`,`ENOTFOUND`,`EAI_AGAIN`,`EHOSTUNREACH`,`ENETUNREACH`,`UND_ERR_CONNECT_TIMEOUT`]);function be(e){return e instanceof n&&e.details?.reason===P}const xe=new Set([`GET`,`HEAD`]),Se=Object.freeze({});var Ce=class{endpoint;headers;requestPolicy;constructor(e){this.endpoint=se(new URL(e.endpoint)),this.headers={...x(e.clientVersion),...e.auth?{Authorization:C(e.auth)}:{},...e.headers},this.requestPolicy={timeoutMs:e.requestPolicy?.timeoutMs??3e4,retryAttempts:e.requestPolicy?.retryAttempts??1,retryDelayMs:e.requestPolicy?.retryDelayMs??250}}async requestValue(e,t,n,r){return(await this.request(e,t,n,r)).value}async request(e,t,n,r){let i=r?.idempotent??xe.has(e);return await this.requestWithRetries(e,t,n,{retryAttempts:r?.retryAttempts??(i?this.requestPolicy.retryAttempts:0),timeoutMs:r?.timeoutMs??this.requestPolicy.timeoutMs,signal:r?.signal})}async requestWithRetries(e,t,n,r){let i;for(let a=0;a<=r.retryAttempts;a+=1)try{return await this.requestOnce(e,t,n,r.timeoutMs,r.signal)}catch(e){if(i=e,!Te(e,a,r.retryAttempts,r.signal))throw e;await _(this.requestPolicy.retryDelayMs,void 0,{signal:r.signal})}throw i}async requestOnce(e,t,n,r,i){let{ok:a,status:o,text:s}=await this.fetchWebDriver(e,t,n,r,i),c=s?De(s):{};if(a)return{status:o,value:Ee(c)};let l=Oe(o,c);throw H(l)&&V(R,{method:e,path:t,status:o,code:B(c)??null}),l}async fetchWebDriver(e,t,n,r,i){let a=new URL(ie(t),this.endpoint),o=n===void 0&&e===`POST`?Se:n,s=AbortSignal.timeout(r),c=i?AbortSignal.any([i,s]):s,l={method:e,path:t,timeoutMs:r,timeoutSignal:s,requestSignal:i},u;try{u=await fetch(a,{method:e,headers:{Accept:`application/json`,...o===void 0?{}:{"Content-Type":`application/json`},...this.headers},body:o===void 0?void 0:JSON.stringify(o),signal:c})}catch(e){throw I(e,l,`request`)}try{return{ok:u.ok,status:u.status,text:await u.text()}}catch(e){throw I(e,l,`response`)}}};function I(e,t,n){let{method:r,path:i,timeoutMs:a,timeoutSignal:o,requestSignal:s}=t;return s?.aborted?e:o.aborted?Me(r,i,a,e):n===`request`&&we(e)?Ne(r,i,e):n===`response`||e instanceof TypeError?Pe(r,i,e):e}function we(e){let t=L(e,0);return t.length>0&&t.every(e=>ye.has(e))}function L(e,t){if(t>4||!e||typeof e!=`object`)return[];let{code:n,cause:r}=e,i=e instanceof AggregateError?e.errors:[];return[...typeof n==`string`?[n]:[],...L(r,t+1),...i.flatMap(e=>L(e,t+1))]}function Te(e,t,n,r){return!r?.aborted&&Fe(e)&&t<n}function Ee(e){if(!e||typeof e!=`object`)return e;let t=e;return`value`in t?t.value:e}function De(e){try{return JSON.parse(e)}catch(t){throw new n(`COMMAND_FAILED`,`WebDriver response was not valid JSON.`,{text:e},t)}}function Oe(e,t){let r=t&&typeof t==`object`&&`value`in t?t.value:t,i=r&&typeof r==`object`&&typeof r.message==`string`?r.message:`WebDriver request failed with HTTP ${e}.`;return je(e,t)?new n(`COMMAND_FAILED`,i,{...z(),status:e,response:t}):new n(`COMMAND_FAILED`,i,{status:e,response:t,...e>=500?N(`unknown`):{}})}const R=`webdriver_route_unsupported`;function z(){return{reason:R,...N(`no`)}}const ke=new Set([`unknown command`,`unknown method`]),Ae=new Set([404,405,501]);function je(e,t){let n=B(t);return n===void 0?Ae.has(e):ke.has(n.toLowerCase())}function B(e){let t=e&&typeof e==`object`&&`value`in e?e.value:void 0,n=t&&typeof t==`object`?t.error:void 0;return typeof n==`string`?n:void 0}function V(e,t){import(`./diagnostics2.js`).then(e=>e.t).then(({emitDiagnostic:n})=>n({level:`debug`,phase:e,data:t})).catch(()=>void 0)}function H(e){return e instanceof n&&e.details?.reason===R}function Me(e,t,r,i){return new n(`COMMAND_FAILED`,`WebDriver ${e} ${t} timed out after ${r}ms.`,{reason:j,method:e,path:t,timeoutMs:r,...N(`unknown`)},i instanceof Error?i:void 0)}function Ne(e,t,r){return new n(`COMMAND_FAILED`,`WebDriver ${e} ${t} could not reach the driver.`,{reason:P,method:e,path:t,...N(`no`)},r instanceof Error?r:void 0)}function Pe(e,t,r){return new n(`COMMAND_FAILED`,`WebDriver ${e} ${t} lost its connection to the driver.`,{reason:F,method:e,path:t,...N(`unknown`)},r instanceof Error?r:void 0)}function Fe(e){if(M(e)||be(e)||e instanceof n&&e.details?.reason===F)return!0;if(e instanceof n){let t=e.details?.status;return typeof t==`number`&&t>=500}return!1}var Ie=class{transport;sessionCreateTimeoutMs;sessionId;constructor(e){this.transport=new Ce(e),this.sessionCreateTimeoutMs=e.requestPolicy?.sessionCreateTimeoutMs??18e4}async createSession(e,t){let n=Re(await this.requestValue(`POST`,`/session`,{capabilities:Le(e)},{timeoutMs:Be(this.sessionCreateTimeoutMs,t?.deadline)}));return this.sessionId=n.sessionId,n}async deleteSession(){let e=this.requireSessionId();await this.requestValue(`DELETE`,`/session/${e}`),this.sessionId=void 0}async installApp(e,t){await this.sessionRequest(`POST`,`/appium/device/install_app`,{appPath:e},{signal:t})}async activateApp(e){await this.appRouteWithSibling(`/appium/device/activate_app`,`mobile: activateApp`,e)}async terminateApp(e){await this.appRouteWithSibling(`/appium/device/terminate_app`,`mobile: terminateApp`,e)}async appRouteWithSibling(e,t,n){try{await this.sessionRequest(`POST`,e,{appId:n})}catch(r){if(!H(r))throw r;let{status:i}=await this.transport.request(`POST`,`/session/${this.requireSessionId()}/execute/sync`,{script:t,args:[{appId:n,bundleId:n}]});V(`webdriver_route_fallback`,{from:e,to:t,status:i})}}async performActions(e){await this.sessionRequest(`POST`,`/actions`,{actions:e})}async releaseActions(){await this.sessionRequest(`DELETE`,`/actions`)}async sendKeys(e){await this.sessionRequest(`POST`,`/keys`,{value:Array.from(e)})}async hideKeyboard(){await this.sessionRequest(`POST`,`/appium/device/hide_keyboard`)}async isKeyboardShown(e){let t;try{t=await this.sessionRequest(`GET`,`/appium/device/is_keyboard_shown`,void 0,{retryAttempts:0,...e===void 0?{}:{timeoutMs:e}})}catch(e){if(H(e))return`unsupported`;throw e}return typeof t==`boolean`?t:`unsupported`}async activeElement(e){let t=e===void 0?void 0:Date.now()+e,n;try{n=ze(await this.sessionRequest(`GET`,`/element/active`,void 0,G(t)))}catch(e){if(H(e))return`unsupported`;if(q(e))return`none`;throw e}if(n===void 0)return`unsupported`;try{let e=await this.sessionRequest(`GET`,`/element/${encodeURIComponent(n)}/rect`,void 0,G(t));return{id:n,rect:U(e)}}catch(e){if(H(e))return`unsupported`;if(q(e))return`none`;throw e}}async back(){await this.sessionRequest(`POST`,`/back`)}async setRotation(e){await this.sessionRequest(`POST`,`/rotation`,{x:0,y:0,z:e})}async setOrientation(e){await this.sessionRequest(`POST`,`/orientation`,{orientation:e})}async source(e){let t=await this.sessionRequest(`GET`,`/source`,void 0,e);if(typeof t!=`string`)throw new n(`COMMAND_FAILED`,`WebDriver source response was not a string`,{valueType:typeof t});return t}async screenshot(e){let t=await this.sessionRequest(`GET`,`/screenshot`);if(typeof t!=`string`)throw new n(`COMMAND_FAILED`,`WebDriver screenshot response was not base64 text`,{valueType:typeof t});await ne.writeFile(e,Buffer.from(t,`base64`))}async windowRect(){return U(await this.sessionRequest(`GET`,`/window/rect`))}async executeScript(e,t=[]){return await this.sessionRequest(`POST`,`/execute/sync`,{script:e,args:t})}async executeReadScript(e,t=[]){return await this.sessionRequest(`POST`,`/execute/sync`,{script:e,args:t},{idempotent:!0})}async sessionRequest(e,t,n,r){let i=this.requireSessionId();return await this.requestValue(e,`/session/${i}${t}`,n,r)}requireSessionId(){if(!this.sessionId)throw new n(`SESSION_NOT_FOUND`,`WebDriver session has not been created yet.`);return this.sessionId}async requestValue(e,t,n,r){return await this.transport.requestValue(e,t,n,r)}};function U(e){if(!e||typeof e!=`object`)throw new n(`COMMAND_FAILED`,`WebDriver window rect response was empty.`);let t=e,r={x:W(t,`x`),y:W(t,`y`),width:W(t,`width`),height:W(t,`height`)};if(r.x===void 0||r.y===void 0||r.width===void 0||r.height===void 0)throw new n(`COMMAND_FAILED`,`WebDriver window rect response was invalid.`,{response:t});return r}function W(e,t){let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function Le(e){return`alwaysMatch`in e||`firstMatch`in e?e:{alwaysMatch:e}}function Re(e){if(!e||typeof e!=`object`)throw new n(`COMMAND_FAILED`,`WebDriver create-session response was empty.`);let t=e,r=typeof t.sessionId==`string`?t.sessionId:typeof t.session_id==`string`?t.session_id:void 0;if(!r)throw new n(`COMMAND_FAILED`,`WebDriver create-session response missed sessionId.`,{response:t});return{sessionId:r,capabilities:t.capabilities&&typeof t.capabilities==`object`?t.capabilities:{}}}function ze(e){if(!e||typeof e!=`object`)return;let t=e,n=t[`element-6066-11e4-a52e-4f735466cecf`]??t.ELEMENT;return typeof n==`string`&&n.length>0?n:void 0}function G(e){return e===void 0?{retryAttempts:0}:{retryAttempts:0,timeoutMs:K(e)}}function Be(e,t){return t===void 0?e:Math.min(e,K(t))}function K(e){return Math.max(0,e-Date.now())}function q(e){return e instanceof n&&Ve(e).toLowerCase()===`no such element`}function Ve(e){let t=e.details?.response,n=t&&typeof t==`object`?t.value:void 0,r=n&&typeof n==`object`?n.error:void 0;return typeof r==`string`?r:``}function J(e,t){return{type:`pointer`,id:e,parameters:{pointerType:`touch`},actions:t}}async function He(e){return Y(p(e,`android`).nodes)}function Ue(e){return Y(p(e).nodes)}function Y(e){let t=e.flatMap(e=>We(e)&&Ge(e.rect)?[e.rect]:[]).sort((e,t)=>t.width*t.height-e.width*e.height)[0];return t?{x:t.x,y:t.y,width:t.width,height:t.height}:void 0}function We(e){let t=e.type?.toLowerCase()??``;return e.visibleToUser!==!1&&(t.includes(`scrollview`)||t.includes(`listview`)||t.includes(`recyclerview`))}function Ge(e){return!!e&&e.width>=50&&e.height>=50}async function Ke(e,t,r){let i=[];for(let n of t===`android`?[`rotation`,`orientation`]:[`orientation`,`rotation`])try{await qe(e,n,r);return}catch(e){if(!H(e))throw e;i.push({transport:n,error:e instanceof Error?e.message:String(e)})}throw new n(`COMMAND_FAILED`,`Could not set device orientation to ${r} on the hosted WebDriver session.`,{...z(),hint:`The provider driver rejected both orientation endpoints. Set the orientation as a session capability instead, for example connect --provider-device-orientation portrait.`,rotation:r,attempts:i})}async function qe(e,t,n){if(t===`rotation`){await e.setRotation(c(n));return}await e.setOrientation(s(n))}const X=1500;function Je(e){return new Promise(t=>setTimeout(t,e))}function Z(e,t,r){return new n(`COMMAND_FAILED`,`fill tapped (${e}, ${t}) but ${r}`,{reason:`text_entry_focus_not_observed`,x:e,y:t,hint:`The tap most likely missed the field. Re-check the target with snapshot -i and fill the element it reports, rather than retrying the same coordinates.`})}function Ye(e,t){return new n(`COMMAND_FAILED`,`fill tapped (${e}, ${t}) but this driver reports neither the focused element nor keyboard state, so the text was not sent`,{reason:`text_entry_focus_unobservable`,x:e,y:t,hint:`This provider cannot confirm a field took focus. Use press <target> followed by type <text> to enter it anyway, accepting that nothing witnesses which field receives the keys.`})}function Xe(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function Ze(e){return new Qe(e.client,e.backend,e.capabilities,e.targetId)}var Qe=class{client;backend;capabilities;targetId;constructor(e,t,n,r){this.client=e,this.backend=t,this.capabilities=n,this.targetId=r}async open(e,t){if(t?.url){await this.client.executeScript(`mobile: deepLink`,[{url:t.url,package:e}]);return}let n=t?.appBundleId??e;n&&await this.client.activateApp(n)}async openDevice(){await this.client.executeScript(`mobile: activateApp`,[{}])}async close(e){e&&await this.client.terminateApp(e)}async tap(e,t){return this.requireSupport(`tap`),await this.pointerGesture(`tap`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t}}async doubleTap(e,t){return this.requireSupport(`doubleTap`),await this.pointerGesture(`doubleTap`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0},{type:`pause`,duration:80},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t}}async swipe(e,t,n,r,i=400){return this.requireSupport(`swipe`),await this.pointerGesture(`swipe`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerMove`,duration:i,x:n,y:r},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x1:e,y1:t,x2:n,y2:r,durationMs:i}}async longPress(e,t,n=600){return this.requireSupport(`longPress`),await this.pointerGesture(`longPress`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pause`,duration:n},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t,durationMs:n}}async focus(e,t){return await this.tap(e,t)}async type(e){this.requireSupport(`type`),await this.client.sendKeys(e)}async fill(e,t,r,i){if(this.requireSupport(`fill`),r.length===0)throw new n(`UNSUPPORTED_OPERATION`,`fill with empty text (clear field) is not supported on the webdriver backend`,{hint:`Use a visible clear/reset control in the app, or fill the field with the intended replacement text directly.`});let a=await this.readTextEntryState();await this.tap(e,t);let o=await this.awaitTextEntryReadiness(a,e,t);return await this.type(r),{backend:`webdriver`,x:e,y:t,text:r,textEntryReadiness:o}}async scroll(e,t){this.requireSupport(`scroll`);let n=t?.durationMs??350;await this.client.hideKeyboard().catch(()=>void 0);let r=await this.scrollGestureFrame(),i=a({direction:e,amount:t?.amount,pixels:t?.pixels,referenceWidth:r.width,referenceHeight:r.height}),o={...i,x1:i.x1+r.x,y1:i.y1+r.y,x2:i.x2+r.x,y2:i.y2+r.y};return await this.swipe(o.x1,o.y1,o.x2,o.y2,n),{backend:`webdriver`,...o,distance:i.pixels,durationMs:n}}async gestureViewport(){return await this.scrollGestureFrame()}async performGesture(e){return this.requireSupport($e(e)),await this.client.performActions(e.pointers.map(e=>J(`gesture-pointer-${e.pointerId}`,Q(e.samples)))),await this.client.releaseActions().catch(()=>void 0),{backend:`webdriver-w3c-actions`}}async screenshot(e,t){this.requireSupport(`screenshot`),await this.client.screenshot(e)}async snapshot(e){return this.requireSupport(`snapshot`),await this.captureSource(e?.signal)}async captureSource(e){let t=await this.readSource(e);if(this.backend===`xctest`){let{acquireWebDriverIosSnapshot:e}=await import(`./webdriver-ios-snapshot.js`);return e(t,this.targetId)}let{parseWebDriverSourceFacts:n}=await import(`./webdriver-source.js`).then(e=>e.n);return{backend:`android`,producer:`appium-source`,nodes:n(t,`android`).nodes}}async readSource(e){try{return await this.client.source(e===void 0?{}:{signal:e})}catch(e){throw M(e)?et(e):e}}async back(e){this.requireSupport(`back`),await this.client.back()}async home(){this.requireSupport(`home`),await this.client.executeScript(`mobile: pressButton`,[{name:`home`}])}async setOrientation(e){this.requireSupport(`orientation`),await Ke(this.client,this.backend,e)}async appSwitcher(){this.requireSupport(`appSwitcher`),await this.client.executeScript(`mobile: pressButton`,[{name:`appSwitch`}])}async tvRemote(e,t){this.unsupported(`tvRemote`)}async keyboardStatus(){return this.requireSupport(`keyboard`),{kind:`ime-probe`,visible:await this.keyboardVisible()}}async keyboardDismiss(){this.requireSupport(`keyboard`);let e=await this.keyboardVisibility();if(e===!1)return this.dismissResult({wasVisible:e,visible:!1,dismissed:!1});await this.client.hideKeyboard();let t=await this.keyboardVisibilityAfterMutation();return this.dismissResult({...e===void 0?{}:{wasVisible:e},...t===void 0?{}:{visible:t,dismissed:e===!0&&!t}})}dismissResult(e){return this.backend===`android`?{kind:`ime-probe`,...e}:{kind:`mechanism`,mechanism:`appium-hide-keyboard`,...e}}async keyboardEnter(){if(this.requireSupport(`keyboard`),this.backend===`android`)return await this.client.executeScript(`mobile: pressKey`,[{keycode:66}]),{kind:`android-acknowledged`};let e=await this.keyboardVisibility();await this.client.sendKeys(`
2
+ `);let t=await this.keyboardVisibilityAfterMutation();return{kind:`visibility-echo`,...e===void 0?{}:{wasVisible:e},...t===void 0?{}:{visible:t}}}async keyboardVisibilityAfterMutation(){try{return await this.keyboardVisibility()}catch{return}}async keyboardVisibility(){let e=await this.client.isKeyboardShown(X);return e===`unsupported`?void 0:e}async keyboardVisible(){let e=await this.keyboardVisibility();if(e===void 0)throw new n(`UNSUPPORTED_OPERATION`,`This driver does not implement the keyboard visibility route.`,{provider:this.capabilities.provider,platform:this.capabilities.platform,operation:`keyboard`});return e}async readClipboard(){this.requireSupport(`clipboard.read`);let e=await this.client.executeReadScript(`mobile: getClipboard`,[{}]);return typeof e==`string`?e:``}async writeClipboard(e){this.requireSupport(`clipboard.write`),await this.client.executeScript(`mobile: setClipboard`,[{content:e}])}async setSetting(e,t,n,r){this.unsupported(`settings`)}async awaitTextEntryReadiness(e,t,n){let r=e.keyboard,i=Date.now()+2e3,a=e.focusedElementId,o=await this.pollWithinBudget(i,async e=>{let r=await this.client.activeElement(e);return r===`unsupported`?`abandon`:r===`none`?`retry`:r.id!==a||Xe(r.rect,t,n)?`satisfied`:`retry`});if(o===`satisfied`)return`focused-element`;if(o===`expired`)throw Z(t,n,`nothing there took text-entry focus, so the text was not sent`);if(r===`unsupported`)throw Ye(t,n);if(r)throw Z(t,n,`the keyboard was already up and this driver cannot report which field holds focus, so the text was not sent`);if(await this.pollWithinBudget(i,async e=>await this.client.isKeyboardShown(e)===!0?`satisfied`:`retry`)===`satisfied`)return`keyboard-shown`;throw Z(t,n,`no keyboard appeared, so the text was not sent`)}async readTextEntryState(){let[e,t]=await Promise.all([this.client.isKeyboardShown(X),this.client.activeElement(X)]);return{keyboard:e,focusedElementId:t===`none`||t===`unsupported`?void 0:t.id}}async pollWithinBudget(e,t){let n=!1,r;for(;;){let i=e-Date.now();if(i<=0)break;try{let e=await t(Math.min(X,i));if(n=!0,e!==`retry`)return e}catch(e){r=e}let a=e-Date.now();if(a<=0)break;await Je(Math.min(100,a))}if(!n&&r!==void 0)throw r;return`expired`}async pointerGesture(e,t){await this.client.performActions([J(e,t)]),await this.client.releaseActions().catch(()=>void 0)}async scrollGestureFrame(){return await this.client.source().then(e=>this.backend===`xctest`?Ue(e):He(e)).catch(()=>void 0)||await this.client.windowRect()}requireSupport(e){l(this.capabilities,e)||this.unsupported(e)}unsupported(e){throw new n(`UNSUPPORTED_OPERATION`,ee(this.capabilities,e),{provider:this.capabilities.provider,platform:this.capabilities.platform,operation:e})}};function Q(e){let t=e[0];if(!t)throw new n(`INVALID_ARGS`,`WebDriver gesture pointer requires samples`);let r=[{type:`pointerMove`,duration:0,x:t.point.x,y:t.point.y},{type:`pointerDown`,button:0}];for(let t=1;t<e.length;t+=1){let n=e[t-1],i=e[t];r.push({type:`pointerMove`,duration:i.offsetMs-n.offsetMs,x:i.point.x,y:i.point.y})}return r.push({type:`pointerUp`,button:0}),r}function $e(e){if(e.topology===`single`)return`swipe`;switch(e.intent){case`pan`:case`transform`:return`transformGesture`;case`pinch`:return`pinch`;case`rotate`:return`rotateGesture`}}function et(e){return new n(`COMMAND_FAILED`,`The cloud driver did not finish reading the screen in its budget.`,{...e.details,hint:`A screen that never goes idle (looping video, live ticker, continuous animation) gives the driver no moment to read the UI tree. This read has the transport's own budget and does not grow with --timeout; take a screenshot, or drive the screen from refs an earlier snapshot already captured.`},e)}var tt=class{sessionsByLeaseId=new Map;ownedDeviceIds=new Set;releasedProviderSessionIdsByLeaseId=new Map;options;constructor(e){this.options=e}ownsDevice(e){return this.ownedDeviceIds.has(e.id)}findSessionForDevice(e){return[...this.sessionsByLeaseId.values()].find(t=>t.device.id===e.id)}findSessionForLease(e){return this.sessionsByLeaseId.get(e)}getInteractor(e){return this.findSessionForDevice(e)?.interactor}heartbeat(e){if(e.leaseProvider===this.options.provider&&this.sessionsByLeaseId.has(e.leaseId))return{provider:this.options.provider}}async allocate(e,t){if(e.leaseProvider!==this.options.provider)return;let{rejectRefusedProviderProfileFields:n}=await import(`./provider-profile-fields.js`).then(e=>e.t);if(n(t?.flags,this.options.profileFields),this.sessionsByLeaseId.has(e.leaseId))return this.heartbeat(e);let r=await this.prepareSession(e,t),i=new Ie({clientVersion:this.options.clientVersion,endpoint:r.endpoint,auth:r.auth,headers:r.headers,requestPolicy:this.options.requestPolicy}),a=await this.createSessionWithPreparedCleanup(i,r,e,t),o=this.deviceForLease(e,r),s=r.providerSessionId??a.sessionId,c=d({provider:this.options.provider,platform:r.platform,overrides:this.options.capabilityOverrides});return this.sessionsByLeaseId.set(e.leaseId,Object.freeze({lease:e,device:o,client:i,prepared:r,capabilities:c,webDriverSessionId:a.sessionId,providerSessionId:s,interactor:Ze({client:i,backend:f(r.platform),capabilities:c,targetId:o.id})})),this.ownedDeviceIds.add(o.id),{provider:this.options.provider,deviceId:o.id,sessionId:a.sessionId,providerSessionId:s,capabilities:c,...r.providerData}}async release(e){if(e.leaseProvider!==this.options.provider)return;let t=this.sessionsByLeaseId.get(e.leaseId);if(!t)return;this.sessionsByLeaseId.delete(e.leaseId),this.releasedProviderSessionIdsByLeaseId.set(e.leaseId,t.providerSessionId);let n=await this.closeSession(t),r=await this.safeListArtifacts(t);return{provider:this.options.provider,providerSessionId:t.providerSessionId,...n.cleanup,...n.warnings.length>0?{warnings:n.warnings}:{},...r?{cloudArtifacts:r}:{}}}async listCloudArtifacts(e){if(e.provider!==this.options.provider)return;let t=this.sessionsByLeaseId.get(e.leaseId??``);return t?await this.listActiveCloudArtifacts(t,e.providerSessionId):await this.listReleasedCloudArtifacts(e)}async listActiveCloudArtifacts(e,t){if(!(t&&t!==e.providerSessionId))return await this.safeListArtifacts(e)}async listReleasedCloudArtifacts(e){let t=this.releasedProviderSessionIdsByLeaseId.get(e.leaseId??``);if(!(!t||!this.options.listArtifacts)&&!(e.providerSessionId&&e.providerSessionId!==t))return await this.options.listArtifacts({provider:this.options.provider,providerSessionId:t})}async shutdown(){await Promise.allSettled([...this.sessionsByLeaseId.values()].map(async e=>await this.closeSession(e))),this.sessionsByLeaseId.clear(),this.ownedDeviceIds.clear()}async createSessionWithPreparedCleanup(e,t,n,r){try{return await e.createSession(t.webdriverCapabilities,{deadline:r?.deadline})}catch(e){let r=M(e)?nt(e,this.options.provider,n,t):e;throw await S(r,()=>t.cleanup?.()),r}}async prepareSession(e,t){let n=this.baseSessionForLease(e);return this.options.prepareSession?await this.options.prepareSession({lease:e,req:t,base:n}):n}baseSessionForLease(e){let t=typeof this.options.webdriverCapabilities==`function`?this.options.webdriverCapabilities(e):this.options.webdriverCapabilities??{};return{provider:this.options.provider,endpoint:this.options.endpoint,platform:this.options.platform,deviceName:this.options.deviceName,auth:this.options.auth,headers:this.options.headers,webdriverCapabilities:u(this.options.platform,this.options.deviceName,t)}}deviceForLease(e,t){return{...r(t.platform),...t.platform===`ios`?{appleOs:`ios`}:{},id:t.deviceId??this.options.deviceId?.(e)??`${this.options.provider}:${t.platform}:${e.leaseId}`,name:t.deviceName,kind:`device`,target:`mobile`,booted:!0}}async closeSession(e){let n=[],r;try{await e.client.deleteSession()}catch(e){n.push({code:`WEBDRIVER_SESSION_DELETE_FAILED`,message:t(e)})}try{r=await e.prepared.cleanup?.()}catch(e){n.push({code:`PROVIDER_CLEANUP_FAILED`,message:t(e)})}return{cleanup:r,warnings:n}}async safeListArtifacts(e){let t=e.prepared.listArtifacts??this.options.listArtifacts;if(t)try{return await t({provider:this.options.provider,lease:e.lease,device:e.device,webDriverSessionId:e.webDriverSessionId,providerSessionId:e.providerSessionId})}catch(t){return y({provider:this.options.provider,providerSessionId:e.providerSessionId,error:t})}}};function nt(e,t,r,i){let a=e.details?.timeoutMs;return new n(`COMMAND_FAILED`,`${t} did not create the WebDriver session within ${String(a)}ms.`,{reason:`provider_session_create_timeout`,provider:t,leaseId:r.leaseId,runId:r.runId,timeoutMs:a,...i.providerSessionId?{providerSessionId:i.providerSessionId}:{},hint:`${t} may still finish creating the session after agent-device stopped waiting, and that session would keep billing until the provider reaps it. Before retrying, check ${t} for a running session created for lease ${r.leaseId} (run ${r.runId}) and stop it.`},e)}var rt=e({createCloudWebDriverRuntime:()=>$});function $(e){return new it(e)}var it=class{provider;owner;leaseLifecycle;cloudArtifacts;deviceInventoryProvider;capabilities;platformRuntimeModule;sessions;deployment;constructor(e){this.provider=e.provider,this.owner=i(e.provider,e.platform),this.capabilities=d({provider:e.provider,platform:e.platform,overrides:e.capabilityOverrides}),this.sessions=new tt(e),this.deployment=te({provider:e.provider,uploadApp:e.uploadApp,findSessionForDevice:e=>this.sessions.findSessionForDevice(e)}),this.platformRuntimeModule=Object.freeze({owner:this.owner,loadRuntime:async e=>await this.loadRuntime(e)}),this.leaseLifecycle={allocate:async(e,t)=>await this.sessions.allocate(e,t),heartbeat:async e=>this.sessions.heartbeat(e),release:async e=>await this.sessions.release(e)},this.cloudArtifacts={listCloudArtifacts:async e=>await this.sessions.listCloudArtifacts(e)},this.deviceInventoryProvider=async e=>{if(e.leaseProvider!==this.provider)return null;if(!e.leaseId)return[];let t=this.sessions.findSessionForLease(e.leaseId);return t?[t.device]:[]}}async loadRuntime(e){let{createWebDriverPlatformRuntimeOwner:t}=await import(`./platform-runtime2.js`);return t({host:e,owner:this.owner,ownsDevice:e=>this.ownsDevice(e),isSessionActive:e=>this.sessions.findSessionForDevice(e)!==void 0,deployment:this.deployment,capabilities:this.capabilities,snapshotAvailable:this.capabilities.operations.snapshot.support!==`unsupported`,screenshotAvailable:this.capabilities.operations.screenshot.support!==`unsupported`,getInteractor:e=>this.getInteractor(e)})}ownsDevice(e){return this.sessions.ownsDevice(e)}getInteractor(e){return this.sessions.getInteractor(e)}async installApp(e,t,n,r){return await this.deployment.installApp(e,t,n,r)}async installInstallablePath(e,t,n){return await this.deployment.installInstallablePath(e,t,n)}async shutdown(){await this.sessions.shutdown()}};export{b as S,_e as _,ue as a,me as b,le as c,k as d,O as f,ge as g,he as h,oe as i,E as l,ve as m,rt as n,pe as o,D as p,ce as r,fe as s,$ as t,S as u,de as v,v as x,A as y};
@@ -1 +1,5 @@
1
- import{J as e}from"./sdk-contracts.js";function t(e){return Object.freeze({canShutdownTarget:n,shutdownTarget:async(t,n)=>await r(e.commands,t,n)})}function n(e){return e.platform===`android`&&e.kind===`emulator`}async function r(t,n,r){if(n.booted===!1)return i();r.throwIfAborted();try{let e=await t.run({executable:`adb`,args:[`-s`,n.id,`emu`,`kill`],allowFailure:!0,timeoutMs:15e3},r);r.throwIfAborted();let i=e.exitCode??-1;return{success:i===0,exitCode:i,stdout:e.stdout,stderr:e.stderr}}catch(t){r.throwIfAborted();let n=e(t);return{success:!1,exitCode:-1,stdout:``,stderr:n.message,error:n}}}function i(){return{success:!0,exitCode:0,stdout:``,stderr:``}}export{t as createAndroidShutdownRuntime};
1
+ import{J as e,P as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{N as r}from"./sdk-device.js";import{Xt as i,nn as a,rn as o}from"./sdk-batch.js";import{n as s}from"./device-shell.js";import{n as c,t as l}from"./android-snapshot-quality.js";import{i as u,n as d}from"./recording-stop-observation.js";import{n as f,r as p,t as m}from"./application-lifecycle-runtime.js";import{A as h,B as g,C as ee,D as te,G as ne,H as re,I as ie,J as ae,N as oe,V as se,d as ce,h as le,n as ue,o as de,s as fe,v as pe,w as me,x as he,z as ge}from"./alert-runtime.js";import{n as _e}from"./audio-probe-runtime.js";import{n as ve}from"./perf-runtime.js";import{i as ye}from"./touch-runtime.js";import{a as be,n as xe}from"./durable-resource.js";import{n as Se}from"./async-lifecycle.js";import{i as Ce,l as we,n as Te,r as Ee,t as De}from"./src7.js";import{n as Oe}from"./screen-recording-completion.js";import{a as _,c as ke,n as Ae,o as je,s as Me,t as Ne}from"./device-readiness-runtime.js";import{n as Pe}from"./screen-recording-runtime.js";import{readAndroidAppStateWithExecutor as Fe}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as Ie}from"./clipboard-shell-response.js";import{i as Le,t as Re}from"./gesture-admission.js";import{t as ze}from"./local-interactor-operation-set.js";import{a as Be,i as v,n as y,r as Ve,t as He}from"./perf-runtime-operation-builder.js";import{t as b}from"./app-log-runtime.js";import{t as Ue}from"./mp4-duration.js";import{n as x,r as We}from"./managed-device-scope.js";import{a as Ge,n as Ke,o as qe,s as Je}from"./application-lifecycle-interaction.js";import S from"node:path";function Ye(e){return je(e)?Object.freeze({available:!0}):e.kind===`emulator`?Object.freeze({available:!1,reason:`unsupported-device-backend`,hint:`audio probe capture requires a macOS host.`}):Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`audio probe capture is supported for Android emulators on macOS hosts.`})}function Xe(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...He({platform:`Android`,expectedProfileKind:`simpleperf`,start:async e=>await t().start(n,r,e),reattach:async e=>await t().reattach(n,e),cleanup:async e=>await t().cleanup(n,e),writeProfileReport:async e=>await t().writeProfileReport(n,e)}),perfFrames:async({appId:e})=>({metric:e?await v(t().sampleFrames(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-gfxinfo-framestats`,description:`Rendered-frame health from the current adb shell dumpsys gfxinfo <package> framestats window. Dropped frames use Android gfxinfo janky-frame/frame-deadline data when available; this is not video recording FPS.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`since previous Android gfxinfo reset or app process start`,resetsAfterRead:!0,relatedActionsLimit:12}}),perfMemorySample:async({appId:e})=>({metric:e?await v(t().sampleMemory(n,e)):y(`Android`,`package`),sampling:{method:`adb-shell-dumpsys-meminfo`,description:`Memory snapshot from adb shell dumpsys meminfo <package>. Values are reported in kilobytes.`,unit:`kB`,topConsumerLimit:5}}),perfMemorySnapshot:async({appId:e,kind:r,outPath:i,artifactsDir:a})=>{let o=r??`android-hprof`,s=Ze();if(o!==`android-hprof`)return Be(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Ve();let c=i??S.join(a,`memory-android-hprof-${Qe()}.hprof`);return{artifact:await t().captureMemorySnapshot(n,e,c),support:s,sampling:{method:`adb-shell-am-dumpheap`,description:`Java heap dump captured with adb shell am dumpheap, pulled to a local artifact path.`,defaultKind:`android-hprof`,artifactOnly:!0}}}})}function Ze(){return{platform:`android`,defaultKind:`android-hprof`,androidHprof:!0,memgraph:!1,heapprofd:!1,heapprofdDecision:`Deferred until Android Perfetto/heapprofd plumbing is available in the perf trace slice.`}}function Qe(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function $e(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new t(`INVALID_ARGS`,`Invalid Android package name for logs: ${e}`)}const C=Object.freeze({resourceKind:b,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!tt(e.outputPath)||!tt(e.pidPath)?{status:`invalid`,message:`Invalid Android app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:e.transport,outputPath:e.outputPath,pidPath:e.pidPath})}});function et(e){let t=C.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return xe({resourceKind:b,sessionId:e.sessionId,device:{id:e.device.id,family:`android`,kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:be(C,t.descriptor)})}function tt(e){return typeof e==`string`&&e.trim().length>0}function nt(e){return Ee(e,{family:`android`,backend:`android`,label:`Android`,codec:C,startUnavailableHint:`The selected Android transport cannot start a background adb logcat stream.`,cleanupFailureMessage:`Android app-log cleanup did not settle every owned resource`,doctor:async({host:e,device:t,signal:n},r)=>await rt(e,t.id,r,n),validateStart:({input:e})=>$e(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await Ce(e,it(t.id,n.appBundleId),r),command:e=>({kind:`android-adb`,serial:t.id,args:[`logcat`,`-v`,`time`,`--pid`,e],options:{allowFailure:!0}})}),descriptor:({artifacts:e,transport:t})=>({transport:t.mode===`transport-composed`?`android-logcat-transport-composed`:`android-logcat-local`,...e}),envelope:({input:e,device:t,owner:n,descriptor:r})=>et({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function rt(e,t,n,r){let i={};return i.adbAvailable=await ke(async()=>Me(await e.commands.run({executable:`adb`,args:s(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(i.androidPidVisible=await ke(async()=>!!await Ce(e,it(t,n),r),r)),{backend:`android`,checks:i,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function it(e,t){return{executable:`adb`,args:s(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function at(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=Te(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await st(e,t,n,r);if(s&&n.appBundleId){$e(n.appBundleId);let c=await lt(e,t,n.appBundleId,r);if(c){let e=Te(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=De(e,a,n.maxEntries),o.push(s.reason===`stale-active`?`Session app log stream was still bound to prior Android PID ${s.trackedPid}. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`:`Session app log stream was inactive. Recovered recent Android HTTP entries from adb logcat for PID set ${c.pids.join(`, `)}.`))}}return n.appLogSnapshot?n.appLogSnapshot.state!==`active`&&o.length===0&&o.push(`Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump.`):o.push(`Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests.`),a.dump.entries.length===0&&o.push(`No HTTP(s) entries were found in recent session app logs.`),Object.freeze({source:`app-log`,backend:`android`,dump:a.dump,notes:Object.freeze(o)})}async function ot(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function st(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=ct(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await ut(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function ct(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function lt(e,t,n,r){let i=await ut(e,t.id,n,r),a=await ot(e,{executable:`adb`,args:[`-s`,t.id,`logcat`,`-d`,`-v`,`time`,`-t`,`4000`],allowFailure:!0,timeoutMs:3e3},r);if(!a||a.exitCode!==0||!a.stdout.trim())return;let o=dt(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
2
+ `).filter(e=>{if(!e.trim())return!1;if(e.includes(n))return!0;let t=/\(\s*(\d+)\)\s*:/.exec(e)?.[1];return!!(t&&s.has(t))}).join(`
3
+ `);return c.trim()?{text:c,pids:o}:void 0}async function ut(e,t,n,r){let i=await ot(e,{executable:`adb`,args:s(`adb`,`shell`,[`pidof`,n],[`-s`,t]),allowFailure:!0},r);if(!i)return;let a=i.stdout.trim().split(/\s+/)[0];return a&&/^\d+$/.test(a)?a:void 0}function dt(e,t,n){let r=new Set(n?[n]:[]),i=t.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),a=[RegExp(`\\bStart proc\\s+(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`\\b(\\d+):${i}(?:\\b|/)`,`i`),RegExp(`${i}.*?\\bpid\\s*[=:]?\\s*(\\d+)\\b`,`i`),RegExp(`\\bpid\\s*[=:]?\\s*(\\d+)\\b.*${i}`,`i`)];for(let n of e.split(`
4
+ `))if(n.includes(t))for(let e of a){let t=e.exec(n)?.[1];t&&/^\d+$/.test(t)&&r.add(t)}return Object.freeze([...r])}function w(e,t){if(t===1)return e;let n=S.parse(e);return S.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}const ft=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,pt=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function mt(e){return _t(e)&&vt(e)&&yt(e)}function ht(e){if(!T(e))return!1;let t=e;return bt(t)&&xt(t)&&St(t)&&Ct(t)&&(t.completion===void 0||At(t))}function gt(e,t){return jt(e,t)&&Mt(e,t.outputPath,t.clientOutputPath)}function _t(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&pt.test(e.manifestPath)&&typeof e.outputPath==`string`}function vt(e){return Pt(e.clientOutputPath)&&_(e)}function yt(e){return Nt(e.transportMode)}function bt(e){return e.version===1&&e.resourceKind===`screen-recording`&&typeof e.fenceToken==`string`&&Number.isInteger(e.fenceGeneration)&&typeof e.sessionId==`string`&&typeof e.deviceId==`string`&&Number.isFinite(e.startedAt)}function xt(e){return typeof e.outputPath==`string`&&Pt(e.clientOutputPath)&&_(e)}function St(e){return Nt(e.transportMode)&&(e.pendingRemotePath===void 0||Ft(e.pendingRemotePath))}function Ct(e){return Array.isArray(e.chunks)&&e.chunks.every(wt)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||Tt(e.completion))}function wt(e,t){if(!T(e))return!1;let n=e;return n.index===t+1&&Ft(n.remotePath)&&It(n.remotePid)&&It(n.remoteStartTime)}function Tt(e){if(!T(e))return!1;let t=e;return Dt(t)&&Ot(t)&&Et(t)&&(t.chunks===void 0||t.chunks.every(kt))}function Et(e){return(e.stopObservation===void 0||d(e.stopObservation))&&(e.nativePathDisposition===void 0||u(e.nativePathDisposition))}function Dt(e){return typeof e.backend==`string`&&typeof e.outPath==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)&&Number.isFinite(e.startedAt)&&Number.isFinite(e.completedAt)&&(e.capturedDurationMs===void 0||Number.isFinite(e.capturedDurationMs))}function Ot(e){return _(e)}function kt(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function At(e){let t=e.completion;return t!==void 0&&jt(t,e)&&t.startedAt===e.startedAt&&Mt(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function jt(e,t){return e.backend===`adb screenrecord`&&e.outPath===t.outputPath&&e.clientOutPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&Lt(e.activeSessionApp,t.activeSessionApp)}function Mt(e,t,n,r=e.chunks===void 0?1:e.chunks.length){return r===1?e.chunks===void 0:e.chunks?.length===r&&e.chunks.every((e,r)=>e.path===w(t,r+1)&&e.clientOutPath===(n===void 0?void 0:w(n,r+1)))}function T(e){return typeof e==`object`&&!!e}function Nt(e){return e===`local`||e===`transport-composed`}function Pt(e){return e===void 0||typeof e==`string`}function Ft(e){return typeof e==`string`&&ft.test(e)}function It(e){return typeof e==`string`&&/^\d+$/.test(e)}function Lt(e,t){return JSON.stringify(e)===JSON.stringify(t)}const E=Object.freeze({resourceKind:Pe,version:1,encode:e=>({...e}),decode:e=>mt(e)?{status:`decoded`,descriptor:Object.freeze({backend:`adb-screenrecord`,manifestPath:e.manifestPath,outputPath:e.outputPath,...e.clientOutputPath===void 0?{}:{clientOutputPath:e.clientOutputPath},scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,transportMode:e.transportMode,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...e.exportQuality===void 0?{}:{exportQuality:e.exportQuality},...e.fps===void 0?{}:{fps:e.fps}})}:{status:`invalid`,message:`Invalid Android screen-recording descriptor`}});function D(e,t,n,r,i,a=`local`){return Object.freeze({version:1,resourceKind:`screen-recording`,fenceToken:t.fence.token,fenceGeneration:t.fence.generation,sessionId:t.sessionId,deviceId:e.id,startedAt:n,outputPath:t.outputPath,...t.clientOutputPath===void 0?{}:{clientOutputPath:t.clientOutputPath},scope:t.scope,showTouches:t.showTouches,recordOnlySession:t.recordOnlySession,...t.activeSessionApp===void 0?{}:{activeSessionApp:t.activeSessionApp},...t.exportQuality===void 0?{}:{exportQuality:t.exportQuality},...t.fps===void 0?{}:{fps:t.fps},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Rt(e,t){return Object.freeze({...e,completion:t})}function O(e){try{let t=e&&JSON.parse(e);return ht(t)?t:void 0}catch{return}}function zt(e,t,n){return e.deviceId===t.id&&e.deviceId===n.device.id&&e.fenceToken===n.fence.token&&e.fenceGeneration===n.fence.generation&&e.sessionId===n.sessionId}function Bt(e,t){return e.outputPath===t.outputPath&&e.clientOutputPath===t.clientOutputPath&&e.scope===t.scope&&e.showTouches===t.showTouches&&e.recordOnlySession===t.recordOnlySession&&JSON.stringify(e.activeSessionApp)===JSON.stringify(t.activeSessionApp)&&e.exportQuality===t.exportQuality&&e.fps===t.fps&&e.transportMode===t.transportMode&&(e.completion===void 0||gt(e.completion,t))}function k(e){switch(e){case`missing`:case`ownership-lost`:case`foreign-writer`:return!0;case`owned-alive`:case`uncertain`:return!1}}function Vt(e){switch(e){case`missing`:case`ownership-lost`:return!0;case`foreign-writer`:case`owned-alive`:case`uncertain`:return!1}}const Ht=1e4,Ut=1e3;var A=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function j(e,t=Date.now()){return[...new Set(e?[e,`/sdcard`,`/data/local/tmp`]:[`/sdcard`,`/data/local/tmp`])].map(e=>`${e}/agent-device-recording-${t}.mp4`)}async function Wt(e,t,n,r){let i;try{if(i=(await e.start({remotePath:t,quality:n.exportQuality??`medium`},r)).process,!/^\d+$/.test(i.pid)||!/^\d+$/.test(i.startTime)||i.remotePath!==t)throw Error(`Android screenrecord returned an invalid process identity`);if(!await Xt(e,t,i,r))throw Error(`Android screenrecord did not begin producing frames`);return{index:1,remotePath:t,remotePid:i.pid,remoteStartTime:i.startTime}}catch(t){throw i&&Gt(i)&&!await Zt(e,i)?new A(t):r?.aborted?r.reason:t}}function Gt(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function M(e,t){let n=t.at(-1),r=!1,i;for(let a of[...t].reverse())try{let t=await P(e,a);a===n&&(r=t)}catch(e){i??=e}if(i)throw i;return r}async function Kt(e,t){for(let n of t){let t;for(let r=0;r<3;r+=1){let i=await e.size(n.remotePath);if(typeof i==`number`&&i>0&&i===t)break;if(t=typeof i==`number`&&i>0?i:void 0,r===2)throw Error(`Android recording artifact is not stable: ${n.remotePath}`);await new Promise(e=>setTimeout(e,250))}}}async function qt(e,t,n){for(let[r,i]of t.entries())await Qt(e,i.remotePath,w(n,r+1))}async function N(e,t){let n;for(let r of t)try{if(!await e.remove(r.remotePath))throw Error(`failed to remove Android recording artifact: ${r.remotePath}`)}catch(e){n??=e}if(n)throw n}async function Jt(e,t){for(let n of t)if(await e.exists(n.remotePath)!==!1)return`retirable`;return`retired`}async function Yt(e,t){try{await M(e,t)}finally{await N(e,t)}}async function Xt(e,t,n,r){for(let i=0;i<3;i+=1){if(r?.throwIfAborted(),await e.exists(t,r)===!0)return!0;if(await e.inspect(n,r)!==`owned-alive`)return!1;i<2&&await new Promise(e=>setTimeout(e,250))}return!0}async function Zt(e,t){try{let n=await e.stop(t,{force:!0});return(n===`stopped`||n===`already-missing`)&&await e.remove(t.remotePath)}catch{return!1}}async function P(e,t){if(!t)return!1;let n={pid:t.remotePid,remotePath:t.remotePath,startTime:t.remoteStartTime},r=await e.stop(n);if(r===`already-missing`)return!0;if(r===`ownership-lost`)throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.remotePid}`);if(await $t(e,n))return!1;let i=await e.stop(n,{force:!0});if(i===`stopped`||i===`already-missing`)return!1;throw Error(`failed to stop Android screenrecord pid ${t.remotePid}`)}async function Qt(e,t,n){for(let r=0;r<3;r+=1){let i=await e.pullPlayable({remotePath:t,outputPath:n});if(i.exitCode===0&&i.playable)return;r+1<3&&await en(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function $t(e,t){for(let n=0;n<=Ht;n+=Ut){let r=await e.inspect(t);if(r===`missing`)return!0;if(k(r))throw Error(`Android screenrecord ownership could not be confirmed for pid ${t.pid}`);n<Ht&&await en(Ut)}return!1}function en(e){return new Promise(t=>setTimeout(t,e))}async function F(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function I(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}async function tn(e,t){let n=(await nn(e)).flatMap(n=>rn(n,t,e.mode));for(let t of n)await on(e,t.evidence,t.manifestPath)}async function nn(e){return await Promise.all(j(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function rn(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw ln(e.manifestPath,e.read.message);let r=O(e.read.contents);if(r===void 0)throw un(e.manifestPath);if(r.transportMode!==n)throw dn(e.manifestPath,r,n);if(!an(r,t))throw fn(e.manifestPath,r,t);return[{manifestPath:e.manifestPath,evidence:r}]}function an(e,t){return e.completion!==void 0||e.deviceId!==t.id}async function on(e,t,n){if(await sn(e,t),await N(e,t.chunks),await cn(e,t),await I(e,n),(await e.readManifest(n)).status!==`missing`)throw hn(n)}async function sn(e,t){for(let n of t.chunks){let t=await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime});if(!Vt(t))throw t===`uncertain`?gn(n.remotePath):pn(n.remotePath,t===`owned-alive`?`named-recorder`:`other-recorder`)}let n=t.pendingRemotePath;if(n===void 0)return;let r=await e.probeRunningWriters(n);if(r.writers.length>0)throw pn(n,`other-recorder`);if(!r.conclusive)throw gn(n)}async function cn(e,t){let n=t.pendingRemotePath;if(n!==void 0&&!await e.remove(n))throw mn(n)}function ln(e,n){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unavailable: ${e}`,{reason:`native_recovery_evidence_unavailable`,manifestPath:e,hint:`Confirm the device is online and its storage readable, then run record start again.`},Error(n))}function un(e){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unreadable: ${e}`,{reason:`native_recovery_evidence_unreadable`,manifestPath:e,hint:L(e)})}function dn(e,n,r){return new t(`COMMAND_FAILED`,`Android screenrecord native recovery evidence was written by the ${n.transportMode} transport, not this ${r} one: ${e}`,{reason:`native_recovery_evidence_transport_mismatch`,manifestPath:e,evidenceTransportMode:n.transportMode,hint:L(e)})}function fn(e,n,r){return new t(`DEVICE_IN_USE`,`Android screenrecord native recovery evidence already exists: ${e} (open recording of session "${n.sessionId}" on ${r.id})`,{reason:`native_recovery_evidence_open`,manifestPath:e,sessionId:n.sessionId,retriable:!1,hint:`Run record stop --session ${n.sessionId} to retire it, or close that session. If it is already closed, ${L(e)}`})}function pn(e,n){let r=n===`named-recorder`;return new t(`DEVICE_IN_USE`,`Android screenrecord recovery evidence is retained: ${r?`its recorder`:`another recorder`} is writing ${e}`,{reason:`native_recording_artifact_claimed`,remotePath:e,writer:n,...r?{retriable:!1}:{},hint:r?`Run record stop for the session that owns that recording before starting another.`:`Android ends any recorder after 180 seconds. Run record start again once that recorder has stopped.`})}function mn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence could not remove ${e}`,{reason:`native_recording_artifact_removal_failed`,remotePath:e,hint:`Confirm the device is online and run record start again.`})}function hn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence removal could not be confirmed: ${e}`,{reason:`native_recovery_evidence_retirement_unconfirmed`,manifestPath:e,hint:`Run record start again; the marker is retired from the beginning.`})}function gn(e){return new t(`COMMAND_FAILED`,`Android screenrecord recovery evidence cannot be safely retired: ${e}`,{reason:`native_recording_recorder_unproven`,remotePath:e,hint:`Confirm the device is online and run record start again.`})}function L(e){return`no recording session can retire this marker; remove it on the device with \`adb shell rm -f ${e}\`.`}async function _n(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await tn(t,n),await o();let s;for(let e of j(void 0)){let o=t.manifestPathFor(e);await F(t,o,D(n,r,i,[],e,t.mode),a);let c,l;try{l=Date.now(),c=await Wt(t,e,r,a)}catch(e){if(a.aborted)throw await vn(t,o,e),a.reason;await xn(t,o,e),s=e;continue}try{await F(t,o,D(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await yn(t,o,c),e}return{chunk:c,manifestPath:o,startedAtMs:l}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function vn(e,t,n){n instanceof A||await I(e,t).catch(()=>{})}async function yn(e,t,n){try{await Yt(e,[n])}catch{return}await I(e,t).catch(()=>{})}async function bn(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of j(s)){await F(t,o,D(n,r,i,a,e,t.mode));try{return await Wt(t,e,r)}catch(e){if(e instanceof A)throw e;try{await F(t,o,D(n,r,i,a,void 0,t.mode))}catch{throw new A(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function xn(e,t,n){if(n instanceof A)throw n;try{await I(e,t)}catch{throw new A(n)}}function Sn(e,t){return Object.freeze({backend:`adb screenrecord`,outPath:e.outputPath,...e.clientOutputPath?{clientOutPath:e.clientOutputPath}:{},startedAt:t,scope:e.scope,showTouches:e.showTouches,recordOnlySession:e.recordOnlySession,...e.activeSessionApp?{activeSessionApp:e.activeSessionApp}:{},...e.exportQuality?{exportQuality:e.exportQuality}:{},...e.fps===void 0?{}:{fps:e.fps},gestureEvents:[]})}function Cn(e){let t=wn(e.chunkPaths);if(t===void 0)return{};let n=e.stoppedAtMs-e.startedAtMs;return n-t<2e3?{capturedDurationMs:t}:{capturedDurationMs:t,idleTailWarning:`Android screenrecord encodes a frame only when the screen changes, so this video ends at the last frame it encoded: it covers ${Tn(t)}s of the ${Tn(n)}s recording window.`}}function wn(e){let t=0;for(let n of e){let e=Ue(n);if(e===void 0)return;t+=e}return t}function Tn(e){return(e/1e3).toFixed(1)}async function En(e){let{host:t,transport:n,evidence:r,recording:i,startedAtMs:a,progress:o}=e,s=e.reachedLimit===!0;return await jn(e,await Ae({snapshot:i,progress:o,steps:{stop:async()=>(s=await M(n,r.chunks)||s,await Kt(n,r.chunks),{observation:{recorder:`confirmed`},...s?{warning:`Android adb screenrecord stopped before record stop, likely after reaching the 180s platform limit. The MP4 may be truncated; final interactions after the limit are not in the video.`}:{}}),collect:e=>qt(n,r.chunks,e),finalize:({collectedPath:e,exportPath:n,stoppedAtMs:o})=>Dn({host:t,evidence:r,recording:i,startedAtMs:a,stoppedAtMs:o,collectedPath:e,exportPath:n}),discard:e=>kn(t,e,r.chunks.length)}}))}async function Dn(e){let{host:t,evidence:n,recording:r,collectedPath:i,exportPath:a}=e,o=Mn({collectedPath:i,exportPath:a,exportClientPath:r.clientOutPath,count:n.chunks.length}),s=o.length>1,c;try{await On(t,o),c=await t.screenRecording.finalize.complete({outputPath:a,showTouches:!s&&r.showTouches,gestureEvents:r.gestureEvents,exportQuality:r.exportQuality??`medium`,...r.fps===void 0?{}:{fps:r.fps},targetLabel:`Android recording`})}catch(e){for(let{served:e}of o)await t.screenRecording.outputs.remove(e.path);throw e}let l=Cn({chunkPaths:o.map(({collected:e})=>e.path),startedAtMs:e.startedAtMs,stoppedAtMs:e.stoppedAtMs});return An({finalization:c,captured:l,recording:r,chunked:s,files:o})}async function On(e,t){for(let{collected:n,served:r}of t)await e.screenRecording.outputs.copy({from:n.path,to:r.path})}async function kn(e,t,n){for(let r=1;r<=n;r+=1)await e.screenRecording.outputs.remove(w(t,r))}function An(e){let{finalization:t,captured:n,recording:r,chunked:i,files:a}=e,o=[t.warning,...i?[`Android adb screenrecord is capped at 180s, so this recording was split into multiple MP4 chunks.`]:[],n.idleTailWarning].filter(e=>e!==void 0&&e.length>0);return{...t.telemetryPath===void 0?{}:{telemetryPath:t.telemetryPath},...o.length===0?{}:{warning:o.join(` `)},...i&&r.showTouches&&r.gestureEvents.length>0?{overlayWarning:`touch overlay burn-in is skipped for chunked Android recordings; returning raw chunks plus gesture telemetry`}:{},...n.capturedDurationMs===void 0?{}:{capturedDurationMs:n.capturedDurationMs},...i?{chunks:a.map(e=>e.served)}:{},nativePathDisposition:`retirable`}}async function jn(e,t){let{transport:n,evidence:r,manifestPath:i}=e;return await F(n,i,Rt(r,t.result)),await N(n,r.chunks),{status:`completed`,result:{...t.result,nativePathDisposition:await Jt(n,r.chunks)}}}function Mn(e){return Object.freeze(Array.from({length:e.count},(t,n)=>({collected:Object.freeze({index:n+1,path:w(e.collectedPath,n+1)}),served:Object.freeze({index:n+1,path:w(e.exportPath,n+1),...e.exportClientPath===void 0?{}:{clientOutPath:w(e.exportClientPath,n+1)}})})))}async function Nn(e,t,n){try{let r=t.pendingRemotePath;if(await M(e,[...t.chunks,...await Pn(e,t)]),await N(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await I(e,n),{status:`cleaned`}}catch(e){return Fn(e)}}async function Pn(e,t){let n=t.pendingRemotePath;if(n===void 0)return[];let r=await e.probeRunningWriters(n);if(!r.conclusive)throw Error(`cannot list every recorder writing Android artifact: ${n}`);return r.writers.map((e,r)=>({index:t.chunks.length+1+r,remotePath:n,remotePid:e.pid,remoteStartTime:e.startTime}))}function Fn(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function In(e){let{transport:t,device:n,envelope:r,descriptor:i}=e;if(i.transportMode!==t.mode)return{status:`transport-unavailable`};let a=await t.readManifest(i.manifestPath);if(a.status===`unavailable`)return{status:`transport-unavailable`};let o=a.status===`read`?O(a.contents):void 0;return o&&zt(o,n,r)&&Bt(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function Ln(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=O(t.contents);return n&&Rn(n,e)?n:void 0}function Rn(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function zn(e){let{host:t,transport:n,device:r,input:i}=e,a=E.decode(i.envelope.descriptor.body);if(a.status!==`decoded`)return R(`descriptor-invalid`);let o=await In({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await Vn({host:t,transport:n,device:r,input:i,descriptor:a.descriptor,evidence:o.evidence}):R(o.status===`transport-unavailable`?`transport-not-reattachable`:`ownership-fence-lost`)}async function Bn(e){let t=E.decode(e.input.envelope.descriptor.body);if(t.status!==`decoded`)return{status:`cleanup-pending`,reason:`manual-recovery-required`};let n=await In({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await Nn(e.transport,n.evidence,t.descriptor.manifestPath):n.status===`transport-unavailable`?{status:`cleanup-pending`,reason:`owner-unavailable`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function Vn(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0){let e=await Hn(n,o);return e.status===`terminal`?{status:`completed`,result:{...o.completion,nativePathDisposition:e.nativePathDisposition}}:R(`ownership-fence-lost`,`Android recording completed evidence still names a live or unverifiable recorder.`)}if(o.pendingRemotePath!==void 0)return R(`transport-not-reattachable`,`Android recording launch was interrupted before its process identity was committed.`);let s=o.chunks.at(-1);if(!s)return{status:`missing`};let c=await n.inspect({pid:s.remotePid,remotePath:s.remotePath,startTime:s.remoteStartTime});if(c!==`owned-alive`&&await n.exists(s.remotePath)===!1)return R(`transport-not-reattachable`,`Android recording process ended before its artifact could be recovered.`);let l=Un(i.envelope.sessionId,i.envelope.fence,a),u=!1;return{status:`active`,handle:Oe(Sn(l,o.startedAt),{finish:async(e,r)=>{let i=await En({host:t,transport:n,evidence:o,manifestPath:a.manifestPath,recording:e,startedAtMs:o.startedAt,reachedLimit:k(c),progress:r});return u=!0,i},forceCleanup:async()=>u?{status:`cleaned`}:await Bn({transport:n,device:r,input:i})})}}async function Hn(e,t){try{for(let n of t.chunks)if(!k(await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime})))return{status:`retained`};return{status:`terminal`,nativePathDisposition:await Jt(e,t.chunks)}}catch{return{status:`retained`}}}function Un(e,t,n){return{sessionId:e,outputPath:n.outputPath,...n.clientOutputPath===void 0?{}:{clientOutputPath:n.clientOutputPath},scope:n.scope,showTouches:n.showTouches,hideTouchesRequested:!1,recordOnlySession:n.recordOnlySession,...n.activeSessionApp===void 0?{}:{activeSessionApp:n.activeSessionApp},...n.exportQuality===void 0?{}:{exportQuality:n.exportQuality},...n.fps===void 0?{}:{fps:n.fps},fence:t}}function R(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function Wn(e){let{host:t,device:n,owner:r,signal:i}=e,a=await t.screenRecording.android.resolve(n);return Object.freeze({screenRecordingStart:async e=>await Gn({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await zn({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await Bn({transport:a,device:n,input:e})})}async function Gn(e){let{host:t,transport:n,device:i,owner:a,input:o,signal:s}=e;s.throwIfAborted();let c=Date.now(),l=await _n({transport:n,device:i,input:o,startedAt:c,signal:s,prepareOutput:async()=>await t.screenRecording.outputs.prepare(o.outputPath)}),u=l.manifestPath,d=[l.chunk],f,p,m,h=!1,g=()=>{f=setTimeout(()=>{p=ee().catch(e=>{m=e})},17e4),f.unref?.()},ee=async()=>{let e=d.at(-1);if(!e)throw Error(`Android recording has no active chunk`);let t=!1,r;try{r=await bn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:S.posix.dirname(e.remotePath)})}catch(a){await P(n,e),t=!0;try{r=await bn({transport:n,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:S.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:a}}let a=[...d,{...r,index:d.length+1}];try{await F(n,u,D(i,o,c,a,void 0,n.mode))}catch(a){if(await Yt(n,[r]).catch(()=>{}),t)await F(n,u,D(i,o,c,d,r.remotePath,n.mode)).catch(()=>{});else try{await F(n,u,D(i,o,c,d,void 0,n.mode))}catch{await P(n,e).catch(()=>{}),await F(n,u,D(i,o,c,d,r.remotePath,n.mode)).catch(()=>{})}throw a}d=a,t||await P(n,e),g()};g();let te=Oe(Sn(o,c),{finish:async(e,r)=>{if(f&&clearTimeout(f),await p,m)throw m;let a=await En({host:t,transport:n,evidence:D(i,o,c,d,void 0,n.mode),manifestPath:u,recording:e,startedAtMs:l.startedAtMs,progress:r});return h=!0,a},forceCleanup:async()=>{if(f&&clearTimeout(f),h)return{status:`cleaned`};try{await p}catch(e){m=e}let e=await Ln({transport:n,deviceId:i.id,sessionId:o.sessionId,fence:o.fence,manifestPath:u});return e?await Nn(n,e,u):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new Se(te),envelope:xe({resourceKind:Pe,sessionId:o.sessionId,device:r(i),owner:a,fence:o.fence,lifecycle:`open`,descriptor:be(E,{backend:`adb-screenrecord`,manifestPath:u,outputPath:o.outputPath,...o.clientOutputPath===void 0?{}:{clientOutputPath:o.clientOutputPath},scope:o.scope,showTouches:o.showTouches,recordOnlySession:o.recordOnlySession,...o.activeSessionApp===void 0?{}:{activeSessionApp:o.activeSessionApp},...o.exportQuality===void 0?{}:{exportQuality:o.exportQuality},...o.fps===void 0?{}:{fps:o.fps},transportMode:n.mode})})})}const Kn=1e3;async function z(e,t,n,r){return r.throwIfAborted(),await We(t)?{...t,booted:!0}:t.kind===`emulator`&&(t.booted!==!0||!B(t))?await qn(e,t,n,r):(t.booted!==!0&&await Zn(e,t.id,$n(e,n),r),{...t,booted:!0})}async function qn(e,t,n,r){await Jn(e);let i=er(n),a=$n(e,n),o=Yn(await e.deviceReadiness.androidEmulator.discover(i,r),t.name,n.serial),s=B(o)?o:void 0,c=s?void 0:e.deviceReadiness.androidEmulator.launch(o.name,n.headless);try{let t=s??await Xn(e,o.name,i,n.serial,a,r);return await Zn(e,t.id,a,r),{...(await e.deviceReadiness.androidEmulator.discover(i,r)).find(e=>e.id===t.id)??t,name:o.name,booted:!0}}catch(t){throw c!==void 0&&r.aborted&&await e.deviceReadiness.androidEmulator.terminate(c),r.throwIfAborted(),t}}async function Jn(e){if(await e.toolchains.prepare(`android`),!await e.commands.which(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await e.commands.which(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`)}function Yn(e,n,r){let i=tr(e,n,r);if(i)return i;throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${n}`,{requestedAvdName:n,availableAvds:e.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."})}async function Xn(e,t,n,r,i,a){for(;e.clock.now()<i;){let i=tr(await e.deviceReadiness.androidEmulator.discover(n,a),t,r);if(i&&B(i))return i;await e.clock.sleep(Kn,a)}throw Qn(`Android emulator did not appear in time`,{avdName:t,serial:r})}async function Zn(e,t,n,r){for(;e.clock.now()<n;){if((await e.commands.run({executable:`adb`,args:s(`adb`,`shell`,[`getprop`,`sys.boot_completed`],[`-s`,t]),allowFailure:!0,timeoutMs:Math.min(1e4,Math.max(1e3,n-e.clock.now()))},r)).stdout.trim()===`1`)return;await e.clock.sleep(Kn,r)}throw Qn(`Android device failed to finish booting`,{serial:t})}function Qn(e,n){return new t(`COMMAND_FAILED`,e,{...n,reason:Ne,hint:`The emulator keeps booting in the background. Retry once it is up, or pass a larger --timeout.`})}function $n(e,t){return t.deadlineAtMs??e.clock.now()+12e4}function er(e){return{platform:`android`,kind:`emulator`,...e.serial?{serial:e.serial}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}}}function tr(e,t,n){let r=nr(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&nr(e.name)===r&&(!n||!B(e)||e.id===n))}function B(e){return e.id.startsWith(`emulator-`)}function nr(e){return e.toLowerCase().replaceAll(`_`,` `).replaceAll(/\s+/g,` `).trim()}async function rr(e,t,n){try{let r=await e.snapshot({appBundleId:t,signal:n,transient:{settleBy:Date.now()+6e3}});return{observation:`androidSnapshot`in r&&r.androidSnapshot?.systemSurfaceOnly===!0?`unobservable`:`observable`}}catch(e){return n.throwIfAborted(),l(e)?{observation:`unobservable`}:{observation:`probe-failed`,failure:ir(e)}}}function ir(t){let n=e(t),r=c(n)??n.details?.reason,{code:i}=n;return typeof r==`string`?{source:`capture`,code:i,reason:r}:{source:`capture`,code:i}}function ar(e){let{host:t,device:n,signal:r}=e,i=Ke({device:n,signal:r,resolveInteractor:t.localInteractors.resolve});return Object.freeze({resolveOpenTarget:async e=>await t.androidApplications.resolveOpenTarget(n,e),prepareApplicationOpen:async e=>{await z(t,n,{headless:!1,deadlineAtMs:e.execution.startupDeadlineAtMs},r)},openApplication:async e=>await or(t,i,e),applyRuntimeHints:async e=>await t.androidApplications.applyRuntimeHints(n,e),clearRuntimeHints:async e=>await t.androidApplications.clearRuntimeHints(n,e),closeApplication:async e=>{e.ensureReady&&await z(t,n,{headless:!1},r),await qe({device:n,interactor:await i.resolveInteractor(e.execution,e.appBundleId),positionals:e.positionals})},finalizeApplicationClose:async e=>{await t.androidApplications.restoreTestIme(n,{stateDir:e.stateDir,shutdownTarget:e.shutdownTarget===!0&&n.kind===`emulator`,signal:r});let i=e.shutdownTarget&&n.kind===`emulator`?await t.deviceShutdown.android.shutdownTarget(n,r):void 0;return i===void 0?{}:{shutdown:i}},prepareAppleRunner:cr,configureProviderPortReverse:cr})}async function or(e,n,r){let i={};if(r.relaunch&&r.target){let e=Date.now();await qe({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:[r.appBundleId??r.target]}),i.relaunchCloseDurationMs=V(e)}if(p(r.runtimeHints)){if(!r.applyRuntimeHints)throw new t(`COMMAND_FAILED`,`Runtime hint operation was not admitted for this open.`,{reason:`runtime-hints-operation-missing`});let e=Date.now();await r.applyRuntimeHints({appId:r.appBundleId,values:r.runtimeHints}),i.runtimeHintsDurationMs=V(e)}let a=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:r.positionals,appBundleId:r.appBundleId,execution:r.execution}),i.openDispatchDurationMs=V(a),r.enableTestIme&&await e.androidApplications.activateTestIme(n.device,{stateDir:r.stateDir});let o=Ge(r);if(o){let e=Date.now();await Je({device:n.device,interactor:await n.resolveInteractor({...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0},r.appBundleId),positionals:[o],appBundleId:r.appBundleId,execution:{...r.execution,clearAppState:void 0,launchConsole:void 0,launchArgs:void 0}}),i.launchUrlDurationMs=V(e)}else i.launchUrlDurationMs=0;let s=await e.androidApplications.inferOpenedAppBundleId(n.device,r.target,r.appBundleId);s&&await e.androidApplications.resetFramePerfStats(n.device,s);let c=Date.now();return Object.assign(i,await sr(n,r,s)),i.postOpenSettleDurationMs=V(c),{appBundleId:s,timing:i}}async function sr(e,t,r){if(!t.target||n(t.target))return{};if(!r)return{postOpenObservation:`app-unidentified`};let i=await rr(await e.resolveInteractor(t.execution,r),r,e.signal);return i.observation===`probe-failed`?{postOpenObservation:`probe-failed`,postOpenObservationFailure:i.failure}:{postOpenObservation:i.observation}}function V(e){return Math.max(0,Date.now()-e)}async function cr(){throw new t(`UNSUPPORTED_OPERATION`,`This lifecycle operation is unavailable for Android.`)}async function H(e,t,n,r,i){U(n);let a=r?void 0:await pr(e,t,i);if(S.extname(n).toLowerCase()===`.aab`?await fr(e,t,n,i):G(await e.androidTools.installPackage(t,n,{replace:!0},i),`adb install failed`),r)return r;let o=[...await pr(e,t,i)].filter(e=>!a?.has(e));return o.length===1?o[0]:void 0}function U(e){if(x()&&S.extname(e).toLowerCase()===`.aab`)throw new t(`UNSUPPORTED_OPERATION`,`Managed Android deployment does not support app bundles.`,{reason:`managed-bundle-install-unavailable`,hint:`Install an APK on this managed device.`})}async function lr(e,t,n,r){let i=await W(e,t,[`uninstall`,n],r);if(i.exitCode===0)return;let a=`${i.stdout}\n${i.stderr}`.toLowerCase();a.includes(`unknown package`)||a.includes(`not installed`)||G(i,`adb uninstall failed for ${n}`)}async function ur(e,n,r,i){let a=r.payload,o=typeof a.action==`string`&&a.action.trim()?a.action.trim():`${r.appId}.TEST_PUSH`,c=[`am`,`broadcast`,`-a`,o,`-p`,r.appId];typeof a.receiver==`string`&&a.receiver.trim()&&c.push(`-n`,a.receiver.trim());let l=a.extras??{};if(typeof l!=`object`||!l||Array.isArray(l))throw new t(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=0;for(let[e,t]of Object.entries(l))e&&(mr(c,e,t),u+=1);return G(await W(e,n,s(`adb`,`shell`,c),i),`adb push broadcast failed`),{action:o,extrasCount:u}}function dr(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(/[._-]+/).map(e=>e.trim().toLowerCase()).filter(Boolean),r=[...n].reverse().find(e=>!t.has(e))??n.at(-1)??e;return r.charAt(0).toUpperCase()+r.slice(1)}async function fr(e,n,r,i){if(await e.androidTools.installBundle(n,r,`universal`,i))return;let a=await e.commands.which(`bundletool`),o=e.androidDeployment.bundletoolJar;if(!a&&!o)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR.`);let s=a?`bundletool`:`java`,c=a?[]:[`-jar`,o],l=await e.temporaryFiles.create({prefix:`agent-device-aab-`,suffix:`.apks`}),u=l.path;try{G(await e.commands.run({executable:s,args:[...c,`build-apks`,`--bundle`,r,`--output`,u,`--mode`,`universal`]},i),`bundletool build-apks failed`),G(await e.commands.run({executable:s,args:[...c,`install-apks`,`--apks`,u,`--device-id`,n.id]},i),`bundletool install-apks failed`)}finally{await l[Symbol.asyncDispose]()}}async function pr(e,t,n){let r=await W(e,t,s(`adb`,`shell`,[`pm`,`list`,`packages`]),n);return G(r,`adb package inventory failed`),new Set(r.stdout.split(`
5
+ `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}function mr(e,n,r){if(typeof r==`string`)e.push(`--es`,n,r);else if(typeof r==`boolean`)e.push(`--ez`,n,String(r));else if(typeof r==`number`&&Number.isFinite(r))e.push(Number.isInteger(r)?`--ei`:`--ef`,n,String(r));else throw new t(`INVALID_ARGS`,`Unsupported Android broadcast extra type for "${n}". Use string, boolean, or number.`)}async function W(e,t,n,r,i=15e3){return await e.androidTools.runAdb(t,n,{timeoutMs:i,allowFailure:!0},r)}function G(e,n){if(e.exitCode===0)return;let r={stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode};throw new t(`COMMAND_FAILED`,n,r)}const hr=Object.freeze({available:!0});function gr(e){let t=br(e);return Object.freeze({deployApp:t,materializeAppSource:t,deployMaterializedApp:t,sendPushNotification:t})}function _r(e){let{host:t,device:n,signal:r}=e;return gr(n).deployApp.available?Object.freeze({deployApp:async e=>await vr(t,n,e,r),materializeAppSource:async e=>await t.androidDeployment.prepareArtifact(e,{signal:r}),deployMaterializedApp:async e=>await yr(t,n,e,r),sendPushNotification:async e=>await ur(t,n,e,r)}):Object.freeze({})}async function vr(e,t,n,r){if(n.replaceExisting)return await e.androidDeployment.withInvalidatedAppResolutionCache(t,async()=>{let i;try{x()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),U(i.installablePath)),t.booted!==!0&&await z(e,t,{headless:!1},r);let a=await e.androidDeployment.resolveAppPackage(t,n.app);return await lr(e,t,a,r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),await H(e,t,i.installablePath,void 0,r),{packageName:a,launchTarget:a}}finally{await i?.cleanup()}});let i;try{x()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r}),U(i.installablePath)),t.booted!==!0&&await z(e,t,{headless:!1},r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r});let a=await H(e,t,i.installablePath,i.packageName,r);return a?{packageName:a,appName:dr(a),launchTarget:a}:{}}finally{await i?.cleanup()}}async function yr(e,n,r,i){let a=await H(e,n,r.artifact.installablePath,r.artifact.packageName,i);if(!a)throw new t(`COMMAND_FAILED`,`Installed Android app identity could not be resolved from the artifact or device state`);return{packageName:a,appName:dr(a),launchTarget:a}}function br(e){return e.kind===`emulator`||e.kind===`device`?hr:Object.freeze({available:!1,reason:`unsupported-device-kind`})}const K=i(`android`),q=Object.freeze({available:!0}),xr=a(`unsupported-device-kind`),J=a(`unsupported-device-kind`,`focus is supported on Android emulators and physical devices.`),Sr=a(`unsupported-device-kind`,`keyboard actions are supported on Android emulators and physical devices.`),Cr=a(`unsupported-platform-leaf`),wr=a(`unsupported-platform-leaf`,`Android has no key event for this system button.`),Tr=a(`unsupported-platform-leaf`,`fold drives the hinge of a foldable iPhone simulator; the Android emulator posture control is not driven by agent-device yet.`),Er=a(`unsupported-device-kind`,`Headless boot is supported only for Android emulators.`),Dr=a(`unsupported-device-kind`,`Android appstate is supported only for Android emulators and devices.`),Or=a(`unsupported-platform-leaf`,`Apple runner preparation is supported only for Apple targets.`),kr=a(`unsupported-device-kind`,`open is supported only for Android emulators and devices.`),Ar=a(`unsupported-device-kind`,`close is supported only for Android emulators and devices.`),jr=a(`unsupported-device-kind`,`Runtime hints are supported only for Android emulators and devices.`),Mr=a(`unsupported-provider-mode`,`Port reverse is supported only by an owning provider runtime.`),Nr=a(`unsupported-device-kind`,`shutdown is supported only for Apple simulators and Android emulators.`),Pr=a(`unsupported-device-kind`,`screenshot is supported only for Android emulators and devices.`),Y=a(`unsupported-device-kind`,`snapshot is supported only for Android emulators and devices.`),Fr=a(`unsupported-platform-leaf`,`Re-run without --actions, or target an iOS simulator.`),Ir=a(`unsupported-platform-leaf`,`viewport resizes web targets only (--platform web).`),Lr=a(`unsupported-platform-leaf`,`the stateless audio page probe is a web-session operation; Android targets use the host capture.`);function Rr(e){let t=zr(e),n=Br(e),r=Vr(e);return m({resolveOpenTarget:t,prepareApplicationOpen:t,openApplication:t,applyRuntimeHints:r,clearRuntimeHints:r,closeApplication:n,finalizeApplicationClose:n,prepareAppleRunner:Or,configureProviderPortReverse:Mr})}function zr(e){return e.kind===`emulator`||e.kind===`device`?q:kr}function Br(e){return e.kind===`emulator`||e.kind===`device`?q:Ar}function Vr(e){return e.kind===`emulator`||e.kind===`device`?q:jr}const X=a(`unsupported-device-kind`,`Gestures are supported on Android emulators and physical devices.`),Hr=a(`unsupported-platform-leaf`,Re),Ur=a(`unsupported-platform-leaf`,Le);function Wr(e,t){return e.kind===`simulator`?X:e.target===`tv`?t:q}function Z(e){return e.kind===`simulator`?X:q}function Q(e){return e.kind===`simulator`?J:q}const $=a(`owner-capability-missing`,Ie),Gr=a(`owner-capability-missing`,`Could not determine whether this Android build supports a shell clipboard: the adb probe did not complete. Retry once the device is reachable.`);async function Kr(e,t){let n=e.androidTools?.probeClipboardShellSupport;return n?await n.call(e.androidTools,t):`probe-failed`}const qr=a(`unsupported-device-kind`,`tv-remote is supported only on Android TV targets.`);function Jr(e){return e.kind!==`simulator`&&e.target===`tv`?q:qr}function Yr(e){let t=nt(e),n=new Map,r=async t=>{if(t.kind===`simulator`)return $;let r=n.get(t.id)??await Kr(e,t);return r!==`probe-failed`&&n.set(t.id,r),r===`supported`?q:r===`unsupported`?$:Gr},i=async e=>{let n=await t.inspectFacts(e),i=gr(e),a=await r(e);return Object.freeze({device:n.device,operations:{...n.operations,...i,appState:e.kind===`simulator`?Dr:q,networkDump:q,screenRecordingStart:q,screenRecordingReattach:q,screenRecordingCleanup:q,...ne({capture:e.kind===`simulator`?Y:q,customActions:Fr,withoutActiveApp:e.kind===`simulator`?Y:q}),...ae({capture:e.kind===`simulator`?Pr:q}),...se({findText:Y}),...g({setViewport:Ir}),...ge({focus:Q(e)}),...ie({unsupported:X,plan:Z(e),directionalFling:Z(e),multiTouch:Wr(e,Hr),targetAuthoredDrag:Wr(e,Ur),viewport:Z(e)}),...oe({scroll:Z(e)}),...h({type:Q(e)}),...ye({unsupported:J,tap:Q(e),longPress:Q(e),hover:Cr,fill:Q(e)}),...te({readTextAtPoint:e.kind===`simulator`?xr:q}),...me({back:Q(e)}),...ce({unsupported:wr,home:Q(e),appSwitcher:Q(e)}),setFoldPose:Tr,...fe({triggerAppEvent:Q(e)}),...de({setSetting:Q(e),readSetting:Q(e)}),...ue({read:Q(e),wait:Q(e),accept:Q(e),dismiss:Q(e)}),...ee({orientation:Q(e)}),...he({tvRemote:Jr(e)}),...pe({unsupported:Sr,status:Q(e),dismiss:Q(e),enter:Q(e)}),...le({unsupported:a.available?$:a,read:a,write:a}),..._e({capture:Ye(e),query:Lr}),...ve({frames:Q(e),memorySample:Q(e),memorySnapshot:Q(e),nativeCapture:Q(e),profileReport:Q(e)}),ensureReady:q,bootTarget:q,bootTargetHeadless:e.kind===`emulator`?q:Er,listApps:q,...Rr(e),shutdownTarget:e.kind===`emulator`?q:Nr}})};return Object.freeze({owner:K,ownsDevice:e=>e.platform===`android`,inspectFacts:i,bind:async n=>{let r=await t.bind(n),a=await i(n.device),s=await Wn({host:e,device:n.device,owner:K,signal:n.scope.signal});return Object.freeze({device:r.device,owner:K,facts:a,operations:Object.freeze({...r.operations,..._r({host:e,device:n.device,signal:n.scope.signal}),...a.operations.appState.available?{appState:async()=>{n.scope.signal.throwIfAborted();let{runAndroidAdb:e}=await import(`./adb.js`).then(e=>e.t);return await Fe(async(t,r)=>await e(n.device,t,{...r,signal:n.scope.signal}),n.scope.signal)}}:{},networkDump:async t=>await at(e,n.device,t,n.scope.signal),...s,...o(a.operations.audioProbeStart,()=>we({host:e.audioProbe.hostCapture,device:n.device,owner:K})),...o(a.operations.perfFrames,()=>Xe({resolveHost:()=>e.perf.android,device:n.device,owner:K})),...Xr(e,n,a),ensureReady:async t=>await z(e,n.device,{...t,headless:!1},n.scope.signal),bootTarget:async t=>await z(e,n.device,{...t,headless:!1},n.scope.signal),...a.operations.bootTargetHeadless.available?{bootTargetHeadless:async t=>await z(e,n.device,{...t,headless:!0},n.scope.signal)}:{},listApps:async e=>{n.scope.signal.throwIfAborted();let{listAndroidApps:t}=await import(`./app-lifecycle.js`).then(e=>e.t);return(await t(e.device,e.filter)).map(e=>({id:e.package,name:e.name}))},...f(ar({host:e,device:n.device,signal:n.scope.signal}),a.operations),...a.operations.shutdownTarget.available?{shutdownTarget:async()=>await e.deviceShutdown.android.shutdownTarget(n.device,n.scope.signal)}:{}}),[Symbol.asyncDispose]:async()=>await r[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}function Xr(e,t,n){let r={device:t.device,signal:t.scope.signal,resolveInteractor:e.localInteractors.resolve};return{...n.operations.captureSnapshot.available?re(r):{},...ze({...r,facts:n.operations,pause:async n=>await e.clock.sleep(n,t.scope.signal)})}}export{Yr as createAndroidPlatformRuntime};