agent-device 0.20.5 → 0.20.7

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 (196) hide show
  1. package/README.md +5 -3
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.apk → agent-device-android-ime-helper-0.20.7.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.manifest.json → agent-device-android-ime-helper-0.20.7.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.apk → agent-device-android-snapshot-helper-0.20.7.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.manifest.json → agent-device-android-snapshot-helper-0.20.7.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +48 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +108 -1
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +630 -89
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +149 -10
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +161 -32
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +18 -1
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +145 -20
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +234 -0
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +106 -448
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +602 -0
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
  37. package/dist/src/agent-browser-tool.js +1 -1
  38. package/dist/src/agent-device-client.js +2 -2
  39. package/dist/src/android-adb.js +1 -1
  40. package/dist/src/android.js +1 -1
  41. package/dist/src/app-helpers.js +1 -1
  42. package/dist/src/app-lifecycle.js +7 -7
  43. package/dist/src/app-lifecycle2.js +2 -0
  44. package/dist/src/app-log-files.js +1 -0
  45. package/dist/src/app-log-reconnect.js +1 -0
  46. package/dist/src/app-log-runtime.js +4 -0
  47. package/dist/src/app-resolution.js +2 -1
  48. package/dist/src/apps.js +5 -5
  49. package/dist/src/audio-probe.js +1 -1
  50. package/dist/src/auth-session.js +1 -0
  51. package/dist/src/auth.js +2 -0
  52. package/dist/src/boot-diagnostics.js +2 -2
  53. package/dist/src/cli-config.js +1 -1
  54. package/dist/src/cli-grammar.js +1 -0
  55. package/dist/src/cli-help.js +204 -254
  56. package/dist/src/cli-output.js +1 -0
  57. package/dist/src/cli-runner.js +1 -2
  58. package/dist/src/cli.js +6 -16
  59. package/dist/src/client-metro.js +1 -1
  60. package/dist/src/cloud-artifacts.d.ts +2 -137
  61. package/dist/src/command-metadata.js +1 -1
  62. package/dist/src/command-schema.js +3 -3
  63. package/dist/src/connection-runtime.js +1 -0
  64. package/dist/src/connection.js +5 -0
  65. package/dist/src/context.js +1 -1
  66. package/dist/src/daemon-shutdown-report.js +1 -0
  67. package/dist/src/daemon.js +2 -0
  68. package/dist/src/debug-symbols.js +3 -3
  69. package/dist/src/device-claim-inspection.js +1 -0
  70. package/dist/src/device-input-state.js +2 -2
  71. package/dist/src/device.js +1 -1
  72. package/dist/src/device2.js +2 -0
  73. package/dist/src/find.js +1 -1
  74. package/dist/src/finders.js +1 -1
  75. package/dist/src/generic-settle.js +1 -0
  76. package/dist/src/generic.js +1 -1
  77. package/dist/src/harmonyos.js +1 -0
  78. package/dist/src/helper.js +1 -1
  79. package/dist/src/host-process.js +2 -2
  80. package/dist/src/ime-lifecycle.js +7 -7
  81. package/dist/src/index.d.ts +69 -18
  82. package/dist/src/input-actions.js +4 -4
  83. package/dist/src/input-actions2.js +1 -1
  84. package/dist/src/input-actions3.js +1 -0
  85. package/dist/src/install-artifact.js +1 -5
  86. package/dist/src/install-artifact2.js +1 -1
  87. package/dist/src/install-source2.js +1 -1
  88. package/dist/src/interaction-runtime.js +1 -0
  89. package/dist/src/interaction-snapshot.js +1 -1
  90. package/dist/src/interaction-touch-reference-frame.js +1 -0
  91. package/dist/src/interaction.js +1 -1
  92. package/dist/src/interactor.js +2 -2
  93. package/dist/src/interactor2.js +1 -1
  94. package/dist/src/internal/bin.js +2 -2
  95. package/dist/src/internal/daemon.js +9 -16
  96. package/dist/src/inventory.js +5 -0
  97. package/dist/src/inventory2.js +1 -0
  98. package/dist/src/inventory3.js +2 -0
  99. package/dist/src/inventory4.js +1 -0
  100. package/dist/src/inventory5.js +1 -0
  101. package/dist/src/inventory6.js +1 -0
  102. package/dist/src/lease-context.js +1 -1
  103. package/dist/src/lease.js +1 -1
  104. package/dist/src/limrun-runtime-dependencies.js +1 -0
  105. package/dist/src/limrun.d.ts +10 -104
  106. package/dist/src/limrun.js +1 -1
  107. package/dist/src/linux.js +1 -1
  108. package/dist/src/logcat.js +1 -1
  109. package/dist/src/manifest.js +1 -1
  110. package/dist/src/owner-identity.js +1 -0
  111. package/dist/src/physical-device-control.js +1 -1
  112. package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
  113. package/dist/src/platform-runtime-app-log-process.js +1 -0
  114. package/dist/src/platform-runtime-host.js +1 -0
  115. package/dist/src/platform-runtime-network-web-transport.js +1 -0
  116. package/dist/src/platform-runtime-operation-host.js +5 -0
  117. package/dist/src/platform-runtime-toolchain-host.js +1 -0
  118. package/dist/src/platform-runtime.js +1 -0
  119. package/dist/src/prepare-kind.js +15 -0
  120. package/dist/src/process-entry.js +1 -0
  121. package/dist/src/process-exit.js +1 -0
  122. package/dist/src/process-lock.js +1 -1
  123. package/dist/src/provider-webdriver.js +1 -0
  124. package/dist/src/provider.js +1 -0
  125. package/dist/src/proxy.js +2 -0
  126. package/dist/src/react-native.js +1 -1
  127. package/dist/src/record-trace.js +1 -1
  128. package/dist/src/registry.js +25 -24
  129. package/dist/src/remote-config.js +1 -1
  130. package/dist/src/remote-config2.js +1 -1
  131. package/dist/src/replay.js +3 -0
  132. package/dist/src/reporting.js +4 -4
  133. package/dist/src/runner-client.js +1 -1
  134. package/dist/src/runner-disposal.js +1 -1
  135. package/dist/src/runner-lease.js +1 -1
  136. package/dist/src/runtime.js +3 -3
  137. package/dist/src/runtime2.js +4 -0
  138. package/dist/src/runtime3.js +3 -0
  139. package/dist/src/runtime4.js +1 -0
  140. package/dist/src/runtime5.js +1 -0
  141. package/dist/src/runtime6.js +1 -0
  142. package/dist/src/runtime7.js +1 -0
  143. package/dist/src/screenshot-result.js +4 -4
  144. package/dist/src/screenshot.js +1 -0
  145. package/dist/src/sdk-android-adb.d.ts +20 -2
  146. package/dist/src/sdk-android-adb.js +2 -2
  147. package/dist/src/sdk-batch-runner.js +3 -3
  148. package/dist/src/sdk-contracts.d.ts +47 -6
  149. package/dist/src/sdk-contracts.js +1 -1
  150. package/dist/src/sdk-device.js +1 -1
  151. package/dist/src/sdk-finders.d.ts +4 -20
  152. package/dist/src/sdk-finders.js +1 -1
  153. package/dist/src/sdk-remote-config.js +1 -1
  154. package/dist/src/sdk-selectors.d.ts +601 -0
  155. package/dist/src/sdk-selectors.js +1 -1
  156. package/dist/src/selector-runtime.js +1 -1
  157. package/dist/src/selector-vocabulary.js +1 -1
  158. package/dist/src/selectors.d.ts +1 -46
  159. package/dist/src/selectors.js +1 -1
  160. package/dist/src/server.js +3 -3
  161. package/dist/src/session-target-evidence.js +1 -1
  162. package/dist/src/session.js +10 -9
  163. package/dist/src/shared.js +2 -0
  164. package/dist/src/shell-quote.js +1 -0
  165. package/dist/src/simulator.js +1 -1
  166. package/dist/src/snapshot-runtime.js +1 -0
  167. package/dist/src/snapshot-session.js +1 -0
  168. package/dist/src/snapshot.js +1 -1
  169. package/dist/src/snapshot2.js +1 -1
  170. package/dist/src/src.js +1 -1
  171. package/dist/src/src2.js +2 -0
  172. package/dist/src/src3.js +1 -0
  173. package/dist/src/text-surface.js +1 -0
  174. package/dist/src/timing-safe-equal.js +1 -0
  175. package/dist/src/tool-provider.js +3 -3
  176. package/dist/src/tool-provider2.js +1 -1
  177. package/dist/src/tool-provider3.js +1 -1
  178. package/dist/src/update-check.js +1 -1
  179. package/dist/src/version.js +1 -1
  180. package/dist/src/web.js +1 -1
  181. package/package.json +72 -50
  182. package/server.json +3 -3
  183. package/skills/agent-device/SKILL.md +6 -31
  184. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +0 -1
  185. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +0 -1
  186. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
  187. package/dist/src/app-log-request-scope.js +0 -1
  188. package/dist/src/devices.js +0 -1
  189. package/dist/src/devices2.js +0 -1
  190. package/dist/src/devices3.js +0 -1
  191. package/dist/src/devices4.js +0 -1
  192. package/dist/src/interaction.d.ts +0 -230
  193. package/dist/src/provider-limrun-runtime.js +0 -1
  194. package/dist/src/register-builtins.js +0 -1
  195. package/dist/src/screenshot-geometry.js +0 -1
  196. package/dist/src/viewport-dimension.js +0 -14
