agent-device 0.19.3 → 0.20.0

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 (168) hide show
  1. package/README.md +61 -70
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.0.apk +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.0.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.0.manifest.json +10 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.0.apk +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.0.apk.sha256 +1 -0
  7. package/{android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.manifest.json → android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.0.manifest.json} +6 -6
  8. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +2 -0
  9. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +5 -0
  10. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +5 -10
  11. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +74 -174
  12. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +113 -19
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +82 -0
  14. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +272 -118
  15. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +2 -2
  16. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +134 -101
  17. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +56 -2
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +73 -0
  19. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +44 -24
  20. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +2 -2
  21. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -107
  22. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +126 -11
  23. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +51 -8
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +24 -0
  25. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +1 -1
  26. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +43 -35
  27. package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +14 -0
  28. package/dist/src/agent-browser-tool.js +1 -1
  29. package/dist/src/agent-device-client.js +3 -0
  30. package/dist/src/android-adb.d.ts +1 -1
  31. package/dist/src/android-adb.js +1 -1
  32. package/dist/src/android-input-method-overlays.js +1 -0
  33. package/dist/src/android-input-ownership.js +1 -6
  34. package/dist/src/android-system-chrome.js +1 -0
  35. package/dist/src/android.js +1 -1
  36. package/dist/src/app-lifecycle.js +5 -5
  37. package/dist/src/app-log-request-scope.js +1 -0
  38. package/dist/src/app-resolution.js +1 -0
  39. package/dist/src/apple-multitouch-support.js +1 -0
  40. package/dist/src/apps.js +5 -5
  41. package/dist/src/boot-diagnostics.js +2 -0
  42. package/dist/src/cli-config.js +1 -0
  43. package/dist/src/cli-help.js +61 -27
  44. package/dist/src/cli-runner.js +1 -1
  45. package/dist/src/cli.js +15 -11
  46. package/dist/src/command-schema.js +3 -3
  47. package/dist/src/config.js +1 -0
  48. package/dist/src/context.js +1 -0
  49. package/dist/src/contracts.d.ts +1 -1
  50. package/dist/src/daemon-shutdown-report.js +1 -0
  51. package/dist/src/debug-symbols.js +1 -1
  52. package/dist/src/device-input-state.js +1 -1
  53. package/dist/src/devices2.js +1 -1
  54. package/dist/src/find.js +1 -1
  55. package/dist/src/finders.js +1 -1
  56. package/dist/src/generic.js +1 -1
  57. package/dist/src/helper.js +1 -1
  58. package/dist/src/index.d.ts +412 -293
  59. package/dist/src/index.js +1 -1
  60. package/dist/src/input-actions.js +4 -3
  61. package/dist/src/install-artifact.js +1 -0
  62. package/dist/src/install-source.d.ts +5 -1
  63. package/dist/src/install-source.js +1 -1
  64. package/dist/src/install-source2.js +1 -1
  65. package/dist/src/interaction-snapshot.js +1 -1
  66. package/dist/src/interaction.d.ts +230 -0
  67. package/dist/src/interaction.js +1 -1
  68. package/dist/src/interactor.js +2 -2
  69. package/dist/src/internal/bin.js +1 -1
  70. package/dist/src/internal/daemon.js +42 -20
  71. package/dist/src/internal/png-worker.d.ts +22 -0
  72. package/dist/src/internal/png-worker.js +1 -1
  73. package/dist/src/launch-console.js +1 -0
  74. package/dist/src/lease-context.js +1 -0
  75. package/dist/src/lease.js +1 -1
  76. package/dist/src/linux.js +1 -1
  77. package/dist/src/logcat.js +5 -0
  78. package/dist/src/metro.d.ts +2 -2
  79. package/dist/src/notifications.js +1 -1
  80. package/dist/src/png-worker-contract.js +1 -1
  81. package/dist/src/process-lock.js +1 -0
  82. package/dist/src/react-native.js +1 -1
  83. package/dist/src/record-trace.js +1 -1
  84. package/dist/src/register-builtins.js +1 -0
  85. package/dist/src/registry.js +24 -24
  86. package/dist/src/reporting.js +8 -7
  87. package/dist/src/runner-client.js +1 -1
  88. package/dist/src/runner-disposal.js +2 -0
  89. package/dist/src/runner-lease.js +1 -0
  90. package/dist/src/runner-sequence.js +1 -1
  91. package/dist/src/runtime.js +3 -3
  92. package/dist/src/runtime2.js +1 -0
  93. package/dist/src/sdk-android-adb.d.ts +119 -33
  94. package/dist/src/sdk-android-adb.js +2 -2
  95. package/dist/src/sdk-batch-runner.d.ts +2 -1
  96. package/dist/src/sdk-batch-runner.js +2 -2
  97. package/dist/src/sdk-batch.js +2 -2
  98. package/dist/src/sdk-contracts.d.ts +105 -98
  99. package/dist/src/sdk-contracts.js +1 -1
  100. package/dist/src/sdk-device.js +1 -1
  101. package/dist/src/sdk-finders.d.ts +3 -3
  102. package/dist/src/sdk-finders.js +1 -1
  103. package/dist/src/sdk-io.d.ts +1 -1
  104. package/dist/src/sdk-remote-config.d.ts +9 -1
  105. package/dist/src/sdk-remote-config.js +1 -1
  106. package/dist/src/sdk-selectors.js +1 -1
  107. package/dist/src/selector-runtime.js +1 -1
  108. package/dist/src/selector-vocabulary.js +1 -0
  109. package/dist/src/selectors.d.ts +12 -3
  110. package/dist/src/selectors.js +1 -1
  111. package/dist/src/server.js +3 -3
  112. package/dist/src/session-target-evidence.js +1 -0
  113. package/dist/src/session.js +8 -10
  114. package/dist/src/simulator.js +1 -1
  115. package/dist/src/snapshot-diagnostics.js +5 -2
  116. package/dist/src/snapshot.js +1 -1
  117. package/dist/src/snapshot2.js +1 -2
  118. package/dist/src/tv-remote.js +13 -12
  119. package/dist/src/url.js +1 -1
  120. package/dist/src/web.js +1 -1
  121. package/package.json +28 -23
  122. package/server.json +2 -2
  123. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.apk +0 -0
  124. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.apk.sha256 +0 -1
  125. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.3.manifest.json +0 -10
  126. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.apk +0 -0
  127. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.3.apk.sha256 +0 -1
  128. package/dist/src/apple-runner-options.js +0 -1
  129. package/dist/src/cli-output.js +0 -1
  130. package/dist/src/client.js +0 -3
  131. package/dist/src/handler-utils.js +0 -1
  132. package/dist/src/output-path.js +0 -1
  133. package/dist/src/points.js +0 -4
  134. package/dist/src/provider.js +0 -1
  135. package/dist/src/providers.js +0 -1
  136. package/dist/src/record-trace-recording.js +0 -23
  137. package/dist/src/recording-provider.js +0 -1
  138. package/dist/src/selectors2.js +0 -1
  139. package/dist/src/simctl.js +0 -1
  140. package/dist/src/ttl-memo.js +0 -1
  141. package/dist/src/xml.js +0 -2
  142. /package/{macos-helper → apple/macos-helper}/Package.swift +0 -0
  143. /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +0 -0
  144. /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +0 -0
  145. /package/{macos-helper → apple/macos-helper}/Sources/AgentDeviceMacOSHelper/main.swift +0 -0
  146. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +0 -0
  147. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +0 -0
  148. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  149. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +0 -0
  150. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +0 -0
  151. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements +0 -0
  152. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.h +0 -0
  153. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.m +0 -0
  154. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -0
  155. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +0 -0
  156. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -0
  157. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +0 -0
  158. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +0 -0
  159. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +0 -0
  160. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +0 -0
  161. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +0 -0
  162. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +0 -0
  163. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -0
  164. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +0 -0
  165. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +0 -0
  166. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -0
  167. /package/dist/{apple-runner → apple/runner}/AgentDeviceRunner/RecordingScripts/recording-trim.swift +0 -0
  168. /package/{src/platforms/linux → linux}/atspi-dump.py +0 -0
