agent-device 0.21.8 → 0.21.9

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 (171) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.8.apk → agent-device-android-ime-helper-0.21.9.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.9.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.8.manifest.json → agent-device-android-ime-helper-0.21.9.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.8.apk → agent-device-android-snapshot-helper-0.21.9.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.9.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.8.manifest.json → agent-device-android-snapshot-helper-0.21.9.manifest.json} +6 -6
  7. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubWindowInventory.swift +65 -0
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +45 -140
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubSidebar.swift +57 -0
  10. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubWindowDiscovery.swift +108 -0
  11. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubWindowInventoryTests.swift +65 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +175 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +10 -2
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +42 -15
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +8 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +45 -22
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +39 -734
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +20 -4
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +63 -1
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +13 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -10
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +5 -562
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +566 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +5 -1
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +594 -0
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +35 -1
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +160 -0
  29. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +3 -0
  30. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-frames.swift +203 -0
  31. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +5 -0
  32. package/dist/src/absence-observation-errors.js +1 -1
  33. package/dist/src/adapter.js +1 -1
  34. package/dist/src/agent-browser-lifecycle.js +1 -1
  35. package/dist/src/agent-browser-process-record.js +1 -1
  36. package/dist/src/agent-device-client.js +1 -1
  37. package/dist/src/alert-runtime.js +1 -1
  38. package/dist/src/android-adb.js +1 -1
  39. package/dist/src/android-input-ownership.js +1 -1
  40. package/dist/src/android.js +1 -1
  41. package/dist/src/app-launch.js +1 -1
  42. package/dist/src/app-log-runtime2.js +3 -3
  43. package/dist/src/app-resolution.js +2 -2
  44. package/dist/src/apple-runner-platform.js +1 -1
  45. package/dist/src/application-lifecycle-interaction.js +1 -1
  46. package/dist/src/artifact-paths.js +1 -0
  47. package/dist/src/back-mode.js +1 -1
  48. package/dist/src/cli-config.js +1 -1
  49. package/dist/src/cli-help.js +8 -7
  50. package/dist/src/cli.js +4 -4
  51. package/dist/src/client-types.d.ts +23 -5
  52. package/dist/src/command-tools.js +3 -3
  53. package/dist/src/connection-runtime.js +1 -1
  54. package/dist/src/device-claim-inspection.js +1 -1
  55. package/dist/src/device-claim-rule.js +2 -2
  56. package/dist/src/device-input-state.d.ts +1 -1
  57. package/dist/src/device-selection-resolver.js +1 -1
  58. package/dist/src/device.js +1 -1
  59. package/dist/src/device2.js +1 -1
  60. package/dist/src/dispatch-resolve.js +1 -1
  61. package/dist/src/doctor-facade.js +1 -1
  62. package/dist/src/durable-resource.js +1 -1
  63. package/dist/src/find.js +1 -1
  64. package/dist/src/finders.js +1 -1
  65. package/dist/src/fold-runtime.js +1 -0
  66. package/dist/src/gesture-admission.js +1 -1
  67. package/dist/src/interaction-positionals.js +1 -1
  68. package/dist/src/interaction-ref-policy.js +1 -1
  69. package/dist/src/interaction.js +1 -1
  70. package/dist/src/interaction2.js +1 -1
  71. package/dist/src/interactor-operation-catalog.js +1 -1
  72. package/dist/src/interactor.js +4 -4
  73. package/dist/src/interactors.js +1 -1
  74. package/dist/src/internal/bin.js +1 -1
  75. package/dist/src/internal/daemon.js +2 -2
  76. package/dist/src/inventory2.js +1 -1
  77. package/dist/src/ios-snapshot-acquisition.js +1 -1
  78. package/dist/src/ios-snapshot-runtime.js +1 -1
  79. package/dist/src/lease.js +1 -1
  80. package/dist/src/local-interactor-operation-set.js +1 -1
  81. package/dist/src/location-coordinates.js +1 -1
  82. package/dist/src/managed-device-scope.js +1 -1
  83. package/dist/src/mechanics.js +17 -17
  84. package/dist/src/mobile-snapshot-semantics.js +1 -1
  85. package/dist/src/mp4-duration.js +1 -0
  86. package/dist/src/multitouch-support.js +1 -1
  87. package/dist/src/owner-identity.js +1 -1
  88. package/dist/src/parameterized-recorded-fill.js +1 -1
  89. package/dist/src/perf-facade.js +2 -2
  90. package/dist/src/perf-runtime-plan.js +1 -1
  91. package/dist/src/platform-request-scope.js +1 -1
  92. package/dist/src/platform-runtime-managed-owner.js +1 -1
  93. package/dist/src/platform-runtime-open-target.js +1 -1
  94. package/dist/src/platform-runtime-operation-host.js +2 -2
  95. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  96. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  97. package/dist/src/platform-runtime-unavailable.js +1 -1
  98. package/dist/src/platform-runtime.js +1 -1
  99. package/dist/src/platform-runtime2.js +1 -1
  100. package/dist/src/png-crop-bytes.js +1 -1
  101. package/dist/src/png-encode.js +1 -0
  102. package/dist/src/png-size.js +1 -0
  103. package/dist/src/provider-webdriver.js +1 -1
  104. package/dist/src/quality-warnings.js +1 -1
  105. package/dist/src/react-native.js +1 -1
  106. package/dist/src/record-runtime.js +1 -1
  107. package/dist/src/recording-export-quality.js +1 -1
  108. package/dist/src/recording-scope.js +1 -0
  109. package/dist/src/recording.js +3 -0
  110. package/dist/src/registry.js +35 -35
  111. package/dist/src/replay.js +2 -2
  112. package/dist/src/request-admission.js +1 -1
  113. package/dist/src/request-runtime-binding.js +1 -1
  114. package/dist/src/result-serialization.js +1 -1
  115. package/dist/src/runner-cache-metadata.js +2 -2
  116. package/dist/src/runner-client.js +1 -1
  117. package/dist/src/runner-contract.js +1 -1
  118. package/dist/src/runner-dev-tools-security.js +1 -1
  119. package/dist/src/runner-device-readiness.js +1 -1
  120. package/dist/src/runner-disposal.js +1 -1
  121. package/dist/src/runner-operations-facade.js +1 -1
  122. package/dist/src/runner-presentation.js +1 -1
  123. package/dist/src/runner.js +1 -1
  124. package/dist/src/runtime.js +2 -2
  125. package/dist/src/runtime10.js +2 -1
  126. package/dist/src/runtime2.js +4 -4
  127. package/dist/src/runtime4.js +5 -5
  128. package/dist/src/runtime5.js +1 -1
  129. package/dist/src/runtime6.js +1 -1
  130. package/dist/src/runtime7.js +1 -1
  131. package/dist/src/runtime8.js +1 -1
  132. package/dist/src/runtime9.js +1 -1
  133. package/dist/src/screen-recording-admission-ledger.js +1 -1
  134. package/dist/src/screen-recording-resource-recovery.js +1 -1
  135. package/dist/src/screen-recording-transport.js +1 -1
  136. package/dist/src/screenshot-density.js +1 -1
  137. package/dist/src/screenshot-overlay-draw.js +1 -0
  138. package/dist/src/screenshot-runtime.js +1 -1
  139. package/dist/src/script.js +1 -1
  140. package/dist/src/scroll-gesture.js +1 -1
  141. package/dist/src/sdk-batch.js +2 -2
  142. package/dist/src/sdk-contracts.d.ts +7 -5
  143. package/dist/src/sdk-device.js +1 -1
  144. package/dist/src/sdk-finders.js +1 -1
  145. package/dist/src/sdk-selectors.d.ts +44 -1
  146. package/dist/src/sdk-selectors.js +1 -1
  147. package/dist/src/selection.js +0 -0
  148. package/dist/src/selector-runtime.js +1 -1
  149. package/dist/src/selectors.js +1 -1
  150. package/dist/src/semantic-index.js +1 -1
  151. package/dist/src/session-routing.js +1 -1
  152. package/dist/src/session-snapshot.js +1 -1
  153. package/dist/src/session-store.js +3 -3
  154. package/dist/src/session2.js +3 -3
  155. package/dist/src/simctl.js +1 -1
  156. package/dist/src/simulator-boot.js +1 -1
  157. package/dist/src/snapshot-runtime-binding.js +1 -1
  158. package/dist/src/snapshot-runtime.js +1 -1
  159. package/dist/src/snapshot-state.js +1 -1
  160. package/dist/src/snapshot4.js +1 -1
  161. package/dist/src/src.js +1 -1
  162. package/dist/src/src7.js +1 -1
  163. package/dist/src/stop-sequence.js +1 -1
  164. package/dist/src/text-entry-focus.js +1 -1
  165. package/dist/src/tree.js +1 -1
  166. package/dist/src/type-text-runtime.js +1 -1
  167. package/dist/src/video.js +2 -2
  168. package/package.json +1 -1
  169. package/server.json +2 -2
  170. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +0 -1
  171. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +0 -1