@@ -0,0 +1 @@
1
+ import{t as e}from"./registry.js";const t=e();function n(e){return t[e.name]?.({input:e.input??{},result:e.result})}export{n as t};
@@ -1,2 +1 @@
1
- import{ut as e}from"./viewport-dimension.js";import{n as t}from"./registry.js";import{n}from"./cli-config.js";import{n as r}from"./command-surface.js";function i(t,n,r){if(t.json){e({success:!0,data:n});return}let i=r?.();i&&a(i)}function a(e){process.stdout.write(e.endsWith(`
2
- `)?e:`${e}\n`)}const o=t();function s(e,t,n){let r=o[e];if(!r)throw Error(`Missing CLI reader for command: ${e}`);return r(t,n)}async function c(e){return(await l(e)).result}async function l(e){let t=s(e.command,e.positionals,e.flags),i=await r(e.client,e.command,t);return{result:i,cliOutput:n({name:e.command,input:t,result:i})}}export{i,l as n,s as r,c as t};
1
+ import{t as e}from"./cli-grammar.js";import{t}from"./cli-output.js";import{n}from"./command-surface.js";async function r(e){return(await i(e)).result}async function i(r){let i=e(r.command,r.positionals,r.flags),a=await n(r.client,r.command,i);return{result:a,cliOutput:t({name:r.command,input:i,result:a})}}export{i as n,r as t};
package/dist/src/cli.js CHANGED
@@ -1,17 +1,7 @@
1
- import{S as e,_ as t,a as n,v as r,w as i}from"./sdk-contracts.js";import{Gt as a,Ht as o,Ut as s,Wt as c,at as l,dt as u,fn as d,ln as f,lt as p,ot as m,pn as h,st as g,ut as _}from"./viewport-dimension.js";import"./screenshot-geometry.js";import{H as ee,p as te,q as v}from"./sdk-batch-runner.js";import{bt as ne,d as re,gt as ie,h as y,ht as ae,mt as oe,p as se,pt as ce,r as le,st as ue,t as de,vt as fe,xt as pe,y as b}from"./screenshot-result.js";import{h as me,i as he,s as ge,v as _e}from"./sdk-device.js";import{a as ve,i as ye,n as be,r as xe}from"./agent-device-client.js";import{S as Se,l as Ce,x as we}from"./registry.js";import{t as Te}from"./sdk-remote-config.js";import"./sdk-selectors.js";import{n as Ee}from"./command-metadata.js";import{A as De,L as Oe,M as ke,N as Ae,P as je,S as Me,j as Ne,v as Pe}from"./sdk-android-adb.js";import{n as Fe}from"./version.js";import{n as x}from"./path-resolution.js";import{t as Ie}from"./timeouts.js";import{n as Le,u as Re}from"./host-process.js";import{v as ze}from"./url.js";import{a as Be,i as Ve}from"./client-metro.js";import{n as He}from"./metro2.js";import{n as S,t as Ue}from"./remote-config2.js";import{t as We}from"./src.js";import{C as Ge,S as C,a as Ke,b as qe,i as Je,n as Ye,p as Xe,u as Ze,w as Qe,x as $e,y as et}from"./selector-vocabulary.js";import{i as tt,n as nt,t as rt}from"./command-schema.js";import{t as it}from"./update-check.js";import{i as at,r as w,t as ot}from"./cli-config.js";import{i as T,r as st,t as ct}from"./cli-runner.js";import E from"node:path";import D,{randomBytes as lt,randomUUID as ut}from"node:crypto";import O from"node:fs";import dt from"node:http";import{pipeline as ft}from"node:stream/promises";import{Readable as pt}from"node:stream";import{pathToFileURL as mt}from"node:url";import{stringify as ht}from"yaml";function gt(e,t){return`${e},${t}`}function _t(e){return`${e.map(e=>ht(e).trimEnd()).join(`
2
- ---
3
- `)}\n`}const vt=new Set(Je),yt=new Set(Ye);function bt(e,n){let r={config:xt(n.metadata),warnings:[],unsupported:[]},i=[];for(let[t,a]of e.entries()){let e=n.actionLines?.[t]??t+1,o=Ct(a,n.parseSelector);switch(o.kind){case`commands`:i.push(...o.commands),$t(r,o.warnings,a,e);break;case`config`:Zt(r,o.appId,a,e),i.push(...o.commands),$t(r,o.warnings,a,e);break;case`unsupported`:r.unsupported.push({line:e,action:A(a),message:o.message});break}}if(r.unsupported.length>0)throw new t(`INVALID_ARGS`,`Cannot export replay to Maestro YAML: unsupported .ad action ${nn(r.unsupported)}.`,{unsupported:r.unsupported});return{yaml:tn(r.config,i),warnings:r.warnings}}function xt(e){return e?.env&&Object.keys(e.env).length>0?{env:e.env}:{}}const St={open:wt,click:Dt,press:Dt,longpress:Ot,fill:Mt,type:Nt,keyboard:Pt,back:()=>({kind:`commands`,commands:[`back`]}),wait:Ft,find:It,screenshot:Lt,scroll:Rt,swipe:zt};function Ct(e,t){return St[e.command]?.(e,t)??{kind:`unsupported`,message:`${e.command} has no Maestro equivalent`}}function wt(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`open requires an app id or URL`};if(rn(t))return{kind:`commands`,commands:[{openLink:t}]};let r=Tt(e,t);return n&&rn(n)?{kind:`config`,appId:t,commands:[r,{openLink:n}]}:n?{kind:`unsupported`,message:`open with a non-URL second argument is unsupported`}:{kind:`config`,appId:t,commands:[r]}}function Tt(e,t){let n=Et(e);return n?{launchApp:{appId:t,...n}}:`launchApp`}function Et(e){let t=e.flags?.launchArgs,n={};return e.flags?.relaunch===!0&&(n.stopApp=!0),e.flags?.clearAppState===!0&&(n.clearState=!0),Array.isArray(t)&&t.length>0&&(n.launchArguments=t),Object.keys(n).length>0?n:void 0}function Dt(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`${e.command} requires a target`};let i=k(n,r,t);if(!i)return{kind:`unsupported`,message:`tap target is not Maestro-compatible`};let a=qt(e);return a.ok?e.flags?.doubleTap===!0?{kind:`commands`,commands:[{doubleTapOn:i}],warnings:jt(e,`doubleTapOn`)}:typeof e.flags?.holdMs==`number`?{kind:`commands`,commands:[{longPressOn:i}],warnings:[At(e.flags.holdMs),...jt(e,`longPressOn`)]}:{kind:`commands`,commands:[Xt(i,a.options)]}:{kind:`unsupported`,message:a.message}}function Ot(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`longpress requires a target`};let i=k(n,r,t);return i?{kind:`commands`,commands:[{longPressOn:i}],warnings:kt(e).map(At)}:{kind:`unsupported`,message:`longpress target is not Maestro-compatible`}}function kt(e){let[t,n,r]=e.positionals,i=j(t)&&j(n)?r:n;return i&&j(i)?[Number(i)]:[]}function At(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function jt(e,t){let n=[];return typeof e.flags?.count==`number`&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function Mt(e,t){let[n,r]=e.positionals;if(!n||r===void 0)return{kind:`unsupported`,message:`fill requires a target and text`};let i=k(n,void 0,t);return i?{kind:`commands`,commands:[{tapOn:i},{inputText:r}],warnings:[`fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents`]}:{kind:`unsupported`,message:`fill target is not Maestro-compatible`}}function Nt(e){let[t]=e.positionals;if(t===void 0)return{kind:`unsupported`,message:`type requires text`};let n=Qt(t);return n===null?{kind:`commands`,commands:[{inputText:t}]}:{kind:`commands`,commands:[{eraseText:n}]}}function Pt(e){let[t]=e.positionals;return t===`dismiss`?{kind:`commands`,commands:[`hideKeyboard`]}:t===`enter`||t===`return`?{kind:`commands`,commands:[{pressKey:`Enter`}]}:{kind:`unsupported`,message:`keyboard ${t??``}`.trim()}}function Ft(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`wait requires a target or duration`};if(j(n))return{kind:`commands`,commands:[{waitForAnimationToEnd:{timeout:Number(n)}}],warnings:[`wait <ms> exports as waitForAnimationToEnd and may return before the full duration`]};if(n===`text`&&r)return{kind:`commands`,commands:[{extendedWaitUntil:{visible:r,timeout:en(e,Ke.extendedWaitUntilTimeoutMs)}}]};let i=Ut(n,t);return i?{kind:`commands`,commands:[{extendedWaitUntil:{visible:i,timeout:en(e,Ke.extendedWaitUntilTimeoutMs)}}]}:{kind:`unsupported`,message:`wait selector is not Maestro-compatible`}}function It(e){let[t,n,r]=e.positionals;return t!==`text`||!n||!r?{kind:`unsupported`,message:`only find text <query> exists|missing exports to Maestro`}:r===`exists`?{kind:`commands`,commands:[{assertVisible:n}]}:r===`missing`||r===`not-exists`?{kind:`commands`,commands:[{assertNotVisible:n}]}:{kind:`unsupported`,message:`find text assertion "${r}" is unsupported`}}function Lt(e){let[t]=e.positionals;return t?{kind:`commands`,commands:[{takeScreenshot:t}]}:{kind:`unsupported`,message:`screenshot requires an output path`}}function Rt(e){let[t]=e.positionals;return!t||t===`down`?{kind:`commands`,commands:[`scroll`]}:{kind:`unsupported`,message:`scroll ${t} is not exported yet`}}function zt(e){let t=Bt(e);if(!t)return{kind:`unsupported`,message:`only coordinate swipe exports to Maestro`};let n=Vt(e);if(n===null)return{kind:`unsupported`,message:`swipe count must be a positive integer`};let r=Ht(e);return r?{kind:`unsupported`,message:r}:{kind:`commands`,commands:Array.from({length:n},()=>({swipe:t}))}}function Bt(e){let[t,n,r,i]=e.positionals;if(!(!j(t)||!j(n)||!j(r)||!j(i)))return{start:gt(t,n),end:gt(r,i),duration:100}}function Vt(e){let t=e.flags?.count??1;return Number.isInteger(t)&&t>=1?t:null}function Ht(e){if(e.flags?.pauseMs!==void 0)return`swipe --pause-ms has no Maestro equivalent`;if(e.flags?.pattern&&e.flags.pattern!==`one-way`)return`swipe ping-pong pattern has no Maestro equivalent`}function k(e,t,n){return j(e)&&j(t)?{point:gt(e,t)}:e.startsWith(`@`)?null:Ut(e,n)}function Ut(e,t){let n;try{n=t(e)}catch{return e.includes(`=`)||e.includes(`||`)?null:e}let r=Wt(n.selectors);return r===null?n.selectors.length===1?Gt(n.selectors[0]):null:r}function Wt(e){if(e.length<=1)return null;let t=e.flatMap(e=>e.terms.length===1&&vt.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||t.length===0)return null;let n=t[0];return typeof n==`string`&&t.every(e=>e===n)?n:null}function Gt(e){let t={};for(let n of e.terms)if(!Kt(t,n))return null;return Object.keys(t).length>0?t:null}function Kt(e,t){return vt.has(t.key)?typeof t.value!=`string`||e.id||e.text||e.label?!1:(e[t.key]=t.value,!0):yt.has(t.key)&&typeof t.value==`boolean`?(e[t.key]=t.value,!0):!1}function qt(e){let t=Yt(e);return t?{ok:!1,message:t}:{ok:!0,options:Jt(e)}}function Jt(e){let t={};return typeof e.flags?.count==`number`&&e.flags.count>1&&(t.repeat=e.flags.count),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&(t.delay=e.flags.intervalMs),t}function Yt(e){if(e.flags?.jitterPx!==void 0)return`tap --jitter-px has no Maestro equivalent`;if(e.flags?.clickButton&&e.flags.clickButton!==`primary`)return`tap --button ${e.flags.clickButton} has no Maestro equivalent`}function Xt(e,t){return Object.keys(t).length===0?{tapOn:e}:typeof e==`string`?{tapOn:{text:e,...t}}:e&&typeof e==`object`&&!Array.isArray(e)?{tapOn:{...e,...t}}:{tapOn:e}}function Zt(e,t,n,r){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:r,action:A(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})}function Qt(e){return e.length===0||![...e].every(e=>e===`\b`)?null:e.length}function $t(e,t,n,r){for(let i of t??[])e.warnings.push({line:r,action:A(n),message:i})}function en(e,t){let n=e.positionals.at(-1);return n&&j(n)?Number(n):t}function tn(e,t){return _t(Object.keys(e).length>0?[e,t]:[t])}function nn(e){return e.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join(`; `)}function A(e){return[e.command,...e.positionals??[]].join(` `).trim()}function rn(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function j(e){return e!==void 0&&Number.isFinite(Number(e))}const an=new Map([{alias:`long-press`,command:`longpress`},{alias:`metrics`,command:`perf`},{alias:`tap`,command:`press`},{alias:`launch`,command:`open`},{alias:`relaunch`,command:`open`,impliedFlags:[`relaunch`]}].map(e=>[e.alias,e]));function on(e){return an.get(e.toLowerCase())?.command??e}function sn(e){return an.get(e.toLowerCase())}const M=`open <app> --relaunch`,cn={start:{command:`open`,example:M},restart:{command:`open`,example:M},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function ln(e){if(e.length<=2)return[];let t=a(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=un(e),i=t.map(t=>({name:t,distance:dn(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let o=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===o).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function un(e){return e.length<4?1:e.length<=6?2:3}function dn(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):fn(e,t)}function fn(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function pn(e){let t=e.toLowerCase(),n=cn[t]?.example;if(n)return n;let r=ln(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const mn=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),hn=new Set([`--session-locked`,`--session-lock-conflicts`]);function gn(e){return mn.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${M}.`:hn.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:`Unknown flag: ${e}`}function _n(e){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=In(l));continue}if(xn(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=In(l));continue}let[f,p]=u?Tn(l):[l,void 0];if(yn(r,f))continue;let m=Sn(f,r);if(bn(r,m)){a.push(l);continue}if(!m){if(An(r,a,l)){r?a.push(l):r=l;continue}throw new t(`INVALID_ARGS`,gn(f))}let h=En(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return vn(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function vn(e,t){if(e)for(let n of sn(e)?.impliedFlags??[])t[n]=!0}function yn(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function bn(e,t){return e===`react-devtools`?t?!w(t.key,e):!0:!1}function xn(e){return e===`cdp`}function Sn(e,t){let n=Se().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??we(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return we(e)}function Cn(e,n){let r=n?.strictFlags??!0,i=[...e.warnings],a=at({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(at(a,e.flags),e.command&&!c(e.command)&&!a.help){let n=pn(e.command);throw new t(`INVALID_ARGS`,n?`Unknown command: ${e.command}. Did you mean ${n}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!w(t.key,e.command));if(o.length>0){let n=o.map(e=>e.token),s=Nn(e.command,n);if(r)throw new t(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(w(t,e.command)||delete a[t]);wn(e),rt(e.command,a);let s=Mn({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(nt(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new t(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function wn(e){if(e.command!==`back`)return;let n=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new t(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function Tn(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function En(e,n,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new t(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||On(i)?{value:!0,consumeNext:!1}:kn(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&On(a))throw new t(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new t(`INVALID_ARGS`,`Invalid ${Dn(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new t(`INVALID_ARGS`,`Invalid ${Dn(n)}: ${a}`);return{value:Math.floor(o),consumeNext:r===void 0}}function Dn(e){return e.replace(/^-+/,``)}function On(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?Tn(e):[e,void 0];return we(t)!==void 0}function kn(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function An(e,t,n){if(!jn(n)||!e)return!1;let r=tt(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function jn(e){return/^-\d+(\.\d+)?$/.test(e)}function Mn(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function Nn(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function Pn(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function Fn(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(In(e))}function In(e){if(e.toLowerCase()===`rotate`)throw new t(`INVALID_ARGS`,`rotate was renamed to orientation; for the two-finger gesture use: gesture rotate`);return on(e)}const Ln={slug:`react-devtools-companion`,runArg:ze,displayName:`React DevTools companion`};async function Rn(e){return await Ve({...e,definition:Ln,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function zn(e){return await Be({...e,definition:Ln})}function Bn(e){return e===`android-instance`||e===`ios-instance`}function Vn(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function Hn(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function Un(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!Hn(e)}function Wn(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function Gn(e){let t=e?.metroPublicBaseUrl?.trim();return t?Wn(t):null}function Kn(e,n={}){if(!Un(e)||!n.flags?.metroProxyBaseUrl||!Bn(n.flags.leaseBackend))return e;let r=Gn(n.flags);if(!r)throw new t(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...e,`--url`,r]}async function qn(e,t={}){return(await Me(`npm`,Vn(Kn(e,t)),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function N(e){let t=er(e);if(!O.existsSync(t))return null;let n;try{n=JSON.parse(O.readFileSync(t,`utf8`))}catch(t){return or(e,t),null}return cr(n)?n:(or(e),null)}function Jn(e){let t=er({stateDir:e.stateDir,session:e.state.session});O.mkdirSync(E.dirname(t),{recursive:!0}),ir(t,e.state),ir(P(e.stateDir),{session:e.state.session})}function Yn(e){return{baseUrl:ar(e.daemonBaseUrl),authToken:e.daemonAuthToken,transport:e.daemonTransport,serverMode:e.daemonServerMode}}function Xn(e){O.rmSync(er(e),{force:!0});let t=P(e.stateDir);tr(e.stateDir)===e.session&&O.rmSync(t,{force:!0})}function Zn(e){let n=e.validateRemoteConfigHash??!0,r=e.remoteConfig?Ue({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,i=N(e)??(e.allowActiveFallback?F({stateDir:e.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&$n(i.remoteConfigPath)!==i.remoteConfigHash)throw new t(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=rr(i,e),o=f(i);return{runtime:i.runtime,connection:h(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:i.daemon?.authToken??a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...d(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function Qn(e){return h(f(e))}function $n(e){try{return D.createHash(`sha256`).update(O.readFileSync(e)).digest(`hex`)}catch(n){throw new t(`INVALID_ARGS`,`Remote config file not found: ${e}`,{cause:n instanceof Error?n.message:String(n)})}}function er(e){return E.join(e.stateDir,`remote-connections`,`${sr(e.session)}.json`)}function P(e){return E.join(e,`remote-connections`,`.active-session.json`)}function F(e){let t=tr(e.stateDir);return t?N({stateDir:e.stateDir,session:t}):null}function tr(e){let t=P(e);if(O.existsSync(t))try{let e=JSON.parse(O.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function nr(e){if(e)return D.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function rr(e,t){try{return S({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function ir(e,t){O.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:`utf8`,mode:384}),O.chmodSync(e,384)}function ar(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of[...t.searchParams.keys()])/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function or(e,t){Ne({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),Xn(e)}function sr(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${D.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function cr(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&lr(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ur(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&dr(t.daemon)}function lr(e,t){return t.every(t=>typeof e[t]==`string`)}function ur(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function dr(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:fr(e)}function fr(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const pr=Te.map(e=>e.key);function I(e){let t={};for(let n of pr){let r=e[n];r!==void 0&&(t[n]=r)}return t}function mr(e){return e.remoteConfig?{...I(S({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function hr(e){return e===`cloud`||e===`proxy`||L(e)}function L(e){return e===`limrun`||Ge(e)}function gr(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function _r(e){return!L(e)}function vr(e){return e===`proxy`?`proxy`:L(e)?`direct-device-provider`:`remote-provider`}function yr(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function R(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const z=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),br=new Set([`open`]),xr=new Set([s.open,s.install,s.reinstall,o.installSource]);async function Sr(e){let{command:n,flags:r,client:i}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=b(r.stateDir).baseDir,o=S({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...I(o.profile),...r,remoteConfig:o.resolvedPath},c=N({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new t(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??Gr(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=Wr(l.runtime,u.platform)??e.runtime,f=l,p=!c,m,h=Ar(f);if(h.shouldAllocate(n)){let e=await Dr({command:n,client:i,state:l,nextState:f,nextFlags:u,policy:h});f=e.state,p||=e.changed,m=e.acquiredLeaseForCleanup}let g=await Cr({command:n,flags:u,client:i,state:l,nextState:f,runtime:d,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return f=g.state,d=g.runtime,p||=g.changed,await Er({changed:p,stateDir:a,state:f,client:i,acquiredLeaseForCleanup:m,preparedMetroCleanupOnFailure:g.preparedMetroCleanupOnFailure,metroCleanupToStop:g.metroCleanupToStop}),{flags:{...u,session:f.session,leaseId:f.leaseId,leaseBackend:f.leaseBackend,platform:f.platform??u.platform,target:f.target??u.target},runtime:d,connection:Qn(f)}}async function Cr(e){let{command:n,flags:r,state:i,client:a}=e,o=wr(e.nextState,r),s=e.runtime;if(!Br(n,r,e.batchSteps,e.positionals)||!Vr(r)||!Tr(e.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new t(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Pr(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Ur(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function wr(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Tr(e,t,n){return e===!0||!t||!Hr(t,n)}async function Er(e){if(e.changed)try{Jn({stateDir:e.stateDir,state:e.state})}catch(t){throw await B(e.preparedMetroCleanupOnFailure),await Rr(e.client,e.state,e.acquiredLeaseForCleanup),t}await B(e.metroCleanupToStop)}async function Dr(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??V(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&Jr(i,c.device);let l=s.leaseBackend??o??zr(i,t);Qr(r,i,l);let u=await Kr(n,s,l,a,i),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Or(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:kr(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Or(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function kr(e,t,n,r){return{...e,leaseId:t.leaseId,leaseBackend:n,leaseProvider:t.leaseProvider??e.leaseProvider,clientId:t.clientId??e.clientId,deviceKey:t.deviceKey??e.deviceKey,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Ar(e){return e.leaseProvider===`proxy`?Mr:Ge(e.leaseProvider)?Nr:jr}const jr={shouldAllocate:e=>!z.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Mr={shouldAllocate:e=>e!==`devices`&&!z.has(e),ttlMs:()=>3e5,resolveLeaseState:qr},Nr={shouldAllocate:e=>!z.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Pr(e,n,r,i,a){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if(e.platform!==`ios`&&e.platform!==`android`)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:e.metroProjectRoot,kind:Ce(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:a,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:e.metroNoReuseExisting?!1:void 0,installDependenciesIfNeeded:e.metroNoInstallDeps?!1:void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:e.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function B(e){if(e)try{await He(e)}catch{}}async function Fr(e){try{await zn({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function Ir(e,t){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:t.daemon?.authToken,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}async function Lr(e,t){if(t.leaseId)try{await Ir(e,t)}catch{}}async function Rr(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function V(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`}function zr(e,n){let r=V(e);if(r)return r;throw new t(`INVALID_ARGS`,`${n} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}function Br(e,t,n,r=[]){return e===`cdp`?Un(r)&&!!t.metroPublicBaseUrl:br.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return br.has(t)&&e.runtime===void 0})}function Vr(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Hr(e,t){return!e.platform||!t||t!==`ios`&&t!==`android`?!0:e.platform===t}function Ur(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Wr(e,t){if(e)return Hr(e,t)?e:void 0}function Gr(e,n,r={}){if(!e.tenant)throw new t(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&_r(r.leaseProvider))throw new t(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:e.session??`default`,remoteConfigPath:n,remoteConfigHash:$n(n),daemon:Yn(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??V(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.target,connectedAt:i,updatedAt:i}}async function Kr(e,t,n,r,i){if(t.leaseId&&t.leaseBackend===n){let i=await $r(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...yr(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function qr(e){if(!xr.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new t(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await Yr(e.client,e.flags),r=Xr(n);return{state:{...e.state,deviceKey:r,leaseBackend:e.state.leaseBackend??e.leaseBackend??Zr(n),platform:e.state.platform??n.platform,target:e.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function Jr(e,t){if(e.platform=t.platform,e.target=t.target??e.target,ge(t)){e.udid=t.id;return}t.platform===`android`&&(e.serial=t.id)}async function Yr(e,t){return await _e((await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist})).map(e=>({...he(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function Xr(e){return`${me(e)}:${e.target??`mobile`}:${e.id}`}function Zr(e){if(ge(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`}function Qr(e,n,r){if(e.leaseBackend&&e.leaseBackend!==r)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:e.session,leaseBackend:e.leaseBackend});if(e.platform&&n.platform&&e.platform!==n.platform)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:e.session,platform:e.platform});if(e.target&&n.target&&e.target!==n.target)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:e.session,target:e.target})}async function $r(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){if(ei(e))return;throw e}}function ei(e){return!(e instanceof t)||e.code!==`UNAUTHORIZED`?!1:e.details?.reason===`LEASE_NOT_FOUND`||e.details?.reason===`LEASE_EXPIRED`||e.details?.reason===`LEASE_REVOKED`}function ti(e){return Ee(e)}async function ni(e,n){let r=await e.text(),i={};if(r.trim().length>0)try{i=JSON.parse(r)}catch(r){throw new t(`COMMAND_FAILED`,n.invalidJsonMessage,{status:e.status},r instanceof Error?r:void 0)}if(!e.ok)throw new t(`UNAUTHORIZED`,n.rejectedMessage,{status:e.status,response:i});return i}const ri=1e3;async function ii(e){return await ai({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:e.command===`connect`&&!e.flags.noLogin,env:e.env})}async function ai(e){let n=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:`none`};if(G(e.flags.daemonAuthToken))return{flags:e.flags,source:`flag`};if(G(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:`env`};if(!bi(e.flags.daemonBaseUrl,n))return{flags:e.flags,source:`none`};let r=await di({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});if(r)return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:`cli-session`};if(!e.allowInteractiveLogin)throw e.flags.noLogin?new t(`UNAUTHORIZED`,`Remote daemon authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`}):yi(e.command,n);let i=await H({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});return{flags:{...e.flags,daemonAuthToken:i.accessToken},source:`login`}}async function oi(e){let n=e.env??e.io?.env??process.env;if(G(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:W(n)};if(G(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:n.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:W(n)};let r=await di({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(e.flags.noLogin)throw new t(`UNAUTHORIZED`,`Cloud connection profile authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`});let i=await H({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io,commandLabel:`agent-device connect`});return{accessToken:i.accessToken,cloudBaseUrl:i.session.cloudBaseUrl}}async function H(e){let n=e.env??e.io?.env??process.env,r=gi(n,e.io);if(r===`non-interactive`)throw yi(e.commandLabel??`agent-device connect`,n);let i=W(n),a=await mi({baseUrl:i,pathName:`/api/control-plane/device-auth/start`,body:{client:`agent-device`,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});hi(a);let o=a.verificationUriComplete??a.verificationUri,s=r===`local-browser`?a.verificationUri:xi(a.verificationUri,a.userCode);r===`local-browser`?(Ci(e.io,`Opening ${a.verificationUri}...\n`),await Si(o,e.io)):Ci(e.io,`Open this URL on your machine:\n${s}\n\nWaiting for approval for 10 minutes...\n`);let c=await pi({cloudBaseUrl:i,deviceCode:a.deviceCode,expiresIn:a.expiresIn,interval:a.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),l=c.cliSession?.refreshCredential??c.cliSession?.refreshToken;if(!G(c.accessToken)||!G(l))throw new t(`UNAUTHORIZED`,`Device authorization did not return CLI credentials.`);let u=new Date(e.io?.now?.()??Date.now()).toISOString(),d={version:1,id:c.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:i,workspaceId:c.cliSession?.workspaceId,accountId:c.cliSession?.accountId,name:c.cliSession?.name,refreshCredential:l,createdAt:u,expiresAt:c.cliSession?.expiresAt};return ci({stateDir:e.stateDir,session:d}),{accessToken:c.accessToken,expiresAt:c.expiresAt,session:d}}function si(e){let t=U(e.stateDir);if(!O.existsSync(t))return null;try{let e=JSON.parse(O.readFileSync(t,`utf8`));return e.version!==1||!G(e.id)||!G(e.cloudBaseUrl)||!G(e.refreshCredential)||!G(e.createdAt)?null:e}catch{return null}}function ci(e){let t=U(e.stateDir);O.mkdirSync(E.dirname(t),{recursive:!0,mode:448}),O.writeFileSync(t,`${JSON.stringify(e.session,null,2)}\n`,{mode:384});try{O.chmodSync(t,384)}catch{}}function li(e){let t=U(e.stateDir);return O.existsSync(t)?(O.rmSync(t,{force:!0}),!0):!1}function U(e){return E.join(e,`auth`,`cli-session.json`)}function ui(e){let t=si({stateDir:e.stateDir});return t?{authenticated:!0,source:`cli-session`,sessionId:t.id,cloudBaseUrl:t.cloudBaseUrl,workspaceId:t.workspaceId,accountId:t.accountId,name:t.name,createdAt:t.createdAt,expiresAt:t.expiresAt,expired:wi(t.expiresAt,e.now)}:{authenticated:!1,source:`none`}}async function di(e){let t=si({stateDir:e.stateDir});return!t||wi(t.expiresAt,e.io?.now)?null:{accessToken:(await fi({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:W(e.env,t.cloudBaseUrl)}}async function fi(e){let n=await mi({baseUrl:W(e.env,e.session.cloudBaseUrl),pathName:`/api/control-plane/cli-session/refresh`,body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(G(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};throw n.status===`revoked`||n.error===`revoked`?new t(`UNAUTHORIZED`,`Stored cloud CLI session was revoked.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error}):new t(`UNAUTHORIZED`,`Failed to refresh CLI session.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error})}async function pi(e){let n=e.now??Date.now,r=Math.min((e.expiresIn??600)*1e3,6e5),i=n()+r,a=Math.max(ri,(e.interval??5e3/1e3)*1e3);for(;n()<i;){let n=await mi({baseUrl:e.cloudBaseUrl,pathName:`/api/control-plane/device-auth/poll`,body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if(n.status===`approved`||G(n.accessToken))return n;if(n.status===`slow_down`||n.error===`slow_down`)a+=ri;else if(n.status!==`authorization_pending`&&n.error!==`authorization_pending`)throw new t(`UNAUTHORIZED`,`Device authorization was not approved.`,{status:n.status,error:n.error});await Ti(a)}throw new t(`TIMEOUT`,`Device authorization expired before approval.`)}async function mi(e){let t=await(e.fetchImpl??fetch)(new URL(e.pathName,e.baseUrl),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await ni(t,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud auth endpoint rejected the request.`})}function hi(e){if(!G(e.deviceCode)||!G(e.userCode)||!G(e.verificationUri))throw new t(`COMMAND_FAILED`,`Cloud auth start returned an unusable response.`)}function gi(e,t){let n=t?.stdinIsTTY??process.stdin.isTTY,r=t?.stdoutIsTTY??process.stdout.isTTY;return _i(e)||!n||!r?`non-interactive`:vi(e)?`device-code`:`local-browser`}function _i(e){return e.CI===`true`||e.GITHUB_ACTIONS===`true`||e.BUILDKITE===`true`}function vi(e){return!!(e.SSH_TTY||e.SSH_CONNECTION||e.CODESPACES===`true`||e.GITPOD_WORKSPACE_ID||e.REMOTE_CONTAINERS===`true`)}function yi(e,n){let r=W(n);return new t(`UNAUTHORIZED`,`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL(`/api-keys`,r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function W(e,n){let r=e.AGENT_DEVICE_CLOUD_BASE_URL??n??`https://cloud.agent-device.dev`;try{return new URL(r).toString().replace(/\/+$/,``)}catch(e){throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_CLOUD_BASE_URL.`,{cloudBaseUrl:r},e instanceof Error?e:void 0)}}function bi(e,t){if(t.AGENT_DEVICE_CLOUD_AUTH===`1`||t.AGENT_DEVICE_CLOUD_AUTH===`true`||G(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return t===`agent-device.dev`||t.endsWith(`.agent-device.dev`)}catch{return!1}}function xi(e,t){let n=new URL(e);return n.searchParams.set(`user_code`,t),n.toString()}async function Si(e,t){if(t?.openBrowser){await t.openBrowser(e);return}let n=process.platform;try{n===`darwin`?await Pe(`open`,[e],{allowFailure:!0,timeoutMs:5e3}):n===`win32`?await Pe(`cmd`,[`/c`,`start`,``,e],{allowFailure:!0,timeoutMs:5e3}):await Pe(`xdg-open`,[e],{allowFailure:!0,timeoutMs:5e3})}catch{Ci(t,`Open this URL on your machine:\n${e}\n`)}}function Ci(e,t){(e?.stderr??process.stderr).write(t)}function wi(e,t){if(!e)return!1;let n=Date.parse(e);return Number.isFinite(n)?n<=(t?.()??Date.now()):!0}function G(e){return typeof e==`string`&&e.trim().length>0}async function Ti(e){await new Promise(t=>setTimeout(t,e))}const Ei=new Set([`daemonAuthToken`,`metroBearerToken`]);function Di(e){let t=ji(ki(e.profile)),n=E.join(e.stateDir,`remote-connections`,`generated`);O.mkdirSync(n,{recursive:!0,mode:448});let r=E.join(n,`${Mi(e.provider)}-${Ai(t)}.json`);O.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{O.chmodSync(r,384)}catch{}return r}function Oi(e){try{return S(e)}catch(n){let i=r(n);throw new t(`COMMAND_FAILED`,`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:i.message},i)}}function K(e){let t=Oi({configPath:Di({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Ni(e.provider)});return{flags:{...I(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function ki(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!Ei.has(e)))}function Ai(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function ji(e){return Array.isArray(e)?e.map(ji):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,ji(t)])):e}function Mi(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Ni(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function Pi(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function Fi(e){let t=await oi({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await Ii({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=Pi(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return K({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function Ii(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return Li(await ni(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function Li(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return Ri(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Ri(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function zi(e){let t=Vi(e.provider)(e),n=Pi(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??V(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...R(e.flags)};return K({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const Bi=[{provider:C.browserStack,buildProfileFields:Hi},{provider:C.awsDeviceFarm,buildProfileFields:Wi}];function Vi(e){let n=Bi.find(t=>t.provider===e)?.buildProfileFields;if(n)return n;throw new t(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Hi(e){return Ki(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),Ki(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:Gi(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:q(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:q(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ui(q(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...yr(e.flags)}}function Ui(e,n){if(e.startsWith(`bs://`)||/^https?:\/\//i.test(e))return e;let r=E.resolve(n,e);try{if(O.statSync(r).isFile())return r}catch{}throw new t(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function Wi(e){let{env:t,flags:n}=e;$e(n,C.awsDeviceFarm);let r=Gi(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=qi(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:qi(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:J(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:J(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??qe(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function Gi(e,n){if(e===`android`||e===`ios`)return e;throw new t(`INVALID_ARGS`,n)}function q(e,n){if(e)return e;throw new t(`INVALID_ARGS`,n)}function Ki(e,n,r){let i=e?.[n];if(i)return i;throw new t(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function qi(e,t,n,r){return q(J(e,t,n),r)}function J(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Ji(e){let n=e.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=Yi({flags:e.flags});return K({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Yi(e){let t=e.flags,n=Xi(t);return{stateDir:b(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...R(t)}}function Xi(e){if(e.platform!==`android`&&e.platform!==`ios`)throw new t(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(e.device!==void 0)throw new t(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=V(e),r=e.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new t(`INVALID_ARGS`,`connect limrun --platform ${e.platform} requires --lease-backend ${r}.`);return r}function Zi(e){let n=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new t(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=Pi(e.stateDir,n,e.flags.session),i={daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??V(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...R(e.flags)};return K({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const Qi={cloud:{resolve:Fi,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Zi,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>zi({provider:`browserstack`,...e}),verify:ta},"aws-device-farm":{resolve:e=>zi({provider:`aws-device-farm`,...e}),verify:na},limrun:{resolve:Ji,verify:ra}};async function $i(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=S({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...I(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...hr(i)?{provider:i}:{}}}let r=e.provider??(ia(e.flags)?`proxy`:`cloud`);return{...await Qi[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function ea(e){let t=e.env??process.env;return e.provider?await Qi[e.provider].verify({flags:e.flags,env:t}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function ta(e){let{flags:t,env:n}=e;return await et.verifyConnection({provider:`browserstack`,username:Y(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:Y(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:aa(t.platform,`BrowserStack`),deviceName:Y(t.device,`BrowserStack profile missed device.`),osVersion:Y(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:Y(t.providerApp,`BrowserStack profile missed app.`)})}async function na(e){let{flags:t}=e;return await et.verifyConnection({provider:`aws-device-farm`,platform:aa(t.platform,`AWS Device Farm`),projectArn:Y(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:Y(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function ra(e){return await We({apiKey:Y(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:Fe(),platform:aa(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function ia(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function Y(e,n){if(e!==void 0)return e;throw new t(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function aa(e,n){if(e===`android`||e===`ios`)return e;throw new t(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function X(e,t){if(e.leaseId)return;let n=vr(e.leaseProvider);return n===`proxy`?{status:`deferred`,nextSteps:da(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`}:n===`direct-device-provider`?{status:`deferred`,nextSteps:da(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`}:{status:`deferred`,nextSteps:[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`],message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+(e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``)}}function oa(e,t){return{...t,preparationMessage:X(e,t)?.message??`No live device session has been created.`,...da(e,t)}}function sa(e){let{state:t,readiness:n,runtimePreparation:r}=e;if(!n){let e=X(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message].filter(e=>!!e).join(`
4
- `)}let i=va(n),a=[`${i===`verified`?`Connected`:`Configured`} successfully with ${n.service}.`,`${i===`verified`?`Verified`:`Status`}: ${n.verificationMessage}`];return n.project&&a.push(`Project: ${n.project.name??n.project.reference} — verified`),n.device&&a.push(la(n.device)),n.app&&a.push(ua(t,n.app)),a.push(n.preparationMessage),a.push(`Next:`),a.push(...n.nextSteps.map(e=>` ${e}`)),a.push(...n.notes??[]),r&&a.push(r.message),a.join(`
5
- `)}function ca(e){let{state:t,runtimePreparation:n,readiness:r}=e,i=X(t,r),a=r?.nextSteps??i?.nextSteps??[];return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:nr(t.daemon?.baseUrl),liveSession:{status:t.leaseId?`created`:`not-created`,...t.leaseId?{leaseId:t.leaseId}:{}},...r?{verification:{status:va(r),service:r.service,message:r.verificationMessage,...r.project?{project:r.project}:{}},...r.device?{device:r.device}:{},...r.app?{app:r.app}:{},nextSteps:a,...r.notes?{notes:r.notes}:{}}:{},metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...i?{leasePreparation:i}:{},...n?{runtimePreparation:n}:{},connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function la(e){let t=`osVersion`in e?e.osVersion:void 0,n=[e.platform,t].filter(Boolean).join(` `),r=n?` (${n})`:``;return e.status===`deferred`?`Device: ${e.name??`Provider-selected device`} — allocated on first device command`:`Device: ${e.name??e.reference??`Configured device`}${r} — verified`}function ua(e,t){return t.status===`missing`?`App: ${xa(e)} — ${t.message??`Install or attach an app before open.`}`:`App: ${t.name??t.reference??`configured app`} — ${t.status===`verified`?`verified`:t.message??`configured`}`}function da(e,t){let n=vr(e.leaseProvider);if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${ba(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:ya()};let r=t?.app?.status===`missing`;return{nextSteps:fa(t)?_a(e):[...ma(t),...ga(e).nextSteps],...pa(t)?{notes:ha(!r)}:{}}}function fa(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function pa(e){return e?.provider===`browserstack`||e?.provider===`aws-device-farm`}function ma(e){return e?.app?.status!==`missing`||!e.project?.reference||!e.device?.reference?[]:[`agent-device connect aws-device-farm --platform ${e.device.platform} --aws-project-arn ${e.project.reference} --aws-device-arn ${e.device.reference} --aws-app-arn <arn> --force`]}function ha(e){return[...e?[`Use the installed package or bundle identifier in open, not the app artifact name.`]:[],`After close, run agent-device artifacts --json for provider video and logs.`]}function ga(e){return{nextSteps:[`agent-device open ${ba(e.platform)} --relaunch`]}}function _a(e){let t=ba(e.platform);return[`agent-device install ${t} <app-path-or-url>`,`agent-device open ${t} --relaunch`]}function va(e){return`status`in e?e.status:`verified`}function ya(){return[`agent-device open <package-or-bundle-id> --relaunch`,`agent-device snapshot -i`,`agent-device close`,`agent-device artifacts --json`]}function ba(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function xa(e){return e.leaseProvider===`aws-device-farm`?`not attached`:e.leaseProvider===`limrun`?`not installed yet`:`not available`}const Sa=async({positionals:e,flags:t,client:n})=>{let r=b(t.stateDir).baseDir,i=Ba(e);Ca(i,t);let a=await $i({provider:i,flags:t,stateDir:r}),o=a.flags,s=Ma(a.remoteConfigPath),c=wa(o,s),l=Ta({stateDir:r,flags:o,remoteConfigPath:a.remoteConfigPath});Ea(l.previous,{flags:o,session:l.session,remoteConfigPath:a.remoteConfigPath,remoteConfigHash:l.remoteConfigHash,desiredLeaseBackend:V(o),connection:s,daemon:l.daemon});let u=await ea({provider:a.provider,flags:o,env:process.env}),d=Da({flags:o,scope:c,connectionMetadata:s,context:l,remoteConfigPath:a.remoteConfigPath});Jn({stateDir:r,state:d}),await ja(n,r,o,l.previous);let f=Ja(o,d),p=oa(d,u);return T(o,ca({state:d,runtimePreparation:f,readiness:p}),()=>sa({state:d,runtimePreparation:f,readiness:p})),!0};function Ca(e,n){if(!(!e||!n.remoteConfig))throw new t(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function wa(e,n){if(!e.tenant)throw new t(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&_r(n?.leaseProvider))throw new t(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:e.tenant,runId:e.runId}}function Ta(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session?null:F({stateDir:t}),a=n.session??i?.session??Fa(t);return{session:a,previous:i?.session===a?i:N({stateDir:t,session:a}),remoteConfigHash:$n(r),daemon:qa(n)}}function Ea(e,n){if(!(!e||Ua(e,n))&&!n.flags.force)throw new t(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:n.session,remoteConfig:e.remoteConfigPath})}function Da(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=Aa(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=Oa(t,o,r),l=ka(t,o,s);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function Oa(e,t,n){return{leaseId:t?.leaseId,leaseBackend:t?.leaseBackend??V(e),leaseProvider:n?.leaseProvider??t?.leaseProvider,clientId:n?.clientId??t?.clientId,deviceKey:t?.deviceKey??n?.deviceKey}}function ka(e,t,n){return{platform:e.platform??t?.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function Aa(e,t){return!!(t&&!e.force)}async function ja(e,t,n,r){!r||!n.force||(await B(r.metro),await Fr({stateDir:t,state:r}),await Lr(e,r))}function Ma(e){let t=S({configPath:e,cwd:process.cwd(),env:process.env}).profile,n={leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey};return Object.values(n).some(e=>e!==void 0)?n:void 0}const Na=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=Va(e);if(!i)return Ha(e,n),!0;let a=i.session,o;if(i.leaseId||i.runtime||i.metro)try{o=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await B(i.metro),await Fr({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let e=await Ir(t,i);s=e.released,o??=e.provider}catch{}return Xn({stateDir:r,session:a}),T(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>Ia(a,o)),!0},Pa=async({positionals:e,flags:n})=>{if(e[0]!==`status`)throw new t(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=Va(n);if(!i)return Ha(n,r),!0;let a=X(i),o=Ya(i);return T(n,ca({state:i,runtimePreparation:o}),()=>[`Configured remote session "${i.session}".`,`tenant=${i.tenant} runId=${i.runId} leaseId=${i.leaseId??`pending`} backend=${i.leaseBackend??`pending`}`,`remoteConfig=${i.remoteConfigPath}`,i.runtime?`metro=prepared`:`metro=not-prepared`,a?.message,o?.message].filter(e=>!!e).join(`
6
- `)),!0};function Fa(e){for(let t=0;t<8;t+=1){let t=`adc-${D.randomBytes(3).toString(`hex`)}`;if(!N({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${D.randomBytes(2).toString(`hex`)}`}function Ia(e,t){return[`Disconnected remote session "${e}".`,...La(t),...za(t?.cloudArtifacts?.cloudArtifacts)].join(`
7
- `)}function La(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=Ra(e);return t?[t]:[]})}function Ra(e){if(!e||typeof e!=`object`)return;let t=e;if(!(typeof t.message!=`string`||t.message.length===0))return`Provider release warning${typeof t.code==`string`&&t.code.length>0?` (${t.code})`:``}: ${t.message}`}function za(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function Ba(e){let n=e[0];if(n!==void 0){if(e.length>1)throw new t(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(hr(n))return n;throw new t(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${gr()}.`)}}function Va(e){let t=e.session??`default`,n=b(e.stateDir).baseDir;return{session:t,stateDir:n,state:N({stateDir:n,session:t})??(e.session?null:F({stateDir:n}))}}function Ha(e,t){T(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function Ua(e,t){return Wa(e,t)&&Ga(e,t)&&Ka(e.daemon,t.daemon)}function Wa(e,t){return[[e.remoteConfigPath,t.remoteConfigPath],[e.remoteConfigHash,t.remoteConfigHash],[e.session,t.session],[e.tenant,t.flags.tenant],[e.runId,t.flags.runId]].every(([e,t])=>e===t)}function Ga(e,t){return[[e.leaseBackend,t.desiredLeaseBackend],[e.platform,t.flags.platform],[e.target,t.flags.target],[e.leaseProvider,t.connection?.leaseProvider],[e.clientId,t.connection?.clientId]].every(([e,t])=>t===void 0||e===t)}function Ka(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function qa(e){return Yn(e)}function Ja(e,t){if(!t.runtime&&!(!Vr(e)&&!Za(t.remoteConfigPath)))return Xa(t.remoteConfigPath)}function Ya(e){if(!(e.runtime||!Za(e.remoteConfigPath)))return Xa(e.remoteConfigPath)}function Xa(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function Za(e){try{let t=S({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}const Qa=async({positionals:e,flags:n})=>{let r=e[0]??`status`,i=b(n.stateDir).baseDir;if(r===`status`){let e=ui({stateDir:i});return T(n,e,()=>$a(e)),!0}if(r===`login`){let e=await H({stateDir:i,flags:n,commandLabel:`agent-device auth login`});return T(n,{authenticated:!0,source:`cli-session`,sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>`Authenticated with cloud CLI session.`),!0}if(r===`logout`){let e=li({stateDir:i});return T(n,{authenticated:!1,removed:e},()=>e?`Removed stored cloud CLI session.`:`No stored cloud CLI session.`),!0}throw new t(`INVALID_ARGS`,`auth accepts only: status, login, logout`)};function $a(e){return e.authenticated?[`Authenticated with cloud CLI session.`,`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?`status=expired`:null].filter(e=>!!e).join(`
8
- `):`Not authenticated.`}async function eo(e){let n=ro(e.paths.infoPath);if(!n)return Z();if(!n.processStartTime){if(!Le(n.pid))return Z();throw new t(`COMMAND_FAILED`,`Refusing to stop a daemon without a verified process start-time identity.`,{pid:n.pid})}if(!re(n.pid,n.processStartTime)){if(!Le(n.pid))return Z();throw new t(`COMMAND_FAILED`,`Refusing to stop a daemon whose PID or start-time identity could not be verified.`,{pid:n.pid,processStartTime:n.processStartTime})}if(!to(n.pid,`SIGTERM`))return Z();if(await Re(n.pid,e.graceTimeoutMs??1e4))return await ao(e.paths,1e3),{stopped:!0,mode:`graceful`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]};if(re(n.pid,n.processStartTime)&&to(n.pid,`SIGKILL`),!await Re(n.pid,e.killTimeoutMs??2e3))throw new t(`COMMAND_FAILED`,`Daemon did not exit after SIGKILL.`,{pid:n.pid});return{stopped:!0,mode:`forced`,cleanupConfidence:`unknown`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`unknown`,released:[],pending:null},warnings:[`The daemon was force-killed before provider lease state could be finalized. Provider allocations may remain active.`]}}function to(e,n){if(se(e,n))return!0;if(!Le(e))return!1;throw new t(`COMMAND_FAILED`,`Daemon could not be signaled with ${n}.`,{pid:e,signal:n})}function no(e){let t=ro(e);return t?.processStartTime?{pid:t.pid,processStartTime:t.processStartTime}:null}function ro(e){try{let t=JSON.parse(O.readFileSync(e,`utf8`)),n=t.pid;return typeof n!=`number`||!Number.isInteger(n)||n<=0?null:{pid:n,...io(t.processStartTime)?{processStartTime:t.processStartTime}:{}}}catch{return null}}function io(e){return typeof e==`string`&&e.trim().length>0}async function ao(e,t){let n=Date.now();for(;Date.now()-n<t;){if(!O.existsSync(e.infoPath)&&!O.existsSync(e.lockPath))return;await Ie(25)}}function Z(){return{stopped:!1,mode:`not-running`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]}}const oo=async({positionals:e,flags:n})=>{if(e[0]!==`stop`||e.length!==1)throw new t(`INVALID_ARGS`,`daemon accepts only: stop`);let r=b(n.stateDir),i=no(r.infoPath),a=await eo({paths:r}),o=so(a,a.mode===`graceful`?Ze(r.baseDir):null),s=n.clean===!0&&i!==null&&o.stopped;if(s){let[{cleanupRunnerLeasesForOwner:e},{runnerLeaseCleanupAdapter:t}]=await Promise.all([import(`./runner-lease.js`).then(e=>e.c),import(`./runner-disposal.js`).then(e=>e.s)]);await e({pid:i.pid,startTime:i.processStartTime},t)}let c={...o,clean:s};return T(n,c,()=>co(c)),!0};function so(e,t){return e.mode!==`graceful`||t?t?{...e,providerReleases:{status:`completed`,...t.providerReleases}}:e:{...e,cleanupConfidence:`unknown`,providerReleases:{status:`unknown`,released:[],pending:null},warnings:[...e.warnings,`The graceful shutdown report is unavailable, so provider cleanup state is unknown. Provider allocations may remain active.`]}}function co(e){return[e.stopped?`Daemon stopped (${e.mode}).`:`No running daemon found.`,e.clean?`Retained runner cleanup completed.`:null,...e.warnings].filter(e=>!!e).join(`
9
- `)}const lo=async({positionals:e,flags:n})=>{if(e[0]!==`status`||e.length!==1)throw new t(`INVALID_ARGS`,`device accepts only: status`);let r=Xe({platform:n.platform,device:n.device,udid:n.udid,serial:n.serial}),i=r.filter(uo),a=(n.stale?i:r.filter(e=>!uo(e))).map(fo);return T(n,{claims:a,...n.stale?{}:{hiddenStaleClaims:i.length}},()=>po(a,{staleOnly:n.stale===!0,hiddenStaleClaims:i.length,staleCommand:_o(n)})),!0};function uo(e){return e.classification===`owner-process-dead`||e.classification===`owner-state-dir-gone`}function fo(e){let t=e.claim;return{...e.deviceKey?{deviceKey:e.deviceKey}:{},...t?{}:{fileName:e.fileName},classification:e.classification,...t?{device:t.device,owner:{session:t.session,workspace:t.workspace,stateDir:t.stateDir,pid:t.ownerPid,startTime:t.ownerStartTime}}:{},...e.error?{error:e.error}:{}}}function po(e,t){let n=e.map(mo);if(n.length===0){if(t.staleOnly)return`No stale local advisory device claims found.`;if(t.hiddenStaleClaims===0)return`No local advisory device claims found.`}return[...n.length===0?[`No live local advisory device claims found.`]:n,!t.staleOnly&&t.hiddenStaleClaims>0?`${t.hiddenStaleClaims} stale ${t.hiddenStaleClaims===1?`claim`:`claims`} hidden; inspect with: ${t.staleCommand}`:null].filter(e=>!!e).join(`
10
- `)}function mo(e){return`${ho(e)}: ${e.classification}${go(e.owner)}`}function ho(e){let t=e.device;return t?`${t.platform??`unknown`} ${t.name??t.id??`claim`}`:String(e.deviceKey??e.fileName??`claim`)}function go(e){if(!e||typeof e!=`object`)return``;let t=e;return` session=${t.session} workspace=${t.workspace}`}function _o(e){return[`agent-device device status`,...[e.platform?`--platform ${y(e.platform)}`:null,e.device?`--device ${y(e.device)}`:null,e.udid?`--udid ${y(e.udid)}`:null,e.serial?`--serial ${y(e.serial)}`:null].filter(e=>!!e),`--stale`].join(` `)}const vo=`${ce}/`,yo=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,oe],bo=[`content-type`,`content-disposition`,`x-request-id`];function xo(e){let t=No(e);return dt.createServer((e,n)=>{So(e,n,t).catch(e=>{Xo(n,e)})})}async function So(e,t,n){let r=Io(e.url??`/`);if(e.method===`GET`&&r===`/health`){await Co(t,n);return}if(!Lo(r,e.method)){t.statusCode=404,t.end(`Not found`);return}let i;if(r===`/rpc`&&(i=(await ue(e,n.maxRpcBodyBytes,`Proxy request body is too large.`)).toString(`utf8`)),!Uo(e,n.clientToken,i)){Yo(t,r,qo(i));return}await To({req:e,res:t,route:r,options:n,rpcBody:i})}async function Co(e,t){let n=await wo(t);e.statusCode=200,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify(le(`agent-device-proxy`,{upstream:n})))}async function wo(e){let t=new URL(fe(e.upstreamBaseUrl,`health`)),n=await e.fetchImpl(t,{method:`GET`,headers:Vo({headers:{}},e.upstreamToken,`/health`),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function To(e){let{req:t,res:n,route:r,options:i,rpcBody:a}=e,o=Bo(i.upstreamBaseUrl,r,t.url??`/`),s=t.method??`GET`,c=Vo(t,i.upstreamToken,r),l=Ho(t,r,a,i.upstreamToken);await Eo({req:t,res:n,route:r,response:await i.fetchImpl(o,{method:s,headers:c,signal:AbortSignal.timeout(i.upstreamTimeoutMs),...l?{body:l,duplex:`half`}:{}}),clientToken:i.clientToken})}async function Eo(e){let{req:t,res:n,route:r,response:i,clientToken:a}=e;if(n.statusCode=i.status,Do(i,n),Oo(t,n),zo(r)){await ko({req:t,res:n,response:i,clientToken:a});return}await Mo(i,n)}function Do(e,t){for(let n of bo){let r=e.headers.get(n);r&&t.setHeader(n,r)}}function Oo(e,t){t.hasHeader(`x-request-id`)||t.setHeader(`x-request-id`,Jo(e))}async function ko(e){let{req:t,res:n,response:r,clientToken:i}=e,a=await r.text();n.setHeader(`content-type`,r.headers.get(`content-type`)??`application/json`),n.end(Ao(a,t,i))}function Ao(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let i=r;if(!i.upload||typeof i.upload.url!=`string`)return e;let a=jo(i.upload.url,t);if(!a)return e;let o=i.upload.headers&&typeof i.upload.headers==`object`?{...i.upload.headers}:{};return Object.assign(o,ae(n)),JSON.stringify({...r,upload:{...i.upload,url:a,headers:o}})}function jo(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=typeof t.headers.host==`string`?t.headers.host:``;if(!r)return null;let i=new URL(t.url??`/`,`http://127.0.0.1`).pathname,a=i.lastIndexOf(`/upload/preflight`),o=a>=0?i.slice(0,a):``,s=t.headers[`x-forwarded-proto`],c=Array.isArray(s)?s[0]:s,l=new URL(`${c||`http`}://${r}`);return l.pathname=`${o}${n.pathname}`,l.search=n.search,l.toString()}async function Mo(e,t){if(!e.body){t.end();return}await ft(pt.fromWeb(e.body),t)}function No(e){return{upstreamBaseUrl:Po(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:Fo(e.upstreamToken,`upstreamToken`),clientToken:Fo(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,fetchImpl:e.fetchImpl??fetch}}function Po(e,n){try{let t=new URL(e);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`unsupported protocol`);return t.toString().replace(/\/+$/,``)}catch(r){throw new t(`INVALID_ARGS`,`Invalid ${n}`,{[n]:e},r)}}function Fo(e,n){let r=e.trim();if(!r)throw new t(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function Io(e){let t=new URL(e,`http://127.0.0.1`).pathname;return t===`/agent-device`?`/`:t.startsWith(vo)?`/${t.slice(vo.length)}`:t}function Lo(e,t){return e===`/rpc`?t===`POST`:Ro(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)?t===`GET`:!1}function Ro(e,t){return e===`/upload`||zo(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function zo(e){return e===`/upload/preflight`}function Bo(e,t,n){let r=new URL(fe(e,t)),i=n.indexOf(`?`);return i>=0&&(r.search=n.slice(i)),r}function Vo(e,t,n){let r=new Headers;for(let t of yo){let n=e.headers[t];typeof n==`string`&&n.trim()&&r.set(t,n)}n===`/rpc`&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);for(let[e,n]of Object.entries(ae(t)))r.set(e,n);return r}function Ho(e,t,n,r){if(!(e.method===`GET`||e.method===`HEAD`))return t===`/rpc`?Go(n??``,r):e}function Uo(e,t,n){let r=Wo(e,n);return r.length>0&&Qe(r,t)}function Wo(e,t){let n=typeof e.headers.authorization==`string`?e.headers.authorization:``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers[`x-agent-device-token`];if(typeof r==`string`)return r;if(t){let e=Ko(t);if(e)return e}return``}function Go(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function Ko(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function qo(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function Jo(e){let t=e.headers[`x-request-id`];return typeof t==`string`&&t.trim()?t.trim().slice(0,128):ut()}function Yo(n,r,i){if(n.statusCode=401,n.setHeader(`content-type`,`application/json`),r===`/rpc`){n.end(JSON.stringify({jsonrpc:`2.0`,id:i,error:{code:-32001,message:`Invalid proxy token`,data:e(new t(`UNAUTHORIZED`,`Invalid proxy token`))}}));return}n.end(JSON.stringify({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`}))}function Xo(t,n){if(t.headersSent){t.destroy(n instanceof Error?n:void 0);return}let r=e(n);t.statusCode=r.code===`INVALID_ARGS`?400:500,t.setHeader(`content-type`,`application/json`),t.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}const Zo=async({positionals:e,flags:n})=>{if(e.length>0)throw new t(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await Qo(n);return T(n,r,()=>rs(r)),await is(),!0};async function Qo(e){let n=ve({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:e.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await ye(n),i=$o(r.info.httpPort),a=es(e),o=xo({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:a});await ts(o,e.proxyHost?.trim()||`127.0.0.1`,e.proxyPort??0);let s=o.address();if(!s||typeof s==`string`)throw new t(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let c=`http://${ns(s.address)}:${s.port}`;return{proxyBaseUrl:c,agentDeviceBaseUrl:ie(c),token:a,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function $o(e){if(!e)throw new t(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${e}`}function es(e){return e.daemonAuthToken?.trim()||lt(32).toString(`hex`)}function ts(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function ns(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function rs(e,t={}){let n=t.useColor??u(),r=Q(`✓`,`green`,n),i=Q(e.proxyBaseUrl,`cyan`,n),a=Q(`<tunnel URL>`,`cyan`,n),o=Q(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
11
- `)}function Q(e,t,n){return n?l(e,t,{validateStream:!1}):e}function is(){return new Promise(()=>{})}const as=async e=>{let{positionals:t}=e;return t[0]===`export`?await ss(e):os(e)};function os({positionals:e,flags:n}){if(e.length>1)throw new t(`INVALID_ARGS`,`replay accepts exactly one input path: replay <path>`);if(n.out!==void 0)throw new t(`INVALID_ARGS`,`replay --out is only supported with replay export.`);return!1}async function ss({positionals:e,flags:n}){cs(e,n);let r=e[1];if(!r)throw new t(`INVALID_ARGS`,`replay export requires an input path.`);let i=x(r),a=O.readFileSync(i,`utf8`),o=ne(a),s=bt(o.actions,{actionLines:o.actionLines,metadata:pe(a),parseSelector:ee}),c=typeof n.out==`string`?x(n.out):void 0;c&&(O.mkdirSync(E.dirname(c),{recursive:!0}),O.writeFileSync(c,s.yaml));for(let e of s.warnings)process.stderr.write(`Warning: line ${e.line}: ${e.message}\n`);return T(n,{format:`maestro`,sourcePath:i,...c?{path:c}:{yaml:s.yaml},warnings:s.warnings},()=>c??s.yaml),!0}function cs(e,n){if(e.length>2)throw new t(`INVALID_ARGS`,`replay export accepts exactly one input path: replay export <file.ad>`);if(n.replayUpdate)throw new t(`INVALID_ARGS`,`replay export does not support --update.`);if(n.replayMaestro)throw new t(`INVALID_ARGS`,`replay export reads .ad files; omit --maestro.`);if(n.replayEnv?.length)throw new t(`INVALID_ARGS`,`replay export does not evaluate --env substitutions.`)}const ls=async({positionals:e,flags:t,client:r})=>{let i=await ct({client:r,command:`screenshot`,positionals:e,flags:t});return n(t.responseLevel)?(T(t,i,()=>JSON.stringify(i,null,2)),!0):(T(t,de(i),()=>i.overlayRefs?`Annotated ${i.overlayRefs.length} refs onto ${i.path}`:fs(i)),!0)},us=async({positionals:e,flags:n,client:r})=>{if(e[0]===`snapshot`){let t=await ct({client:r,command:`diff`,positionals:e,flags:n});return T(n,t,()=>g(t)),!0}if(e[0]!==`screenshot`)return!1;let i=n.baseline;if(!i||typeof i!=`string`)throw new t(`INVALID_ARGS`,`diff screenshot requires --baseline <path>`);let a=x(i),o=typeof n.out==`string`?x(n.out):void 0,s=e[1];if(e.length>2)throw new t(`INVALID_ARGS`,`diff screenshot accepts at most one current screenshot path`);let[{createAgentDevice:c,localCommandPolicy:l},{createLocalArtifactAdapter:u}]=await Promise.all([import(`./runtime.js`).then(e=>e.r),import(`./sdk-io.js`).then(e=>e.n)]),d=await c({backend:ds(r,n),artifacts:u(),sessions:{get:e=>({name:e}),set:()=>{}},policy:l()}).capture.diffScreenshot({session:n.session,baseline:{kind:`path`,path:a},current:s?{kind:`path`,path:x(s)}:{kind:`live`},...o?{out:{kind:`path`,path:o}}:{},threshold:ms(n.threshold),overlayRefs:n.overlayRefs,normalizeStatusBar:n.screenshotNormalizeStatusBar,surface:n.surface});return T(n,d,()=>m(d)),!0};function ds(e,t){return{platform:ps(t),captureScreenshot:async(t,n,r)=>de(await e.capture.screenshot({path:n,session:t.session,overlayRefs:r?.overlayRefs,pixelDensity:r?.pixelDensity,fullscreen:r?.fullscreen,normalizeStatusBar:r?.normalizeStatusBar,stabilize:r?.stabilize,surface:r?.surface}))}}function fs(e){if(typeof e.width!=`number`||typeof e.height!=`number`)return e.path;let t=typeof e.pixelDensity==`number`?` @${e.pixelDensity}x`:``;return`${e.path} (${e.width}x${e.height}${t})`}function ps(e){switch(e.platform){case`android`:case`linux`:case`macos`:return e.platform;default:return`ios`}}function ms(e){if(!(e==null||e===``))return Number(e)}const hs={connect:Sa,disconnect:Na,connection:Pa,auth:Qa,daemon:oo,device:lo,proxy:Zo,replay:as,screenshot:ls,diff:us};async function gs(e){let t={...e.flags},n=hs[e.command];return n&&await n({...e,flags:t})?!0:ti(e.command)?await _s({...e,command:e.command,flags:t}):!1}async function _s(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function vs(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function ys(e){return e===`ios-instance`}function bs(e){return e[0]===`wait`&&e.includes(`--connected`)}function xs(e,t,n){n===0||!bs(e)||!ys(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.",``].join(`
12
- `))}function $(e,t,n){return n||(e.push(t),``)}function Ss(e){if(!e?.metroProxyBaseUrl||!Bn(e.leaseBackend))return null;let n=[],r={serverBaseUrl:$(n,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:$(n,`metroBearerToken`,e.metroBearerToken),tenantId:$(n,`tenant`,e.tenant),runId:$(n,`runId`,e.runId),leaseId:$(n,`leaseId`,e.leaseId)};if(n.length>0)throw new t(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function Cs(e,t,n){let{flags:r}=t,i=Ss(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await zn({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await Rn({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function ws(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?n.leaseProvider===`limrun`&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function Ts(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await Cs(e,t,async()=>(ws(e,t)&&await t.configureDirectPortReverse?.(),(await Me(`npm`,vs(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return xs(e,t.flags,i),i}async function Es(e,n){switch(e[0]){case`setup`:{Ds(n.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Os(n.flags.json,t),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return ks(n.flags.json,t.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,t),t.exitCode}default:throw new t(`INVALID_ARGS`,`web requires setup or doctor`)}}function Ds(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
13
- `)}function Os(e,t){if(e){_({success:!0,data:{status:As(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function ks(e,t,n){if(e){_({success:!0,data:js(n)});return}process.stdout.write(`${t}\n`)}function As(e){let{socketDir:t,...n}=e;return n}function js(e){let t=e.status;return Ms(t)?{...e,status:As(t)}:e}function Ms(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function Ns(e){let n;try{n=JSON.parse(e)}catch{throw new t(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new t(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return Ps(n)}function Ps(e){let t=!1,n=e.map((e,n)=>{if(Is(e))return Ls(e,n+1);let r=Rs(e,n+1);return t=!0,Fs(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
14
- `),n}function Fs(e){let t=st(e.command,e.positionals??[],Us(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function Is(e){return v(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function Ls(e,t){let n=te(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function Rs(e,n){if(!v(e))throw new t(`INVALID_ARGS`,`Invalid batch step ${n}.`);Bs(e,n);let r=zs(e.command,n),i=Vs(e.positionals,n);nt(r,i??[],`Batch step ${n}`);let a=Hs(e.flags,n),o=te(e.runtime,n);return{command:r,...i===void 0?{}:{positionals:i},...a===void 0?{}:{flags:a},...o===void 0?{}:{runtime:o}}}function zs(e,n){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new t(`INVALID_ARGS`,`Batch step ${n} requires command.`);if(Ee(r))return r;throw new t(`INVALID_ARGS`,`Batch step ${n} command is not available through command batch: ${String(e)}`)}function Bs(e,n){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new t(`INVALID_ARGS`,`Batch step ${n} has unknown legacy field(s): ${r.join(`, `)}.`)}function Vs(e,n){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new t(`INVALID_ARGS`,`Batch step ${n} positionals must contain only strings.`);return e}}function Hs(e,n){if(e!==void 0){if(!v(e))throw new t(`INVALID_ARGS`,`Batch step ${n} flags must be an object.`);return e}}function Us(e){return{json:!1,help:!1,version:!1,...e}}function Ws(e,t={}){let n=Gs(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function Gs(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??qs(t.AGENT_DEVICE_PLATFORM),r=Ys(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:Ks(e.policyOverrides,t,r)}}function Ks(e,t,n){let r=e?.sessionLock??Js(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function qs(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function Js(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new t(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function Ys(e){return typeof e==`string`&&e.trim().length>0}function Xs(e,t){let n=_n(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=Zs(n.command)?mr({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=at(ot({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Cn(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function Zs(e){return e!==null}const Qs={sendToDaemon:xe},$s=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),ec=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`]);async function tc(e,t=Qs){let n=De(),r=Fe(),i=pc(e),a=e.includes(`--json`);await Oe({session:kc(e)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await rc(e,{version:r,jsonRequested:a,debugEnabled:i}),l=gc(s,o.providedFlags),u=ic(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});nc(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){process.exit(await ac(u,t));return}if(s===`web`){process.exit(await Es(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(it({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await oc(u,t),nc(u.effectiveFlags),s===`cdp`){process.exit(await qn(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=cc(u);let e=await lc(u);await uc(u,be(sc(u),{transport:Ec({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,transport:t.sendToDaemon})}),e)}catch(e){dc(e,u,d)}finally{d&&d()}})}function nc(e){e.daemonAuthToken&&je(e.daemonAuthToken)}async function rc(n,r){let i;try{i=Xs(n,{cwd:process.cwd(),env:process.env})}catch(t){Ne({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});r.jsonRequested?_({success:!1,error:n}):p(n,{showDetails:r.debugEnabled}),process.exit(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);i.flags.version&&(process.stdout.write(`${r.version}\n`),process.exit(0));let a=i.command===`help`,o=i.flags.help;if(a||o){a&&i.positionals.length>1&&(p(new t(`INVALID_ARGS`,`help accepts at most one command.`)),process.exit(1));let e=a?i.positionals[0]:i.command;e||(process.stdout.write(`${await Pn()}\n`),process.exit(0));let n=await Fn(e);n&&(process.stdout.write(n),process.exit(0)),p(new t(`INVALID_ARGS`,mc(e))),process.stdout.write(`${await Pn()}\n`),process.exit(1)}return i.command||(process.stdout.write(`${await Pn()}\n`),process.exit(1)),{parsed:i,command:i.command,positionals:i.positionals}}function ic(t,n){let i=new Set(t.providedFlags.map(e=>e.key));try{let e=Gs({policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),r=e.lockPolicy?{...t.flags}:Ws(t.flags,{policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),a=b(r.stateDir),o=r.session??`default`,s=yc({command:n.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?wc(r,s.flags,i):r;return{...n,binding:e,flags:r,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(r(i),{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});t.flags.json?_({success:!1,error:a}):p(a,{showDetails:n.debugOutputEnabled}),process.exit(1)}}async function ac(e,t){let{daemonAuthToken:n,...r}=e.effectiveFlags;return await Ts(e.positionals,{flags:{...r,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await t.sendToDaemon({command:o.runtime,positionals:[`port-reverse`],flags:{...r,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},{authToken:n});a.ok||i(a.error)}})}async function oc(e,n){if(e.command===`batch`){if(e.positionals.length>0)throw new t(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=_c(e.flags)}if(xc(e.command)&&(e.effectiveFlags=(await ii({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&bc(e.command)){let t=be(sc(e),{transport:Dc(n.sendToDaemon)}),r=await Sr({command:e.command,flags:e.effectiveFlags,client:t,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Tc(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Sc({command:e.command,flags:e.effectiveFlags,runtime:e.resolvedRuntime,explicitFlagKeys:e.explicitFlagKeys,hadConnectionDefaults:!!e.connectionDefaults})&&process.stderr.write(`Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.
15
- `)}function sc(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function cc(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Ac(e.daemonPaths.logPath):null}async function lc(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function uc(e,n,r){let{command:i,positionals:a,effectiveFlags:o}=e;if(i===`batch`){if(!e.parsedBatchSteps)throw new t(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let s=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:Ws(t.input,{policyOverrides:o,configuredPlatform:o.platform,configuredSession:o.session,inheritedPlatform:o.platform})}));if(await gs({command:i,positionals:a,flags:{...o,batchSteps:s},client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return}else if(i===`runtime`)throw new t(`INVALID_ARGS`,`runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.`);else if(await gs({command:i,positionals:a,flags:o,client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return;throw new t(`INVALID_ARGS`,hc(i))}function dc(t,n,i){let a=r(t),o=e(a,{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});if(n.command===`close`&&vc(a)){n.effectiveFlags.json&&_({success:!0,data:{closed:`session`,source:`no-daemon`}});return}n.effectiveFlags.json?_({success:!1,error:o}):(p(o,{showDetails:n.debugOutputEnabled}),n.debugOutputEnabled&&fc(n.daemonPaths.logPath)),i&&i(),process.exit(1)}function fc(e){try{if(O.existsSync(e)){let t=O.readFileSync(e,`utf8`).split(`
1
+ import{S as e,_ as t,v as n,w as r}from"./sdk-contracts.js";import{Tt as i,n as a}from"./version.js";import{Wn as o,f as s}from"./sdk-batch-runner.js";import{Qt as c,Yt as l,Zt as u,vt as d,yt as f}from"./prepare-kind.js";import{n as p,r as m}from"./agent-device-client.js";import{_ as h}from"./screenshot-result.js";import{S as g,x as _}from"./registry.js";import{n as v}from"./command-metadata.js";import{A as y,I as ee,M as b,N as te,j as x,k as ne,x as re}from"./sdk-android-adb.js";import{n as ie,t as ae}from"./internal/bin.js";import{i as S,n as C,t as oe}from"./command-schema.js";import{t as se}from"./update-check.js";import{n as w,r as T,t as ce}from"./cli-config.js";import{exitAfterFlush as E}from"./process-exit.js";import{D as le,E as ue,S as de,T as fe,h as pe,n as me,w as he}from"./connection-runtime.js";import{t as ge}from"./cli-grammar.js";import{i as _e}from"./auth-session.js";import D from"node:fs";import{pathToFileURL as ve}from"node:url";const O=`open <app> --relaunch`,ye={start:{command:`open`,example:O},restart:{command:`open`,example:O},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function k(e){if(e.length<=2)return[];let t=c(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=A(e),i=t.map(t=>({name:t,distance:j(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function A(e){return e.length<4?1:e.length<=6?2:3}function j(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):M(e,t)}function M(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function N(e){let t=e.toLowerCase(),n=ye[t]?.example;if(n)return n;let r=k(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const P=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),be=new Set([`--session-locked`,`--session-lock-conflicts`]);function xe(e){return P.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:be.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===i.cliToken?`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`:`Unknown flag: ${e}`}function F(e){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=B(l));continue}if(Te(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=B(l));continue}let[f,p]=u?I(l):[l,void 0];if(Ce(r,f))continue;let m=Ee(f,r);if(we(r,m)){a.push(l);continue}if(!m){if(je(r,a,l)){r?a.push(l):r=l;continue}throw new t(`INVALID_ARGS`,xe(f))}let h=ke(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return Se(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Se(e,t){if(e)for(let n of ae(e)?.impliedFlags??[])t[n]=!0}function Ce(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function we(e,t){return e===`react-devtools`?t?!w(t.key,e):!0:!1}function Te(e){return e===`cdp`}function Ee(e,t){let n=g().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??_(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return _(e)}function De(e,n){let r=n?.strictFlags??!0,i=[...e.warnings],a=T({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(T(a,e.flags),e.command&&!u(e.command)&&!a.help){let n=N(e.command);throw new t(`INVALID_ARGS`,n?`Unknown command: ${e.command}. Did you mean ${n}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!w(t.key,e.command));if(o.length>0){let n=o.map(e=>e.token),s=Pe(e.command,n);if(r)throw new t(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(w(t,e.command)||delete a[t]);Oe(e),oe(e.command,a);let s=Ne({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(C(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new t(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Oe(e){if(e.command!==`back`)return;let n=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new t(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function I(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function ke(e,n,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new t(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||R(i)?{value:!0,consumeNext:!1}:Ae(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&R(a))throw new t(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new t(`INVALID_ARGS`,`Invalid ${L(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new t(`INVALID_ARGS`,`Invalid ${L(n)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function L(e){return e.replace(/^-+/,``)}function R(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?I(e):[e,void 0];return _(t)!==void 0}function Ae(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function je(e,t,n){if(!Me(n)||!e)return!1;let r=S(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function Me(e){return/^-\d+(\.\d+)?$/.test(e)}function Ne(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function Pe(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function z(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function Fe(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(B(e))}function B(e){if(e.toLowerCase()===`rotate`)throw new t(`INVALID_ARGS`,`rotate was renamed to orientation; for the two-finger gesture use: gesture rotate`);return ie(e)}function Ie(e){return v(e)}const Le={connect:async()=>(await import(`./connection.js`)).connectCommand,disconnect:async()=>(await import(`./connection.js`)).disconnectCommand,connection:async()=>(await import(`./connection.js`)).connectionCommand,auth:async()=>(await import(`./auth.js`)).authCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device2.js`)).deviceCommand,proxy:async()=>(await import(`./proxy.js`)).proxyCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot.js`)).diffCommand};async function V(e){let t={...e.flags},n=Le[e.command];return n&&await(await n())({...e,flags:t})?!0:Ie(e.command)?await Re({...e,command:e.command,flags:t}):!1}async function Re(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function ze(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function Be(e){return e===`ios-instance`}function Ve(e){return e[0]===`wait`&&e.includes(`--connected`)}function He(e,t,n){n===0||!Ve(e)||!Be(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.",``].join(`
2
+ `))}function H(e,t,n){return n||(e.push(t),``)}function Ue(e){if(!e?.metroProxyBaseUrl||!fe(e.leaseBackend))return null;let n=[],r={serverBaseUrl:H(n,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:H(n,`metroBearerToken`,e.metroBearerToken),tenantId:H(n,`tenant`,e.tenant),runId:H(n,`runId`,e.runId),leaseId:H(n,`leaseId`,e.leaseId)};if(n.length>0)throw new t(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function We(e,t,n){let{flags:r}=t,i=Ue(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await le({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await ue({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function Ge(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?n.leaseProvider===`limrun`&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function Ke(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await We(e,t,async()=>(Ge(e,t)&&await t.configureDirectPortReverse?.(),(await re(`npm`,ze(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return He(e,t.flags,i),i}async function qe(e,n){switch(e[0]){case`setup`:{Je(n.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Ye(n.flags.json,t),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Xe(n.flags.json,t.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,t),t.exitCode}default:throw new t(`INVALID_ARGS`,`web requires setup or doctor`)}}function Je(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
3
+ `)}function Ye(e,t){if(e){f({success:!0,data:{status:U(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function Xe(e,t,n){if(e){f({success:!0,data:Ze(n)});return}process.stdout.write(`${t}\n`)}function U(e){let{socketDir:t,...n}=e;return n}function Ze(e){let t=e.status;return Qe(t)?{...e,status:U(t)}:e}function Qe(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function $e(e){let n;try{n=JSON.parse(e)}catch{throw new t(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new t(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return et(n)}function et(e){let t=!1,n=e.map((e,n)=>{if(nt(e))return rt(e,n+1);let r=it(e,n+1);return t=!0,tt(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
4
+ `),n}function tt(e){let t=ge(e.command,e.positionals??[],lt(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function nt(e){return o(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function rt(e,t){let n=s(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function it(e,n){if(!o(e))throw new t(`INVALID_ARGS`,`Invalid batch step ${n}.`);ot(e,n);let r=at(e.command,n),i=st(e.positionals,n);C(r,i??[],`Batch step ${n}`);let a=ct(e.flags,n),c=s(e.runtime,n);return{command:r,...i===void 0?{}:{positionals:i},...a===void 0?{}:{flags:a},...c===void 0?{}:{runtime:c}}}function at(e,n){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new t(`INVALID_ARGS`,`Batch step ${n} requires command.`);if(v(r))return r;throw new t(`INVALID_ARGS`,`Batch step ${n} command is not available through command batch: ${String(e)}`)}function ot(e,n){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new t(`INVALID_ARGS`,`Batch step ${n} has unknown legacy field(s): ${r.join(`, `)}.`)}function st(e,n){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new t(`INVALID_ARGS`,`Batch step ${n} positionals must contain only strings.`);return e}}function ct(e,n){if(e!==void 0){if(!o(e))throw new t(`INVALID_ARGS`,`Batch step ${n} flags must be an object.`);return e}}function lt(e){return{json:!1,help:!1,version:!1,...e}}function W(e,t={}){let n=G(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function G(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??dt(t.AGENT_DEVICE_PLATFORM),r=pt(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:ut(e.policyOverrides,t,r)}}function ut(e,t,n){let r=e?.sessionLock??ft(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function dt(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function ft(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new t(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function pt(e){return typeof e==`string`&&e.trim().length>0}function mt(e,t){let n=F(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=ht(n.command)?pe({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=T(ce({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...De(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function ht(e){return e!==null}const gt={sendToDaemon:m},_t=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),vt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`]);async function K(e,t=gt){let n=ne(),r=a(),i=Ot(e),o=e.includes(`--json`);await ee({session:Bt(e)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:n,command:e[0],debug:i},async()=>{let{parsed:a,command:s,positionals:c}=await yt(e,{version:r,jsonRequested:o,debugEnabled:i}),l=Z(s,a.providedFlags),u=await bt(a,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});q(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await E(await xt(u,t));return}if(s===`web`){await E(await qe(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(se({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await St(u,t),q(u.effectiveFlags),s===`cdp`){await E(await he(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=Ct(u);let e=await wt(u);await Tt(u,p(J(u),{transport:zt({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,transport:t.sendToDaemon})}),e)}catch(e){await Et(e,u,d)}finally{d&&d()}})}function q(e){e.daemonAuthToken&&te(e.daemonAuthToken)}async function yt(n,r){let i;try{i=mt(n,{cwd:process.cwd(),env:process.env})}catch(t){y({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:b().diagnosticId,logPath:x({force:!0})??void 0});return r.jsonRequested?f({success:!1,error:n}):d(n,{showDetails:r.debugEnabled}),E(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),E(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return d(new t(`INVALID_ARGS`,`help accepts at most one command.`)),E(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await z()}\n`),E(0);let n=await Fe(e);return n?(process.stdout.write(n),E(0)):(d(new t(`INVALID_ARGS`,kt(e))),process.stdout.write(`${await z()}\n`),E(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await z()}\n`),E(1))}async function bt(t,r){let i=new Set(t.providedFlags.map(e=>e.key));try{let e=G({policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),n=e.lockPolicy?{...t.flags}:W(t.flags,{policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),a=h(n.stateDir),o=n.session??`default`,s=Mt({command:r.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:n.remoteConfig,hasResolvedSession:n.session!==void 0}),c=s?Lt(n,s.flags,i):n;return{...r,binding:e,flags:n,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(n(i),{diagnosticId:b().diagnosticId,logPath:x({force:!0})??void 0});return t.flags.json?f({success:!1,error:a}):d(a,{showDetails:r.debugOutputEnabled}),E(1)}}async function xt(e,t){let{daemonAuthToken:n,...i}=e.effectiveFlags;return await Ke(e.positionals,{flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await t.sendToDaemon({command:l.runtime,positionals:[`port-reverse`],flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},{authToken:n});a.ok||r(a.error)}})}async function St(e,n){if(e.command===`batch`){if(e.positionals.length>0)throw new t(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=At(e.flags)}if(Pt(e.command)&&(e.effectiveFlags=(await _e({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&Nt(e.command)){let t=p(J(e),{transport:Q(n.sendToDaemon)}),r=await me({command:e.command,flags:e.effectiveFlags,client:t,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Rt(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Ft({command:e.command,flags:e.effectiveFlags,runtime:e.resolvedRuntime,explicitFlagKeys:e.explicitFlagKeys,hadConnectionDefaults:!!e.connectionDefaults})&&process.stderr.write(`Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.
5
+ `)}function J(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function Ct(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Vt(e.daemonPaths.logPath):null}async function wt(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function Tt(e,n,r){let{command:i,positionals:a,effectiveFlags:o}=e;if(i===`batch`){if(!e.parsedBatchSteps)throw new t(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let s=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:W(t.input,{policyOverrides:o,configuredPlatform:o.platform,configuredSession:o.session,inheritedPlatform:o.platform})}));if(await V({command:i,positionals:a,flags:{...o,batchSteps:s},client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return}else if(i===`runtime`)throw new t(`INVALID_ARGS`,`runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.`);else if(await V({command:i,positionals:a,flags:o,client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return;throw new t(`INVALID_ARGS`,X(i))}async function Et(t,r,i){let a=n(t),o=e(a,{diagnosticId:b().diagnosticId,logPath:x({force:!0})??void 0});if(r.command===`close`&&jt(a)){r.effectiveFlags.json&&f({success:!0,data:{closed:`session`,source:`no-daemon`}});return}r.effectiveFlags.json?f({success:!1,error:o}):(d(o,{showDetails:r.debugOutputEnabled}),r.debugOutputEnabled&&Dt(r.daemonPaths.logPath)),i&&i(),await E(1)}const Y=64e3;function Dt(e){try{if(D.existsSync(e)){let t=D.readFileSync(e,`utf8`).split(`
16
6
  `),n=t.slice(Math.max(0,t.length-200)).join(`
17
- `);n.trim().length>0&&process.stderr.write(`\n[daemon log]\n${n}\n`)}}catch{}}function pc(e){try{let t=_n(e);return gc(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function mc(e){let t=pn(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function hc(e){return c(e)?(Ne({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function gc(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function _c(e){let n=``;if(e.steps)n=e.steps;else if(e.stepsFile)try{n=O.readFileSync(e.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new t(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return Ns(n)}function vc(e){return e.code===`COMMAND_FAILED`?e.details?.kind===`daemon_startup_failed`?!0:e.message.toLowerCase().includes(`failed to start daemon`)?typeof e.details?.infoPath==`string`||typeof e.details?.lockPath==`string`:!1:!1}function yc(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:Zn({stateDir:e.stateDir,session:e.session,remoteConfig:e.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!e.explicitFlagKeys.has(`session`)&&(!e.remoteConfig||e.command===`disconnect`||!e.hasResolvedSession),validateRemoteConfigHash:e.command!==`disconnect`})}function bc(e){return!ec.has(e)}function xc(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Sc(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Cc(e.explicitFlagKeys)}function Cc(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function wc(e,t,n){let r={...e};for(let[e,i]of Object.entries(t))i!==void 0&&(n.has(e)||(r[e]=i));return r}function Tc(e){for(let t of $s)if(e.has(t))return!0;return!1}function Ec(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;return n.json?Dc(i):async(e,n)=>{let a=t===`test`&&r?{...n,onProgress:r.onProgress}:n;return await Oc(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},a)}}function Dc(e){return async(t,n)=>await Oc(e,t,n)}async function Oc(e,t,n){return await e(t,n)}function kc(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`--session=`)){let e=n.slice(10).trim();return e.length>0?e:null}if(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}mt(process.argv[1]??``).href===import.meta.url&&tc(process.argv.slice(2)).catch(t=>{p(e(r(t)),{showDetails:!0}),process.exit(1)});function Ac(e){try{let t=O.existsSync(e)?O.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&O.existsSync(e))try{let n=O.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=O.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);O.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{O.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{tc as runCli};
7
+ `);n.length>Y&&(n=n.slice(n.length-Y)),n.trim().length>0&&process.stderr.write(`\n[daemon log]\n${n}\n`)}}catch{}}function Ot(e){try{let t=F(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function kt(e){let t=N(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function X(e){return u(e)?(y({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function Z(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function At(e){let n=``;if(e.steps)n=e.steps;else if(e.stepsFile)try{n=D.readFileSync(e.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new t(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return $e(n)}function jt(e){return e.code===`COMMAND_FAILED`?e.details?.kind===`daemon_startup_failed`?!0:e.message.toLowerCase().includes(`failed to start daemon`)?typeof e.details?.infoPath==`string`||typeof e.details?.lockPath==`string`:!1:!1}function Mt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:de({stateDir:e.stateDir,session:e.session,remoteConfig:e.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!e.explicitFlagKeys.has(`session`)&&(!e.remoteConfig||e.command===`disconnect`||!e.hasResolvedSession),validateRemoteConfigHash:e.command!==`disconnect`})}function Nt(e){return!vt.has(e)}function Pt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Ft(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:It(e.explicitFlagKeys)}function It(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Lt(e,t,n){let r={...e};for(let[e,i]of Object.entries(t))i!==void 0&&(n.has(e)||(r[e]=i));return r}function Rt(e){for(let t of _t)if(e.has(t))return!0;return!1}function zt(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;return n.json?Q(i):async(e,n)=>{let a=t===`test`&&r?{...n,onProgress:r.onProgress}:n;return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},a)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Bt(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`--session=`)){let e=n.slice(10).trim();return e.length>0?e:null}if(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}ve(process.argv[1]??``).href===import.meta.url&&K(process.argv.slice(2)).catch(async t=>{d(e(n(t)),{showDetails:!0}),await E(1)});function Vt(e){try{let t=D.existsSync(e)?D.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&D.existsSync(e))try{let n=D.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=D.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);D.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{D.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{K as runCli};
@@ -1 +1 @@
1
- import{_ as e,v as t}from"./sdk-contracts.js";import{C as n,b as r}from"./sdk-android-adb.js";import{n as i}from"./path-resolution.js";import{t as a}from"./timeouts.js";import{a as o,n as s,o as c,u as l}from"./host-process.js";import{a as u,c as d,d as f,f as ee,g as te,h as p,i as ne,l as re,m as ie,n as m,o as h,p as g,s as ae,t as oe,u as se}from"./url.js";import{a as ce,i as le,t as ue}from"./runtime-transport.js";import _ from"node:path";import{createHash as de}from"node:crypto";import v from"node:fs";import{fileURLToPath as fe}from"node:url";const y=`companion-tunnel`;function b(e){return de(`sha256`).update(e).digest(`hex`)}function x(e){return e?.trim()?e.trim():void 0}function pe(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(!(typeof t.tenantId!=`string`||typeof t.runId!=`string`||typeof t.leaseId!=`string`))return{tenantId:t.tenantId,runId:t.runId,leaseId:t.leaseId}}function me(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function S(e,t,n,r){let i=r??_.join(e,`.agent-device`);if(!n)return{statePath:_.join(i,`${t.slug}.json`),logPath:_.join(i,`${t.slug}.log`)};let a=b(n).slice(0,12),o=_.join(i,t.slug);return{statePath:_.join(o,`${t.slug}-${a}.json`),logPath:_.join(o,`${t.slug}-${a}.log`)}}function C(e){try{let t=JSON.parse(v.readFileSync(e,`utf8`));if(!Number.isInteger(t.pid)||Number(t.pid)<=0||typeof t.serverBaseUrl!=`string`||typeof t.localBaseUrl!=`string`||typeof t.tokenHash!=`string`||t.tokenHash.length===0)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>typeof e==`string`&&e.length>0):[];return{pid:Number(t.pid),startTime:typeof t.startTime==`string`?t.startTime:void 0,command:typeof t.command==`string`?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:x(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:x(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:x(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:x(typeof t.session==`string`?t.session:void 0),bridgeScope:pe(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function w(e,t){v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function he(e){v.mkdirSync(_.dirname(e),{recursive:!0}),v.closeSync(v.openSync(e,`a`))}function ge(e){try{v.unlinkSync(e)}catch{}}function _e(e){try{v.unlinkSync(e)}catch{}}function T(e){try{v.readdirSync(e).length===0&&v.rmdirSync(e)}catch{}}function E(e,t){let n=_.dirname(e.statePath),r=_.dirname(e.logPath);ge(e.statePath),_e(e.logPath),T(n),r!==n&&T(r),_.basename(n)===t.slug&&T(_.dirname(n))}function D(e,t){return e.includes(t.runArg)}function ve(e,t){if(!s(e.pid))return!1;if(e.startTime){let t=c(e.pid);if(!t||t!==e.startTime)return!1}let n=o(e.pid);return!n||!D(n,t.definition)||!e.bridgeScope?!1:e.serverBaseUrl===m(t.serverBaseUrl)&&e.localBaseUrl===m(t.localBaseUrl)&&e.launchUrl===x(t.launchUrl)&&e.registerPath===x(t.registerPath)&&e.unregisterPath===x(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===x(t.session)&&me(e.bridgeScope,t.bridgeScope)&&e.tokenHash===b(t.bearerToken)}function O(e){return x(e.consumerKey)??x(e.profileKey)??null}function k(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function ye(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function A(e,t){if(!s(e.pid))return;let n=o(e.pid);if(!(!n||!D(n,t))){try{process.kill(e.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await l(e.pid,1e3)){try{process.kill(e.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await l(e.pid,1e3)}}}function be(e,t){let n={...t};return n[ee]=m(e.serverBaseUrl),n[ne]=e.bearerToken,n[ae]=m(e.localBaseUrl),n[ie]=S(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[f]=e.bridgeScope.tenantId,n[se]=e.bridgeScope.runId,n[re]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[h]=e.launchUrl.trim():delete n[h],e.registerPath?.trim()?n[d]=e.registerPath.trim():delete n[d],e.unregisterPath?.trim()?n[p]=e.unregisterPath.trim():delete n[p],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[g]=e.session.trim():delete n[g],n}function xe(e){let t=fe(import.meta.url),n=_.extname(t)||`.js`,r=[_.join(_.dirname(t),`${y}${n}`),_.join(_.dirname(t),`internal`,`${y}${n}`)].find(e=>v.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function Se(e,t){let n=xe(e.definition),i=n.endsWith(`.ts`)?[`--experimental-strip-types`]:[];v.mkdirSync(_.dirname(t),{recursive:!0});let a=v.openSync(t,`a`),s=0;try{s=r(process.execPath,[...i,n,e.definition.runArg],{env:be(e,e.env??process.env),stdio:[`ignore`,a,a]})}finally{v.closeSync(a)}if(!Number.isInteger(s)||s<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:s,startTime:c(s)??void 0,command:o(s)??void 0,serverBaseUrl:m(e.serverBaseUrl),localBaseUrl:m(e.localBaseUrl),launchUrl:x(e.launchUrl),registerPath:x(e.registerPath),unregisterPath:x(e.unregisterPath),devicePort:e.devicePort,session:x(e.session),bridgeScope:e.bridgeScope,tokenHash:b(e.bearerToken),consumers:[]}}async function j(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(r&&ve(r,e)){let e=k(r,t);return e!==r&&w(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await A(r,e.definition),E(n,e.definition)),he(n.statePath);let i;try{i=Se(e,n.logPath),w(n.statePath,k(i,t))}catch(t){throw i&&await A(i,e.definition).catch(()=>{}),E(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function M(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(!r)return E(n,e.definition),{stopped:!1,statePath:n.statePath};let i=ye(r,t);return i.consumers.length>0?(w(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await A(r,e.definition),E(n,e.definition),{stopped:!0,statePath:n.statePath})}const N={slug:`metro-companion`,runArg:te,displayName:`Metro companion`};async function Ce(e){return await j({...e,definition:N,registerPath:e.registerPath??`/api/metro/companion/register`})}async function we(e){return await M({...e,definition:N})}const P=8081,F=`.expo/.virtual-metro-entry.bundle`;function I(t,n){if(t==null||t===``)return n;let r=Number.parseInt(String(t),10);if(!Number.isInteger(r)||r<1||r>65535)throw new e(`INVALID_ARGS`,`Invalid Metro port: ${String(t)}. Use 1-65535.`);return r}function Te(t){let n=R(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!R(r),o=ue({metroHost:Ee(t,i,a),metroPort:De(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=Oe(r);return{reloadUrl:L(o,o.scheme,`${s}/reload`),messageSocketUrl:L(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function Ee(e,t,n){return R(e.metroHost)??(t?void 0:R(e.runtime?.metroHost))??(n?void 0:`localhost`)}function De(e,t,n){if(e.metroPort!==void 0)return I(e.metroPort,P);if(!t)return e.runtime?.metroPort??(n?void 0:P)}function Oe(e){let t=R(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${F}`;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 L(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 R(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function z(e){return typeof e==`string`&&e.trim()?m(e.trim()):``}function B(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function V(e,t,n){return i(e,{env:t,cwd:n})}function H(e){try{return v.accessSync(e,v.constants.F_OK),!0}catch{return!1}}function ke(e){try{return v.statSync(e).isDirectory()}catch{return!1}}function U(t){let n=_.join(t,`package.json`),r=ce(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const Ae=[{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 je(e){let t=e;for(;;){for(let{file:e,command:n}of Ae)if(H(_.join(t,e)))return{command:n,installArgs:[`install`]};if(H(_.join(t,`.git`)))return null;let e=_.dirname(t);if(e===t)return null;t=e}}function Me(e){return je(e)??{command:`npm`,installArgs:[`install`]}}function Ne(e,t){if(t!==`auto`)return t;let n=le(e);return n===`expo`||n===`repack`?n:`react-native`}function W(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function G(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>H(_.join(e,`${t}.config.${n}`)))}function Pe(e,t){return G(e,`rspack`)?`rspack`:G(e,`webpack`)?`webpack`:W(t,`@rspack/core`)?`rspack`:W(t,`webpack`)?`webpack`:`rspack`}function K(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 Fe(e){return e===`expo`?F:`index.bundle`}function q(e,t,n){return{platform:t,bundleUrl:oe(e,t,Fe(n))}}function J(e,t){return{platform:t,metroHost:B(e?.metro_host),metroPort:e?.metro_port,bundleUrl:B(e?.metro_bundle_url),launchUrl:B(e?.launch_url)}}function Ie(e,t){if(ke(_.join(e,`node_modules`)))return{installed:!1};let r=Me(e);try{n(r.command,r.installArgs,{cwd:e,env:t})}catch(e){throw Le(e,r)}return{installed:!0,packageManager:r.command}}function Le(n,r){let i=t(n),a=`Dependency install failed using detected package manager "${r.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 "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new e(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function Y(e){await a(e)}async function X(t,n,r={}){try{let e=await fetch(t,{headers:r,signal:AbortSignal.timeout(n)});return{ok:e.ok,status:e.status,body:await e.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new e(`COMMAND_FAILED`,`Timed out fetching ${t} after ${n}ms`):r}}async function Re(e,t){try{let n=await X(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function ze(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 Be(t,n,i,a,o,s,c){let l=ze(n,i,a,o);v.mkdirSync(_.dirname(s),{recursive:!0});let u=v.openSync(s,`a`),d=0;try{d=r(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{v.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new e(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function Ve(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 l(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await l(e,1e3)}}}function He(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function Z(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function Ue(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function We(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function Q(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:He(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`?Z(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):Z(t instanceof Error?t.message:String(t),!0)}let n=Ge(await t.text(),t.status,e.baseUrl);if(!t.ok)throw Z(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,Ue(t.status,n));return qe(n)}function Ge(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 Z(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,Ue(t,e))}}function Ke(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:J(e.ios_runtime,`ios`),androidRuntime:J(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 qe(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw Z(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return Ke(t)}catch(e){throw Z(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function $(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 Je(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,$(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function Ye(t,n,r){let i=n||B(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&B(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(t&&!a)throw new e(`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(!t&&i)throw new e(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(t&&a),proxyBaseUrl:t,proxyBearerToken:a}}function Xe(t){if(!t?.tenantId||!t.runId||!t.leaseId)throw new e(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return t}function Ze(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function Qe(e,t,n){return e.runtimeFilePath?V(e.runtimeFilePath,t,n):null}function $e(e,t,n,r){return V(e.logPath??_.join(r,`.agent-device`,`metro.log`),t,n)}function et(e){let t=e.env??process.env,n=process.cwd(),r=V(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=U(r),o=Ne(a,i)):o=i;let s=null;o===`repack`&&(a??=U(r),s=Pe(r,a));let c=z(e.publicBaseUrl),l=z(e.proxyBaseUrl);Ze(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=Ye(l,B(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:I(e.metroPort??8081,8081),listenHost:B(e.listenHost)??`0.0.0.0`,statusHost:B(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?Xe(e.bridgeScope):null,startupTimeoutMs:K(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:K(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:Qe(e,t,n),logPath:$e(e,t,n,r)}}async function tt(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await Re(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await Y(i)}return!1}async function nt(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await Q({baseUrl:t.baseUrl,bearerToken:t.bearerToken,scope:t.scope,runtime:t.runtime,timeoutMs:t.probeTimeoutMs});if(e.probe.reachable!==!1)return e;r=e,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!We(n))throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await Y(a)}throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function rt(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await Re(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=Be(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await tt(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await Ve(r.pid).catch(()=>{}),new e(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${t.startupTimeoutMs}ms. Check ${t.logPath}.`,{logPath:t.logPath})}async function it(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await Q({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!We(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await at(e,t,n,r,i)),Je(t.proxyBaseUrl,r),r}async function at(t,n,r,i,a){let o;try{o=(await Ce({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:B(t.launchUrl),profileKey:B(t.companionProfileKey),consumerKey:B(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,$(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await nt({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ot(e,t){return{baseIosRuntime:e?q(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?q(e,`android`,t):{platform:`android`}}}function st(e,t){e&&(v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,JSON.stringify(t,null,2)))}async function ct(e={}){let t=et(e),n=t.installProjectDeps?Ie(t.projectRoot,t.env):{installed:!1},r=await rt(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ot(t.publicBaseUrl,t.kind),o=await it(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 st(t.runtimeFilePath,l),l}function lt(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function ut(t,n){await new Promise((r,i)=>{let a=new WebSocket(t),o=t=>{clearTimeout(s);try{a.close()}catch{}i(new e(`COMMAND_FAILED`,t))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${t} after ${n}ms`)},n);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 ${t}`)})})}async function dt(t={}){let n=K(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=Te(t),a=await X(r,n);if(a.ok&&!lt(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await ut(i,n)}catch(t){throw new e(`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.`},t instanceof Error?t:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{M as a,j as i,dt as n,we as r,ct as t};
1
+ import{_ as e,v as t}from"./sdk-contracts.js";import{S as n,y as r}from"./sdk-android-adb.js";import{n as i}from"./path-resolution.js";import{t as a}from"./timeouts.js";import{d as o,n as s,o as c,s as l}from"./host-process.js";import{a as u,c as d,d as f,f as ee,g as te,h as p,i as ne,l as re,m as ie,n as m,o as h,p as g,s as ae,t as oe,u as se}from"./url.js";import{a as ce,i as le,t as ue}from"./runtime-transport.js";import _ from"node:path";import{createHash as de}from"node:crypto";import v from"node:fs";import{fileURLToPath as fe}from"node:url";const y=`companion-tunnel`;function b(e){return de(`sha256`).update(e).digest(`hex`)}function x(e){return e?.trim()?e.trim():void 0}function pe(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(!(typeof t.tenantId!=`string`||typeof t.runId!=`string`||typeof t.leaseId!=`string`))return{tenantId:t.tenantId,runId:t.runId,leaseId:t.leaseId}}function me(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function S(e,t,n,r){let i=r??_.join(e,`.agent-device`);if(!n)return{statePath:_.join(i,`${t.slug}.json`),logPath:_.join(i,`${t.slug}.log`)};let a=b(n).slice(0,12),o=_.join(i,t.slug);return{statePath:_.join(o,`${t.slug}-${a}.json`),logPath:_.join(o,`${t.slug}-${a}.log`)}}function C(e){try{let t=JSON.parse(v.readFileSync(e,`utf8`));if(!Number.isInteger(t.pid)||Number(t.pid)<=0||typeof t.serverBaseUrl!=`string`||typeof t.localBaseUrl!=`string`||typeof t.tokenHash!=`string`||t.tokenHash.length===0)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>typeof e==`string`&&e.length>0):[];return{pid:Number(t.pid),startTime:typeof t.startTime==`string`?t.startTime:void 0,command:typeof t.command==`string`?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:x(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:x(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:x(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:x(typeof t.session==`string`?t.session:void 0),bridgeScope:pe(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function w(e,t){v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function he(e){v.mkdirSync(_.dirname(e),{recursive:!0}),v.closeSync(v.openSync(e,`a`))}function ge(e){try{v.unlinkSync(e)}catch{}}function _e(e){try{v.unlinkSync(e)}catch{}}function T(e){try{v.readdirSync(e).length===0&&v.rmdirSync(e)}catch{}}function E(e,t){let n=_.dirname(e.statePath),r=_.dirname(e.logPath);ge(e.statePath),_e(e.logPath),T(n),r!==n&&T(r),_.basename(n)===t.slug&&T(_.dirname(n))}function D(e,t){return e.includes(t.runArg)}function ve(e,t){if(!s(e.pid))return!1;if(e.startTime){let t=l(e.pid);if(!t||t!==e.startTime)return!1}let n=c(e.pid);return!n||!D(n,t.definition)||!e.bridgeScope?!1:e.serverBaseUrl===m(t.serverBaseUrl)&&e.localBaseUrl===m(t.localBaseUrl)&&e.launchUrl===x(t.launchUrl)&&e.registerPath===x(t.registerPath)&&e.unregisterPath===x(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===x(t.session)&&me(e.bridgeScope,t.bridgeScope)&&e.tokenHash===b(t.bearerToken)}function O(e){return x(e.consumerKey)??x(e.profileKey)??null}function k(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function ye(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function A(e,t){if(!s(e.pid))return;let n=c(e.pid);if(!(!n||!D(n,t))){try{process.kill(e.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await o(e.pid,1e3)){try{process.kill(e.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await o(e.pid,1e3)}}}function be(e,t){let n={...t};return n[ee]=m(e.serverBaseUrl),n[ne]=e.bearerToken,n[ae]=m(e.localBaseUrl),n[ie]=S(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[f]=e.bridgeScope.tenantId,n[se]=e.bridgeScope.runId,n[re]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[h]=e.launchUrl.trim():delete n[h],e.registerPath?.trim()?n[d]=e.registerPath.trim():delete n[d],e.unregisterPath?.trim()?n[p]=e.unregisterPath.trim():delete n[p],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[g]=e.session.trim():delete n[g],n}function xe(e){let t=fe(import.meta.url),n=_.extname(t)||`.js`,r=[_.join(_.dirname(t),`${y}${n}`),_.join(_.dirname(t),`internal`,`${y}${n}`)].find(e=>v.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function Se(e,t){let n=xe(e.definition),i=n.endsWith(`.ts`)?[`--experimental-strip-types`]:[];v.mkdirSync(_.dirname(t),{recursive:!0});let a=v.openSync(t,`a`),o=0;try{o=r(process.execPath,[...i,n,e.definition.runArg],{env:be(e,e.env??process.env),stdio:[`ignore`,a,a]})}finally{v.closeSync(a)}if(!Number.isInteger(o)||o<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:o,startTime:l(o)??void 0,command:c(o)??void 0,serverBaseUrl:m(e.serverBaseUrl),localBaseUrl:m(e.localBaseUrl),launchUrl:x(e.launchUrl),registerPath:x(e.registerPath),unregisterPath:x(e.unregisterPath),devicePort:e.devicePort,session:x(e.session),bridgeScope:e.bridgeScope,tokenHash:b(e.bearerToken),consumers:[]}}async function j(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(r&&ve(r,e)){let e=k(r,t);return e!==r&&w(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await A(r,e.definition),E(n,e.definition)),he(n.statePath);let i;try{i=Se(e,n.logPath),w(n.statePath,k(i,t))}catch(t){throw i&&await A(i,e.definition).catch(()=>{}),E(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function M(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(!r)return E(n,e.definition),{stopped:!1,statePath:n.statePath};let i=ye(r,t);return i.consumers.length>0?(w(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await A(r,e.definition),E(n,e.definition),{stopped:!0,statePath:n.statePath})}const N={slug:`metro-companion`,runArg:te,displayName:`Metro companion`};async function Ce(e){return await j({...e,definition:N,registerPath:e.registerPath??`/api/metro/companion/register`})}async function we(e){return await M({...e,definition:N})}const P=8081,F=`.expo/.virtual-metro-entry.bundle`;function I(t,n){if(t==null||t===``)return n;let r=Number.parseInt(String(t),10);if(!Number.isInteger(r)||r<1||r>65535)throw new e(`INVALID_ARGS`,`Invalid Metro port: ${String(t)}. Use 1-65535.`);return r}function Te(t){let n=R(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!R(r),o=ue({metroHost:Ee(t,i,a),metroPort:De(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=Oe(r);return{reloadUrl:L(o,o.scheme,`${s}/reload`),messageSocketUrl:L(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function Ee(e,t,n){return R(e.metroHost)??(t?void 0:R(e.runtime?.metroHost))??(n?void 0:`localhost`)}function De(e,t,n){if(e.metroPort!==void 0)return I(e.metroPort,P);if(!t)return e.runtime?.metroPort??(n?void 0:P)}function Oe(e){let t=R(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${F}`;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 L(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 R(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function z(e){return typeof e==`string`&&e.trim()?m(e.trim()):``}function B(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function V(e,t,n){return i(e,{env:t,cwd:n})}function H(e){try{return v.accessSync(e,v.constants.F_OK),!0}catch{return!1}}function ke(e){try{return v.statSync(e).isDirectory()}catch{return!1}}function U(t){let n=_.join(t,`package.json`),r=ce(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const Ae=[{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 je(e){let t=e;for(;;){for(let{file:e,command:n}of Ae)if(H(_.join(t,e)))return{command:n,installArgs:[`install`]};if(H(_.join(t,`.git`)))return null;let e=_.dirname(t);if(e===t)return null;t=e}}function Me(e){return je(e)??{command:`npm`,installArgs:[`install`]}}function Ne(e,t){if(t!==`auto`)return t;let n=le(e);return n===`expo`||n===`repack`?n:`react-native`}function W(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function G(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>H(_.join(e,`${t}.config.${n}`)))}function Pe(e,t){return G(e,`rspack`)?`rspack`:G(e,`webpack`)?`webpack`:W(t,`@rspack/core`)?`rspack`:W(t,`webpack`)?`webpack`:`rspack`}function K(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 Fe(e){return e===`expo`?F:`index.bundle`}function q(e,t,n){return{platform:t,bundleUrl:oe(e,t,Fe(n))}}function J(e,t){return{platform:t,metroHost:B(e?.metro_host),metroPort:e?.metro_port,bundleUrl:B(e?.metro_bundle_url),launchUrl:B(e?.launch_url)}}function Ie(e,t){if(ke(_.join(e,`node_modules`)))return{installed:!1};let r=Me(e);try{n(r.command,r.installArgs,{cwd:e,env:t})}catch(e){throw Le(e,r)}return{installed:!0,packageManager:r.command}}function Le(n,r){let i=t(n),a=`Dependency install failed using detected package manager "${r.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 "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new e(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function Y(e){await a(e)}async function X(t,n,r={}){try{let e=await fetch(t,{headers:r,signal:AbortSignal.timeout(n)});return{ok:e.ok,status:e.status,body:await e.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new e(`COMMAND_FAILED`,`Timed out fetching ${t} after ${n}ms`):r}}async function Re(e,t){try{let n=await X(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function ze(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 Be(t,n,i,a,o,s,c){let l=ze(n,i,a,o);v.mkdirSync(_.dirname(s),{recursive:!0});let u=v.openSync(s,`a`),d=0;try{d=r(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{v.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new e(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function Ve(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 o(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await o(e,1e3)}}}function He(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function Z(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function Ue(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function We(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function Q(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:He(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`?Z(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):Z(t instanceof Error?t.message:String(t),!0)}let n=Ge(await t.text(),t.status,e.baseUrl);if(!t.ok)throw Z(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,Ue(t.status,n));return qe(n)}function Ge(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 Z(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,Ue(t,e))}}function Ke(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:J(e.ios_runtime,`ios`),androidRuntime:J(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 qe(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw Z(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return Ke(t)}catch(e){throw Z(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function $(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 Je(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,$(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function Ye(t,n,r){let i=n||B(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&B(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(t&&!a)throw new e(`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(!t&&i)throw new e(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(t&&a),proxyBaseUrl:t,proxyBearerToken:a}}function Xe(t){if(!t?.tenantId||!t.runId||!t.leaseId)throw new e(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return t}function Ze(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function Qe(e,t,n){return e.runtimeFilePath?V(e.runtimeFilePath,t,n):null}function $e(e,t,n,r){return V(e.logPath??_.join(r,`.agent-device`,`metro.log`),t,n)}function et(e){let t=e.env??process.env,n=process.cwd(),r=V(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=U(r),o=Ne(a,i)):o=i;let s=null;o===`repack`&&(a??=U(r),s=Pe(r,a));let c=z(e.publicBaseUrl),l=z(e.proxyBaseUrl);Ze(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=Ye(l,B(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:I(e.metroPort??8081,8081),listenHost:B(e.listenHost)??`0.0.0.0`,statusHost:B(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?Xe(e.bridgeScope):null,startupTimeoutMs:K(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:K(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:Qe(e,t,n),logPath:$e(e,t,n,r)}}async function tt(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await Re(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await Y(i)}return!1}async function nt(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await Q({baseUrl:t.baseUrl,bearerToken:t.bearerToken,scope:t.scope,runtime:t.runtime,timeoutMs:t.probeTimeoutMs});if(e.probe.reachable!==!1)return e;r=e,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!We(n))throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await Y(a)}throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function rt(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await Re(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=Be(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await tt(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await Ve(r.pid).catch(()=>{}),new e(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${t.startupTimeoutMs}ms. Check ${t.logPath}.`,{logPath:t.logPath})}async function it(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await Q({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!We(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await at(e,t,n,r,i)),Je(t.proxyBaseUrl,r),r}async function at(t,n,r,i,a){let o;try{o=(await Ce({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:B(t.launchUrl),profileKey:B(t.companionProfileKey),consumerKey:B(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,$(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await nt({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ot(e,t){return{baseIosRuntime:e?q(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?q(e,`android`,t):{platform:`android`}}}function st(e,t){e&&(v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,JSON.stringify(t,null,2)))}async function ct(e={}){let t=et(e),n=t.installProjectDeps?Ie(t.projectRoot,t.env):{installed:!1},r=await rt(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ot(t.publicBaseUrl,t.kind),o=await it(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 st(t.runtimeFilePath,l),l}function lt(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function ut(t,n){await new Promise((r,i)=>{let a=new WebSocket(t),o=t=>{clearTimeout(s);try{a.close()}catch{}i(new e(`COMMAND_FAILED`,t))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${t} after ${n}ms`)},n);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 ${t}`)})})}async function dt(t={}){let n=K(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=Te(t),a=await X(r,n);if(a.ok&&!lt(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await ut(i,n)}catch(t){throw new e(`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.`},t instanceof Error?t:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{M as a,j as i,dt as n,we as r,ct as t};
@@ -1,139 +1,4 @@
1
- import { A as SnapshotNode, M as SnapshotQualityVerdict, N as SnapshotState, O as ScreenshotOverlayRef, U as PublicPlatform, n as DaemonArtifactType } from "./sdk-contracts.js";
2
- //#region packages/contracts/src/back-mode.d.ts
3
- declare const BACK_MODES: readonly ['in-app', 'system'];
4
- type BackMode = (typeof BACK_MODES)[number];
5
- //#endregion
6
- //#region packages/contracts/src/device-rotation.d.ts
7
- declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
8
- type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
9
- //#endregion
10
- //#region packages/contracts/src/tv-remote.d.ts
11
- declare const TV_REMOTE_BUTTON_DEFINITIONS: {
12
- readonly up: {
13
- readonly aliases: readonly [];
14
- readonly androidKeyevent: 'KEYCODE_DPAD_UP';
15
- readonly appleRemoteButton: 'up';
16
- readonly vegaKey: 'KEY_UP';
17
- };
18
- readonly down: {
19
- readonly aliases: readonly [];
20
- readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
21
- readonly appleRemoteButton: 'down';
22
- readonly vegaKey: 'KEY_DOWN';
23
- };
24
- readonly left: {
25
- readonly aliases: readonly [];
26
- readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
27
- readonly appleRemoteButton: 'left';
28
- readonly vegaKey: 'KEY_LEFT';
29
- };
30
- readonly right: {
31
- readonly aliases: readonly [];
32
- readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
33
- readonly appleRemoteButton: 'right';
34
- readonly vegaKey: 'KEY_RIGHT';
35
- };
36
- readonly select: {
37
- readonly aliases: readonly ["ok", "center", "enter"];
38
- readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
39
- readonly appleRemoteButton: 'select';
40
- readonly vegaKey: 'KEY_ENTER';
41
- };
42
- readonly menu: {
43
- readonly aliases: readonly [];
44
- readonly androidKeyevent: 'KEYCODE_MENU';
45
- readonly appleRemoteButton: 'menu';
46
- readonly vegaKey: 'KEY_MENU';
47
- };
48
- readonly home: {
49
- readonly aliases: readonly [];
50
- readonly androidKeyevent: 'KEYCODE_HOME';
51
- readonly appleRemoteButton: 'home';
52
- readonly vegaKey: 'KEY_HOMEPAGE';
53
- };
54
- readonly back: {
55
- readonly aliases: readonly [];
56
- readonly androidKeyevent: 'KEYCODE_BACK';
57
- readonly appleRemoteButton: 'menu';
58
- readonly vegaKey: 'KEY_BACK';
59
- };
60
- };
61
- declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
62
- type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
63
- //#endregion
64
- //#region packages/contracts/src/session-surface.d.ts
65
- declare const SESSION_SURFACES: readonly ['app', 'frontmost-app', 'desktop', 'menubar'];
66
- type SessionSurface = (typeof SESSION_SURFACES)[number];
67
- //#endregion
68
- //#region packages/contracts/src/snapshot-diagnostics.d.ts
69
- type SnapshotTimingStats = {
70
- count: number;
71
- p50Ms: number;
72
- p95Ms: number;
73
- maxMs: number;
74
- slowThresholdMs: number;
75
- platform?: PublicPlatform;
76
- backends?: Record<string, number>;
77
- };
78
- type SnapshotDiagnosticsSummary = {
79
- stats: SnapshotTimingStats;
80
- warning?: string;
81
- };
82
- //#endregion
83
- //#region packages/contracts/src/snapshot-types.d.ts
84
- type ScreenshotResultData = {
85
- path?: string;
86
- width?: number;
87
- height?: number;
88
- logicalWidth?: number;
89
- logicalHeight?: number;
90
- pixelDensity?: number;
91
- overlayRefs?: ScreenshotOverlayRef[];
92
- };
93
- type BackendSnapshotResult = {
94
- nodes?: SnapshotNode[];
95
- truncated?: boolean;
96
- backend?: string;
97
- snapshot?: SnapshotState;
98
- appName?: string;
99
- appBundleId?: string;
100
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
101
- analysis?: {
102
- rawNodeCount: number;
103
- maxDepth: number;
104
- };
105
- androidSnapshot?: AndroidSnapshotBackendMetadata;
106
- freshness?: {
107
- action: string;
108
- retryCount: number;
109
- staleAfterRetries: boolean;
110
- reason?: 'empty-interactive' | 'sharp-drop' | 'stuck-route';
111
- };
112
- quality?: SnapshotQualityVerdict;
113
- warnings?: string[];
114
- };
115
- type AndroidSnapshotBackendMetadata = {
116
- backend: 'android-helper';
117
- helperVersion?: string;
118
- helperApiVersion?: string;
119
- helperTransport?: string;
120
- helperSessionReused?: boolean;
121
- installReason?: string;
122
- waitForIdleTimeoutMs?: number;
123
- waitForIdleQuietMs?: number;
124
- timeoutMs?: number;
125
- maxDepth?: number;
126
- maxNodes?: number;
127
- rootPresent?: boolean;
128
- captureMode?: string;
129
- systemSurfaceOnly?: boolean;
130
- windowCount?: number;
131
- nodeCount?: number;
132
- helperTruncated?: boolean;
133
- elapsedMs?: number;
134
- };
135
- type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
136
- //#endregion
1
+ import { n as DaemonArtifactType } from "./sdk-contracts.js";
137
2
  //#region packages/contracts/src/cloud-artifacts.d.ts
138
3
  declare const CLOUD_ARTIFACT_KINDS: readonly ['video', 'appium-log', 'device-log', 'automation-log', 'provider-session', 'raw'];
139
4
  type CloudArtifactKind = (typeof CLOUD_ARTIFACT_KINDS)[number];
@@ -193,4 +58,4 @@ type CloudArtifactProvider = {
193
58
  listCloudArtifacts?: (query: CloudArtifactsQuery) => Promise<CloudArtifactsResult | undefined>;
194
59
  };
195
60
  //#endregion
196
- export { BackendSnapshotResult as a, SnapshotDiagnosticsSummary as c, DeviceRotation as d, BackMode as f, AndroidSnapshotBackendMetadata as i, SessionSurface as l, CloudArtifactProvider as n, FindLocator as o, CloudProviderSessionResult as r, ScreenshotResultData as s, AgentArtifactsResult as t, TvRemoteButton as u };
61
+ export { CloudArtifactProvider as n, CloudProviderSessionResult as r, AgentArtifactsResult as t };