agent-device 0.20.8 → 0.20.10

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 (220) hide show
  1. package/README.md +94 -31
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +3 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +13 -7
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +10 -117
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +103 -2
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +108 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +179 -73
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
  24. package/dist/src/agent-browser-tool.js +1 -1
  25. package/dist/src/agent-device-client.js +2 -2
  26. package/dist/src/ai-sdk.d.ts +61 -0
  27. package/dist/src/ai-sdk.js +1 -0
  28. package/dist/src/android-adb.d.ts +6 -6
  29. package/dist/src/android-adb.js +1 -1
  30. package/dist/src/android.js +1 -1
  31. package/dist/src/app-helpers.js +1 -1
  32. package/dist/src/app-lifecycle.js +6 -7
  33. package/dist/src/app-lifecycle2.js +2 -2
  34. package/dist/src/app-log-reconnect.js +1 -1
  35. package/dist/src/app-log-runtime.js +3 -3
  36. package/dist/src/app-resolution.js +2 -2
  37. package/dist/src/app-state.js +2 -0
  38. package/dist/src/appearance.js +1 -0
  39. package/dist/src/apps.js +5 -5
  40. package/dist/src/artifacts.d.ts +1 -1
  41. package/dist/src/audio-probe.js +1 -1
  42. package/dist/src/auth-session.js +1 -1
  43. package/dist/src/backend-snapshot-options.js +1 -0
  44. package/dist/src/boot-diagnostics.js +2 -2
  45. package/dist/src/bounds.js +1 -0
  46. package/dist/src/byte-limit-stream.js +1 -0
  47. package/dist/src/cli-config.js +1 -1
  48. package/dist/src/cli-help.js +42 -30
  49. package/dist/src/cli-runner.js +1 -1
  50. package/dist/src/cli.js +7 -7
  51. package/dist/src/client-metro.js +1 -1
  52. package/dist/src/client-types.d.ts +1582 -0
  53. package/dist/src/command-catalog.js +1 -0
  54. package/dist/src/command-metadata.js +1 -1
  55. package/dist/src/command-schema.js +1 -1
  56. package/dist/src/command-surface.js +1 -1
  57. package/dist/src/command-tools.js +2 -0
  58. package/dist/src/config.js +1 -0
  59. package/dist/src/connection-runtime.js +1 -1
  60. package/dist/src/connection.js +3 -3
  61. package/dist/src/contracts.d.ts +1 -1
  62. package/dist/src/contracts.js +1 -1
  63. package/dist/src/daemon-shutdown-report.js +1 -1
  64. package/dist/src/daemon.js +1 -1
  65. package/dist/src/debug-symbols.js +3 -3
  66. package/dist/src/device-claim-inspection.js +1 -1
  67. package/dist/src/device-input-state.js +1 -1
  68. package/dist/src/device-ready.js +1 -1
  69. package/dist/src/device2.js +2 -2
  70. package/dist/src/dispatch.js +1 -1
  71. package/dist/src/entities.js +1 -1
  72. package/dist/src/find.js +1 -1
  73. package/dist/src/finders.js +1 -1
  74. package/dist/src/generic-settle.js +1 -1
  75. package/dist/src/generic.js +1 -1
  76. package/dist/src/harmonyos.js +1 -1
  77. package/dist/src/hdc.js +1 -1
  78. package/dist/src/helper-package-install.js +1 -0
  79. package/dist/src/helper.js +2 -2
  80. package/dist/src/host-process.js +1 -1
  81. package/dist/src/ime-lifecycle.js +2 -9
  82. package/dist/src/ime-recovery-marker.js +1 -0
  83. package/dist/src/index.d.ts +2 -1569
  84. package/dist/src/index.js +1 -1
  85. package/dist/src/input-actions.js +4 -4
  86. package/dist/src/input-actions2.js +1 -1
  87. package/dist/src/install-artifact.js +1 -1
  88. package/dist/src/install-artifact2.js +1 -1
  89. package/dist/src/install-source2.js +1 -1
  90. package/dist/src/interaction-common.js +1 -0
  91. package/dist/src/interaction-runtime.js +1 -1
  92. package/dist/src/interaction-snapshot.js +1 -1
  93. package/dist/src/interaction.js +1 -1
  94. package/dist/src/interaction2.js +1 -0
  95. package/dist/src/interactor.js +2 -2
  96. package/dist/src/interactor2.js +1 -1
  97. package/dist/src/interactors.js +1 -0
  98. package/dist/src/internal/bin.js +2 -2
  99. package/dist/src/internal/daemon.js +4 -7
  100. package/dist/src/internal/png-worker.js +1 -1
  101. package/dist/src/inventory.js +1 -1
  102. package/dist/src/keyed-lock.js +1 -0
  103. package/dist/src/lease-context.js +1 -1
  104. package/dist/src/lease.js +1 -1
  105. package/dist/src/limrun-runtime-dependencies.js +1 -1
  106. package/dist/src/limrun.d.ts +13 -3
  107. package/dist/src/limrun.js +1 -1
  108. package/dist/src/linux.js +1 -1
  109. package/dist/src/location-coordinates.js +1 -0
  110. package/dist/src/logcat.js +1 -1
  111. package/dist/src/manifest.js +1 -1
  112. package/dist/src/mobile-snapshot-semantics.js +1 -0
  113. package/dist/src/observability.js +1 -0
  114. package/dist/src/owner-identity.js +1 -1
  115. package/dist/src/perf.js +4 -0
  116. package/dist/src/physical-device-control.js +1 -1
  117. package/dist/src/platform-runtime-app-log-process.js +1 -1
  118. package/dist/src/platform-runtime-host.js +1 -1
  119. package/dist/src/platform-runtime-network-web-transport.js +1 -1
  120. package/dist/src/platform-runtime-open-target.js +1 -0
  121. package/dist/src/platform-runtime-operation-host.js +4 -4
  122. package/dist/src/platform-runtime-runtime-hints.js +2 -0
  123. package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
  124. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  125. package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
  126. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  127. package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
  128. package/dist/src/platform-runtime.js +1 -1
  129. package/dist/src/platform-runtime2.js +1 -0
  130. package/dist/src/plist.js +1 -1
  131. package/dist/src/png-resize.js +1 -0
  132. package/dist/src/png-worker-contract.js +1 -1
  133. package/dist/src/process-lock.js +1 -1
  134. package/dist/src/project-runtime.js +1 -0
  135. package/dist/src/provider-webdriver.js +1 -1
  136. package/dist/src/provider.js +1 -0
  137. package/dist/src/proxy.js +1 -1
  138. package/dist/src/react-native.js +1 -1
  139. package/dist/src/record-runtime.js +1 -1
  140. package/dist/src/record-trace.js +1 -1
  141. package/dist/src/recording-export-quality.js +1 -0
  142. package/dist/src/registry.js +29 -26
  143. package/dist/src/remote-config2.js +1 -1
  144. package/dist/src/replay.js +2 -2
  145. package/dist/src/reporting.js +5 -5
  146. package/dist/src/rolldown-runtime.js +1 -0
  147. package/dist/src/runner-client.js +1 -0
  148. package/dist/src/runner-disposal.js +1 -1
  149. package/dist/src/runner-lease.js +1 -1
  150. package/dist/src/runner-sequence.js +1 -1
  151. package/dist/src/runtime-transport.js +1 -1
  152. package/dist/src/runtime.js +3 -3
  153. package/dist/src/runtime2.js +4 -3
  154. package/dist/src/runtime3.js +1 -3
  155. package/dist/src/runtime4.js +3 -1
  156. package/dist/src/runtime5.js +1 -1
  157. package/dist/src/runtime6.js +1 -1
  158. package/dist/src/runtime7.js +1 -1
  159. package/dist/src/runtime8.js +1 -0
  160. package/dist/src/runtime9.js +1 -0
  161. package/dist/src/scoped-provider.js +1 -0
  162. package/dist/src/screenshot-density.js +1 -0
  163. package/dist/src/screenshot-result.js +4 -4
  164. package/dist/src/screenshot.js +1 -1
  165. package/dist/src/script-source-bundle.js +16 -0
  166. package/dist/src/sdk-android-adb.d.ts +44 -26
  167. package/dist/src/sdk-android-adb.js +4 -4
  168. package/dist/src/sdk-batch-runner.js +3 -3
  169. package/dist/src/sdk-contracts.d.ts +125 -88
  170. package/dist/src/sdk-contracts.js +2 -2
  171. package/dist/src/sdk-device.js +1 -1
  172. package/dist/src/sdk-finders.d.ts +1 -1
  173. package/dist/src/sdk-finders.js +1 -1
  174. package/dist/src/sdk-io.js +1 -1
  175. package/dist/src/sdk-remote-config.js +1 -1
  176. package/dist/src/sdk-selectors.d.ts +107 -95
  177. package/dist/src/sdk-selectors.js +1 -1
  178. package/dist/src/sdk.js +1 -0
  179. package/dist/src/selector-runtime.js +1 -1
  180. package/dist/src/selectors.d.ts +1 -1
  181. package/dist/src/selectors.js +1 -1
  182. package/dist/src/server.js +10 -3
  183. package/dist/src/session-target-evidence.js +1 -1
  184. package/dist/src/session.js +1 -30
  185. package/dist/src/session2.js +27 -0
  186. package/dist/src/setting-state.js +1 -1
  187. package/dist/src/shared.js +1 -1
  188. package/dist/src/simctl.js +1 -0
  189. package/dist/src/simulator-state.js +1 -0
  190. package/dist/src/simulator.js +1 -1
  191. package/dist/src/snapshot-runtime.js +1 -1
  192. package/dist/src/snapshot-scope.js +1 -0
  193. package/dist/src/snapshot-session.js +1 -1
  194. package/dist/src/snapshot.js +8 -1
  195. package/dist/src/snapshot2.js +1 -1
  196. package/dist/src/snapshot3.js +1 -0
  197. package/dist/src/src.js +1 -1
  198. package/dist/src/src2.js +1 -2
  199. package/dist/src/src3.js +2 -1
  200. package/dist/src/src4.js +1 -0
  201. package/dist/src/string-enum.js +1 -0
  202. package/dist/src/tool-provider.js +3 -3
  203. package/dist/src/tool-provider2.js +1 -1
  204. package/dist/src/tool-provider3.js +1 -1
  205. package/dist/src/update-check.js +1 -1
  206. package/dist/src/verdict.js +1 -0
  207. package/dist/src/verified-file.js +1 -0
  208. package/dist/src/version.js +1 -1
  209. package/dist/src/video.js +1 -1
  210. package/dist/src/web.js +1 -1
  211. package/package.json +27 -10
  212. package/server.json +3 -3
  213. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +0 -1
  214. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +0 -1
  215. package/dist/src/interaction-touch-reference-frame.js +0 -1
  216. package/dist/src/notifications.js +0 -1
  217. package/dist/src/platform-runtime-toolchain-host.js +0 -1
  218. package/dist/src/prepare-kind.js +0 -15
  219. package/dist/src/selector-vocabulary.js +0 -1
  220. package/dist/src/text-surface.js +0 -1