@@ -1,5 +1,5 @@
1
- import{D as e}from"./sdk-contracts.js";import{T as t}from"./sdk-device.js";import{$t as n,qt as r}from"./sdk-batch.js";import{n as i}from"./device-shell.js";import{i as a,n as o}from"./recording-stop-observation.js";import{n as s,r as c,t as l}from"./application-lifecycle-runtime.js";import{C as u,E as d,F as f,I as p,L as m,M as h,R as g,V as ee,W as te,_ as ne,a as re,b as ie,f as ae,h as oe,i as se,k as ce,l as le,t as ue,y as de}from"./alert-runtime.js";import{n as fe}from"./audio-probe-runtime.js";import{n as pe}from"./perf-runtime.js";import{i as me}from"./touch-runtime.js";import{a as he,n as ge}from"./durable-resource.js";import{n as _e}from"./async-lifecycle.js";import{i as ve,l as ye,n as be,r as xe,t as Se}from"./src7.js";import{n as Ce}from"./screen-recording-completion.js";import{a as we,i as Te,r as Ee,t as De}from"./stop-sequence.js";import{n as Oe}from"./screen-recording-runtime.js";import{t as ke}from"./mp4-atoms.js";import{readAndroidAppStateWithExecutor as Ae}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as je}from"./clipboard-shell-response.js";import{i as Me,t as Ne}from"./gesture-admission.js";import{t as Pe}from"./local-interactor-operation-set.js";import{a as Fe,i as Ie,n as Le,r as Re,t as ze}from"./perf-runtime-operation-builder.js";import{t as Be}from"./app-log-runtime.js";import{n as _,r as Ve}from"./managed-device-scope.js";import{a as He,i as Ue,n as We,o as Ge}from"./application-lifecycle-interaction.js";import v from"node:path";import y from"node:fs";function Ke(e){return Ee(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 qe(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...ze({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 Ie(t().sampleFrames(n,e)):Le(`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 Ie(t().sampleMemory(n,e)):Le(`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=Je();if(o!==`android-hprof`)return Fe(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Re();let c=i??v.join(a,`memory-android-hprof-${Ye()}.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 Je(){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 Ye(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function Xe(t){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new e(`INVALID_ARGS`,`Invalid Android package name for logs: ${t}`)}const b=Object.freeze({resourceKind:Be,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!Qe(e.outputPath)||!Qe(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 Ze(e){let t=b.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return ge({resourceKind:Be,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:he(b,t.descriptor)})}function Qe(e){return typeof e==`string`&&e.trim().length>0}function $e(e){return xe(e,{family:`android`,backend:`android`,label:`Android`,codec:b,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 et(e,t.id,r,n),validateStart:({input:e})=>Xe(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await ve(e,tt(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})=>Ze({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function et(e,t,n,r){let a={};return a.adbAvailable=await we(async()=>Te(await e.commands.run({executable:`adb`,args:i(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(a.androidPidVisible=await we(async()=>!!await ve(e,tt(t,n),r),r)),{backend:`android`,checks:a,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function tt(e,t){return{executable:`adb`,args:i(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function nt(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=be(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await it(e,t,n,r);if(s&&n.appBundleId){Xe(n.appBundleId);let c=await ot(e,t,n.appBundleId,r);if(c){let e=be(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=Se(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 rt(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function it(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=at(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await st(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function at(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function ot(e,t,n,r){let i=await st(e,t.id,n,r),a=await rt(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=ct(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
1
+ import{D as e}from"./sdk-contracts.js";import{E as t}from"./sdk-device.js";import{Yt as n,tn as r}from"./sdk-batch.js";import{n as i}from"./device-shell.js";import{i as a,n as o}from"./recording-stop-observation.js";import{n as s,r as c,t as l}from"./application-lifecycle-runtime.js";import{A as u,D as d,G as f,H as p,I as m,L as h,N as g,R as ee,a as _,b as te,g as ne,o as re,p as ie,t as ae,u as oe,v as se,w as ce,x as le,z as ue}from"./alert-runtime.js";import{n as de}from"./audio-probe-runtime.js";import{n as fe}from"./perf-runtime.js";import{i as pe}from"./touch-runtime.js";import{a as me,n as he}from"./durable-resource.js";import{n as ge}from"./async-lifecycle.js";import{i as _e,l as ve,n as ye,r as be,t as xe}from"./src7.js";import{n as Se}from"./screen-recording-completion.js";import{a as Ce,i as v,o as we,s as Te,t as Ee}from"./stop-sequence.js";import{n as De}from"./screen-recording-runtime.js";import{readAndroidAppStateWithExecutor as Oe}from"./app-state.js";import{ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT as ke}from"./clipboard-shell-response.js";import{i as Ae,t as je}from"./gesture-admission.js";import{t as Me}from"./local-interactor-operation-set.js";import{a as Ne,i as Pe,n as Fe,r as Ie,t as Le}from"./perf-runtime-operation-builder.js";import{t as Re}from"./app-log-runtime.js";import{t as ze}from"./mp4-duration.js";import{n as y,r as Be}from"./managed-device-scope.js";import{a as Ve,i as He,n as Ue,o as We}from"./application-lifecycle-interaction.js";import b from"node:path";function Ge(e){return Ce(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 Ke(e){let{resolveHost:t,device:n,owner:r}=e;return Object.freeze({...Le({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 Pe(t().sampleFrames(n,e)):Fe(`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 Pe(t().sampleMemory(n,e)):Fe(`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=qe();if(o!==`android-hprof`)return Ne(`Android`,o,s,`Use perf memory snapshot --kind android-hprof for Android Java heap artifacts.`);if(!e)throw Ie();let c=i??b.join(a,`memory-android-hprof-${Je()}.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 qe(){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 Je(){return new Date().toISOString().replaceAll(/[:.]/g,`-`)}function Ye(t){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new e(`INVALID_ARGS`,`Invalid Android package name for logs: ${t}`)}const x=Object.freeze({resourceKind:Re,version:1,encode:e=>({...e}),decode:e=>e.transport!==`android-logcat-local`&&e.transport!==`android-logcat-transport-composed`||!Ze(e.outputPath)||!Ze(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 Xe(e){let t=x.decode(e.descriptor);if(t.status!==`decoded`)throw TypeError(t.message);return he({resourceKind:Re,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:me(x,t.descriptor)})}function Ze(e){return typeof e==`string`&&e.trim().length>0}function Qe(e){return be(e,{family:`android`,backend:`android`,label:`Android`,codec:x,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 $e(e,t.id,r,n),validateStart:({input:e})=>Ye(e.appBundleId),process:async({host:e,device:t,input:n})=>({resolvePid:async r=>await _e(e,et(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})=>Xe({sessionId:e.sessionId,device:t,owner:n,fence:e.fence,descriptor:r})})}async function $e(e,t,n,r){let a={};return a.adbAvailable=await Te(async()=>we(await e.commands.run({executable:`adb`,args:i(`adb`,`shell`,[`echo`,`ok`],[`-s`,t]),allowFailure:!0,timeoutMs:1e3},r)),r),n&&(a.androidPidVisible=await Te(async()=>!!await _e(e,et(t,n),r),r)),{backend:`android`,checks:a,notes:n?[]:[`No app bundle is tracked in this session. Run open <app> first for app-scoped logs.`]}}function et(e,t){return{executable:`adb`,args:i(`adb`,`shell`,[`pidof`,t],[`-s`,e]),allowFailure:!0,timeoutMs:5e3}}async function tt(e,t,n,r){let i=await e.appLogs.readRecent(n.sessionId,n.maxScanLines),a=ye(i.text,{...n,path:i.path,exists:i.exists,lineNumberOffset:i.skippedLines,backend:`android`}),o=[],s=await rt(e,t,n,r);if(s&&n.appBundleId){Ye(n.appBundleId);let c=await at(e,t,n.appBundleId,r);if(c){let e=ye(c.text,{...n,path:`${i.path} (adb logcat recovery)`,exists:!0,backend:`android`});e.dump.entries.length>0&&(a=xe(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 nt(e,t,n){n.throwIfAborted();try{let r=await e.commands.run(t,n);return n.throwIfAborted(),r}catch{n.throwIfAborted();return}}async function rt(e,t,n,r){if(!n.appBundleId||n.appLogSnapshot?.state===void 0)return;if(n.appLogSnapshot.state!==`active`)return{reason:`inactive`};let i=it(await e.appLogs.readProcessMarker(n.sessionId));if(!i)return;let a=await ot(e,t.id,n.appBundleId,r);if(!(!a||a===i))return{reason:`stale-active`,trackedPid:i}}function it(e){if(e.status===`decoded`)return/(?:^|\s)--pid\s+(\d+)(?:\s|$)/.exec(e.marker.command)?.[1]}async function at(e,t,n,r){let i=await ot(e,t.id,n,r),a=await nt(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=st(a.stdout,n,i);if(o.length===0)return;let s=new Set(o),c=a.stdout.split(`
2
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 st(e,t,n,r){let a=await rt(e,{executable:`adb`,args:i(`adb`,`shell`,[`pidof`,n],[`-s`,t]),allowFailure:!0},r);if(!a)return;let o=a.stdout.trim().split(/\s+/)[0];return o&&/^\d+$/.test(o)?o:void 0}function ct(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 x(e,t){if(t===1)return e;let n=v.parse(e);return v.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}const lt=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,ut=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function dt(e){return mt(e)&&ht(e)&&gt(e)}function ft(e){if(!S(e))return!1;let t=e;return _t(t)&&vt(t)&&yt(t)&&bt(t)&&(t.completion===void 0||Dt(t))}function pt(e,t){return Ot(e,t)&&kt(e,t.outputPath,t.clientOutputPath)}function mt(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&ut.test(e.manifestPath)&&typeof e.outputPath==`string`}function ht(e){return(e.clientOutputPath===void 0||typeof e.clientOutputPath==`string`)&&C(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function gt(e){return At(e.transportMode)&&jt(e.exportQuality)&&w(e.activeSessionApp)}function _t(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 vt(e){return typeof e.outputPath==`string`&&(e.clientOutputPath===void 0||typeof e.clientOutputPath==`string`)&&C(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`}function yt(e){return w(e.activeSessionApp)&&jt(e.exportQuality)&&At(e.transportMode)&&(e.pendingRemotePath===void 0||Mt(e.pendingRemotePath))}function bt(e){return Array.isArray(e.chunks)&&e.chunks.every(xt)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||St(e.completion))}function xt(e,t){if(!S(e))return!1;let n=e;return n.index===t+1&&Mt(n.remotePath)&&Nt(n.remotePid)&&Nt(n.remoteStartTime)}function St(e){if(!S(e))return!1;let t=e;return wt(t)&&Tt(t)&&Ct(t)&&(t.chunks===void 0||t.chunks.every(Et))}function Ct(e){return(e.stopObservation===void 0||o(e.stopObservation))&&(e.nativePathDisposition===void 0||a(e.nativePathDisposition))}function wt(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 Tt(e){return C(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`&&w(e.activeSessionApp)}function Et(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function Dt(e){let t=e.completion;return t!==void 0&&Ot(t,e)&&t.startedAt===e.startedAt&&kt(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function Ot(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&&Pt(e.activeSessionApp,t.activeSessionApp)}function kt(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===x(t,r+1)&&e.clientOutPath===(n===void 0?void 0:x(n,r+1)))}function S(e){return typeof e==`object`&&!!e}function C(e){return e===`app`||e===`device`||e===`system`}function At(e){return e===`local`||e===`transport-composed`}function jt(e){return e===void 0||e===`medium`||e===`high`}function w(e){return e===void 0||S(e)&&typeof e.bundleId==`string`&&(e.name===void 0||typeof e.name==`string`)}function Mt(e){return typeof e==`string`&&lt.test(e)}function Nt(e){return typeof e==`string`&&/^\d+$/.test(e)}function Pt(e,t){return JSON.stringify(e)===JSON.stringify(t)}const T=Object.freeze({resourceKind:Oe,version:1,encode:e=>({...e}),decode:e=>dt(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}})}:{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},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Ft(e,t){return Object.freeze({...e,completion:t})}function D(e){try{let t=e&&JSON.parse(e);return ft(t)?t:void 0}catch{return}}function It(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 Lt(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.transportMode===t.transportMode&&(e.completion===void 0||pt(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 Rt(e){switch(e){case`missing`:case`ownership-lost`:return!0;case`foreign-writer`:case`owned-alive`:case`uncertain`:return!1}}const zt=1e4,Bt=1e3;var k=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function A(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 Vt(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 qt(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&&Ht(i)&&!await Jt(e,i)?new k(t):r?.aborted?r.reason:t}}function Ht(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function j(e,t){let n=t.at(-1),r=!1,i;for(let a of[...t].reverse())try{let t=await N(e,a);a===n&&(r=t)}catch(e){i??=e}if(i)throw i;return r}async function Ut(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 Wt(e,t,n){for(let[r,i]of t.entries())await Yt(e,i.remotePath,x(n,r+1))}async function M(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 Gt(e,t){for(let n of t)if(await e.exists(n.remotePath)!==!1)return`retirable`;return`retired`}async function Kt(e,t){try{await j(e,t)}finally{await M(e,t)}}async function qt(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 Jt(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 N(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 Xt(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 Yt(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 Zt(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function Xt(e,t){for(let n=0;n<=zt;n+=Bt){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<zt&&await Zt(Bt)}return!1}function Zt(e){return new Promise(t=>setTimeout(t,e))}async function P(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function F(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}async function Qt(e,t){let n=(await $t(e)).flatMap(n=>en(n,t,e.mode));for(let t of n)await nn(e,t.evidence,t.manifestPath)}async function $t(e){return await Promise.all(A(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function en(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw on(e.manifestPath,e.read.message);let r=D(e.read.contents);if(r===void 0)throw sn(e.manifestPath);if(r.transportMode!==n)throw cn(e.manifestPath,r,n);if(!tn(r,t))throw ln(e.manifestPath,r,t);return[{manifestPath:e.manifestPath,evidence:r}]}function tn(e,t){return e.completion!==void 0||e.deviceId!==t.id}async function nn(e,t,n){if(await rn(e,t),await M(e,t.chunks),await an(e,t),await F(e,n),(await e.readManifest(n)).status!==`missing`)throw fn(n)}async function rn(e,t){for(let n of t.chunks){let t=await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime});if(!Rt(t))throw t===`uncertain`?pn(n.remotePath):un(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 un(n,`other-recorder`);if(!r.conclusive)throw pn(n)}async function an(e,t){let n=t.pendingRemotePath;if(n!==void 0&&!await e.remove(n))throw dn(n)}function on(t,n){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unavailable: ${t}`,{reason:`native_recovery_evidence_unavailable`,manifestPath:t,hint:`Confirm the device is online and its storage readable, then run record start again.`},Error(n))}function sn(t){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unreadable: ${t}`,{reason:`native_recovery_evidence_unreadable`,manifestPath:t,hint:I(t)})}function cn(t,n,r){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence was written by the ${n.transportMode} transport, not this ${r} one: ${t}`,{reason:`native_recovery_evidence_transport_mismatch`,manifestPath:t,evidenceTransportMode:n.transportMode,hint:I(t)})}function ln(t,n,r){return new e(`DEVICE_IN_USE`,`Android screenrecord native recovery evidence already exists: ${t} (open recording of session "${n.sessionId}" on ${r.id})`,{reason:`native_recovery_evidence_open`,manifestPath:t,sessionId:n.sessionId,retriable:!1,hint:`Run record stop --session ${n.sessionId} to retire it, or close that session. If it is already closed, ${I(t)}`})}function un(t,n){let r=n===`named-recorder`;return new e(`DEVICE_IN_USE`,`Android screenrecord recovery evidence is retained: ${r?`its recorder`:`another recorder`} is writing ${t}`,{reason:`native_recording_artifact_claimed`,remotePath:t,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 dn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence could not remove ${t}`,{reason:`native_recording_artifact_removal_failed`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function fn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence removal could not be confirmed: ${t}`,{reason:`native_recovery_evidence_retirement_unconfirmed`,manifestPath:t,hint:`Run record start again; the marker is retired from the beginning.`})}function pn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence cannot be safely retired: ${t}`,{reason:`native_recording_recorder_unproven`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function I(e){return`no recording session can retire this marker; remove it on the device with \`adb shell rm -f ${e}\`.`}async function mn(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await Qt(t,n),await o();let s;for(let e of A(void 0)){let o=t.manifestPathFor(e);await P(t,o,E(n,r,i,[],e,t.mode),a);let c,l;try{l=Date.now(),c=await Vt(t,e,r,a)}catch(e){if(a.aborted)throw await hn(t,o,e),a.reason;await vn(t,o,e),s=e;continue}try{await P(t,o,E(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await gn(t,o,c),e}return{chunk:c,manifestPath:o,startedAtMs:l}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function hn(e,t,n){n instanceof k||await F(e,t).catch(()=>{})}async function gn(e,t,n){try{await Kt(e,[n])}catch{return}await F(e,t).catch(()=>{})}async function _n(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of A(s)){await P(t,o,E(n,r,i,a,e,t.mode));try{return await Vt(t,e,r)}catch(e){if(e instanceof k)throw e;try{await P(t,o,E(n,r,i,a,void 0,t.mode))}catch{throw new k(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function vn(e,t,n){if(n instanceof k)throw n;try{await F(e,t)}catch{throw new k(n)}}function yn(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}:{},gestureEvents:[]})}const bn=[`moov`,`mvhd`];function xn(e){let t=Cn(e);if(!t)return;let n=t[0];if(n===1)return Sn(t.readUInt32BE(20),Number(t.readBigUInt64BE(24)));if(n!==0)return;let r=t.readUInt32BE(16);if(r!==4294967295)return Sn(t.readUInt32BE(12),r)}function Sn(e,t){if(!(e<=0||t<0||!Number.isSafeInteger(t)))return Math.round(t*1e3/e)}function Cn(e){let t=ke(e,bn);if(!t||!Number.isSafeInteger(t.size))return;let n=t.offset+t.headerSize;if(t.size-t.headerSize<32)return;let r=Buffer.alloc(32),i;try{return i=y.openSync(e,`r`),y.readSync(i,r,0,r.length,n)===r.length?r:void 0}catch{return}finally{i!==void 0&&y.closeSync(i)}}function wn(e){let t=Tn(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 ${En(t)}s of the ${En(n)}s recording window.`}}function Tn(e){let t=0;for(let n of e){let e=xn(n);if(e===void 0)return;t+=e}return t}function En(e){return(e/1e3).toFixed(1)}async function Dn(e){let{host:t,transport:n,evidence:r,recording:i,startedAtMs:a,progress:o}=e,s=e.reachedLimit===!0;return await Mn(e,await De({snapshot:i,progress:o,steps:{stop:async()=>(s=await j(n,r.chunks)||s,await Ut(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=>Wt(n,r.chunks,e),finalize:({collectedPath:e,exportPath:n,stoppedAtMs:o})=>On({host:t,evidence:r,recording:i,startedAtMs:a,stoppedAtMs:o,collectedPath:e,exportPath:n}),discard:e=>An(t,e,r.chunks.length)}}))}async function On(e){let{host:t,evidence:n,recording:r,collectedPath:i,exportPath:a}=e,o=Nn({collectedPath:i,exportPath:a,exportClientPath:r.clientOutPath,count:n.chunks.length}),s=o.length>1,c;try{await kn(t,o),c=await t.screenRecording.finalize.complete({outputPath:a,showTouches:!s&&r.showTouches,gestureEvents:r.gestureEvents,exportQuality:r.exportQuality??`medium`,targetLabel:`Android recording`})}catch(e){for(let{served:e}of o)await t.screenRecording.outputs.remove(e.path);throw e}let l=wn({chunkPaths:o.map(({collected:e})=>e.path),startedAtMs:e.startedAtMs,stoppedAtMs:e.stoppedAtMs});return jn({finalization:c,captured:l,recording:r,chunked:s,files:o})}async function kn(e,t){for(let{collected:n,served:r}of t)await e.screenRecording.outputs.copy({from:n.path,to:r.path})}async function An(e,t,n){for(let r=1;r<=n;r+=1)await e.screenRecording.outputs.remove(x(t,r))}function jn(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 Mn(e,t){let{transport:n,evidence:r,manifestPath:i}=e;return await P(n,i,Ft(r,t.result)),await M(n,r.chunks),{status:`completed`,result:{...t.result,nativePathDisposition:await Gt(n,r.chunks)}}}function Nn(e){return Object.freeze(Array.from({length:e.count},(t,n)=>({collected:Object.freeze({index:n+1,path:x(e.collectedPath,n+1)}),served:Object.freeze({index:n+1,path:x(e.exportPath,n+1),...e.exportClientPath===void 0?{}:{clientOutPath:x(e.exportClientPath,n+1)}})})))}async function Pn(e,t,n){try{let r=t.pendingRemotePath;if(await j(e,[...t.chunks,...await Fn(e,t)]),await M(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await F(e,n),{status:`cleaned`}}catch(e){return In(e)}}async function Fn(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 In(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function Ln(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&&It(o,n,r)&&Lt(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function Rn(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=D(t.contents);return n&&zn(n,e)?n:void 0}function zn(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function Bn(e){let{host:t,transport:n,device:r,input:i}=e,a=T.decode(i.envelope.descriptor.body);if(a.status!==`decoded`)return L(`descriptor-invalid`);let o=await Ln({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await Hn({host:t,transport:n,device:r,input:i,descriptor:a.descriptor,evidence:o.evidence}):L(o.status===`transport-unavailable`?`transport-not-reattachable`:`ownership-fence-lost`)}async function Vn(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 Ln({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await Pn(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 Hn(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0){let e=await Un(n,o);return e.status===`terminal`?{status:`completed`,result:{...o.completion,nativePathDisposition:e.nativePathDisposition}}:L(`ownership-fence-lost`,`Android recording completed evidence still names a live or unverifiable recorder.`)}if(o.pendingRemotePath!==void 0)return L(`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 L(`transport-not-reattachable`,`Android recording process ended before its artifact could be recovered.`);let l=Wn(i.envelope.sessionId,i.envelope.fence,a),u=!1;return{status:`active`,handle:Ce(yn(l,o.startedAt),{finish:async(e,r)=>{let i=await Dn({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 Vn({transport:n,device:r,input:i})})}}async function Un(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 Gt(e,t.chunks)}}catch{return{status:`retained`}}}function Wn(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},fence:t}}function L(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function Gn(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 Kn({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await Bn({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await Vn({transport:a,device:n,input:e})})}async function Kn(e){let{host:n,transport:r,device:i,owner:a,input:o,signal:s}=e;s.throwIfAborted();let c=Date.now(),l=await mn({transport:r,device:i,input:o,startedAt:c,signal:s,prepareOutput:async()=>await n.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,n;try{n=await _n({transport:r,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:v.posix.dirname(e.remotePath)})}catch(a){await N(r,e),t=!0;try{n=await _n({transport:r,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:v.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:a}}let a=[...d,{...n,index:d.length+1}];try{await P(r,u,E(i,o,c,a,void 0,r.mode))}catch(a){if(await Kt(r,[n]).catch(()=>{}),t)await P(r,u,E(i,o,c,d,n.remotePath,r.mode)).catch(()=>{});else try{await P(r,u,E(i,o,c,d,void 0,r.mode))}catch{await N(r,e).catch(()=>{}),await P(r,u,E(i,o,c,d,n.remotePath,r.mode)).catch(()=>{})}throw a}d=a,t||await N(r,e),g()};g();let te=Ce(yn(o,c),{finish:async(e,t)=>{if(f&&clearTimeout(f),await p,m)throw m;let a=await Dn({host:n,transport:r,evidence:E(i,o,c,d,void 0,r.mode),manifestPath:u,recording:e,startedAtMs:l.startedAtMs,progress:t});return h=!0,a},forceCleanup:async()=>{if(f&&clearTimeout(f),h)return{status:`cleaned`};try{await p}catch(e){m=e}let e=await Rn({transport:r,deviceId:i.id,sessionId:o.sessionId,fence:o.fence,manifestPath:u});return e?await Pn(r,e,u):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new _e(te),envelope:ge({resourceKind:Oe,sessionId:o.sessionId,device:t(i),owner:a,fence:o.fence,lifecycle:`open`,descriptor:he(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},transportMode:r.mode})})})}const R=12e4,qn=1e3;async function z(e,t,n,r){return r.throwIfAborted(),await Ve(t)?{...t,booted:!0}:t.kind===`emulator`&&(t.booted!==!0||!B(t))?await Jn(e,t,n,r):(t.booted!==!0&&await Qn(e,t.id,R,r),{...t,booted:!0})}async function Jn(e,t,n,r){await Yn(e);let i=$n(n),a=Xn(await e.deviceReadiness.androidEmulator.discover(i,r),t.name,n.serial),o=B(a)?a:void 0,s=o?void 0:e.deviceReadiness.androidEmulator.launch(a.name,n.headless);try{let t=o??await Zn(e,a.name,i,n.serial,r);return await Qn(e,t.id,R,r),{...(await e.deviceReadiness.androidEmulator.discover(i,r)).find(e=>e.id===t.id)??t,name:a.name,booted:!0}}catch(t){throw s!==void 0&&r.aborted&&await e.deviceReadiness.androidEmulator.terminate(s),r.throwIfAborted(),t}}async function Yn(t){if(await t.toolchains.prepare(`android`),!await t.commands.which(`adb`))throw new e(`TOOL_MISSING`,`adb not found in PATH`);if(!await t.commands.which(`emulator`))throw new e(`TOOL_MISSING`,`emulator not found in PATH`)}function Xn(t,n,r){let i=er(t,n,r);if(i)return i;throw new e(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${n}`,{requestedAvdName:n,availableAvds:t.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."})}async function Zn(t,n,r,i,a){let o=t.clock.now()+R;for(;t.clock.now()<o;){let e=er(await t.deviceReadiness.androidEmulator.discover(r,a),n,i);if(e&&B(e))return e;await t.clock.sleep(qn,a)}throw new e(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:n,serial:i,timeoutMs:R})}async function Qn(t,n,r,a){let o=t.clock.now()+r;for(;t.clock.now()<o;){if((await t.commands.run({executable:`adb`,args:i(`adb`,`shell`,[`getprop`,`sys.boot_completed`],[`-s`,n]),allowFailure:!0,timeoutMs:Math.min(1e4,Math.max(1e3,o-t.clock.now()))},a)).stdout.trim()===`1`)return;await t.clock.sleep(qn,a)}throw new e(`COMMAND_FAILED`,`Android device failed to finish booting`,{serial:n,timeoutMs:r,reason:`ANDROID_BOOT_TIMEOUT`})}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()}function nr(e){let{host:t,device:n,signal:r}=e,i=We({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},r)},openApplication:async e=>await rr(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 He({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:ir,configureProviderPortReverse:ir})}async function rr(t,n,r){let i={};if(r.relaunch&&r.target){let e=Date.now();await He({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:[r.appBundleId??r.target]}),i.relaunchCloseDurationMs=V(e)}if(c(r.runtimeHints)){if(!r.applyRuntimeHints)throw new e(`COMMAND_FAILED`,`Runtime hint operation was not admitted for this open.`,{reason:`runtime-hints-operation-missing`});let t=Date.now();await r.applyRuntimeHints({appId:r.appBundleId,values:r.runtimeHints}),i.runtimeHintsDurationMs=V(t)}let a=Date.now();await Ge({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 t.androidApplications.activateTestIme(n.device,{stateDir:r.stateDir});let o=Ue(r);if(o){let e=Date.now();await Ge({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 t.androidApplications.inferOpenedAppBundleId(n.device,r.target,r.appBundleId);return s&&await t.androidApplications.resetFramePerfStats(n.device,s),i.postOpenSettleDurationMs=0,{appBundleId:s,timing:i}}function V(e){return Math.max(0,Date.now()-e)}async function ir(){throw new e(`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 lr(e,t,i);if(v.extname(n).toLowerCase()===`.aab`?await cr(e,t,n,i):G(await e.androidTools.installPackage(t,n,{replace:!0},i),`adb install failed`),r)return r;let o=[...await lr(e,t,i)].filter(e=>!a?.has(e));return o.length===1?o[0]:void 0}function U(t){if(_()&&v.extname(t).toLowerCase()===`.aab`)throw new e(`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 ar(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 or(t,n,r,a){let o=r.payload,s=typeof o.action==`string`&&o.action.trim()?o.action.trim():`${r.appId}.TEST_PUSH`,c=[`am`,`broadcast`,`-a`,s,`-p`,r.appId];typeof o.receiver==`string`&&o.receiver.trim()&&c.push(`-n`,o.receiver.trim());let l=o.extras??{};if(typeof l!=`object`||!l||Array.isArray(l))throw new e(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=0;for(let[e,t]of Object.entries(l))e&&(ur(c,e,t),u+=1);return G(await W(t,n,i(`adb`,`shell`,c),a),`adb push broadcast failed`),{action:s,extrasCount:u}}function sr(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 cr(t,n,r,i){if(await t.androidTools.installBundle(n,r,`universal`,i))return;let a=await t.commands.which(`bundletool`),o=t.androidDeployment.bundletoolJar;if(!a&&!o)throw new e(`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 t.temporaryFiles.create({prefix:`agent-device-aab-`,suffix:`.apks`}),u=l.path;try{G(await t.commands.run({executable:s,args:[...c,`build-apks`,`--bundle`,r,`--output`,u,`--mode`,`universal`]},i),`bundletool build-apks failed`),G(await t.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 lr(e,t,n){let r=await W(e,t,i(`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 ur(t,n,r){if(typeof r==`string`)t.push(`--es`,n,r);else if(typeof r==`boolean`)t.push(`--ez`,n,String(r));else if(typeof r==`number`&&Number.isFinite(r))t.push(Number.isInteger(r)?`--ei`:`--ef`,n,String(r));else throw new e(`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(t,n){if(t.exitCode===0)return;let r={stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode};throw new e(`COMMAND_FAILED`,n,r)}const dr=Object.freeze({available:!0});function fr(e){let t=gr(e);return Object.freeze({deployApp:t,materializeAppSource:t,deployMaterializedApp:t,sendPushNotification:t})}function pr(e){let{host:t,device:n,signal:r}=e;return fr(n).deployApp.available?Object.freeze({deployApp:async e=>await mr(t,n,e,r),materializeAppSource:async e=>await t.androidDeployment.prepareArtifact(e,{signal:r}),deployMaterializedApp:async e=>await hr(t,n,e,r),sendPushNotification:async e=>await or(t,n,e,r)}):Object.freeze({})}async function mr(e,t,n,r){if(n.replaceExisting)return await e.androidDeployment.withInvalidatedAppResolutionCache(t,async()=>{let i;try{_()&&(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 ar(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{_()&&(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:sr(a),launchTarget:a}:{}}finally{await i?.cleanup()}}async function hr(t,n,r,i){let a=await H(t,n,r.artifact.installablePath,r.artifact.packageName,i);if(!a)throw new e(`COMMAND_FAILED`,`Installed Android app identity could not be resolved from the artifact or device state`);return{packageName:a,appName:sr(a),launchTarget:a}}function gr(e){return e.kind===`emulator`||e.kind===`device`?dr:Object.freeze({available:!1,reason:`unsupported-device-kind`})}const K=r(`android`),q=Object.freeze({available:!0}),_r=Object.freeze({available:!1,reason:`unsupported-device-kind`}),vr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`focus is supported on Android emulators and physical devices.`}),yr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`keyboard actions are supported on Android emulators and physical devices.`}),br=Object.freeze({available:!1,reason:`unsupported-platform-leaf`}),xr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Android has no key event for this system button.`}),Sr=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.`}),Cr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Headless boot is supported only for Android emulators.`}),wr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Android appstate is supported only for Android emulators and devices.`}),Tr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Apple runner preparation is supported only for Apple targets.`}),Er=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`open is supported only for Android emulators and devices.`}),Dr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`close is supported only for Android emulators and devices.`}),Or=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Runtime hints are supported only for Android emulators and devices.`}),kr=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Port reverse is supported only by an owning provider runtime.`}),Ar=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`shutdown is supported only for Apple simulators and Android emulators.`}),jr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`screenshot is supported only for Android emulators and devices.`}),J=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`snapshot is supported only for Android emulators and devices.`}),Mr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Re-run without --actions, or target an iOS simulator.`}),Nr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`viewport resizes web targets only (--platform web).`}),Pr=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 Fr(e){let t=Ir(e),n=Lr(e),r=Rr(e);return l({resolveOpenTarget:t,prepareApplicationOpen:t,openApplication:t,applyRuntimeHints:r,clearRuntimeHints:r,closeApplication:n,finalizeApplicationClose:n,prepareAppleRunner:Tr,configureProviderPortReverse:kr})}function Ir(e){return e.kind===`emulator`||e.kind===`device`?q:Er}function Lr(e){return e.kind===`emulator`||e.kind===`device`?q:Dr}function Rr(e){return e.kind===`emulator`||e.kind===`device`?q:Or}const Y=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Gestures are supported on Android emulators and physical devices.`}),zr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ne}),Br=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Me});function X(e,t){return e.kind===`simulator`?Y:e.target===`tv`?t:q}function Z(e){return e.kind===`simulator`?Y:q}function Q(e){return e.kind===`simulator`?vr:q}const $=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:je}),Vr=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 Hr(e,t){let n=e.androidTools?.probeClipboardShellSupport;return n?await n.call(e.androidTools,t):`probe-failed`}const Ur=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`});function Wr(e){return e.kind!==`simulator`&&e.target===`tv`?q:Ur}function Gr(e){let t=$e(e),r=new Map,i=async t=>{if(t.kind===`simulator`)return $;let n=r.get(t.id)??await Hr(e,t);return n!==`probe-failed`&&r.set(t.id,n),n===`supported`?q:n===`unsupported`?$:Vr},a=async e=>{let n=await t.inspectFacts(e),r=fr(e),a=await i(e);return Object.freeze({device:n.device,operations:{...n.operations,...r,appState:e.kind===`simulator`?wr:q,networkDump:q,screenRecordingStart:q,screenRecordingReattach:q,screenRecordingCleanup:q,...ee({capture:e.kind===`simulator`?J:q,customActions:Mr,withoutActiveApp:e.kind===`simulator`?J:q}),...te({capture:e.kind===`simulator`?jr:q}),...m({findText:J}),...p({setViewport:Nr}),...f({focus:Q(e)}),...h({unsupported:Y,plan:Z(e),directionalFling:Z(e),multiTouch:X(e,zr),targetAuthoredDrag:X(e,Br),viewport:Z(e)}),...ce({scroll:Z(e)}),...d({type:Q(e)}),...me({unsupported:vr,tap:Q(e),longPress:Q(e),hover:br,fill:Q(e)}),...u({readTextAtPoint:e.kind===`simulator`?_r:q}),...ie({back:Q(e)}),...le({unsupported:xr,home:Q(e),appSwitcher:Q(e)}),setFoldPose:Sr,...re({triggerAppEvent:Q(e)}),...se({setSetting:Q(e)}),...ue({read:Q(e),wait:Q(e),accept:Q(e),dismiss:Q(e)}),...de({orientation:Q(e)}),...ne({tvRemote:Wr(e)}),...oe({unsupported:yr,status:Q(e),dismiss:Q(e),enter:Q(e)}),...ae({unsupported:a.available?$:a,read:a,write:a}),...fe({capture:Ke(e),query:Pr}),...pe({frames:Q(e),memorySample:Q(e),memorySnapshot:Q(e),nativeCapture:Q(e),profileReport:Q(e)}),ensureReady:q,bootTarget:q,bootTargetHeadless:e.kind===`emulator`?q:Cr,listApps:q,...Fr(e),shutdownTarget:e.kind===`emulator`?q:Ar}})};return Object.freeze({owner:K,ownsDevice:e=>e.platform===`android`,inspectFacts:a,bind:async r=>{let i=await t.bind(r),o=await a(r.device),c=await Gn({host:e,device:r.device,owner:K,signal:r.scope.signal});return Object.freeze({device:i.device,owner:K,facts:o,operations:Object.freeze({...i.operations,...pr({host:e,device:r.device,signal:r.scope.signal}),...o.operations.appState.available?{appState:async()=>{r.scope.signal.throwIfAborted();let{runAndroidAdb:e}=await import(`./adb.js`).then(e=>e.t);return await Ae(async(t,n)=>await e(r.device,t,{...n,signal:r.scope.signal}),r.scope.signal)}}:{},networkDump:async t=>await nt(e,r.device,t,r.scope.signal),...c,...n(o.operations.audioProbeStart,()=>ye({host:e.audioProbe.hostCapture,device:r.device,owner:K})),...n(o.operations.perfFrames,()=>qe({resolveHost:()=>e.perf.android,device:r.device,owner:K})),...Kr(e,r,o),ensureReady:async t=>await z(e,r.device,{...t,headless:!1},r.scope.signal),bootTarget:async t=>await z(e,r.device,{...t,headless:!1},r.scope.signal),...o.operations.bootTargetHeadless.available?{bootTargetHeadless:async t=>await z(e,r.device,{...t,headless:!0},r.scope.signal)}:{},listApps:async e=>{r.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}))},...s(nr({host:e,device:r.device,signal:r.scope.signal}),o.operations),...o.operations.shutdownTarget.available?{shutdownTarget:async()=>await e.deviceShutdown.android.shutdownTarget(r.device,r.scope.signal)}:{}}),[Symbol.asyncDispose]:async()=>await i[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}function Kr(e,t,n){let r={device:t.device,signal:t.scope.signal,resolveInteractor:e.localInteractors.resolve};return{...n.operations.captureSnapshot.available?g(r):{},...Pe({...r,facts:n.operations,pause:async n=>await e.clock.sleep(n,t.scope.signal)})}}export{Gr as createAndroidPlatformRuntime};
3
+ `);return c.trim()?{text:c,pids:o}:void 0}async function ot(e,t,n,r){let a=await nt(e,{executable:`adb`,args:i(`adb`,`shell`,[`pidof`,n],[`-s`,t]),allowFailure:!0},r);if(!a)return;let o=a.stdout.trim().split(/\s+/)[0];return o&&/^\d+$/.test(o)?o:void 0}function st(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 S(e,t){if(t===1)return e;let n=b.parse(e);return b.join(n.dir,`${n.name}.part-${String(t).padStart(3,`0`)}${n.ext||`.mp4`}`)}const ct=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-\d{1,20}\.mp4$/,lt=/^(?:\/sdcard|\/data\/local\/tmp)\/agent-device-recording-active\.json$/;function ut(e){return pt(e)&&mt(e)&&ht(e)}function dt(e){if(!w(e))return!1;let t=e;return gt(t)&&_t(t)&&vt(t)&&yt(t)&&(t.completion===void 0||Et(t))}function ft(e,t){return Dt(e,t)&&C(e,t.outputPath,t.clientOutputPath)}function pt(e){return e.backend===`adb-screenrecord`&&typeof e.manifestPath==`string`&&lt.test(e.manifestPath)&&typeof e.outputPath==`string`}function mt(e){return kt(e.clientOutputPath)&&v(e)}function ht(e){return Ot(e.transportMode)}function gt(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 _t(e){return typeof e.outputPath==`string`&&kt(e.clientOutputPath)&&v(e)}function vt(e){return Ot(e.transportMode)&&(e.pendingRemotePath===void 0||At(e.pendingRemotePath))}function yt(e){return Array.isArray(e.chunks)&&e.chunks.every(bt)&&(e.chunks.length>0||e.pendingRemotePath!==void 0)&&(e.completion===void 0||xt(e.completion))}function bt(e,t){if(!w(e))return!1;let n=e;return n.index===t+1&&At(n.remotePath)&&jt(n.remotePid)&&jt(n.remoteStartTime)}function xt(e){if(!w(e))return!1;let t=e;return Ct(t)&&wt(t)&&St(t)&&(t.chunks===void 0||t.chunks.every(Tt))}function St(e){return(e.stopObservation===void 0||o(e.stopObservation))&&(e.nativePathDisposition===void 0||a(e.nativePathDisposition))}function Ct(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 wt(e){return v(e)}function Tt(e,t){return e.index===t+1&&typeof e.path==`string`&&(e.clientOutPath===void 0||typeof e.clientOutPath==`string`)}function Et(e){let t=e.completion;return t!==void 0&&Dt(t,e)&&t.startedAt===e.startedAt&&C(t,e.outputPath,e.clientOutputPath,e.chunks.length)}function Dt(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&&Mt(e.activeSessionApp,t.activeSessionApp)}function C(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===S(t,r+1)&&e.clientOutPath===(n===void 0?void 0:S(n,r+1)))}function w(e){return typeof e==`object`&&!!e}function Ot(e){return e===`local`||e===`transport-composed`}function kt(e){return e===void 0||typeof e==`string`}function At(e){return typeof e==`string`&&ct.test(e)}function jt(e){return typeof e==`string`&&/^\d+$/.test(e)}function Mt(e,t){return JSON.stringify(e)===JSON.stringify(t)}const T=Object.freeze({resourceKind:De,version:1,encode:e=>({...e}),decode:e=>ut(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}})}:{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},chunks:r,...i===void 0?{}:{pendingRemotePath:i},transportMode:a})}function Nt(e,t){return Object.freeze({...e,completion:t})}function D(e){try{let t=e&&JSON.parse(e);return dt(t)?t:void 0}catch{return}}function Pt(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 Ft(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.transportMode===t.transportMode&&(e.completion===void 0||ft(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 It(e){switch(e){case`missing`:case`ownership-lost`:return!0;case`foreign-writer`:case`owned-alive`:case`uncertain`:return!1}}const Lt=1e4,Rt=1e3;var k=class extends Error{constructor(e){super(`Android screenrecord launch rollback could not be confirmed`,{cause:e})}};function A(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 zt(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 Gt(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&&Bt(i)&&!await Kt(e,i)?new k(t):r?.aborted?r.reason:t}}function Bt(e){return/^\d+$/.test(e.pid)&&/^\d+$/.test(e.startTime)&&e.remotePath.length>0}async function j(e,t){let n=t.at(-1),r=!1,i;for(let a of[...t].reverse())try{let t=await N(e,a);a===n&&(r=t)}catch(e){i??=e}if(i)throw i;return r}async function Vt(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 Ht(e,t,n){for(let[r,i]of t.entries())await qt(e,i.remotePath,S(n,r+1))}async function M(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 Ut(e,t){for(let n of t)if(await e.exists(n.remotePath)!==!1)return`retirable`;return`retired`}async function Wt(e,t){try{await j(e,t)}finally{await M(e,t)}}async function Gt(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 Kt(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 N(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 Jt(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 Yt(1e3)}throw Error(`failed to retrieve playable Android recording`)}async function Jt(e,t){for(let n=0;n<=Lt;n+=Rt){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<Lt&&await Yt(Rt)}return!1}function Yt(e){return new Promise(t=>setTimeout(t,e))}async function P(e,t,n,r){await e.writeManifest({manifestPath:t,contents:JSON.stringify(n)},r)}async function F(e,t){if(!await e.removeManifest(t))throw Error(`failed to remove Android recording manifest: ${t}`)}async function Xt(e,t){let n=(await Zt(e)).flatMap(n=>Qt(n,t,e.mode));for(let t of n)await en(e,t.evidence,t.manifestPath)}async function Zt(e){return await Promise.all(A(void 0).map(async t=>{let n=e.manifestPathFor(t);return{manifestPath:n,read:await e.readManifest(n)}}))}function Qt(e,t,n){if(e.read.status===`missing`)return[];if(e.read.status!==`read`)throw rn(e.manifestPath,e.read.message);let r=D(e.read.contents);if(r===void 0)throw an(e.manifestPath);if(r.transportMode!==n)throw on(e.manifestPath,r,n);if(!$t(r,t))throw sn(e.manifestPath,r,t);return[{manifestPath:e.manifestPath,evidence:r}]}function $t(e,t){return e.completion!==void 0||e.deviceId!==t.id}async function en(e,t,n){if(await tn(e,t),await M(e,t.chunks),await nn(e,t),await F(e,n),(await e.readManifest(n)).status!==`missing`)throw un(n)}async function tn(e,t){for(let n of t.chunks){let t=await e.inspect({pid:n.remotePid,remotePath:n.remotePath,startTime:n.remoteStartTime});if(!It(t))throw t===`uncertain`?dn(n.remotePath):cn(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 cn(n,`other-recorder`);if(!r.conclusive)throw dn(n)}async function nn(e,t){let n=t.pendingRemotePath;if(n!==void 0&&!await e.remove(n))throw ln(n)}function rn(t,n){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unavailable: ${t}`,{reason:`native_recovery_evidence_unavailable`,manifestPath:t,hint:`Confirm the device is online and its storage readable, then run record start again.`},Error(n))}function an(t){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence is unreadable: ${t}`,{reason:`native_recovery_evidence_unreadable`,manifestPath:t,hint:I(t)})}function on(t,n,r){return new e(`COMMAND_FAILED`,`Android screenrecord native recovery evidence was written by the ${n.transportMode} transport, not this ${r} one: ${t}`,{reason:`native_recovery_evidence_transport_mismatch`,manifestPath:t,evidenceTransportMode:n.transportMode,hint:I(t)})}function sn(t,n,r){return new e(`DEVICE_IN_USE`,`Android screenrecord native recovery evidence already exists: ${t} (open recording of session "${n.sessionId}" on ${r.id})`,{reason:`native_recovery_evidence_open`,manifestPath:t,sessionId:n.sessionId,retriable:!1,hint:`Run record stop --session ${n.sessionId} to retire it, or close that session. If it is already closed, ${I(t)}`})}function cn(t,n){let r=n===`named-recorder`;return new e(`DEVICE_IN_USE`,`Android screenrecord recovery evidence is retained: ${r?`its recorder`:`another recorder`} is writing ${t}`,{reason:`native_recording_artifact_claimed`,remotePath:t,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 ln(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence could not remove ${t}`,{reason:`native_recording_artifact_removal_failed`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function un(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence removal could not be confirmed: ${t}`,{reason:`native_recovery_evidence_retirement_unconfirmed`,manifestPath:t,hint:`Run record start again; the marker is retired from the beginning.`})}function dn(t){return new e(`COMMAND_FAILED`,`Android screenrecord recovery evidence cannot be safely retired: ${t}`,{reason:`native_recording_recorder_unproven`,remotePath:t,hint:`Confirm the device is online and run record start again.`})}function I(e){return`no recording session can retire this marker; remove it on the device with \`adb shell rm -f ${e}\`.`}async function fn(e){let{transport:t,device:n,input:r,startedAt:i,signal:a,prepareOutput:o}=e;await Xt(t,n),await o();let s;for(let e of A(void 0)){let o=t.manifestPathFor(e);await P(t,o,E(n,r,i,[],e,t.mode),a);let c,l;try{l=Date.now(),c=await zt(t,e,r,a)}catch(e){if(a.aborted)throw await pn(t,o,e),a.reason;await gn(t,o,e),s=e;continue}try{await P(t,o,E(n,r,i,[c],void 0,t.mode),a)}catch(e){throw await mn(t,o,c),e}return{chunk:c,manifestPath:o,startedAtMs:l}}throw s??Error(`Android screenrecord did not begin producing frames`)}async function pn(e,t,n){n instanceof k||await F(e,t).catch(()=>{})}async function mn(e,t,n){try{await Wt(e,[n])}catch{return}await F(e,t).catch(()=>{})}async function hn(e){let{transport:t,device:n,input:r,startedAt:i,chunks:a,manifestPath:o,preferredDir:s}=e,c;for(let e of A(s)){await P(t,o,E(n,r,i,a,e,t.mode));try{return await zt(t,e,r)}catch(e){if(e instanceof k)throw e;try{await P(t,o,E(n,r,i,a,void 0,t.mode))}catch{throw new k(e)}c=e}}throw c??Error(`failed to start next Android recording chunk`)}async function gn(e,t,n){if(n instanceof k)throw n;try{await F(e,t)}catch{throw new k(n)}}function _n(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}:{},gestureEvents:[]})}function vn(e){let t=yn(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 ${bn(t)}s of the ${bn(n)}s recording window.`}}function yn(e){let t=0;for(let n of e){let e=ze(n);if(e===void 0)return;t+=e}return t}function bn(e){return(e/1e3).toFixed(1)}async function xn(e){let{host:t,transport:n,evidence:r,recording:i,startedAtMs:a,progress:o}=e,s=e.reachedLimit===!0;return await En(e,await Ee({snapshot:i,progress:o,steps:{stop:async()=>(s=await j(n,r.chunks)||s,await Vt(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=>Ht(n,r.chunks,e),finalize:({collectedPath:e,exportPath:n,stoppedAtMs:o})=>Sn({host:t,evidence:r,recording:i,startedAtMs:a,stoppedAtMs:o,collectedPath:e,exportPath:n}),discard:e=>wn(t,e,r.chunks.length)}}))}async function Sn(e){let{host:t,evidence:n,recording:r,collectedPath:i,exportPath:a}=e,o=Dn({collectedPath:i,exportPath:a,exportClientPath:r.clientOutPath,count:n.chunks.length}),s=o.length>1,c;try{await Cn(t,o),c=await t.screenRecording.finalize.complete({outputPath:a,showTouches:!s&&r.showTouches,gestureEvents:r.gestureEvents,exportQuality:r.exportQuality??`medium`,targetLabel:`Android recording`})}catch(e){for(let{served:e}of o)await t.screenRecording.outputs.remove(e.path);throw e}let l=vn({chunkPaths:o.map(({collected:e})=>e.path),startedAtMs:e.startedAtMs,stoppedAtMs:e.stoppedAtMs});return Tn({finalization:c,captured:l,recording:r,chunked:s,files:o})}async function Cn(e,t){for(let{collected:n,served:r}of t)await e.screenRecording.outputs.copy({from:n.path,to:r.path})}async function wn(e,t,n){for(let r=1;r<=n;r+=1)await e.screenRecording.outputs.remove(S(t,r))}function Tn(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 En(e,t){let{transport:n,evidence:r,manifestPath:i}=e;return await P(n,i,Nt(r,t.result)),await M(n,r.chunks),{status:`completed`,result:{...t.result,nativePathDisposition:await Ut(n,r.chunks)}}}function Dn(e){return Object.freeze(Array.from({length:e.count},(t,n)=>({collected:Object.freeze({index:n+1,path:S(e.collectedPath,n+1)}),served:Object.freeze({index:n+1,path:S(e.exportPath,n+1),...e.exportClientPath===void 0?{}:{clientOutPath:S(e.exportClientPath,n+1)}})})))}async function On(e,t,n){try{let r=t.pendingRemotePath;if(await j(e,[...t.chunks,...await kn(e,t)]),await M(e,t.chunks),r!==void 0&&!await e.remove(r))throw Error(`failed to remove Android recording artifact: ${r}`);return await F(e,n),{status:`cleaned`}}catch(e){return An(e)}}async function kn(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 An(e){return{status:`cleanup-pending`,reason:`transport-failed`,message:e instanceof Error?e.message:String(e)}}async function jn(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&&Pt(o,n,r)&&Ft(o,i)?{status:`matched`,evidence:o}:{status:`ownership-lost`}}async function Mn(e){let t=await e.transport.readManifest(e.manifestPath);if(t.status!==`read`)return;let n=D(t.contents);return n&&Nn(n,e)?n:void 0}function Nn(e,t){return e.deviceId===t.deviceId&&e.sessionId===t.sessionId&&e.fenceToken===t.fence.token&&e.fenceGeneration===t.fence.generation}async function Pn(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 jn({transport:n,device:r,envelope:i.envelope,descriptor:a.descriptor});return o.status===`matched`?await Fn({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 L(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 jn({transport:e.transport,device:e.device,envelope:e.input.envelope,descriptor:t.descriptor});return n.status===`matched`?await On(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 Fn(e){let{host:t,transport:n,device:r,input:i,descriptor:a,evidence:o}=e;if(o.completion!==void 0){let e=await In(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=Ln(i.envelope.sessionId,i.envelope.fence,a),u=!1;return{status:`active`,handle:Se(_n(l,o.startedAt),{finish:async(e,r)=>{let i=await xn({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 L({transport:n,device:r,input:i})})}}async function In(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 Ut(e,t.chunks)}}catch{return{status:`retained`}}}function Ln(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},fence:t}}function R(e,t){return{status:`unreattachable`,reason:e,...t===void 0?{}:{message:t}}}async function Rn(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 zn({host:t,transport:a,device:n,owner:r,input:e,signal:i}),screenRecordingReattach:async e=>await Pn({host:t,transport:a,device:n,input:e}),screenRecordingCleanup:async e=>await L({transport:a,device:n,input:e})})}async function zn(e){let{host:n,transport:r,device:i,owner:a,input:o,signal:s}=e;s.throwIfAborted();let c=Date.now(),l=await fn({transport:r,device:i,input:o,startedAt:c,signal:s,prepareOutput:async()=>await n.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,n;try{n=await hn({transport:r,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:b.posix.dirname(e.remotePath)})}catch(a){await N(r,e),t=!0;try{n=await hn({transport:r,device:i,input:o,startedAt:c,chunks:d,manifestPath:u,preferredDir:b.posix.dirname(e.remotePath)})}catch(e){throw e instanceof Error?e:a}}let a=[...d,{...n,index:d.length+1}];try{await P(r,u,E(i,o,c,a,void 0,r.mode))}catch(a){if(await Wt(r,[n]).catch(()=>{}),t)await P(r,u,E(i,o,c,d,n.remotePath,r.mode)).catch(()=>{});else try{await P(r,u,E(i,o,c,d,void 0,r.mode))}catch{await N(r,e).catch(()=>{}),await P(r,u,E(i,o,c,d,n.remotePath,r.mode)).catch(()=>{})}throw a}d=a,t||await N(r,e),g()};g();let _=Se(_n(o,c),{finish:async(e,t)=>{if(f&&clearTimeout(f),await p,m)throw m;let a=await xn({host:n,transport:r,evidence:E(i,o,c,d,void 0,r.mode),manifestPath:u,recording:e,startedAtMs:l.startedAtMs,progress:t});return h=!0,a},forceCleanup:async()=>{if(f&&clearTimeout(f),h)return{status:`cleaned`};try{await p}catch(e){m=e}let e=await Mn({transport:r,deviceId:i.id,sessionId:o.sessionId,fence:o.fence,manifestPath:u});return e?await On(r,e,u):{status:`cleanup-pending`,reason:`ownership-fence-lost`}}});return Object.freeze({pendingHandle:new ge(_),envelope:he({resourceKind:De,sessionId:o.sessionId,device:t(i),owner:a,fence:o.fence,lifecycle:`open`,descriptor:me(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},transportMode:r.mode})})})}const z=12e4,Bn=1e3;async function B(e,t,n,r){return r.throwIfAborted(),await Be(t)?{...t,booted:!0}:t.kind===`emulator`&&(t.booted!==!0||!V(t))?await Vn(e,t,n,r):(t.booted!==!0&&await Gn(e,t.id,z,r),{...t,booted:!0})}async function Vn(e,t,n,r){await Hn(e);let i=Kn(n),a=Un(await e.deviceReadiness.androidEmulator.discover(i,r),t.name,n.serial),o=V(a)?a:void 0,s=o?void 0:e.deviceReadiness.androidEmulator.launch(a.name,n.headless);try{let t=o??await Wn(e,a.name,i,n.serial,r);return await Gn(e,t.id,z,r),{...(await e.deviceReadiness.androidEmulator.discover(i,r)).find(e=>e.id===t.id)??t,name:a.name,booted:!0}}catch(t){throw s!==void 0&&r.aborted&&await e.deviceReadiness.androidEmulator.terminate(s),r.throwIfAborted(),t}}async function Hn(t){if(await t.toolchains.prepare(`android`),!await t.commands.which(`adb`))throw new e(`TOOL_MISSING`,`adb not found in PATH`);if(!await t.commands.which(`emulator`))throw new e(`TOOL_MISSING`,`emulator not found in PATH`)}function Un(t,n,r){let i=qn(t,n,r);if(i)return i;throw new e(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${n}`,{requestedAvdName:n,availableAvds:t.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."})}async function Wn(t,n,r,i,a){let o=t.clock.now()+z;for(;t.clock.now()<o;){let e=qn(await t.deviceReadiness.androidEmulator.discover(r,a),n,i);if(e&&V(e))return e;await t.clock.sleep(Bn,a)}throw new e(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:n,serial:i,timeoutMs:z})}async function Gn(t,n,r,a){let o=t.clock.now()+r;for(;t.clock.now()<o;){if((await t.commands.run({executable:`adb`,args:i(`adb`,`shell`,[`getprop`,`sys.boot_completed`],[`-s`,n]),allowFailure:!0,timeoutMs:Math.min(1e4,Math.max(1e3,o-t.clock.now()))},a)).stdout.trim()===`1`)return;await t.clock.sleep(Bn,a)}throw new e(`COMMAND_FAILED`,`Android device failed to finish booting`,{serial:n,timeoutMs:r,reason:`ANDROID_BOOT_TIMEOUT`})}function Kn(e){return{platform:`android`,kind:`emulator`,...e.serial?{serial:e.serial}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}}}function qn(e,t,n){let r=Jn(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&Jn(e.name)===r&&(!n||!V(e)||e.id===n))}function V(e){return e.id.startsWith(`emulator-`)}function Jn(e){return e.toLowerCase().replaceAll(`_`,` `).replaceAll(/\s+/g,` `).trim()}function Yn(e){let{host:t,device:n,signal:r}=e,i=Ue({device:n,signal:r,resolveInteractor:t.localInteractors.resolve});return Object.freeze({resolveOpenTarget:async e=>await t.androidApplications.resolveOpenTarget(n,e),prepareApplicationOpen:async e=>{await B(t,n,{headless:!1},r)},openApplication:async e=>await Xn(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 B(t,n,{headless:!1},r),await Ve({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:Zn,configureProviderPortReverse:Zn})}async function Xn(t,n,r){let i={};if(r.relaunch&&r.target){let e=Date.now();await Ve({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:[r.appBundleId??r.target]}),i.relaunchCloseDurationMs=H(e)}if(c(r.runtimeHints)){if(!r.applyRuntimeHints)throw new e(`COMMAND_FAILED`,`Runtime hint operation was not admitted for this open.`,{reason:`runtime-hints-operation-missing`});let t=Date.now();await r.applyRuntimeHints({appId:r.appBundleId,values:r.runtimeHints}),i.runtimeHintsDurationMs=H(t)}let a=Date.now();await We({device:n.device,interactor:await n.resolveInteractor(r.execution,r.appBundleId),positionals:r.positionals,appBundleId:r.appBundleId,execution:r.execution}),i.openDispatchDurationMs=H(a),r.enableTestIme&&await t.androidApplications.activateTestIme(n.device,{stateDir:r.stateDir});let o=He(r);if(o){let e=Date.now();await We({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=H(e)}else i.launchUrlDurationMs=0;let s=await t.androidApplications.inferOpenedAppBundleId(n.device,r.target,r.appBundleId);return s&&await t.androidApplications.resetFramePerfStats(n.device,s),i.postOpenSettleDurationMs=0,{appBundleId:s,timing:i}}function H(e){return Math.max(0,Date.now()-e)}async function Zn(){throw new e(`UNSUPPORTED_OPERATION`,`This lifecycle operation is unavailable for Android.`)}async function U(e,t,n,r,i){W(n);let a=r?void 0:await nr(e,t,i);if(b.extname(n).toLowerCase()===`.aab`?await tr(e,t,n,i):K(await e.androidTools.installPackage(t,n,{replace:!0},i),`adb install failed`),r)return r;let o=[...await nr(e,t,i)].filter(e=>!a?.has(e));return o.length===1?o[0]:void 0}function W(t){if(y()&&b.extname(t).toLowerCase()===`.aab`)throw new e(`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 Qn(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 $n(t,n,r,a){let o=r.payload,s=typeof o.action==`string`&&o.action.trim()?o.action.trim():`${r.appId}.TEST_PUSH`,c=[`am`,`broadcast`,`-a`,s,`-p`,r.appId];typeof o.receiver==`string`&&o.receiver.trim()&&c.push(`-n`,o.receiver.trim());let l=o.extras??{};if(typeof l!=`object`||!l||Array.isArray(l))throw new e(`INVALID_ARGS`,`Android push payload extras must be an object`);let u=0;for(let[e,t]of Object.entries(l))e&&(rr(c,e,t),u+=1);return K(await G(t,n,i(`adb`,`shell`,c),a),`adb push broadcast failed`),{action:s,extrasCount:u}}function er(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 tr(t,n,r,i){if(await t.androidTools.installBundle(n,r,`universal`,i))return;let a=await t.commands.which(`bundletool`),o=t.androidDeployment.bundletoolJar;if(!a&&!o)throw new e(`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 t.temporaryFiles.create({prefix:`agent-device-aab-`,suffix:`.apks`}),u=l.path;try{K(await t.commands.run({executable:s,args:[...c,`build-apks`,`--bundle`,r,`--output`,u,`--mode`,`universal`]},i),`bundletool build-apks failed`),K(await t.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 nr(e,t,n){let r=await G(e,t,i(`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 rr(t,n,r){if(typeof r==`string`)t.push(`--es`,n,r);else if(typeof r==`boolean`)t.push(`--ez`,n,String(r));else if(typeof r==`number`&&Number.isFinite(r))t.push(Number.isInteger(r)?`--ei`:`--ef`,n,String(r));else throw new e(`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(t,n){if(t.exitCode===0)return;let r={stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode};throw new e(`COMMAND_FAILED`,n,r)}const ir=Object.freeze({available:!0});function ar(e){let t=lr(e);return Object.freeze({deployApp:t,materializeAppSource:t,deployMaterializedApp:t,sendPushNotification:t})}function or(e){let{host:t,device:n,signal:r}=e;return ar(n).deployApp.available?Object.freeze({deployApp:async e=>await sr(t,n,e,r),materializeAppSource:async e=>await t.androidDeployment.prepareArtifact(e,{signal:r}),deployMaterializedApp:async e=>await cr(t,n,e,r),sendPushNotification:async e=>await $n(t,n,e,r)}):Object.freeze({})}async function sr(e,t,n,r){if(n.replaceExisting)return await e.androidDeployment.withInvalidatedAppResolutionCache(t,async()=>{let i;try{y()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),W(i.installablePath)),t.booted!==!0&&await B(e,t,{headless:!1},r);let a=await e.androidDeployment.resolveAppPackage(t,n.app);return await Qn(e,t,a,r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!1,signal:r}),await U(e,t,i.installablePath,void 0,r),{packageName:a,launchTarget:a}}finally{await i?.cleanup()}});let i;try{y()&&(i=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r}),W(i.installablePath)),t.booted!==!0&&await B(e,t,{headless:!1},r),i??=await e.androidDeployment.prepareArtifact({source:{kind:`path`,path:n.appPath}},{resolveIdentity:!0,signal:r});let a=await U(e,t,i.installablePath,i.packageName,r);return a?{packageName:a,appName:er(a),launchTarget:a}:{}}finally{await i?.cleanup()}}async function cr(t,n,r,i){let a=await U(t,n,r.artifact.installablePath,r.artifact.packageName,i);if(!a)throw new e(`COMMAND_FAILED`,`Installed Android app identity could not be resolved from the artifact or device state`);return{packageName:a,appName:er(a),launchTarget:a}}function lr(e){return e.kind===`emulator`||e.kind===`device`?ir:Object.freeze({available:!1,reason:`unsupported-device-kind`})}const q=n(`android`),J=Object.freeze({available:!0}),ur=Object.freeze({available:!1,reason:`unsupported-device-kind`}),dr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`focus is supported on Android emulators and physical devices.`}),fr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`keyboard actions are supported on Android emulators and physical devices.`}),pr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`}),mr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Android has no key event for this system button.`}),hr=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.`}),gr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Headless boot is supported only for Android emulators.`}),_r=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Android appstate is supported only for Android emulators and devices.`}),vr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Apple runner preparation is supported only for Apple targets.`}),yr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`open is supported only for Android emulators and devices.`}),br=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`close is supported only for Android emulators and devices.`}),xr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Runtime hints are supported only for Android emulators and devices.`}),Sr=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Port reverse is supported only by an owning provider runtime.`}),Cr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`shutdown is supported only for Apple simulators and Android emulators.`}),wr=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.`}),Tr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`Re-run without --actions, or target an iOS simulator.`}),Er=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:`viewport resizes web targets only (--platform web).`}),Dr=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 Or(e){let t=kr(e),n=Ar(e),r=jr(e);return l({resolveOpenTarget:t,prepareApplicationOpen:t,openApplication:t,applyRuntimeHints:r,clearRuntimeHints:r,closeApplication:n,finalizeApplicationClose:n,prepareAppleRunner:vr,configureProviderPortReverse:Sr})}function kr(e){return e.kind===`emulator`||e.kind===`device`?J:yr}function Ar(e){return e.kind===`emulator`||e.kind===`device`?J:br}function jr(e){return e.kind===`emulator`||e.kind===`device`?J:xr}const X=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`Gestures are supported on Android emulators and physical devices.`}),Mr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:je}),Nr=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ae});function Pr(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`?dr:J}const $=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:ke}),Fr=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 Ir(e,t){let n=e.androidTools?.probeClipboardShellSupport;return n?await n.call(e.androidTools,t):`probe-failed`}const Lr=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`});function Rr(e){return e.kind!==`simulator`&&e.target===`tv`?J:Lr}function zr(e){let t=Qe(e),n=new Map,i=async t=>{if(t.kind===`simulator`)return $;let r=n.get(t.id)??await Ir(e,t);return r!==`probe-failed`&&n.set(t.id,r),r===`supported`?J:r===`unsupported`?$:Fr},a=async e=>{let n=await t.inspectFacts(e),r=ar(e),a=await i(e);return Object.freeze({device:n.device,operations:{...n.operations,...r,appState:e.kind===`simulator`?_r:J,networkDump:J,screenRecordingStart:J,screenRecordingReattach:J,screenRecordingCleanup:J,...p({capture:e.kind===`simulator`?Y:J,customActions:Tr,withoutActiveApp:e.kind===`simulator`?Y:J}),...f({capture:e.kind===`simulator`?wr:J}),...ee({findText:Y}),...h({setViewport:Er}),...m({focus:Q(e)}),...g({unsupported:X,plan:Z(e),directionalFling:Z(e),multiTouch:Pr(e,Mr),targetAuthoredDrag:Pr(e,Nr),viewport:Z(e)}),...u({scroll:Z(e)}),...d({type:Q(e)}),...pe({unsupported:dr,tap:Q(e),longPress:Q(e),hover:pr,fill:Q(e)}),...ce({readTextAtPoint:e.kind===`simulator`?ur:J}),...le({back:Q(e)}),...oe({unsupported:mr,home:Q(e),appSwitcher:Q(e)}),setFoldPose:hr,...re({triggerAppEvent:Q(e)}),..._({setSetting:Q(e),readSetting:Q(e)}),...ae({read:Q(e),wait:Q(e),accept:Q(e),dismiss:Q(e)}),...te({orientation:Q(e)}),...se({tvRemote:Rr(e)}),...ne({unsupported:fr,status:Q(e),dismiss:Q(e),enter:Q(e)}),...ie({unsupported:a.available?$:a,read:a,write:a}),...de({capture:Ge(e),query:Dr}),...fe({frames:Q(e),memorySample:Q(e),memorySnapshot:Q(e),nativeCapture:Q(e),profileReport:Q(e)}),ensureReady:J,bootTarget:J,bootTargetHeadless:e.kind===`emulator`?J:gr,listApps:J,...Or(e),shutdownTarget:e.kind===`emulator`?J:Cr}})};return Object.freeze({owner:q,ownsDevice:e=>e.platform===`android`,inspectFacts:a,bind:async n=>{let i=await t.bind(n),o=await a(n.device),c=await Rn({host:e,device:n.device,owner:q,signal:n.scope.signal});return Object.freeze({device:i.device,owner:q,facts:o,operations:Object.freeze({...i.operations,...or({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 Oe(async(t,r)=>await e(n.device,t,{...r,signal:n.scope.signal}),n.scope.signal)}}:{},networkDump:async t=>await tt(e,n.device,t,n.scope.signal),...c,...r(o.operations.audioProbeStart,()=>ve({host:e.audioProbe.hostCapture,device:n.device,owner:q})),...r(o.operations.perfFrames,()=>Ke({resolveHost:()=>e.perf.android,device:n.device,owner:q})),...Br(e,n,o),ensureReady:async t=>await B(e,n.device,{...t,headless:!1},n.scope.signal),bootTarget:async t=>await B(e,n.device,{...t,headless:!1},n.scope.signal),...o.operations.bootTargetHeadless.available?{bootTargetHeadless:async t=>await B(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}))},...s(Yn({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 i[Symbol.asyncDispose]()})},shutdown:async()=>await t.shutdown()})}function Br(e,t,n){let r={device:t.device,signal:t.scope.signal,resolveInteractor:e.localInteractors.resolve};return{...n.operations.captureSnapshot.available?ue(r):{},...Me({...r,facts:n.operations,pause:async n=>await e.clock.sleep(n,t.scope.signal)})}}export{zr as createAndroidPlatformRuntime};