@@ -1 +1 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{T as r,j as i,v as a}from"./sdk-android-adb.js";import{t as o}from"./timeouts.js";import{c as s,i as c,n as l,o as u,t as d}from"./host-process.js";import f from"node:crypto";import p from"node:fs";import m from"node:os";import h from"node:path";async function g(e){let{lockDirPath:n,owner:r}=e,i=h.join(n,`owner.json`),a=Date.now()+(e.timeoutMs??3e4),s=e.pollMs??100,c=e.ownerGraceMs??5e3,l=e.description??`process lock`;for(p.mkdirSync(h.dirname(n),{recursive:!0});Date.now()<a;)try{p.mkdirSync(n),_(i,r);let e=!1;return async()=>{e||(e=!0,p.rmSync(n,{recursive:!0,force:!0}))}}catch(e){let t=e;if(t.code!==`EEXIST`)throw t;if(ee(n,i,c))continue;await o(s)}throw new t(`COMMAND_FAILED`,`Timed out waiting for ${l}`,{lockDirPath:n,...y(n,i)})}function _(e,t){let n=`${e}.${process.pid}.${Date.now()}.tmp`;p.writeFileSync(n,JSON.stringify(t),`utf8`),p.renameSync(n,e)}function ee(e,t,n){let r=null;try{r=p.statSync(e)}catch{return!0}let i=v(t);return i?b(i)?!1:(p.rmSync(e,{recursive:!0,force:!0}),!0):Date.now()-r.mtimeMs<n?!1:(p.rmSync(e,{recursive:!0,force:!0}),!0)}function v(e){try{return JSON.parse(p.readFileSync(e,`utf8`))}catch{return null}}function y(e,t){let n=Date.now(),r=v(t),i;try{i=Math.max(0,Math.round(n-p.statSync(e).mtimeMs))}catch{}return{...i===void 0?{}:{lockAgeMs:i},...r?{ownerPid:r.pid,ownerStartTime:r.startTime,ownerAgeMs:Math.max(0,Math.round(n-r.acquiredAtMs))}:{}}}function b(e){return!Number.isInteger(e.pid)||e.pid<=0||!l(e.pid)?!1:e.startTime?u(e.pid)===e.startTime:!0}const x=new Map;function S(e){let t=f.createHash(`sha256`);return t.update(h.resolve(e.stateDir)),t.update(`\0`),t.update(h.resolve(e.installDir)),`--agent-device-managed-web=${t.digest(`hex`).slice(0,16)}`}function C(e,t){let n=S(t),r=e?.trim();return r?k(r).includes(n)?r:`${r},${n}`:n}function w(e){return A(e.AGENT_BROWSER_IDLE_TIMEOUT_MS)??A(e.AGENT_DEVICE_WEB_IDLE_TIMEOUT_MS)??3e5}function te(e,t){if(e.pid!==process.pid&&j(e.command)){if(e.command.includes(S(t)))return{process:e,reason:`launch-marker`};if(M(t).some(t=>re(e,t)))return{process:e,reason:`managed-browser-home`}}}function T(e,t){let n=e.flatMap(e=>{let n=te(e,t);return n?[n]:[]});return{count:n.length,pids:n.map(e=>e.process.pid),processes:n}}async function E(e){return T(await O(),e)}async function D(e,t,n={}){let r=N([...n.openWebSessionNames??[]]);if(r.length>0)return P(`open-web-session`,{openWebSessionNames:r});let a=w(process.env),o=I(e);if(o!==void 0&&Date.now()-o<a)return P(`recent-browser-activity`,{idleTimeoutMs:a,latestActivityMs:o});let c=await O(),l=T(c,e),u=d(l.processes.map(e=>e.process.pid),c).map(e=>e.pid),f={...l,signalPids:u};return l.count===0?f:(i({level:`warn`,phase:`web_agent_browser_orphan_cleanup`,data:{reason:t,count:l.count,pids:l.pids,signalPids:u,stateDir:e.stateDir,installDir:e.installDir,matchReasons:l.processes.map(e=>e.reason)}}),await s({pids:u,termTimeoutMs:1500,killTimeoutMs:1e3}),f)}async function ne(e,t={}){let n=Date.now(),r=h.resolve(e.stateDir),i=x.get(r);if(!(i!==void 0&&n-i<3e4))return x.set(r,n),await D(e,`provider-startup`,t)}async function O(){return await r(async()=>await c({timeoutMs:1500}))}function k(e){return e.split(/[,\n]/).map(e=>e.trim()).filter(Boolean)}function A(e){if(e===void 0||e.trim()===``)return;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0?t:void 0}function j(e){return/\b(?:Google Chrome for Testing|Chrome for Testing|Chromium|chrome|chrome\.exe|chromium|chromium-browser|headless_shell)\b/i.test(e)}function M(e){return N([h.join(e.homeDir,`.agent-browser`,`browsers`),h.join(e.runtimeHomeDir,`.agent-browser`,`browsers`)])}function N(e){return[...new Set(e.filter(e=>e.length>0))]}function P(e,t){return{count:0,pids:[],processes:[],signalPids:[],skipped:{reason:e,...t}}}function re(e,t){let n=F(e.command),r=`${F(h.resolve(t)).replace(/\/+$/,``)}/`;return n.includes(r)}function F(e){return e.replace(/\\/g,`/`)}function I(e){let t=L(e.socketDir).map(e=>R(e)).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function L(e){try{return p.readdirSync(e).map(t=>h.join(e,t))}catch{return[]}}function R(e){try{return p.statSync(e).mtimeMs}catch{return}}var z=e({doctorManagedAgentBrowser:()=>K,getManagedAgentBrowserStatus:()=>q,mapManagedAgentBrowserError:()=>$,resolveAgentBrowserTool:()=>W,setupManagedAgentBrowser:()=>G});const B=`0.27.1`,V=`agent-browser`,H=5*6e4,U=6e4;async function W(e){let t=q(e);if(t.installed)return J(t);throw Q(t)}async function G(e){let t=q(e);ce(t.nodeMajor);let n=await g({lockDirPath:h.join(t.installDir,`..`,`.agent-browser-install.lock`),owner:{pid:process.pid,startTime:u(process.pid),acquiredAtMs:Date.now()},timeoutMs:H,description:`managed agent-browser setup`});try{let t=q(e);return t.installed?t:(p.mkdirSync(t.installDir,{recursive:!0}),await Y(t),await X(t,[`install`],{timeoutMs:H}),await X(t,[`doctor`,`--offline`,`--quick`],{timeoutMs:U}),ae(t),q(e))}finally{await n()}}async function K(e){let t=q(e);if(!t.installed)throw Q(t);return{status:t,...await X(t,[`doctor`,`--offline`,`--quick`],{timeoutMs:U,allowFailure:!0})}}function q(e){let t=e.stateDir??process.env.AGENT_DEVICE_STATE_DIR??pe(),n=h.join(t,`tools`,`agent-browser`,B),r=se(n),i=h.join(n,`home`),a=le(n),o=ue(n),s=fe(r)&&oe(n),c=Number.parseInt(process.versions.node.split(`.`)[0]??`0`,10);return{version:B,stateDir:t,installDir:n,binaryPath:r,homeDir:i,runtimeHomeDir:a,socketDir:o,installed:s,nodeMajor:c,nodeSupported:c>=24}}function J(e){if(!e.installed)throw Q(e);return{command:e.binaryPath,env:Z(e,process.env)}}async function Y(e){let t=h.join(e.installDir,`package`);p.mkdirSync(t,{recursive:!0}),await a(`npm`,[`install`,`--prefix`,t,`--no-audit`,`--no-fund`,`--no-save`,`${V}@${B}`],{env:process.env,timeoutMs:H})}async function X(e,t,n){return await a(e.binaryPath,t,{allowFailure:n.allowFailure,env:Z(e,process.env),timeoutMs:n.timeoutMs})}function Z(e,t){return p.mkdirSync(e.homeDir,{recursive:!0}),ie(e),p.mkdirSync(e.socketDir,{recursive:!0}),{...t,HOME:e.runtimeHomeDir,AGENT_BROWSER_SOCKET_DIR:e.socketDir,AGENT_BROWSER_IDLE_TIMEOUT_MS:String(w(t)),AGENT_BROWSER_ARGS:C(t.AGENT_BROWSER_ARGS,e)}}function ie(e){if(e.runtimeHomeDir!==e.homeDir){p.mkdirSync(h.dirname(e.runtimeHomeDir),{recursive:!0});try{let t=p.lstatSync(e.runtimeHomeDir);if(t.isSymbolicLink()&&p.readlinkSync(e.runtimeHomeDir)===e.homeDir||t.isDirectory())return;t.isSymbolicLink()&&p.unlinkSync(e.runtimeHomeDir)}catch(e){if(!de(e))throw e}try{p.symlinkSync(e.homeDir,e.runtimeHomeDir,`dir`)}catch{p.mkdirSync(e.runtimeHomeDir,{recursive:!0})}}}function ae(e){p.writeFileSync(h.join(e.installDir,`manifest.json`),JSON.stringify({package:V,version:B,node:process.version,installedAt:new Date().toISOString()},null,2),`utf8`)}function oe(e){return p.existsSync(h.join(e,`manifest.json`))}function se(e){let t=h.join(e,`package`);return h.join(t,`node_modules`,`.bin`,process.platform===`win32`?`agent-browser.cmd`:`agent-browser`)}function Q(e){return new t(`TOOL_MISSING`,`Managed web browser backend is not installed.`,{version:B,installDir:e.installDir,hint:e.nodeSupported===!1?`Web automation requires Node 24+; current Node is ${process.version}.`:"Run `agent-device web setup` to install the managed web backend."})}function ce(e){if(!(e>=24))throw new t(`UNSUPPORTED_OPERATION`,`Web automation requires Node 24 or newer.`,{currentNode:process.version,requiredNodeMajor:24,hint:`Run agent-device with Node 24+ for web setup and web automation.`})}function le(e){if(process.platform===`win32`)return h.join(e,`home`);let t=f.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return h.join(m.tmpdir(),`agent-device-web`,t)}function ue(e){let t=f.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return h.join(m.tmpdir(),`adw`,t)}function de(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function fe(e){try{return p.accessSync(e,p.constants.X_OK),!0}catch{return!1}}function pe(){return h.join(process.env.HOME??process.cwd(),`.agent-device`)}function $(e){let r=n(e);return r.code===`TOOL_MISSING`?new t(r.code,r.message,{...r.details??{},hint:typeof r.details?.hint==`string`?r.details.hint:"Run `agent-device web setup` to install the managed web backend."}):r}export{D as a,g as c,W as i,q as n,ne as o,$ as r,E as s,z as t};
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{T as r,j as i,v as a}from"./sdk-android-adb.js";import{c as o,i as s,o as c,t as l}from"./host-process.js";import{t as u}from"./process-lock.js";import d from"node:crypto";import f from"node:fs";import p from"node:os";import m from"node:path";const h=new Map;function g(e){let t=d.createHash(`sha256`);return t.update(m.resolve(e.stateDir)),t.update(`\0`),t.update(m.resolve(e.installDir)),`--agent-device-managed-web=${t.digest(`hex`).slice(0,16)}`}function _(e,t){let n=g(t),r=e?.trim();return r?T(r).includes(n)?r:`${r},${n}`:n}function v(e){return E(e.AGENT_BROWSER_IDLE_TIMEOUT_MS)??E(e.AGENT_DEVICE_WEB_IDLE_TIMEOUT_MS)??3e5}function y(e,t){if(e.pid!==process.pid&&D(e.command)){if(e.command.includes(g(t)))return{process:e,reason:`launch-marker`};if(O(t).some(t=>j(e,t)))return{process:e,reason:`managed-browser-home`}}}function b(e,t){let n=e.flatMap(e=>{let n=y(e,t);return n?[n]:[]});return{count:n.length,pids:n.map(e=>e.process.pid),processes:n}}async function x(e){return b(await w(),e)}async function S(e,t,n={}){let r=k([...n.openWebSessionNames??[]]);if(r.length>0)return A(`open-web-session`,{openWebSessionNames:r});let a=v(process.env),s=N(e);if(s!==void 0&&Date.now()-s<a)return A(`recent-browser-activity`,{idleTimeoutMs:a,latestActivityMs:s});let c=await w(),u=b(c,e),d=l(u.processes.map(e=>e.process.pid),c).map(e=>e.pid),f={...u,signalPids:d};return u.count===0?f:(i({level:`warn`,phase:`web_agent_browser_orphan_cleanup`,data:{reason:t,count:u.count,pids:u.pids,signalPids:d,stateDir:e.stateDir,installDir:e.installDir,matchReasons:u.processes.map(e=>e.reason)}}),await o({pids:d,termTimeoutMs:1500,killTimeoutMs:1e3}),f)}async function C(e,t={}){let n=Date.now(),r=m.resolve(e.stateDir),i=h.get(r);if(!(i!==void 0&&n-i<3e4))return h.set(r,n),await S(e,`provider-startup`,t)}async function w(){return await r(async()=>await s({timeoutMs:1500}))}function T(e){return e.split(/[,\n]/).map(e=>e.trim()).filter(Boolean)}function E(e){if(e===void 0||e.trim()===``)return;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0?t:void 0}function D(e){return/\b(?:Google Chrome for Testing|Chrome for Testing|Chromium|chrome|chrome\.exe|chromium|chromium-browser|headless_shell)\b/i.test(e)}function O(e){return k([m.join(e.homeDir,`.agent-browser`,`browsers`),m.join(e.runtimeHomeDir,`.agent-browser`,`browsers`)])}function k(e){return[...new Set(e.filter(e=>e.length>0))]}function A(e,t){return{count:0,pids:[],processes:[],signalPids:[],skipped:{reason:e,...t}}}function j(e,t){let n=M(e.command),r=`${M(m.resolve(t)).replace(/\/+$/,``)}/`;return n.includes(r)}function M(e){return e.replace(/\\/g,`/`)}function N(e){let t=ee(e.socketDir).map(e=>P(e)).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function ee(e){try{return f.readdirSync(e).map(t=>m.join(e,t))}catch{return[]}}function P(e){try{return f.statSync(e).mtimeMs}catch{return}}var F=e({doctorManagedAgentBrowser:()=>H,getManagedAgentBrowserStatus:()=>U,mapManagedAgentBrowserError:()=>$,resolveAgentBrowserTool:()=>B,setupManagedAgentBrowser:()=>V});const I=`0.27.1`,L=`agent-browser`,R=5*6e4,z=6e4;async function B(e){let t=U(e);if(t.installed)return W(t);throw Q(t)}async function V(e){let t=U(e);te(t.nodeMajor);let n=await u({lockDirPath:m.join(t.installDir,`..`,`.agent-browser-install.lock`),owner:{pid:process.pid,startTime:c(process.pid),acquiredAtMs:Date.now()},timeoutMs:R,description:`managed agent-browser setup`});try{let t=U(e);return t.installed?t:(f.mkdirSync(t.installDir,{recursive:!0}),await G(t),await K(t,[`install`],{timeoutMs:R}),await K(t,[`doctor`,`--offline`,`--quick`],{timeoutMs:z}),Y(t),U(e))}finally{await n()}}async function H(e){let t=U(e);if(!t.installed)throw Q(t);return{status:t,...await K(t,[`doctor`,`--offline`,`--quick`],{timeoutMs:z,allowFailure:!0})}}function U(e){let t=e.stateDir??process.env.AGENT_DEVICE_STATE_DIR??oe(),n=m.join(t,`tools`,`agent-browser`,I),r=Z(n),i=m.join(n,`home`),a=ne(n),o=re(n),s=ae(r)&&X(n),c=Number.parseInt(process.versions.node.split(`.`)[0]??`0`,10);return{version:I,stateDir:t,installDir:n,binaryPath:r,homeDir:i,runtimeHomeDir:a,socketDir:o,installed:s,nodeMajor:c,nodeSupported:c>=24}}function W(e){if(!e.installed)throw Q(e);return{command:e.binaryPath,env:q(e,process.env)}}async function G(e){let t=m.join(e.installDir,`package`);f.mkdirSync(t,{recursive:!0}),await a(`npm`,[`install`,`--prefix`,t,`--no-audit`,`--no-fund`,`--no-save`,`${L}@${I}`],{env:process.env,timeoutMs:R})}async function K(e,t,n){return await a(e.binaryPath,t,{allowFailure:n.allowFailure,env:q(e,process.env),timeoutMs:n.timeoutMs})}function q(e,t){return f.mkdirSync(e.homeDir,{recursive:!0}),J(e),f.mkdirSync(e.socketDir,{recursive:!0}),{...t,HOME:e.runtimeHomeDir,AGENT_BROWSER_SOCKET_DIR:e.socketDir,AGENT_BROWSER_IDLE_TIMEOUT_MS:String(v(t)),AGENT_BROWSER_ARGS:_(t.AGENT_BROWSER_ARGS,e)}}function J(e){if(e.runtimeHomeDir!==e.homeDir){f.mkdirSync(m.dirname(e.runtimeHomeDir),{recursive:!0});try{let t=f.lstatSync(e.runtimeHomeDir);if(t.isSymbolicLink()&&f.readlinkSync(e.runtimeHomeDir)===e.homeDir||t.isDirectory())return;t.isSymbolicLink()&&f.unlinkSync(e.runtimeHomeDir)}catch(e){if(!ie(e))throw e}try{f.symlinkSync(e.homeDir,e.runtimeHomeDir,`dir`)}catch{f.mkdirSync(e.runtimeHomeDir,{recursive:!0})}}}function Y(e){f.writeFileSync(m.join(e.installDir,`manifest.json`),JSON.stringify({package:L,version:I,node:process.version,installedAt:new Date().toISOString()},null,2),`utf8`)}function X(e){return f.existsSync(m.join(e,`manifest.json`))}function Z(e){let t=m.join(e,`package`);return m.join(t,`node_modules`,`.bin`,process.platform===`win32`?`agent-browser.cmd`:`agent-browser`)}function Q(e){return new t(`TOOL_MISSING`,`Managed web browser backend is not installed.`,{version:I,installDir:e.installDir,hint:e.nodeSupported===!1?`Web automation requires Node 24+; current Node is ${process.version}.`:"Run `agent-device web setup` to install the managed web backend."})}function te(e){if(!(e>=24))throw new t(`UNSUPPORTED_OPERATION`,`Web automation requires Node 24 or newer.`,{currentNode:process.version,requiredNodeMajor:24,hint:`Run agent-device with Node 24+ for web setup and web automation.`})}function ne(e){if(process.platform===`win32`)return m.join(e,`home`);let t=d.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return m.join(p.tmpdir(),`agent-device-web`,t)}function re(e){let t=d.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return m.join(p.tmpdir(),`adw`,t)}function ie(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function ae(e){try{return f.accessSync(e,f.constants.X_OK),!0}catch{return!1}}function oe(){return m.join(process.env.HOME??process.cwd(),`.agent-device`)}function $(e){let r=n(e);return r.code===`TOOL_MISSING`?new t(r.code,r.message,{...r.details??{},hint:typeof r.details?.hint==`string`?r.details.hint:"Run `agent-device web setup` to install the managed web backend."}):r}export{S as a,B as i,U as n,C as o,$ as r,x as s,F as t};
@@ -0,0 +1,3 @@
1
+ import{t as e}from"./rolldown-runtime.js";import{S as t,_ as n,a as r,v as i,w as a}from"./sdk-contracts.js";import{A as o,C as s,F as c,b as l,j as u,v as d,x as f}from"./sdk-android-adb.js";import{v as p}from"./sdk-batch.js";import{At as m,Dn as ee,Sn as te,Vt as ne,kn as re,kt as ie,nr as h,rr as g,xn as ae}from"./tv-remote.js";import{$ as oe,E as se,T as ce,Y as le,Z as ue,at as de,g as fe,h as pe,it as me,k as he,l as ge,m as _e,n as ve,nt as _,q as ye,s as be,u as xe,v,w as y,x as Se,y as Ce}from"./snapshot-diagnostics.js";import{n as b,t as we}from"./version.js";import{n as Te}from"./path-resolution.js";import{a as Ee,o as De,u as Oe}from"./sdk-device.js";import{_ as ke,g as Ae,h as x,l as je,m as Me,p as Ne,u as S,v as Pe,x as Fe,y as C}from"./sdk-batch-runner.js";import{t as w}from"./timeouts.js";import{u as Ie}from"./host-process.js";import{S as Le,c as Re,g as ze,h as Be,i as Ve,m as He}from"./registry.js";import{n as Ue,t as We}from"./url.js";import{t as Ge}from"./client-metro-companion.js";import{n as Ke,r as qe}from"./project-runtime.js";import{t as Je}from"./runtime-transport.js";import{t as Ye}from"./command-metadata.js";import{createHash as Xe,randomUUID as Ze}from"node:crypto";import T from"node:fs";import Qe from"node:os";import E from"node:path";import D from"node:http";import O from"node:https";import{pipeline as k}from"node:stream/promises";import{Transform as $e,Writable as et}from"node:stream";import A from"node:net";async function tt(e,t){let n=T.statSync(e),r=E.basename(e),i=n.isDirectory(),a=it(t)??rt(e,n),o=[];try{let t=i?await nt(e,o):e,n=T.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await ot(t),sizeBytes:n.size,cleanup:()=>at(o)}}catch(e){throw at(o),e}}async function nt(e,t){let n=T.mkdtempSync(E.join(Qe.tmpdir(),`agent-device-upload-${Ze()}-`));t.push(n);let r=E.join(n,`${E.basename(e)}.tar.gz`);return await d(`tar`,[`czf`,r,`-C`,E.dirname(e),E.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function rt(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function it(e){return e===`ios`||e===`android`?e:void 0}function at(e){for(let t of e)T.rmSync(t,{recursive:!0,force:!0})}async function ot(e){let t=Xe(`sha256`),r=new et({write(e,n,r){t.update(e),r()}});return await k(T.createReadStream(e),r).catch(e=>{throw new n(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),t.digest(`hex`)}function st(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=ut(i),c=Math.min(i,r+s);return new $e({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function ct(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${lt(e)}\n`)}}function lt(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${j(e.totalBytes)}) via ${dt(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${j(e.transferredBytes)} of ${j(e.totalBytes)}`;case`progress`:return`Uploaded ${j(e.transferredBytes)} of ${j(e.totalBytes)} (${ft(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${dt(e.to)} upload`}}function ut(e){return Math.max(8388608,Math.ceil(e*.05))}function dt(e){return e===`direct`?`direct`:`legacy`}function ft(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function j(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const pt=300*1e3,mt=`uploadStreamRetryable`;async function ht(e){return await M({...e,url:e.url,redirectCount:0,startOffset:0})}function gt(e){return e instanceof n&&e.details?.[mt]===!0}async function M(e){let t=e.url.protocol===`https:`?O:D,r=T.statSync(e.payloadPath).size,i=yt(e.headers,e.startOffset,r);return vt(e.progress,e.startOffset,r),await new Promise((a,o)=>{let s=!1,c=t.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i},t=>{s=!0,le(t).then(i=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&bt(s)){if(e.redirectCount>=5){o(new n(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);M({...e,url:t,redirectCount:e.redirectCount+1}).then(a,o);return}let u=xt(s)?St(t.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new n(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}M({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:t.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new n(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:pt,...e.timeoutHint?{hint:e.timeoutHint}:{},..._t(e)}))},pt);c.on(`error`,t=>{s||(clearTimeout(l),o(new n(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},..._t(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),k(T.createReadStream(e.payloadPath,{start:e.startOffset}),st({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??E.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:r,onProgress:e.progress?.onProgress}),c).catch(e=>{s||(c.destroy(),o(new n(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:Error(String(e)))))})})}function _t(e){return e.retryable===!0?{[mt]:!0}:{}}function vt(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function yt(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function bt(e){return[301,302,303,307,308].includes(e)}function xt(e){return e===308}function St(e,t){let n=Ct(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=wt(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function Ct(e){let t=wt(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function wt(e){return Array.isArray(e)?e[0]:e}const Tt=30*1e3;async function Et(e){let t=await tt(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=Ze();try{let i=await At({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Dt({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await kt({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await kt({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Dt(e){let t=async t=>(await Nt(e.artifact,t,e.onProgress),await Pt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Ot(n))return;let r=await At({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function Ot(e){return e instanceof n?gt(e):!0}async function kt(e){let{normalizedBase:t,token:r,artifact:i}=e,a=new URL(`upload`,t),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,_(r));let s=await ht({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new n(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof n?e:new n(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function At(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,_(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(Tt),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return jt(await r.json().catch(()=>void 0))}function jt(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Mt(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Mt(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Nt(e,t,r){let i=await ht({url:new URL(t.url),method:`PUT`,headers:t.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:e.fileName,onProgress:r}});if(i.statusCode<200||i.statusCode>=300)throw new n(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function Pt(e){let t=new URL(`upload/finalize`,e.normalizedBase),r={"content-type":`application/json`};Object.assign(r,_(e.token));let i=await fetch(t,{method:`POST`,headers:r,signal:AbortSignal.timeout(Tt),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new n(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!i.ok)throw new n(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new n(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Ft(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=ct();if(!Zt(t))return Bt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});r=Lt(e,n,r,a);let c=await Vt(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await It(e,t,n,s)??o),Bt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}async function It(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=zt(a,e.meta?.cwd);if(o)return await Et({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function Lt(e,t,n,r){let i=Ht(e,t);if(!i)return n;i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=Rt(n,i.flagPath);return r[i.field]=i.localPath,a}function Rt(e,t){return t===void 0?e:{...e??{},out:t}}function zt(e,t){let n=E.isAbsolute(e)?e:E.resolve(t??process.cwd(),e);return T.existsSync(n)?n:void 0}function Bt(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function Vt(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=E.isAbsolute(i)?i:E.resolve(e.meta?.cwd??process.cwd(),i);if(!T.existsSync(a))return{installSource:{...r,path:a}};let o=await Et({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function Ht(e,t){if(e.command===`screenshot`){let n=Kt(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:P(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:P(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!Wt(e)&&e.flags?.platform===void 0)return null;let t=Ut(e),n=Gt(Kt(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:P(`recording`,E.extname(n)||t)}}return null}function Ut(e){return oe(e.flags?.platform)}function Wt(e){return N(e.positionals?.[1])||N(e.flags?.out)}function Gt(e,t){return t.flags?.platform===`web`?ue(e,Ut(t)):e}function Kt(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`,o=N(i)?i:a;return E.isAbsolute(o)?o:E.resolve(e.meta?.cwd??process.cwd(),o)}function N(e){return typeof e==`string`&&e.trim().length>0}function P(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return E.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}async function qt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=Jt(n,t);await Yt({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta}),i[n.field]=r,a.push({...n,localPath:r})}return i.artifacts=a,{ok:!0,data:i}}function Jt(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return E.resolve(t.meta?.cwd??process.cwd(),r)}async function Yt(e){let t=new URL(Xt(e.baseUrl,e.artifactId)),r=t.protocol===`https:`?O:D;await T.promises.mkdir(E.dirname(e.destinationPath),{recursive:!0}),await new Promise((i,a)=>{let o=!1,s=e.timeoutMs??9e4,c=t=>{if(!o){if(o=!0,clearTimeout(u),t){T.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(t));return}i()}},l=r.request({protocol:t.protocol,host:t.hostname,port:t.port,method:`GET`,path:t.pathname+t.search,headers:{..._(e.token),...me(e.requestScope?.tenantId)}},t=>{if((t.statusCode??500)>=400){let r=``;t.setEncoding(`utf8`),t.on(`data`,e=>{r+=e}),t.on(`end`,()=>{c(new n(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestScope?.requestId,body:r}))});return}t.on(`aborted`,()=>{c(new n(`COMMAND_FAILED`,`Remote artifact download was interrupted`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId}))}),k(t,T.createWriteStream(e.destinationPath)).then(()=>c(),e=>c(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let t=new n(`COMMAND_FAILED`,`Remote artifact download timed out`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s});c(t),l.destroy(t)},s);l.on(`error`,t=>{if(t instanceof n){c(t);return}c(new n(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s},t instanceof Error?t:void 0))}),l.end()})}function Xt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function Zt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const Qt=3e3,$t=1e3;function en(e){let t=dn(e);if(!t||typeof t!=`object`)return null;let n=t,r=tn(n);if(!r)return null;let i=nn(n);return i?{token:r,...i,transport:rn(n.transport),pid:F(n.pid)??0,version:an(n.version),codeSignature:an(n.codeSignature),processStartTime:an(n.processStartTime)}:null}function tn(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function nn(e){let t=F(e.port),n=F(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function rn(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function an(e){return typeof e==`string`?e:void 0}function F(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function I(e){let t=dn(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function L(e){fn(e)}function R(e){fn(e)}function on(e){let t=B(e);if(!t.hasLock||t.hasInfo)return;let n=I(e.lockPath);if(!n){R(e.lockPath);return}v(n.pid,n.processStartTime)||R(e.lockPath)}async function z(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=T.existsSync(e.infoPath),n=en(e.infoPath);if(n){let t=v(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await V(n),i.stoppedInfoProcess=!0),L(e.infoPath),i.removedInfo=!0)}else t&&(L(e.infoPath),i.removedInfo=!0);let a=T.existsSync(e.lockPath),o=I(e.lockPath);if(o){let t=v(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await Ce(o.pid,{termTimeoutMs:Qt,killTimeoutMs:$t,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),R(e.lockPath),i.removedLock=!0)}else a&&(R(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return u({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function B(e){return{hasInfo:T.existsSync(e.infoPath),hasLock:T.existsSync(e.lockPath)}}async function sn(e){let t=B(e);if(!t.hasLock||t.hasInfo)return!1;let n=I(e.lockPath);return!n||!v(n.pid,n.processStartTime)?(R(e.lockPath),!0):!1}async function V(e){await Ce(e.pid,{termTimeoutMs:Qt,killTimeoutMs:$t,expectedStartTime:e.processStartTime})}function cn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function ln(e,t=y(process.env.AGENT_DEVICE_STATE_DIR)){let n=un(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function un(e){return`rm -f ${fe(e.infoPath)} ${fe(e.lockPath)}`}function dn(e){if(!T.existsSync(e))return null;try{return JSON.parse(T.readFileSync(e,`utf8`))}catch{return null}}function fn(e){try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}function pn(e,t){if(t.onProgress){t.onProgress(e);return}e.type===`command`&&(t.req.command===`doctor`&&Le(),process.stderr.write(`${e.message}\n`))}function H(e,t,r){return new n(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:t},r instanceof Error?r:void 0)}function mn(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(H(e.req,n,r))}if(ge(r))try{return pn(r.event,{req:e.req,onProgress:e.onProgress}),!1}catch(e){return t(e)}return xe(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(H(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function hn(e,t){return _e(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function gn(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=mn({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=pe(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return})}function _n(e,t){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=t,s=``,c=!1,l=mn({req:r,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=pe(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(H(r,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new n(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},e instanceof Error?e:void 0)))})}function vn(e,t){let{info:r,req:i,resolve:a,reject:o}=t;try{let t=yn(e);if(t.error){o(bn(t.error,i.meta?.requestId));return}if(!t.result||typeof t.result!=`object`){o(new n(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}xn(r,i,t.result,a,o)}catch(t){o(new n(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function yn(e){return JSON.parse(e)}function bn(e,t){let r=e.data??{};return new n(a(r.code==null?void 0:String(r.code),`COMMAND_FAILED`),String(r.message??e.message??`Daemon RPC request failed`),{...typeof r.details==`object`&&r.details?r.details:{},hint:typeof r.hint==`string`?r.hint:void 0,diagnosticId:typeof r.diagnosticId==`string`?r.diagnosticId:void 0,logPath:typeof r.logPath==`string`?r.logPath:void 0,retriable:typeof r.retriable==`boolean`?r.retriable:void 0,supportedOn:typeof r.supportedOn==`string`?r.supportedOn:void 0,requestId:t})}async function xn(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await qt(e,t,n):n)}catch(e){i(e)}}function Sn(e,t){let n=e.meta?.requestId??o();return Cn(e.command)?{jsonrpc:`2.0`,id:n,method:wn(e.command),params:Tn(e,e.command,t)}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Cn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function wn(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Tn(e,t,n){return ee(te(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const En=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,`xcodebuild .*AgentDeviceRunner\\.env\\.session-`,`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj`];function Dn(e){let t=p(e.command);if(t.envelopeMs===`unbounded`)return;let n={...t,envelopeMs:t.envelopeMs};return On(n,e.positionals??[])??kn(n,e.flags)??n.envelopeMs}function On(e,t){if(e.budget.source!==`positional-parser`)return;let n=e.budget.parser(t);return n===null?void 0:jn(e,n)}function kn(e,t){if(e.budget.source===`flag`)return e.budget.envelope===`widen`?An(e,e.budget,t):typeof t?.timeoutMs==`number`?t.timeoutMs:e.envelopeMs}function An(e,t,n){if(n?.settle!==!0)return e.envelopeMs;let r=typeof n.timeoutMs==`number`?n.timeoutMs:t.defaultBudgetMs;return typeof r==`number`?Mn(e,r):e.envelopeMs}function jn(e,t){return Math.max(e.envelopeMs,t+Rn)}function Mn(e,t){return Math.max(e.envelopeMs,e.envelopeMs+t+Rn)}function Nn(e,t,r,i,a,o){let s=a?{terminated:0}:In(),c=!a&&Pn(i),l=c?Ln(e,t):{forcedKill:!1};return u({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:r,command:i,timedOutRunnerPidsTerminated:s.terminated,timedOutRunnerCleanupError:s.error,daemonPidReset:c?e.pid:void 0,daemonPidForceKilled:c?l.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!c,daemonBaseUrl:e.baseUrl}}),new n(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:r,hint:Fn({remote:a,resetDaemon:c,command:i})})}function Pn(e){return p(e).onTimeout===`reset-daemon`}function Fn(e){let{remote:t,resetDaemon:n,command:r}=e;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=r===g.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`}function In(){let e=0;try{for(let t of En)s(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function Ln(e,t){let n=!1;try{v(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{V(e)}finally{L(t.infoPath),R(t.lockPath)}return{forcedKill:n}}const Rn=3e4,zn=`Daemon HTTP endpoint is unavailable`,Bn=`Daemon socket endpoint is unavailable`;async function Vn(e,t){let n=Xn(e,t);if(await Hn(e,n))return!0;let r=Zn(e,t,n);return r?await Hn(e,r):!1}async function Hn(e,t){return t===`http`?await Wn(e):await Un(e.port)}function Un(e){return e?new Promise(t=>{let n=!1,r=A.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function Wn(e){return Kn(e).then(e=>e.reachable)}async function Gn(e){let t=await Kn(e);if(!e.baseUrl||!t.reachable)return t;if(typeof t.rpcProtocolVersion==`number`&&t.rpcProtocolVersion!==2)throw new n(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:b(),remoteVersion:t.version,remoteService:t.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:t.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return t}function Kn(e){let t=e.baseUrl?de(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return Promise.resolve({reachable:!1});let n=new URL(t),r=n.protocol===`https:`?O:D,i=e.baseUrl?3e3:500;return new Promise(t=>{let a=e.baseUrl?_(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...qn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function qn(e){try{let t=JSON.parse(e);return{service:typeof t.service==`string`?t.service:void 0,version:typeof t.version==`string`?t.version:void 0,rpcProtocolVersion:typeof t.rpcProtocolVersion==`number`?t.rpcProtocolVersion:void 0}}catch{return{}}}async function Jn(e,t,n,r,i,a={}){let o=Xn(e,n);try{return await Yn(e,t,r,i,o,a)}catch(s){let c=Zn(e,n,o);if(!c||!Qn(s,o))throw s;return await Yn(e,t,r,i,c,a)}}async function Yn(e,t,n,r,i,a){return i===`http`?await nr(e,t,n,r,a):await tr(e,t,n,r,a)}function Xn(e,t){if(e.baseUrl){if(t===`socket`)throw new n(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return $n(e,t);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>U(e,t));if(r)return r;throw new n(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function U(e,t){return t===`http`?!!e.httpPort:!!e.port}function Zn(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return U(e,r)?r:null}function Qn(e,t){return t===`socket`&&e instanceof n&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function $n(e,t){if(U(e,t))return t;throw new n(`COMMAND_FAILED`,t===`http`?zn:Bn)}function er(e,t,r,i={}){return u({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new n(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:t,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},e instanceof Error?e:void 0)}async function tr(e,t,r,i,a){let o=e.port;if(!o)throw new n(`COMMAND_FAILED`,Bn);return new Promise((n,s)=>{let c=!1,l=A.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(Nn(e,r,t.meta?.requestId,t.command,!1,i))},i):void 0;gn(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,n(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(er(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function nr(e,t,r,i,a){let o=e.baseUrl?new URL(de(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new n(`COMMAND_FAILED`,zn);let s=JSON.stringify(Sn(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};return e.baseUrl&&Object.assign(c,_(e.token)),await new Promise((l,u)=>{let d=(o.protocol===`https:`?O:D).request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},r=>{if(hn(t,r.headers?.[`content-type`])){_n(r,{req:t,onProgress:a.onProgress,reject:u,clearTimeout:()=>{p&&clearTimeout(p)},handleResponseBody:n=>vn(n,{info:e,req:t,resolve:l,reject:u})});return}le(r).then(n=>{p&&clearTimeout(p),vn(n,{info:e,req:t,resolve:l,reject:u})}).catch(e=>{p&&clearTimeout(p),u(new n(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),f=cn(e),p=typeof i==`number`?setTimeout(()=>{d.destroy(),u(Nn(e,r,t.meta?.requestId,t.command,f,i))},i):void 0;d.on(`error`,e=>{p&&clearTimeout(p),u(er(e,t.meta?.requestId,f))}),d.write(s),d.end()})}const W=15e3,G=new A.BlockList;G.addSubnet(`127.0.0.0`,8,`ipv4`),G.addAddress(`::1`,`ipv6`),G.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function rr(e){let t=ir(e),n=ar(e),r=or(e,n.remoteBaseUrl),i=sr(e,t,n.rawBaseUrl);return{paths:y(i?cr():t),transportPreference:r.preference,serverMode:r.serverMode,ownedStateDir:i,remoteBaseUrl:n.remoteBaseUrl,remoteAuthToken:n.authToken}}function ir(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function ar(e){let t=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,n=kr(t),r=e.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Ar(n,r),{rawBaseUrl:t,remoteBaseUrl:n,authToken:r}}function or(e,t){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=se(r);if(t&&i===`socket`)throw new n(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});return{preference:i,serverMode:ce(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0))}}function sr(e,t,n){return Sr(e.command)&&!t&&!n}function cr(){return T.mkdtempSync(E.join(Qe.tmpdir(),`agent-device-replay-daemon-`))}async function lr(e){if(e.remoteBaseUrl)return await ur(e);let t=await dr(e);return t?{info:t,startedByClient:!1}:(on(e.paths),await _r(e))}async function ur(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await Gn(t)).reachable)return{info:t,startedByClient:!1};throw new n(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function dr(e){let t=en(e.paths.infoPath);if(!t)return null;let n=await fr(t,e.transportPreference);return mr(t,n)?t:(hr(t,n,e.paths.baseDir),await V(t),L(e.paths.infoPath),null)}async function fr(e,t){try{return await Vn(e,t)}catch(e){if(pr(e))return!1;throw e}}function pr(e){return e instanceof n&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function mr(e,t){return e.version===b()&&e.codeSignature===Er()&&t}function hr(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,i=gr(e,t);process.stderr.write(`Replacing daemon (${r}) in ${n}: ${i}\n`)}catch{}}function gr(e,t){return e.version===b()?e.codeSignature===Er()?t?`not reusable`:`unreachable`:`code-signature mismatch`:`version mismatch (client v${b()})`}async function _r(e){let t=0,r=[],i,a;for(let n=1;n<=2;n+=1){let o;try{o=wr(e),a={pid:o.pid}}catch(t){if(i=t instanceof Error?t.message:String(t),r.push(await z(e.paths,`start_error`)),n<2){await w(150);continue}break}let s=await Cr(W,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=Dr(s.exit),r.push(await z(e.paths,`start_error`)),n<2){await w(150);continue}break}if(await sn(e.paths)){t+=1;continue}let c=B(e.paths),l=n<2,u=await z(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Cr(W,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=Dr(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await w(150)}let o=B(e.paths),s=Or(e.paths.logPath);throw new n(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:W,startupAttempts:2,lockRecoveryCount:t,cleanupResults:r,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:ln(o,e.paths)})}async function vr(e,t,n,r){if(!Sr(e.command)||!t.startedByClient&&!n.ownedStateDir||cn(t.info)||br(r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await V(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=T.existsSync(n.paths.infoPath);L(n.paths.infoPath),i.removedInfo=e&&!T.existsSync(n.paths.infoPath);let t=T.existsSync(n.paths.lockPath);if(R(n.paths.lockPath),i.removedLock=t&&!T.existsSync(n.paths.lockPath),n.ownedStateDir){let e=he(n.paths.sessionsDir);e?a=yr(r,e):(T.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!T.existsSync(n.paths.baseDir))}}return u({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function yr(e,r){if(e&&!e.ok)return e;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`;return{ok:!1,error:t(new n(`REPAIR_COMMIT_FAILED`,`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`))}}function br(e){if(!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`)return!1;let t=e.error.details?.divergence;if(!t||typeof t!=`object`)return!1;let n=t.resume;return!n||typeof n!=`object`?!1:n.repairSessionHeld===!0}function xr(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Sr(e){return e===g.replay||e===g.test}async function Cr(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=en(t.paths.infoPath);if(e&&await Vn(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await w(100)}return{kind:`timeout`}}function wr(e){let t=Tr(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};T.mkdirSync(e.paths.baseDir,{recursive:!0});let i=T.openSync(e.paths.logPath,`a`),a=T.openSync(e.paths.logPath,`a`);try{return f(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{T.closeSync(i),T.closeSync(a)}}function Tr(){let e=we(),t=[E.join(e,`dist`,`src`,`internal`,`daemon.js`),E.join(e,`dist`,`src`,`daemon.js`)],r=t[0];if(r===void 0)throw new n(`COMMAND_FAILED`,`Daemon dist path list is empty`);let i=t.find(e=>T.existsSync(e))??r,a=E.join(e,`src`,`daemon.ts`),o=t.some(e=>T.existsSync(e)),s=T.existsSync(a);if(!o&&!s)throw new n(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:t,srcPath:a});return{root:e,distPath:i,distPaths:t,srcPath:a,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!o)&&s}}function Er(){let e=Tr();return Se(e.useSrc?e.srcPath:e.distPath,e.root)}function Dr(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function Or(e){try{if(!T.existsSync(e))return;let t=T.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=T.openSync(e,`r`);try{let e=Buffer.alloc(n);T.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{T.closeSync(r)}}catch{return}}function kr(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new n(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new n(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function Ar(e,t){if(!e)return;let r=new URL(e).hostname;if(!jr(r)&&!(typeof t==`string`&&t.trim().length>0))throw new n(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function jr(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:A.isIPv4(t)?G.check(t,`ipv4`):A.isIPv6(t)?G.check(t,`ipv6`):!1}async function Mr(e,t={}){let n=e.meta?.requestId??o(),r=!!(e.meta?.debug||e.flags?.verbose),i=rr(e),a=Dn(e),s=await c(`daemon_startup`,async()=>await lr(i),{requestId:n,session:e.session}),l=s.info,d=await Ft(e,l);Fr(e.command);let f={...e,positionals:d.positionals,flags:d.flags,token:l.token,meta:{...e.meta??{},requestId:n,debug:r,includeCost:e.meta?.includeCost,cwd:e.meta?.cwd,sessionExplicit:e.meta?.sessionExplicit,tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,sessionIsolation:e.meta?.sessionIsolation??e.flags?.sessionIsolation,lockPolicy:e.meta?.lockPolicy,lockPlatform:e.meta?.lockPlatform,...d.uploadedArtifactId?{uploadedArtifactId:d.uploadedArtifactId}:{},...d.clientArtifactPaths?{clientArtifactPaths:d.clientArtifactPaths}:{},...d.installSource?{installSource:d.installSource}:{}}};return u({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:e.command,session:e.session}}),await Nr(e,s,i,async()=>Pr(await c(`daemon_request`,async()=>await Jn(l,f,i.transportPreference,i.paths,a,t),{requestId:n,command:e.command}),i))}async function Nr(e,t,r,i){let a,o=!1,s;try{a=await i()}catch(e){o=!0,s=e}let c=await vr(e,t,r,a);if(o)throw s;if(!c)throw new n(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function Pr(e,t){return e.ok||!t.ownedStateDir||!br(e)?e:xr(e,t.paths.baseDir)}function Fr(e){!Ir(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===g.reinstall?`Reinstalling...
2
+ `:`Installing...
3
+ `)}function Ir(e){return e===g.install||e===g.reinstall||e===h.installSource}const Lr=8081,Rr=`.expo/.virtual-metro-entry.bundle`;function zr(e,t){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new n(`INVALID_ARGS`,`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}function Br(e){let t=K(e.bundleUrl),r=t??e.runtime?.bundleUrl,i=!!t,a=!!K(r),o=Je({metroHost:Vr(e,i,a),metroPort:Hr(e,i,a),bundleUrl:r});if(!o)throw new n(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=Ur(r);return{reloadUrl:Wr(o,o.scheme,`${s}/reload`),messageSocketUrl:Wr(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function Vr(e,t,n){return K(e.metroHost)??(t?void 0:K(e.runtime?.metroHost))??(n?void 0:`localhost`)}function Hr(e,t,n){if(e.metroPort!==void 0)return zr(e.metroPort,Lr);if(!t)return e.runtime?.metroPort??(n?void 0:Lr)}function Ur(e){let t=K(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${Rr}`;if(r.endsWith(i))return r.slice(0,-i.length);let a=r.lastIndexOf(`/`);return(a>=0?r.slice(a+1):r).endsWith(`.bundle`)&&a>0?r.slice(0,a):``}function Wr(e,t,n){let r=new URL(`${t}://localhost`);return r.hostname=e.host,r.port=String(e.port),r.pathname=n,r.toString()}function K(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function Gr(e){return typeof e==`string`&&e.trim()?Ue(e.trim()):``}function q(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function J(e,t,n){return Te(e,{env:t,cwd:n})}function Kr(e){try{return T.accessSync(e,T.constants.F_OK),!0}catch{return!1}}function qr(e){try{return T.statSync(e).isDirectory()}catch{return!1}}function Jr(e){let t=E.join(e,`package.json`),r=qe(e);if(!r)throw new n(`INVALID_ARGS`,`package.json not found at ${t}`);return r}const Yr=[{file:`pnpm-lock.yaml`,command:`pnpm`},{file:`yarn.lock`,command:`yarn`},{file:`bun.lock`,command:`bun`},{file:`bun.lockb`,command:`bun`},{file:`package-lock.json`,command:`npm`}];function Xr(e){let t=e;for(;;){for(let{file:e,command:n}of Yr)if(Kr(E.join(t,e)))return{command:n,installArgs:[`install`]};if(Kr(E.join(t,`.git`)))return null;let e=E.dirname(t);if(e===t)return null;t=e}}function Zr(e){return Xr(e)??{command:`npm`,installArgs:[`install`]}}function Qr(e,t){if(t!==`auto`)return t;let n=Ke(e);return n===`expo`||n===`repack`?n:`react-native`}function $r(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function ei(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>Kr(E.join(e,`${t}.config.${n}`)))}function ti(e,t){return ei(e,`rspack`)?`rspack`:ei(e,`webpack`)?`webpack`:$r(t,`@rspack/core`)?`rspack`:$r(t,`webpack`)?`webpack`:`rspack`}function ni(e,t,n){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);return Number.isInteger(r)?Math.max(r,n):t}function ri(e){return e===`expo`?Rr:`index.bundle`}function ii(e,t,n){return{platform:t,bundleUrl:We(e,t,ri(n))}}function ai(e,t){return{platform:t,metroHost:q(e?.metro_host),metroPort:e?.metro_port,bundleUrl:q(e?.metro_bundle_url),launchUrl:q(e?.launch_url)}}function oi(e,t){if(qr(E.join(e,`node_modules`)))return{installed:!1};let n=Zr(e);try{s(n.command,n.installArgs,{cwd:e,env:t})}catch(e){throw si(e,n)}return{installed:!0,packageManager:n.command}}function si(e,t){let r=i(e),a=`Dependency install failed using detected package manager "${t.command}". If dependencies are already installed (for example via a monorepo root install), pass --no-install-deps to skip this step, or install manually with "${t.command} ${t.installArgs.join(` `)}" from the project root.`;return new n(r.code,r.message,{...r.details??{},hint:a,packageManager:t.command},r)}async function ci(e){await w(e)}async function li(e,t,r={}){try{let n=await fetch(e,{headers:r,signal:AbortSignal.timeout(t)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new n(`COMMAND_FAILED`,`Timed out fetching ${e} after ${t}ms`):r}}async function ui(e,t){try{let n=await li(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function di(e,t,n,r){return e===`expo`?{command:`npx`,installArgs:[`expo`,`start`,`--host`,`lan`,`--port`,String(n)]}:e===`repack`?{command:`npx`,installArgs:[`react-native`,t===`webpack`?`webpack-start`:`rspack-start`,`--host`,r,`--port`,String(n)]}:{command:`npx`,installArgs:[`react-native`,`start`,`--host`,r,`--port`,String(n)]}}function fi(e,t,r,i,a,o,s){let c=di(t,r,i,a);T.mkdirSync(E.dirname(o),{recursive:!0});let u=T.openSync(o,`a`),d=0;try{d=l(c.command,c.installArgs,{cwd:e,env:s,stdio:[`ignore`,u,u]})}finally{T.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new n(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function pi(e){if(!(!Number.isInteger(e)||e<=0)){try{process.kill(e,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await Ie(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await Ie(e,1e3)}}}function mi(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function Y(e,t){let r=new n(`COMMAND_FAILED`,e);return r.retryable=t,r}function hi(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function gi(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function _i(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:mi(e.baseUrl,e.bearerToken),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?Y(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):Y(t instanceof Error?t.message:String(t),!0)}let n=vi(await t.text(),t.status,e.baseUrl);if(!t.ok)throw Y(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,hi(t.status,n));return bi(n)}function vi(e,t,n){if(!e)return{};try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Expected a JSON object`);return t}catch(r){let i=e.slice(0,200);throw Y(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,hi(t,e))}}function yi(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:ai(e.ios_runtime,`ios`),androidRuntime:ai(e.android_runtime,`android`),upstream:{bundleUrl:e.upstream.bundle_url??``,host:e.upstream.host??``,port:e.upstream.port??0,statusUrl:e.upstream.status_url??``},probe:{reachable:e.probe.reachable,statusCode:e.probe.status_code,latencyMs:e.probe.latency_ms,detail:e.probe.detail}}}function bi(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw Y(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return yi(t)}catch(e){throw Y(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function X(e,t,n,r,i){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&a.push(`bridgeError=${t}`),n?.probe.reachable===!1&&a.push(`bridgeProbe=${n.probe.detail||`unreachable (status ${n.probe.statusCode||0})`}`),r&&r!==t&&a.push(`initialBridgeError=${r}`),i&&a.push(`metroCompanionLog=${i}`),a.join(` `)}function xi(e,t){if(!t?.iosRuntime.bundleUrl)throw new n(`COMMAND_FAILED`,X(e,`bridge descriptor is missing ios_runtime.metro_bundle_url`,t))}function Si(e,t,r){let i=t||q(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||e&&q(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(e&&!a)throw new n(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!e&&i)throw new n(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(e&&a),proxyBaseUrl:e,proxyBearerToken:a}}function Ci(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new n(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return e}function wi(e,t){if(!(e||t))throw new n(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function Ti(e,t,n){return e.runtimeFilePath?J(e.runtimeFilePath,t,n):null}function Ei(e,t,n,r){return J(e.logPath??E.join(r,`.agent-device`,`metro.log`),t,n)}function Di(e){let t=e.env??process.env,n=process.cwd(),r=J(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=Jr(r),o=Qr(a,i)):o=i;let s=null;o===`repack`&&(a??=Jr(r),s=ti(r,a));let c=Gr(e.publicBaseUrl),l=Gr(e.proxyBaseUrl);wi(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=Si(l,q(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:zr(e.metroPort??8081,8081),listenHost:q(e.listenHost)??`0.0.0.0`,statusHost:q(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?Ci(e.bridgeScope):null,startupTimeoutMs:ni(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:ni(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:Ti(e,t,n),logPath:Ei(e,t,n,r)}}async function Oi(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await ui(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await ci(i)}return!1}async function ki(e){let t=Date.now()+e.startupTimeoutMs,r=null,i=null;for(;Date.now()<t;){try{let t=await _i({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(t.probe.reachable!==!1)return t;r=t,i=null}catch(t){if(i=t instanceof Error?t.message:String(t),!gi(t))throw new n(`COMMAND_FAILED`,X(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath),void 0,t)}let a=Math.min(1e3,Math.max(t-Date.now(),0));a>0&&await ci(a)}throw new n(`COMMAND_FAILED`,X(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath))}async function Ai(e){let t=`http://${e.statusHost}:${e.metroPort}/status`;if(e.reuseExisting&&await ui(t,e.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:t};let r=fi(e.projectRoot,e.kind,e.repackBundler,e.metroPort,e.listenHost,e.logPath,e.env);if(await Oi(t,e.startupTimeoutMs,e.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:t};throw await pi(r.pid).catch(()=>{}),new n(`COMMAND_FAILED`,`React Native dev server did not become ready at ${t} within ${e.startupTimeoutMs}ms. Check ${e.logPath}.`,{logPath:e.logPath})}async function ji(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await _i({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!gi(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await Mi(e,t,n,r,i)),xi(t.proxyBaseUrl,r),r}async function Mi(e,t,r,i,a){let o;try{o=(await Ge({projectRoot:t.projectRoot,serverBaseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${t.statusHost}:${t.metroPort}`,launchUrl:q(e.launchUrl),profileKey:q(e.companionProfileKey),consumerKey:q(e.companionConsumerKey),env:t.env})).logPath}catch(e){throw new n(`COMMAND_FAILED`,X(t.proxyBaseUrl,e instanceof Error?e.message:String(e),i,a),void 0,e)}try{return await ki({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:r,probeTimeoutMs:t.probeTimeoutMs,startupTimeoutMs:t.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function Ni(e,t){return{baseIosRuntime:e?ii(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?ii(e,`android`,t):{platform:`android`}}}function Pi(e,t){e&&(T.mkdirSync(E.dirname(e),{recursive:!0}),T.writeFileSync(e,JSON.stringify(t,null,2)))}async function Fi(e={}){let t=Di(e),n=t.installProjectDeps?oi(t.projectRoot,t.env):{installed:!1},r=await Ai(t),{baseIosRuntime:i,baseAndroidRuntime:a}=Ni(t.publicBaseUrl,t.kind),o=await ji(e,t),s=o?.iosRuntime??i,c=o?.androidRuntime??a,l={projectRoot:t.projectRoot,kind:t.kind,dependenciesInstalled:n.installed,packageManager:n.packageManager??null,started:r.started,reused:r.reused,pid:r.pid,logPath:t.logPath,statusUrl:r.statusUrl,runtimeFilePath:t.runtimeFilePath,iosRuntime:s,androidRuntime:c,bridge:o};return Pi(t.runtimeFilePath,l),l}function Ii(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function Li(e,t){await new Promise((r,i)=>{let a=new WebSocket(e),o=e=>{clearTimeout(s);try{a.close()}catch{}i(new n(`COMMAND_FAILED`,e))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${e} after ${t}ms`)},t);a.addEventListener(`open`,()=>{a.send(JSON.stringify({version:2,method:`reload`}));let e=()=>{if(a.bufferedAmount===0){clearTimeout(s),a.close(),r();return}setTimeout(e,20)};e()}),a.addEventListener(`error`,()=>{o(`Failed to reach the dev server message socket at ${e}`)})})}async function Ri(e={}){let t=ni(e.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=Br(e),a=await li(r,t);if(a.ok&&!Ii(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await Li(i,t)}catch(e){throw new n(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},e instanceof Error?e:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}function zi(e,t){return E.join(e,`metro-sessions`,`${ye(t)}.json`)}function Bi(e){let t=zi(e.stateDir,e.session);T.mkdirSync(E.dirname(t),{recursive:!0}),T.writeFileSync(t,`${JSON.stringify(e.hints,null,2)}\n`,`utf8`)}function Vi(e){let t=zi(e.stateDir,e.session),n;try{n=T.readFileSync(t,`utf8`)}catch{return}let r;try{r=JSON.parse(n)}catch{return}if(!r||typeof r!=`object`||Array.isArray(r))return;let i=r,a={};return typeof i.metroHost==`string`&&i.metroHost&&(a.metroHost=i.metroHost),typeof i.metroPort==`number`&&Number.isInteger(i.metroPort)&&(a.metroPort=i.metroPort),typeof i.bundleUrl==`string`&&i.bundleUrl&&(a.bundleUrl=i.bundleUrl),Object.keys(a).length>0?a:void 0}function Hi(e){T.rmSync(zi(e.stateDir,e.session),{force:!0})}const Ui={...Ve(),batch:He(Wi)};function Wi(e,t,r){let i=Ui[e];if(!i)throw Error(`Missing daemon writer for batch command: ${e}`);let a=Ye(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return Ki(i,a,a.readInput(t))}catch(t){throw new n(`INVALID_ARGS`,`Batch step ${r} ${e} input is invalid: ${t instanceof Error?t.message:String(t)}`,void 0,t)}}function Gi(e,t){let n=Ui[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return Ki(n,Ye(e),t)}function Ki(e,t,n){let r=e(n);return{...r,...t?{metadataFlags:ze(t,r.options)}:{}}}function qi(e){throw new n(a(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,retriable:e.retriable,supportedOn:e.supportedOn})}function Ji(e,t){let n=x(e,`bundleId`),r=x(e,`package`);return{app:C(e,`app`),appPath:C(e,`appPath`),platform:Pe(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:ie({session:t,bundleId:n,packageName:r})}}function Yi(e,t){let r=x(e,`bundleId`),i=x(e,`packageName`),a=r??i??x(e,`appId`),o=x(e,`launchTarget`)??i??r??a;if(!o)throw new n(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:x(e,`appName`),appId:a,bundleId:r,packageName:i,launchTarget:o,installablePath:x(e,`installablePath`),archivePath:x(e,`archivePath`),materializationId:x(e,`materializationId`),materializationExpiresAt:x(e,`materializationExpiresAt`),identifiers:ie({session:t,bundleId:r,packageName:i,appId:a})}}function Xi(e){return{released:e.released===!0,materializationId:C(e,`materializationId`),identifiers:{}}}function Zi(e){let{record:t,platform:n,id:r,name:i,target:a}=ea(e,`name`),o=$i(t);return{platform:n,target:a,kind:Ae(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...De(n)&&o?{appleOs:o}:{},identifiers:m(n,r,i),...ta(n,r)}}function Qi(e){let{record:t,platform:n,id:r,name:i,target:a}=ea(e,`name`),o=C(t,`device`),s=$i(t),c={session:i,...m(n,r,o)};return{name:i,createdAt:ke(t,`createdAt`),sessionStateDir:x(t,`sessionStateDir`),runnerLogPath:x(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...s?{appleOs:s}:{},identifiers:c,...ta(n,r,Me(t,`ios_simulator_device_set`))},identifiers:c}}function $i(e){let t=e.appleOs;return Ee(t)?t:void 0}function ea(e,t){let n=je(e);return{record:n,platform:Pe(n,`platform`),id:C(n,`id`),name:C(n,t),target:Ne(n,`target`)}}function ta(e,t,n){return{ios:e===`ios`?{udid:t,...n===void 0?{}:{simulatorSetPath:n}}:void 0,android:e===`android`?{serial:t}:void 0}}function na(e){if(!S(e))return;let t=e.platform,n=x(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=x(e,`bundleUrl`),a=x(e,`launchUrl`);return{platform:t===`ios`||t===`android`?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:a}}function ra(e){let t=e.platform,n=x(e,`id`),r=x(e,`device`);if(!(!Oe(t)||!n||!r))return{platform:t,target:Ne(e,`target`),id:n,name:r,identifiers:m(t,n,r),ios:t===`ios`?{udid:x(e,`device_udid`)??n,simulatorSetPath:Me(e,`ios_simulator_device_set`)}:void 0,android:t===`android`?{serial:x(e,`serial`)??n}:void 0}}function ia(e){if(S(e)&&!(typeof e.durationMs!=`number`||typeof e.measuredAt!=`string`||typeof e.method!=`string`))return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:x(e,`appTarget`),appBundleId:x(e,`appBundleId`)}}function aa(e){if(!S(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=oa(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}function oa(e){if(S(e)&&!(typeof e.code!=`string`||typeof e.message!=`string`))return{code:e.code,message:e.message,...typeof e.hint==`string`?{hint:e.hint}:{},...typeof e.diagnosticId==`string`?{diagnosticId:e.diagnosticId}:{},...typeof e.logPath==`string`?{logPath:e.logPath}:{},...S(e.details)?{details:e.details}:{}}}function sa(e){return Array.isArray(e)?e:[]}function ca(e){let t=ae(e);return Fe({requestId:e.requestId,cwd:e.cwd,sessionExplicit:e.session!==void 0,debug:e.debug,includeCost:e.cost,responseLevel:e.responseLevel,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform,...re(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function la(e){return e??`default`}var ua=e({createAgentDeviceClient:()=>da});function da(e={},t={}){let i=t.transport??Mr,a=t=>r(t.responseLevel??e.responseLevel),o=async(t,n=[],r={},a,o)=>{let s=Q(e,r),c=await i({session:la(s.session),command:t,positionals:n,...o?{input:o}:{},flags:Be(s,a),runtime:s.runtime,meta:ca(s)});return c.ok||qi(c.error),c.data??{}},s=async(e={})=>{let t=await o(h.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(Qi)},c=async(e,t={})=>{let n=Gi(e,t);return await o(n.command,n.positionals,n.options,n.metadataFlags,n.input)},l=(t={})=>la(Q(e,t).session);return{command:{wait:async e=>await c(`wait`,e),alert:async(e={})=>await c(`alert`,e),...xa(c),reactNative:async e=>await c(`react-native`,e),doctor:async(e={})=>await c(`doctor`,e),prepare:async e=>await c(`prepare`,e),viewport:async e=>await c(`viewport`,e)},devices:{list:async(e={})=>{let t=await c(`devices`,e);return(Array.isArray(t.devices)?t.devices:[]).map(Zi)},capabilities:async(e={})=>{let t=await c(`capabilities`,e),n=Array.isArray(t.availableCommands)?t.availableCommands.filter(e=>typeof e==`string`):[];return{device:Zi(t.device),availableCommands:n}},boot:async(e={})=>await c(`boot`,e),shutdown:async(e={})=>await c(`shutdown`,e)},sessions:{list:async(e={})=>await s(e),stateDir:async(t={})=>y(Q(e,t).stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,close:async(t={})=>{let n=l(t);try{let e=await c(`close`,t);return{session:n,shutdown:aa(e.shutdown),provider:Z(e.provider),savedScript:x(e,`savedScript`),identifiers:{session:n}}}finally{Ea(e,t)}},saveScript:async(e={})=>{let t=await o(h.sessionSaveScript,e.path===void 0?[]:[e.path],e,{force:e.force}),r=t.actionCount;if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw new n(`COMMAND_FAILED`,`Daemon returned an invalid saved-script action count.`);let i=C(t,`session`);return{session:i,savedScript:C(t,`savedScript`),actionCount:r,identifiers:{session:i}}},artifacts:async(e={})=>await c(`artifacts`,e)},apps:{install:async e=>Ji(await c(`install`,e),l(e)),reinstall:async e=>Ji(await c(`reinstall`,e),l(e)),installFromSource:async e=>Yi(await c(`install-from-source`,e),l(e)),list:async(e={})=>{let t=await c(`apps`,e);return Array.isArray(t.apps)?t.apps.filter(e=>typeof e==`string`):[]},open:async t=>{let n=l(t),r=await c(`open`,t);Ta({config:e,options:t,runtime:Q(e,t).runtime,sessionReused:r.sessionReused===!0});let i=ra(r),a=x(r,`appBundleId`),o=a,s=Array.isArray(r.warnings)?r.warnings.filter(e=>typeof e==`string`):[];return{session:n,...s.length>0?{warnings:s}:{},sessionStateDir:x(r,`sessionStateDir`),eventLogPath:x(r,`eventLogPath`),appName:x(r,`appName`),appBundleId:a,appId:o,startup:ia(r.startup),runtime:na(r.runtime),device:i,identifiers:{session:n,deviceId:i?.id,deviceName:i?.name,udid:i?.ios?.udid,serial:i?.android?.serial,appId:o,appBundleId:a}}},close:async(e={})=>{let t=l(e),n=await c(`close`,e);return{session:t,closedApp:e.app,shutdown:aa(n.shutdown),savedScript:x(n,`savedScript`),identifiers:{session:t}}},push:async e=>await c(`push`,e),triggerEvent:async e=>await c(`trigger-app-event`,e)},materializations:{release:async e=>Xi(await o(h.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>Da(await o(h.leaseAllocate,[],{...e,leaseId:void 0})),heartbeat:async e=>Da(await o(h.leaseHeartbeat,[],e)),release:async e=>{let t=await o(h.leaseRelease,[],e);return{released:t.released===!0,provider:Z(t.provider)}}},metro:{prepare:async t=>{let n=await Fi({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath});return Sa(e,n),n},reload:async(t={})=>await Ri({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime??Ca(e),timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{let t=l(e),n=await c(`snapshot`,e);return a(e)?n:ya(n,t)},screenshot:async(e={})=>{let t=l(e),n=await c(`screenshot`,e);if(a(e))return n;let r=be(n);return{path:C(n,`path`),width:r?.width,height:r?.height,logicalWidth:r?.logicalWidth,logicalHeight:r?.logicalHeight,pixelDensity:r?.pixelDensity,overlayRefs:r?.overlayRefs,identifiers:{session:t}}},diff:async e=>await c(`diff`,e)},interactions:{click:async e=>await c(`click`,e),press:async e=>await c(`press`,e),longPress:async e=>await c(`longpress`,e),swipe:async e=>await c(`swipe`,e),pan:async e=>await c(`gesture`,fa(e)),fling:async e=>await c(`gesture`,pa(e)),swipeGesture:async e=>await c(`gesture`,ma(e)),focus:async e=>await c(`focus`,e),type:async e=>await c(`type`,e),fill:async e=>await c(`fill`,e),scroll:async e=>await c(`scroll`,e),pinch:async e=>await c(`gesture`,ha(e)),rotateGesture:async e=>await c(`gesture`,ga(e)),transformGesture:async e=>await c(`gesture`,_a(e)),get:async e=>await c(`get`,e),is:async e=>await c(`is`,e),find:async e=>await c(`find`,e)},replay:{run:async e=>await c(`replay`,e),test:async e=>await c(`test`,e)},batch:{run:async e=>await c(`batch`,e)},observability:{perf:async(e={})=>await c(`perf`,e),logs:async(e={})=>await c(`logs`,e),events:async(e={})=>await c(`events`,e),network:async(e={})=>await c(`network`,e),audio:async(e={})=>await c(`audio`,e)},debug:{symbols:async t=>{let{symbolicateCrashArtifact:n}=await import(`./debug-symbols.js`);return n({cwd:t.cwd??e.cwd,...t})}},recording:{record:async e=>await c(`record`,e),trace:async e=>await c(`trace`,e)},settings:{update:async e=>await c(`settings`,e)}}}function fa(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`pan`,origin:{x:t,y:n},delta:{x:r,y:i}}}function pa(e){let{x:t,y:n,...r}=e;return{...r,kind:`fling`,origin:{x:t,y:n}}}function ma(e){return{...e,kind:`swipe`}}function ha(e){let{x:t,y:n,...r}=e;return va(t,n,`pinch`),{...r,kind:`pinch`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function ga(e){let{x:t,y:n,...r}=e;return va(t,n,`rotate`),{...r,kind:`rotate`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function _a(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`transform`,origin:{x:t,y:n},delta:{x:r,y:i}}}function va(e,t,r){if(e===void 0!=(t===void 0))throw new n(`INVALID_ARGS`,`gesture ${r} center requires both x and y`)}function ya(e,t){let n=x(e,`appBundleId`);return{nodes:sa(e.nodes),truncated:e.truncated===!0,appName:x(e,`appName`),appBundleId:n,...ba(e),identifiers:{session:t,appId:n,appBundleId:n}}}function ba(e){let t=Z(e.visibility),n=Z(e.unchanged),r=ve(e.snapshotDiagnostics);return{...t?{visibility:t}:{},...ne(e),...n?{unchanged:n}:{},...r?{snapshotDiagnostics:r}:{},...typeof e.refsGeneration==`number`?{refsGeneration:e.refsGeneration}:{}}}function xa(e){let t={};for(let[n,r]of Object.entries(Re.clientCommandMethods??{}))t[n]=async(t={})=>await e(r,t);let n=t.orientation;if(!n)throw Error(`orientation client method missing from the system command family`);return t.rotate=async(e={})=>({...await n(e),action:`rotate`}),t}function Z(e){return S(e)?e:void 0}function Q(e,t){return{...e,...t}}function $(e,t={}){let n=Q(e,t);return{stateDir:y(n.stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,session:la(n.session)}}function Sa(e,t){try{let n=new URL(t.statusUrl),r=Number.parseInt(n.port,10);if(!n.hostname||!Number.isInteger(r))return;let i=t.bridge?void 0:t.iosRuntime.bundleUrl??t.androidRuntime.bundleUrl;Bi({...$(e),hints:{metroHost:n.hostname,metroPort:r,bundleUrl:i}})}catch{}}function Ca(e){try{return Vi($(e))}catch{return}}function wa(e){if(!e)return;let{metroHost:t,metroPort:n,bundleUrl:r}=e;if(!(t===void 0&&n===void 0&&r===void 0))return{metroHost:t,metroPort:n,bundleUrl:r}}function Ta(e){try{let t=$(e.config,e.options),n=wa(e.runtime);if(n){Bi({...t,hints:n});return}e.sessionReused||Hi(t)}catch{}}function Ea(e,t){try{Hi($(e,t))}catch{}}function Da(e){let t=e.lease;if(!S(t))throw Error(`Invalid lease response from daemon`);return{leaseId:C(t,`leaseId`),tenantId:C(t,`tenantId`),runId:C(t,`runId`),backend:C(t,`backend`),leaseProvider:x(t,`leaseProvider`),clientId:x(t,`clientId`),deviceKey:x(t,`deviceKey`),createdAt:typeof t.createdAt==`number`?t.createdAt:void 0,heartbeatAt:typeof t.heartbeatAt==`number`?t.heartbeatAt:void 0,expiresAt:typeof t.expiresAt==`number`?t.expiresAt:void 0}}export{lr as a,Mr as i,da as n,rr as o,qi as r,ua as t};
@@ -36,7 +36,7 @@ type AndroidLogcatCaptureOptions = {
36
36
  };
37
37
  declare function captureAndroidLogcatWithAdb(adb: AndroidAdbExecutor, options?: AndroidLogcatCaptureOptions): Promise<string>;
38
38
  //#endregion
39
- //#region src/core/android-input-ownership.d.ts
39
+ //#region src/contracts/android-input-ownership.d.ts
40
40
  type AndroidInputOwner = 'app' | 'ime' | 'unknown';
41
41
  //#endregion
42
42
  //#region src/platforms/android/device-input-state.d.ts
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{a as t,n}from"./sdk-android-adb.js";import{r}from"./sdk-app-inventory.js";import{a as i,g as a,h as o,m as s,o as c,u as l}from"./app-lifecycle.js";import{s as u}from"./android-input-ownership.js";import{c as d,i as f,n as p,o as m}from"./device-input-state.js";const h=`android.intent.category.LAUNCHER`,g=`android.intent.category.LEANBACK_LAUNCHER`;async function _(e,t={}){let n=await y(e,t.target??`auto`);return(r(t.filter)===`user-installed`?(await C(e)).filter(e=>n.has(e)):Array.from(n)).map(e=>({package:e,name:i(e)})).sort((e,t)=>e.package.localeCompare(t.package))}async function v(e){return await w(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await w(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function y(e,t){let n=(await Promise.all(b(t).map(async t=>{let n=await e(x(t),{allowFailure:!0});return n.exitCode===0?S(n.stdout):[]}))).flat();return new Set(n)}function b(e){switch(e){case`mobile`:return[h];case`tv`:return[g];default:return[h,g]}}function x(e){return[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,e]}function S(e){return e.trim().length===0?[]:o(e)}async function C(e){let t=await e([`shell`,`pm`,`list`,`packages`,`-3`],{allowFailure:!0});if(t.exitCode!==0)throw n(`Failed to list Android user-installed apps`,t);return a(t.stdout)}async function w(e,t){for(let n of t){let t=s((await e(n,{allowFailure:!0})).stdout??``);if(t)return t}return null}const T=`android.intent.category.LAUNCHER`,E=`android.intent.category.DEFAULT`;async function D(e,t){await e([`shell`,`am`,`force-stop`,t])}async function O(e,t,n=[T]){for(let r of n){let n=await e([`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=l(n.stdout);if(i)return i}return null}async function k(t,n,r={}){let i=r.category??T;if(r.activity){await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-n`,A(n,r.activity)]);return}let a=await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-p`,n],{allowFailure:!0});if(a.exitCode===0&&!c(a.stdout,a.stderr))return;let o=await O(t,n,[i]);if(!o)throw new e(`COMMAND_FAILED`,`Failed to resolve Android launch component for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-n`,o])}function A(e,t){return t.includes(`/`)?t:`${e}/${t.startsWith(`.`)?t:`.${t}`}`}export{u as captureAndroidLogcatWithAdb,t as createAndroidPortReverseManager,p as dismissAndroidKeyboardWithAdb,D as forceStopAndroidAppWithAdb,v as getAndroidAppStateWithAdb,f as getAndroidKeyboardStatusWithAdb,_ as listAndroidAppsWithAdb,k as openAndroidAppWithAdb,m as readAndroidClipboardWithAdb,d as writeAndroidClipboardWithAdb};
1
+ import{_ as e}from"./sdk-contracts.js";import{i as t,n}from"./sdk-android-adb.js";import{r}from"./sdk-app-inventory.js";import{a as i,g as a,h as o,m as s,o as c,u as l}from"./app-lifecycle.js";import{t as u}from"./logcat.js";import{c as d,i as f,n as p,o as m}from"./device-input-state.js";const h=`android.intent.category.LAUNCHER`,g=`android.intent.category.LEANBACK_LAUNCHER`;async function _(e,t={}){let n=await y(e,t.target??`auto`);return(r(t.filter)===`user-installed`?(await C(e)).filter(e=>n.has(e)):Array.from(n)).map(e=>({package:e,name:i(e)})).sort((e,t)=>e.package.localeCompare(t.package))}async function v(e){return await w(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await w(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function y(e,t){let n=(await Promise.all(b(t).map(async t=>{let n=await e(x(t),{allowFailure:!0});return n.exitCode===0?S(n.stdout):[]}))).flat();return new Set(n)}function b(e){switch(e){case`mobile`:return[h];case`tv`:return[g];default:return[h,g]}}function x(e){return[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,e]}function S(e){return e.trim().length===0?[]:o(e)}async function C(e){let t=await e([`shell`,`pm`,`list`,`packages`,`-3`],{allowFailure:!0});if(t.exitCode!==0)throw n(`Failed to list Android user-installed apps`,t);return a(t.stdout)}async function w(e,t){for(let n of t){let t=s((await e(n,{allowFailure:!0})).stdout??``);if(t)return t}return null}const T=`android.intent.category.LAUNCHER`,E=`android.intent.category.DEFAULT`;async function D(e,t){await e([`shell`,`am`,`force-stop`,t])}async function O(e,t,n=[T]){for(let r of n){let n=await e([`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=l(n.stdout);if(i)return i}return null}async function k(t,n,r={}){let i=r.category??T;if(r.activity){await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-n`,A(n,r.activity)]);return}let a=await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-p`,n],{allowFailure:!0});if(a.exitCode===0&&!c(a.stdout,a.stderr))return;let o=await O(t,n,[i]);if(!o)throw new e(`COMMAND_FAILED`,`Failed to resolve Android launch component for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,E,`-c`,i,`-n`,o])}function A(e,t){return t.includes(`/`)?t:`${e}/${t.startsWith(`.`)?t:`.${t}`}`}export{u as captureAndroidLogcatWithAdb,t as createAndroidPortReverseManager,p as dismissAndroidKeyboardWithAdb,D as forceStopAndroidAppWithAdb,v as getAndroidAppStateWithAdb,f as getAndroidKeyboardStatusWithAdb,_ as listAndroidAppsWithAdb,k as openAndroidAppWithAdb,m as readAndroidClipboardWithAdb,d as writeAndroidClipboardWithAdb};
@@ -0,0 +1 @@
1
+ import{u as e}from"./sdk-contracts.js";import{G as t,Z as n}from"./sdk-selectors.js";import{n as r}from"./android-input-ownership.js";const i=[`x`,`y`,`width`,`height`];function a(t){let n=o(t);if(!n)return null;let r=e(n);return!Number.isFinite(r.x)||!Number.isFinite(r.y)?null:r}function o(e){if(!e)return null;let t=Number(e.x),n=Number(e.y),r=Number(e.width),i=Number(e.height);return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(i)||r<0||i<0?null:{x:t,y:n,width:r,height:i}}function s(e,t){return!e||!t?!1:i.every(n=>Math.abs(e[n]-t[n])<=.5)}function c(e){return{x:l(e.x,e.width),y:l(e.y,e.height)}}function l(e,t){if(t<=1)return Math.floor(e);let n=Math.ceil(e),r=Math.floor(e+t-1);return Math.round(Math.min(r,Math.max(n,e+t/2)))}const u=[`tabbar`,`toolbar`,`navigationbar`,`bottomnavigation`,`bottomnavigationview`,`sheet`,`dialog`,`alert`,`popover`,`menu`],d=[`button`,`link`,`menuitem`,`tabitem`,`textfield`,`searchfield`,`edittext`,`checkbox`,`radio`,`switch`,`cell`];function f(e,t={}){if(e.length<2)return e;let n=[...e],r=new Map(n.map(e=>[e.index,e])),i={nodes:n,byIndex:r,overlayPositions:n.flatMap((e,n)=>v(e,r,t)?[n]:[])},a=!1;for(let[e,r]of n.entries()){if(!_(r)||!m(i,e,r,t))continue;a=!0;let o={...r,hittable:!1,interactionBlocked:`covered`,presentationHints:k(r.presentationHints)};n[e]=o,i.byIndex.set(o.index,o)}return a?n:e}function p(e){return e.interactionBlocked!==void 0}function m(t,n,r,i){let a=O(r.rect);if(!a)return null;let o=e(a);for(let e of t.overlayPositions){if(e<=n)continue;let s=t.nodes[e];if(s&&h(t,e,r,a,o,i))return s}return null}function h(e,n,r,i,a,o){if(!e.nodes[n])return!1;let s=g(e,n,r,i,o);return!!(s&&t(s,a.x,a.y))}function g(e,t,n,r,i){let a=e.nodes[t];if(!a||!v(a,e.byIndex,i)||E(n,a,e.byIndex))return null;let o=O(a.rect);return!o||s(r,o)||m(e,t,a,i)?null:o}function _(e){return O(e.rect)?e.hittable===!0||S(e)?!0:!!(e.label?.trim()||e.value?.trim()||e.identifier?.trim()):!1}function v(e,t,n){return!O(e.rect)||T(e)?!1:C(e,u)||y(e,t,n)}function y(e,t,n){return n.isAdditionalOverlayNode?.(e)===!0?!b(e,t,n):!1}function b(e,t,n){let r=typeof e.parentIndex==`number`?t.get(e.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(x(r,n))return!0;i.add(r.index),r=typeof r.parentIndex==`number`?t.get(r.parentIndex):void 0}return!1}function x(e,t){return t.isAdditionalOverlayNode?.(e)===!0&&O(e.rect)!==null&&!T(e)}function S(e){return C(e,d)}function C(e,t){let n=w(e);return t.some(e=>n.includes(e))}function w(e){return[e.type,e.role,e.subrole].map(e=>n(e??``)).join(` `)}function T(e){let t=w(e);return t.includes(`application`)||t.includes(`window`)}function E(e,t,n){return D(e,t,n)||D(t,e,n)}function D(e,t,n){let r=typeof t.parentIndex==`number`?n.get(t.parentIndex):void 0,i=new Set;for(;r&&!i.has(r.index);){if(r.index===e.index)return!0;i.add(r.index),r=typeof r.parentIndex==`number`?n.get(r.parentIndex):void 0}return!1}function O(e){let t=o(e);return t&&t.width>0&&t.height>0?t:null}function k(e){return Array.from(new Set([...e??[],`covered`]))}function A(e){return e?r({packageName:e.bundleId,resourceId:e.identifier}).inputMethodOwned:!1}export{o as a,s as i,f as n,c as o,p as r,a as s,A as t};
@@ -1,6 +1 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{b as r,c as i,h as a,j as o,n as s,r as c,v as l,w as u}from"./sdk-android-adb.js";import{t as d}from"./timeouts.js";import{n as f,t as p}from"./manifest.js";import{n as m,t as h}from"./install-source2.js";import"node:fs";import g from"node:path";function ee(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let n=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!n)return!1;let r=n[1]?.toLowerCase(),i=n[2]??``;return r===`http`||r===`https`||r===`ws`||r===`wss`||r===`ftp`||r===`ftps`?i.startsWith(`//`):!0}function _(e){let t=e.trim().split(`:`)[0]?.toLowerCase();return t===`http`||t===`https`}function te(e,t){let n=e?.trim();if(n)return n;if(_(t))return`com.apple.mobilesafari`}function ne(e={}){let t=e.ttlMs??3e4,n=e.nowMs??Date.now,r=new Map,i=e=>{let t=y(e);for(let e of r.keys())e.startsWith(t)&&r.delete(e)};return{get(e,t){let i=v(e,t),a=r.get(i);if(a){if(a.expiresAtMs<=n()){r.delete(i);return}return a.value}},set(e,i,a){return r.set(v(e,i),{value:a,expiresAtMs:n()+t}),a},clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function v(e,t){return[e.platform,e.deviceId,e.variant??``,t.trim().toLowerCase()].join(`\0`)}function y(e){return[e.platform,e.deviceId,``].join(`\0`)}function b(e){return[`1`,`true`,`yes`,`on`].includes((e??``).trim().toLowerCase())}const x={attempts:3,baseDelayMs:200,maxDelayMs:2e3,jitter:.2};var S=class e{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(t,n=Date.now()){return new e(n,t)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return this.remainingMs(e)<=0}};async function C(e,n={},r={}){let i={maxAttempts:n.maxAttempts??x.attempts,baseDelayMs:n.baseDelayMs??x.baseDelayMs,maxDelayMs:n.maxDelayMs??x.maxDelayMs,jitter:n.jitter??x.jitter,shouldRetry:n.shouldRetry},a;for(let n=1;n<=i.maxAttempts;n+=1){if(r.signal?.aborted)throw new t(`COMMAND_FAILED`,`request canceled`,{reason:`request_canceled`});if(r.deadline?.isExpired()&&n>1)break;try{let t=await e({attempt:n,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:`succeeded`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),w({phase:r.phase,event:`succeeded`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),t}catch(e){a=e;let t=r.classifyReason?.(e),o={phase:r.phase,event:`attempt_failed`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:t};if(r.onEvent?.(o),w(o),n>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(e,n))break;let s=ie(i.baseDelayMs,i.maxDelayMs,i.jitter,n),c=r.deadline?Math.min(s,r.deadline.remainingMs()):s;if(c<=0)break;let l={phase:r.phase,event:`retry_scheduled`,attempt:n,maxAttempts:i.maxAttempts,delayMs:c,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:t};r.onEvent?.(l),w(l),await ae(c,r.signal)}}let o={phase:r.phase,event:`exhausted`,attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};throw r.onEvent?.(o),w(o),a||new t(`COMMAND_FAILED`,`retry failed`)}async function re(e,t={}){return C(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function ie(e,t,n,r){let i=Math.min(t,e*2**(r-1)),a=i*n;return Math.max(0,i+(Math.random()*2-1)*a)}function ae(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=!1,i=()=>{r||(r=!0,t&&t.removeEventListener(`abort`,o),n())},a=setTimeout(i,e);function o(){clearTimeout(a),i()}t&&t.addEventListener(`abort`,o,{once:!0})})}function w(e){o({level:e.event===`attempt_failed`||e.event===`exhausted`?`warn`:`debug`,phase:`retry`,data:{...e}})}function T(e){return e?.trim()||void 0}function oe(e){return T(e)}function E(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function D(e,t=process.env){let n=T(e)??T(t.AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST);if(n)return E(n)}const se=new Set([`IOS_BOOT_TIMEOUT`,`IOS_RUNNER_CONNECT_TIMEOUT`,`IOS_TOOL_MISSING`,`ANDROID_BOOT_TIMEOUT`,`ADB_TRANSPORT_UNAVAILABLE`,`CI_RESOURCE_STARVATION_SUSPECTED`]);function ce(e){return se.has(e.toUpperCase())}function O(e){let t=e.error?n(e.error):null,r=e.context?.platform,i=e.context?.phase;if(t?.code===`TOOL_MISSING`)return r===`android`?`ADB_TRANSPORT_UNAVAILABLE`:`IOS_TOOL_MISSING`;let a=t?.details??{},o=typeof a.message==`string`?a.message:void 0,s=typeof a.stdout==`string`?a.stdout:void 0,c=typeof a.stderr==`string`?a.stderr:void 0,l=a.boot&&typeof a.boot==`object`?a.boot:null,u=a.bootstatus&&typeof a.bootstatus==`object`?a.bootstatus:null,d=[e.message,t?.message,e.stdout,e.stderr,o,s,c,typeof l?.stdout==`string`?l.stdout:void 0,typeof l?.stderr==`string`?l.stderr:void 0,typeof u?.stdout==`string`?u.stdout:void 0,typeof u?.stderr==`string`?u.stderr:void 0].filter(Boolean).join(`
2
- `).toLowerCase();return r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:t?.code===`COMMAND_FAILED`||d.length>0?`BOOT_COMMAND_FAILED`:`UNKNOWN`}function k(e){switch(e){case`IOS_BOOT_TIMEOUT`:return`Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.`;case`IOS_RUNNER_CONNECT_TIMEOUT`:return`Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.`;case`ANDROID_BOOT_TIMEOUT`:return`Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.`;case`ADB_TRANSPORT_UNAVAILABLE`:return`Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.`;case`CI_RESOURCE_STARVATION_SUSPECTED`:return`CI machine may be resource constrained; reduce parallel jobs or use a larger runner.`;case`IOS_TOOL_MISSING`:return`Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.`;case`BOOT_COMMAND_FAILED`:return`Inspect command stderr/stdout for the failing boot phase and retry after environment validation.`;default:return`Retry once and inspect verbose logs for the failing phase.`}}var le=e({ensureAndroidEmulatorBooted:()=>Se,listAndroidDevices:()=>U,parseAndroidAvdList:()=>G,parseAndroidEmulatorAvdNameOutput:()=>I,parseAndroidFeatureListForTv:()=>H,parseAndroidTargetFromCharacteristics:()=>V,resolveAndroidAvdName:()=>K,resolveAndroidEmulatorAvdName:()=>B,waitForAndroidBoot:()=>J});const A=1e4,ue=[`android.software.leanback`,`android.software.leanback_only`,`android.hardware.type.television`];async function j(e,t,n){let r=Array(e.length),i=0,a=Math.min(t,e.length);return await Promise.all(Array.from({length:a},async()=>{for(;i<e.length;){let t=i;i+=1,r[t]=await n(e[t])}})),r}function M(e){return`${e.stdout}\n${e.stderr}`}function N(e,t){return[`-s`,e,...t]}function P(e){return e.startsWith(`emulator-`)}function F(e){return e.toLowerCase().replace(/_/g,` `).replace(/\s+/g,` `).trim()}function I(e){let t=e.split(`
3
- `).map(e=>e.trim()).filter(e=>e.length>0);if(t.length!==0)return t.at(-1)===`OK`&&t.pop(),t.join(`
4
- `).trim()||void 0}async function L(e,t=A){return l(`adb`,N(e,[`shell`,`getprop`,`sys.boot_completed`]),{allowFailure:!0,timeoutMs:t})}async function R(e,t){let n=t.replace(/_/g,` `).trim();if(!P(e))return n||e;let r=await B(e);return r?r.replace(/_/g,` `):n||e}async function z(e,t,r){try{return await r(`adb`,N(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){if(de(n(e)))return;throw e}}function de(e){return e.code===`COMMAND_FAILED`&&typeof e.details?.timeoutMs==`number`}async function B(e,t=l){for(let n of[`ro.boot.qemu.avd_name`,`persist.sys.avd_name`]){let r=await z(e,[`shell`,`getprop`,n],t);if(!r)continue;let i=r.stdout.trim();if(r.exitCode===0&&i.length>0)return i}let n=await z(e,[`emu`,`avd`,`name`],t);if(!n)return;let r=I(n.stdout);if(n.exitCode===0&&r)return r}function V(e){let t=e.toLowerCase();return t.includes(`tv`)||t.includes(`leanback`)?`tv`:null}function H(e){return/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(e)}async function fe(e,t){let n=M(await l(`adb`,N(e,[`shell`,`cmd`,`package`,`has-feature`,t]),{allowFailure:!0,timeoutMs:A})).toLowerCase();return n.includes(`true`)?!0:n.includes(`false`)?!1:null}async function pe(e){return(await j(ue,2,async t=>await fe(e,t))).some(e=>e===!0)}async function me(e){return V(M(await l(`adb`,N(e,[`shell`,`getprop`,`ro.build.characteristics`]),{allowFailure:!0,timeoutMs:A})))===`tv`||await pe(e)||H(M(await l(`adb`,N(e,[`shell`,`pm`,`list`,`features`]),{allowFailure:!0,timeoutMs:A})))?`tv`:`mobile`}async function U(e={}){if(await f(),!await u(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);let n=e.serialAllowlist??D(void 0),r=await j((await W()).filter(e=>!n||n.has(e.serial)),3,async({serial:e,rawModel:t})=>{let[n,r,i]=await Promise.all([R(e,t),xe(e),me(e)]);return{platform:`android`,id:e,name:n,kind:P(e)?`emulator`:`device`,target:i,booted:r}});return[...r,...await ge(r)]}function he(e){return e.split(`
5
- `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`List of devices`)).map(e=>e.split(/\s+/)).flatMap(e=>{let t=e[0];return t===void 0||e[1]!==`device`?[]:[{serial:t,rawModel:(e.find(e=>e.startsWith(`model:`))??``).replace(`model:`,``)}]})}async function W(){try{return he((await l(`adb`,[`devices`,`-l`],{timeoutMs:A})).stdout)}catch(e){throw c(e)}}function G(e){return e.split(`
6
- `).map(e=>e.trim()).filter(e=>e.length>0)}function K(e,t){let n=e.find(e=>e===t);if(n)return n;let r=F(t);return e.find(e=>F(e)===r)}async function q(){return G(a(await l(`emulator`,[`-list-avds`],{allowFailure:!0,timeoutMs:A}),`Failed to list Android emulator AVDs`,{hint:`Verify Android emulator tooling is installed and available in PATH.`}).stdout)}async function ge(e){let t=await q().catch(()=>[]),n=new Set(e.filter(e=>e.kind===`emulator`).map(e=>F(e.name)));return t.filter(e=>!n.has(F(e))).map(e=>({platform:`android`,id:e,name:e,kind:`emulator`,target:_e(e),booted:!1}))}function _e(e){return/\b(tv|television)\b/i.test(F(e))?`tv`:`mobile`}function ve(e,t,n){let r=F(t);return e.find(e=>e.platform!==`android`||e.kind!==`emulator`||n&&e.id!==n?!1:F(e.name)===r)}async function ye(e){let n=Date.now(),r=Math.min(1e3,Math.max(50,Math.floor(e.timeoutMs/20)));for(;Date.now()-n<e.timeoutMs;){try{let t=await be(e.avdName,e.serial);if(t)return{platform:`android`,id:t,name:e.avdName,kind:`emulator`,target:`mobile`,booted:!1}}catch{}await d(r)}throw new t(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:`Check emulator logs and verify the AVD can start from command line.`})}async function be(e,t){let n=F(e),r=(await W()).filter(e=>t&&e.serial!==t?!1:P(e.serial));for(let e of r)if(F(e.rawModel)===n||F(await R(e.serial,e.rawModel))===n)return e.serial}async function xe(e){try{return(await L(e)).stdout.trim()===`1`}catch{return!1}}async function Se(e){await f();let n=e.avdName.trim();if(!n)throw new t(`INVALID_ARGS`,`Android emulator boot requires a non-empty AVD name.`);let i=e.timeoutMs??12e4;if(!await u(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await u(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`);let a=await q(),o=K(a,n);if(!o)throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:n,availableAvds:a,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let s=Date.now(),c=ve(await U(),o,e.serial),l=c&&P(c.id)?c:void 0;if(!l){let t=[`-avd`,o];e.headless&&t.push(`-no-window`,`-no-audio`),r(`emulator`,t)}let d=l??await ye({avdName:o,serial:e.serial,timeoutMs:i}),p=Date.now()-s,m=Math.max(1e3,i-p);await J(d.id,m);let h=(await U()).find(e=>e.id===d.id);return h?{...h,name:o,booted:!0}:{...d,name:o,booted:!0}}async function J(e,r=6e4){let i=r,a=S.fromTimeoutMs(i),o=Math.min(1e3,Math.max(50,Math.floor(i/20))),s=Math.max(1,Math.ceil(i/o)),c,l=!1;try{await C(async({deadline:n})=>{if(n?.isExpired())throw l=!0,new t(`COMMAND_FAILED`,`Android boot deadline exceeded`,{serial:e,timeoutMs:r,elapsedMs:a.elapsedMs(),message:`timeout`});let o=Math.max(1e3,n?.remainingMs()??i),s=await L(e,Math.min(o,A));if(c=s,s.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:s,baseDelayMs:o,maxDelayMs:o,jitter:0,shouldRetry:e=>{let t=O({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}});return t!==`ADB_TRANSPORT_UNAVAILABLE`&&t!==`ANDROID_BOOT_TIMEOUT`}},{deadline:a,phase:`boot`,classifyReason:e=>O({error:e,stdout:c?.stdout,stderr:c?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(r){let o=n(r),s=c?.stdout,u=c?.stderr,d=c?.exitCode,f=O({error:r,stdout:s,stderr:u,context:{platform:`android`,phase:`boot`}});f===`BOOT_COMMAND_FAILED`&&o.message===`Android device is still booting`&&(f=`ANDROID_BOOT_TIMEOUT`);let p={serial:e,timeoutMs:i,elapsedMs:a.elapsedMs(),reason:f,hint:k(f),stdout:s,stderr:u,exitCode:d};throw l||f===`ANDROID_BOOT_TIMEOUT`?new t(`COMMAND_FAILED`,`Android device did not finish booting in time`,p):o.code===`TOOL_MISSING`?new t(`TOOL_MISSING`,o.message,{...p,...o.details??{}}):f===`ADB_TRANSPORT_UNAVAILABLE`?new t(`COMMAND_FAILED`,o.message,{...p,...o.details??{}}):new t(o.code,o.message,{...p,...o.details??{}},o.cause)}}async function Ce(e,t,n){return await i(e)(t,n)}function we(e){return{platform:`android`,id:e,name:e,kind:e.startsWith(`emulator-`)?`emulator`:`device`,booted:!0}}function Te(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`no shell command implementation`)||n.includes(`unknown command`)}var Ee=e({prepareAndroidInstallArtifact:()=>Y});async function Y(e,t){let n=e.kind===`url`&&h(e.url),r=await m({source:e,isInstallablePath:(e,t)=>t.isFile()&&De(e),installableLabel:`Android installable (.apk or .aab)`,allowArchiveExtraction:e.kind!==`url`||n,signal:t?.signal});try{let e=t?.resolveIdentity===!1?{}:await Oe(r.installablePath);return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:e.packageName,cleanup:r.cleanup}}catch(e){throw await r.cleanup(),e}}function De(e){let t=g.extname(e).toLowerCase();return t===`.apk`||t===`.aab`}async function Oe(e){let t=g.extname(e).toLowerCase();return t!==`.apk`&&t!==`.aab`?{}:{packageName:await p(e)}}async function ke(e,t={}){let n=[`logcat`,`-d`,`-v`,`time`];t.lines!==void 0&&n.push(`-t`,String(Math.max(1,Math.floor(t.lines))));let r=await e(n,{allowFailure:!0,timeoutMs:t.timeoutMs,signal:t.signal});if(r.exitCode!==0)throw s(`Failed to capture Android logcat`,r);return r.stdout}function X(e,n={}){if(!e.spawn)throw new t(`UNSUPPORTED_OPERATION`,`Android ADB provider does not support streams`,{capability:`adb.spawn`});let r=[`logcat`,`-v`,`time`];n.pid&&r.push(`--pid`,n.pid);let i=e.spawn(r,{stdio:[`ignore`,`pipe`,`pipe`],signal:n.signal});return n.output&&i.stdout&&i.stdout.pipe(n.output,{end:!1}),i}const Z=new Set([`com.google.android.inputmethod.latin`,`com.samsung.android.honeyboard`,`com.touchtype.swiftkey`,`com.microsoft.swiftkey`]);function Q(e){let t=$(e.packageName),n=(e.resourceId??``).toLowerCase(),r=$(e.activeInputMethodPackage);if(t&&r&&t===r)return{inputMethodOwned:!0,source:`active-input-method`};if(r&&n.startsWith(`${r}:id/`))return{inputMethodOwned:!0,source:`active-input-method-resource`};if(t&&Z.has(t))return{inputMethodOwned:!0,source:`known-ime-package`};for(let e of Z)if(n.startsWith(`${e}:id/`))return{inputMethodOwned:!0,source:`known-ime-resource`};return{inputMethodOwned:!1,source:`app`}}function Ae(e,t,n){return Q({packageName:e,resourceId:t,activeInputMethodPackage:n}).inputMethodOwned}function je(e){return Q(e).inputMethodOwned}function Me(e){let t=$(e);return!!(t&&Z.has(t))}function Ne(e){let t=(e??``).toLowerCase();for(let e of Z)if(t.startsWith(`${e}:id/`))return!0;return!1}function Pe(e,t,n){return!e&&!t?`unknown`:Ae(e,t,n)?`ime`:`app`}function Fe(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let n=Ie(e.match(t)?.[1]);if(n)return n}}function Ie(e){let t=(e??``).trim();if(t)return $((t.split(`/`)[0]??``).match(/[a-zA-Z0-9_.]+/)?.[0])}function $(e){return(e??``).trim().toLowerCase()||void 0}export{b as C,ee as D,ne as E,_ as O,S,re as T,O as _,Ne as a,D as b,X as c,we as d,Te as f,k as g,J as h,Me as i,te as k,Ee as l,le as m,Q as n,Fe as o,Ce as p,je as r,ke as s,Pe as t,Y as u,ce as v,C as w,oe as x,E as y};
1
+ const e=new Set([`com.google.android.inputmethod.latin`,`com.samsung.android.honeyboard`,`com.touchtype.swiftkey`,`com.microsoft.swiftkey`]);function t(t){let n=l(t.packageName),r=(t.resourceId??``).toLowerCase(),i=l(t.activeInputMethodPackage);if(n&&i&&n===i)return{inputMethodOwned:!0,source:`active-input-method`};if(i&&r.startsWith(`${i}:id/`))return{inputMethodOwned:!0,source:`active-input-method-resource`};if(n&&e.has(n))return{inputMethodOwned:!0,source:`known-ime-package`};for(let t of e)if(r.startsWith(`${t}:id/`))return{inputMethodOwned:!0,source:`known-ime-resource`};return{inputMethodOwned:!1,source:`app`}}function n(e,n,r){return t({packageName:e,resourceId:n,activeInputMethodPackage:r}).inputMethodOwned}function r(e){return t(e).inputMethodOwned}function i(t){let n=l(t);return!!(n&&e.has(n))}function a(t){let n=(t??``).toLowerCase();for(let t of e)if(n.startsWith(`${t}:id/`))return!0;return!1}function o(e,t,r){return!e&&!t?`unknown`:n(e,t,r)?`ime`:`app`}function s(e){for(let t of[/\bmCurMethodId=([^\s]+)/i,/\bmCurId=([^\s]+)/i,/\bmCurrentInputMethodId=([^\s]+)/i,/\bcurMethodId=([^\s]+)/i]){let n=c(e.match(t)?.[1]);if(n)return n}}function c(e){let t=(e??``).trim();if(t)return l((t.split(`/`)[0]??``).match(/[a-zA-Z0-9_.]+/)?.[0])}function l(e){return(e??``).trim().toLowerCase()||void 0}export{a,i,t as n,s as o,r,o as t};
@@ -0,0 +1 @@
1
+ const e=`com.android.systemui`,t=[`com.android.systemui:id/status_bar`,`com.android.systemui:id/navigation_bar`],n=new Set([`clock`,`battery`,`statusIcons`,`notificationIcons`,`notification_icon_area`,`system_icons`,`cutout_space_view`,`mobile_signal`,`mobile_combo`,`mobile_group`,`wifi_signal`,`wifi_combo`,`wifi_group`,`start_side_notif_and_chip_container`,`back`,`home`,`recent_apps`,`home_handle`].map(t=>`${e}:id/${t}`));function r(e){let r=e??``;return n.has(r)?!0:t.some(e=>r.startsWith(e))}export{r as n,e as t};
@@ -1 +1 @@
1
- import{S as e,_ as t}from"./sdk-contracts.js";import{F as n,c as r,d as i,j as a,l as o,n as s,o as c,p as l}from"./sdk-android-adb.js";import{Ct as u,pn as d}from"./tv-remote.js";import{n as ee,t as te}from"./version.js";import{t as ne}from"./timeouts.js";import{c as f,d as re,l as ie,n as p}from"./app-lifecycle.js";import{p as m}from"./android-input-ownership.js";import{a as h,s as g}from"./device-input-state.js";import{At as _,Dt as v,Ot as ae,jt as y,kt as oe}from"./internal/daemon.js";import{a as se,c as ce,d as le,f as ue,i as de,l as b,m as x,n as S,o as C,p as w,r as T,t as E,u as D}from"./input-actions.js";import{a as O,i as k,n as A,r as j,t as M}from"./setting-state.js";import N from"node:crypto";import{promises as P}from"node:fs";import F from"node:path";import I from"node:fs/promises";const L=`android-multitouch-helper-v1`,R=`ANDROID_MULTITOUCH_HELPER_NO_FINAL_RESULT`,z=`ANDROID_MULTITOUCH_HELPER_REPORTED_FAILURE`;async function B(t,n){let r=await G(t,{kind:`swipe`,...n});if(r)return r;try{return await K(t,{kind:`swipe`,...n})}catch(r){return a({level:`warn`,phase:`android_swipe_helper_fallback`,data:{error:e(r).message}}),await w(t,n.x1,n.y1,n.x2,n.y2,n.durationMs),{backend:`adb-input-swipe-fallback`}}}async function V(e,n){if(!Number.isFinite(n.scale)||n.scale<=0)throw new t(`INVALID_ARGS`,`gesture pinch requires scale > 0`);let r=await U(e,n.x,n.y);return await W(e,{kind:`pinch`,x:r.x,y:r.y,scale:n.scale,durationMs:n.durationMs})}async function H(e,n){if(!Number.isFinite(n.degrees))throw new t(`INVALID_ARGS`,`gesture rotate requires finite degrees`);if(n.velocity!==void 0&&(!Number.isFinite(n.velocity)||n.velocity===0))throw new t(`INVALID_ARGS`,`gesture rotate velocity must be a non-zero number`);let r=await U(e,n.x,n.y),i=n.degrees;return await W(e,{kind:`rotate`,x:r.x,y:r.y,degrees:i,durationMs:n.durationMs})}async function fe(e,n){if(!Number.isFinite(n.scale)||n.scale<=0)throw new t(`INVALID_ARGS`,`gesture transform requires scale > 0`);if(!Number.isFinite(n.degrees))throw new t(`INVALID_ARGS`,`gesture transform requires finite degrees`);if(![n.x,n.y,n.dx,n.dy].every(Number.isFinite))throw new t(`INVALID_ARGS`,`gesture transform requires finite x y dx dy`);return await W(e,{kind:`transform`,x:n.x,y:n.y,dx:n.dx,dy:n.dy,scale:n.scale,degrees:n.degrees,durationMs:n.durationMs})}async function U(e,t,n){if(t!==void 0&&n!==void 0)return{x:t,y:n};let r=await se(e);return{x:Math.round(r.width/2),y:Math.round(r.height/2)}}async function W(e,t){return await G(e,t)||await K(e,t)}async function G(e,t){let n=i(e);if(n)return{backend:`provider-native-touch`,...await n(t)??{}}}async function K(e,t){let i=r(e),s=await _e(),c=o(e),l=await n(`android_multitouch_helper_install`,async()=>await ye({adb:i,adbProvider:c,artifact:s,deviceKey:Ce(e)}),{packageName:s.manifest.packageName,versionCode:s.manifest.versionCode});a({phase:`android_multitouch_helper_install_decision`,data:l});let u=await n(`android_multitouch_helper_gesture`,async()=>await me({adb:i,request:q(t),packageName:s.manifest.packageName,instrumentationRunner:s.manifest.instrumentationRunner}),{packageName:s.manifest.packageName,version:s.manifest.version});return{backend:`android-multitouch-helper`,helperVersion:s.manifest.version,installReason:l.reason,...u}}function q(e){let t=Math.round(pe(e));switch(e.kind){case`swipe`:return{kind:`swipe`,x1:Math.round(e.x1),y1:Math.round(e.y1),x2:Math.round(e.x2),y2:Math.round(e.y2),durationMs:t};case`pinch`:return{kind:`pinch`,x:Math.round(e.x),y:Math.round(e.y),scale:e.scale,radius:160,durationMs:t};case`rotate`:return{kind:`rotate`,x:Math.round(e.x),y:Math.round(e.y),degrees:e.degrees,radius:160,durationMs:t};case`transform`:return{kind:`transform`,x:Math.round(e.x),y:Math.round(e.y),dx:Math.round(e.dx),dy:Math.round(e.dy),scale:e.scale,degrees:e.degrees,durationMs:t}}}function pe(e){if(e.durationMs!==void 0)return e.durationMs;if(e.kind===`swipe`||e.kind===`pinch`)return 300;let t=Math.ceil(Math.abs(e.degrees)/3)*16;return Math.min(Math.max(300,t),2400)}async function me(e){let n=Buffer.from(JSON.stringify({protocol:L,...e.request})).toString(`base64`),r=await e.adb([`shell`,`am`,`instrument`,`-w`,`-e`,`payloadBase64`,n,e.instrumentationRunner],{allowFailure:!0,timeoutMs:45e3}),i;try{i=he(`${r.stdout}\n${r.stderr}`)}catch(e){if(e instanceof t){if(e.code===z)throw new t(`COMMAND_FAILED`,e.message,e.details,e);if(e.code!==R)throw e}throw new t(`COMMAND_FAILED`,r.exitCode===0?`Android multi-touch helper output could not be parsed`:`Android multi-touch helper failed before returning parseable output`,{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode},e)}if(r.exitCode!==0)throw new t(`COMMAND_FAILED`,`Android multi-touch helper failed`,l(r,{helper:i}));return i}function he(e){let n=ae(e).results.find(e=>e.agentDeviceProtocol===L);if(!n)throw new t(R,`Android multi-touch helper did not return a final result`);if(n.ok!==`true`)throw new t(z,ge(n),{errorType:n.errorType,helper:n});return{kind:n.kind,helperApiVersion:n.helperApiVersion,injectedEvents:y(n.injectedEvents),elapsedMs:y(n.elapsedMs)}}function ge(e){return e.message&&e.message!==`null`?e.message:e.errorType||`Android multi-touch helper returned an error`}async function _e(){let n=ee(),r=F.join(te(),`android-multitouch-helper`,`dist`),i=F.join(r,`agent-device-android-multitouch-helper-${n}.manifest.json`);try{let e=ve(JSON.parse(await I.readFile(i,`utf8`))),t=F.join(r,e.assetName);return await I.access(t),{apkPath:t,manifest:e}}catch(n){throw new t(`UNSUPPORTED_OPERATION`,`Android touch gestures require the bundled Android touch helper artifact, but it was not found or could not be read`,{manifestPath:i,error:e(n).message},n)}}function ve(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`Android multi-touch helper manifest must be an object.`);let n=e;return{name:X(n.name,`name`,`android-multitouch-helper`),version:Y(n.version,`version`),assetName:Y(n.assetName,`assetName`),sha256:Te(n.sha256),packageName:X(n.packageName,`packageName`,`com.callstack.agentdevice.multitouchhelper`),versionCode:we(n.versionCode,`versionCode`),instrumentationRunner:X(n.instrumentationRunner,`instrumentationRunner`,`com.callstack.agentdevice.multitouchhelper/.MultiTouchInstrumentation`),statusProtocol:X(n.statusProtocol,`statusProtocol`,L)}}async function ye(e){let{adb:t,artifact:n}=e,r=n.manifest.packageName,i=n.manifest.versionCode,a=`${e.deviceKey}\0${r}\0${i}`;if(J.has(a))return{packageName:r,versionCode:i,installed:!1,reason:`current`};let o=await be(t,r);if(o!==void 0&&o>=i)return J.add(a),{packageName:r,versionCode:i,installedVersionCode:o,installed:!1,reason:`current`};await xe(n);let l=await c(n.apkPath,{provider:e.adbProvider,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:3e4});if(l.exitCode!==0)throw s(`Failed to install Android multi-touch helper`,l,{packageName:r,versionCode:i});return J.add(a),{packageName:r,versionCode:i,installedVersionCode:o,installed:!0,reason:o===void 0?`missing`:`outdated`}}const J=new Set;async function be(e,t){let n=await e([`shell`,`cmd`,`package`,`list`,`packages`,`--show-versioncode`,t],{allowFailure:!0,timeoutMs:5e3});if(n.exitCode!==0)return;let r=RegExp(`package:${Ee(t)}(?:\\s|$).*versionCode:(\\d+)`).exec(`${n.stdout}\n${n.stderr}`);return r?Number(r[1]):void 0}async function xe(e){let n=await Se(e.apkPath);if(n!==e.manifest.sha256)throw new t(`COMMAND_FAILED`,`Android multi-touch helper APK checksum mismatch`,{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:n})}async function Se(e){let t=N.createHash(`sha256`);return t.update(await I.readFile(e)),t.digest(`hex`)}function Ce(e){return`${e.platform}:${e.id}`}function Y(e,n){if(typeof e!=`string`||e.length===0)throw new t(`INVALID_ARGS`,`Android multi-touch helper manifest ${n} is required.`);return e}function we(e,t){return oe(e,t,`multi-touch helper`)}function X(e,t,n){return _(e,t,n,`multi-touch helper`)}function Te(e){let n=Y(e,`sha256`).trim().toLowerCase();if(n.length!==64||!/^[0-9a-f]+$/.test(n))throw new t(`INVALID_ARGS`,`Android multi-touch helper manifest sha256 must be a 64-character hex string.`);return n}function Ee(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const Z=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`];async function De(e,n,r,i,a){switch(n.toLowerCase()){case`wifi`:await m(e,[`shell`,`svc`,`wifi`,M(r)?`enable`:`disable`]);return;case`airplane`:{let t=M(r),n=t?`1`:`0`,i=t?`true`:`false`;await m(e,[`shell`,`settings`,`put`,`global`,`airplane_mode_on`,n]),await m(e,[`shell`,`am`,`broadcast`,`-a`,`android.intent.action.AIRPLANE_MODE`,`--ez`,`state`,i]);return}case`location`:if(r.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:r}=u(a);return await m(e,[`emu`,`geo`,`fix`,String(r),String(n)]),{latitude:n,longitude:r}}await m(e,[`shell`,`settings`,`put`,`secure`,`location_mode`,M(r)?`3`:`0`]);return;case`animations`:{let t=M(r)?`1`:`0`;for(let n of Z)await m(e,[`shell`,`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...Z]}}case`appearance`:await m(e,[`shell`,`cmd`,`uimode`,`night`,await Me(e,r)===`dark`?`yes`:`no`]);return;case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await re(e,i);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await m(e,[`shell`,`am`,`force-stop`,n.value],{allowFailure:!0});let a=await m(e,[`shell`,`pm`,`clear`,n.value],{allowFailure:!0});if(a.exitCode!==0||!/\bSuccess\b/i.test(a.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await ke(e,Oe(r));return;case`permission`:{if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);let n=j(r),o=Pe(a?.permissionTarget,a?.permissionMode);if(o.kind===`notifications`){await Ie(e,i,n,o);return}let s=n===`grant`?`grant`:`revoke`;if(o.type===`photos`){await Fe(e,i,s);return}await m(e,[`shell`,`pm`,s,i,o.value]);return}default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}function Oe(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function ke(e,n){let r=Ae(e,n),i=[];for(let t of r){let n=await m(e,t,{allowFailure:!0});if(n.exitCode===0)return;i.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let a=O(i);throw i.length>0&&i.every(e=>je(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:a}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:a})}function Ae(e,t){let n=t===`match`?`1`:`9999`,r=[[`shell`,`cmd`,`fingerprint`,`touch`,n],[`shell`,`cmd`,`fingerprint`,`finger`,n]];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function je(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function Me(e,n){let r=A(n);if(r!==`toggle`)return r;let i=await m(e,[`shell`,`cmd`,`uimode`,`night`],{allowFailure:!0});if(i.exitCode!==0)throw s(`Failed to read current Android appearance`,i);let a=Ne(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`auto`?`dark`:a===`dark`?`light`:`dark`}function Ne(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}function Pe(e,n){let r=k(e);if(n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return{kind:`pm`,value:`android.permission.CAMERA`,type:`camera`};if(r===`microphone`)return{kind:`pm`,value:`android.permission.RECORD_AUDIO`,type:`microphone`};if(r===`photos`)return{kind:`pm`,value:`android.permission.READ_MEDIA_IMAGES`,type:`photos`};if(r===`contacts`)return{kind:`pm`,value:`android.permission.READ_CONTACTS`,type:`contacts`};if(r===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}async function Fe(e,n,r){let i=await Le(e),a=i!==null&&i>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],o=[];for(let t of a){let i=await m(e,[`shell`,`pm`,r,n,t],{allowFailure:!0});if(i.exitCode===0)return;o.push({permission:t,stderr:i.stderr,exitCode:i.exitCode})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:i,attempts:o})}async function Ie(e,t,n,r){let i=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await m(e,[`shell`,`pm`,`grant`,t,r.permission],{allowFailure:!0}):(await m(e,[`shell`,`pm`,`revoke`,t,r.permission],{allowFailure:!0}),n===`reset`&&(await m(e,[`shell`,`pm`,`clear-permission-flags`,t,r.permission,`user-set`],{allowFailure:!0}),await m(e,[`shell`,`pm`,`clear-permission-flags`,t,r.permission,`user-fixed`],{allowFailure:!0}))),await m(e,[`shell`,`appops`,`set`,t,r.appOps,i])}async function Le(e){let t=await m(e,[`shell`,`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const Q=Buffer.from([137,80,78,71,13,10,26,10]);async function Re(e,t,n={}){if(n.stabilize===!1){await $(e,t);return}await ze(e);try{await ne(1e3),await $(e,t)}finally{await Be(e).catch(()=>{})}}async function ze(e){let t=t=>m(e,[`shell`,t],{allowFailure:!0});await t(`settings put global sysui_demo_allowed 1`);let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n(`clock -e hhmm 0941`),await n(`notifications -e visible false`)}async function Be(e){await m(e,[`shell`,`am broadcast -a com.android.systemui.demo -e command exit`],{allowFailure:!0})}async function $(e,n){let r=await m(e,[`exec-out`,`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(Q);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=Ve(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await P.writeFile(n,r.stdoutBuffer.subarray(i,a))}function Ve(e,t){let n=t+Q.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}function He(e){return{open:(t,n)=>f(e,t,{activity:n?.activity,appBundleId:n?.appBundleId,launchArgs:n?.launchArgs,url:n?.url}),openDevice:()=>ie(e),close:t=>p(e,t),tap:(t,n)=>b(e,t,n),doubleTap:async(t,n)=>{await b(e,t,n),await b(e,t,n)},swipe:(t,n,r,i,a)=>B(e,{x1:t,y1:n,x2:r,y2:i,durationMs:a}),pan:(t,n,r,i,a)=>B(e,{x1:t,y1:n,x2:r,y2:i,durationMs:a}),fling:(t,n,r,i,a)=>B(e,{x1:t,y1:n,x2:r,y2:i,durationMs:a}),longPress:(t,n,r)=>ce(e,t,n,r),focus:(t,n)=>de(e,t,n),type:(t,n)=>x(e,t,n),fill:(t,n,r,i)=>T(e,t,n,r,i),scroll:(t,n)=>ue(e,t,n),pinch:(t,n,r)=>V(e,{scale:t,x:n,y:r}),screenshot:(t,n)=>Re(e,t,n),snapshot:async t=>{let r=await n(`snapshot_capture`,async()=>await v(e,{appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,depth:t?.depth,scope:t?.scope,raw:t?.raw,helperSessionScope:t?.appBundleId?`daemon-session`:`command`}),{backend:`android`});return{nodes:r.nodes??[],truncated:r.truncated??!1,backend:`android`,...d(r)}},back:t=>S(e),home:()=>C(e),rotate:t=>le(e,t),rotateGesture:(t,n,r,i)=>H(e,{degrees:t,x:n,y:r,velocity:i}),transformGesture:t=>fe(e,t),appSwitcher:()=>E(e),tvRemote:(t,n)=>D(e,t,n),readClipboard:()=>h(e),writeClipboard:t=>g(e,t),setSetting:(t,n,r,i)=>De(e,t,n,r,i)}}export{He as createAndroidInteractor};
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{F as n,d as r,n as i}from"./sdk-android-adb.js";import{Ht as a,Wt as o}from"./tv-remote.js";import{t as s}from"./timeouts.js";import{c,d as l,l as u,n as d}from"./app-lifecycle.js";import{s as f}from"./logcat.js";import{a as p,s as m}from"./device-input-state.js";import{Nt as h}from"./internal/daemon.js";import{c as g,d as _,f as v,h as y,i as b,l as x,m as S,n as C,o as w,p as T,r as E,t as D,u as O}from"./input-actions.js";import{a as k,i as A,n as j,r as ee,t as M}from"./setting-state.js";import{promises as N}from"node:fs";const P=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`];async function F(e,n,r,i,a){switch(n.toLowerCase()){case`wifi`:await f(e,[`shell`,`svc`,`wifi`,M(r)?`enable`:`disable`]);return;case`airplane`:{let t=M(r),n=t?`1`:`0`,i=t?`true`:`false`;await f(e,[`shell`,`settings`,`put`,`global`,`airplane_mode_on`,n]),await f(e,[`shell`,`am`,`broadcast`,`-a`,`android.intent.action.AIRPLANE_MODE`,`--ez`,`state`,i]);return}case`location`:if(r.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:r}=o(a);return await f(e,[`emu`,`geo`,`fix`,String(r),String(n)]),{latitude:n,longitude:r}}await f(e,[`shell`,`settings`,`put`,`secure`,`location_mode`,M(r)?`3`:`0`]);return;case`animations`:{let t=M(r)?`1`:`0`;for(let n of P)await f(e,[`shell`,`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...P]}}case`appearance`:await f(e,[`shell`,`cmd`,`uimode`,`night`,await B(e,r)===`dark`?`yes`:`no`]);return;case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await l(e,i);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await f(e,[`shell`,`am`,`force-stop`,n.value],{allowFailure:!0});let a=await f(e,[`shell`,`pm`,`clear`,n.value],{allowFailure:!0});if(a.exitCode!==0||!/\bSuccess\b/i.test(a.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await L(e,I(r));return;case`permission`:{if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);let n=ee(r),o=H(a?.permissionTarget,a?.permissionMode);if(o.kind===`notifications`){await W(e,i,n,o);return}let s=n===`grant`?`grant`:`revoke`;if(o.type===`photos`){await U(e,i,s);return}await f(e,[`shell`,`pm`,s,i,o.value]);return}default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}function I(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function L(e,n){let r=R(e,n),i=[];for(let t of r){let n=await f(e,t,{allowFailure:!0});if(n.exitCode===0)return;i.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let a=k(i);throw i.length>0&&i.every(e=>z(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:a}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:a})}function R(e,t){let n=t===`match`?`1`:`9999`,r=[[`shell`,`cmd`,`fingerprint`,`touch`,n],[`shell`,`cmd`,`fingerprint`,`finger`,n]];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function z(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function B(e,n){let r=j(n);if(r!==`toggle`)return r;let a=await f(e,[`shell`,`cmd`,`uimode`,`night`],{allowFailure:!0});if(a.exitCode!==0)throw i(`Failed to read current Android appearance`,a);let o=V(a.stdout,a.stderr);if(!o)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:a.stdout,stderr:a.stderr});return o===`auto`?`dark`:o===`dark`?`light`:`dark`}function V(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}function H(e,n){let r=A(e);if(n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return{kind:`pm`,value:`android.permission.CAMERA`,type:`camera`};if(r===`microphone`)return{kind:`pm`,value:`android.permission.RECORD_AUDIO`,type:`microphone`};if(r===`photos`)return{kind:`pm`,value:`android.permission.READ_MEDIA_IMAGES`,type:`photos`};if(r===`contacts`)return{kind:`pm`,value:`android.permission.READ_CONTACTS`,type:`contacts`};if(r===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}async function U(e,n,r){let i=await G(e),a=i!==null&&i>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],o=[];for(let t of a){let i=await f(e,[`shell`,`pm`,r,n,t],{allowFailure:!0});if(i.exitCode===0)return;o.push({permission:t,stderr:i.stderr,exitCode:i.exitCode})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:i,attempts:o})}async function W(e,t,n,r){let i=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await f(e,[`shell`,`pm`,`grant`,t,r.permission],{allowFailure:!0}):(await f(e,[`shell`,`pm`,`revoke`,t,r.permission],{allowFailure:!0}),n===`reset`&&(await f(e,[`shell`,`pm`,`clear-permission-flags`,t,r.permission,`user-set`],{allowFailure:!0}),await f(e,[`shell`,`pm`,`clear-permission-flags`,t,r.permission,`user-fixed`],{allowFailure:!0}))),await f(e,[`shell`,`appops`,`set`,t,r.appOps,i])}async function G(e){let t=await f(e,[`shell`,`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const K=Buffer.from([137,80,78,71,13,10,26,10]);async function q(e,t,n={}){if(n.stabilize===!1){await X(e,t);return}await J(e);try{await s(1e3),await X(e,t)}finally{await Y(e).catch(()=>{})}}async function J(e){let t=t=>f(e,[`shell`,t],{allowFailure:!0});await t(`settings put global sysui_demo_allowed 1`);let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n(`clock -e hhmm 0941`),await n(`notifications -e visible false`)}async function Y(e){await f(e,[`shell`,`am broadcast -a com.android.systemui.demo -e command exit`],{allowFailure:!0})}async function X(e,n){let r=await f(e,[`exec-out`,`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(K);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=Z(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await N.writeFile(n,r.stdoutBuffer.subarray(i,a))}function Z(e,t){let n=t+K.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}var Q=e({createAndroidInteractor:()=>$});function $(e,t){let i={open:(t,n)=>c(e,t,{activity:n?.activity,appBundleId:n?.appBundleId,launchArgs:n?.launchArgs,url:n?.url}),openDevice:()=>u(e),close:t=>d(e,t),tap:(t,n)=>x(e,t,n),doubleTap:async(t,n)=>{await x(e,t,n),await x(e,t,n)},longPress:(t,n,r)=>g(e,t,n,r),focus:(t,n)=>b(e,t,n),type:(t,n)=>T(e,t,n),fill:(t,n,r,i)=>E(e,t,n,r,i),scroll:(t,n)=>_(e,t,n),performGesture:t=>S(e,t),gestureViewport:()=>y(e),screenshot:(t,n)=>q(e,t,n),snapshot:async t=>{let r=await n(`snapshot_capture`,async()=>await h(e,{appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,depth:t?.depth,scope:t?.scope,raw:t?.raw,includeHiddenContentHints:t?.includeHiddenContentHints,helperSessionScope:t?.appBundleId?`daemon-session`:`command`}),{backend:`android`});return{nodes:r.nodes??[],truncated:r.truncated??!1,backend:`android`,...a(r)}},back:t=>C(e),home:()=>w(e),setOrientation:t=>v(e,t),appSwitcher:()=>D(e),tvRemote:(t,n)=>O(e,t,n),readClipboard:()=>p(e),writeClipboard:t=>m(e,t),setSetting:(t,n,r,i)=>F(e,t,n,r,i)};return t?new Proxy(i,{get(n,i,a){let o=Reflect.get(n,i,a);return typeof o==`function`?(...i)=>r(t,{serial:e.id},async()=>await o.apply(n,i)):o}}):i}export{$ as n,Q as t};
@@ -1,7 +1,7 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,a as r,l as i,n as a,o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{D as u,E as ee,h as d,p as f,u as p}from"./android-input-ownership.js";import{promises as m}from"node:fs";import te from"node:os";import h from"node:path";const ne=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],re=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,ie=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,ae=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function g(e){let t=new Set;for(let n of e.split(`
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,a as r,c as i,i as a,n as o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{d as u,i as d,l as f,s as p,u as ee}from"./logcat.js";import{promises as m}from"node:fs";import te from"node:os";import h from"node:path";const ne=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],re=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,ie=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,ae=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function g(e){let t=new Set;for(let n of e.split(`
2
2
  `)){let e=n.trim();if(!e)continue;let r=e.split(/\s+/)[0]??``;if(!r.includes(`/`))continue;let i=r.split(`/`)[0]??``;i.includes(`.`)&&i&&t.add(i)}return Array.from(t)}function _(e){return e.split(`
3
3
  `).map(e=>{let t=e.trim();return t.startsWith(`package:`)?t.slice(8):t}).filter(Boolean)}function v(e){return y(e,e=>ce(e))}function oe(e){return y(e,(e,t)=>se(e,t))}function y(e,t){let n=e.split(`
4
- `);for(let e of ne)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function se(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=re.exec(n);if(r){let e=r[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=ie.exec(n);if(!i)return null;let a=i[1];if(a===void 0)return null;let o=a.trim().replace(/\s+/g,` `),s=ae.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}}function ce(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf(`/`);if(e<=0)continue;let n=b(t.slice(0,e),!1),r=b(t.slice(e+1),!0);if(n&&r&&n.length===e)return{package:n,activity:r}}return null}function b(e,t){let n=0;for(;n<e.length&&le(e[n],t);)n+=1;return e.slice(0,n)}function le(e,t){if(!e)return!1;let n=e.charCodeAt(0);return n>=48&&n<=57||n>=65&&n<=90||n>=97&&n<=122||e===`_`||e===`.`||t&&e===`$`}const ue=/\.(?:apk|aab)$/i,de=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function x(e){let t=e.trim();return t.length===0?`other`:ue.test(t)?t.includes(`/`)||t.includes(`\\`)||t.startsWith(`.`)||t.startsWith(`~`)||!S(t)?`binary`:`package`:S(t)?`package`:`other`}function S(e){return de.test(e)}function fe(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}var pe=e({closeAndroidApp:()=>G,getAndroidAppState:()=>N,getAndroidBlockingDialogFocus:()=>P,inferAndroidAppName:()=>M,installAndroidApp:()=>He,installAndroidInstallablePath:()=>Q,installAndroidInstallablePathAndResolvePackageName:()=>$,isAmStartError:()=>H,listAndroidApps:()=>A,openAndroidApp:()=>L,openAndroidDevice:()=>W,parseAndroidLaunchComponent:()=>U,reinstallAndroidApp:()=>Ue,resolveAndroidApp:()=>k});const me={settings:{type:`intent`,value:`android.settings.SETTINGS`}},C=`android.intent.category.LAUNCHER`,w=`android.intent.category.LEANBACK_LAUNCHER`,T=`android.intent.category.DEFAULT`,E=`Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.`,he=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]),D=ee();function O(e){return{platform:`android`,deviceId:e.id,variant:e.target??``}}async function k(e,n){let r=n.trim();if(x(r)===`package`)return{type:`package`,value:r};let i=me[r.toLowerCase()];if(i)return i;let a=O(e),o=D.get(a,r);if(o)return o;let s=(await f(e,[`shell`,`pm`,`list`,`packages`])).stdout.split(`
5
- `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return D.set(a,r,{type:`package`,value:c});throw s.length>1?new t(`INVALID_ARGS`,`Multiple packages matched "${n}"`,{matches:s,hint:`Run agent-device apps --platform android to see the exact installed package names before retrying open.`}):new t(`APP_NOT_INSTALLED`,`No package found matching "${n}"`,{hint:E})}async function A(e,t){let n=await ge(e);return(t===`user-installed`?(await ve(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:M(e)}))}async function ge(e){let t=new Set;for(let n of j(e,{includeFallbackWhenUnknown:!0})){let r=await f(e,[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,n],{allowFailure:!0});if(!(r.exitCode!==0||r.stdout.trim().length===0))for(let e of g(r.stdout))t.add(e)}return t}function _e(e){return j(e)[0]??C}function j(e,t={}){return e.target===`tv`?[w]:e.target===`mobile`?[C]:t.includeFallbackWhenUnknown?[C,w]:[C]}async function ve(e){return _((await f(e,[`shell`,`pm`,`list`,`packages`,`-3`])).stdout)}function M(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(`.`).flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),r=n[n.length-1]??e;for(let e=n.length-1;e>=0;--e){let i=n[e];if(i&&!t.has(i)){r=i;break}}return r.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}async function N(e){return await F(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await F(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function P(e){return await ye(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])}async function F(e,t){for(let n of t){let t=v((await f(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}async function ye(e,t){for(let n of t){let t=oe((await f(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}function be(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!he.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function xe(e,n){let a=be(n);if(!a)return;let o=r(i(e));try{await o.ensure({local:a,remote:a})}catch(e){let n={localPort:a.replace(`tcp:`,``),operation:`adb reverse ${a} ${a}`};throw e instanceof t&&Object.assign(n,{hint:e.details?.hint,diagnosticId:e.details?.diagnosticId,logPath:e.details?.logPath}),new t(`COMMAND_FAILED`,`Failed to ensure Android port reverse ${a} before opening localhost URL`,n,e)}}function Se(e){return/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function I(e){return(e.launchArgs??[]).map(Se)}async function L(e,t,n){e.booted||await d(e.id);let r=ke(n),i=r.activity,a=t.trim();if(u(a)){await Ce(e,a,r);return}if(r.url!==void 0){await we(e,t,r);return}let o=await k(e,t),s=_e(e);if(o.type===`intent`){await Te(e,o.value,r);return}if(i){await Ee(e,o.value,i,s,r);return}await De(e,o.value,s,r)}async function Ce(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await xe(e,n),await f(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,n,...Ae(r.appBundleId),...I(r)])}async function we(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening an app-bound deep link URL`);let i=r.url?.trim()??``;if(!u(i))throw new t(`INVALID_ARGS`,`Android app-bound open requires a valid URL target`);await f(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,i,`-p`,await Oe(e,n,`app-bound open`),...I(r)])}async function Te(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await f(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...I(r)])}async function Ee(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await f(e,R(a,r,i))}catch(n){throw await je(e,t,n),n}}async function De(e,t,n,r){let i=await f(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,n,`-p`,t,...I(r)],{allowFailure:!0});if(i.exitCode===0&&!H(i.stdout,i.stderr))return;let o=await Me(e,t);if(!o)throw await B(e,t)?a(`Failed to launch ${t}`,i):z(t);await f(e,R(o,n,r))}function R(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,t,`-n`,e,...I(n)]}async function Oe(e,n,r){let i=await k(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function ke(e){return typeof e==`string`?{activity:e}:e??{}}function Ae(e){let t=e?.trim();return t?[`-p`,t]:[]}function z(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:E})}async function B(e,t){let n=await f(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(V(r),!1)}async function je(e,n,r){if(V(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await B(e,n))throw z(n)}function V(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function Me(e,t){let n=Array.from(new Set(j(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await f(e,[`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=U(n.stdout);if(i)return i}return null}function H(e,t){let n=`${e}\n${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)}function U(e){let t=e.split(`
6
- `).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function W(e){e.booted||await d(e.id)}async function G(e,n){if(n.trim().toLowerCase()===`settings`){await f(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await K(e,`com.android.settings`);return}let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await f(e,[`shell`,`am`,`force-stop`,r.value]),await K(e,r.value)}async function K(e,t){await Ne(e,t),await Fe(e,t)}async function Ne(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Pe(e))?.package!==t)return;await l(50)}}async function Pe(e){for(let t of[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`],[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]]){let n=v((await f(e,t,{allowFailure:!0})).stdout??``);if(n)return n}return null}async function Fe(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await q(e,t)&&(await l(150),!await q(e,t)))return;await l(50)}}async function q(e,t){return((await f(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}async function Ie(e,n){let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`);let i=await f(e,[`uninstall`,r.value],{allowFailure:!0});if(i.exitCode!==0){let e=`${i.stdout}\n${i.stderr}`.toLowerCase();if(!e.includes(`unknown package`)&&!e.includes(`not installed`))throw a(`adb uninstall failed for ${r.value}`,i)}return{package:r.value}}let J=null;function Le(){return`${process.env.PATH??``}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function Re(){let e=Le();if(J?.key===e)return J.invocation;if(await c(`bundletool`)){let t={cmd:`bundletool`,prefixArgs:[]};return J={key:e,invocation:t},t}let r=await n(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return J={key:e,invocation:i},i}async function Y(e){let t=await Re();await s(t.cmd,[...t.prefixArgs,...e])}function ze(e){return h.extname(e).toLowerCase()===`.aab`}async function Be(e,t){let n=i(e),r=`universal`;if(n.installBundle){await n.installBundle(t,{mode:r});return}let a=await m.mkdtemp(h.join(te.tmpdir(),`agent-device-aab-`)),o=h.join(a,`bundle.apks`);try{await Y([`build-apks`,`--bundle`,t,`--output`,o,`--mode`,r]),await Y([`install-apks`,`--apks`,o,`--device-id`,e.id])}finally{await m.rm(a,{recursive:!0,force:!0})}}async function X(e,t){if(ze(t)){await Be(e,t);return}await o(t,{device:e,replace:!0})}async function Z(e){let t=await f(e,[`shell`,`pm`,`list`,`packages`]);return new Set(t.stdout.split(`
7
- `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}async function Ve(e,t){let n=await Z(e),r=Array.from(n).filter(e=>!t.has(e));if(r.length===1)return r[0]}async function Q(e,t){await D.invalidateWhile(O(e),async()=>{e.booted||await d(e.id),await X(e,t)})}async function $(e,t,n){let r=n?void 0:await Z(e);return await Q(e,t),n??(r?await Ve(e,r):void 0)}async function He(e,t){e.booted||await d(e.id);let n=await p({kind:`path`,path:t});try{let t=await $(e,n.installablePath,n.packageName),r=t?M(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:r,launchTarget:t}}finally{await n.cleanup()}}async function Ue(e,t,n){return await D.invalidateWhile(O(e),async()=>{e.booted||await d(e.id);let{package:r}=await Ie(e,t),i=await p({kind:`path`,path:n},{resolveIdentity:!1});try{await Q(e,i.installablePath)}finally{await i.cleanup()}return{package:r}})}export{M as a,L as c,k as d,x as f,_ as g,g as h,P as i,W as l,v as m,G as n,H as o,fe as p,N as r,A as s,pe as t,U as u};
4
+ `);for(let e of ne)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function se(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=re.exec(n);if(r){let e=r[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=ie.exec(n);if(!i)return null;let a=i[1];if(a===void 0)return null;let o=a.trim().replace(/\s+/g,` `),s=ae.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}}function ce(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf(`/`);if(e<=0)continue;let n=b(t.slice(0,e),!1),r=b(t.slice(e+1),!0);if(n&&r&&n.length===e)return{package:n,activity:r}}return null}function b(e,t){let n=0;for(;n<e.length&&le(e[n],t);)n+=1;return e.slice(0,n)}function le(e,t){if(!e)return!1;let n=e.charCodeAt(0);return n>=48&&n<=57||n>=65&&n<=90||n>=97&&n<=122||e===`_`||e===`.`||t&&e===`$`}const ue=/\.(?:apk|aab)$/i,de=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function x(e){let t=e.trim();return t.length===0?`other`:ue.test(t)?t.includes(`/`)||t.includes(`\\`)||t.startsWith(`.`)||t.startsWith(`~`)||!S(t)?`binary`:`package`:S(t)?`package`:`other`}function S(e){return de.test(e)}function fe(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}var pe=e({closeAndroidApp:()=>K,getAndroidAppState:()=>N,getAndroidBlockingDialogFocus:()=>P,inferAndroidAppName:()=>M,installAndroidApp:()=>He,installAndroidInstallablePath:()=>Q,installAndroidInstallablePathAndResolvePackageName:()=>$,isAmStartError:()=>U,listAndroidApps:()=>A,openAndroidApp:()=>R,openAndroidDevice:()=>G,parseAndroidLaunchComponent:()=>W,reinstallAndroidApp:()=>Ue,resolveAndroidApp:()=>k});const me={settings:{type:`intent`,value:`android.settings.SETTINGS`}},C=`android.intent.category.LAUNCHER`,w=`android.intent.category.LEANBACK_LAUNCHER`,T=`android.intent.category.DEFAULT`,E=`Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.`,he=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]),D=ee();function O(e){return{platform:`android`,deviceId:e.id,variant:e.target??``}}async function k(e,n){let r=n.trim();if(x(r)===`package`)return{type:`package`,value:r};let i=me[r.toLowerCase()];if(i)return i;let a=O(e),o=D.get(a,r);if(o)return o;let s=(await p(e,[`shell`,`pm`,`list`,`packages`])).stdout.split(`
5
+ `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return D.set(a,r,{type:`package`,value:c});throw s.length>1?new t(`INVALID_ARGS`,`Multiple packages matched "${n}"`,{matches:s,hint:`Run agent-device apps --platform android to see the exact installed package names before retrying open.`}):new t(`APP_NOT_INSTALLED`,`No package found matching "${n}"`,{hint:E})}async function A(e,t){let n=await ge(e);return(t===`user-installed`?(await ve(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:M(e)}))}async function ge(e){let t=new Set;for(let n of j(e,{includeFallbackWhenUnknown:!0})){let r=await p(e,[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,n],{allowFailure:!0});if(!(r.exitCode!==0||r.stdout.trim().length===0))for(let e of g(r.stdout))t.add(e)}return t}function _e(e){return j(e)[0]??C}function j(e,t={}){return e.target===`tv`?[w]:e.target===`mobile`?[C]:t.includeFallbackWhenUnknown?[C,w]:[C]}async function ve(e){return _((await p(e,[`shell`,`pm`,`list`,`packages`,`-3`])).stdout)}function M(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(`.`).flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),r=n[n.length-1]??e;for(let e=n.length-1;e>=0;--e){let i=n[e];if(i&&!t.has(i)){r=i;break}}return r.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}async function N(e){return await F(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await F(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function P(e){return await ye(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])}async function F(e,t){for(let n of t){let t=v((await p(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}async function ye(e,t){for(let n of t){let t=oe((await p(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}function be(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!he.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function I(e,n){let r=be(n);if(!r)return;let o=a(i(e));try{await o.ensure({local:r,remote:r})}catch(e){let n={localPort:r.replace(`tcp:`,``),operation:`adb reverse ${r} ${r}`};throw e instanceof t&&Object.assign(n,{hint:e.details?.hint,diagnosticId:e.details?.diagnosticId,logPath:e.details?.logPath}),new t(`COMMAND_FAILED`,`Failed to ensure Android port reverse ${r} before opening localhost URL`,n,e)}}function xe(e){return/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function L(e){return(e.launchArgs??[]).map(xe)}async function R(e,t,n){e.booted||await f(e.id);let r=Oe(n),i=r.activity,a=t.trim();if(u(a)){await Se(e,a,r);return}if(r.url!==void 0){await Ce(e,t,r);return}let o=await k(e,t),s=_e(e);if(o.type===`intent`){await we(e,o.value,r);return}if(i){await Te(e,o.value,i,s,r);return}await Ee(e,o.value,s,r)}async function Se(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await I(e,n),await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,n,...ke(r.appBundleId),...L(r)])}async function Ce(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening an app-bound deep link URL`);let i=r.url?.trim()??``;if(!u(i))throw new t(`INVALID_ARGS`,`Android app-bound open requires a valid URL target`);await I(e,i),await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,i,`-p`,await De(e,n,`app-bound open`),...L(r)])}async function we(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await p(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...L(r)])}async function Te(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await p(e,z(a,r,i))}catch(n){throw await Ae(e,t,n),n}}async function Ee(e,t,n,r){let i=await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,n,`-p`,t,...L(r)],{allowFailure:!0});if(i.exitCode===0&&!U(i.stdout,i.stderr))return;let a=await je(e,t);if(!a)throw await V(e,t)?o(`Failed to launch ${t}`,i):B(t);await p(e,z(a,n,r))}function z(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,t,`-n`,e,...L(n)]}async function De(e,n,r){let i=await k(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function Oe(e){return typeof e==`string`?{activity:e}:e??{}}function ke(e){let t=e?.trim();return t?[`-p`,t]:[]}function B(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:E})}async function V(e,t){let n=await p(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(H(r),!1)}async function Ae(e,n,r){if(H(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await V(e,n))throw B(n)}function H(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function je(e,t){let n=Array.from(new Set(j(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await p(e,[`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=W(n.stdout);if(i)return i}return null}function U(e,t){let n=`${e}\n${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)}function W(e){let t=e.split(`
6
+ `).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function G(e){e.booted||await f(e.id)}async function K(e,n){if(n.trim().toLowerCase()===`settings`){await p(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await q(e,`com.android.settings`);return}let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await p(e,[`shell`,`am`,`force-stop`,r.value]),await q(e,r.value)}async function q(e,t){await Me(e,t),await Pe(e,t)}async function Me(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Ne(e))?.package!==t)return;await l(50)}}async function Ne(e){for(let t of[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`],[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]]){let n=v((await p(e,t,{allowFailure:!0})).stdout??``);if(n)return n}return null}async function Pe(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await J(e,t)&&(await l(150),!await J(e,t)))return;await l(50)}}async function J(e,t){return((await p(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}async function Fe(e,n){let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`);let i=await p(e,[`uninstall`,r.value],{allowFailure:!0});if(i.exitCode!==0){let e=`${i.stdout}\n${i.stderr}`.toLowerCase();if(!e.includes(`unknown package`)&&!e.includes(`not installed`))throw o(`adb uninstall failed for ${r.value}`,i)}return{package:r.value}}let Y=null;function Ie(){return`${process.env.PATH??``}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function Le(){let e=Ie();if(Y?.key===e)return Y.invocation;if(await c(`bundletool`)){let t={cmd:`bundletool`,prefixArgs:[]};return Y={key:e,invocation:t},t}let r=await n(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return Y={key:e,invocation:i},i}async function X(e){let t=await Le();await s(t.cmd,[...t.prefixArgs,...e])}function Re(e){return h.extname(e).toLowerCase()===`.aab`}async function ze(e,t){let n=i(e),r=`universal`;if(n.installBundle){await n.installBundle(t,{mode:r});return}let a=await m.mkdtemp(h.join(te.tmpdir(),`agent-device-aab-`)),o=h.join(a,`bundle.apks`);try{await X([`build-apks`,`--bundle`,t,`--output`,o,`--mode`,r]),await X([`install-apks`,`--apks`,o,`--device-id`,e.id])}finally{await m.rm(a,{recursive:!0,force:!0})}}async function Be(e,t){if(Re(t)){await ze(e,t);return}await r(t,{device:e,replace:!0})}async function Z(e){let t=await p(e,[`shell`,`pm`,`list`,`packages`]);return new Set(t.stdout.split(`
7
+ `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}async function Ve(e,t){let n=await Z(e),r=Array.from(n).filter(e=>!t.has(e));if(r.length===1)return r[0]}async function Q(e,t){await D.invalidateWhile(O(e),async()=>{e.booted||await f(e.id),await Be(e,t)})}async function $(e,t,n){let r=n?void 0:await Z(e);return await Q(e,t),n??(r?await Ve(e,r):void 0)}async function He(e,t){e.booted||await f(e.id);let n=await d({kind:`path`,path:t});try{let t=await $(e,n.installablePath,n.packageName),r=t?M(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:r,launchTarget:t}}finally{await n.cleanup()}}async function Ue(e,t,n){return await D.invalidateWhile(O(e),async()=>{e.booted||await f(e.id);let{package:r}=await Fe(e,t),i=await d({kind:`path`,path:n},{resolveIdentity:!1});try{await Q(e,i.installablePath)}finally{await i.cleanup()}return{package:r}})}export{M as a,R as c,k as d,x as f,_ as g,g as h,P as i,G as l,v as m,K as n,U as o,fe as p,N as r,A as s,pe as t,W as u};
@@ -0,0 +1 @@
1
+ import{gt as e}from"./internal/daemon.js";export{e as withAppLogProvider};
@@ -0,0 +1 @@
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{c as n,s as r}from"./sdk-device.js";import{d as i,u as a}from"./logcat.js";import{M as o}from"./runner-disposal.js";import{a as s,i as c,r as l,s as u}from"./tool-provider.js";import{n as d}from"./helper.js";import{at as f}from"./internal/daemon.js";import{n as p}from"./setting-state.js";import m from"node:path";import{fileURLToPath as h}from"node:url";const g={settings:`com.apple.systempreferences`},_=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,v={platform:`macos`,deviceId:`host`,variant:`all`},y=a();function b(e){return _.test(e)}async function x(e){let n=e.trim(),r=g[n.toLowerCase()];if(r)return r;if(b(n))return n;let i=y.get(v,n);if(i)return i;let a=(await O(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return y.set(v,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function S(e,n,r){let a=r?.url?.trim();if(a){if(!i(a))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=r?.appBundleId??await x(n);await k().openBundle(e,a);return}let o=n.trim();if(i(o)){await k().openTarget(o);return}let s=r?.appBundleId??await x(o);await k().openBundle(s)}async function C(e,n){let r=await x(n),i=await d(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function w(){return await k().readClipboard()}async function T(e){await k().writeClipboard(e)}async function E(){return await k().readDarkMode()}async function D(e){let t=p(e),n=t===`toggle`?!await E():t===`dark`;await k().setDarkMode(n)}async function O(e){return await k().listApps(e)}function k(){let e=l().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}function A(e,t){return o(e,t)}function j(e,t,n){return s(A(e,t),n)}function M(e){return e.includes(`not installed`)||e.includes(`not found`)||e.includes(`no such file`)}var N=e({invalidateIosAppResolutionCache:()=>L,listIosApps:()=>H,resolveIosApp:()=>R,resolveIosAppAlias:()=>z,resolveIosSimulatorDeepLinkBundleId:()=>B});const P={settings:`com.apple.Preferences`},F=a();function I(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function L(e,t){return await F.invalidateWhile(I(e),t)}async function R(e,r){if(n(e))return await x(r);let i=r.trim();if(i.includes(`.`))return i;let a=z(i);if(a!==i)return a;let o=I(e),s=F.get(o,i);if(s)return s;let c=(e.kind===`simulator`?await U(e):await f(e,`all`)).filter(e=>e.name.toLowerCase()===i.toLowerCase()),l=c[0];if(l!==void 0&&c.length===1)return F.set(o,i,l.bundleId);throw c.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${r}"`,{matches:c}):new t(`APP_NOT_INSTALLED`,`No app found matching "${r}"`)}function z(e){let t=e.trim();return P[t.toLowerCase()]??e}async function B(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=V(t);if(!n)return;let i=await W(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await K(m.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function V(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function H(e,t){return n(e)?await O(t):e.kind===`simulator`?u(await U(e),t):await f(e,t)}async function U(e){return(await W(e)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function W(e){let t=(await j(e,[`listapps`,e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith(`{`))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith(`{`))try{let e=await c(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:t});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>{let n=G(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function G(e){if(e.Path)return e.Path;if(e.Bundle)try{return h(e.Bundle)}catch{return}}async function K(e){let t=await c(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{B as a,A as c,w as d,D as f,R as i,C as l,L as n,M as o,T as p,H as r,j as s,N as t,S as u};
@@ -0,0 +1 @@
1
+ import{_ as e}from"./sdk-contracts.js";import{o as t,v as n}from"./sdk-device.js";const r={ios:`iOS`,ipados:`iPadOS`,tvos:`tvOS`,watchos:`watchOS`,visionos:`visionOS`,macos:`macOS`},i={visionos:`visionOS uses spatial input and does not support two-finger touch synthesis.`,tvos:`tvOS has no touch input — this gesture is supported on Android and the iOS simulator only.`,macos:`macOS automation has no multi-touch input — this gesture is supported on Android and the iOS simulator only.`};function a(a,s){if(!t(a.platform))throw o(s,a.platform);let c=n(a);if(!((c===`ios`||c===`ipados`)&&a.kind===`simulator`))throw c===`ios`||c===`ipados`?new e(`UNSUPPORTED_OPERATION`,`gesture ${s} is not supported on physical iOS devices`,{hint:`Two-finger gesture synthesis is iOS-simulator only — not available on physical iOS devices.`}):o(s,r[c],i[c])}function o(t,n,r){return new e(`UNSUPPORTED_OPERATION`,`gesture ${t} is not supported on ${n}`,r===void 0?void 0:{hint:r})}export{a as t};