@@ -1 +1 @@
1
- import{S as e,_ as t}from"./sdk-contracts.js";import{bt as n,wt as r}from"./version.js";import{$ as i}from"./sdk-batch-runner.js";import{_ as a,c as o}from"./sdk-device.js";import{H as s}from"./prepare-kind.js";import{j as c}from"./screenshot-result.js";import{t as l}from"./runtime.js";import{j as u}from"./sdk-android-adb.js";import{n as d}from"./shell-quote.js";import{N as f}from"./runner-disposal.js";import{E as p,b as m,c as h,o as g,t as _,y as v}from"./dispatch.js";import{$t as y,Qt as b,Wt as x,an as S,fn as C,on as w,qt as T}from"./internal/daemon.js";import{i as E,l as D,r as O,t as k}from"./snapshot-session.js";import{n as A}from"./app-resolution.js";import j from"node:path";import{promises as M}from"node:fs";import N from"node:os";function P(e){return o(e)&&e.kind===`simulator`}function F(e){return e.platform===`android`&&e.kind===`emulator`}async function I(e={}){try{let t=await v({platform:`ios`,iosSimulatorSetPath:e.simulatorSetPath,kind:`simulator`,booted:!0});if(t.length!==1)return;let[n]=t;if(!n)return;let r=await A(n);return r?{device:n,app:r}:void 0}catch(e){if(m(e))throw e;return}}async function L(e){if(!o(e)||e.kind!==`simulator`)return;let t=await I({simulatorSetPath:e.simulatorSetPath});if(!t)return;let n=R(t.device,t.app.bundleId),r=`One booted device found ("${t.device.name}", udid ${t.device.id}) with ${t.app.bundleId} running. Run: ${n}`;return r.length<=350?r:void 0}function R(e,t){let n=e.simulatorSetPath?` --ios-simulator-device-set ${d(e.simulatorSetPath)}`:``;return`agent-device open ${t} --platform ios --udid ${e.id}${n}`}async function z(t){if(t.command!==`snapshot`||t.device.platform!==`android`)return;let n=e(t.error);if(U(n))return{ok:!1,error:{...n,details:{...n.details??{},androidSnapshotTimeoutScreenshot:await ee(t)}}}}async function ee(t){try{let e=await M.mkdtemp(j.join(N.tmpdir(),`agent-device-android-snapshot-timeout-`)),n=j.join(e,`snapshot-timeout-overlay-refs.png`),r=V(await _(t.device,`screenshot`,[n],void 0,{...C(t.logPath,{screenshotNoStabilize:!0},t.session?.appBundleId,t.session?.trace?.outPath),surface:t.session?.surface}),n);await M.access(r);let i=await B(r,t.session);return u({level:`warn`,phase:`android_snapshot_timeout_screenshot_captured`,data:{path:r,overlayRefCount:`overlayRefCount`in i?i.overlayRefCount:void 0,overlayRefsAnnotated:`overlayRefsAnnotated`in i?i.overlayRefsAnnotated:void 0}}),i}catch(t){let n=e(t);return u({level:`warn`,phase:`android_snapshot_timeout_screenshot_failed`,data:{error:n.message}}),{captureFailed:!0,error:n.message}}}async function B(t,n){if(!n?.snapshot)return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`unavailable`,overlayRefCount:0};try{let e=await x({screenshotPath:t,snapshot:n.snapshot});return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:e.length>0,overlayRefCount:e.length,overlayRefSource:`session-snapshot`,overlayRefs:e}}catch(n){let r=e(n);return u({level:`warn`,phase:`android_snapshot_timeout_screenshot_overlay_failed`,data:{path:t,error:r.message}}),{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`session-snapshot`,overlayRefCount:0,overlayAnnotationError:r.message}}}function V(e,t){return H(e)?e.path:t}function H(e){return typeof e==`object`&&!!e&&`path`in e&&typeof e.path==`string`}function U(e){return e.code===`COMMAND_FAILED`?W(e)||G(e.details?.helper):!1}function W(e){let t=`${e.message}\n${e.hint??``}`;return/Android accessibility snapshots can be blocked/i.test(t)}function G(e){if(!e||typeof e!=`object`)return!1;let t=e,n=String(t.errorType??``),r=String(t.message??``);return/TimeoutException/i.test(n)||/timed out/i.test(r)}function K(e){let{verdict:t,appBundleId:n,latch:r}=e;return t?t.state===`healthy`?{latch:void 0}:t.state!==`recovered`||t.reasonCode===`requested-backend`?{latch:r}:t.reasonCode===`deferred`?r!==void 0&&r.appBundleId===n?{latch:r}:{warning:s(t.backend),latch:{appBundleId:n}}:{latch:{appBundleId:n}}:{latch:r}}function q(e){let{session:t,data:n,verdict:r,internalObservation:i}=e;if(i||!t)return n;let a=K({verdict:r,appBundleId:t.appBundleId,latch:t.recoveredSnapshotWarningLatch});if(t.recoveredSnapshotWarningLatch=a.latch,!a.warning)return n;let o=Array.isArray(n.warnings)?n.warnings:[];return{...n,warnings:[a.warning,...o]}}async function J(e){return await Z({...e,command:`snapshot`,unsupportedMessage:`snapshot is not supported on this device`,execute:async({runtime:t,sessionName:n,req:r,snapshotScope:a})=>{let o=await t.capture.snapshot({session:n,interactiveOnly:r.flags?.snapshotInteractiveOnly,depth:r.flags?.snapshotDepth,scope:a,raw:r.flags?.snapshotRaw,customActions:r.flags?.snapshotCustomActions,forceFull:r.flags?.snapshotForceFull}),s=Y(r,e.sessionStore.get(n)),c=i(o.nodes),l=c===o.nodes?o:{...o,nodes:c};return{data:s===void 0?l:{...l,refsGeneration:s},record:{kind:`snapshot`,nodes:o.nodes.length,truncated:o.truncated}}}})}function Y(e,t){return e.internal?.observationOnly===!0?void 0:t?.snapshotGeneration}async function X(e){return await Z({...e,command:`diff`,unsupportedMessage:`diff is not supported on this device`,execute:async({runtime:e,sessionName:t,req:n,snapshotScope:r})=>{let i=await e.capture.diffSnapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,depth:n.flags?.snapshotDepth,scope:r,raw:n.flags?.snapshotRaw});return{data:i,record:{kind:`diff`,mode:`snapshot`,baselineInitialized:i.baselineInitialized,summary:i.summary}}}})}async function Z(e){let{req:t,sessionName:n,logPath:r,sessionStore:i}=e,{session:a,device:o}=await O(i,n,t.flags),s=h(e.command,o,{message:e.unsupportedMessage});if(s)return s;let c=w(t.flags?.snapshotScope,a);return c.ok?Q(t,o)||await $(e.command,a,o)||await E(a,o,async()=>{let s={},l=te({req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:c.scope,capturedQuality:s}),u;try{u=await e.execute({runtime:l,sessionName:n,req:t,snapshotScope:c.scope})}catch(t){let n=await z({error:t,command:e.command,logPath:r,session:a,device:o});if(!n)throw t;return n}return ce({req:t,sessionName:n,sessionStore:i,result:u.record}),{ok:!0,data:q({session:i.get(n),data:u.data,verdict:s.value,internalObservation:t.internal?.observationOnly===!0})}}):c}function Q(e,t){return e.flags?.snapshotCustomActions!==!0||P(t)?null:g(`UNSUPPORTED_OPERATION`,`--actions requires an iOS simulator: custom actions are read through the private accessibility snapshot backend, which ${t.platform}/${t.kind} targets do not have.`,{hint:`Re-run without --actions, or target an iOS simulator.`})}async function $(e,t,n){if(!o(n)||t?.appBundleId||p(n))return null;let r=await L(n);return g(`SESSION_NOT_FOUND`,`iOS ${e} requires an active app session on the target device. Run open first (for example: open --session ${t?.name??`sim`} --platform ios --device "<name>" <app>).`,{reason:`ios_app_session_required`,...r?{hint:r}:{}})}function te(e){let{req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:s}=e;return l({backend:se({req:t,logPath:r,session:a,device:o,snapshotScope:s,capturedQuality:e.capturedQuality}),...D(`snapshot`),signal:f(t.meta?.requestId),sessions:T({sessionName:n,getSession:()=>i.get(n),recordOptions:{includeSnapshot:!0},setRecord:e=>{let r=le(e),a=i.get(n);i.set(n,ne({current:a,sessionName:n,device:o,record:r,refScopedSnapshot:re(t),issuesRefsToClient:t.command===`snapshot`&&t.internal?.observationOnly!==!0}))}})})}function ne(e){let{current:t,sessionName:n,device:r,record:i,refScopedSnapshot:a}=e,o=ie(t,i,a),s=k({session:t,sessionName:n,device:r,snapshot:o?t.snapshot:i.snapshot,appBundleId:i.appBundleId});return b(s,{scopeSource:oe({current:t,keepCurrentSnapshot:o,refScopedSnapshot:a}),keptCurrentSnapshot:o,previousGeneration:t?.snapshotGeneration}),ae(s,o,e.issuesRefsToClient),i.appName&&(s.appName=i.appName),s}function re(e){return e.flags?.snapshotScope?.trim().startsWith(`@`)===!0}function ie(e,t,n){return n&&t.snapshot?.nodes.length===0&&e?.snapshot!==void 0}function ae(e,t,n){!t&&n&&y(e)}function oe(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:r}=e;if(r)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}function se(e){let{req:t,logPath:i,session:o,device:s,snapshotScope:c}=e;return{platform:a(s),captureSnapshot:async(a,l)=>{let u=await S({device:s,session:o,flags:t.flags,outPath:l?.outPath??t.flags?.out,logPath:i,snapshotScope:c,signal:a.signal}),d=r(u);e.capturedQuality.value=d.quality;let f=n(o);return{snapshot:u.snapshot,...d,...f?{snapshotDiagnostics:f}:{},appName:o?.appBundleId?o.appName??o.appBundleId:void 0,appBundleId:o?.appBundleId}}}}function ce(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:ue(e.result),interactiveObservation:c(e.req)})}function le(e){if(!e.snapshot)throw new t(`UNKNOWN`,`snapshot runtime did not produce session state`);return e}function ue(e){return e.kind===`snapshot`?{nodes:e.nodes,truncated:e.truncated}:{mode:e.mode,baselineInitialized:e.baselineInitialized,summary:e.summary}}export{P as a,F as i,J as n,I as r,X as t};
1
+ import{E as e,_ as t}from"./sdk-contracts.js";import{f as n,g as r}from"./location-coordinates.js";import{wt as i,zt as a}from"./sdk-batch-runner.js";import{_ as o,c as s}from"./sdk-device.js";import{N as c}from"./screenshot-result.js";import{t as l}from"./verdict.js";import{o as u,t as d}from"./runtime.js";import{A as f}from"./sdk-android-adb.js";import{n as p}from"./shell-quote.js";import{j as ee}from"./runner-disposal.js";import{a as m,t as h}from"./dispatch.js";import{Tt as g,_t as _,ct as v,dt as y,ft as te,jt as b,vt as x,wt as S}from"./internal/daemon.js";import{a as C,i as w,r as T,t as E}from"./snapshot-session.js";import{a as D}from"./platform-runtime-open-target.js";import O from"node:path";import{promises as k}from"node:fs";import A from"node:os";function j(e,t){if(!t.available)return m(`UNSUPPORTED_OPERATION`,`${e} is not supported on this device`,{reason:t.reason},t.hint?{hint:t.hint}:void 0)}function M(e){if(e)return e;throw new t(`COMMAND_FAILED`,`Device runtime facts inspection is unavailable.`)}async function N(e){let t=await M(e.inspectFacts)(e.device);for(let n of e.use.required){let e=t.operations[n];if(!e.available)return{admitted:!1,operation:n,fact:e}}return{admitted:!0}}function P(e){if(e)return e;throw new t(`COMMAND_FAILED`,`Device runtime binding is unavailable.`)}async function F(t){if(t.command!==`snapshot`||t.device.platform!==`android`)return;let n=e(t.error);if(B(n))return{ok:!1,error:{...n,details:{...n.details??{},androidSnapshotTimeoutScreenshot:await I(t)}}}}async function I(t){try{let e=await k.mkdtemp(O.join(A.tmpdir(),`agent-device-android-snapshot-timeout-`)),n=O.join(e,`snapshot-timeout-overlay-refs.png`),r=R(await h(t.device,`screenshot`,[n],void 0,{...b(t.logPath,{screenshotNoStabilize:!0},t.session?.appBundleId,t.session?.trace?.outPath),surface:t.session?.surface}),n);await k.access(r);let i=await L(r,t.session);return f({level:`warn`,phase:`android_snapshot_timeout_screenshot_captured`,data:{path:r,overlayRefCount:`overlayRefCount`in i?i.overlayRefCount:void 0,overlayRefsAnnotated:`overlayRefsAnnotated`in i?i.overlayRefsAnnotated:void 0}}),i}catch(t){let n=e(t);return f({level:`warn`,phase:`android_snapshot_timeout_screenshot_failed`,data:{error:n.message}}),{captureFailed:!0,error:n.message}}}async function L(t,n){if(!n?.snapshot)return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`unavailable`,overlayRefCount:0};try{let e=await v({screenshotPath:t,snapshot:n.snapshot});return{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:e.length>0,overlayRefCount:e.length,overlayRefSource:`session-snapshot`,overlayRefs:e}}catch(n){let r=e(n);return f({level:`warn`,phase:`android_snapshot_timeout_screenshot_overlay_failed`,data:{path:t,error:r.message}}),{path:t,overlayRefsRequested:!0,overlayRefsAnnotated:!1,overlayRefSource:`session-snapshot`,overlayRefCount:0,overlayAnnotationError:r.message}}}function R(e,t){return z(e)?e.path:t}function z(e){return typeof e==`object`&&!!e&&`path`in e&&typeof e.path==`string`}function B(e){return e.code===`COMMAND_FAILED`?V(e)||H(e.details?.helper):!1}function V(e){let t=`${e.message}\n${e.hint??``}`;return/Android accessibility snapshots can be blocked/i.test(t)}function H(e){if(!e||typeof e!=`object`)return!1;let t=e,n=String(t.errorType??``),r=String(t.message??``);return/TimeoutException/i.test(n)||/timed out/i.test(r)}function U(e){let{verdict:t,appBundleId:n,latch:r}=e;return t?t.state===`healthy`?{latch:void 0}:t.state!==`recovered`||t.reasonCode===`requested-backend`?{latch:r}:t.reasonCode===`deferred`?r!==void 0&&r.appBundleId===n?{latch:r}:{warning:u(t.backend),latch:{appBundleId:n}}:{latch:{appBundleId:n}}:{latch:r}}function W(e){let{session:t,data:n,verdict:r,internalObservation:i}=e;if(i||!t)return n;let a=U({verdict:r,appBundleId:t.appBundleId,latch:t.recoveredSnapshotWarningLatch});if(t.recoveredSnapshotWarningLatch=a.latch,!a.warning)return n;let o=Array.isArray(n.warnings)?n.warnings:[];return{...n,warnings:[a.warning,...o]}}async function ne(e){if(!s(e)||e.kind!==`simulator`)return;let t=await D({simulatorSetPath:e.simulatorSetPath});if(!t)return;let n=G(t.device,t.app.bundleId),r=`One booted device found ("${t.device.name}", udid ${t.device.id}) with ${t.app.bundleId} running. Run: ${n}`;return r.length<=350?r:void 0}function G(e,t){let n=e.simulatorSetPath?` --ios-simulator-device-set ${p(e.simulatorSetPath)}`:``;return`agent-device open ${t} --platform ios --udid ${e.id}${n}`}async function K(e,t){let{req:n,sessionName:r,sessionStore:a}=e,{session:o,device:s}=await T(a,r,n.flags),c=g(n.flags?.snapshotScope,o);if(!c.ok)return{ok:!1,response:c};let l=i({customActions:n.flags?.snapshotCustomActions===!0,hasActiveApp:o?.appBundleId!==void 0}),u=await N({device:s,use:l.use,inspectFacts:e.inspectFacts});if(!u.admitted)return{ok:!1,response:await Z({operation:u.operation,fact:u.fact,session:o,device:s,command:t})};let d=await q(e.bindDevice,s,l),f=ie(e,o,c.scope);return Object.freeze({ok:!0,session:o,device:s,snapshotScope:c.scope,captureSnapshot:async()=>await d.captureSnapshot(f)})}async function q(e,t,n){let r=P(e);switch(n.kind){case`active-app`:return J(await r(t,n.use));case`custom-actions-active-app`:return Y(await r(t,n.use));case`without-active-app`:return X(await r(t,n.use));case`custom-actions-without-active-app`:return Y(await r(t,n.use))}}function J(e){return Object.freeze({captureSnapshot:async t=>await e.operations.captureSnapshot(t)})}function Y(e){return Object.freeze({captureSnapshot:async t=>await e.operations.captureSnapshotWithCustomActions(t)})}function X(e){return Object.freeze({captureSnapshot:async t=>await e.operations.captureSnapshotWithoutActiveApp(t)})}async function Z(e){if(e.operation===`captureSnapshot`)return j(e.command,e.fact);if(e.operation===`captureSnapshotWithCustomActions`)return re(e);let t=await ne(e.device);return m(`SESSION_NOT_FOUND`,`iOS ${e.command} requires an active app session on the target device. Run open first (for example: open --session ${e.session?.name??`sim`} --platform ios --device "<name>" <app>).`,{reason:`ios_app_session_required`,...t?{hint:t}:{}})}function re(e){return m(`UNSUPPORTED_OPERATION`,e.command===`diff`?`--actions requires an iOS simulator: custom actions are read through the private accessibility snapshot backend, which ${e.device.platform}/${e.device.kind} targets do not have.`:`--actions requires an iOS simulator: custom actions are unavailable on this ${e.device.platform}/${e.device.kind} target.`,{reason:e.fact.available?void 0:e.fact.reason},{hint:e.command===`diff`||e.fact.available||!e.fact.hint?`Re-run without --actions, or target an iOS simulator.`:e.fact.hint})}function ie(e,t,n){let{req:r,logPath:i}=e,a=r.flags??{},{appBundleId:o,trace:s,surface:c}=t??{},{requestId:l}=r.meta??{},u=b(i,a,o,s?.outPath,l,r.meta);return{options:{appBundleId:o,interactiveOnly:a.snapshotInteractiveOnly,preferredBackend:a.snapshotPreferredBackend,depth:a.snapshotDepth,scope:n,raw:a.snapshotRaw,customActions:a.snapshotCustomActions,includeHiddenContentHints:a.snapshotIncludeHiddenContentHints,surface:c},execution:{requestId:u.requestId,verbose:u.verbose,logPath:u.logPath,traceLogPath:u.traceLogPath,iosXctestrunFile:u.iosXctestrunFile,iosXctestDerivedDataPath:u.iosXctestDerivedDataPath,iosXctestEnvDir:u.iosXctestEnvDir,runnerLeaseContext:u.runnerLeaseContext}}}async function Q(e){let t=await K(e,e.command);if(!t.ok)return t.response;let{session:n,device:r,snapshotScope:i}=t;return await w(n,r,async()=>{let{req:a,sessionName:o,logPath:s,sessionStore:c}=e,l={},u=ae({req:a,sessionName:o,logPath:s,sessionStore:c,session:n,device:r,snapshotScope:i,capturedQuality:l,captureSnapshotData:t.captureSnapshot}),d;try{d=await e.execute({runtime:u,sessionName:o,req:a,snapshotScope:i})}catch(t){let i=await F({error:t,command:e.command,logPath:s,session:n,device:r});if(!i)throw t;return i}return fe({req:a,sessionName:o,sessionStore:c,result:d.record}),{ok:!0,data:W({session:c.get(o),data:d.data,verdict:l.value,internalObservation:a.internal?.observationOnly===!0})}})}function ae(e){let{req:t,sessionName:n,logPath:r,sessionStore:i,session:a,device:o,snapshotScope:s}=e;return d({backend:de({req:t,logPath:r,session:a,device:o,snapshotScope:s,capturedQuality:e.capturedQuality,captureSnapshotData:e.captureSnapshotData}),...C(`snapshot`),signal:ee(t.meta?.requestId),sessions:te({sessionName:n,getSession:()=>i.get(n),recordOptions:{includeSnapshot:!0},setRecord:e=>{let r=pe(e),a=i.get(n);i.set(n,oe({current:a,sessionName:n,device:o,record:r,refScopedSnapshot:se(t),issuesRefsToClient:t.command===`snapshot`&&t.internal?.observationOnly!==!0}))}})})}function oe(e){let{current:t,sessionName:n,device:r,record:i,refScopedSnapshot:a}=e,o=ce(t,i,a),s=E({session:t,sessionName:n,device:r,snapshot:o?t.snapshot:i.snapshot,appBundleId:i.appBundleId});return _(s,{scopeSource:ue({current:t,keepCurrentSnapshot:o,refScopedSnapshot:a}),keptCurrentSnapshot:o,previousGeneration:t?.snapshotGeneration}),le(s,o,e.issuesRefsToClient),i.appName&&(s.appName=i.appName),s}function se(e){return e.flags?.snapshotScope?.trim().startsWith(`@`)===!0}function ce(e,t,n){return n&&t.snapshot?.nodes.length===0&&e?.snapshot!==void 0}function le(e,t,n){!t&&n&&x(e)}function ue(e){let{current:t,keepCurrentSnapshot:n,refScopedSnapshot:r}=e;if(r)return n?t?.snapshotScopeSource:t?.snapshotScopeSource??t?.snapshot}function de(e){let{req:t,logPath:i,session:a,device:s,snapshotScope:c}=e;return{platform:o(s),captureSnapshot:async(o,l)=>{let u=await S({device:s,session:a,flags:t.flags,outPath:l?.outPath??t.flags?.out,logPath:i,snapshotScope:c,signal:o.signal,captureData:e.captureSnapshotData}),d=r(u);e.capturedQuality.value=d.quality;let f=n(a);return{snapshot:u.snapshot,...d,...f?{snapshotDiagnostics:f}:{},appName:a?.appBundleId?a.appName??a.appBundleId:void 0,appBundleId:a?.appBundleId}}}}function fe(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:$(e.result),interactiveObservation:c(e.req)})}function pe(e){if(!e.snapshot)throw new t(`UNKNOWN`,`snapshot runtime did not produce session state`);return e}function $(e){return e.kind===`snapshot`?{nodes:e.nodes,truncated:e.truncated}:{mode:e.mode,baselineInitialized:e.baselineInitialized,summary:e.summary}}async function me(e){let t=e.session;if(!t||!l(e.verdict)||e.req.internal?.observationOnly===!0)return;let n=await he({...e,session:t});if(n!==void 0)return{path:n,artifact:{field:`fallbackScreenshotPath`,artifactType:`screenshot`,path:n,fileName:`snapshot-fallback.png`}}}async function he(e){let{req:t,session:n}=e;try{let r=await y({session:n,sessionName:e.sessionName,outputPlacement:`default`,dispatchContext:b(e.logPath,t.flags,n.appBundleId,n.trace?.outPath,t.meta?.requestId,t.meta)});return typeof r.path==`string`?r.path:void 0}catch{return}}async function ge(e){return await Q({...e,command:`snapshot`,execute:async({runtime:t,sessionName:n,req:r,snapshotScope:i})=>{let o=await t.capture.snapshot({session:n,interactiveOnly:r.flags?.snapshotInteractiveOnly,depth:r.flags?.snapshotDepth,scope:i,raw:r.flags?.snapshotRaw,customActions:r.flags?.snapshotCustomActions,forceFull:r.flags?.snapshotForceFull}),s=_e(r,e.sessionStore.get(n)),c=a(o.nodes),l=c===o.nodes?o:{...o,nodes:c},u=await me({req:r,session:e.sessionStore.get(n),sessionName:n,logPath:e.logPath,verdict:o.snapshotQuality}),d=u?{...l,fallbackScreenshotPath:u.path,artifacts:[u.artifact]}:l;return{data:s===void 0?d:{...d,refsGeneration:s},record:{kind:`snapshot`,nodes:o.nodes.length,truncated:o.truncated}}}})}function _e(e,t){return e.internal?.observationOnly===!0?void 0:t?.snapshotGeneration}export{j as a,M as i,Q as n,P as r,ge as t};
@@ -0,0 +1 @@
1
+ function e(e,t){let n=t.toLowerCase();return[e.label,e.value,e.identifier].some(e=>(e??``).toLowerCase().includes(n))}function t(t,n){let r=t.findIndex(t=>e(t,n));if(r===-1)return null;let i=t[r]?.depth??0,a=r+1;for(;a<t.length&&(t[a]?.depth??0)>i;)a+=1;return{start:r,end:a}}function n(e,t=0){let n=new Map;for(let[t,r]of e.entries())n.set(r.index,t);return e.map((e,r)=>({...e,index:r,depth:Math.max(0,(e.depth??0)-t),parentIndex:typeof e.parentIndex==`number`?n.get(e.parentIndex):void 0}))}export{e as n,n as r,t};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{s as t}from"./sdk-batch-runner.js";import{c as n}from"./sdk-device.js";import"./screenshot-result.js";import{n as r}from"./runtime.js";import{j as i}from"./sdk-android-adb.js";import{E as a,g as o}from"./dispatch.js";import{w as s}from"./physical-device-control.js";import{fn as c,ot as l,pt as u}from"./internal/daemon.js";import{a as d}from"./apps.js";import{t as f}from"./device-ready.js";function p(t,n={}){let r=n.plural===!0?`do`:`does`;return{resolveInput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not create temporary files`)}}}function m(e,t={}){return{artifacts:p(e,t),policy:r()}}function h(e){let{req:t,logPath:n,traceLogPath:r}=e;return{verbose:t.flags?.verbose,logPath:n,traceLogPath:r,requestId:t.meta?.requestId,iosXctestrunFile:t.flags?.iosXctestrunFile,iosXctestDerivedDataPath:t.flags?.iosXctestDerivedDataPath,iosXctestEnvDir:t.flags?.iosXctestEnvDir}}function g(e){let{req:t,logPath:n,appBundleId:r,traceLogPath:i}=e;return{...h({req:t,logPath:n,traceLogPath:i}),runnerLeaseContext:c(n,t.flags,r,i,t.meta?.requestId,t.meta).runnerLeaseContext}}function _(e){let{req:t,logPath:r,device:i,traceLogPath:o,enabled:s}=e;if(!(!s||!n(i)||a(i)||i.kind!==`simulator`))return e=>l(e,h({req:t,logPath:r,traceLogPath:o}))}function v(e){let{req:n,logPath:r,device:i,surface:a,openTarget:o,traceLogPath:s}=e;return _({req:n,logPath:r,device:i,traceLogPath:s,enabled:a===`app`&&!!o&&!t(o??``)})}async function y(e,t,n){let r=e.get(t),i=r?.device??await o(n??{});return r||await f(i),{session:r,device:i}}async function b(e,t,r){let i=!e&&n(t);try{return await r()}finally{i&&(await u(t.id),await x(t))}}async function x(e){let t=s();await d(e,t).catch(n=>{i({level:`debug`,phase:`ios_sessionless_runner_host_close_failed`,data:{deviceId:e.id,bundleId:t,error:n instanceof Error?n.message:String(n)}})})}function S(e,t,n,r){t&&e.recordAction(t,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:r})}function C(e){let{session:t,sessionName:n,device:r,snapshot:i,appBundleId:a}=e;return t?{...t,snapshot:i,lastComparisonSafeSnapshot:i?.comparisonSafe===!0?i:t.lastComparisonSafeSnapshot}:{name:n,device:r,createdAt:Date.now(),appBundleId:a,snapshot:i,...i?.comparisonSafe===!0?{lastComparisonSafeSnapshot:i}:{},actions:[]}}export{h as a,_ as c,b as i,m as l,S as n,g as o,y as r,v as s,C as t};
1
+ import{_ as e}from"./sdk-contracts.js";import{c as t}from"./sdk-device.js";import"./screenshot-result.js";import{n}from"./runtime.js";import{A as r}from"./sdk-android-adb.js";import{p as i}from"./dispatch.js";import{p as a}from"./physical-device-control.js";import{s as o}from"./runner-client.js";import{a as s}from"./apps.js";import{t as c}from"./device-ready.js";function l(t,n={}){let r=n.plural===!0?`do`:`does`;return{resolveInput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not create temporary files`)}}}function u(e,t={}){return{artifacts:l(e,t),policy:n()}}async function d(e,t,n){let r=e.get(t),a=r?.device??await i(n??{});return r||await c(a),{session:r,device:a}}async function f(e,n,r){let i=!e&&t(n);try{return await r()}finally{i&&(await o(n.id),await p(n))}}async function p(e){let t=a();await s(e,t).catch(n=>{r({level:`debug`,phase:`ios_sessionless_runner_host_close_failed`,data:{deviceId:e.id,bundleId:t,error:n instanceof Error?n.message:String(n)}})})}function m(e,t,n,r){t&&e.recordAction(t,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:r})}function h(e){let{session:t,sessionName:n,device:r,snapshot:i,appBundleId:a}=e;return t?{...t,snapshot:i,lastComparisonSafeSnapshot:i?.comparisonSafe===!0?i:t.lastComparisonSafeSnapshot}:{name:n,device:r,createdAt:Date.now(),appBundleId:a,snapshot:i,...i?.comparisonSafe===!0?{lastComparisonSafeSnapshot:i}:{},actions:[]}}export{u as a,f as i,m as n,d as r,h as t};
@@ -1 +1,8 @@
1
- import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{j as n}from"./sdk-android-adb.js";import{n as r,t as i}from"./tool-provider2.js";import a from"node:path";import o from"node:fs";import{fileURLToPath as s}from"node:url";const c={"push button":`Button`,"toggle button":`Button`,"push button menu":`Button`,label:`StaticText`,static:`StaticText`,caption:`StaticText`,text:`TextField`,entry:`TextField`,"password text":`TextField`,"spin button":`TextField`,terminal:`TextArea`,"document text":`TextArea`,paragraph:`TextArea`,frame:`Window`,window:`Window`,dialog:`Dialog`,alert:`Alert`,"file chooser":`Dialog`,"color chooser":`Dialog`,"font chooser":`Dialog`,panel:`Group`,filler:`Group`,section:`Group`,form:`Group`,grouping:`Group`,"layered pane":`Group`,"glass pane":`Group`,"root pane":`Group`,"option pane":`Group`,"internal frame":`Group`,"desktop frame":`Group`,"block quote":`Group`,article:`Group`,comment:`Group`,landmark:`Group`,log:`Group`,marquee:`Group`,math:`Group`,notification:`Group`,"content deletion":`Group`,"content insertion":`Group`,mark:`Group`,suggestion:`Group`,"scroll pane":`ScrollArea`,"scroll bar":`ScrollBar`,"menu bar":`MenuBar`,menu:`Menu`,"popup menu":`Menu`,"menu item":`MenuItem`,"check menu item":`MenuItem`,"radio menu item":`MenuItem`,"tearoff menu item":`MenuItem`,"check box":`CheckBox`,"radio button":`RadioButton`,switch:`Switch`,"combo box":`ComboBox`,"page tab":`Tab`,"page tab list":`TabList`,table:`Table`,"tree table":`Table`,"table cell":`Cell`,"table row":`Row`,"table column header":`Cell`,"table row header":`Cell`,"column header":`Cell`,"row header":`Cell`,list:`List`,"list item":`ListItem`,"list box":`List`,tree:`Tree`,"tree item":`TreeItem`,"description list":`List`,"description term":`ListItem`,"description value":`ListItem`,"tool bar":`Toolbar`,"status bar":`StatusBar`,"info bar":`StatusBar`,slider:`Slider`,"progress bar":`ProgressBar`,"level bar":`ProgressBar`,image:`Image`,icon:`Image`,animation:`Image`,canvas:`Image`,"drawing area":`Image`,video:`Video`,audio:`Audio`,link:`Link`,hyperlink:`Link`,separator:`Separator`,application:`Application`,"tool tip":`Tooltip`,timer:`Timer`,heading:`Heading`,footnote:`Footnote`,"title bar":`TitleBar`,"date editor":`DateEditor`,rating:`Slider`};function l(e){let t=e.toLowerCase().trim();return c[t]||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}const u=`atspi-dump.py`;let d=null;function f(){if(d)return d;let e=a.dirname(s(import.meta.url));for(let t=0;t<6;t++){let t=a.join(e,`linux`,u);if(o.existsSync(t))return d=t,t;e=a.dirname(e)}throw new t(`TOOL_MISSING`,`Cannot find ${u}. Ensure the agent-device package is installed correctly.`)}async function p(e,n={}){let a=i().accessibility;if(a)return await a.captureTree(e,n);if(process.platform!==`linux`)throw new t(`UNSUPPORTED_PLATFORM`,`AT-SPI2 bridge is only available on Linux`);if(!await i().whichCommand(`python3`))throw new t(`TOOL_MISSING`,`python3 is required for AT-SPI2 accessibility snapshots on Linux.`);let o=n.maxNodes??1500,s=n.maxDepth??12,c=n.maxApps??24,u=await r(`python3`,[f(),`--surface`,e,`--max-nodes`,String(o),`--max-depth`,String(s),`--max-apps`,String(c)],{allowFailure:!0,timeoutMs:3e4,signal:n.signal});if(u.exitCode!==0){let e=u.stderr.trim();throw e.includes(`No module named`)||e.includes(`gi.require_version`)?new t(`TOOL_MISSING`,`AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.`,{cause:e}):new t(`COMMAND_FAILED`,`AT-SPI2 snapshot failed (exit ${u.exitCode}): ${e||u.stdout}`)}let d;try{d=JSON.parse(u.stdout)}catch{throw new t(`COMMAND_FAILED`,`AT-SPI2 snapshot returned invalid JSON: ${u.stdout.slice(0,200)}`)}if(d.error)throw new t(`COMMAND_FAILED`,`AT-SPI2: ${d.error}`);return{nodes:(d.nodes??[]).map(e=>({index:e.index,type:l(e.role),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0})),truncated:d.truncated,surface:e}}var m=e({readLinuxTextAtPoint:()=>_,snapshotLinux:()=>g});function h(e){return e===`desktop`?`desktop`:e===`frontmost-app`||e===`app`?`frontmost-app`:(e===`menubar`&&n({level:`warn`,phase:`linux_snapshot`,data:{message:`menubar surface is not supported on Linux, falling back to desktop`}}),`desktop`)}async function g(e,t){let n=await p(h(e),{signal:t});return{nodes:n.nodes,truncated:n.truncated}}async function _(e,t,n){let{nodes:r}=await g(n),i=r.filter(n=>{let r=n.rect;return r?e>=r.x&&t>=r.y&&e<=r.x+r.width&&t<=r.y+r.height:!1}).sort((e,t)=>{let n=e.depth??0,r=t.depth??0;return n===r?v(e.rect)-v(t.rect):r-n});for(let e of i){let t=y(e);if(t.trim())return t}return``}function v(e){return(e?.width??0)*(e?.height??0)}function y(e){for(let t of[e.value,e.label,e.identifier])if(typeof t==`string`&&t.length>0)return t;return``}export{m as n,g as t};
1
+ import{A as e,E as t,_ as n,c as r,u as i,v as a}from"./sdk-contracts.js";import{Lt as o,Or as s,Rt as c,Wt as l}from"./sdk-batch-runner.js";import{n as u,r as d}from"./snapshot-scope.js";import{r as f}from"./mobile-snapshot-semantics.js";import{A as p,F as m,f as ee,i as te,n as ne,s as h}from"./sdk-android-adb.js";import{n as re,t as ie}from"./version.js";import{t as ae}from"./timeouts.js";import"./app-lifecycle.js";import{t as oe}from"./bounds.js";import{t as se}from"./entities.js";import{a as ce,d as g,i as le,o as ue,s as de,t as fe,u as _}from"./helper-package-install.js";import v from"node:path";import y from"node:fs/promises";import pe from"node:net";function me(e,t,n,r){let i=he(t,n,new Set(e.sourceNodes));if(!i)return{nodes:[],sourceNodes:[]};let a=_e(i),o=[...e.sourceNodes.entries()].filter(([,e])=>a.has(e)).map(([e])=>e);if(o.length===0)return{nodes:[],sourceNodes:[]};let s=Math.min(...o.map(t=>e.nodes[t]?.depth??0)),c=o.filter(t=>(e.nodes[t]?.depth??0)-s<=r);return{nodes:d(c.map(t=>e.nodes[t]),s),sourceNodes:c.map(t=>e.sourceNodes[t])}}function he(e,t,n){for(let r of b(e))if(u(r,t)&&ge(r,n))return r;return null}function*b(e){let t=[...e].reverse();for(;t.length>0;){let e=t.pop();yield e;for(let n=e.children.length-1;n>=0;--n)t.push(e.children[n])}}function ge(e,t){for(let n of b([e]))if(t.has(n))return!0;return!1}function _e(e){return new Set(b([e]))}function ve(){let e=[],t=()=>e[e.length-1]===!0;return{open(n,r){let i=t()||c(n);return r||e.push(i),i},close(){e.pop()}}}function*ye(e){let t=/<node\b[^>]*>|<\/node>/g,n=ve(),r=t.exec(e);for(;r;){let i=r[0];if(i.startsWith(`</node`))n.close();else{let e=be(i);yield n.open(e.resourceId,i.endsWith(`/>`))?{...e,systemChrome:!0}:e}r=t.exec(e)}}function be(e){let t=Ee(e),n=oe(t.bounds);return{...t,...n?{rect:n}:{}}}function xe(e,t,n){let r=n.depth??1/0,i={nodes:[],sourceNodes:[],...t===void 0?{}:{maxNodes:t},maxDepth:n.scope?1/0:r,options:n,analysis:_t(e),interactiveDescendantMemo:new Map,truncated:!1};for(let t of e.children)if(Se(i,t,0),i.truncated)break;let{nodes:a,sourceNodes:o}=n.scope?me(i,e.children,n.scope,r):i,s={nodes:a,sourceNodes:o,analysis:i.analysis};return i.truncated?{...s,truncated:!0}:s}function Se(e,t,n,r,i=!1,a=!1,o=!1){if(e.maxNodes!==void 0&&e.nodes.length>=e.maxNodes){e.truncated=!0;return}if(n>e.maxDepth)return;let s=e.options.raw?!0:ct(t,e.options,i,Te(e,t),a),l=o||c(t.identifier),u=s?Ce(e,t,r,l):r,d=i||C(t),f=a||mt(t.type);for(let r of t.children)if(Se(e,r,n+1,u,d,f,l),e.truncated)return}function Ce(e,t,n,r){let i=e.nodes.length;return e.sourceNodes.push(t),e.nodes.push({index:i,type:t.type??void 0,label:t.label??void 0,value:t.value??void 0,identifier:t.identifier??void 0,bundleId:t.packageName??void 0,rect:t.rect,enabled:t.enabled,focused:t.focused,visibleToUser:t.visibleToUser,hittable:C(t)||void 0,depth:we(e.nodes,n),parentIndex:n,...t.hiddenContentAbove?{hiddenContentAbove:!0}:{},...t.hiddenContentBelow?{hiddenContentBelow:!0}:{},...r?{systemChrome:!0}:{}}),i}function we(e,t){return t===void 0?0:(e[t]?.depth??-1)+1}function Te(e,t){let n=e.interactiveDescendantMemo.get(t);if(n!==void 0)return n;for(let n of t.children)if(n.visibleToUser!==!1&&(C(n)||Te(e,n)))return e.interactiveDescendantMemo.set(t,!0),!0;return e.interactiveDescendantMemo.set(t,!1),!1}function Ee(e){let t=De(e),n=e=>Pe(t,e),r=e=>{let t=n(e);if(t!==null)return t===`true`},i=e=>{let t=n(e);if(t===null||t.trim()===``)return;let r=Number(t);return Number.isFinite(r)?r:void 0},a=(e,t)=>{let n=i(t);return n===void 0?{}:{[e]:n}},o=(e,t)=>{let r=oe(n(t));return r===void 0?{}:{[e]:r}},s=(e,t)=>{let n=r(t);return n===void 0?{}:{[e]:n}};return{text:n(`text`),desc:n(`content-desc`),resourceId:n(`resource-id`),packageName:n(`package`),className:n(`class`),bounds:n(`bounds`),clickable:r(`clickable`),enabled:r(`enabled`),focusable:r(`focusable`),focused:r(`focused`),password:r(`password`),...s(`visibleToUser`,`visible-to-user`),...a(`drawingOrder`,`drawing-order`),...s(`scrollable`,`scrollable`),...s(`canScrollForward`,`can-scroll-forward`),...s(`canScrollBackward`,`can-scroll-backward`),...a(`windowIndex`,`window-index`),...a(`windowType`,`window-type`),...a(`windowLayer`,`window-layer`),...s(`windowActive`,`window-active`),...s(`windowFocused`,`window-focused`),...o(`windowRect`,`window-bounds`)}}function De(e){let t=new Map,n=e.indexOf(` `),r=e.lastIndexOf(`>`);if(n<0||r<=n)return t;let i=n;for(;i<r;){let n=Oe(e,i,r);if(!n)break;t.set(n.name,n.value),i=n.nextCursor}return t}function Oe(e,t,n){if(t=x(e,t,n),t>=n||Ae(e[t]))return;let r=t;t=ke(e,t,n);let i=e.slice(r,t);if(t=x(e,t,n),!i||e[t]!==`=`)return;t=x(e,t+1,n);let a=e[t];if(!je(a))return;let o=t+1,s=e.indexOf(a,o);if(!(s<0||s>=n))return{name:i,value:se(e.slice(o,s)),nextCursor:s+1}}function ke(e,t,n){for(;t<n&&!Ne(e[t]??``);)t+=1;return t}function x(e,t,n){for(;t<n&&Me(e[t]??``);)t+=1;return t}function Ae(e){return e===`/`||e===`>`}function je(e){return e===`"`||e===`'`}function Me(e){return e===` `||e===`
2
+ `||e===`\r`||e===` `}function Ne(e){return e===`=`||e===`/`||e===`>`||Me(e)}function Pe(e,t){return e.get(t)??null}function Fe(e){let t={type:null,label:null,value:null,identifier:null,packageName:null,clickable:!1,focusable:!1,depth:-1,children:[]},n=[t],r=/<node\b[^>]*>|<\/node>/g,i=r.exec(e);for(;i;){let t=i[0];if(t.startsWith(`</node`)){n.length>1&&n.pop(),i=r.exec(e);continue}let a=be(t),o=n[n.length-1],s={type:a.className,label:a.text||a.desc,value:a.text,identifier:a.resourceId,packageName:a.packageName,rect:a.rect,enabled:a.enabled,focused:a.focused,visibleToUser:a.visibleToUser,drawingOrder:a.drawingOrder,clickable:a.clickable===!0,focusable:a.focusable===!0,scrollable:a.scrollable,canScrollForward:a.canScrollForward,canScrollBackward:a.canScrollBackward,windowIndex:a.windowIndex,windowType:a.windowType,windowLayer:a.windowLayer,windowActive:a.windowActive,windowFocused:a.windowFocused,windowRect:a.windowRect,depth:o.depth+1,parentIndex:void 0,children:[]};o.children.push(s),t.endsWith(`/>`)||n.push(s),i=r.exec(e)}return qe(t),tt(t),Je(t,{footprintMemo:new WeakMap}),et(t),t}function S(e){return e.clickable}function Ie(e){return e.focusable||e.focused===!0}function C(e){return S(e)||Ie(e)}function Le(e){return $e(e)||Ze(e)}function Re(e){return e.visibleToUser!==!1&&S(e)}function ze(e,t){return e.children.some(e=>e.visibleToUser!==!1&&w(e,t).hasAgentTarget)}function w(e,t){let n=t.footprintMemo.get(e);if(n!==void 0)return n;let r=T(e)?Be(e,e.rect,t):Ve(e,t);return t.footprintMemo.set(e,r),r}function Be(e,t,n){if(He(e))return{paints:[t],shows:[t],hasAgentTarget:C(e)};let r=Ve(e,n);return Le(e)&&r.shows.push(t),r}function Ve(e,t){let n={paints:[],shows:[],hasAgentTarget:C(e)};for(let r of e.children){if(r.visibleToUser===!1)continue;let e=w(r,t);n.hasAgentTarget||=e.hasAgentTarget,n.paints.push(...e.paints),n.shows.push(...e.shows)}return n}function He(e){return S(e)||e.scrollable===!0||e.children.length===0&&$e(e)}function Ue(e,t){let n=We([...e,...t],e=>[e.x,e.x+e.width]),r=We([...e,...t],e=>[e.y,e.y+e.height]),i=Ge(e,n,r),a=Ge(t,n,r),o=0,s=0;for(let e=0;e<n.length-1;e+=1){let t=n[e+1]-n[e];for(let n=0;n<r.length-1;n+=1){let c=e*(r.length-1)+n;if(!a[c])continue;let l=t*(r[n+1]-r[n]);o+=l,i[c]&&(s+=l)}}return o<=0?0:s/o}function We(e,t){return[...new Set(e.flatMap(t))].sort((e,t)=>e-t)}function Ge(e,t,n){let r=n.length-1,i=new Uint8Array((t.length-1)*r);for(let a of e){let e=t.indexOf(a.x),o=t.indexOf(a.x+a.width),s=n.indexOf(a.y),c=n.indexOf(a.y+a.height);for(let t=e;t<o;t+=1)i.fill(1,t*r+s,t*r+c)}return i}function Ke(e){return e.children.length===0&&!C(e)&&Le(e)}function qe(e){let t=0;for(let n of e.children)n.visibleToUser!==!1&&(qe(n),e.children[t]=n,t+=1);t<e.children.length&&(e.children.length=t)}function Je(e,t){for(let n of e.children)Je(n,t);if(e.children.length<2)return;let n=e.children,r=n.map(e=>Qe(e,t)).filter(e=>e!==null);r.length!==0&&(e.children=n.filter(e=>Ye(e,r,t)))}function Ye(e,t,n){return Ke(e)||!Xe(e,t,n)}function Xe(e,t,n){if(e.visibleToUser===!1||e.drawingOrder===void 0||!T(e))return!1;let r=w(e,n).shows,i=r.length>0?r:[e.rect];for(let n of t)if(!(n.node===e||n.drawingOrder<=e.drawingOrder)&&Ue(n.footprint,i)>=.9)return!0;return!1}function Ze(e){let t=e.identifier?.trim()??``;return!!(t&&!E(t))}function Qe(e,t){let{drawingOrder:n}=e;if(e.visibleToUser===!1||n===void 0||!T(e)||!Re(e)&&!ze(e,t))return null;let r=w(e,t).paints;return r.length>0?{node:e,drawingOrder:n,footprint:r}:null}function $e(e){let t=e.label?.trim()??``;return!!(t&&!E(t))}function T(e){return!!(e.rect&&e.rect.width>0&&e.rect.height>0)}function et(e){let t=[...e.children];for(;t.length>0;){let e=t.pop();t.push(...e.children),ot(e)&&(e.canScrollBackward&&(e.hiddenContentAbove=!0),e.canScrollForward&&(e.hiddenContentBelow=!0))}}function tt(e){let t=e.children.filter(rt);if(t.length<2)return;let n=t.filter(e=>it(e)&&at(e));if(n.length===0)return;let r=nt(n);e.children=e.children.filter(e=>it(e)?at(e)?r===void 0||e.windowLayer===r:!1:!0)}function nt(e){let t=e.map(e=>e.windowLayer).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function rt(e){return e.windowIndex!==void 0||e.windowType!==void 0}function it(e){return e.windowType===1}function at(e){return e.windowActive===!0||e.windowFocused===!0}function ot(e){if(!e.scrollable||!s(e.type)||`${e.type??``}`.toLowerCase().includes(`horizontalscrollview`))return!1;let t=st(e);return!(t&&t.horizontal>t.vertical&&t.horizontal>16)}function st(e){if(!e.rect||e.children.length===0)return null;let t=e.children.map(e=>e.rect).filter(e=>e!==void 0);if(t.length===0)return null;let n=Math.min(...t.map(e=>e.x)),r=Math.max(...t.map(e=>e.x+e.width)),i=Math.min(...t.map(e=>e.y)),a=Math.max(...t.map(e=>e.y+e.height));return{horizontal:Math.max(0,r-n-e.rect.width),vertical:Math.max(0,a-i-e.rect.height)}}function ct(e,t,n,r,i){if(e.visibleToUser===!1)return!1;let a=lt(e);return t.interactiveOnly?ut(e,a,n,r,i):a.isStructural||a.isVisual?pt(e,a,r):!0}function lt(e){let t=ht(e.type),n=!!(e.label&&e.label.trim().length>0),r=!!(e.identifier&&e.identifier.trim().length>0);return{type:t,hasMeaningfulText:n&&!E(e.label??``),hasMeaningfulId:r&&!E(e.identifier??``),isStructural:gt(t),isVisual:t===`imageview`||t===`imagebutton`}}function ut(e,t,n,r,i){return ft(e)?!1:C(e)||s(t.type)&&r?!0:dt(t,n,r,i)}function dt(e,t,n,r){return!e.hasMeaningfulText&&!e.hasMeaningfulId||e.isVisual||e.isStructural&&!r&&!t?!1:t||n||r}function ft(e){return!!(e.rect&&(e.rect.width<=0||e.rect.height<=0))}function pt(e,t,n){return C(e)||t.hasMeaningfulText||t.hasMeaningfulId?!0:n}function mt(e){if(!e)return!1;let t=ht(e);return t.includes(`recyclerview`)||t.includes(`listview`)||t.includes(`gridview`)}function ht(e){return e?e.toLowerCase():``}function gt(e){let t=e.split(`.`).pop()??e;return t.includes(`layout`)||t===`viewgroup`||t===`view`}function E(e){let t=e.trim();return t?/^[\w.]+:id\/[\w.-]+$/i.test(t):!1}function _t(e){let t=0,n=0,r=[...e.children];for(;r.length>0;){let e=r.pop();t+=1,n=Math.max(n,e.depth),r.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}const D=`android-snapshot-helper-v1`,O=`uiautomator-xml`,vt={"-r":`replace`,"-t":`allowTestPackages`,"-d":`allowDowngrade`,"-g":`grantPermissions`};function yt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest must be an object.`);let t=e;return{name:A(t.name,`name`,`android-snapshot-helper`),version:j(t.version,`version`),releaseTag:M(t.releaseTag),assetName:M(t.assetName),apkUrl:wt(t.apkUrl,`apkUrl`),sha256:Ct(t.sha256),checksumName:M(t.checksumName),packageName:j(t.packageName,`packageName`),versionCode:k(t.versionCode,`versionCode`),instrumentationRunner:j(t.instrumentationRunner,`instrumentationRunner`),minSdk:k(t.minSdk,`minSdk`),targetSdk:t.targetSdk===void 0?void 0:k(t.targetSdk,`targetSdk`),outputFormat:A(t.outputFormat,`outputFormat`,O),statusProtocol:A(t.statusProtocol,`statusProtocol`,D),installArgs:xt(t.installArgs)}}function k(e,t){return ue(e,t,`snapshot helper`)}function A(e,t,n){return de(e,t,n,`snapshot helper`)}function bt(e){return St(xt(e.installArgs))}function xt(e){let t=Tt(e,`installArgs`);if(t[0]!==`install`)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must start with "install".`);if(t.some(e=>e.includes(`\0`)))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs must not contain null bytes.`);let r=t.slice(1).find(e=>!Et(e));if(r)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);return t}function St(e){let t={};for(let r of e.slice(1)){let e=Dt(r);if(!e)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest installArgs contains unsupported install flag "${r}".`);t[e]=!0}return t}function Ct(e){let t=j(e,`sha256`).trim().toLowerCase();if(t.length!==64||!Ot(t))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest sha256 must be a 64-character hex string.`);return t}function j(e,t){if(typeof e!=`string`||e.trim().length===0)throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} is required.`);return e}function M(e){return typeof e==`string`&&e.trim().length>0?e:void 0}function wt(e,t){return e===null?null:j(e,t)}function Tt(e,t){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`))throw new n(`INVALID_ARGS`,`Android snapshot helper manifest ${t} must be a string array.`);return e}function Et(e){return Dt(e)!==void 0}function Dt(e){if(Object.hasOwn(vt,e))return vt[e]}function Ot(e){for(let t of e){let e=t.charCodeAt(0);if(!(e>=48&&e<=57)&&!(e>=97&&e<=102))return!1}return!0}const kt=2e3,At=`android_snapshot_helper_retirement_unconfirmed`,N=new Map;function P(e){return`${e.platform}:${e.id}`}async function jt(e){await Lt({adb:e.adb,packageName:e.packageName,timeoutMs:2e3})||I(e)}async function F(e){let t=N.get(e.deviceKey);if(t){try{let n=await e.adb([`shell`,`am`,`force-stop`,t.packageName],{allowFailure:!0,timeoutMs:5e3,signal:e.signal});if(e.signal?.throwIfAborted(),n.exitCode===0){N.delete(e.deviceKey);return}}catch{e.signal?.throwIfAborted()}I({deviceKey:e.deviceKey,packageName:t.packageName,cause:t.cause})}}function I(e){let t=e.cause instanceof Error?e.cause.message:String(e.cause);throw N.set(e.deviceKey,{packageName:e.packageName,cause:t}),new n(`COMMAND_FAILED`,`Android snapshot helper could not confirm release of device automation ownership`,{reason:At,deviceKey:e.deviceKey,cause:t,hint:`Retry after the helper process exits, or restart the device if Android still reports automation as busy.`})}function Mt(e){return e instanceof n&&e.details?.reason===At}async function Nt(e){let t=AbortSignal.timeout(e.timeoutMs),[n]=await Promise.allSettled([Lt({adb:e.adb,packageName:e.packageName,timeoutMs:e.timeoutMs,signal:t}),Rt({...e,signal:t})]);return{timedOut:t.aborted,runtimeForceStopped:n?.status===`fulfilled`?n.value:!1}}function Pt(e){return e.exitCode!=null||e.signalCode!=null?Promise.resolve():new Promise(t=>{e.once(`close`,()=>t()),e.once(`exit`,()=>t())})}async function L(e,t,n){let r,i,a=await Promise.race([e.then(()=>!0),new Promise(e=>{r=setTimeout(()=>e(!1),t)}),...n?[new Promise(e=>{i=()=>e(!1),n.addEventListener(`abort`,i,{once:!0}),n.aborted&&i()})]:[]]);return r&&clearTimeout(r),i&&n?.removeEventListener(`abort`,i),a}async function Ft(e){if(e.alreadyExited)return!0;try{e.process.kill(`SIGTERM`)}catch{}return await L(e.processExit,e.timeoutMs)}function It(){N.clear()}async function Lt(e){let t=e.signal??AbortSignal.timeout(e.timeoutMs);try{return(await e.adb([`shell`,`am`,`force-stop`,e.packageName],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:t})).exitCode===0}catch{return!1}}async function Rt(e){e.process.stdin?.end(),e.process.stdout?.destroy(),e.process.stderr?.destroy(),await e.adb([`forward`,`--remove`,`tcp:${e.port}`],{allowFailure:!0,timeoutMs:e.timeoutMs,signal:e.signal})}async function zt(e){let t=R(e),r=e.deviceKey??`android:default`;await F({deviceKey:r,adb:e.adb,signal:e.signal});let i;try{i=await e.adb(Bt(t),{allowFailure:!0,timeoutMs:t.commandTimeoutMs,signal:e.signal})}catch(n){throw e.signal?.aborted?(await jt({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:n}),e.signal.throwIfAborted(),n):n}e.signal?.aborted&&(await jt({deviceKey:r,packageName:t.packageName,adb:e.adb,cause:e.signal.reason}),e.signal.throwIfAborted());let{output:a,cleanupDone:o}=await Vt(e,t,i);if(t.outputPath&&!o&&await Jt(e.adb,t.outputPath),i.exitCode!==0)throw new n(`COMMAND_FAILED`,`Android snapshot helper failed`,ee(i,{helper:a.metadata}));return a}function R(e){let t=z(e.timeoutMs,8e3),n=z(e.packageName,`com.callstack.agentdevice.snapshothelper`);return{waitForIdleTimeoutMs:z(e.waitForIdleTimeoutMs,500),waitForIdleQuietMs:z(e.waitForIdleQuietMs,100),timeoutMs:t,commandTimeoutMs:z(e.commandTimeoutMs,t+5e3),maxDepth:z(e.maxDepth,128),maxNodes:z(e.maxNodes,5e3),packageName:n,runner:z(e.instrumentationRunner,`${n}/.SnapshotInstrumentation`),...e.outputPath?{outputPath:e.outputPath}:{},...e.emitChunks===void 0?{}:{emitChunks:e.emitChunks}}}function z(e,t){return e===void 0?t:e}function Bt(e){return[`shell`,`am`,`instrument`,`-w`,`-e`,`waitForIdleTimeoutMs`,String(e.waitForIdleTimeoutMs),`-e`,`waitForIdleQuietMs`,String(e.waitForIdleQuietMs),`-e`,`timeoutMs`,String(e.timeoutMs),`-e`,`maxDepth`,String(e.maxDepth),`-e`,`maxNodes`,String(e.maxNodes),...e.outputPath?[`-e`,`outputPath`,e.outputPath]:[],...e.emitChunks===void 0?[]:[`-e`,`emitChunks`,String(e.emitChunks)],e.runner]}async function Vt(e,t,n){try{return{output:Yt(`${n.stdout}\n${n.stderr}`),cleanupDone:!1}}catch(r){return await Ht(e,t,n,r)}}async function Ht(e,t,r,i){if(i instanceof n&&r.exitCode!==0&&i.details?.helper)throw i;let a=await Ut(e,t,r);if(a)return{output:a,cleanupDone:!0};throw new n(`COMMAND_FAILED`,r.exitCode===0?`Android snapshot helper output could not be parsed`:`Android snapshot helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},i)}async function Ut(e,t,n){if(!(n.exitCode!==0||!t.outputPath))return await Gt(e.adb,t.outputPath,qt(`${n.stdout}\n${n.stderr}`)??Wt(t))}function Wt(e){return{outputFormat:O,waitForIdleTimeoutMs:e.waitForIdleTimeoutMs,waitForIdleQuietMs:e.waitForIdleQuietMs,timeoutMs:e.timeoutMs,maxDepth:e.maxDepth,maxNodes:e.maxNodes,transport:`instrumentation`}}async function Gt(e,t,n){let r;try{r=await e(Kt(t),{allowFailure:!0,timeoutMs:5e3})}catch{return}if(r.exitCode!==0)return;let i=r.stdout.trim();if(!(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`)))return{xml:i,metadata:n}}function Kt(e){return[`shell`,`sh`,`-c`,`cat "$1"; status=$?; rm -f "$1"; exit "$status"`,`agent-device-snapshot-helper-output`,e]}function qt(e){try{return rn(Zt(ce(e).results))}catch{return null}}async function Jt(e,t){try{await e([`shell`,`rm`,`-f`,t],{allowFailure:!0,timeoutMs:5e3})}catch{}}function Yt(e){let t=ce(e),n=Zt(t.results);return{xml:$t(Xt(t.status),n),metadata:{...rn(n),transport:`instrumentation`}}}function Xt(e){let t=[];for(let n of e){if(n.agentDeviceProtocol!==`android-snapshot-helper-v1`||n.outputFormat!==`uiautomator-xml`)continue;let{payloadBase64:e}=n;e!==void 0&&t.push({index:B(n.chunkIndex),count:B(n.chunkCount),payloadBase64:e})}return t}function Zt(e){let t=e.find(e=>e.agentDeviceProtocol===D);if(!t)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return a final result`);if(t.ok!==`true`)throw new n(`COMMAND_FAILED`,Qt(t),{errorType:t.errorType,helper:t});return t}function Qt(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android snapshot helper returned an error`}function $t(e,t){if(e.length===0)throw new n(`COMMAND_FAILED`,`Android snapshot helper did not return XML chunks`,{helper:t});let r=en(e),i=Buffer.concat(nn(tn(e,r),r)).toString(`utf8`);if(!i.includes(`<hierarchy`)||!i.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper output did not contain XML`,{xml:i});return i}function en(e){let t=e[0]?.count??e.length;if(t<1||e.length!==t||e.some(e=>e.count!==t))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{expectedChunks:t,actualChunks:e.length});return t}function tn(e,t){let r=new Map;for(let i of e){if(i.index===void 0||i.index<0||i.index>=t)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned invalid chunk index`,{chunkIndex:i.index,expectedChunks:t});if(r.has(i.index))throw new n(`COMMAND_FAILED`,`Android snapshot helper returned duplicate XML chunks`,{chunkIndex:i.index});r.set(i.index,i.payloadBase64)}return r}function nn(e,t){let r=[];for(let i=0;i<t;i+=1){let a=e.get(i);if(a===void 0)throw new n(`COMMAND_FAILED`,`Android snapshot helper returned incomplete XML chunks`,{missingChunkIndex:i,expectedChunks:t});r.push(Buffer.from(a,`base64`))}return r}function rn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:B(e.waitForIdleTimeoutMs),waitForIdleQuietMs:B(e.waitForIdleQuietMs),timeoutMs:B(e.timeoutMs),maxDepth:B(e.maxDepth),maxNodes:B(e.maxNodes),rootPresent:on(e.rootPresent),captureMode:an(e.captureMode),windowCount:B(e.windowCount),nodeCount:B(e.nodeCount),truncated:on(e.truncated),elapsedMs:B(e.elapsedMs)}}function an(e){return e===`interactive-windows`||e===`active-window`?e:void 0}const B=g,on=_;function sn(){return new Promise((e,t)=>{let n=pe.createServer();n.unref(),n.on(`error`,t),n.listen(0,`127.0.0.1`,()=>{let r=n.address();if(!r||typeof r==`string`){n.close(()=>t(Error(`Failed to allocate a local TCP port`)));return}let i=r.port;n.close(()=>e(i))})})}function V(e,t,r,i){return new Promise((a,o)=>{let s=pe.connect({host:`127.0.0.1`,port:e}),c=[],l=setTimeout(()=>{u(),s.destroy(),o(new n(`COMMAND_FAILED`,`Android snapshot helper session request timed out`,{command:t,timeoutMs:r,port:e}))},r),u=()=>{clearTimeout(l),i?.removeEventListener(`abort`,d)},d=()=>{u(),s.destroy(),o(i?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(i?.addEventListener(`abort`,d,{once:!0}),i?.aborted){d();return}s.on(`connect`,()=>s.write(`${t}\n`)),s.on(`data`,e=>c.push(Buffer.from(e))),s.on(`error`,e=>{u(),o(e)}),s.on(`close`,()=>{u(),a(Buffer.concat(c).toString(`utf8`))})})}async function cn(e){let t=`snapshot-${Date.now()}-${Math.random().toString(16).slice(2)}`;return mn(await V(e.port,`snapshot ${t}`,ln(e),e.signal),t)}function ln(e){return Math.min(e.commandTimeoutMs,Math.max(e.timeoutMs+3e3,3e3))}function un(e,t,r){return new Promise((i,a)=>{let o=``,s=setTimeout(()=>{r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session did not become ready`,{output:o,timeoutMs:t}))},t),c=e=>{o+=e.toString(),o.includes(`agentDeviceProtocol=android-snapshot-helper-v1`)&&o.includes(`sessionReady=true`)&&(clearTimeout(s),r?.removeEventListener(`abort`,l),i())},l=()=>{clearTimeout(s),a(r?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r?.addEventListener(`abort`,l,{once:!0}),r?.aborted){l();return}e.stdout?.on(`data`,c),e.stderr?.on(`data`,c),e.once(`exit`,(e,t)=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(new n(`COMMAND_FAILED`,`Android snapshot helper session exited before ready`,{output:o,exitCode:e,signal:t}))}),e.on(`error`,e=>{clearTimeout(s),r?.removeEventListener(`abort`,l),a(e)})})}function dn(e){let t=e.indexOf(`
3
+
4
+ `);return _n(e.slice(0,t<0?e.length:t))}function fn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android automation helper session returned wrong protocol`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android automation helper session returned stale output`,{headers:e,requestId:t})}function pn(e,t){let n=dn(e);return n.agentDeviceProtocol===`android-snapshot-helper-v1`&&n.requestId===t&&n.ok===`true`}function mn(e,t){let r=e.indexOf(`
5
+
6
+ `);if(r<0)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned malformed output`,{response:e});let i=_n(e.slice(0,r)),a=e.slice(r+2);return hn(i,t),gn(i,a),{xml:a,metadata:vn(i)}}function hn(e,t){if(e.agentDeviceProtocol!==`android-snapshot-helper-v1`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong protocol`,{headers:e});if(e.outputFormat!==`uiautomator-xml`)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned wrong output format`,{headers:e});if(e.requestId!==t)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned stale output`,{headers:e,requestId:t});if(e.ok!==`true`)throw new n(`COMMAND_FAILED`,e.message||e.errorType||`Android snapshot helper session returned an error`,{helper:e})}function gn(e,t){let r=g(e.byteLength);if(r!==void 0&&Buffer.byteLength(t,`utf8`)!==r)throw new n(`COMMAND_FAILED`,`Android snapshot helper session returned truncated XML`,{headers:e,actualByteLength:Buffer.byteLength(t,`utf8`)});if(!t.includes(`<hierarchy`)||!t.includes(`</hierarchy>`))throw new n(`COMMAND_FAILED`,`Android snapshot helper session did not return XML`,{headers:e,xml:t})}function _n(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.indexOf(`=`);e<0||(t[n.slice(0,e)]=n.slice(e+1))}return t}function vn(e){return{helperApiVersion:e.helperApiVersion,outputFormat:O,waitForIdleTimeoutMs:g(e.waitForIdleTimeoutMs),waitForIdleQuietMs:g(e.waitForIdleQuietMs),timeoutMs:g(e.timeoutMs),maxDepth:g(e.maxDepth),maxNodes:g(e.maxNodes),rootPresent:_(e.rootPresent),captureMode:e.captureMode===`interactive-windows`||e.captureMode===`active-window`?e.captureMode:void 0,windowCount:g(e.windowCount),nodeCount:g(e.nodeCount),truncated:_(e.truncated),elapsedMs:g(e.elapsedMs)}}const yn=5e3,H=new Map,U=new Map;async function bn(e){let t=e.deviceKey??`android:default`;if(await F({deviceKey:t,adb:e.adb,signal:e.signal}),!Mn()||!e.adbProvider?.spawn)return;let n=Cn(R(e)),r=await xn({deviceKey:t,identity:jn(t,n,e),options:e,resolved:n});if(r)return await Sn({session:r,deviceKey:t,options:e,resolved:n})}async function xn(e){let{deviceKey:t,identity:n,options:r,resolved:i}=e;if(U.get(t)===n)return;let a=H.get(t);if(a&&a.identity!==n&&(await G(t),a=void 0),!a)try{a=await An({deviceKey:t,identity:n,options:r,resolved:i})}catch(e){if(r.signal?.throwIfAborted(),U.set(t,n),p({level:`warn`,phase:`android_snapshot_helper_session_disabled`,data:{deviceKey:t,reason:e instanceof Error?e.message:String(e)}}),Mt(e))throw e;return}return a}async function Sn(e){let{session:t,deviceKey:n,options:r,resolved:i}=e;try{let e=t.capturedCount>0,n=await cn({port:t.port,timeoutMs:i.timeoutMs,commandTimeoutMs:i.commandTimeoutMs,signal:r.signal});return t.capturedCount+=1,{xml:n.xml,metadata:{...n.metadata,transport:`persistent-session`,sessionReused:e}}}catch(e){await G(n,{force:!0,signal:r.signal,cause:e}),r.signal?.throwIfAborted(),p({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{deviceKey:n,reason:e instanceof Error?e.message:String(e),uiAutomationConnectionTimeout:wn(e)}});return}}function Cn(e){let t=Math.min(e.timeoutMs,2e3);return{...e,timeoutMs:t,commandTimeoutMs:Math.min(e.commandTimeoutMs,t+3e3)}}function wn(e){if(!(e instanceof n))return!1;let t=e.details?.helper;return!t||typeof t!=`object`?!1:t.errorType===`java.util.concurrent.TimeoutException`}async function Tn(e){let t=H.get(e.deviceKey);if(!t)return;if(!En(t.helper,e.helper)){p({level:`warn`,phase:`android_snapshot_helper_session_touch_identity_mismatch`,data:{deviceKey:e.deviceKey,sessionHelper:t.helper,requestedHelper:e.helper}}),await G(e.deviceKey);return}let r=`${e.action}-${Date.now()}-${Math.random().toString(16).slice(2)}`,i=e.payloadBase64?`${e.action} ${r} ${e.payloadBase64}`:`${e.action} ${r}`,a;try{a=dn(await V(t.port,i,e.timeoutMs)),fn(a,r)}catch(t){throw await G(e.deviceKey),t}if(a.ok!==`true`)throw new n(`COMMAND_FAILED`,a.message||a.errorType||`Android automation helper ${e.action} failed`,{errorType:a.errorType,helper:a});return a}function En(e,t){return e.packageName===t.packageName&&e.runner===t.runner&&W(e.helperVersion,t.helperVersion)&&W(e.helperVersionCode,t.helperVersionCode)&&W(e.sha256,t.sha256)}function W(e,t){return e===void 0||t===void 0||e===t}async function G(e,t={}){let n=H.get(e);if(!n)return!1;H.delete(e);let r=Pt(n.process),i=t.force===!0||t.signal?.aborted===!0,a=await Dn(n,r,i,t.signal),o=i?t.signal?.aborted===!0?250:kt:yn,s=i?250:2e3,[c,l]=await Promise.all([Ft({process:n.process,processExit:r,alreadyExited:a.exited,timeoutMs:s}),Nt({adb:n.adb,process:n.process,port:n.port,packageName:n.helper.packageName,timeoutMs:o})]);return p({phase:`android_snapshot_helper_session_stop`,data:{deviceKey:e,port:n.port,capturedCount:n.capturedCount,lifetimeMs:Date.now()-n.startedAtMs,quitAcknowledged:a.acknowledged,forceKilled:!a.exited&&c,forced:i||t.signal?.aborted===!0,runtimeForceStopped:l.runtimeForceStopped,externalCleanupTimedOut:l.timedOut}}),!a.exited&&!l.runtimeForceStopped&&I({deviceKey:e,packageName:n.helper.packageName,cause:t.cause}),!0}async function Dn(e,t,n,r){if(n)return{acknowledged:!1,exited:!1};let i=`quit-${Date.now()}`;try{let n=pn(await V(e.port,`quit ${i}`,1e3,r),i);return{acknowledged:n,exited:n&&await L(t,11e3,r)}}catch{return{acknowledged:!1,exited:!1}}}async function On(e){await G(P(e))}async function kn(){let e=await Promise.allSettled([...H.keys()].map(e=>G(e)));U.clear();let t=e.filter(e=>e.status===`rejected`).map(e=>e.reason);if(t.length>0)throw AggregateError(t,`Failed to retire every Android snapshot helper session`);It()}async function An(e){let t=await sn();await e.options.adb([`forward`,`tcp:${t}`,`tcp:${t}`],{allowFailure:!1,timeoutMs:yn,signal:e.options.signal});let r=Bt({...e.resolved,outputPath:void 0,emitChunks:!1}),i=r[r.length-1];if(!i)throw new n(`INVALID_ARGS`,`Android snapshot helper runner was not resolved`);let a=[...r.slice(0,-1),`-e`,`sessionPort`,String(t),i],o=e.options.adbProvider.spawn(a,{allowFailure:!0,captureOutput:!1}),s={identity:e.identity,deviceKey:e.deviceKey,helper:{packageName:e.resolved.packageName,runner:e.resolved.runner,helperVersion:e.options.helperVersion,helperVersionCode:e.options.helperVersionCode,sha256:e.options.helperSha256},port:t,adb:e.options.adb,process:o,startedAtMs:Date.now(),capturedCount:0};try{return await un(o,1e4,e.options.signal),H.set(e.deviceKey,s),p({phase:`android_snapshot_helper_session_ready`,data:{deviceKey:e.deviceKey,port:t,packageName:e.resolved.packageName,runner:e.resolved.runner}}),s}catch(t){let n=Pt(o);try{o.kill(`SIGTERM`)}catch{}let[,r]=await Promise.all([L(n,250),Nt({adb:s.adb,process:s.process,port:s.port,packageName:s.helper.packageName,timeoutMs:kt})]);throw r.runtimeForceStopped||I({deviceKey:e.deviceKey,packageName:s.helper.packageName,cause:t}),t}}function jn(e,t,n){return JSON.stringify({deviceKey:e,packageName:t.packageName,runner:t.runner,helperVersion:n.helperVersion,helperVersionCode:n.helperVersionCode,helperSha256:n.helperSha256,waitForIdleTimeoutMs:t.waitForIdleTimeoutMs,waitForIdleQuietMs:t.waitForIdleQuietMs,timeoutMs:t.timeoutMs,maxDepth:t.maxDepth,maxNodes:t.maxNodes})}function Mn(){let e=process.env.AGENT_DEVICE_ANDROID_SNAPSHOT_HELPER_SESSION;return e===void 0||!/^(0|false|no|off)$/i.test(e)}const K=new Map;function Nn(e){let t=`${e.deviceKey}\0${e.packageName}\0${e.versionCode}\0`;for(let e of K.keys())e.startsWith(t)&&q(e)}function Pn(e,t,n,r){return e?`${e}\0${t}\0${n}\0${r}`:void 0}function Fn(e,t){if(!e)return;let[n,r]=e.split(`\0`),i=`${n}\0${r}\0`;for(let t of K.keys())t!==e&&t.startsWith(i)&&K.delete(t);K.set(e,t)}function q(e){e&&K.delete(e)}async function In(e){let{adb:t,artifact:n}=e,r=e.installPolicy??`missing-or-outdated`,i=n.manifest.packageName,a=n.manifest.versionCode,o=n.manifest.sha256;if(r===`never`)return{packageName:i,versionCode:a,installed:!1,reason:`skipped`};let s=Pn(e.deviceKey,i,a,o),c=s?K.get(s):void 0;if(s&&r!==`always`&&c!==void 0)return{packageName:i,versionCode:a,installedVersionCode:c,installedSha256:o,installed:!1,reason:`current`};await le(n.apkPath,o,`Android snapshot helper`);let l=r===`always`?{installedVersionCode:await zn(t,i,e.timeoutMs,e.signal),reason:`forced`}:await fe({adb:t,adbProvider:Rn(e.adbProvider,t),packageName:i,versionCode:a,sha256:o,signal:e.signal}),{installedVersionCode:u}=l,d=`installedSha256`in l?l.installedSha256:void 0,f=l.reason;if(f===`current`){if(u===void 0)throw Error(`Expected installed versionCode for current Android snapshot helper`);return Fn(s,u),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!1,reason:f}}let p;try{p=await Bn(t,e.adbProvider??t,n.apkPath,bt(n.manifest),{packageName:i,timeoutMs:e.timeoutMs,signal:e.signal})}catch(e){throw q(s),Ln(e,{packageName:i,versionCode:a})}if(p.exitCode!==0)throw q(s),Ln(ne(`Failed to install Android snapshot helper`,p,{packageName:i,versionCode:a}));return Fn(s,a),{packageName:i,versionCode:a,installedVersionCode:u,installedSha256:d,installed:!0,reason:f}}function Ln(e,t){let n=a(e,`COMMAND_FAILED`);return n.details={...t,...n.details,androidSnapshotHelperInstallFailure:!0},n}function Rn(e,t){return e?typeof e==`function`?{exec:e}:e:{exec:t}}async function zn(e,t,n,r){let i=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:n,signal:r});if(i.exitCode===0)return Vn(`${i.stdout}\n${i.stderr}`,t)}async function Bn(e,t,n,r,i){let a=async()=>await te(n,{allowFailure:!0,provider:t,...r,timeoutMs:i.timeoutMs,signal:i.signal}),o=await a();if(o.exitCode===0||!Hn(o))return o;let s=await e([`uninstall`,i.packageName],{allowFailure:!0,timeoutMs:i.timeoutMs,signal:i.signal}),c=await a();return c.exitCode===0?c:{...c,stderr:[c.stderr,s.stderr?`Previous uninstall stderr after INSTALL_FAILED_UPDATE_INCOMPATIBLE: ${s.stderr}`:``].filter(Boolean).join(`
7
+ `)}}function Vn(e,t){let n=`package:${t}`;for(let t of e.split(/\r?\n/)){if(!t.startsWith(n)||t.length>n.length&&!/\s/.test(t[n.length]??``))continue;let e=/(?:^|\s)versionCode:(\d+)(?:\s|$)/.exec(t);if(e)return Number(e[1])}}function Hn(e){return`${e.stdout}\n${e.stderr}`.includes(`INSTALL_FAILED_UPDATE_INCOMPATIBLE`)}const Un=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.google.android.packageinstaller`,`com.android.packageinstaller`]);function Wn(e){return Un.has(e)}const Gn=new Set([`android`,`com.android.systemui`]),Kn=/^android:id\/(?:alertTitle|message|button[123]|parentPanel|buttonPanel|contentPanel)$/i,J=/^android:id\/button[123]$/i,qn=/(?:^|:)id\/permission_/i,Jn=/\b(?:is(?:n't| not) responding|keeps stopping|has stopped|close app|app info)\b/i,Yn=/^(?:ok|allow|allow all|while using the app|only this time|yes|continue|save|confirm|turn on|open settings)$/i,Xn=/^(?:cancel|deny|don.t allow|don’t allow|not now|no|dismiss|close|close app|later|skip)$/i;function Zn(e){if(e!==null){if(J.test(e))return`button`;if(Kn.test(e))return`content`}}function Qn(e){let t=er(e),n=t.nodes;if(n.length===0)return null;let r=ar(n),i=n.filter(e=>Y(e)&&!hr(e)),a=cr(i),o=lr(i,a),s=gr(n);return{alert:{...a?{title:a}:{},...o?{message:o}:{},buttons:r.map(e=>e.label),platform:`android`,source:t.source,...s?{packageName:s}:{}},buttons:r}}function $n(e,t){let n=t===`accept`?`accept`:`dismiss`;return e.find(e=>e.role===n)||(t===`dismiss`?e.find(e=>e.role===`neutral`)??null:e.length===1?e[0]??null:null)}function er(e){let t=e.filter(e=>pr(e));if(t.length)return{nodes:t,source:`permission`};let n=ir(e);return n.length?{nodes:n,source:`system-dialog`}:{nodes:tr(e),source:`native-dialog`}}function tr(e){let t=e.filter(e=>nr(e.type??``)),n=e.filter(e=>Kn.test(e.identifier??``)),r=t.length?[...t,...n]:rr(n);if(r.length===0)return[];let i=ur(e,r);return i===void 0?r:fr(e,i)}function nr(e){return/(?:^|[.$])[^.]*Dialog$/i.test(e)}function rr(e){let t=e.some(e=>J.test(e.identifier??``)),n=e.some(e=>!J.test(e.identifier??``));return t&&n?e:[]}function ir(e){let t=e.filter(e=>mr(e));if(t.length===0)return[];let n=ur(e,t);return n===void 0?t:fr(e,n).filter(e=>e.bundleId&&Gn.has(e.bundleId))}function ar(e){let t=new Set,n=[];for(let r of e){let e=Y(r);if(!e||!r.rect||!hr(r))continue;let a=e.trim().toLowerCase();if(!a||t.has(a))continue;t.add(a);let o=i(r.rect);n.push({label:e,x:o.x,y:o.y,role:or(r,e)})}return n}function or(e,t){return sr(e.identifier??``)||(Yn.test(t.trim())?`accept`:Xn.test(t.trim())?`dismiss`:`neutral`)}function sr(e){return/(?:^|:)id\/button1$/i.test(e)?`accept`:/(?:^|:)id\/button2$/i.test(e)?`dismiss`:/(?:^|:)id\/button3$/i.test(e)?`neutral`:/(?:^|:)id\/permission_allow/i.test(e)?`accept`:/(?:^|:)id\/permission_deny/i.test(e)?`dismiss`:null}function cr(e){return Y(e.find(e=>/(?:^|:)id\/(?:alertTitle|permission_message)$/i.test(e.identifier??``)))||Y(e[0])}function lr(e,t){let n=e.map(e=>Y(e)).filter(e=>e&&e!==t);return n.length?[...new Set(n)].join(`
8
+ `):void 0}function ur(e,t){let n=t[0];if(!n)return;let r=dr(e,n.index);for(let n of t.slice(1)){let t=new Set(dr(e,n.index));for(let e=r.length-1;e>=0;--e)t.has(r[e])||r.splice(e,1)}return r[r.length-1]}function dr(e,t){let n=new Map(e.map(e=>[e.index,e])),r=[],i=n.get(t);for(;i;)r.push(i.index),i=i.parentIndex===void 0?void 0:n.get(i.parentIndex);return r.reverse()}function fr(e,t){let n=new Map;for(let t of e){if(t.parentIndex===void 0)continue;let e=n.get(t.parentIndex)??[];e.push(t),n.set(t.parentIndex,e)}let r=new Set([t]),i=[t];for(let e of i)for(let t of n.get(e)??[])r.has(t.index)||(r.add(t.index),i.push(t.index));return e.filter(e=>r.has(e.index))}function pr(e){let t=e.bundleId??``;return Un.has(t)||qn.test(e.identifier??``)}function mr(e){let t=e.bundleId??``;return Gn.has(t)&&Jn.test(Y(e))}function hr(e){let t=e.type??``,n=e.identifier??``;return!!(e.hittable||/\bbutton\b/i.test(t)||J.test(n)||/(?:^|:)id\/permission_(?:allow|deny)/i.test(n))}function Y(e){return e?[e.label,e.value].filter(e=>typeof e==`string`&&e.trim().length>0)[0]?.trim()??``:``}function gr(e){return e.find(e=>e.bundleId)?.bundleId}const _r=new Set([`android`,`com.android.systemui`]);function vr(e,t,n={}){if(t.backend!==`android-helper`)return{outcome:`ok`};let r=Or(e,n.foregroundAppPackage);return br(r,t)?X(r,t,`empty-helper-output`,`Android snapshot helper returned no accessibility nodes`):Er(r)?{outcome:`ok`}:yr(r)?{outcome:`system-surface-only`}:xr(r)?{outcome:`ok`}:Sr(r)?X(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient foreground app content`):Cr(r)||wr(r,t)?X(r,t,`content-poor-app-window`,`Android snapshot helper returned insufficient application window content`):Tr(r)?X(r,t,`system-window-only`,`Android snapshot helper returned only non-application windows`):{outcome:`ok`}}function X(e,t,n,r){return{outcome:`unusable`,decision:Dr(e,t,n,r)}}function yr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0&&e.activeSystemSurfaceMeaningfulNodeCount>=3}function br(e,t){return e.nodeCount===0||t.nodeCount===0||t.rootPresent===!1}function xr(e){return Sr(e)&&e.inputMethodMeaningfulNodeCount>=2}function Sr(e){let t=e.foregroundAppMeaningfulNodeCount;return t===void 0?!1:t===0?e.applicationMeaningfulNodeCount<2:t<2&&e.meaningfulNodeCount>t}function Cr(e){return e.foregroundAppMeaningfulNodeCount===void 0&&e.applicationWindowRootCount>0&&e.applicationMeaningfulNodeCount<2}function wr(e,t){return e.foregroundAppMeaningfulNodeCount===void 0&&e.windowRootCount===0&&(t.windowCount??0)>1&&e.nonSystemMeaningfulNodeCount<2}function Tr(e){return e.windowRootCount>0&&e.applicationWindowRootCount===0||e.windowRootCount===0&&e.nodeCount>0&&e.systemUiNodeCount===e.nodeCount}function Er(e){return e.hasAlertButtonIdentifier&&e.hasAlertContentIdentifier}function Dr(e,t,n,r){return{reason:n,failureReason:r,diagnostics:Vr(e,t)}}function Or(e,t){let n=kr(t);for(let t of ye(e))Ar(n,t);return Lr(n)}function kr(e){return{nodeCount:0,systemUiNodeCount:0,windowRootCount:0,applicationWindowRootCount:0,activeSystemSurfaceMeaningfulNodeCount:0,meaningfulNodeCount:0,applicationMeaningfulNodeCount:0,nonSystemMeaningfulNodeCount:0,inputMethodMeaningfulNodeCount:0,hasAlertButtonIdentifier:!1,hasAlertContentIdentifier:!1,...e===void 0?{}:{foregroundAppPackage:e,foregroundAppMeaningfulNodeCount:0},windowTypes:new Set}}function Ar(e,t){e.nodeCount+=1,Br(t.packageName)&&(e.systemUiNodeCount+=1),t.visibleToUser!==!1&&jr(e,t.resourceId),Mr(e,t),Nr(e,t)}function jr(e,t){let n=Zn(t);n===`button`&&(e.hasAlertButtonIdentifier=!0),n===`content`&&(e.hasAlertContentIdentifier=!0)}function Mr(e,t){t.windowType!==void 0&&(e.currentWindowType=t.windowType,e.currentWindowActiveOrFocused=t.windowActive===!0||t.windowFocused===!0,e.windowRootCount+=1,e.windowTypes.add(t.windowType),t.windowType===1&&(e.applicationWindowRootCount+=1))}function Nr(e,t){Rr(t)&&(e.meaningfulNodeCount+=1,Pr(e,t),Ir(e,t))}function Pr(e,t){e.currentWindowType===1&&!zr(t.packageName)&&(e.applicationMeaningfulNodeCount+=1),Fr(e)&&!o(t)&&(e.activeSystemSurfaceMeaningfulNodeCount+=1)}function Fr(e){return e.currentWindowType!==void 0&&e.currentWindowType!==1&&e.currentWindowActiveOrFocused===!0}function Ir(e,t){zr(t.packageName)||(e.nonSystemMeaningfulNodeCount+=1),l({packageName:t.packageName,resourceId:t.resourceId})&&(e.inputMethodMeaningfulNodeCount+=1),e.foregroundAppPackage!==void 0&&t.packageName===e.foregroundAppPackage&&(e.foregroundAppMeaningfulNodeCount=(e.foregroundAppMeaningfulNodeCount??0)+1)}function Lr(e){return{nodeCount:e.nodeCount,systemUiNodeCount:e.systemUiNodeCount,windowRootCount:e.windowRootCount,applicationWindowRootCount:e.applicationWindowRootCount,activeSystemSurfaceMeaningfulNodeCount:e.activeSystemSurfaceMeaningfulNodeCount,meaningfulNodeCount:e.meaningfulNodeCount,applicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,nonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,inputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,hasAlertButtonIdentifier:e.hasAlertButtonIdentifier,hasAlertContentIdentifier:e.hasAlertContentIdentifier,...e.foregroundAppPackage===void 0?{}:{foregroundAppPackage:e.foregroundAppPackage,foregroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount??0},windowTypes:[...e.windowTypes].sort((e,t)=>e-t).slice(0,8)}}function Rr(e){return e.visibleToUser===!1?!1:Z(e.text)||Z(e.desc)||Z(e.resourceId)}function Z(e){return e!==null&&e.trim()!==``}function zr(e){return e===null||_r.has(e)}function Br(e){return e!==null&&_r.has(e)}function Vr(e,t){return{helperNodeCount:e.nodeCount,helperSystemUiNodeCount:e.systemUiNodeCount,helperWindowRootCount:e.windowRootCount,helperApplicationWindowRootCount:e.applicationWindowRootCount,helperMeaningfulNodeCount:e.meaningfulNodeCount,helperApplicationMeaningfulNodeCount:e.applicationMeaningfulNodeCount,helperNonSystemMeaningfulNodeCount:e.nonSystemMeaningfulNodeCount,helperInputMethodMeaningfulNodeCount:e.inputMethodMeaningfulNodeCount,...e.foregroundAppPackage===void 0?{}:{helperForegroundAppPackage:e.foregroundAppPackage,helperForegroundAppMeaningfulNodeCount:e.foregroundAppMeaningfulNodeCount,helperForegroundAppMeaningfulNodeThreshold:2},helperWindowTypes:e.windowTypes,...t.captureMode?{helperCaptureMode:t.captureMode}:{}}}async function Hr(e){let t=await G(e.deviceKey,{signal:e.signal,cause:e.cause});e.signal?.throwIfAborted(),t||await Q(e.adb,e.packageName)}async function Q(e,n){try{await e([`shell`,`am`,`force-stop`,n],{allowFailure:!0,timeoutMs:2e3}),await ae(150),p({level:`debug`,phase:`android_snapshot_helper_runtime_reset`,data:{packageName:n}})}catch(e){p({level:`warn`,phase:`android_snapshot_helper_runtime_reset_failed`,data:{packageName:n,error:t(e).message}})}}const $=5e3,Ur=3e4;async function Wr(e,t={}){let n=h(e,t.helperAdb).exec;return(await Zr(e,t,n)).xml}async function Gr(e,t={}){let n=h(e,t.helperAdb).exec,r=await Zr(e,t,n),i=r.xml,a=Fe(i),o=xe(a,void 0,t),s=Jr(o.truncated,r.metadata);t.interactiveOnly&&t.includeHiddenContentHints!==!1&&Xr({options:t,tree:a,xml:i,interactiveSnapshot:o});let{sourceNodes:c,...l}=o;return{...l,...Yr(s),androidSnapshot:Kr(r.metadata,a)}}function Kr(e,t){return qr(t)===!1?{...e,occlusionScanUnavailable:!0}:e}function qr(e){let t=[...e.children];if(t.length!==0){for(;t.length>0;){let e=t.pop();if(e.drawingOrder!==void 0)return!0;t.push(...e.children)}return!1}}function Jr(e,t){return e===!0||t.helperTruncated===!0?!0:e}function Yr(e){return e===!0?{truncated:!0}:{}}function Xr(e){if(gi(e.interactiveSnapshot.nodes).size>0||hi(e.xml))return;let t=xe(e.tree,void 0,{...e.options,interactiveOnly:!1});_i(f(r(t.nodes)),t,e.interactiveSnapshot)}async function Zr(e,t,n){let r=h(e,t.helperAdb),i=await m(`android_snapshot_helper_artifact_resolution`,async()=>await pi(t.helperArtifact??r.snapshotHelperArtifact));if(i.artifact)return await Qr(e,t,n,i.artifact);throw p({level:`error`,phase:`android_snapshot_helper_unavailable`,data:{reason:i.errorReason??`artifact_not_found`}}),mi(i.errorReason)}async function Qr(e,t,n,r){let i=P(e),a=h(e,t.helperAdb),o=t.helperSessionScope!==`daemon-session`;try{let e;for(let o=0;;o+=1){o>0&&await ri(t.signal);let s=await ni({options:t,adb:n,adbProvider:a,artifact:r,helperDeviceKey:i,attempt:o,previousContentReason:e});if(s.outcome===`captured`)return s.capture;if(o+1>=3)return await ii({contentRecovery:s.decision,attempts:o+1,helperDeviceKey:i,artifact:r,adb:n,signal:t.signal});e=s.decision.reason}}finally{o&&await G(i)}}async function $r(e,t,n,r,i){let a=await m(`android_snapshot_helper_install`,async()=>await In({adb:t,adbProvider:n,artifact:r,deviceKey:i,installPolicy:e.helperInstallPolicy,timeoutMs:3e4,signal:e.signal}),{packageName:r.manifest.packageName,versionCode:r.manifest.versionCode,installPolicy:e.helperInstallPolicy??`missing-or-outdated`});return p({phase:`android_snapshot_helper_install_decision`,data:{packageName:a.packageName,versionCode:a.versionCode,installedVersionCode:a.installedVersionCode,artifactSha256:r.manifest.sha256,installedSha256:a.installedSha256,installed:a.installed,reason:a.reason}}),a}async function ei(e){let{signal:n,adb:r,adbProvider:i,artifact:a,helperDeviceKey:o}=e,s={adb:r,adbProvider:i,deviceKey:o,helperVersion:a.manifest.version,helperVersionCode:a.manifest.versionCode,helperSha256:a.manifest.sha256,packageName:a.manifest.packageName,instrumentationRunner:a.manifest.instrumentationRunner,waitForIdleTimeoutMs:500,timeoutMs:$,commandTimeoutMs:Ur,signal:n};try{let e=await m(`android_snapshot_helper_session_capture`,async()=>await bn(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$});if(e)return e}catch(e){if(n?.throwIfAborted(),Mt(e))throw e;p({level:`warn`,phase:`android_snapshot_helper_session_fallback`,data:{reason:t(e).message}}),await Q(r,a.manifest.packageName)}return await m(`android_snapshot_helper_capture`,async()=>await zt(s),{packageName:a.manifest.packageName,version:a.manifest.version,timeoutMs:$,commandTimeoutMs:Ur})}function ti(e,t,n){return{xml:e.xml,metadata:{backend:`android-helper`,helperVersion:t.manifest.version,helperApiVersion:e.metadata.helperApiVersion,helperTransport:e.metadata.transport,helperSessionReused:e.metadata.sessionReused,installReason:n,waitForIdleTimeoutMs:e.metadata.waitForIdleTimeoutMs,waitForIdleQuietMs:e.metadata.waitForIdleQuietMs,timeoutMs:e.metadata.timeoutMs,maxDepth:e.metadata.maxDepth,maxNodes:e.metadata.maxNodes,rootPresent:e.metadata.rootPresent,captureMode:e.metadata.captureMode,windowCount:e.metadata.windowCount,nodeCount:e.metadata.nodeCount,helperTruncated:e.metadata.truncated,elapsedMs:e.metadata.elapsedMs}}}async function ni(e){let{options:t,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a,attempt:o}=e,s;try{let e=await $r(t,n,r,i,a);e.installed&&await G(a),s=ti(await ei({signal:t.signal,adb:n,adbProvider:r,artifact:i,helperDeviceKey:a}),i,e.reason)}catch(e){return t.signal?.throwIfAborted(),{outcome:`captured`,capture:await ai({error:e,helperDeviceKey:a,artifact:i,adb:n})}}let c=vr(s.xml,s.metadata,{foregroundAppPackage:t.appBundleId});return c.outcome===`system-surface-only`?(p({phase:`android_snapshot_helper_system_surface`,data:{foregroundAppPackage:t.appBundleId}}),{outcome:`captured`,capture:{xml:s.xml,metadata:{...s.metadata,systemSurfaceOnly:!0}}}):c.outcome===`ok`?(o>0&&p({phase:`android_snapshot_helper_content_recaptured`,data:{attempts:o+1,recoveredFromReason:e.previousContentReason}}),{outcome:`captured`,capture:s}):{outcome:`unusable`,decision:c.decision}}async function ri(e){e?.throwIfAborted(),await ae(250),e?.throwIfAborted()}async function ii(e){throw p({level:`error`,phase:`android_snapshot_helper_content_invalid`,data:{reason:e.contentRecovery.reason,failureReason:e.contentRecovery.failureReason,attempts:e.attempts,...e.contentRecovery.diagnostics}}),await Hr({adb:e.adb,deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,signal:e.signal,cause:e.contentRecovery.failureReason}),new n(`COMMAND_FAILED`,e.contentRecovery.failureReason,{...e.contentRecovery.diagnostics,androidSnapshotHelperFailureReason:e.contentRecovery.reason,attempts:e.attempts,retriable:!0,hint:`Retry after the app UI stabilizes. If this persists, capture a screenshot and report the helper diagnostics; agent-device does not substitute a second snapshot engine.`})}async function ai(e){let t=oi(e.error);throw p({level:`error`,phase:`android_snapshot_helper_failed`,data:{reason:t}}),await G(e.helperDeviceKey),await Q(e.adb,e.artifact.manifest.packageName),Nn({deviceKey:e.helperDeviceKey,packageName:e.artifact.manifest.packageName,versionCode:e.artifact.manifest.versionCode}),si(e.error,t)}function oi(e){let n=t(e),r=di(n.details?.helper);if(r&&r!==n.message)return`${n.message}: ${r}`;if(r)return r;let i=(typeof n.details?.stderr==`string`?n.details.stderr.trim():``).split(/\r?\n/).find(e=>e.trim());return i?`${n.message}: ${i}`:n.message}function si(r,i){let a=t(r);return new n(e(a.code),`Android snapshot helper failed: ${i}`,{...a.details,...li(a),androidSnapshotHelperFailureReason:i,hint:ci(a)},r)}function ci(e){return fi(e.details?.helper,e.message)||ui(e)?`Android accessibility snapshots can be blocked by busy or continuously changing app UI. Use screenshot as visual truth after this timeout and report the busy UI if it persists.`:e.details?.androidSnapshotHelperInstallFailure===!0?[e.hint,`This is a device-side install failure (adb rejection or OEM policy) — the helper artifact itself is present, this is not a missing/unbuilt build.`].filter(Boolean).join(` `):e.hint??`Retry once. If the helper still fails, run agent-device doctor and report the diagnostic log; agent-device does not substitute a second snapshot engine.`}function li(e){let t={};return e.diagnosticId!==void 0&&(t.diagnosticId=e.diagnosticId),e.logPath!==void 0&&(t.logPath=e.logPath),e.retriable!==void 0&&(t.retriable=e.retriable),e.supportedOn!==void 0&&(t.supportedOn=e.supportedOn),t}function ui(e){return e.details?.exitCode===137?/Android snapshot helper (failed before returning parseable output|output could not be parsed)/.test(e.message):!1}function di(e){if(!e||typeof e!=`object`||!(`message`in e))return;let t=String(e.message).trim();return t&&t!==`null`?t:void 0}function fi(e,t){if(!e||typeof e!=`object`)return!1;let n=`errorType`in e?String(e.errorType):``,r=di(e)??t;return/TimeoutException/.test(n)||/timed out/i.test(r)}async function pi(e){if(e)return{artifact:e};let n=re(),r=v.join(ie(),`android`,`snapshot-helper`,`dist`),i=v.join(r,`agent-device-android-snapshot-helper-${n}.manifest.json`);try{await y.access(i)}catch{return{}}try{let e=yt(JSON.parse(await y.readFile(i,`utf8`))),t=v.join(r,e.assetName??`agent-device-android-snapshot-helper-${e.version}.apk`);return await y.access(t),{artifact:{apkPath:t,manifest:e}}}catch(e){return{errorReason:t(e).message}}}function mi(e){let t=e??`the bundled helper artifact was not found`;return new n(`COMMAND_FAILED`,`Android snapshot helper is unavailable: ${t}`,{androidSnapshotHelperFailureReason:t,hint:"Run `pnpm build:android` to build the helper dist for a source checkout — the runtime needs android/snapshot-helper/dist/agent-device-android-snapshot-helper-<version>.manifest.json and the .apk it references. Packaged installs ship these via the prepack script; if they are missing from a packaged install, reinstall agent-device."})}function hi(e){return e.includes(` can-scroll-forward=`)||e.includes(` can-scroll-backward=`)}function gi(e){let t=new Map;for(let n of e){let e={};n.hiddenContentAbove&&(e.hiddenContentAbove=!0),n.hiddenContentBelow&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n.index,e)}return t}function _i(e,t,n){if(e.size===0)return;let r=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&r.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let a=r.get(e);a&&(i.hiddenContentAbove&&(a.hiddenContentAbove=!0),i.hiddenContentBelow&&(a.hiddenContentBelow=!0))}}export{Wn as a,Tn as c,P as d,F as f,ye as h,Qn as i,G as l,D as m,Gr as n,In as o,yt as p,$n as r,kn as s,Wr as t,On as u};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{_ as t,gt as n,h as r,ht as i,v as a}from"./version.js";import{lt as o}from"./sdk-batch-runner.js";import{c as s,l as c}from"./sdk-device.js";import{gn as l}from"./prepare-kind.js";import"./screenshot-result.js";import{I as u}from"./sdk-android-adb.js";import{t as d}from"./timeouts.js";import{l as f,n as p}from"./input-actions.js";import{f as m,m as h,p as g}from"./ime-lifecycle.js";import{c as _,o as v,t as y}from"./dispatch.js";import{i as b}from"./helper.js";import{ct as x,fn as S,tn as C,yn as w}from"./internal/daemon.js";import{i as T}from"./selector-runtime.js";import{a as E,i as D,n as O,r as k}from"./snapshot-session.js";import{n as A,t as j}from"./snapshot-runtime.js";async function M(e,t,n={}){return t===`wait`?await N(e,n.timeoutMs??1e4):t===`get`?L((await I(e))?.alert??null):await P(e,t)}async function N(t,n){let r=Date.now(),i=await F(t,n);if(!i)throw new e(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:i.alert,waitedMs:Date.now()-r,...l(`Alert visible`)}}async function P(t,n){let r=await F(t,i);if(!r)throw new e(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let a=g(r.buttons,n);if(a)return await f(t,a.x,a.y),R(n,r.alert,a.label);if(n===`dismiss`)return await p(t),R(n,r.alert,`Back`);throw new e(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:r.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function F(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await I(e);if(t)return t;await d(300)}return null}async function I(e){return h((await u(`snapshot_capture`,async()=>await m(e,{includeHiddenContentHints:!1}),{backend:`android`,purpose:`alert`})).nodes)}function L(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...l(e?`Alert visible`:`No alert visible`)}}function R(e,t,n){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:n,...l(`Alert ${e}ed`)}}async function z(e){let{req:t,logPath:n,session:r,device:i}=e,a=V(t.positionals?.[0]),s=r?r.surface===`frontmost-app`?{surface:`frontmost-app`}:{bundleId:r.appBundleId,surface:r.surface}:{},l=_(`alert`,i);if(l)return l;if(r&&w(t)===`may-invalidate`&&C(r),i.platform===`android`)return G(e,await M(i,a,{timeoutMs:o(t.positionals?.[1])??1e4}));if(c(i))return await B(e,a,async e=>await b(e,s));let u=E({req:t,logPath:n,traceLogPath:r?.trace?.outPath});return await B(e,a,async(e,t)=>await x(i,{command:`alert`,action:e,appBundleId:r?.appBundleId,timeoutMs:t},u))}async function B(e,t,r){if(t===`wait`)return await H(e,r);let i=t===`accept`||t===`dismiss`?t:`get`;return i===`accept`||i===`dismiss`?await U(e,i,r):G(e,await r(`get`,n))}function V(e){return e===`accept`||e===`dismiss`||e===`wait`?e:`get`}async function H(e,t){let n=o(e.req.positionals?.[1])??1e4,r=Date.now(),i=!0;for(;Date.now()-r<n;){try{let a=i?n:W(r,n);return i=!1,G(e,await t(`get`,a))}catch{}await d(300)}return v(`COMMAND_FAILED`,`alert wait timed out`)}async function U(e,t,r){let a=s(e.device)?n:i,o=Date.now(),c,l=!0;for(;Date.now()-o<i;){try{let n=l?a:W(o,i);return l=!1,G(e,await r(t,n))}catch(e){c=e;let t=String(e?.message??``).toLowerCase();if(!t.includes(`alert not found`)&&!t.includes(`no alert`))break}await d(300)}throw K(c)}function W(e,t){return Math.max(1,t-(Date.now()-e))}function G(e,t){let n=t;return O(e.sessionStore,e.session,e.req,n),{ok:!0,data:n}}function K(t){return!(t instanceof e)||!q(t)?t:new e(t.code,t.message,{...t.details??{},hint:`If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref.`})}function q(e){let t=String(e?.message??``).toLowerCase();return t.includes(`alert not found`)||t.includes(`no alert`)}function J(e){let t=e.positionals?.[0]?.toLowerCase(),n=e.positionals?.[1]?.toLowerCase(),i=e.positionals?.[2]?.toLowerCase();return t===`clear-app-state`?{ok:!0,parsed:{setting:t,state:`clear`,appBundleId:n===`clear`?e.positionals?.[2]:e.positionals?.[1]}}:!t||!n||t===`permission`&&!i||t===`location`&&n===`set`&&(!e.positionals?.[2]||!e.positionals?.[3])?v(`INVALID_ARGS`,r):{ok:!0,parsed:{setting:t,state:n,permissionTarget:i,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}}async function Y(e){let{req:n,logPath:r,sessionStore:i,session:o,device:s,parsed:l}=e,{setting:u,state:d,appBundleId:f,permissionTarget:p,latitude:m,longitude:h}=l,g=_(`settings`,s);if(g)return g;if(c(s)&&!a(u))return v(`INVALID_ARGS`,t(u));let b=f??o?.appBundleId;if(u===`clear-app-state`&&!b)return v(`INVALID_ARGS`,`settings clear-app-state requires an app id when no app is bound to the session`);let x=u===`clear-app-state`?[u,d,b??``]:u===`permission`?[u,d,p??``,n.positionals?.[3]??``,b??``]:u===`location`&&d===`set`?[u,d,m??``,h??``,b??``]:[u,d,b??``];o&&C(o);let w=await y(s,`settings`,x,n.flags?.out,{...S(r,n.flags,b,o?.trace?.outPath)});return O(i,o,n,w??{setting:u,state:d}),{ok:!0,data:w??{setting:u,state:d}}}const X={snapshot:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await A({req:e,sessionName:t,logPath:n,sessionStore:r}),diff:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>e.positionals?.[0]===`snapshot`?await j({req:e,sessionName:t,logPath:n,sessionStore:r}):v(`INVALID_ARGS`,`diff currently supports only: diff snapshot`),wait:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await T({req:e,sessionName:t,logPath:n,sessionStore:r}),alert:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let{session:i,device:a}=await k(r,t,e.flags);return await D(i,a,async()=>await z({req:e,logPath:n,sessionStore:r,session:i,device:a}))},settings:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let i=J(e);if(!i.ok)return i;let{session:a,device:o}=await k(r,t,e.flags);return await D(a,o,async()=>await Y({req:e,logPath:n,sessionStore:r,session:a,device:o,parsed:i.parsed}))}};async function Z(e){let t=e.req.command,n=X[t];return n?await n(e):null}export{Z as handleSnapshotCommands};
1
+ import{_ as e}from"./sdk-contracts.js";import{a as t,o as n,r}from"./location-coordinates.js";import{Qt as i}from"./sdk-batch-runner.js";import{c as a,l as o}from"./sdk-device.js";import{yn as s}from"./script-source-bundle.js";import{J as c,Y as l}from"./interaction.js";import"./screenshot-result.js";import{F as u}from"./sdk-android-adb.js";import{t as d}from"./timeouts.js";import{l as f,n as p}from"./input-actions.js";import{i as m,n as h,r as g}from"./snapshot.js";import{a as _,s as v,t as y}from"./dispatch.js";import{n as b}from"./runner-client.js";import{It as x,bt as S,jt as C}from"./internal/daemon.js";import{i as w,m as T}from"./selector-runtime.js";import{i as E,n as D,r as O}from"./snapshot-session.js";import{r as k}from"./helper.js";import{n as A,t as j}from"./snapshot-runtime.js";async function M(e,t,n={}){return t===`wait`?await N(e,n.timeoutMs??1e4):t===`get`?L((await I(e))?.alert??null):await P(e,t)}async function N(t,n){let r=Date.now(),i=await F(t,n);if(!i)throw new e(`COMMAND_FAILED`,`alert wait timed out`);return{kind:`alertWait`,platform:`android`,action:`wait`,alert:i.alert,waitedMs:Date.now()-r,...s(`Alert visible`)}}async function P(t,n){let r=await F(t,c);if(!r)throw new e(`COMMAND_FAILED`,`alert not found`,{hint:`If a sheet is visible in snapshot but alert reports no alert, it is likely app-owned UI. Use snapshot -i and press the visible label/ref.`});let i=g(r.buttons,n);if(i)return await f(t,i.x,i.y),R(n,r.alert,i.label);if(n===`dismiss`)return await p(t),R(n,r.alert,`Back`);throw new e(`COMMAND_FAILED`,`alert accept found an alert but no accept button`,{alert:r.alert,hint:`Inspect alert get --json for visible buttons, then use press by visible label/ref if needed.`})}async function F(e,t){let n=Date.now();for(;Date.now()-n<t;){let t=await I(e);if(t)return t;await d(300)}return null}async function I(e){return m((await u(`snapshot_capture`,async()=>await h(e,{includeHiddenContentHints:!1}),{backend:`android`,purpose:`alert`})).nodes)}function L(e){return{kind:`alertStatus`,platform:`android`,action:`get`,alert:e,...s(e?`Alert visible`:`No alert visible`)}}function R(e,t,n){return{kind:`alertHandled`,platform:`android`,action:e,handled:!0,alert:t,button:n,...s(`Alert ${e}ed`)}}async function z(e){let{req:t,logPath:n,session:r,device:a}=e,s=V(t.positionals?.[0]),c=r?r.surface===`frontmost-app`?{surface:`frontmost-app`}:{bundleId:r.appBundleId,surface:r.surface}:{},l=v(`alert`,a);if(l)return l;if(r&&x(t)===`may-invalidate`&&S(r),a.platform===`android`)return G(e,await M(a,s,{timeoutMs:i(t.positionals?.[1])??1e4}));if(o(a))return await B(e,s,async e=>await k(e,c));let u=T({req:t,logPath:n,traceLogPath:r?.trace?.outPath});return await B(e,s,async(e,t)=>await b(a,{command:`alert`,action:e,appBundleId:r?.appBundleId,timeoutMs:t},u))}async function B(e,t,n){if(t===`wait`)return await H(e,n);let r=t===`accept`||t===`dismiss`?t:`get`;return r===`accept`||r===`dismiss`?await U(e,r,n):G(e,await n(`get`,l))}function V(e){return e===`accept`||e===`dismiss`||e===`wait`?e:`get`}async function H(e,t){let n=i(e.req.positionals?.[1])??1e4,r=Date.now(),a=!0;for(;Date.now()-r<n;){try{let i=a?n:W(r,n);return a=!1,G(e,await t(`get`,i))}catch{}await d(300)}return _(`COMMAND_FAILED`,`alert wait timed out`)}async function U(e,t,n){let r=a(e.device)?l:c,i=Date.now(),o,s=!0;for(;Date.now()-i<c;){try{let a=s?r:W(i,c);return s=!1,G(e,await n(t,a))}catch(e){o=e;let t=String(e?.message??``).toLowerCase();if(!t.includes(`alert not found`)&&!t.includes(`no alert`))break}await d(300)}throw K(o)}function W(e,t){return Math.max(1,t-(Date.now()-e))}function G(e,t){let n=t;return D(e.sessionStore,e.session,e.req,n),{ok:!0,data:n}}function K(t){return!(t instanceof e)||!q(t)?t:new e(t.code,t.message,{...t.details??{},hint:`If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref.`})}function q(e){let t=String(e?.message??``).toLowerCase();return t.includes(`alert not found`)||t.includes(`no alert`)}function J(e){let t=e.positionals?.[0]?.toLowerCase(),n=e.positionals?.[1]?.toLowerCase(),i=e.positionals?.[2]?.toLowerCase();return t===`clear-app-state`?{ok:!0,parsed:{setting:t,state:`clear`,appBundleId:n===`clear`?e.positionals?.[2]:e.positionals?.[1]}}:!t||!n||t===`permission`&&!i||t===`location`&&n===`set`&&(!e.positionals?.[2]||!e.positionals?.[3])?_(`INVALID_ARGS`,r):{ok:!0,parsed:{setting:t,state:n,permissionTarget:i,latitude:e.positionals?.[2],longitude:e.positionals?.[3]}}}async function Y(e){let{req:r,logPath:i,sessionStore:a,session:s,device:c,parsed:l}=e,{setting:u,state:d,appBundleId:f,permissionTarget:p,latitude:m,longitude:h}=l,g=v(`settings`,c);if(g)return g;if(o(c)&&!n(u))return _(`INVALID_ARGS`,t(u));let b=f??s?.appBundleId;if(u===`clear-app-state`&&!b)return _(`INVALID_ARGS`,`settings clear-app-state requires an app id when no app is bound to the session`);let x=u===`clear-app-state`?[u,d,b??``]:u===`permission`?[u,d,p??``,r.positionals?.[3]??``,b??``]:u===`location`&&d===`set`?[u,d,m??``,h??``,b??``]:[u,d,b??``];s&&S(s);let w=await y(c,`settings`,x,r.flags?.out,{...C(i,r.flags,b,s?.trace?.outPath)});return D(a,s,r,w??{setting:u,state:d}),{ok:!0,data:w??{setting:u,state:d}}}async function X(e){return await A({...e,command:`diff`,execute:async({runtime:e,sessionName:t,req:n,snapshotScope:r})=>{let i=await e.capture.diffSnapshot({session:t,interactiveOnly:n.flags?.snapshotInteractiveOnly,depth:n.flags?.snapshotDepth,scope:r,raw:n.flags?.snapshotRaw});return{data:i,record:{kind:`diff`,mode:`snapshot`,baselineInitialized:i.baselineInitialized,summary:i.summary}}}})}const Z={snapshot:async({req:e,sessionName:t,logPath:n,sessionStore:r,inspectFacts:i,bindDevice:a})=>await j({req:e,sessionName:t,logPath:n,sessionStore:r,inspectFacts:i,bindDevice:a}),diff:async({req:e,sessionName:t,logPath:n,sessionStore:r,inspectFacts:i,bindDevice:a})=>e.positionals?.[0]===`snapshot`?await X({req:e,sessionName:t,logPath:n,sessionStore:r,inspectFacts:i,bindDevice:a}):_(`INVALID_ARGS`,`diff currently supports only: diff snapshot`),wait:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>await w({req:e,sessionName:t,logPath:n,sessionStore:r}),alert:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let{session:i,device:a}=await O(r,t,e.flags);return await E(i,a,async()=>await z({req:e,logPath:n,sessionStore:r,session:i,device:a}))},settings:async({req:e,sessionName:t,logPath:n,sessionStore:r})=>{let i=J(e);if(!i.ok)return i;let{session:a,device:o}=await O(r,t,e.flags);return await E(a,o,async()=>await Y({req:e,logPath:n,sessionStore:r,session:a,device:o,parsed:i.parsed}))}};async function Q(e){let t=e.req.command,n=Z[t];return n?await n(e):null}export{Q as handleSnapshotCommands};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import{A as t}from"./sdk-android-adb.js";import{n,t as r}from"./tool-provider2.js";import i from"node:path";import a from"node:fs";import{fileURLToPath as o}from"node:url";const s={"push button":`Button`,"toggle button":`Button`,"push button menu":`Button`,label:`StaticText`,static:`StaticText`,caption:`StaticText`,text:`TextField`,entry:`TextField`,"password text":`TextField`,"spin button":`TextField`,terminal:`TextArea`,"document text":`TextArea`,paragraph:`TextArea`,frame:`Window`,window:`Window`,dialog:`Dialog`,alert:`Alert`,"file chooser":`Dialog`,"color chooser":`Dialog`,"font chooser":`Dialog`,panel:`Group`,filler:`Group`,section:`Group`,form:`Group`,grouping:`Group`,"layered pane":`Group`,"glass pane":`Group`,"root pane":`Group`,"option pane":`Group`,"internal frame":`Group`,"desktop frame":`Group`,"block quote":`Group`,article:`Group`,comment:`Group`,landmark:`Group`,log:`Group`,marquee:`Group`,math:`Group`,notification:`Group`,"content deletion":`Group`,"content insertion":`Group`,mark:`Group`,suggestion:`Group`,"scroll pane":`ScrollArea`,"scroll bar":`ScrollBar`,"menu bar":`MenuBar`,menu:`Menu`,"popup menu":`Menu`,"menu item":`MenuItem`,"check menu item":`MenuItem`,"radio menu item":`MenuItem`,"tearoff menu item":`MenuItem`,"check box":`CheckBox`,"radio button":`RadioButton`,switch:`Switch`,"combo box":`ComboBox`,"page tab":`Tab`,"page tab list":`TabList`,table:`Table`,"tree table":`Table`,"table cell":`Cell`,"table row":`Row`,"table column header":`Cell`,"table row header":`Cell`,"column header":`Cell`,"row header":`Cell`,list:`List`,"list item":`ListItem`,"list box":`List`,tree:`Tree`,"tree item":`TreeItem`,"description list":`List`,"description term":`ListItem`,"description value":`ListItem`,"tool bar":`Toolbar`,"status bar":`StatusBar`,"info bar":`StatusBar`,slider:`Slider`,"progress bar":`ProgressBar`,"level bar":`ProgressBar`,image:`Image`,icon:`Image`,animation:`Image`,canvas:`Image`,"drawing area":`Image`,video:`Video`,audio:`Audio`,link:`Link`,hyperlink:`Link`,separator:`Separator`,application:`Application`,"tool tip":`Tooltip`,timer:`Timer`,heading:`Heading`,footnote:`Footnote`,"title bar":`TitleBar`,"date editor":`DateEditor`,rating:`Slider`};function c(e){let t=e.toLowerCase().trim();return s[t]||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}const l=`atspi-dump.py`;let u=null;function d(){if(u)return u;let t=i.dirname(o(import.meta.url));for(let e=0;e<6;e++){let e=i.join(t,`linux`,l);if(a.existsSync(e))return u=e,e;t=i.dirname(t)}throw new e(`TOOL_MISSING`,`Cannot find ${l}. Ensure the agent-device package is installed correctly.`)}async function f(t,i={}){let a=r().accessibility;if(a)return await a.captureTree(t,i);if(process.platform!==`linux`)throw new e(`UNSUPPORTED_PLATFORM`,`AT-SPI2 bridge is only available on Linux`);if(!await r().whichCommand(`python3`))throw new e(`TOOL_MISSING`,`python3 is required for AT-SPI2 accessibility snapshots on Linux.`);let o=i.maxNodes??1500,s=i.maxDepth??12,l=i.maxApps??24,u=await n(`python3`,[d(),`--surface`,t,`--max-nodes`,String(o),`--max-depth`,String(s),`--max-apps`,String(l)],{allowFailure:!0,timeoutMs:3e4,signal:i.signal});if(u.exitCode!==0){let t=u.stderr.trim();throw t.includes(`No module named`)||t.includes(`gi.require_version`)?new e(`TOOL_MISSING`,`AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.`,{cause:t}):new e(`COMMAND_FAILED`,`AT-SPI2 snapshot failed (exit ${u.exitCode}): ${t||u.stdout}`)}let f;try{f=JSON.parse(u.stdout)}catch{throw new e(`COMMAND_FAILED`,`AT-SPI2 snapshot returned invalid JSON: ${u.stdout.slice(0,200)}`)}if(f.error)throw new e(`COMMAND_FAILED`,`AT-SPI2: ${f.error}`);return{nodes:(f.nodes??[]).map(e=>({index:e.index,type:c(e.role),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0})),truncated:f.truncated,surface:t}}function p(e){return e===`desktop`?`desktop`:e===`frontmost-app`||e===`app`?`frontmost-app`:(e===`menubar`&&t({level:`warn`,phase:`linux_snapshot`,data:{message:`menubar surface is not supported on Linux, falling back to desktop`}}),`desktop`)}async function m(e,t){let n=await f(p(e),{signal:t});return{nodes:n.nodes,truncated:n.truncated}}async function h(e,t,n){let{nodes:r}=await m(n),i=r.filter(n=>{let r=n.rect;return r?e>=r.x&&t>=r.y&&e<=r.x+r.width&&t<=r.y+r.height:!1}).sort((e,t)=>{let n=e.depth??0,r=t.depth??0;return n===r?g(e.rect)-g(t.rect):r-n});for(let e of i){let t=_(e);if(t.trim())return t}return``}function g(e){return(e?.width??0)*(e?.height??0)}function _(e){for(let t of[e.value,e.label,e.identifier])if(typeof t==`string`&&t.length>0)return t;return``}export{h as readLinuxTextAtPoint,m as snapshotLinux};
package/dist/src/src.js CHANGED
@@ -1 +1 @@
1
- import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{s as n,z as r}from"./sdk-batch-runner.js";import{p as i}from"./device.js";import a from"node:path";import{scryptSync as o}from"node:crypto";import s from"node:fs";import ee from"node:os";import c from"@limrun/api";import{createInstanceClient as l}from"@limrun/api/instance-client";import{createInstanceClient as te}from"@limrun/api/ios-client";import{setTimeout as u}from"node:timers/promises";const d=`limrun`,f=d;function p(e){if(e===`ios-instance`)return`ios`;if(e===`android-instance`)return`android`}function m(e,t,n){return{platform:e===`ios`?`apple`:`android`,...e===`ios`?{appleOs:`ios`}:{},id:ne(e,t.leaseId),name:`Limrun ${e} ${n.slice(0,8)}`,kind:e===`ios`?`simulator`:`emulator`,target:`mobile`,booted:!0}}function h(e){let[t,n,r]=e.split(`:`);if(t===f&&!(n!==`ios`&&n!==`android`)&&r)return{platform:n,leaseId:r}}function ne(e,t){return`${f}:${e}:${t}`}function g(e){return e?.trim()||void 0}async function _(e,t){let n=await l({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},i={exec:async(e,t)=>await C(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return i.reverse=await t.android.createPortReverse(i.exec),Object.assign(r,{adbProvider:i})}function v(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function y(e,t,n,r){let i=g(r?.packageNameHint);r?.relaunch&&i&&await C(t,[`shell`,`am`,`force-stop`,i],{allowFailure:!0});let a=await e.assets.getOrUpload({path:n,name:se(i,n)});await t.client.sendAsset(a.signedDownloadUrl);let o=i?await t.dependencies.android.inferAppName(i):void 0;return{...i?{packageName:i,launchTarget:i}:{},...o?{appName:o}:{}}}async function b(e,t){await e.adbProvider.reverse?.ensure({local:w(t.devicePort),remote:w(t.hostPort),ownerId:t.name})}async function x(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await S(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function S(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function C(e,t,n){let{adbArgs:r,result:i}=await re(e,t,n);return await ie(r,i,n?.allowFailure,e.dependencies)}async function re(e,t,n){let r=[`-s`,await ae(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function ie(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function ae(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??oe(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function oe(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function w(e){if(!Number.isInteger(e)||e<1||e>65535)throw new t(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${e}`);return`tcp:${e}`}function se(e,t){let n=a.extname(t)||`.apk`;return`${e?.replace(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}function T(e){let t=Array.isArray(e)?e:[e],n=[],r=(e,t,i)=>{let a=n.length;n.push(E(e,{index:a,depth:t,parentIndex:i}));for(let n of N(e))r(n,t+1,a)};for(let e of t)r(e,0);return n}function E(e,t){return{index:t.index,type:D(e),role:O(e),label:k(e),value:A(e),identifier:j(e),rect:M(e),enabled:e.enabled,selected:e.selected,hittable:e.hittable,depth:t.depth,parentIndex:t.parentIndex}}function D(e){return e.elementType??e.type}function O(e){return e.role??D(e)}function k(e){return e.label??e.AXLabel??void 0}function A(e){return e.value??e.AXValue??void 0}function j(e){return e.identifier??e.AXUniqueId??void 0}function M(e){let t=e.rect??e.frame;if(!(!t||typeof t.x!=`number`||typeof t.y!=`number`||typeof t.width!=`number`||typeof t.height!=`number`))return{x:t.x,y:t.y,width:t.width,height:t.height}}function N(e){return e.children??e.nodes??e.elements??[]}function P(e){return e.key===`id`?{accessibilityId:e.value}:e.key===`value`?{value:e.value}:{label:e.value}}async function F(e,t){s.mkdirSync(a.dirname(e),{recursive:!0}),await s.promises.writeFile(e,Buffer.from(t,`base64`))}async function I(e,t){let n=await te({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function L(e,t,n,r){let i=await ce(n,t.dependencies);try{let n=await e.assets.getOrUpload({path:i.uploadPath,name:i.assetName}),a=(await R(t,n.signedDownloadUrl,{md5:n.md5,relaunch:r?.relaunch,appIdentifierHint:r?.appIdentifierHint})).appId;return{...a?{bundleId:a,launchTarget:a}:{},...i.appName?{appName:i.appName}:{}}}finally{await i.cleanup()}}async function R(e,n,r){let i=await e.client.listApps().catch(()=>void 0),a=g((await e.client.installApp(n,{md5:r?.md5,launchMode:r?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`})).bundleId),o=g(r?.appIdentifierHint),s=[];for(let t of H){t>0&&await u(t),s=await e.client.listApps();let n=U({resultBundleId:a,requestedBundleId:o,beforeInstallApps:i,afterInstallApps:s});if(n)return{appId:n}}throw new t(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:a,requestedBundleId:o,installedUserApps:s.filter(G).map(e=>e.bundleId).sort()})}function z(e){return new B(e)}var B=class{session;constructor(e){this.session=e}async open(e,t){if(t?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(t.url);return}if(n(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(P(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw K(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n),await u(t);return}await this.session.client.typeText(e)}async fill(e,t,n){await this.tap(e,t),await this.session.client.typeText(n)}async fillElementSelector(e,t){await this.session.client.setElementValue(t,P(e))}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){await F(e,(await this.session.client.screenshot()).base64)}async snapshot(e){let t=await this.session.client.elementTree();return{nodes:T(JSON.parse(t)),backend:`xctest`}}async back(){await this.session.client.pressKey(`escape`)}async home(){throw K(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw K(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw K(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw K(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw K(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readClipboard(){throw K(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw K(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw K(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function ce(e,t){if(!(await s.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:a.basename(e),appName:V(e),cleanup:async()=>{}};let n=await s.promises.mkdtemp(a.join(ee.tmpdir(),`agent-device-limrun-ios-app-`)),r=a.join(n,`${a.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:a.dirname(e),entryName:a.basename(e),archivePath:r})}catch(e){throw await s.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:a.basename(r),appName:await t.ios.readBundleAppName(e)??V(e),cleanup:async()=>{await s.promises.rm(n,{recursive:!0,force:!0})}}}function V(e){return a.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const H=[0,250];function U(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??W(e.beforeInstallApps,e.afterInstallApps)}function W(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>G(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function G(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}function K(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}function q(e){return e.platform===`android`?le(e):ue(e)}function le(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:v(e),adb:e.adbProvider,listApps:async n=>await e.dependencies.android.listApps(t,i(n)),getForegroundApp:async()=>await e.dependencies.android.getForegroundApp(t),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...J(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function ue(e){return{platform:`ios`,device:e.device,interactor:z(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>i(t)===`all`||G(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...J(e.client),installRemoteApp:async(t,n)=>await R(e,t,n),runSimctl:t=>e.client.simctl(t)}}function J(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}const Y=`agent-device-cli`;function X(e){return{apiKey:e.apiKey,defaultHeaders:{"x-agent-device-client":Y,"x-agent-device-version":e.clientVersion}}}function de(e){if(e.runtimeInstance!==void 0){let t=e.runtimeInstance.trim();if(!t)throw TypeError(`Limrun runtimeInstance must be a non-empty string`);return t}return`principal-${o(JSON.stringify({provider:`limrun`,region:e.region?.trim().toLowerCase()||`default`,apiKey:e.apiKey}),`agent-device:limrun-runtime-owner:v1`,32,{N:16384,r:8,p:1,maxmem:67108864}).toString(`hex`)}`}function Z(e,t,n){let i=new Q(e,t);if(!n?.includePlatformModule)return i;let a=r(d,de(e));if(a.kind!==`provider-runtime`)throw TypeError(`Invalid Limrun runtime owner`);return Object.freeze({runtime:i,platformModule:Object.freeze({owner:a,loadRuntime:async e=>await fe(i,a.instance,e)})})}var Q=class{limrun;sessions=new Map;options;dependencies;provider=d;leaseLifecycle={allocate:async e=>await this.allocate(e),release:async e=>await this.release(e)};recoverExpiredLease=async e=>{if(e.leaseProvider!==this.provider||!p(e.backend))throw new t(`UNSUPPORTED_OPERATION`,`Limrun cannot recover this expired lease.`,{leaseId:e.leaseId,leaseProvider:e.leaseProvider,leaseBackend:e.backend});await this.release(e)};deviceInventoryProvider=async e=>{if(e.leaseProvider!==this.provider||!e.leaseId)return null;let t=this.sessions.get(e.leaseId);return t?e.platform&&e.platform!==t.platform?[]:[t.device]:null};constructor(e,t){this.options=e,this.dependencies=t,this.limrun=new c(X({apiKey:e.apiKey,clientVersion:t.clientVersion}))}ownsDevice(e){return h(e.id)!==void 0}getInteractor(e){let t=this.getSessionForDevice(e);if(t)return t.platform===`ios`?z(t):v(t)}getDeviceSession(e){let t=this.getSessionForDevice(e);return t?q(t):void 0}async installApp(e,t,n,r){return await this.installInstallablePath(e,n,{...r,appIdentifierHint:r?.appIdentifierHint??t,packageNameHint:r?.packageNameHint??t})}async installInstallablePath(e,t,n){let r=this.getSessionForDevice(e);if(r)return r.platform===`ios`?await L(this.limrun,r,t,n):await y(this.limrun,r,t,n)}async configurePortReverse(e){let t=this.requireAndroidPortReverseSession(e.leaseId);if(t)return await b(t,e),pe(e)}async shutdown(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(async e=>await this.terminateSession(e))),this.sessions.clear()}async allocate(e){if(e.leaseProvider!==this.provider)return;let t=p(e.backend);if(!t)return;let n=this.sessions.get(e.leaseId);if(n)return{limrunInstanceId:n.instanceId,device:n.device};let r=t===`ios`?await this.createIosSession(e):await this.createAndroidSession(e);return this.sessions.set(e.leaseId,r),{limrunInstanceId:r.instanceId,device:r.device}}async createIosSession(e){let n=await this.limrun.iosInstances.create({wait:!0,metadata:this.buildInstanceMetadata(e),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl)throw new t(`COMMAND_FAILED`,`Limrun iOS instance did not expose apiUrl`);return await I({lease:e,instanceId:n.metadata.id,device:m(`ios`,e,n.metadata.id),apiUrl:n.status.apiUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.iosInstances.delete(n.metadata.id).catch(()=>{}),e}}async createAndroidSession(e){let n=await this.limrun.androidInstances.create({wait:!0,metadata:this.buildInstanceMetadata(e),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl||!n.status.adbWebSocketUrl)throw new t(`COMMAND_FAILED`,`Limrun Android instance did not expose API and ADB websocket endpoints`);return await _({lease:e,instanceId:n.metadata.id,device:m(`android`,e,n.metadata.id),apiUrl:n.status.apiUrl,adbUrl:n.status.adbWebSocketUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.androidInstances.delete(n.metadata.id).catch(()=>{}),e}}buildInstanceMetadata(e){return{displayName:`agent-device-${e.tenantId}-${e.runId}`,labels:{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId,provider:e.leaseProvider??`limrun`,source:Y}}}async release(e){let t=this.sessions.get(e.leaseId);return t?(await this.terminateSession(t),this.sessions.delete(e.leaseId),{limrunInstanceId:t.instanceId}):await this.releaseRecoveredSession(e)}async releaseRecoveredSession(e){let t=p(e.backend);if(!t)return;let n=`provider=${d},leaseId=${e.leaseId}`,r=(t===`ios`?await this.limrun.iosInstances.list({labelSelector:n}):await this.limrun.androidInstances.list({labelSelector:n})).getPaginatedItems().map(e=>e.metadata.id);for(let e of r)t===`ios`?await this.limrun.iosInstances.delete(e):await this.limrun.androidInstances.delete(e);if(r.length!==0)return{limrunInstanceId:r[0],limrunInstanceCount:r.length}}async terminateSession(e){if(e.client.disconnect(),e.platform===`ios`){await this.limrun.iosInstances.delete(e.instanceId);return}await x(e),await this.limrun.androidInstances.delete(e.instanceId)}getSessionForDevice(e){let t=h(e.id);if(!t)return;let n=this.sessions.get(t.leaseId);return n?.platform===t.platform?n:void 0}currentAppLogReader(e){let t=this.getSessionForDevice(e);if(!t)return;let n=q(t);return{platform:t.platform,leaseId:t.lease.leaseId,instanceId:t.instanceId,readLogs:async(e,t)=>n.platform===`ios`?await n.readLogs(e,t):await n.readLogs(t),[Symbol.asyncDispose]:async()=>void 0}}async reconnectAppLogReader(e,t){let{reconnectLimrunAppLogReader:n}=await import(`./app-log-reconnect.js`);return await n({limrun:this.limrun,descriptor:e,dependencies:this.dependencies,signal:t})}requireAndroidPortReverseSession(e){let t=this.sessions.get(e);if(!t||t.platform===`android`)return t;throw me(`port reverse`,`Direct Limrun iOS sessions cannot reach local host ports; use a bridge public URL.`)}};async function fe(e,t,n){let{createLimrunPlatformRuntimeOwner:r}=await import(`./app-log-runtime.js`);return r({host:n,runtimeInstance:t,ownsDevice:t=>e.ownsDevice(t),openCurrent:async t=>e.currentAppLogReader(t),reconnect:async(t,n)=>await e.reconnectAppLogReader(t,n)})}function pe(e){return{leaseId:e.leaseId,devicePort:e.devicePort,hostPort:e.hostPort,name:e.name}}function me(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}async function $(e){let n=new c({...X(e),timeout:15e3,maxRetries:0}),r={limit:1,...e.region?{region:e.region}:{}};try{e.platform===`android`?await n.androidInstances.list(r):await n.iosInstances.list(r)}catch(e){let n=he(e);throw n===401||n===403?new t(`UNAUTHORIZED`,`Limrun rejected connection verification.`,{status:n,hint:`Check LIMRUN_API_KEY and its organization access.`}):new t(`COMMAND_FAILED`,`Limrun connection verification failed.`,{hint:`Check Limrun service access, LIMRUN_REGION, and network connectivity, then retry.`},e)}let i=e.platform===`android`?`Android`:`iOS`,a=e.platform===`android`?`emulator`:`simulator`;return{provider:`limrun`,service:`Limrun`,verificationMessage:`Credentials and ${i} instance access verified.`,device:{status:`deferred`,name:`Provider-selected ${i} ${a}`,platform:e.platform},app:{status:`missing`,message:`A new Limrun instance does not have your app yet.`}}}function he(e){if(!e||typeof e!=`object`)return;let t=e.status;return typeof t==`number`?t:void 0}var ge=e({LIMRUN_PROVIDER:()=>d,createLimrunRuntime:()=>Z,verifyLimrunConnection:()=>$});export{h as a,d as i,$ as n,Z as r,ge as t};
1
+ import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{J as n,Ot as r}from"./sdk-batch-runner.js";import{p as i}from"./device.js";import a from"node:path";import{scryptSync as o}from"node:crypto";import s from"node:fs";import c from"node:os";import l from"@limrun/api";import{createInstanceClient as u}from"@limrun/api/instance-client";import{createInstanceClient as ee}from"@limrun/api/ios-client";import{setTimeout as d}from"node:timers/promises";const f=`limrun`,p=f;function m(e){if(e===`ios-instance`)return`ios`;if(e===`android-instance`)return`android`}function h(e,t,n){return{platform:e===`ios`?`apple`:`android`,...e===`ios`?{appleOs:`ios`}:{},id:_(e,t.leaseId),name:`Limrun ${e} ${n.slice(0,8)}`,kind:e===`ios`?`simulator`:`emulator`,target:`mobile`,booted:!0}}function g(e){let[t,n,r]=e.split(`:`);if(t===p&&!(n!==`ios`&&n!==`android`)&&r)return{platform:n,leaseId:r}}function _(e,t){return`${p}:${e}:${t}`}function v(e){return e?.trim()||void 0}async function y(e,t,n=`Limrun provider operation aborted`,r){if(!t)try{return await e}finally{r?.()}return await new Promise((i,a)=>{let o=()=>a(t.reason??Error(n));if(t.aborted){e.then(e=>{r?.(),i(e)},e=>{r?.(),a(e)}),o();return}t.addEventListener(`abort`,o,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,o),r?.(),i(e)},e=>{t.removeEventListener(`abort`,o),r?.(),a(e)})})}function te(){let e=new Set;return{wait:async(t,n,r)=>{let i,a=new Promise(e=>{i=e});return e.add(a),a.then(()=>e.delete(a)),await y(t,n,r,i)},[Symbol.asyncDispose]:async()=>{for(;e.size>0;)await Promise.all(e)}}}async function b(e,t,n,r){return await(e?e.wait(t,n,r):y(t,n,r))}async function x(e,t){let n=await u({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},i={exec:async(e,t)=>await T(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return i.reverse=await t.android.createPortReverse(i.exec),Object.assign(r,{adbProvider:i})}function S(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function C(e,t,n,r,i,a){i?.throwIfAborted();let o=v(r?.packageNameHint);r?.relaunch&&o&&await T(t,[`shell`,`am`,`force-stop`,o],{allowFailure:!0,signal:i});let s=await b(a,e.assets.getOrUpload({path:n,name:ce(o,n)},{signal:i}),i);await b(a,t.client.sendAsset(s.signedDownloadUrl),i),i?.throwIfAborted();let c=o?await t.dependencies.android.inferAppName(o):void 0;return{...o?{packageName:o,launchTarget:o}:{},...c?{appName:c}:{}}}async function w(e,t){await e.adbProvider.reverse?.ensure({local:E(t.devicePort),remote:E(t.hostPort),ownerId:t.name})}async function ne(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await re(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function re(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function T(e,t,n){let{adbArgs:r,result:i}=await ie(e,t,n);return await ae(r,i,n?.allowFailure,e.dependencies)}async function ie(e,t,n){let r=[`-s`,await oe(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function ae(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function oe(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??se(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function se(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function E(e){if(!Number.isInteger(e)||e<1||e>65535)throw new t(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${e}`);return`tcp:${e}`}function ce(e,t){let n=a.extname(t)||`.apk`;return`${e?.replace(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}function D(e){let t=Array.isArray(e)?e:[e],n=[],r=(e,t,i)=>{let a=n.length;n.push(O(e,{index:a,depth:t,parentIndex:i}));for(let n of F(e))r(n,t+1,a)};for(let e of t)r(e,0);return n}function O(e,t){return{index:t.index,type:k(e),role:A(e),label:j(e),value:M(e),identifier:N(e),rect:P(e),enabled:e.enabled,selected:e.selected,hittable:e.hittable,depth:t.depth,parentIndex:t.parentIndex}}function k(e){return e.elementType??e.type}function A(e){return e.role??k(e)}function j(e){return e.label??e.AXLabel??void 0}function M(e){return e.value??e.AXValue??void 0}function N(e){return e.identifier??e.AXUniqueId??void 0}function P(e){let t=e.rect??e.frame;if(!(!t||typeof t.x!=`number`||typeof t.y!=`number`||typeof t.width!=`number`||typeof t.height!=`number`))return{x:t.x,y:t.y,width:t.width,height:t.height}}function F(e){return e.children??e.nodes??e.elements??[]}function I(e){return e.key===`id`?{accessibilityId:e.value}:e.key===`value`?{value:e.value}:{label:e.value}}async function L(e,t){s.mkdirSync(a.dirname(e),{recursive:!0}),await s.promises.writeFile(e,Buffer.from(t,`base64`))}async function R(e,t){let n=await ee({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function z(e,t,n,r,i,a){i?.throwIfAborted();let o=await le(n,t.dependencies);try{i?.throwIfAborted();let n=await b(a,e.assets.getOrUpload({path:o.uploadPath,name:o.assetName},{signal:i}),i),s=(await B(t,n.signedDownloadUrl,{md5:n.md5,relaunch:r?.relaunch,appIdentifierHint:r?.appIdentifierHint},i,a)).appId;return{...s?{bundleId:s,launchTarget:s}:{},...o.appName?{appName:o.appName}:{}}}finally{await o.cleanup()}}async function B(e,n,r,i,a){i?.throwIfAborted();let o=await b(a,e.client.listApps(),i).catch(e=>{if(i?.aborted)throw e}),s=v((await b(a,e.client.installApp(n,{md5:r?.md5,launchMode:r?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),i)).bundleId),c=v(r?.appIdentifierHint),l=[];for(let t of W){t>0&&await d(t,void 0,{signal:i}),l=await b(a,e.client.listApps(),i);let n=ue({resultBundleId:s,requestedBundleId:c,beforeInstallApps:o,afterInstallApps:l});if(n)return{appId:n}}throw new t(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:s,requestedBundleId:c,installedUserApps:l.filter(G).map(e=>e.bundleId).sort()})}function V(e){return new H(e)}var H=class{session;constructor(e){this.session=e}async open(e,t){if(t?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(t.url);return}if(n(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(I(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw K(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n),await d(t);return}await this.session.client.typeText(e)}async fill(e,t,n){await this.tap(e,t),await this.session.client.typeText(n)}async fillElementSelector(e,t){await this.session.client.setElementValue(t,I(e))}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){await L(e,(await this.session.client.screenshot()).base64)}async snapshot(e){let t=await this.session.client.elementTree();return{nodes:D(JSON.parse(t)),backend:`xctest`}}async back(){await this.session.client.pressKey(`escape`)}async home(){throw K(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw K(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw K(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw K(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw K(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readClipboard(){throw K(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw K(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw K(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function le(e,t){if(!(await s.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:a.basename(e),appName:U(e),cleanup:async()=>{}};let n=await s.promises.mkdtemp(a.join(c.tmpdir(),`agent-device-limrun-ios-app-`)),r=a.join(n,`${a.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:a.dirname(e),entryName:a.basename(e),archivePath:r})}catch(e){throw await s.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:a.basename(r),appName:await t.ios.readBundleAppName(e)??U(e),cleanup:async()=>{await s.promises.rm(n,{recursive:!0,force:!0})}}}function U(e){return a.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const W=[0,250];function ue(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??de(e.beforeInstallApps,e.afterInstallApps)}function de(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>G(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function G(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}function K(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}function q(e){return e.platform===`android`?fe(e):pe(e)}function fe(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:S(e),adb:e.adbProvider,listApps:async n=>await e.dependencies.android.listApps(t,i(n)),getForegroundApp:async n=>await e.dependencies.android.getForegroundApp(e.device,t,n),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...J(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function pe(e){return{platform:`ios`,device:e.device,interactor:V(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>i(t)===`all`||G(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...J(e.client),installRemoteApp:async(t,n)=>await B(e,t,n),runSimctl:t=>e.client.simctl(t)}}function J(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}const Y=`agent-device-cli`;function X(e){return{apiKey:e.apiKey,defaultHeaders:{"x-agent-device-client":Y,"x-agent-device-version":e.clientVersion}}}function me(e){if(e.runtimeInstance!==void 0){let t=e.runtimeInstance.trim();if(!t)throw TypeError(`Limrun runtimeInstance must be a non-empty string`);return t}return`principal-${o(JSON.stringify({provider:`limrun`,region:e.region?.trim().toLowerCase()||`default`,apiKey:e.apiKey}),`agent-device:limrun-runtime-owner:v1`,32,{N:16384,r:8,p:1,maxmem:67108864}).toString(`hex`)}`}function Z(e,t,n){let i=new he(e,t);if(!n?.includePlatformModule)return i;let a=r(f,me(e));if(a.kind!==`provider-runtime`)throw TypeError(`Invalid Limrun runtime owner`);return Object.freeze({runtime:i,platformModule:Object.freeze({owner:a,loadRuntime:async e=>await ge(i,a.instance,e)})})}var he=class{limrun;sessions=new Map;options;dependencies;provider=f;leaseLifecycle={allocate:async e=>await this.allocate(e),release:async e=>await this.release(e)};recoverExpiredLease=async e=>{if(e.leaseProvider!==this.provider||!m(e.backend))throw new t(`UNSUPPORTED_OPERATION`,`Limrun cannot recover this expired lease.`,{leaseId:e.leaseId,leaseProvider:e.leaseProvider,leaseBackend:e.backend});await this.release(e)};deviceInventoryProvider=async e=>{if(e.leaseProvider!==this.provider||!e.leaseId)return null;let t=this.sessions.get(e.leaseId);return t?e.platform&&e.platform!==t.platform?[]:[t.device]:null};constructor(e,t){this.options=e,this.dependencies=t,this.limrun=new l(X({apiKey:e.apiKey,clientVersion:t.clientVersion}))}ownsDevice(e){return g(e.id)!==void 0}hasLiveSession(e){return this.getSessionForDevice(e)!==void 0}getInteractor(e,t){let n=this.getSessionForDevice(e);if(n)return n.platform===`ios`?V(n):S(n)}getDeviceSession(e){let t=this.getSessionForDevice(e);return t?q(t):void 0}async installApp(e,t,n,r,i,a){return await this.installInstallablePath(e,n,{...r,appIdentifierHint:r?.appIdentifierHint??t,packageNameHint:r?.packageNameHint??t},i,a)}async installInstallablePath(e,t,n,r,i){let a=this.getSessionForDevice(e);if(a)return a.platform===`ios`?await z(this.limrun,a,t,n,r,i):await C(this.limrun,a,t,n,r,i)}async configurePortReverse(e){let t=this.requireAndroidPortReverseSession(e.leaseId);if(t)return await w(t,e),_e(e)}async shutdown(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(async e=>await this.terminateSession(e))),this.sessions.clear()}async allocate(e){if(e.leaseProvider!==this.provider)return;let t=m(e.backend);if(!t)return;let n=this.sessions.get(e.leaseId);if(n)return{limrunInstanceId:n.instanceId,device:n.device};let r=t===`ios`?await this.createIosSession(e):await this.createAndroidSession(e);return this.sessions.set(e.leaseId,r),{limrunInstanceId:r.instanceId,device:r.device}}async createIosSession(e){let n=await this.limrun.iosInstances.create({wait:!0,metadata:this.buildInstanceMetadata(e),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl)throw new t(`COMMAND_FAILED`,`Limrun iOS instance did not expose apiUrl`);return await R({lease:e,instanceId:n.metadata.id,device:h(`ios`,e,n.metadata.id),apiUrl:n.status.apiUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.iosInstances.delete(n.metadata.id).catch(()=>{}),e}}async createAndroidSession(e){let n=await this.limrun.androidInstances.create({wait:!0,metadata:this.buildInstanceMetadata(e),spec:this.options.region?{region:this.options.region}:{}});try{if(!n.status.apiUrl||!n.status.adbWebSocketUrl)throw new t(`COMMAND_FAILED`,`Limrun Android instance did not expose API and ADB websocket endpoints`);return await x({lease:e,instanceId:n.metadata.id,device:h(`android`,e,n.metadata.id),apiUrl:n.status.apiUrl,adbUrl:n.status.adbWebSocketUrl,token:n.status.token},this.dependencies)}catch(e){throw await this.limrun.androidInstances.delete(n.metadata.id).catch(()=>{}),e}}buildInstanceMetadata(e){return{displayName:`agent-device-${e.tenantId}-${e.runId}`,labels:{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId,provider:e.leaseProvider??`limrun`,source:Y}}}async release(e){let t=this.sessions.get(e.leaseId);return t?(await this.terminateSession(t),this.sessions.delete(e.leaseId),{limrunInstanceId:t.instanceId}):await this.releaseRecoveredSession(e)}async releaseRecoveredSession(e){let t=m(e.backend);if(!t)return;let n=`provider=${f},leaseId=${e.leaseId}`,r=(t===`ios`?await this.limrun.iosInstances.list({labelSelector:n}):await this.limrun.androidInstances.list({labelSelector:n})).getPaginatedItems().map(e=>e.metadata.id);for(let e of r)t===`ios`?await this.limrun.iosInstances.delete(e):await this.limrun.androidInstances.delete(e);if(r.length!==0)return{limrunInstanceId:r[0],limrunInstanceCount:r.length}}async terminateSession(e){if(e.client.disconnect(),e.platform===`ios`){await this.limrun.iosInstances.delete(e.instanceId);return}await ne(e),await this.limrun.androidInstances.delete(e.instanceId)}getSessionForDevice(e){let t=g(e.id);if(!t)return;let n=this.sessions.get(t.leaseId);return n?.platform===t.platform?n:void 0}currentAppLogReader(e){let t=this.getSessionForDevice(e);if(!t)return;let n=q(t);return{platform:t.platform,leaseId:t.lease.leaseId,instanceId:t.instanceId,readLogs:async(e,t)=>n.platform===`ios`?await n.readLogs(e,t):await n.readLogs(t),[Symbol.asyncDispose]:async()=>void 0}}async reconnectAppLogReader(e,t){let{reconnectLimrunAppLogReader:n}=await import(`./app-log-reconnect.js`);return await n({limrun:this.limrun,descriptor:e,dependencies:this.dependencies,signal:t})}requireAndroidPortReverseSession(e){let t=this.sessions.get(e);if(!t||t.platform===`android`)return t;throw Q(`port reverse`,`Direct Limrun iOS sessions cannot reach local host ports; use a bridge public URL.`)}};async function ge(e,n,r){let{createLimrunPlatformRuntimeOwner:i}=await import(`./app-log-runtime.js`);return i({host:r,runtimeInstance:n,ownsDevice:t=>e.ownsDevice(t),hasLiveSession:t=>e.hasLiveSession(t),getInteractor:(t,n)=>e.getInteractor(t,n),openCurrent:async t=>e.currentAppLogReader(t),reconnect:async(t,n)=>await e.reconnectAppLogReader(t,n),listApps:async(n,r,i)=>{i.throwIfAborted();let a=e.getDeviceSession(n);if(!a)throw new t(`DEVICE_NOT_FOUND`,`Limrun app inventory session is unavailable`,{deviceId:n.id});return(await a.listApps(r)).map(e=>({id:e.id,name:e.name??e.id}))},getAppState:async(n,r)=>{r.throwIfAborted();let i=e.getDeviceSession(n);if(i?.platform!==`android`)throw new t(`UNSUPPORTED_OPERATION`,`Limrun Android appstate requires an active provider session`);let a=await i.getForegroundApp(r);return r.throwIfAborted(),{package:a?.appId,activity:a?.activity}},deployApp:async(t,n,r,i)=>await e.installApp(t,n.app,n.appPath,{relaunch:n.replaceExisting,appIdentifierHint:n.app,packageNameHint:n.app},r,i),deployMaterializedApp:async(t,n,r,i)=>await e.installInstallablePath(t,n.artifact.installablePath,{appIdentifierHint:n.artifact.bundleId,packageNameHint:n.artifact.packageName},r,i),configurePortReverse:async t=>await e.configurePortReverse(t)})}function _e(e){return{leaseId:e.leaseId,devicePort:e.devicePort,hostPort:e.hostPort,name:e.name}}function Q(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}async function $(e){let n=new l({...X(e),timeout:15e3,maxRetries:0}),r={limit:1,...e.region?{region:e.region}:{}};try{e.platform===`android`?await n.androidInstances.list(r):await n.iosInstances.list(r)}catch(e){let n=ve(e);throw n===401||n===403?new t(`UNAUTHORIZED`,`Limrun rejected connection verification.`,{status:n,hint:`Check LIMRUN_API_KEY and its organization access.`}):new t(`COMMAND_FAILED`,`Limrun connection verification failed.`,{hint:`Check Limrun service access, LIMRUN_REGION, and network connectivity, then retry.`},e)}let i=e.platform===`android`?`Android`:`iOS`,a=e.platform===`android`?`emulator`:`simulator`;return{provider:`limrun`,service:`Limrun`,verificationMessage:`Credentials and ${i} instance access verified.`,device:{status:`deferred`,name:`Provider-selected ${i} ${a}`,platform:e.platform},app:{status:`missing`,message:`A new Limrun instance does not have your app yet.`}}}function ve(e){if(!e||typeof e!=`object`)return;let t=e.status;return typeof t==`number`?t:void 0}var ye=e({LIMRUN_PROVIDER:()=>f,createLimrunRuntime:()=>Z,verifyLimrunConnection:()=>$});export{te as a,y as i,$ as n,f as o,Z as r,g as s,ye as t};
package/dist/src/src2.js CHANGED
@@ -1,2 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{H as t,I as n,L as r,W as i,z as a}from"./sdk-batch-runner.js";import{T as o,d as s,o as c}from"./sdk-device.js";const l=4096;function u(e){return f(e,{seen:new WeakSet,nodes:0},0)}function d(e){return Object.freeze(Object.fromEntries(Object.entries(e).map(([e,t])=>[e,m(t)])))}function f(e,t,n){if(!te(e)||n>32||t.seen.has(e))return!1;t.seen.add(e),t.nodes+=1;let r=t.nodes<=l&&Object.values(e).every(e=>p(e,t,n+1));return t.seen.delete(e),r}function p(e,t,n){return ne(e)?!0:n>32?!1:Array.isArray(e)?ee(e,t,n):f(e,t,n)}function ee(e,t,n){if(t.seen.has(e))return!1;t.seen.add(e),t.nodes+=1;let r=t.nodes<=l&&e.every(e=>p(e,t,n+1));return t.seen.delete(e),r}function te(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function ne(e){return e===null?!0:typeof e==`number`?Number.isFinite(e):typeof e==`string`||typeof e==`boolean`}function m(e){return Array.isArray(e)?Object.freeze(e.map(m)):typeof e==`object`&&e?d(e):e}function h(e){if(!x(e))return g(`Durable resource envelope must be an object`);let t=e.envelopeVersion;if(!b(t))return g(`Durable resource envelopeVersion must be a non-negative integer`);if(t!==1)return{status:`unreattachable`,reason:`descriptor-version-unsupported`,message:`Unsupported durable resource envelope version: ${t}`,version:t};if(!y(e.resourceKind))return g(`Durable resource resourceKind must be a non-empty string`);if(!y(e.sessionId))return g(`Durable resource sessionId must be a non-empty string`);let n=oe(e.device);if(!n)return g(`Durable resource device identity is invalid`);let r=ae(e.owner);if(!r)return g(`Durable resource owner reference is invalid`);if(r.kind===`local-family`&&r.family!==n.family)return g(`Durable resource local owner does not match the device family`);let i=fe(e.fence);if(!i)return g(`Durable resource ownership fence is invalid`);if(!me(e.lifecycle))return g(`Durable resource lifecycle state is invalid`);let a=pe(e.descriptor);return a?e.metadata!==void 0&&!u(e.metadata)?g(`Durable resource metadata must be a JSON object`):{status:`decoded`,envelope:Object.freeze({envelopeVersion:1,resourceKind:e.resourceKind,sessionId:e.sessionId,device:n,owner:r,fence:i,lifecycle:e.lifecycle,descriptor:a,...e.metadata===void 0?{}:{metadata:d(e.metadata)}})}:g(`Durable resource descriptor is invalid`)}function re(e,t){return Object.freeze({version:e.version,body:d(e.encode(t))})}function ie(e){let t=h({envelopeVersion:1,...e});if(t.status!==`decoded`)throw TypeError(t.message);return t.envelope}function g(e){return{status:`unreattachable`,reason:`descriptor-invalid`,message:e}}function ae(e){return x(e)?e.kind===`local-family`&&s(e.family)?r(e.family):e.kind===`provider-runtime`&&y(e.provider)&&y(e.instance)?a(e.provider,e.instance):null:null}function oe(e){if(!x(e))return null;let t=ce(e.id),n=_(e.family),r=v(e.kind),i=le(e.target);return!t||!n||!r||i===null||!ue(e,n,r)?null:se(e,t,n,r,i)}function se(e,t,n,r,i){return Object.freeze({id:t,family:n,...e.appleOs===void 0?{}:{appleOs:e.appleOs},kind:r,...i===void 0?{}:{target:i},...e.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:e.iosPhysicalDeviceBackend}})}function ce(e){return y(e)?e:null}function _(e){return s(e)?e:null}function v(e){return he(e)?e:null}function le(e){if(e!==void 0)return ge(e)?e:null}function ue(e,t,n){if(t===`apple`){if(!c(e.appleOs))return!1}else if(e.appleOs!==void 0||e.iosPhysicalDeviceBackend!==void 0)return!1;return de(e.iosPhysicalDeviceBackend,n)}function de(e,t){return e===void 0?!0:t===`device`?e===`coredevice`||e===`xctest`:!1}function fe(e){return!x(e)||!y(e.token)||!b(e.generation)?null:Object.freeze({token:e.token,generation:e.generation})}function pe(e){return!x(e)||!b(e.version)||!u(e.body)?null:Object.freeze({version:e.version,body:d(e.body)})}function me(e){return e===`open`||e===`completed`}function he(e){return e===`simulator`||e===`emulator`||e===`device`}function ge(e){return e===`mobile`||e===`tv`||e===`desktop`}function y(e){return typeof e==`string`&&e.trim().length>0}function b(e){return typeof e==`number`&&Number.isInteger(e)&&e>=0}function x(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function S(e,t){if(e.resourceKind!==t.resourceKind)return{status:`unreattachable`,reason:`descriptor-invalid`,message:`Durable resource kind ${e.resourceKind} does not match ${t.resourceKind}`};if(e.descriptor.version!==t.version)return{status:`unreattachable`,reason:`descriptor-version-unsupported`,message:`Unsupported ${t.resourceKind} descriptor version: ${e.descriptor.version}`,version:e.descriptor.version};try{let n=t.decode(e.descriptor.body);return n.status===`decoded`?n:{status:`unreattachable`,reason:`descriptor-invalid`,message:n.message}}catch(e){return{status:`unreattachable`,reason:`descriptor-invalid`,message:e instanceof Error?e.message:`Descriptor codec rejected the body`}}}function C(e,t){return Object.freeze({pendingHandle:new i(e),envelope:t})}function w(e){return Object.freeze({appLogReattach:async({envelope:t})=>{let n=S(t,e.codec);return n.status===`unreattachable`?n:await e.reattach(n.descriptor,T(t))},appLogCleanup:async({envelope:t})=>{let n=S(t,e.codec);return n.status===`decoded`?await e.cleanup(n.descriptor,T(t)):{status:`cleanup-pending`,reason:`manual-recovery-required`,message:n.message}}})}function T(e){return Object.freeze({sessionId:e.sessionId,fence:e.fence})}function _e(e){if(typeof e!=`object`||!e||Array.isArray(e))return{status:`invalid`,message:`App-log process marker must be an object`};let t=e;return!Number.isInteger(t.pid)||Number(t.pid)<=0?{status:`invalid`,message:`App-log process marker pid must be a positive integer`}:typeof t.startTime!=`string`||t.startTime.trim().length===0?{status:`invalid`,message:`App-log process marker startTime must be a non-empty string`}:typeof t.command!=`string`||t.command.trim().length===0?{status:`invalid`,message:`App-log process marker command must be a non-empty string`}:{status:`decoded`,marker:Object.freeze({pid:Number(t.pid),startTime:t.startTime,command:t.command})}}function ve(e){let t,n,r,i=()=>n??=e.forceCleanup();return Object.freeze({inspect:()=>e.inspect(),finish:()=>t??=e.finish(),forceCleanup:i,[Symbol.asyncDispose]:async()=>{r??=i().then(ye),await r}})}function E(e){return ve({inspect:e.inspect,finish:e.finish,forceCleanup:async()=>{let t=await e.finish();return t.status===`completed`?{status:`cleaned`}:{status:`cleanup-pending`,reason:t.reason,message:t.message}}})}function ye(t){if(!n(t))throw new e(`COMMAND_FAILED`,t.message??`Durable resource cleanup could not be confirmed`,{reason:t.reason,retriable:t.reason!==`ownership-fence-lost`,hint:t.reason===`ownership-fence-lost`?`Use the current resource owner or recovery record before retrying cleanup.`:`Keep the recovery record and retry cleanup through the exact runtime owner.`})}function be(e,t){let n=D(e),r,i,a,o=()=>r??=t.finish(n),s=()=>i??=r?r.then(async e=>e.status===`completed`?{status:`cleaned`}:await t.forceCleanup(n),async()=>await t.forceCleanup(n)):t.forceCleanup(n);return Object.freeze({inspect:()=>n,appendGestureEvents:e=>{e.length===0||r||i||(n=D({...n,gestureEvents:[...n.gestureEvents,...e]}))},setTouchReferenceFrame:e=>{r||i||(n=D({...n,...e?{touchReferenceFrame:e}:{}}))},setRunnerSessionId:e=>{r||i||e.trim().length===0||(n=D({...n,runnerSessionId:e}))},invalidate:e=>{r||i||n.invalidatedReason||(n=D({...n,invalidatedReason:e}))},finish:o,forceCleanup:s,[Symbol.asyncDispose]:async()=>{a??=s().then(xe),await a}})}function D(e){return Object.freeze({...e,gestureEvents:Object.freeze([...e.gestureEvents])})}function xe(t){if(!n(t))throw new e(`COMMAND_FAILED`,t.message??`Screen recording cleanup could not be confirmed`,{reason:t.reason,retriable:t.reason!==`ownership-fence-lost`,hint:t.reason===`ownership-fence-lost`?`Use the current recording owner or recovery record before retrying cleanup.`:`Keep the recovery record and retry cleanup through the exact runtime owner.`})}function O(e,t,n=e.showTouches){return Object.freeze({status:`completed`,result:Object.freeze({backend:e.backend,outPath:e.outPath,...e.clientOutPath===void 0?{}:{clientOutPath:e.clientOutPath},startedAt:e.startedAt,completedAt:Date.now(),scope:e.scope,showTouches:n,recordOnlySession:e.recordOnlySession,...e.activeSessionApp===void 0?{}:{activeSessionApp:e.activeSessionApp},...t})})}function k(t,n,r){let i=A(t,n);if(i.length>0)throw new e(`INVALID_ARGS`,r(i))}function A(e,t){return Object.freeze([...t.scopes.includes(e.scope)?[]:[`--scope`],...t.fps||e.fps===void 0?[]:[`--fps`],...t.exportQuality||e.exportQuality===void 0?[]:[`--quality`],...t.hideTouches||!e.hideTouchesRequested?[]:[`--hide-touches`]])}async function j(e,t){let n=await N(e,t);if(n.status===`missing`)return{status:`missing`};if(n.status===`invalid`)return{status:`unreattachable`,reason:`ownership-fence-lost`,message:n.message};let r=await e.processes.inspect(n.marker);return r===`missing`?(t&&await e.processes.clearMarker(t),{status:`missing`}):r===`ownership-lost`?{status:`unreattachable`,reason:`ownership-fence-lost`}:{status:`unreattachable`,reason:`transport-not-reattachable`}}async function M(e,t){if(!t)return{status:`cleanup-pending`,reason:`manual-recovery-required`,message:`App-log process marker path is missing`};let n=await N(e,t);if(n.status===`missing`)return{status:`already-missing`};if(n.status===`invalid`)return{status:`cleanup-pending`,reason:`manual-recovery-required`,message:n.message};let r=await e.processes.inspect(n.marker);if(r===`ownership-lost`)return P();if(r===`missing`)return await e.processes.clearMarker(t),{status:`already-missing`};let i=await e.processes.terminate(n.marker);return i===`ownership-lost`?P():(await e.processes.clearMarker(t),{status:i===`terminated`?`cleaned`:`already-missing`})}async function N(e,t){return t?await e.processes.readMarker(t):{status:`invalid`,message:`App-log process marker path is missing`}}function P(){return{status:`cleanup-pending`,reason:`ownership-fence-lost`}}async function Se(e){let t=e.initialProcess;for(;!e.stopped();){if(t){await Ce(e,t),t=void 0,await Ae(e);continue}let n=await je(e);if(n.status===`stopped`)return;n.status!==`waiting`&&(t=n.process)}}async function Ce(e,t){let{process:n}=t;e.setActive(n);try{e.setState(`active`),await we(e,t)}finally{await F(e,n)}}async function we(e,t){let n=Te(t.process);try{await Ee(e,t,n),await Oe(e,t.process,n),await ke(n.outcome)}finally{n.controller.abort()}}function Te(e){let t=new AbortController,n=!1,r=()=>{n=!0,t.abort()};return{controller:t,outcome:e.wait.then(()=>(r(),{status:`exited`}),e=>(r(),{status:`failed`,error:e})),settled:()=>n}}async function Ee(e,t,n){for(;!e.stopped()&&!n.settled();){if(!await De(e,n))return;let r=await e.resolvePid();if(e.stopped())return;if(r!==t.pid){await t.process.terminate();return}}}async function De(e,t){try{await e.sleep(500,t.controller.signal)}catch(e){if(!t.settled())throw e}return!t.settled()}async function Oe(e,t,n){e.stopped()&&!n.settled()&&await t.terminate()}async function ke(e){let t=await e;if(t.status===`failed`)throw t.error}async function Ae(e){e.stopped()||(e.setState(`recovering`),await e.sleep(500))}async function je(e){let t=await e.resolvePid();if(e.stopped())return{status:`stopped`};if(!t)return e.setState(`recovering`),await e.sleep(1e3),{status:`waiting`};let n=await e.startProcess(t);return e.setActive(n),e.stopped()?(await Me(e,n),{status:`stopped`}):{status:`started`,process:{pid:t,process:n}}}async function Me(e,t){try{await t.terminate(),await t.wait}finally{await F(e,t)}}async function F(e,t){try{await t[Symbol.asyncDispose]()}finally{e.setActive(void 0)}}async function Ne(e){let t=await e.resolvePid(e.setupSignal);e.setupSignal.throwIfAborted();let n=await e.host.outputs.openAppend(e.outputPath),r=`recovering`,i=!1,a;try{if(e.setupSignal.throwIfAborted(),t){e.setupSignal.throwIfAborted();let i=new AbortController,o=()=>i.abort(e.setupSignal.reason);e.setupSignal.addEventListener(`abort`,o,{once:!0});try{a=await e.processStart({command:e.command(t),output:n,markerPath:e.pidPath},i.signal)}finally{e.setupSignal.removeEventListener(`abort`,o)}e.setupSignal.throwIfAborted(),r=`active`}}catch(e){throw await I([async()=>await a?.terminate(),async()=>{await a?.wait},async()=>await a?.[Symbol.asyncDispose](),async()=>await n[Symbol.asyncDispose]()]),e}let o=Se({initialProcess:a&&t?{pid:t,process:a}:void 0,stopped:()=>i,setActive:e=>{a=e},setState:e=>{r=e},resolvePid:async()=>await e.resolvePid(),startProcess:async t=>await e.processStart({command:e.command(t),output:n,markerPath:e.pidPath}),sleep:async(t,n)=>await e.host.clock.sleep(t,n)}).catch(()=>{r=`failed`}),s,c=async()=>s??=Pe({options:e,monitor:o,active:()=>a,stop:()=>{i=!0},setState:e=>{r=e},output:n}),l=e.host.clock.now();return E({inspect:()=>({backend:e.backend,state:r,startedAt:l}),finish:c})}async function Pe(e){return e.stop(),(await I([async()=>await e.active()?.terminate(),async()=>await e.monitor,async()=>await e.output[Symbol.asyncDispose]()])).length>0?(e.setState(`failed`),{status:`cleanup-pending`,reason:`transport-failed`,message:e.options.cleanupFailureMessage}):(e.setState(`ended`),{status:`completed`,result:{backend:e.options.backend,outputPath:e.options.outputPath,completedAt:e.options.host.clock.now()}})}async function I(e){let t=[];for(let n of e)try{await n()}catch(e){t.push(e)}return t}function L(e,t,n){let r=e.artifacts.resolveSession(t);return n.outputPath===r.outputPath&&(n.pidPath===void 0||n.pidPath===r.pidPath)}function R(t,n){if(!L(t,n.sessionId,n))throw new e(`INVALID_ARGS`,`App-log paths do not match the owning session`)}const z=Object.freeze({available:!0});async function Fe(e,t,n){let r=(await e.commands.run(t,n)).stdout.trim().split(/\s+/)[0]??``;return/^\d+$/.test(r)?r:``}function Ie(n,i){let a=r(i.family);return Object.freeze({owner:a,ownsDevice:e=>e.platform===i.family,bind:async r=>{if(r.intent.kind===`exact-owner`&&!t(r.intent.owner,a))throw new e(`UNSUPPORTED_OPERATION`,`${i.label} app-log owner identity does not match`);if(r.device.platform!==i.family)throw new e(`UNSUPPORTED_PLATFORM`,`${i.label} app-log owner cannot bind ${r.device.platform}`);let o=await n.processTransports.resolve(r.device);return Le(n,r.device,r.scope.signal,o,a,i)},shutdown:async()=>void 0})}function Le(e,t,n,r,i,a){let o=w({codec:a.codec,reattach:async(t,n)=>L(e,n.sessionId,t)?await j(e,t.pidPath):{status:`unreattachable`,reason:`descriptor-invalid`,message:`${a.label} app-log descriptor paths do not match the owning session`},cleanup:async(t,n)=>L(e,n.sessionId,t)?await M(e,t.pidPath):{status:`cleanup-pending`,reason:`ownership-fence-lost`,message:`${a.label} app-log descriptor paths do not match the owning session`}}),s=Object.freeze({appLogInspect:async()=>({backend:a.backend}),appLogDoctor:async({appBundleId:r})=>await a.doctor({host:e,device:t,signal:n},r),...r.start?{appLogStart:async o=>await ze(e,t,n,r,i,o,a)}:{},...o});return Object.freeze({device:t,owner:i,facts:Re(t,r,a),operations:s,[Symbol.asyncDispose]:async()=>void 0})}function Re(e,t,n){let r=t.start?z:{available:!1,reason:`owner-capability-missing`,hint:n.startUnavailableHint};return Object.freeze({device:{family:n.family,kind:e.kind,...e.target===void 0?{}:{target:e.target},providerMode:t.mode},operations:{appLogInspect:z,appLogDoctor:z,appLogStart:r,appLogReattach:z,appLogCleanup:z}})}async function ze(t,n,r,i,a,o,s){if(!i.start)throw new e(`UNSUPPORTED_OPERATION`,s.startUnavailableHint);R(t,o);let c=t.artifacts.resolveSession(o.sessionId),l={host:t,device:n,signal:r,input:o,artifacts:c,transport:i};s.validateStart?.(l),r.throwIfAborted();let u=await s.process(l);r.throwIfAborted();let d=await Ne({host:t,backend:s.backend,outputPath:c.outputPath,pidPath:c.pidPath,processStart:i.start,setupSignal:r,resolvePid:u.resolvePid,command:u.command,cleanupFailureMessage:s.cleanupFailureMessage}),f=s.descriptor({artifacts:c,transport:i});return C(d,s.envelope({input:o,device:n,owner:a,descriptor:f}))}async function Be(e,t){try{return await e()}catch{if(t?.aborted)throw t.reason;return!1}}function Ve(e){return e.exitCode===0}function He(n,i){let a=r(n),o=V(i);return Object.freeze({owner:a,ownsDevice:e=>e.platform===n,bind:async r=>{if(r.intent.kind===`exact-owner`&&!t(r.intent.owner,a))throw new e(`UNSUPPORTED_OPERATION`,`${n} platform runtime owner identity does not match`);if(r.device.platform!==n)throw new e(`UNSUPPORTED_PLATFORM`,`${n} platform runtime cannot bind ${r.device.platform}`);return B(r.device,a,o)},shutdown:async()=>void 0})}function B(e,t,n){let{appLog:r,network:i,screenRecording:a}=V(n),s=Object.freeze({device:{...o(e),providerMode:t.kind===`local-family`?`local`:`provider-runtime`},operations:{appLogInspect:r,appLogDoctor:r,appLogStart:r,appLogReattach:r,appLogCleanup:r,networkDump:i,screenRecordingStart:a,screenRecordingReattach:a,screenRecordingCleanup:a}});return Object.freeze({device:e,owner:t,facts:s,operations:Object.freeze({}),[Symbol.asyncDispose]:async()=>void 0})}function V(e){return Object.freeze({appLog:Object.freeze({...e.appLog}),network:Object.freeze({...e.network}),screenRecording:Object.freeze({...e.screenRecording??e.network})})}function H(e){for(let t of[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i]){let n=t.exec(e);if(!n)continue;let r=Number.parseInt(n[1]??``,10);if(Number.isInteger(r))return r}return null}function U(e){return/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e)?.[0]??/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e)?.[0]}function Ue(e){let t=e.indexOf(`{`),n=e.lastIndexOf(`}`);if(t<0||n<=t)return null;try{let r=JSON.parse(e.slice(t,n+1));return r&&typeof r==`object`&&!Array.isArray(r)?r:null}catch{return null}}function W(e,t){for(let n of t){let t=e?.[n];if(typeof t==`string`&&t.trim())return t.trim()}}function We(e,t){for(let n of t){let t=e?.[n];if(typeof t==`number`&&Number.isInteger(t))return t;if(typeof t==`string`&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t,10)}return null}function Ge(e,t){let n=t?.headers??t?.requestHeaders??t?.responseHeaders;return n===void 0?/\bheaders?["'=: ]+(\{.*\})/i.exec(e)?.[1]?.trim():K(n)}function G(e,t,n){for(let r of n){if(t?.[r]!==void 0)return K(t[r]);let n=r.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),i=RegExp(`\\b${n}["'=: ]+(.+)$`,`i`).exec(e);if(i?.[1])return i[1].trim()}}function K(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function Ke(e,t,n){let r=Y(t,n,5),i=e.packetId??r.map(q).find(e=>typeof e==`string`&&e.length>0);i&&(e.packetId=i);let a=i?Y(t,n,12).filter(e=>q(e)===i):r;e.timestamp??=a.map(U).find(e=>typeof e==`string`&&e.length>0),e.status??=a.map(H).find(e=>typeof e==`number`)??void 0,e.durationMs??=a.map(J).find(e=>typeof e==`number`)??void 0}function q(e){return/\bpacket id (\d+)\b/i.exec(e)?.[1]??null}function J(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);return t?Number.parseInt(t[1]??``,10):null}function Y(e,t,n){return e.slice(Math.max(0,t-n),Math.min(e.length,t+n+1)).map(e=>e.trim()).filter(Boolean)}const qe=RegExp(`\\b(${[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`HEAD`,`OPTIONS`].join(`|`)})\\b\\s+https?:\\/\\/`,`i`),Je=/https?:\/\/[^\s"'<>\])]+/i;function Ye(e,t,n=e.limits.maxEntries){let r=[...e.entries],i=new Set(r.map(Z));for(let e of t.entries){let t=Z(e);if(!i.has(t)&&(i.add(t),r.push(e),r.length>=n))break}return Object.freeze({...e,matchedLines:r.length,entries:Object.freeze(r)})}function Xe(e,t){let n=$(t.maxEntries,25,1,200),r=t.include??`summary`,i=$(t.maxPayloadChars,2048,64,16384),a=$(t.maxScanLines,4e3,100,2e4),o=Ze(t.lineNumberOffset);if(!t.exists)return Object.freeze({path:t.path,exists:!1,scannedLines:0,matchedLines:0,entries:Object.freeze([]),include:r,limits:Object.freeze({maxEntries:n,maxPayloadChars:i,maxScanLines:a})});let s=e.split(`
2
- `),c=Math.max(0,s.length-a),l=s.slice(c),u=[];for(let e=l.length-1;e>=0&&u.length<n;--e){if(!l[e]?.trim())continue;let n=X(l,e,o+c+e+1,t.backend,r,i);n&&u.push(n)}return Object.freeze({path:t.path,exists:!0,scannedLines:l.length,matchedLines:u.length,entries:Object.freeze(u),include:r,limits:Object.freeze({maxEntries:n,maxPayloadChars:i,maxScanLines:a})})}function Ze(e){if(e===void 0)return 0;if(!Number.isInteger(e)||e<0)throw TypeError(`Network line number offset must be a non-negative integer`);return e}function X(e,t,n,r,i,a){let o=e[t]?.trim();if(!o)return null;let s=Ue(o),c=Qe(o,s);if(!c)return null;let l=rt(o,n,c,a);return r===`android`&&Ke(l,e,t),it(l,o,s,i,a),l}function Qe(e,t){let n=$e(e,t),r=et(e,t);if(!r)return null;let i=tt(e,t);return nt(e,n.explicit,i)?{method:n.value,url:r,status:i}:null}function $e(e,t){let n=W(t,[`method`,`httpMethod`]),r=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e)?.[1],i=qe.exec(e)?.[1],a=n??r??i;return{value:a?.toUpperCase(),explicit:!!a}}function et(e,t){return W(t,[`url`,`requestUrl`])??Je.exec(e)?.[0]}function tt(e,t){return We(t,[`status`,`statusCode`,`responseCode`])??H(e)??void 0}function nt(e,t,n){return t||n!==void 0||/\bURL["'=: ]+https?:\/\//i.test(e)||/\bheaders?["'=: ]+/i.test(e)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(e)}function rt(e,t,n,r){return{...n,timestamp:U(e),packetId:q(e)??void 0,durationMs:J(e)??void 0,raw:Q(e,r),line:t}}function it(e,t,n,r,i){if(at(r)){let r=Ge(t,n);r&&(e.headers=Q(r,i))}if(ot(r)){let r=G(t,n,[`requestBody`,`body`,`payload`,`request`]),a=G(t,n,[`responseBody`,`response`]);r&&(e.requestBody=Q(r,i)),a&&(e.responseBody=Q(a,i))}}function at(e){return e===`headers`||e===`all`}function ot(e){return e===`body`||e===`all`}function Z(e){return`${e.timestamp??``}|${e.method??``}|${e.url}|${e.status??``}|${e.raw}`}function Q(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function $(e,t,n,r){return e===void 0||!Number.isInteger(e)?t:Math.max(n,Math.min(r,e))}export{re as S,w as _,Ve as a,ie as b,Fe as c,M as d,j as f,E as g,be as h,He as i,L as l,O as m,Xe as n,Be as o,k as p,B as r,Ie as s,Ye as t,R as u,C as v,h as x,_e as y};
1
+ import{_ as e,x as t}from"./sdk-contracts.js";import{Ot as n}from"./sdk-batch-runner.js";import{_ as r,a as i}from"./sdk-device.js";import{z as a}from"./interaction.js";import{a as o}from"./sdk-remote-config.js";import{i as s,r as c}from"./device.js";import{t as l}from"./bounds.js";import{t as u}from"./parser.js";import d from"node:path";import ee from"node:fs";import f from"node:fs/promises";import{setTimeout as p}from"node:timers/promises";const m={support:`supported`},h={support:`unsupported`},te={lease:m,inventory:{support:`partial`,note:`Inventory exposes only the leased cloud device, not the provider catalog.`},install:{support:`partial`,note:`Requires provider-specific upload or a path visible to the remote Appium server.`},snapshot:{support:`partial`,note:`Uses Appium page source XML, not agent-device native snapshot backends.`},screenshot:m,tap:m,doubleTap:m,longPress:m,swipe:m,scroll:{support:`partial`,note:`Implemented as viewport-relative W3C pointer gestures.`},fill:m,type:m,back:m,home:{support:`partial`,note:`Uses provider/Appium mobile pressButton support where available.`},orientation:{support:`partial`,note:`Uses the WebDriver rotation/orientation endpoints; four-way rotation collapses to portrait/landscape on drivers that only accept the two-way endpoint. Rotates the current display, so an activity that does not pin its orientation may need rotating again once it is foreground.`},appSwitcher:{support:`partial`,note:`Uses provider/Appium mobile pressButton support where available.`},tvRemote:h,"clipboard.read":{support:`partial`,note:`Uses provider/Appium clipboard extension support where available.`},"clipboard.write":{support:`partial`,note:`Uses provider/Appium clipboard extension support where available.`},settings:h,pinch:h,rotateGesture:h,transformGesture:h,logs:h,record:h,artifacts:h,portReverse:h,nativeSnapshotBackend:{support:`unsupported`,note:`Cloud WebDriver cannot upload or run agent-device native runner/helper backends.`}};function ne(e){return{provider:e.provider,platform:e.platform,snapshotBackend:e.platform===`ios`?`xctest`:`android`,snapshotSource:`appium-page-source`,operations:re(te,e.overrides)}}function g(e,t){return e.operations[t].support!==`unsupported`}function _(e,t){let n=e.operations[t],r=n.note?` ${n.note}`:``;return`${e.provider} WebDriver runtime does not support ${t}.${r}`}function re(e,t){let n={...e};for(let[r,i]of Object.entries(t??{}))n[r]=typeof i==`string`?{...e[r],support:i}:{...e[r],...i};return n}function ie(e,t){let n=e?.bundleId??t?.appIdentifierHint,r=e?.packageName??t?.packageNameHint;return{bundleId:n,packageName:r,appName:e?.appName,launchTarget:oe(e?.launchTarget,n,r)}}function ae(e){return e===`ios`?`xctest`:`android`}function oe(...e){return e.find(e=>e!==void 0)}function se(e){let t=async(t,n,r,i,a)=>{let o=e.findSessionForDevice(t);if(!o)return;let s=await le(e,o,t,n,r,i,a);return await o.client.installApp(s?.appReference??r,a),ie(s,i)};return Object.freeze({fact:t=>ce(e.findSessionForDevice(t)),installApp:t,installInstallablePath:async(e,n,r,i)=>await t(e,``,n,r,i),deployApp:async(e,n,r)=>ue(await t(e,n.app,n.appPath,{relaunch:n.replaceExisting,appIdentifierHint:n.app,packageNameHint:n.app},r),n.app),deployMaterializedApp:async(e,n,r)=>ue(await t(e,``,n.artifact.installablePath,{appIdentifierHint:n.artifact.bundleId,packageNameHint:n.artifact.packageName},r))})}function ce(e){return e?g(e.capabilities,`install`)?Object.freeze({available:!0}):Object.freeze({available:!1,reason:`owner-capability-missing`,hint:_(e.capabilities,`install`)}):Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The WebDriver provider session is no longer active for this device.`})}async function le(t,n,i,a,o,s,c){if(!g(n.capabilities,`install`))throw new e(`UNSUPPORTED_OPERATION`,_(n.capabilities,`install`),{provider:t.provider,deviceId:i.id,platform:r(i)});let l=n.prepared.uploadApp??t.uploadApp;if(l)return await l({provider:t.provider,lease:n.lease,device:i,app:a,appPath:o,options:s,signal:c})}function ue(t,n){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The WebDriver provider session no longer supports app deployment.`);return{...t.bundleId?{bundleId:t.bundleId}:{},...t.packageName?{packageName:t.packageName}:{},...t.appName?{appName:t.appName}:{},...t.launchTarget??n?{launchTarget:t.launchTarget??n}:{}}}function v(e){return{provider:e.provider,providerSessionId:e.providerSessionId,status:e.artifacts.length>0?`ready`:`pending`,cloudArtifacts:e.artifacts,...e.artifacts.length>0?{}:{message:e.pendingMessage}}}function de(e){return{provider:e.provider,providerSessionId:e.providerSessionId,status:`unavailable`,cloudArtifacts:[],message:e.error instanceof Error?e.error.message:String(e.error)}}function y(e){return{"x-agent-device-client":`agent-device-cli`,"x-agent-device-version":e}}async function fe(n,r){try{await r()}catch(r){n instanceof e&&(n.details={...n.details,cleanupError:t(r)})}}function pe(e,t){return typeof e==`function`?e(t):e}function b(e){return`Basic ${Buffer.from(`${e.username}:${e.accessKey}`).toString(`base64`)}`}function me(e){let t=0;for(;t<e.length&&e.charCodeAt(t)===47;)t+=1;return t===0?e:e.slice(t)}function he(e){let t=e.length-1;for(;t>=0&&e.charCodeAt(t)===47;)--t;return t===e.length-1?e:e.slice(0,t+1)}function ge(e){if(e.pathname.endsWith(`/`))return e;let t=new URL(e);return t.pathname=`${t.pathname}/`,t}const _e=`webdriver_request_timeout`;function ve(t){return t instanceof e&&t.details?.reason===_e}var ye=class{endpoint;headers;requestPolicy;constructor(e){this.endpoint=ge(new URL(e.endpoint)),this.headers={...y(e.clientVersion),...e.auth?{Authorization:b(e.auth)}:{},...e.headers},this.requestPolicy={timeoutMs:e.requestPolicy?.timeoutMs??3e4,retryAttempts:e.requestPolicy?.retryAttempts??1,retryDelayMs:e.requestPolicy?.retryDelayMs??250}}async requestValue(e,t,n,r){return await this.requestValueWithRetries(e,t,n,{retryAttempts:r?.retryAttempts??this.requestPolicy.retryAttempts,timeoutMs:r?.timeoutMs??this.requestPolicy.timeoutMs,signal:r?.signal})}async requestValueWithRetries(e,t,n,r){let i;for(let a=0;a<=r.retryAttempts;a+=1)try{return await this.requestValueOnce(e,t,n,r.timeoutMs,r.signal)}catch(e){if(i=e,!be(e,a,r.retryAttempts,r.signal))throw e;await p(this.requestPolicy.retryDelayMs,void 0,{signal:r.signal})}throw i}async requestValueOnce(e,t,n,r,i){let{ok:a,status:o,text:s}=await this.fetchWebDriver(e,t,n,r,i),c=s?Se(s):{};if(!a)throw Ce(o,c);return xe(c)}async fetchWebDriver(e,t,n,r,i){let a=AbortSignal.timeout(r),o=i?AbortSignal.any([i,a]):a;try{let r=await fetch(new URL(me(t),this.endpoint),{method:e,headers:{Accept:`application/json`,...n===void 0?{}:{"Content-Type":`application/json`},...this.headers},body:n===void 0?void 0:JSON.stringify(n),signal:o});return{ok:r.ok,status:r.status,text:await r.text()}}catch(n){throw a.aborted&&!i?.aborted?we(e,t,r,n):n}}};function be(e,t,n,r){return!r?.aborted&&Te(e)&&t<n}function xe(e){if(!e||typeof e!=`object`)return e;let t=e;return`value`in t?t.value:e}function Se(t){try{return JSON.parse(t)}catch(n){throw new e(`COMMAND_FAILED`,`WebDriver response was not valid JSON.`,{text:t},n)}}function Ce(t,n){let r=n&&typeof n==`object`&&`value`in n?n.value:n;return new e(`COMMAND_FAILED`,r&&typeof r==`object`&&typeof r.message==`string`?r.message:`WebDriver request failed with HTTP ${t}.`,{status:t,response:n})}function we(t,n,r,i){return new e(`COMMAND_FAILED`,`WebDriver ${t} ${n} timed out after ${r}ms.`,{reason:_e,method:t,path:n,timeoutMs:r},i instanceof Error?i:void 0)}function Te(t){if(ve(t))return!0;if(t instanceof e){let e=t.details?.status;return typeof e==`number`&&e>=500}return t instanceof TypeError}var Ee=class{transport;sessionCreateTimeoutMs;sessionId;constructor(e){this.transport=new ye(e),this.sessionCreateTimeoutMs=e.requestPolicy?.sessionCreateTimeoutMs??18e4}async createSession(e,t){let n=ke(await this.requestValue(`POST`,`/session`,{capabilities:Oe(e)},{retryAttempts:0,timeoutMs:Ne(this.sessionCreateTimeoutMs,t?.deadline)}));return this.sessionId=n.sessionId,n}async deleteSession(){let e=this.requireSessionId();await this.requestValue(`DELETE`,`/session/${e}`),this.sessionId=void 0}async installApp(e,t){await this.sessionRequest(`POST`,`/appium/device/install_app`,{appPath:e},{signal:t})}async activateApp(e){try{await this.sessionRequest(`POST`,`/appium/device/activate_app`,{appId:e})}catch{await this.executeScript(`mobile: activateApp`,[{appId:e,bundleId:e}])}}async terminateApp(e){try{await this.sessionRequest(`POST`,`/appium/device/terminate_app`,{appId:e})}catch{await this.executeScript(`mobile: terminateApp`,[{appId:e,bundleId:e}])}}async performActions(e){await this.sessionRequest(`POST`,`/actions`,{actions:e})}async releaseActions(){await this.sessionRequest(`DELETE`,`/actions`,void 0,{retryAttempts:0})}async sendKeys(e){await this.sessionRequest(`POST`,`/keys`,{value:Array.from(e)})}async hideKeyboard(){await this.sessionRequest(`POST`,`/appium/device/hide_keyboard`,void 0,{retryAttempts:0})}async isKeyboardShown(e){let t;try{t=await this.sessionRequest(`GET`,`/appium/device/is_keyboard_shown`,void 0,{retryAttempts:0,...e===void 0?{}:{timeoutMs:e}})}catch(e){if(C(e))return`unsupported`;throw e}return typeof t==`boolean`?t:`unsupported`}async activeElement(e){let t=e===void 0?void 0:Date.now()+e,n;try{n=Me(await this.sessionRequest(`GET`,`/element/active`,void 0,S(t)))}catch(e){if(C(e))return`unsupported`;if(Fe(e))return`none`;throw e}if(n===void 0)return`unsupported`;try{let e=await this.sessionRequest(`GET`,`/element/${encodeURIComponent(n)}/rect`,void 0,S(t));return{id:n,rect:De(e)}}catch(e){if(C(e))return`unsupported`;if(Fe(e))return`none`;throw e}}async back(){await this.sessionRequest(`POST`,`/back`)}async setRotation(e){await this.sessionRequest(`POST`,`/rotation`,{x:0,y:0,z:e})}async setOrientation(e){await this.sessionRequest(`POST`,`/orientation`,{orientation:e})}async source(){let t=await this.sessionRequest(`GET`,`/source`);if(typeof t!=`string`)throw new e(`COMMAND_FAILED`,`WebDriver source response was not a string`,{valueType:typeof t});return t}async screenshot(t){let n=await this.sessionRequest(`GET`,`/screenshot`);if(typeof n!=`string`)throw new e(`COMMAND_FAILED`,`WebDriver screenshot response was not base64 text`,{valueType:typeof n});await f.writeFile(t,Buffer.from(n,`base64`))}async windowRect(){return De(await this.sessionRequest(`GET`,`/window/rect`))}async executeScript(e,t=[]){return await this.sessionRequest(`POST`,`/execute/sync`,{script:e,args:t})}async sessionRequest(e,t,n,r){let i=this.requireSessionId();return await this.requestValue(e,`/session/${i}${t}`,n,r)}requireSessionId(){if(!this.sessionId)throw new e(`SESSION_NOT_FOUND`,`WebDriver session has not been created yet.`);return this.sessionId}async requestValue(e,t,n,r){return await this.transport.requestValue(e,t,n,r)}};function De(t){if(!t||typeof t!=`object`)throw new e(`COMMAND_FAILED`,`WebDriver window rect response was empty.`);let n=t,r={x:x(n,`x`),y:x(n,`y`),width:x(n,`width`),height:x(n,`height`)};if(r.x===void 0||r.y===void 0||r.width===void 0||r.height===void 0)throw new e(`COMMAND_FAILED`,`WebDriver window rect response was invalid.`,{response:n});return r}function x(e,t){let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function Oe(e){return`alwaysMatch`in e||`firstMatch`in e?e:{alwaysMatch:e}}function ke(t){if(!t||typeof t!=`object`)throw new e(`COMMAND_FAILED`,`WebDriver create-session response was empty.`);let n=t,r=typeof n.sessionId==`string`?n.sessionId:typeof n.session_id==`string`?n.session_id:void 0;if(!r)throw new e(`COMMAND_FAILED`,`WebDriver create-session response missed sessionId.`,{response:n});return{sessionId:r,capabilities:n.capabilities&&typeof n.capabilities==`object`?n.capabilities:{}}}const Ae=new Set([405,501]),je=new Set([`unknown command`,`unknown method`]);function Me(e){if(!e||typeof e!=`object`)return;let t=e,n=t[`element-6066-11e4-a52e-4f735466cecf`]??t.ELEMENT;return typeof n==`string`&&n.length>0?n:void 0}function S(e){return e===void 0?{retryAttempts:0}:{retryAttempts:0,timeoutMs:Pe(e)}}function Ne(e,t){return t===void 0?e:Math.min(e,Pe(t))}function Pe(e){return Math.max(0,e-Date.now())}function Fe(t){return t instanceof e?w(t).toLowerCase()===`no such element`:!1}function C(t){if(!(t instanceof e))return!1;let n=t.details?.status;return typeof n==`number`&&Ae.has(n)?!0:je.has(w(t).toLowerCase())}function w(e){let t=e.details?.response,n=t&&typeof t==`object`?t.value:void 0,r=n&&typeof n==`object`?n.error:void 0;return typeof r==`string`?r:``}function T(e,t){return{type:`pointer`,id:e,parameters:{pointerType:`touch`},actions:t}}function E(t){let n;try{n=u(t)}catch(t){throw new e(`COMMAND_FAILED`,`Failed to parse WebDriver page source XML: ${t instanceof Error?t.message:String(t)}`,void 0,t)}let r=[];for(let e of n)D(r,e);return r}function D(e,t,n,r=0){let i=Object.keys(t.attributes).length===0?n:Ie(e,t,n,r),a=i===n?r:r+1;for(let n of t.children)D(e,n,i,a)}function Ie(e,t,n,r){let i=e.length;return e.push(Le(i,t.name,t.attributes,n,r)),i}function Le(e,t,n,r,i){let a=Re(n),o=A(n.enabled,!0),s=A(n.displayed??n.visible,!0);return{index:e,type:t,role:ze(t,n),label:O(n,[`content-desc`,`label`,`text`,`name`]),value:k(n.value),identifier:O(n,[`resource-id`,`id`,`accessibility-id`,`name`]),rect:a,enabled:o,selected:A(n.selected),focused:A(n.focused),visibleToUser:s,hittable:s&&o&&a!==void 0&&a.width>0&&a.height>0,depth:i,parentIndex:r}}function Re(e){let t=l(e.bounds??null);if(t)return t;let n=j(e.x),r=j(e.y),i=j(e.width),a=j(e.height);if(!(n===void 0||r===void 0||i===void 0||a===void 0))return{x:n,y:r,width:i,height:a}}function O(e,t){for(let n of t){let t=k(e[n]);if(t!==void 0)return t}}function k(e){return e||void 0}function A(e,t=!1){return e===void 0?t:e===`true`||e===`1`}function j(e){if(e===void 0||e===``)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function ze(e,t){return k(t.class)??k(e.replace(/^XCUIElementType/,``).toLowerCase())}function Be(e){let t=E(e).flatMap(e=>Ve(e)&&He(e.rect)?[e.rect]:[]).sort((e,t)=>t.width*t.height-e.width*e.height)[0];return t?{x:t.x,y:t.y,width:t.width,height:t.height}:void 0}function Ve(e){let t=e.type?.toLowerCase()??``;return e.visibleToUser!==!1&&(t.includes(`scrollview`)||t.includes(`listview`)||t.includes(`recyclerview`))}function He(e){return!!e&&e.width>=50&&e.height>=50}async function Ue(t,n,r){let i=[];for(let e of n===`android`?[`rotation`,`orientation`]:[`orientation`,`rotation`])try{await Je(t,e,r);return}catch(t){if(!Ke(t))throw t;i.push({transport:e,error:t instanceof Error?t.message:String(t)})}throw new e(`COMMAND_FAILED`,`Could not set device orientation to ${r} on the hosted WebDriver session.`,{hint:`The provider driver rejected both orientation endpoints. Set the orientation as a session capability instead, for example connect --provider-device-orientation portrait.`,rotation:r,attempts:i})}const We=new Set([`unknown command`,`unknown method`]),Ge=new Set([404,405]);function Ke(t){if(!(t instanceof e)||t.code===`SESSION_NOT_FOUND`)return!1;let n=qe(t.details?.response);if(n)return We.has(n);let r=t.details?.status;return typeof r==`number`&&Ge.has(r)}function qe(e){if(!e||typeof e!=`object`)return``;let t=e.value;if(!t||typeof t!=`object`)return``;let n=t.error;return typeof n==`string`?n:``}async function Je(e,t,n){if(t===`rotation`){await e.setRotation(s(n));return}await e.setOrientation(c(n))}const M=1500;function Ye(e){return new Promise(t=>setTimeout(t,e))}function N(t,n,r){return new e(`COMMAND_FAILED`,`fill tapped (${t}, ${n}) but ${r}`,{reason:`text_entry_focus_not_observed`,x:t,y:n,hint:`The tap most likely missed the field. Re-check the target with snapshot -i and fill the element it reports, rather than retrying the same coordinates.`})}function Xe(t,n){return new e(`COMMAND_FAILED`,`fill tapped (${t}, ${n}) but this driver reports neither the focused element nor keyboard state, so the text was not sent`,{reason:`text_entry_focus_unobservable`,x:t,y:n,hint:`This provider cannot confirm a field took focus. Use press <target> followed by type <text> to enter it anyway, accepting that nothing witnesses which field receives the keys.`})}function Ze(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function Qe(e){return new $e(e.client,e.backend,e.capabilities)}var $e=class{client;backend;capabilities;constructor(e,t,n){this.client=e,this.backend=t,this.capabilities=n}async open(e,t){if(t?.url){await this.client.executeScript(`mobile: deepLink`,[{url:t.url,package:e}]);return}let n=t?.appBundleId??e;n&&await this.client.activateApp(n)}async openDevice(){await this.client.executeScript(`mobile: activateApp`,[{}])}async close(e){e&&await this.client.terminateApp(e)}async tap(e,t){return this.requireSupport(`tap`),await this.pointerGesture(`tap`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t}}async doubleTap(e,t){return this.requireSupport(`doubleTap`),await this.pointerGesture(`doubleTap`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0},{type:`pause`,duration:80},{type:`pointerDown`,button:0},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t}}async swipe(e,t,n,r,i=400){return this.requireSupport(`swipe`),await this.pointerGesture(`swipe`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pointerMove`,duration:i,x:n,y:r},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x1:e,y1:t,x2:n,y2:r,durationMs:i}}async longPress(e,t,n=600){return this.requireSupport(`longPress`),await this.pointerGesture(`longPress`,[{type:`pointerMove`,duration:0,x:e,y:t},{type:`pointerDown`,button:0},{type:`pause`,duration:n},{type:`pointerUp`,button:0}]),{backend:`webdriver`,x:e,y:t,durationMs:n}}async focus(e,t){return await this.tap(e,t)}async type(e){this.requireSupport(`type`),await this.client.sendKeys(e)}async fill(e,t,n,r){this.requireSupport(`fill`);let i=await this.readTextEntryState();await this.tap(e,t);let a=await this.awaitTextEntryReadiness(i,e,t);return await this.type(n),{backend:`webdriver`,x:e,y:t,text:n,textEntryReadiness:a}}async scroll(e,t){this.requireSupport(`scroll`);let n=t?.durationMs??350;await this.client.hideKeyboard().catch(()=>void 0);let r=await this.scrollGestureFrame(),i=a({direction:e,amount:t?.amount,pixels:t?.pixels,referenceWidth:r.width,referenceHeight:r.height}),o={...i,x1:i.x1+r.x,y1:i.y1+r.y,x2:i.x2+r.x,y2:i.y2+r.y};return await this.swipe(o.x1,o.y1,o.x2,o.y2,n),{backend:`webdriver`,...o,distance:i.pixels,durationMs:n}}async gestureViewport(){return await this.scrollGestureFrame()}async performGesture(e){return this.requireSupport(tt(e)),await this.client.performActions(e.pointers.map(e=>T(`gesture-pointer-${e.pointerId}`,et(e.samples)))),await this.client.releaseActions().catch(()=>void 0),{backend:`webdriver-w3c-actions`}}async screenshot(e,t){this.requireSupport(`screenshot`),await this.client.screenshot(e)}async snapshot(e){return this.requireSupport(`snapshot`),{backend:this.backend,nodes:E(await this.client.source())}}async back(e){this.requireSupport(`back`),await this.client.back()}async home(){this.requireSupport(`home`),await this.client.executeScript(`mobile: pressButton`,[{name:`home`}])}async setOrientation(e){this.requireSupport(`orientation`),await Ue(this.client,this.backend,e)}async appSwitcher(){this.requireSupport(`appSwitcher`),await this.client.executeScript(`mobile: pressButton`,[{name:`appSwitch`}])}async tvRemote(e,t){this.unsupported(`tvRemote`)}async readClipboard(){this.requireSupport(`clipboard.read`);let e=await this.client.executeScript(`mobile: getClipboard`,[{}]);return typeof e==`string`?e:``}async writeClipboard(e){this.requireSupport(`clipboard.write`),await this.client.executeScript(`mobile: setClipboard`,[{content:e}])}async setSetting(e,t,n,r){this.unsupported(`settings`)}async awaitTextEntryReadiness(e,t,n){let r=e.keyboard,i=Date.now()+2e3,a=e.focusedElementId,o=await this.pollWithinBudget(i,async e=>{let r=await this.client.activeElement(e);return r===`unsupported`?`abandon`:r===`none`?`retry`:r.id!==a||Ze(r.rect,t,n)?`satisfied`:`retry`});if(o===`satisfied`)return`focused-element`;if(o===`expired`)throw N(t,n,`nothing there took text-entry focus, so the text was not sent`);if(r===`unsupported`)throw Xe(t,n);if(r)throw N(t,n,`the keyboard was already up and this driver cannot report which field holds focus, so the text was not sent`);if(await this.pollWithinBudget(i,async e=>await this.client.isKeyboardShown(e)===!0?`satisfied`:`retry`)===`satisfied`)return`keyboard-shown`;throw N(t,n,`no keyboard appeared, so the text was not sent`)}async readTextEntryState(){let[e,t]=await Promise.all([this.client.isKeyboardShown(M),this.client.activeElement(M)]);return{keyboard:e,focusedElementId:t===`none`||t===`unsupported`?void 0:t.id}}async pollWithinBudget(e,t){let n=!1,r;for(;;){let i=e-Date.now();if(i<=0)break;try{let e=await t(Math.min(M,i));if(n=!0,e!==`retry`)return e}catch(e){r=e}let a=e-Date.now();if(a<=0)break;await Ye(Math.min(100,a))}if(!n&&r!==void 0)throw r;return`expired`}async pointerGesture(e,t){await this.client.performActions([T(e,t)]),await this.client.releaseActions().catch(()=>void 0)}async scrollGestureFrame(){return await this.client.source().then(e=>Be(e)).catch(()=>void 0)||await this.client.windowRect()}requireSupport(e){g(this.capabilities,e)||this.unsupported(e)}unsupported(t){throw new e(`UNSUPPORTED_OPERATION`,_(this.capabilities,t),{provider:this.capabilities.provider,platform:this.capabilities.platform,operation:t})}};function et(t){let n=t[0];if(!n)throw new e(`INVALID_ARGS`,`WebDriver gesture pointer requires samples`);let r=[{type:`pointerMove`,duration:0,x:n.point.x,y:n.point.y},{type:`pointerDown`,button:0}];for(let e=1;e<t.length;e+=1){let n=t[e-1],i=t[e];r.push({type:`pointerMove`,duration:i.offsetMs-n.offsetMs,x:i.point.x,y:i.point.y})}return r.push({type:`pointerUp`,button:0}),r}function tt(e){if(e.topology===`single`)return`swipe`;switch(e.intent){case`pan`:case`transform`:return`transformGesture`;case`pinch`:return`pinch`;case`rotate`:return`rotateGesture`}}var nt=class{sessionsByLeaseId=new Map;ownedDeviceIds=new Set;releasedProviderSessionIdsByLeaseId=new Map;options;constructor(e){this.options=e}ownsDevice(e){return this.ownedDeviceIds.has(e.id)}findSessionForDevice(e){return[...this.sessionsByLeaseId.values()].find(t=>t.device.id===e.id)}findSessionForLease(e){return this.sessionsByLeaseId.get(e)}getInteractor(e){return this.findSessionForDevice(e)?.interactor}heartbeat(e){if(e.leaseProvider===this.options.provider&&this.sessionsByLeaseId.has(e.leaseId))return{provider:this.options.provider}}async allocate(e,t){if(e.leaseProvider!==this.options.provider)return;if(this.sessionsByLeaseId.has(e.leaseId))return this.heartbeat(e);let n=await this.prepareSession(e,t),r=new Ee({clientVersion:this.options.clientVersion,endpoint:n.endpoint,auth:n.auth,headers:n.headers,requestPolicy:this.options.requestPolicy}),i=await this.createSessionWithPreparedCleanup(r,n,e,t),a=this.deviceForLease(e,n),o=n.providerSessionId??i.sessionId,s=ne({provider:this.options.provider,platform:n.platform,overrides:this.options.capabilityOverrides});return this.sessionsByLeaseId.set(e.leaseId,Object.freeze({lease:e,device:a,client:r,prepared:n,capabilities:s,webDriverSessionId:i.sessionId,providerSessionId:o,interactor:Qe({client:r,backend:ae(n.platform),capabilities:s})})),this.ownedDeviceIds.add(a.id),{provider:this.options.provider,deviceId:a.id,sessionId:i.sessionId,providerSessionId:o,capabilities:s,...n.providerData}}async release(e){if(e.leaseProvider!==this.options.provider)return;let t=this.sessionsByLeaseId.get(e.leaseId);if(!t)return;this.sessionsByLeaseId.delete(e.leaseId),this.releasedProviderSessionIdsByLeaseId.set(e.leaseId,t.providerSessionId);let n=await this.closeSession(t),r=await this.safeListArtifacts(t);return{provider:this.options.provider,providerSessionId:t.providerSessionId,...n.cleanup,...n.warnings.length>0?{warnings:n.warnings}:{},...r?{cloudArtifacts:r}:{}}}async listCloudArtifacts(e){if(e.provider!==this.options.provider)return;let t=e.leaseId?this.sessionsByLeaseId.get(e.leaseId):void 0;if(t)return await this.safeListArtifacts(t);let n=e.providerSessionId??(e.leaseId?this.releasedProviderSessionIdsByLeaseId.get(e.leaseId):void 0);if(!(!n||!this.options.listArtifacts))return await this.options.listArtifacts({provider:this.options.provider,providerSessionId:n})}async shutdown(){await Promise.allSettled([...this.sessionsByLeaseId.values()].map(async e=>await this.closeSession(e))),this.sessionsByLeaseId.clear(),this.ownedDeviceIds.clear()}async createSessionWithPreparedCleanup(e,t,n,r){try{return await e.createSession(t.webdriverCapabilities,{deadline:r?.deadline})}catch(e){let r=ve(e)?rt(e,this.options.provider,n,t):e;throw await fe(r,()=>t.cleanup?.()),r}}async prepareSession(e,t){let n=this.baseSessionForLease(e);return this.options.prepareSession?await this.options.prepareSession({lease:e,req:t,base:n}):n}baseSessionForLease(e){let t=typeof this.options.webdriverCapabilities==`function`?this.options.webdriverCapabilities(e):this.options.webdriverCapabilities??{};return{provider:this.options.provider,endpoint:this.options.endpoint,platform:this.options.platform,deviceName:this.options.deviceName,auth:this.options.auth,headers:this.options.headers,webdriverCapabilities:P(this.options.platform,this.options.deviceName,t)}}deviceForLease(e,t){return{...i(t.platform),...t.platform===`ios`?{appleOs:`ios`}:{},id:t.deviceId??this.options.deviceId?.(e)??`${this.options.provider}:${t.platform}:${e.leaseId}`,name:t.deviceName,kind:`device`,target:`mobile`,booted:!0}}async closeSession(e){let n=[],r;try{await e.client.deleteSession()}catch(e){n.push({code:`WEBDRIVER_SESSION_DELETE_FAILED`,message:t(e)})}try{r=await e.prepared.cleanup?.()}catch(e){n.push({code:`PROVIDER_CLEANUP_FAILED`,message:t(e)})}return{cleanup:r,warnings:n}}async safeListArtifacts(e){let t=e.prepared.listArtifacts??this.options.listArtifacts;if(t)try{return await t({provider:this.options.provider,lease:e.lease,device:e.device,webDriverSessionId:e.webDriverSessionId,providerSessionId:e.providerSessionId})}catch(t){return de({provider:this.options.provider,providerSessionId:e.providerSessionId,error:t})}}};function P(e,t,n={}){return{platformName:e===`ios`?`iOS`:`Android`,"appium:deviceName":t,...n}}function rt(t,n,r,i){let a=t.details?.timeoutMs;return new e(`COMMAND_FAILED`,`${n} did not create the WebDriver session within ${String(a)}ms.`,{reason:`provider_session_create_timeout`,provider:n,leaseId:r.leaseId,runId:r.runId,timeoutMs:a,...i.providerSessionId?{providerSessionId:i.providerSessionId}:{},hint:`${n} may still finish creating the session after agent-device stopped waiting, and that session would keep billing until the provider reaps it. Before retrying, check ${n} for a running session created for lease ${r.leaseId} (run ${r.runId}) and stop it.`},t)}function F(e){return new it(e)}var it=class{provider;owner;leaseLifecycle;cloudArtifacts;deviceInventoryProvider;capabilities;platformRuntimeModule;sessions;deployment;constructor(e){this.provider=e.provider,this.owner=n(e.provider,e.platform),this.capabilities=ne({provider:e.provider,platform:e.platform,overrides:e.capabilityOverrides}),this.sessions=new nt(e),this.deployment=se({provider:e.provider,uploadApp:e.uploadApp,findSessionForDevice:e=>this.sessions.findSessionForDevice(e)}),this.platformRuntimeModule=Object.freeze({owner:this.owner,loadRuntime:async e=>await this.loadRuntime(e)}),this.leaseLifecycle={allocate:async(e,t)=>await this.sessions.allocate(e,t),heartbeat:async e=>this.sessions.heartbeat(e),release:async e=>await this.sessions.release(e)},this.cloudArtifacts={listCloudArtifacts:async e=>await this.sessions.listCloudArtifacts(e)},this.deviceInventoryProvider=async e=>{if(e.leaseProvider!==this.provider)return null;if(!e.leaseId)return[];let t=this.sessions.findSessionForLease(e.leaseId);return t?[t.device]:[]}}async loadRuntime(e){let{createWebDriverPlatformRuntimeOwner:t}=await import(`./platform-runtime2.js`);return t({host:e,owner:this.owner,ownsDevice:e=>this.ownsDevice(e),isSessionActive:e=>this.sessions.findSessionForDevice(e)!==void 0,deployment:this.deployment,snapshotAvailable:this.capabilities.operations.snapshot.support!==`unsupported`,getInteractor:e=>this.getInteractor(e)})}ownsDevice(e){return this.sessions.ownsDevice(e)}getInteractor(e){return this.sessions.getInteractor(e)}async installApp(e,t,n,r){return await this.deployment.installApp(e,t,n,r)}async installInstallablePath(e,t,n){return await this.deployment.installInstallablePath(e,t,n)}async shutdown(){await this.sessions.shutdown()}};async function I(e,t,n){if(t)return v({provider:e,providerSessionId:t,artifacts:(await Promise.all([n.listArtifacts(t,`FILE`),n.listArtifacts(t,`LOG`)])).flat().flatMap(n=>ot(e,t,n)),pendingMessage:`AWS Device Farm artifacts are not ready yet.`})}function at(e){if(!e||typeof e!=`object`)return[];let t=e.artifacts;return Array.isArray(t)?t:[]}function ot(e,t,n){let r=n.url;return typeof r!=`string`||r.length===0?[]:[{provider:e,providerSessionId:t,kind:st(n.type),name:n.name??n.type??`AWS Device Farm artifact`,url:r,providerArtifactId:n.arn,extension:n.extension,availability:`ready`,metadata:{awsType:n.type,...n.metadata?{awsMetadata:n.metadata}:{}}}]}function st(e){switch(e){case`VIDEO`:return`video`;case`APPIUM_SERVER_OUTPUT`:return`appium-log`;case`DEVICE_LOG`:return`device-log`;case`MESSAGE_LOG`:case`UNKNOWN`:return`automation-log`;default:return`raw`}}const L={browserStack:`browserstack`,awsDeviceFarm:`aws-device-farm`},ct=new Set(Object.values(L));function lt(e){return e!==void 0&&ct.has(e)}L.awsDeviceFarm;const ut={install:{support:`unsupported`,note:`Pass appArn when creating the remote access session; local artifact upload/install is not implemented.`},portReverse:{support:`unsupported`,note:`AWS Device Farm remote access does not expose agent-device port reverse.`},artifacts:{support:`supported`,note:`AWS Device Farm remote access exposes provider-hosted video, Appium logs, and device logs after session completion.`}};function R(e){let t=z(e);return{createRemoteAccessSession:async e=>B(await t(`create-remote-access-session`,[`--project-arn`,e.projectArn,`--device-arn`,e.deviceArn,`--name`,e.name,...e.appArn?[`--app-arn`,e.appArn]:[],...e.interactionMode?[`--interaction-mode`,e.interactionMode]:[],...e.configuration?[`--configuration`,JSON.stringify(e.configuration)]:[]])),getRemoteAccessSession:async e=>B(await t(`get-remote-access-session`,[`--arn`,e])),stopRemoteAccessSession:async e=>B(await t(`stop-remote-access-session`,[`--arn`,e])),listArtifacts:async(e,n)=>at(await t(`list-artifacts`,[`--arn`,e,`--type`,n]))}}function dt(t){return async({lease:n,req:r,base:i})=>{let a=await t.client.createRemoteAccessSession({projectArn:t.projectArn,deviceArn:t.deviceArn,appArn:t.appArn,name:pe(t.sessionName,n)??`agent-device-${n.leaseId}`,interactionMode:t.interactionMode,configuration:t.configuration}),o,s;try{if(o=await mt(a.arn,t,r),s=ft(o),!s)throw new e(`COMMAND_FAILED`,`AWS Device Farm did not expose a WebDriver endpoint.`,{sessionArn:o.arn,status:o.status})}catch(e){throw await fe(e,()=>t.client.stopRemoteAccessSession(a.arn)),e}let c=o.device?.name??t.deviceName,l=typeof t.webdriverCapabilities==`function`?t.webdriverCapabilities(n):t.webdriverCapabilities??{};return{...i,endpoint:s,platform:t.platform,deviceName:c,webdriverCapabilities:P(t.platform,c,l),cleanup:async()=>(await t.client.stopRemoteAccessSession(o.arn),{awsDeviceFarmSessionArn:o.arn}),providerSessionId:o.arn,providerData:{awsDeviceFarmSessionArn:o.arn}}}}function ft(e){let t=e.endpoints&&typeof e.endpoints==`object`?Object.values(e.endpoints):[],n=[e.remoteDriverEndpoint,e.endpoint,...t,e.remoteDebugUrl,e.remoteRecordAppUrl].filter(e=>typeof e==`string`&&e.length>0).find(e=>!/^wss?:\/\//i.test(e));return n?pt(n):void 0}function pt(e){return/^https?:\/\//i.test(e)?e:`http://${e}`}async function mt(t,n,r){let i=n.pollIntervalMs??5e3,a=Date.now(),o=r?.deadline??a+(n.startupTimeoutMs??12e4),s=r?.signal,c=await n.client.getRemoteAccessSession(t);for(;Date.now()<o;){if(s?.throwIfAborted(),c.status===`RUNNING`)return c;gt(c),await p(i,void 0,{signal:s}).catch(()=>s?.throwIfAborted()),c=await n.client.getRemoteAccessSession(t)}throw new e(`COMMAND_FAILED`,`Timed out waiting for AWS Device Farm remote access.`,{sessionArn:t,status:c.status,result:c.result,timeoutMs:o-a})}const ht=new Set([`ERRORED`,`STOPPED`,`COMPLETED`]);function gt(t){if(!(!t.status||!ht.has(t.status)))throw new e(`COMMAND_FAILED`,`AWS Device Farm remote access session did not start.`,{sessionArn:t.arn,status:t.status,result:t.result})}async function _t(t,n,r){let i=await t(n,r);try{return JSON.parse(i.stdout)}catch(t){throw new e(`COMMAND_FAILED`,`AWS Device Farm returned invalid JSON.`,void 0,t)}}function z(e){let t=e.region?[`--region`,e.region]:[],n=e.awsCommand??`aws`;return async(r,i)=>await _t(e.runHostCommand,n,[`devicefarm`,r,...t,...i,`--output`,`json`])}function B(t){if(!t||typeof t!=`object`)throw new e(`COMMAND_FAILED`,`AWS Device Farm response was not an object.`,{response:t});let n=t.remoteAccessSession;if(!n||typeof n!=`object`)throw new e(`COMMAND_FAILED`,`AWS Device Farm response missed remoteAccessSession.`,{response:t});return n}const V=[{field:`providerDeviceOrientation`,capability:`deviceOrientation`,flag:`--provider-device-orientation`,type:`enum`,enumValues:o},{field:`providerGeoLocation`,capability:`geoLocation`,flag:`--provider-geo-location`,type:`string`},{field:`providerTimezone`,capability:`timezone`,flag:`--provider-timezone`,type:`string`},{field:`providerLanguage`,capability:`language`,flag:`--provider-language`,type:`string`},{field:`providerLocale`,capability:`locale`,flag:`--provider-locale`,type:`string`},{field:`providerNetworkProfile`,capability:`networkProfile`,flag:`--provider-network-profile`,type:`string`},{field:`providerCustomNetwork`,capability:`customNetwork`,flag:`--provider-custom-network`,type:`string`},{field:`providerNoResignApp`,capability:`resignApp`,flag:`--provider-no-resign-app`,type:`negated-boolean`,platform:`ios`}];function vt(e,t){wt(e);let n={};for(let r of V){let i=e[r.field];i===void 0||i===!1||i===``||(Ct(r,t),n[r.capability]=r.type===`negated-boolean`?!1:i)}return n}function yt(e){return V.filter(t=>{let n=e?.[t.field];return n!==void 0&&n!==!1&&n!==``}).map(e=>e.flag)}function H(t,n){let r=yt(t);if(r.length===0)return;let i=r.length!==1;throw new e(`INVALID_ARGS`,`${r.join(`, `)} ${i?`are`:`is`} only supported by BrowserStack, not ${n}.`,{hint:`Drop ${i?`those flags`:`the flag`} or use the browserstack provider.`,provider:n,flags:r})}function bt(e){let t={};for(let n of V){let r=e?.[n.field];if(n.type===`negated-boolean`){r===!0&&(t.providerNoResignApp=!0);continue}typeof r!=`string`||r.length===0||xt(t,n,r)}return t}function xt(e,t,n){if(t.field===`providerDeviceOrientation`){e.providerDeviceOrientation=St(t,n);return}t.field!==`providerNoResignApp`&&(e[t.field]=n)}function St(t,n){let r=o.find(e=>e===n);if(r)return r;throw new e(`INVALID_ARGS`,`Invalid ${t.flag} value: ${n}.`,{hint:`Use ${o.join(`|`)}.`,flag:t.flag,capability:t.capability})}function Ct(t,n){if(!(!t.platform||t.platform===n))throw new e(`INVALID_ARGS`,`${t.flag} applies to ${t.platform} sessions only, but the session platform is ${n}.`,{hint:`Drop ${t.flag} or connect with --platform ${t.platform}.`,flag:t.flag,capability:t.capability,platform:n})}function wt(t){if(!(!t.providerNetworkProfile||!t.providerCustomNetwork))throw new e(`INVALID_ARGS`,`BrowserStack accepts either a named network profile or a custom network shape, not both.`,{hint:`Pass only one of --provider-network-profile or --provider-custom-network.`,networkProfile:t.providerNetworkProfile,customNetwork:t.providerCustomNetwork})}L.browserStack;const Tt={install:{support:`partial`,note:`Local app artifacts are uploaded to BrowserStack App Automate, then installed with Appium.`},portReverse:{support:`unsupported`,note:`Use BrowserStack Local for network tunneling; agent-device port reverse is not available.`},artifacts:{support:`supported`,note:`BrowserStack session details expose provider-hosted video, Appium logs, device logs, and dashboard links.`}};async function U(e,t,n){if(t)return v({provider:e,providerSessionId:t,artifacts:At(e,t,await kt(t,n)),pendingMessage:`BrowserStack artifacts are not ready yet.`})}async function W(t,n,r){r?.throwIfAborted();let i=await f.readFile(t),a=new FormData;a.set(`file`,new Blob([i]),d.basename(t));let o=await fetch(n.endpoint??`https://api-cloud.browserstack.com/app-automate/upload`,{method:`POST`,headers:{...y(n.clientVersion),Authorization:b(n)},body:a,signal:r}),s=await o.json(),c=jt(s);if(!o.ok||!c)throw new e(`COMMAND_FAILED`,`BrowserStack app upload failed.`,{status:o.status,response:s});return c}function Et(e){return async({appPath:t,options:n,signal:r})=>({appReference:await W(t,e,r),bundleId:n?.appIdentifierHint,packageName:n?.packageNameHint,launchTarget:n?.appIdentifierHint??n?.packageNameHint})}function Dt(e){let{"bstack:options":t,...n}=e.configured??{};return{device:e.deviceName,os_version:e.osVersion,...e.app?{app:e.app}:{},...n,"bstack:options":{...e.projectName?{projectName:e.projectName}:{},buildName:e.buildName,sessionName:e.sessionName,...e.deviceFeatures??{},...Ot(t)}}}function Ot(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}async function kt(t,n){let r=new URL(`${he(String(n.endpoint??`https://api-cloud.browserstack.com/app-automate/sessions`))}/${t}.json`),i=await fetch(r,{headers:{...y(n.clientVersion),Authorization:b(n)}}),a=await i.json();if(!i.ok||!a||typeof a!=`object`)throw new e(`COMMAND_FAILED`,`BrowserStack session details lookup failed.`,{status:i.status,response:a});let o=a.automation_session??a;return o&&typeof o==`object`?o:{}}function At(e,t,n){return[G(e,t,n,`video_url`,`video`,`Session video`),G(e,t,n,`appium_logs_url`,`appium-log`,`Appium logs`),G(e,t,n,`device_logs_url`,`device-log`,`Device logs`),G(e,t,n,`browser_url`,`provider-session`,`BrowserStack dashboard`),G(e,t,n,`public_url`,`provider-session`,`Public session link`)].filter(e=>e!==void 0)}function G(e,t,n,r,i,a){let o=n[r];if(!(typeof o!=`string`||o.length===0))return{provider:e,providerSessionId:t,kind:i,name:a,url:o,availability:`ready`}}function jt(e){if(!e||typeof e!=`object`)return;let t=e.app_url;return typeof t==`string`?t:void 0}function K(e){return/^arn:[^:]+:devicefarm:([^:]+):/.exec(e)?.[1]}async function Mt(t,n){let r=z({runHostCommand:n,region:t.region}),[i,a,o]=await Promise.all([r(`get-project`,[`--arn`,t.projectArn]),r(`get-device`,[`--arn`,t.deviceArn]),t.appArn?r(`get-upload`,[`--arn`,t.appArn]):void 0]),s=q(i,`project`),c=q(a,`device`),l=Pt(c.platform);if(l!==t.platform)throw new e(`INVALID_ARGS`,`AWS Device Farm device "${J(c.name)??t.deviceArn}" is ${l}, not ${t.platform}.`);let u=t.appArn?Nt(q(o,`upload`),t):{status:`missing`,message:`No app upload is attached; AWS Device Farm does not support install after allocation. Reconnect with --aws-app-arn <arn>.`};return{provider:`aws-device-farm`,service:`AWS Device Farm`,verificationMessage:t.appArn?`Credentials, project, device, and app upload verified.`:`Credentials, project, and device verified.`,project:{name:J(s.name),reference:t.projectArn},device:{status:`verified`,name:J(c.name)??t.deviceArn,reference:t.deviceArn,platform:l,osVersion:J(c.os),availability:J(c.availability)},app:u}}function Nt(t,n){let r=J(t.status);if(r!==`SUCCEEDED`)throw new e(`COMMAND_FAILED`,`AWS Device Farm app upload is not ready (${r??`unknown status`}).`,{status:r,hint:`Wait for the upload to succeed or reconnect with a different --aws-app-arn.`});let i=n.platform===`android`?`ANDROID_APP`:`IOS_APP`,a=J(t.type);if(a!==i)throw new e(`INVALID_ARGS`,`AWS Device Farm app upload type is ${a??`unknown`}, expected ${i}.`);return{status:`verified`,name:J(t.name),reference:n.appArn}}function q(t,n){if(!t||typeof t!=`object`)throw new e(`COMMAND_FAILED`,`AWS Device Farm ${n} response was not an object.`);let r=t[n];if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`COMMAND_FAILED`,`AWS Device Farm response missed ${n}.`);return r}function Pt(t){if(t===`ANDROID`)return`android`;if(t===`IOS`)return`ios`;throw new e(`UNSUPPORTED_PLATFORM`,`AWS Device Farm device platform is ${String(t)}.`)}function J(e){return typeof e==`string`&&e.length>0?e:void 0}async function Ft(t,n){let r={username:t.username,accessKey:t.accessKey},i=zt(await Lt(t.devicesEndpoint??`https://api-cloud.browserstack.com/app-automate/devices.json`,r,n)).find(e=>e.device===t.deviceName&&e.os.toLowerCase()===t.platform&&Rt(e.osVersion,t.osVersion));if(!i)throw new e(`INVALID_ARGS`,`BrowserStack device "${t.deviceName}" with ${t.platform} ${t.osVersion} is not available.`,{hint:`Choose an exact device and OS version from the BrowserStack App Automate device list.`});let a=await It(t,r,n);return{provider:`browserstack`,service:`BrowserStack`,verificationMessage:a.status===`verified`?`Credentials, device, and uploaded app verified.`:`Credentials and device access verified; app availability is checked when the session is created.`,device:{status:`verified`,name:i.device,platform:t.platform,osVersion:i.osVersion},app:a}}async function It(e,t,n){let{app:r}=e;if(r.startsWith(`bs://`)){let i=Bt(await Lt(e.appsEndpoint??`https://api-cloud.browserstack.com/app-automate/recent_apps?limit=100`,t,n)).find(e=>e.reference===r);return i?{status:`verified`,...i}:{status:`configured`,reference:r,message:`App reference was not found in the 100 most recent uploads; BrowserStack validates it when creating the session.`}}return/^https?:\/\//i.test(r)?{status:`configured`,reference:r,message:`Public app URL configured; BrowserStack validates it when creating the session.`}:{status:`configured`,name:d.basename(r),reference:r,message:`Local app artifact is ready and will be uploaded when creating the session.`}}async function Lt(t,n,r){try{let i=await fetch(t,{headers:{...y(r),Authorization:b(n)},signal:AbortSignal.timeout(15e3)});if(!i.ok){let t=i.status===401||i.status===403;throw new e(t?`UNAUTHORIZED`:`COMMAND_FAILED`,`BrowserStack rejected connection verification.`,{status:i.status,hint:t?`Check BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY.`:`Retry connect or check the BrowserStack service status.`})}return await i.json()}catch(t){throw t instanceof e?t:new e(`COMMAND_FAILED`,`BrowserStack connection verification failed.`,{hint:`Check network access to api-cloud.browserstack.com and retry connect.`},t)}}function Rt(e,t){let n=e=>e.replace(/(?:\.0)+$/,``);return n(e)===n(t)}function zt(t){if(!Array.isArray(t))throw new e(`COMMAND_FAILED`,`BrowserStack device verification response was not a list.`);return t.flatMap(e=>{let t=Y(e),n=t?.os_version;return t&&typeof t.device==`string`&&typeof t.os==`string`&&(typeof n==`string`||typeof n==`number`)?[{device:t.device,os:t.os,osVersion:String(n)}]:[]})}function Bt(t){let n=Y(t);if(n&&Object.keys(n).length===0)return[];if(!Array.isArray(t))throw new e(`COMMAND_FAILED`,`BrowserStack app verification response was not a list.`);return t.flatMap(e=>{let t=Y(e);return!t||typeof t.app_url!=`string`?[]:[{reference:t.app_url,...typeof t.app_name==`string`?{name:t.app_name}:{},...typeof t.app_version==`string`?{version:t.app_version}:{}}]})}function Y(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}async function Vt(e,t){return e.provider===`browserstack`?await Ft(e,t.clientVersion):await Mt(e,t.runHostCommand)}function Ht(e){return[{provider:L.browserStack,createRuntime:t=>F({clientVersion:e.clientVersion,provider:L.browserStack,platform:`android`,deviceName:`BrowserStack device`,endpoint:t.BROWSERSTACK_WEBDRIVER_ENDPOINT??`https://hub-cloud.browserstack.com/wd/hub/`,capabilityOverrides:Tt,listArtifacts:async({provider:n,providerSessionId:r})=>{let i=$(t,`BROWSERSTACK_USERNAME`,`BrowserStack artifact lookup`),a=$(t,`BROWSERSTACK_ACCESS_KEY`,`BrowserStack artifact lookup`);return await U(n,r,{clientVersion:e.clientVersion,username:i,accessKey:a,endpoint:t.BROWSERSTACK_SESSION_DETAILS_ENDPOINT})},prepareSession:async({req:n,lease:r,base:i})=>{let a=Gt(n,`BrowserStack`),o=$(t,`BROWSERSTACK_USERNAME`,`BrowserStack`),s=$(t,`BROWSERSTACK_ACCESS_KEY`,`BrowserStack`),c=X(a,`BrowserStack`),l=Z(a,`device`,`BrowserStack requires --device <name>.`),u=Z(a,`providerOsVersion`,`BrowserStack requires --provider-os-version <version>.`),d=await Ut({clientVersion:e.clientVersion,app:Z(a,`providerApp`,`BrowserStack requires --provider-app <bs://app-id-or-local-path>.`),cwd:a.cwd,username:o,accessKey:s,uploadEndpoint:t.BROWSERSTACK_APP_UPLOAD_ENDPOINT,signal:a.signal});return{...i,platform:c,deviceName:l,auth:{username:o,accessKey:s},uploadApp:Et({clientVersion:e.clientVersion,username:o,accessKey:s,endpoint:t.BROWSERSTACK_APP_UPLOAD_ENDPOINT??`https://api-cloud.browserstack.com/app-automate/upload`}),webdriverCapabilities:Dt({deviceName:l,osVersion:u,app:d,projectName:Q(a,`providerProject`),buildName:Q(a,`providerBuild`)??r.runId,sessionName:Q(a,`providerSessionName`)??r.leaseId,deviceFeatures:vt(bt(a.flags),c),configured:P(c,l)})}}}),listArtifactsFromEnv:async(t,n)=>{let r=$(n,`BROWSERSTACK_USERNAME`,`BrowserStack artifact lookup`),i=$(n,`BROWSERSTACK_ACCESS_KEY`,`BrowserStack artifact lookup`);return await U(L.browserStack,t,{clientVersion:e.clientVersion,username:r,accessKey:i,endpoint:n.BROWSERSTACK_SESSION_DETAILS_ENDPOINT})}},{provider:L.awsDeviceFarm,createRuntime:t=>F({clientVersion:e.clientVersion,provider:L.awsDeviceFarm,endpoint:`http://127.0.0.1/`,platform:`android`,deviceName:`AWS Device Farm device`,capabilityOverrides:ut,listArtifacts:async({provider:n,providerSessionId:r})=>await I(n,r,R({runHostCommand:e.runHostCommand,region:t.AWS_REGION??t.AWS_DEFAULT_REGION??K(r??``)})),prepareSession:async({req:n,lease:r,base:i})=>{let a=Gt(n,`AWS Device Farm`);H(a.flags,L.awsDeviceFarm);let o=X(a,`AWS Device Farm`);return await dt({client:R({runHostCommand:e.runHostCommand,region:Q(a,`awsRegion`)??t.AWS_REGION??t.AWS_DEFAULT_REGION}),projectArn:Kt(a,t,`awsProjectArn`,`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`),deviceArn:Kt(a,t,`awsDeviceArn`,`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`),appArn:Q(a,`awsAppArn`)??t.AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN??t.AWS_DEVICE_FARM_APP_ARN,platform:o,deviceName:Q(a,`device`)??`AWS Device Farm device`,sessionName:Q(a,`providerSessionName`)??r.leaseId,interactionMode:qt(a)})({lease:r,req:n,base:i})}}),listArtifactsFromEnv:async(t,n)=>{let r=R({runHostCommand:e.runHostCommand,region:n.AWS_REGION??n.AWS_DEFAULT_REGION??K(t)});return await I(L.awsDeviceFarm,t,r)}}]}async function Ut(t){if(Wt(t.app))return t.app;let n=d.resolve(t.cwd??process.cwd(),t.app);if(!ee.existsSync(n))throw new e(`INVALID_ARGS`,`BrowserStack --provider-app must be a bs:// app id, URL, or existing local app path.`,{providerApp:t.app});return await W(n,{clientVersion:t.clientVersion,username:t.username,accessKey:t.accessKey,endpoint:t.uploadEndpoint},t.signal)}function Wt(e){return e.startsWith(`bs://`)||/^https?:\/\//.test(e)}function Gt(t,n){if(t)return t;throw new e(`INVALID_ARGS`,`${n} lease allocation requires provider profile flags on the request.`)}function X(t,n){let r=t.flags?.platform;if(r===`android`||r===`ios`)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android.`)}function Z(t,n,r){let i=Q(t,n);if(i)return i;throw new e(`INVALID_ARGS`,r)}function Q(e,t){let n=e.flags?.[t];return typeof n==`string`&&n.length>0?n:void 0}function $(t,n,r){let i=t[n];if(i)return i;throw new e(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function Kt(t,n,r,i,a){let o=Q(t,r)??n[i]??n[a];if(o)return o;throw new e(`INVALID_ARGS`,`AWS Device Farm requires --${Jt(String(r))} or ${a}.`)}function qt(e){let t=Q(e,`awsInteractionMode`);if(t===`INTERACTIVE`||t===`NO_VIDEO`||t===`VIDEO_ONLY`)return t}function Jt(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function Yt(e){let t=Ht(e);return{providerIds:t.map(e=>e.provider),createDefaultRuntimes:(e=process.env)=>t.map(t=>t.createRuntime(e)),listArtifactsFromEnv:async(e,n)=>{if(e.providerSessionId)return await t.find(t=>t.provider===e.provider)?.listArtifactsFromEnv(e.providerSessionId,n)},verifyConnection:async t=>await Vt(t,e)}}export{lt as a,L as i,K as n,H as r,Yt as t};