agent-device 0.21.0 → 0.21.2

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 (328) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.0.apk → agent-device-android-ime-helper-0.21.2.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.2.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.0.manifest.json → agent-device-android-ime-helper-0.21.2.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.2.apk +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.2.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.0.manifest.json → agent-device-android-snapshot-helper-0.21.2.manifest.json} +6 -6
  7. package/apple/snapshot-bridge/README.md +58 -1
  8. package/apple/snapshot-bridge/SnapshotBridge.m +6 -0
  9. package/apple/snapshot-bridge/SnapshotBridgeCapture.h +25 -0
  10. package/apple/snapshot-bridge/SnapshotBridgeCapture.m +138 -0
  11. package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +1 -0
  12. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +32 -3
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +12 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +413 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +15 -15
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +72 -0
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +63 -14
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +668 -82
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +48 -4
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +39 -4
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1078 -211
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +290 -0
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +1 -1
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +10 -10
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +250 -74
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +101 -42
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -13
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +55 -43
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +71 -4
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +144 -7
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +13 -1
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +216 -17
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +206 -22
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +289 -42
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +92 -22
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +617 -122
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +79 -4
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +71 -71
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +92 -6
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +67 -67
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -4
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +17 -17
  44. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +30 -30
  45. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +31 -31
  46. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +28 -0
  47. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +101 -0
  48. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +19 -19
  49. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +55 -17
  50. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +26 -5
  51. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +126 -75
  52. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +8 -12
  53. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +9 -9
  54. package/dist/src/absence-observation-errors.js +1 -0
  55. package/dist/src/adapter.js +1 -1
  56. package/dist/src/adb-executor.js +1 -1
  57. package/dist/src/adb-failure.js +1 -1
  58. package/dist/src/agent-browser-lifecycle.js +1 -1
  59. package/dist/src/agent-browser-process-record.js +1 -1
  60. package/dist/src/agent-browser-provider.js +1 -1
  61. package/dist/src/agent-browser-tool.js +1 -1
  62. package/dist/src/agent-device-client.js +2 -2
  63. package/dist/src/ai-sdk.d.ts +1 -1
  64. package/dist/src/ai-sdk.js +1 -1
  65. package/dist/src/alert-runtime.js +1 -1
  66. package/dist/src/android-input-ownership.js +1 -1
  67. package/dist/src/app-catalog.js +1 -1
  68. package/dist/src/app-deployment-resolution.js +1 -1
  69. package/dist/src/app-helpers.js +1 -1
  70. package/dist/src/app-inventory-contract.js +1 -1
  71. package/dist/src/app-inventory.js +1 -1
  72. package/dist/src/app-launch.js +2 -2
  73. package/dist/src/app-lifecycle.js +3 -3
  74. package/dist/src/app-lifecycle2.js +1 -1
  75. package/dist/src/app-log-files.js +1 -1
  76. package/dist/src/app-log-runtime2.js +3 -3
  77. package/dist/src/app-resolution.js +1 -1
  78. package/dist/src/apple-runner-platform.js +1 -0
  79. package/dist/src/application-lifecycle-interaction.js +1 -1
  80. package/dist/src/archive.js +1 -1
  81. package/dist/src/artifact-download.js +1 -1
  82. package/dist/src/auth-session.js +1 -1
  83. package/dist/src/auth.js +1 -1
  84. package/dist/src/back-mode.js +1 -1
  85. package/dist/src/backend-snapshot-options.js +1 -1
  86. package/dist/src/boot-diagnostics.js +1 -1
  87. package/dist/src/browser-launch.js +1 -0
  88. package/dist/src/capture.js +1 -1
  89. package/dist/src/catalog.js +1 -1
  90. package/dist/src/cli-config.js +1 -1
  91. package/dist/src/cli-help.js +30 -26
  92. package/dist/src/cli.js +4 -4
  93. package/dist/src/click-button.js +1 -1
  94. package/dist/src/client-metro-companion.js +1 -1
  95. package/dist/src/client-metro.js +1 -1
  96. package/dist/src/client-types.d.ts +28 -13
  97. package/dist/src/code-signature-cache.js +1 -1
  98. package/dist/src/code-signature.js +1 -1
  99. package/dist/src/command-metadata.js +1 -1
  100. package/dist/src/command-schema.js +3 -3
  101. package/dist/src/command-tools.js +2 -2
  102. package/dist/src/command.js +1 -1
  103. package/dist/src/config.js +1 -1
  104. package/dist/src/connection-runtime.js +1 -1
  105. package/dist/src/connection.js +3 -3
  106. package/dist/src/contracts.d.ts +1 -1
  107. package/dist/src/contracts.js +1 -1
  108. package/dist/src/daemon-client-lifecycle.js +1 -1
  109. package/dist/src/daemon-process.js +1 -1
  110. package/dist/src/daemon-shutdown-report.js +1 -1
  111. package/dist/src/daemon.js +1 -1
  112. package/dist/src/debug-symbols-facade.js +1 -1
  113. package/dist/src/device-boot.js +1 -0
  114. package/dist/src/device-claim-inspection.js +1 -1
  115. package/dist/src/device-claim-rule.js +1 -1
  116. package/dist/src/device-input-state.d.ts +1 -1
  117. package/dist/src/device-inventory-context.js +1 -1
  118. package/dist/src/device-rotation.js +1 -1
  119. package/dist/src/device-selection-resolver.js +1 -1
  120. package/dist/src/device-session.js +1 -1
  121. package/dist/src/device2.js +1 -1
  122. package/dist/src/diagnostics.js +1 -1
  123. package/dist/src/dispatch-resolve.js +1 -1
  124. package/dist/src/doctor2.js +1 -1
  125. package/dist/src/durable-resource.js +1 -1
  126. package/dist/src/engine-eval-script.js +1 -0
  127. package/dist/src/error.js +1 -1
  128. package/dist/src/exec.js +1 -1
  129. package/dist/src/file.js +1 -1
  130. package/dist/src/find.js +1 -1
  131. package/dist/src/finders.js +1 -1
  132. package/dist/src/format.js +1 -2
  133. package/dist/src/generic-settle.js +1 -1
  134. package/dist/src/gesture-plan.js +1 -1
  135. package/dist/src/gesture-runtime.js +1 -1
  136. package/dist/src/harmonyos.js +1 -1
  137. package/dist/src/hdc.js +1 -1
  138. package/dist/src/helper.js +2 -2
  139. package/dist/src/human-control-contract.js +1 -1
  140. package/dist/src/human-control.js +1 -1
  141. package/dist/src/index.d.ts +1 -1
  142. package/dist/src/index.js +1 -1
  143. package/dist/src/input-actions.js +1 -1
  144. package/dist/src/input-actions2.js +2 -2
  145. package/dist/src/install-artifact-facade.js +1 -1
  146. package/dist/src/install-source-network-transport.js +1 -1
  147. package/dist/src/install-source2.js +1 -1
  148. package/dist/src/interaction-positionals.js +1 -1
  149. package/dist/src/interaction-ref-policy.js +1 -1
  150. package/dist/src/interaction.js +1 -1
  151. package/dist/src/interaction2.js +1 -1
  152. package/dist/src/interactor.js +5 -5
  153. package/dist/src/interactor2.js +1 -1
  154. package/dist/src/interactors.js +1 -1
  155. package/dist/src/internal/bin.js +1 -1
  156. package/dist/src/internal/daemon.js +2 -2
  157. package/dist/src/internal/png-worker.d.ts +3 -0
  158. package/dist/src/internal/png-worker.js +1 -1
  159. package/dist/src/internal/run-script-http-child.js +1 -1
  160. package/dist/src/inventory.js +2 -2
  161. package/dist/src/inventory2.js +1 -1
  162. package/dist/src/inventory3.js +1 -1
  163. package/dist/src/inventory5.js +1 -1
  164. package/dist/src/ios-snapshot-acquisition.js +1 -1
  165. package/dist/src/ios-snapshot-planning.js +1 -1
  166. package/dist/src/ios-snapshot-runtime.js +1 -1
  167. package/dist/src/ios-system-surface.js +1 -0
  168. package/dist/src/lease-scope.js +1 -1
  169. package/dist/src/lease.js +1 -1
  170. package/dist/src/limrun-runtime-dependencies.js +1 -1
  171. package/dist/src/limrun.d.ts +1 -1
  172. package/dist/src/linux.js +1 -1
  173. package/dist/src/local-interactor-operation-set.js +1 -1
  174. package/dist/src/location-coordinates.js +1 -1
  175. package/dist/src/managed-device-scope.js +1 -1
  176. package/dist/src/mechanics.js +16 -16
  177. package/dist/src/mobile-snapshot-semantics.js +1 -1
  178. package/dist/src/mp4-atoms.js +1 -0
  179. package/dist/src/multitouch-support.js +1 -1
  180. package/dist/src/observation.js +1 -1
  181. package/dist/src/open-target-resolution.js +1 -0
  182. package/dist/src/owner-identity.js +3 -3
  183. package/dist/src/parameterized-recorded-fill.js +1 -1
  184. package/dist/src/perf-facade.js +2 -2
  185. package/dist/src/perf-process-identity.js +1 -0
  186. package/dist/src/perf-runtime-operation-builder.js +1 -1
  187. package/dist/src/perf-runtime-plan.js +1 -1
  188. package/dist/src/perf.js +1 -1
  189. package/dist/src/physical-device-control.js +1 -1
  190. package/dist/src/platform-request-scope.js +1 -1
  191. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  192. package/dist/src/platform-runtime-app-log-process.js +1 -1
  193. package/dist/src/platform-runtime-host.js +1 -1
  194. package/dist/src/platform-runtime-managed-owner.js +1 -1
  195. package/dist/src/platform-runtime-open-target.js +1 -1
  196. package/dist/src/platform-runtime-operation-host.js +2 -2
  197. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  198. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  199. package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
  200. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  201. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  202. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  203. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  204. package/dist/src/platform-runtime-unavailable.js +1 -1
  205. package/dist/src/platform-runtime.js +1 -1
  206. package/dist/src/platform-runtime2.js +1 -1
  207. package/dist/src/png-crop-bytes.js +1 -0
  208. package/dist/src/png-worker-contract.js +1 -1
  209. package/dist/src/png.js +1 -0
  210. package/dist/src/prepare-kind.js +1 -1
  211. package/dist/src/process.js +1 -1
  212. package/dist/src/provider-device-runtime.js +1 -1
  213. package/dist/src/provider-session-ownership.js +1 -1
  214. package/dist/src/provider-webdriver.js +1 -1
  215. package/dist/src/proxy.js +1 -1
  216. package/dist/src/quality-warnings.js +1 -0
  217. package/dist/src/react-native.js +1 -1
  218. package/dist/src/record-runtime.js +1 -1
  219. package/dist/src/rect-center.js +1 -1
  220. package/dist/src/register-builtins.js +1 -1
  221. package/dist/src/registry.js +36 -36
  222. package/dist/src/remote-config2.js +1 -1
  223. package/dist/src/replay-divergence.js +1 -1
  224. package/dist/src/replay.js +2 -2
  225. package/dist/src/reporting.js +9 -8
  226. package/dist/src/request-admission.js +1 -1
  227. package/dist/src/request-cancel.js +1 -1
  228. package/dist/src/request-cancellation.js +1 -1
  229. package/dist/src/request-runtime-binding.js +1 -1
  230. package/dist/src/retry.js +1 -1
  231. package/dist/src/runner-cache-metadata.js +2 -2
  232. package/dist/src/runner-client.js +1 -1
  233. package/dist/src/runner-disposal.js +1 -1
  234. package/dist/src/runner-operations-facade.js +1 -1
  235. package/dist/src/runner-presentation.js +1 -1
  236. package/dist/src/runner.js +1 -1
  237. package/dist/src/runtime-transport-hints.js +1 -1
  238. package/dist/src/runtime.js +3 -3
  239. package/dist/src/runtime10.js +1 -0
  240. package/dist/src/runtime2.js +4 -4
  241. package/dist/src/runtime3.js +1 -1
  242. package/dist/src/runtime4.js +5 -4
  243. package/dist/src/runtime5.js +1 -1
  244. package/dist/src/runtime6.js +1 -1
  245. package/dist/src/runtime7.js +1 -1
  246. package/dist/src/runtime8.js +1 -1
  247. package/dist/src/runtime9.js +1 -1
  248. package/dist/src/screen-recording-live-handle.js +1 -1
  249. package/dist/src/screen-recording-options.js +1 -1
  250. package/dist/src/screen-recording-resource-recovery.js +1 -1
  251. package/dist/src/screenshot-density.js +1 -1
  252. package/dist/src/screenshot-runtime.js +1 -1
  253. package/dist/src/screenshot.js +1 -1
  254. package/dist/src/screenshot3.js +3 -3
  255. package/dist/src/script.js +1 -1
  256. package/dist/src/scroll-command.js +1 -1
  257. package/dist/src/scroll-gesture.js +1 -1
  258. package/dist/src/sdk-batch-runner.js +2 -2
  259. package/dist/src/sdk-batch.js +2 -2
  260. package/dist/src/sdk-contracts.d.ts +69 -26
  261. package/dist/src/sdk-contracts.js +2 -2
  262. package/dist/src/sdk-device.js +1 -1
  263. package/dist/src/sdk-finders.d.ts +1 -1
  264. package/dist/src/sdk-finders.js +1 -1
  265. package/dist/src/sdk-io.js +1 -1
  266. package/dist/src/sdk-remote-config.d.ts +1 -1
  267. package/dist/src/sdk-remote-config.js +1 -1
  268. package/dist/src/sdk-selectors.d.ts +80 -16
  269. package/dist/src/sdk-selectors.js +1 -1
  270. package/dist/src/selection.js +0 -0
  271. package/dist/src/selector-runtime.js +1 -1
  272. package/dist/src/selectors.js +1 -1
  273. package/dist/src/semantic-index.js +1 -1
  274. package/dist/src/server.js +3 -3
  275. package/dist/src/session-allocation.js +1 -1
  276. package/dist/src/session-observation.js +1 -0
  277. package/dist/src/session-routing.js +1 -1
  278. package/dist/src/session-runtime-admission.js +1 -1
  279. package/dist/src/session-snapshot.js +1 -1
  280. package/dist/src/session-store.js +3 -3
  281. package/dist/src/session-target-evidence.js +1 -1
  282. package/dist/src/session2.js +5 -5
  283. package/dist/src/settings.js +1 -1
  284. package/dist/src/simulator-boot.js +3 -0
  285. package/dist/src/simulator.js +1 -1
  286. package/dist/src/snapshot-quality-backend-capabilities.js +1 -1
  287. package/dist/src/snapshot-runtime-binding.js +1 -1
  288. package/dist/src/snapshot-runtime.js +1 -1
  289. package/dist/src/snapshot-state.js +1 -1
  290. package/dist/src/snapshot2.js +1 -1
  291. package/dist/src/snapshot3.js +1 -1
  292. package/dist/src/snapshot4.js +1 -1
  293. package/dist/src/src.js +1 -1
  294. package/dist/src/src7.js +2 -2
  295. package/dist/src/src8.js +2 -2
  296. package/dist/src/string-enum.js +1 -1
  297. package/dist/src/takeover.js +1 -1
  298. package/dist/src/telemetry.js +1 -1
  299. package/dist/src/tool-provider.js +2 -2
  300. package/dist/src/tool-provider2.js +1 -1
  301. package/dist/src/tool-provider3.js +1 -1
  302. package/dist/src/toolchain-probe.js +1 -1
  303. package/dist/src/touch-reference-frame.js +1 -0
  304. package/dist/src/touch-runtime.js +1 -1
  305. package/dist/src/transport.js +1 -1
  306. package/dist/src/tree.js +1 -1
  307. package/dist/src/tv-remote.js +1 -1
  308. package/dist/src/type-text-runtime.js +1 -1
  309. package/dist/src/update-check.js +1 -1
  310. package/dist/src/vars.js +2 -0
  311. package/dist/src/verified-file.js +1 -1
  312. package/dist/src/version.js +1 -1
  313. package/dist/src/video.js +2 -2
  314. package/dist/src/viewport.js +1 -0
  315. package/dist/src/web.js +1 -1
  316. package/dist/src/web2.js +1 -1
  317. package/dist/src/webdriver-ios-snapshot.js +1 -1
  318. package/dist/src/webdriver-source.js +1 -1
  319. package/dist/src/window-state.js +1 -0
  320. package/package.json +4 -2
  321. package/server.json +2 -2
  322. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.0.apk.sha256 +0 -1
  323. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk +0 -0
  324. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk.sha256 +0 -1
  325. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +0 -93
  326. package/dist/src/platform-runtime-apple-resources.js +0 -1
  327. package/dist/src/runner-selector-query.js +0 -1
  328. package/dist/src/snapshot-quality-verdict.js +0 -1
@@ -1 +1 @@
1
- import{y as e}from"./sdk-contracts.js";const t={min:.01,max:1},n={flagKey:`screenshotMaxSize`,cliToken:`--max-size`,envVar:`AGENT_DEVICE_SCREENSHOT_MAX_SIZE`,publicOptionKey:`maxSize`,migration:{screenshot:`screenshot --max-size was removed; use --scale <0.01-1> (or AGENT_DEVICE_SCREENSHOT_SCALE) to downscale proportionally`,record:`record --max-size was removed; recordings capture at native resolution`}};function r(e,t){return t&&Object.hasOwn(t,n.flagKey)?n.migration[e]:void 0}function i(t,r){if(Object.hasOwn(r,n.publicOptionKey)||Object.hasOwn(r,n.flagKey))throw new e(`INVALID_ARGS`,n.migration[t])}const a={selectorInvalid:`CROP_SELECTOR_INVALID`,targetNotFound:`CROP_TARGET_NOT_FOUND`,targetAmbiguous:`CROP_TARGET_AMBIGUOUS`,captureUnreadable:`CROP_CAPTURE_UNREADABLE`,captureIncomplete:`CROP_CAPTURE_INCOMPLETE`,emptyIntersection:`CROP_EMPTY_INTERSECTION`,partialIntersection:`CROP_PARTIAL_INTERSECTION`,targetNotAccepted:`CROP_TARGET_NOT_ACCEPTED`,frameMismatch:`CROP_FRAME_MISMATCH`,pendingPixelIdentityEvidence:`PENDING_PIXEL_IDENTITY_EVIDENCE`},o=[`out`,`overlayRefs`,`screenshotCropOn`,`screenshotPixelDensity`,`screenshotFullscreen`,`screenshotScale`,`screenshotNoStabilize`,`screenshotNormalizeStatusBar`],s=[`screenshotCropOn`,`screenshotPixelDensity`,`screenshotFullscreen`,`screenshotScale`,`screenshotNoStabilize`,`screenshotNormalizeStatusBar`],c=[{key:`screenshotCropOn`,names:[`--crop-on`],type:`string`,usageLabel:`--crop-on <selector-expression>`,usageDescription:`Screenshot: crop the capture to the frame of the selector resolved on the same screen`},{key:`screenshotPixelDensity`,names:[`--pixel-density`],type:`int`,min:1,usageLabel:`--pixel-density <n>`,usageDescription:`Screenshot: output PNG pixel density in pixels per logical point (currently supported on iOS simulators)`},{key:`screenshotFullscreen`,names:[`--fullscreen`,`--full`,`-f`],type:`boolean`,usageLabel:`--fullscreen, --full, -f`,usageDescription:`Screenshot: on web capture the full page; on macOS app sessions capture the full desktop instead of the app window`},{key:`screenshotScale`,names:[`--scale`],type:`number`,min:t.min,max:t.max,usageLabel:`--scale <0.01-1>`,usageDescription:`Screenshot: resize both dimensions by this factor (or use AGENT_DEVICE_SCREENSHOT_SCALE)`},{key:`screenshotNoStabilize`,names:[`--no-stabilize`],type:`boolean`,usageLabel:`--no-stabilize`,usageDescription:`Screenshot: skip Android demo-mode/status-bar stabilization and settle delay for low-latency capture loops`},{key:`screenshotNormalizeStatusBar`,names:[`--normalize-status-bar`],type:`boolean`,usageLabel:`--normalize-status-bar`,usageDescription:`Screenshot: on iOS simulators temporarily normalize status-bar chrome for deterministic screenshot diffs`}],l=[{tokens:[`--fullscreen`,`--full`,`-f`],key:`screenshotFullscreen`},{tokens:[`--no-stabilize`],key:`screenshotNoStabilize`},{tokens:[`--normalize-status-bar`],key:`screenshotNormalizeStatusBar`}],u=[{token:`--pixel-density`,key:`screenshotPixelDensity`,label:`screenshot --pixel-density`}],d=[{token:`--scale`,key:`screenshotScale`,label:`screenshot --scale`,min:t.min,max:t.max}],f=[{token:`--crop-on`,key:`screenshotCropOn`,label:`screenshot --crop-on`}];function p(e){return y({overlayRefs:e?.overlayRefs,cropOn:e?.screenshotCropOn,pixelDensity:e?.screenshotPixelDensity,fullscreen:e?.screenshotFullscreen,scale:e?.screenshotScale,stabilize:!e?.screenshotNoStabilize&&void 0,normalizeStatusBar:e?.screenshotNormalizeStatusBar})}function m(e={}){return y({overlayRefs:e.overlayRefs,screenshotCropOn:e.screenshotCropOn??e.cropOn,screenshotPixelDensity:e.screenshotPixelDensity??e.pixelDensity,screenshotFullscreen:e.screenshotFullscreen??e.fullscreen,screenshotScale:e.screenshotScale,screenshotNoStabilize:e.screenshotNoStabilize??(e.stabilize===!1||void 0),screenshotNormalizeStatusBar:e.screenshotNormalizeStatusBar??e.normalizeStatusBar})}function h(e={}){return m({...e,screenshotScale:e.screenshotScale??e.scale})}function g(n){let{min:r,max:i}=t;if(n.scale!==void 0&&(!Number.isFinite(n.scale)||n.scale<r||n.scale>i))throw new e(`INVALID_ARGS`,`screenshot scale must be between ${r} and ${i}`)}function _(e,t){typeof t?.screenshotPixelDensity==`number`&&e.push(`--pixel-density`,String(t.screenshotPixelDensity)),t?.screenshotFullscreen&&e.push(`--fullscreen`),typeof t?.screenshotScale==`number`&&e.push(`--scale`,String(t.screenshotScale)),t?.screenshotNoStabilize&&e.push(`--no-stabilize`),t?.screenshotNormalizeStatusBar&&e.push(`--normalize-status-bar`)}function v(t){let{args:r,flags:i,index:a}=t,o=r[a];if(o===n.cliToken)throw new e(`INVALID_ARGS`,n.migration.screenshot);return b(o,i,a)??x({args:r,index:a,flags:i,token:o})??S({args:r,index:a,flags:i,token:o})??C({args:r,index:a,flags:i,token:o})??{handled:!1}}function y(e){return Object.fromEntries(Object.entries(e).filter(e=>e[1]!==void 0))}function b(e,t,n){let r=l.find(t=>t.tokens.some(t=>t===e));if(r)return t[r.key]=!0,{handled:!0,nextIndex:n}}function x(t){let n=u.find(e=>e.token===t.token);if(!n)return;let r=Number(t.args[t.index+1]);if(!Number.isInteger(r)||r<1)throw new e(`INVALID_ARGS`,`${n.label} requires a positive integer`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}function S(t){let n=d.find(e=>e.token===t.token);if(!n)return;let r=Number(t.args[t.index+1]);if(!Number.isFinite(r)||r<n.min||r>n.max)throw new e(`INVALID_ARGS`,`${n.label} requires a number from ${n.min} to ${n.max}`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}function C(t){let n=f.find(e=>e.token===t.token);if(!n)return;let r=t.args[t.index+1];if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`${n.label} requires a selector expression`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}export{t as a,v as c,h as d,p as f,a as i,r as l,g as m,s as n,c as o,i as p,o as r,_ as s,n as t,m as u};
1
+ import{C as e}from"./sdk-contracts.js";const t={min:.01,max:1},n={flagKey:`screenshotMaxSize`,cliToken:`--max-size`,envVar:`AGENT_DEVICE_SCREENSHOT_MAX_SIZE`,publicOptionKey:`maxSize`,migration:{screenshot:`screenshot --max-size was removed; use --scale <0.01-1> (or AGENT_DEVICE_SCREENSHOT_SCALE) to downscale proportionally`,record:`record --max-size was removed; recordings capture at native resolution`}};function r(e,t){return t&&Object.hasOwn(t,n.flagKey)?n.migration[e]:void 0}function i(t,r){if(Object.hasOwn(r,n.publicOptionKey)||Object.hasOwn(r,n.flagKey))throw new e(`INVALID_ARGS`,n.migration[t])}const a={selectorInvalid:`CROP_SELECTOR_INVALID`,targetNotFound:`CROP_TARGET_NOT_FOUND`,targetAmbiguous:`CROP_TARGET_AMBIGUOUS`,captureUnreadable:`CROP_CAPTURE_UNREADABLE`,captureIncomplete:`CROP_CAPTURE_INCOMPLETE`,emptyIntersection:`CROP_EMPTY_INTERSECTION`,partialIntersection:`CROP_PARTIAL_INTERSECTION`,targetNotAccepted:`CROP_TARGET_NOT_ACCEPTED`,frameMismatch:`CROP_FRAME_MISMATCH`,pendingPixelIdentityEvidence:`PENDING_PIXEL_IDENTITY_EVIDENCE`},o=[`out`,`overlayRefs`,`screenshotCropOn`,`screenshotPixelDensity`,`screenshotFullscreen`,`screenshotScale`,`screenshotNoStabilize`,`screenshotNormalizeStatusBar`],s=[{key:`screenshotCropOn`,names:[`--crop-on`],type:`string`,usageLabel:`--crop-on <selector-expression>`,usageDescription:`Screenshot: crop the capture to the frame of the selector resolved on the same screen`,projectConfig:!1,recorded:!0},{key:`screenshotPixelDensity`,names:[`--pixel-density`],type:`int`,min:1,usageLabel:`--pixel-density <n>`,usageDescription:`Screenshot: output PNG pixel density in pixels per logical point (currently supported on iOS simulators)`,projectConfig:!0,recorded:!0},{key:`screenshotFullscreen`,names:[`--fullscreen`,`--full`,`-f`],type:`boolean`,usageLabel:`--fullscreen, --full, -f`,usageDescription:`Screenshot: on web capture the full page; on macOS app sessions capture the full desktop instead of the app window`,projectConfig:!0,recorded:!0},{key:`screenshotScale`,names:[`--scale`],type:`number`,min:t.min,max:t.max,usageLabel:`--scale <0.01-1>`,usageDescription:`Screenshot: resize both dimensions by this factor (or use AGENT_DEVICE_SCREENSHOT_SCALE)`,projectConfig:!0,recorded:!0},{key:`screenshotNoStabilize`,names:[`--no-stabilize`],type:`boolean`,usageLabel:`--no-stabilize`,usageDescription:`Screenshot: skip Android demo-mode/status-bar stabilization and settle delay for low-latency capture loops`,projectConfig:!0,recorded:!0},{key:`screenshotNormalizeStatusBar`,names:[`--normalize-status-bar`],type:`boolean`,usageLabel:`--normalize-status-bar`,usageDescription:`Screenshot: on iOS simulators temporarily normalize status-bar chrome for deterministic screenshot diffs`,projectConfig:!0,recorded:!0}],c=[{tokens:[`--fullscreen`,`--full`,`-f`],key:`screenshotFullscreen`},{tokens:[`--no-stabilize`],key:`screenshotNoStabilize`},{tokens:[`--normalize-status-bar`],key:`screenshotNormalizeStatusBar`}],l=[{token:`--pixel-density`,key:`screenshotPixelDensity`,label:`screenshot --pixel-density`}],u=[{token:`--scale`,key:`screenshotScale`,label:`screenshot --scale`,min:t.min,max:t.max}],d=[{token:`--crop-on`,key:`screenshotCropOn`,label:`screenshot --crop-on`}];function f(e){return v({overlayRefs:e?.overlayRefs,cropOn:e?.screenshotCropOn,pixelDensity:e?.screenshotPixelDensity,fullscreen:e?.screenshotFullscreen,scale:e?.screenshotScale,stabilize:!e?.screenshotNoStabilize&&void 0,normalizeStatusBar:e?.screenshotNormalizeStatusBar})}function p(e={}){return v({overlayRefs:e.overlayRefs,screenshotCropOn:e.screenshotCropOn??e.cropOn,screenshotPixelDensity:e.screenshotPixelDensity??e.pixelDensity,screenshotFullscreen:e.screenshotFullscreen??e.fullscreen,screenshotScale:e.screenshotScale,screenshotNoStabilize:e.screenshotNoStabilize??(e.stabilize===!1||void 0),screenshotNormalizeStatusBar:e.screenshotNormalizeStatusBar??e.normalizeStatusBar})}function m(e={}){return p({...e,screenshotScale:e.screenshotScale??e.scale})}function h(n){let{min:r,max:i}=t;if(n.scale!==void 0&&(!Number.isFinite(n.scale)||n.scale<r||n.scale>i))throw new e(`INVALID_ARGS`,`screenshot scale must be between ${r} and ${i}`)}function g(e,t){typeof t?.screenshotPixelDensity==`number`&&e.push(`--pixel-density`,String(t.screenshotPixelDensity)),t?.screenshotFullscreen&&e.push(`--fullscreen`),typeof t?.screenshotScale==`number`&&e.push(`--scale`,String(t.screenshotScale)),t?.screenshotNoStabilize&&e.push(`--no-stabilize`),t?.screenshotNormalizeStatusBar&&e.push(`--normalize-status-bar`)}function _(t){let{args:r,flags:i,index:a}=t,o=r[a];if(o===n.cliToken)throw new e(`INVALID_ARGS`,n.migration.screenshot);return y(o,i,a)??b({args:r,index:a,flags:i,token:o})??x({args:r,index:a,flags:i,token:o})??S({args:r,index:a,flags:i,token:o})??{handled:!1}}function v(e){return Object.fromEntries(Object.entries(e).filter(e=>e[1]!==void 0))}function y(e,t,n){let r=c.find(t=>t.tokens.some(t=>t===e));if(r)return t[r.key]=!0,{handled:!0,nextIndex:n}}function b(t){let n=l.find(e=>e.token===t.token);if(!n)return;let r=Number(t.args[t.index+1]);if(!Number.isInteger(r)||r<1)throw new e(`INVALID_ARGS`,`${n.label} requires a positive integer`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}function x(t){let n=u.find(e=>e.token===t.token);if(!n)return;let r=Number(t.args[t.index+1]);if(!Number.isFinite(r)||r<n.min||r>n.max)throw new e(`INVALID_ARGS`,`${n.label} requires a number from ${n.min} to ${n.max}`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}function S(t){let n=d.find(e=>e.token===t.token);if(!n)return;let r=t.args[t.index+1];if(typeof r!=`string`||r.length===0)throw new e(`INVALID_ARGS`,`${n.label} requires a selector expression`);return t.flags[n.key]=r,{handled:!0,nextIndex:t.index+1}}export{s as a,r as c,f as d,i as f,t as i,p as l,o as n,g as o,h as p,a as r,_ as s,n as t,m as u};
@@ -1 +1 @@
1
- import{h as e}from"./sdk-batch.js";const t=s(`public`),n=s(`internal`),r=s(`local-cli`),i={help:`help`};function a(){return[...Object.values(t),...Object.values(r)].sort()}function o(e){return Object.values(i).includes(e)||Object.values(n).includes(e)?!0:a().includes(e)}function s(t){let n={};for(let[r,i]of e(t))n[r]=i;return n}export{a as i,t as n,o as r,n as t};
1
+ import{g as e}from"./sdk-batch.js";const t=s(`public`),n=s(`internal`),r=s(`local-cli`),i={help:`help`};function a(){return[...Object.values(t),...Object.values(r)].sort()}function o(e){return Object.values(i).includes(e)||Object.values(n).includes(e)?!0:a().includes(e)}function s(t){let n={};for(let[r,i]of e(t))n[r]=i;return n}export{a as i,t as n,o as r,n as t};
@@ -1 +1 @@
1
- import{y as e}from"./sdk-contracts.js";import{t}from"./capture.js";import{D as n,f as r,s as i}from"./registry.js";import{i as a}from"./catalog.js";import{a as o,s}from"./sdk-remote-config.js";import{n as c,t as l}from"./path-resolution.js";import"./file.js";import{r as u}from"./command-schema.js";import d from"node:path";import f from"node:fs";const p=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),m=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),h=x(),g=new Map(h.map(e=>[e.key,e]));function _(e){return g.get(e)}function v(e){return h.filter(t=>t.configurable&&t.supportsCommand(e))}function y(e,t){return _(e)?.supportsCommand(t)??!1}function b(e,t,n,r){return s(w(e),t,n,r)}function x(){let e=new Map;for(let t of n()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of r)t.set(e,new Set([`*`]));for(let e of a()){let n=u(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!p.has(e),env:{names:m.has(e)?[]:[o(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>S(e.key,t.key))}function S(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function C(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function w(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=C(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}function T(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}function E(e){let t=e.env??process.env;return T(T({},j(O(e.cwd,e.cliFlags.config,t))),F(t,e.command))}const D=new Set(`json.platform.target.device.udid.serial.session.sessionLock.activity.launchArgs.launchUrl.remote.deviceHub.testIme.appsFilter.clean.force.stale.relaunch.shutdown.surface.headless.restart.noRecord.record.recordAs.snapshotInteractiveOnly.snapshotDiff.snapshotDepth.snapshotScope.snapshotRaw.snapshotCustomActions.snapshotForceFull.screenshotPixelDensity.screenshotFullscreen.screenshotScale.screenshotNoStabilize.screenshotNormalizeStatusBar.overlayRefs.networkInclude.baseline.threshold.count.pointerCount.fps.quality.hideTouches.recordingScope.intervalMs.delayMs.durationMs.holdMs.jitterPx.pixels.doubleTap.verify.settle.settleQuietMs.clickButton.backMode.pauseMs.pattern.kind.perfTemplate.responseLevel.verbose.cost.timeoutMs.retries.failFast.recordVideo.replayUpdate.replayMaestro.replayFrom.replayPlanDigest.replayKeepSession.findFirst.findLast.batchOnError.batchMaxSteps.retainPaths.retentionMs.shardAll.shardSplit.noLogin`.split(`.`));function O(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:A(r,e,n),required:!0,source:`explicit`}]:[{path:k(n),required:!1,source:`user`},{path:d.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function k(e){return d.join(l(`~`,{env:e}),`.agent-device`,`config.json`)}function A(e,t,n){return c(e,{cwd:t,env:n})}function j(e){let t={};for(let n of e)T(t,M(n));return t}function M(t){let{path:n,required:r}=t;if(!f.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=f.readFileSync(n,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}let a;try{a=JSON.parse(i)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${n}`);return N(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function N(n,r){let a={};for(let[o,s]of Object.entries(n)){let n=o,c=_(n);if(!c)throw o===t.flagKey?new e(`INVALID_ARGS`,`Config key "${o}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${o}" in ${r.label}.`);if(!c.configurable)throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!D.has(n))throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(n===`installSource`){a.installSource=i(s,r.label);continue}a[n]=b(c,s,r.label,o)}return a}const P=new Set([`screenshot`,`record`]);function F(n,r){let i=n[t.envVar];if(r!==null&&P.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of v(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=b(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{T as n,y as r,E as t};
1
+ import{C as e}from"./sdk-contracts.js";import{t}from"./capture.js";import{a as n,r}from"./back-mode.js";import{i}from"./catalog.js";import{a,s as o}from"./sdk-remote-config.js";import{f as s,s as c}from"./registry.js";import{n as l,t as u}from"./path-resolution.js";import"./file.js";import{n as d}from"./command-schema.js";import f from"node:path";import p from"node:fs";const m=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),h=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),g=S(),_=new Map(g.map(e=>[e.key,e]));function v(e){return _.get(e)}function y(e){return g.filter(t=>t.configurable&&t.supportsCommand(e))}function b(e,t){return v(e)?.supportsCommand(t)??!1}function x(e,t,n,r){return o(T(e),t,n,r)}function S(){let e=new Map;for(let t of r()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of s)t.set(e,new Set([`*`]));for(let e of i()){let n=d(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!m.has(e),env:{names:h.has(e)?[]:[a(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>C(e.key,t.key))}function C(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function w(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function T(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=w(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}function E(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}function D(e){let t=e.env??process.env;return E(E({},M(k(e.cwd,e.cliFlags.config,t))),I(t,e.command))}const O=n();function k(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:j(r,e,n),required:!0,source:`explicit`}]:[{path:A(n),required:!1,source:`user`},{path:f.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function A(e){return f.join(u(`~`,{env:e}),`.agent-device`,`config.json`)}function j(e,t,n){return l(e,{cwd:t,env:n})}function M(e){let t={};for(let n of e)E(t,N(n));return t}function N(t){let{path:n,required:r}=t;if(!p.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=p.readFileSync(n,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}let a;try{a=JSON.parse(i)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${n}`);return P(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function P(n,r){let i={};for(let[a,o]of Object.entries(n)){let n=a,s=v(n);if(!s)throw a===t.flagKey?new e(`INVALID_ARGS`,`Config key "${a}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${a}" in ${r.label}.`);if(!s.configurable)throw new e(`INVALID_ARGS`,`Config key "${a}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!O.has(n))throw new e(`INVALID_ARGS`,`Config key "${a}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(n===`installSource`){i.installSource=c(o,r.label);continue}i[n]=x(s,o,r.label,a)}return i}const F=new Set([`screenshot`,`record`]);function I(n,r){let i=n[t.envVar];if(r!==null&&F.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of y(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=x(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{E as n,b as r,D as t};
@@ -1,8 +1,8 @@
1
- import{r as e}from"./rolldown-runtime.js";import{D as t,d as n,f as r,v as i}from"./registry.js";import{fr as a}from"./sdk-batch.js";import{i as o}from"./catalog.js";import{r as s}from"./version.js";import{i as c,r as l}from"./command-schema.js";import{n as u}from"./cli-command-aliases.js";const d=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText on the focused element, eraseText, openLink, hideKeyboard, basic pressKey, and back; selector targets poll until available and support recursive index, childOf, above, below, leftOf, rightOf, containsChild, containsDescendants, points, and optional; outer command labels are metadata, not target selectors.`,'Assertions and navigation: assertVisible, assertNotVisible, assertTrue (literal values and ${VAR} lookups only; "", "false", "0", "null", and "undefined" are falsy, everything else is truthy), extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, clearState, and stopApp.',`Scripts: ordered runScript file/env scripts with http.post, json, and output variables.`],f=[`Runtime: iOS and Android only; launchApp.clearState and standalone clearState support Android and iOS simulators, launch arguments are Apple-only, and other standalone device utility/state commands are unsupported.`,"Expressions: when.true supports boolean literals and maestro.platform comparisons; assertTrue supports literal values and ${VAR} lookups only; repeat.while, evalScript, and broader JavaScript expressions are unsupported.",`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Failure diagnostics: resolved targets and runFlow paths are rendered, while inputText payloads remain hidden; do not place secrets in diagnostic identifiers.`,`Trust: runScript executes trusted scripts, may make http.post network requests, and is not a security sandbox; output keys cannot contain a dot.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function p(){return[`Supported subset:`,...d.map(e=>` - ${e}`),``,`Boundaries:`,...f.map(e=>` - ${e}`)].join(`
2
- `)}function m(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function h(e){return t().filter(t=>t.key===e)}function g(e,t){if(t.usageOverride)return t.usageOverride;let n=(t.positionalArgs??[]).map(m),r=(t.allowedFlags??[]).flatMap(e=>h(e).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`);return[e,...n,...r].join(` `)}function _(){return`agent-device <command> [args] [--json]
1
+ import{r as e}from"./rolldown-runtime.js";import{pr as t}from"./sdk-batch.js";import{r as n}from"./back-mode.js";import{i as r}from"./catalog.js";import{d as i,f as a,v as o}from"./registry.js";import{r as s}from"./version.js";import{n as c,r as l}from"./command-schema.js";import{n as u}from"./cli-command-aliases.js";const d=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText on the focused element, eraseText, openLink, hideKeyboard, basic pressKey, and back; selector targets poll until available and support recursive index, childOf, above, below, leftOf, rightOf, containsChild, containsDescendants, points, and optional; outer command labels are metadata, not target selectors.`,'Assertions and navigation: assertVisible, assertNotVisible, assertTrue (literal values and ${VAR} lookups only; "", "false", "0", "null", and "undefined" are falsy, everything else is truthy), extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, clearState, and stopApp.',`Scripts: ordered runScript file/env scripts with http.post, json, and output variables; evalScript inline expressions run flow-scoped JavaScript and write output.* leaves for later steps.`],f=[`Runtime: iOS and Android only; launchApp.clearState and standalone clearState support Android and iOS simulators, launch arguments are Apple-only, and other standalone device utility/state commands are unsupported.`,"Expressions: evalScript is the only command whose payload is evaluated as JavaScript (flow env and prior output leaves are string-typed); with that exception, fields stay literal or ${VAR} lookup-only — assertTrue supports literals and bare lookups, repeat.while is unsupported, and other expression-shaped payloads fail loud.",`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Failure diagnostics: resolved targets and runFlow paths are rendered, while inputText payloads remain hidden; do not place secrets in diagnostic identifiers.`,`Trust: runScript and evalScript execute flow scripts in-process via node:vm, which is not a security sandbox; runScript may make http.post network requests and its output keys cannot contain a dot. evalScript is refused outright for a flow accepted over the daemon’s remote HTTP surface, since that context can escape to the host.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function p(){return[`Supported subset:`,...d.map(e=>` - ${e}`),``,`Boundaries:`,...f.map(e=>` - ${e}`)].join(`
2
+ `)}function m(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function h(e){return n().filter(t=>t.key===e)}function g(e){if(!e.usageHidden)return e.usageLabel??e.names[0]}function _(e){return(e??[]).flatMap(e=>h(e).map(g).filter(e=>e!==void 0).map(e=>`[${e}]`))}function v(e,t){return[t.usageOverride??[e,...(t.positionalArgs??[]).map(m)].join(` `),..._(t.usageFlags??t.allowedFlags)].join(` `)}function y(){return`agent-device <command> [args] [--json]
3
3
 
4
4
  Automates iOS, Android, macOS, TV, and web apps for AI agents.
5
- All ${o().length} commands: agent-device help commands
5
+ All ${r().length} commands: agent-device help commands
6
6
 
7
7
  Start:
8
8
  When starting a task with a known app, first run:
@@ -25,7 +25,7 @@ Loop:
25
25
  Targets:
26
26
  Copy refs exactly: @e12, @e12~s4. Keep @ and any ~sN pin; refs go stale
27
27
  after mutations. A literal @handle is label="@handle", not a bare ref.
28
- Prefer refs, then id/label/role selectors. Selector keys: ${a.join(` `)}.
28
+ Prefer refs, then id/label/role selectors. Selector keys: ${t.join(` `)}.
29
29
  Coordinates are last resort: after snapshot -i shows no semantic target, or a
30
30
  sparse/AX-unavailable warning says its refs and selectors are invalid.
31
31
  Then screenshot, press <x> <y>, and re-snapshot on the changed screen.
@@ -49,7 +49,7 @@ Guides (agent-device help <topic>):
49
49
  manual-qa / dogfood / validate / debugging / scripting / gestures
50
50
  react-native / react-devtools / cdp / tv / web / macos / remote
51
51
  physical-device / ios-system-ui / maestro
52
- `}var v=e({buildCommandUsageText:()=>F,buildUsageText:()=>O,helpTopicIds:()=>L,resolveHelpTargetUsageText:()=>I});const y=[`Default config files: ~/.agent-device/config.json, ./agent-device.json (project-safe defaults only).`,`Use --config <path> or AGENT_DEVICE_CONFIG for explicit connection/provider defaults; project config cannot select endpoints or credentials.`],b=[{label:`AGENT_DEVICE_SESSION`,description:`Explicit session name`},{label:`AGENT_DEVICE_PLATFORM`,description:`Default platform binding`},{label:`AGENT_DEVICE_SCREENSHOT_SCALE`,description:`Default screenshot scale factor`},{label:`AGENT_DEVICE_SESSION_LOCK`,description:`Bound-session conflict mode`},{label:`AGENT_DEVICE_DAEMON_BASE_URL`,description:`Connect to remote daemon`},{label:`AGENT_DEVICE_DAEMON_AUTH_TOKEN`,description:`Remote daemon service/API token`},{label:`AGENT_DEVICE_CLOUD_BASE_URL`,description:`Bridge/control-plane API origin for cloud auth and /api-keys`}],x=[`agent-device open Settings --platform ios`,`agent-device open https://example.com --platform web`,`agent-device snapshot -i`,`agent-device fill @e3 "test@example.com"`,`agent-device replay ./session.ad`,`agent-device wait absent 'label="Loading..."' 3000`,`agent-device test ./suite --platform android`],S=`Wait failure contract:
52
+ `}var b=e({buildCommandUsageText:()=>L,buildUsageText:()=>A,helpTopicIds:()=>z,resolveHelpTargetUsageText:()=>R});const x=[`Default config files: ~/.agent-device/config.json, ./agent-device.json (project-safe defaults only).`,`Use --config <path> or AGENT_DEVICE_CONFIG for explicit connection/provider defaults; project config cannot select endpoints or credentials.`],S=[{label:`AGENT_DEVICE_SESSION`,description:`Explicit session name`},{label:`AGENT_DEVICE_PLATFORM`,description:`Default platform binding`},{label:`AGENT_DEVICE_SCREENSHOT_SCALE`,description:`Default screenshot scale factor`},{label:`AGENT_DEVICE_SESSION_LOCK`,description:`Bound-session conflict mode`},{label:`AGENT_DEVICE_DAEMON_BASE_URL`,description:`Connect to remote daemon`},{label:`AGENT_DEVICE_DAEMON_AUTH_TOKEN`,description:`Remote daemon service/API token`},{label:`AGENT_DEVICE_CLOUD_BASE_URL`,description:`Bridge/control-plane API origin for cloud auth and /api-keys`}],C=[`agent-device open Settings --platform ios`,`agent-device open https://example.com --platform web`,`agent-device snapshot -i`,`agent-device fill @e3 "test@example.com"`,`agent-device replay ./session.ad`,`agent-device wait absent 'label="Loading..."' 3000`,`agent-device test ./suite --platform android`],w=`Wait failure contract:
53
53
  Read error.details.reason in --json, not the message text.
54
54
  wait_target_absent: a readable capture ran and found no match.
55
55
  wait_target_present: wait absent timed out with matches; details include matches and firstMatch.
@@ -58,7 +58,7 @@ Guides (agent-device help <topic>):
58
58
  wait_deadline_exceeded: a later capture used the remaining budget after an earlier readable one.
59
59
  wait_landmark_identity_mismatch: a replay destination guard found the selector but not the recorded identity.
60
60
  wait_stable_timeout: wait stable never saw a stable UI -- not an absence verdict.
61
- `,C={commands:{summary:`Full command catalog, global flags, configuration, and environment`,body:`agent-device help commands`},"manual-qa":{summary:`Follow manual test scripts with exact interactions and verification`,body:`agent-device help manual-qa
61
+ `,T={commands:{summary:`Full command catalog, global flags, configuration, and environment`,body:`agent-device help commands`},"manual-qa":{summary:`Follow manual test scripts with exact interactions and verification`,body:`agent-device help manual-qa
62
62
 
63
63
  Use this when asked to follow a manual QA script, test case, checklist, acceptance flow, or user-provided instructions.
64
64
 
@@ -100,7 +100,7 @@ Recovery:
100
100
  Sparse or recovered accessibility snapshot: use screenshot as visual truth, leave the bad screen if needed, then retry snapshot -i.
101
101
  Non-hittable success hint: verify with the settled diff or snapshot; retarget by a better ref/selector if the UI did not change.
102
102
 
103
- ${S}`},maestro:{summary:`Supported Maestro YAML commands, grammar, and runtime boundaries`,body:`agent-device help maestro
103
+ ${w}`},maestro:{summary:`Supported Maestro YAML commands, grammar, and runtime boundaries`,body:`agent-device help maestro
104
104
 
105
105
  Run Maestro compatibility flows with replay <flow.yaml> --maestro or test <path> --maestro. Bind an iOS or Android target with --platform or an existing session.
106
106
 
@@ -126,10 +126,10 @@ Bootstrap:
126
126
 
127
127
  Snapshots and refs:
128
128
  snapshot reads visible state; snapshot -i gets current interactive refs only -- fast path before interaction. Default text is token-efficient; --raw/--json for full provider tree.
129
- Legend: @e12 [button] label="Add to cart" enabled hittable -> press @e12. [off-screen below] -> scroll down (a hint, not a ref).
129
+ Legend: @e12 [button] label="Add to cart" enabled hittable -> press @e12. [off-screen below] -> scroll down --until (a hint, not a ref).
130
130
  Refs stay valid until you press/click/fill/type/scroll/back/wait-for-async-UI, or otherwise change app state; open/--relaunch clears the stored snapshot outright.
131
131
  Prefer --settle and its diff when it shows next target; refresh with snapshot -i only when you did not settle, it reported not settled, or output lacks what you need. A known selector/label after a mutation is often enough, since interaction commands refresh state internally.
132
- Truncated preview: snapshot -s @e12 (the current concrete ref), not get text. Missing list target: scroll down/up then snapshot -i. TV/D-pad focus: help tv.
132
+ Truncated preview: snapshot -s @e12 (the current concrete ref), not get text. Missing target: scroll <dir> --until <selector>. TV/D-pad focus: help tv.
133
133
 
134
134
  Selectors:
135
135
  id="field-email", label="Allow", role=button label="Search" -- not bare role keys (button="Search"); no CSS selectors/--selector/--text/raw x-y when refs/selectors exist.
@@ -147,7 +147,7 @@ Session ordering:
147
147
  Stateful commands (open/press/fill/type/scroll/back/alert/replay/batch/close) run serially within one session. Parallelize only read-only commands, or separate sessions/devices.
148
148
 
149
149
  Read-only and waits:
150
- ${S}
150
+ ${w}
151
151
  snapshot/get/is/find answer read-only questions; snapshot -i is for refs. --settle confirms local UI quieted; delayed results use wait text "Expected result" or wait <selector> instead of polling; strict disappearance uses wait absent <selector>.
152
152
  wait stable [quietMs] [timeoutMs] (defaults 500/10000) is the fallback for open/relaunch/navigation, or an intentionally-unsettled mutation -- not after a --settle whose diff already shows the change. Ambiguous find: add --first or --last.
153
153
 
@@ -211,7 +211,7 @@ Batch:
211
211
  agent-device test ./e2e/maestro --maestro --device udid1,emulator-5554 --shard-all 2
212
212
 
213
213
  Recording:
214
- record start/stop. Default scope is app (needs an active open session); use --scope device/system for whole-screen capture spanning multiple apps/home/settings. --quality medium|high on Android and Apple targets. stop burns touch overlays into the video by default; --hide-touches skips that for the fastest raw recording, and is recommended for gesture-heavy iOS simulator proof videos since overlay timing depends on a stable runner session. Android adb screenrecord has a 180s limit, so long Android recordings return as multiple MP4 chunks while the daemon stays alive; after a daemon restart, record stop recovers only manifest-owned chunks.
214
+ record start/stop. Default scope is app (needs an active open session); use --scope device/system for whole-screen capture spanning multiple apps/home/settings. --quality medium|high on Android and Apple targets. stop burns touch overlays into the video by default; --hide-touches skips that for the fastest raw recording, and is recommended for gesture-heavy iOS simulator proof videos since overlay timing depends on a stable runner session. Android adb screenrecord has a 180s limit, so long Android recordings return as multiple MP4 chunks while the daemon stays alive; after a daemon restart, record stop recovers only manifest-owned chunks. record stop is safe to repeat: if its request window ended while the daemon was still exporting, running it again in that session returns the completed recording instead of starting a second one.
215
215
  Tracing: trace start ./trace.log, trace stop ./trace.log (path is positional, not --path).`},gestures:{summary:`Full multi-touch gesture shapes and platform quirks`,body:`agent-device help gestures
216
216
 
217
217
  Full command shapes and platform quirks for touch/pointer gestures beyond scroll/swipe. Read this when a task needs multi-touch, a repeated gesture series, or exact per-platform verification.
@@ -222,10 +222,12 @@ Shapes:
222
222
  agent-device swipe 320 500 40 500 --count 8 --pause-ms 30 --pattern ping-pong
223
223
  agent-device gesture pan 200 420 0 -80 500
224
224
  agent-device gesture pan 200 420 80 -40 700 --pointer-count 2
225
+ agent-device scroll down --until 'id=submit'
225
226
  agent-device gesture fling right 200 420 180
226
227
  agent-device gesture pinch 0.5 200 400
227
228
  agent-device gesture rotate 35 200 420
228
229
  agent-device gesture transform 200 420 80 -40 2 35 700
230
+ scroll <dir> --until <selector> repeats scroll-and-check passes until that element is on screen, then stops: one request instead of a scroll-then-snapshot loop, and it stops on the target rather than overshooting it. It reports the passes it spent, fails when the content runs out first, and is refused on top/bottom, which already stop themselves.
229
231
  longpress accepts coordinates, @refs, or selectors; prefer @ref/selector, coordinates only as a fallback. Duration and gesture scale/center are positional. gesture pan is one finger by default; add --pointer-count 2 for a parallel two-finger pan. Keep count/pause/pattern on one swipe: --count (cap 200), --pause-ms (cap 10000ms), --pattern ping-pong; the combined swipe/pause schedule is capped at 60000ms.
230
232
  For repeated iOS smoke checks: press <x> <y> --count <n> --jitter-px <n> for tap series, swipe <x1> <y1> <x2> <y2> --count <n> for drag series.
231
233
 
@@ -460,6 +462,8 @@ Rules:
460
462
  For cross-platform validation with explicit device selectors, use separate sessions/devices and restart react-devtools between platforms.
461
463
  Remote Android and iOS bridge runs normally through agent-device react-devtools; the CLI keeps the needed local service tunnel alive until agent-device react-devtools stop or disconnect. Expo support depends on the SDK's bundled React Native runtime.
462
464
  Remote iOS apps attempt the legacy React DevTools websocket during JavaScript startup. If the app was already open before react-devtools start, run open <bundle-id> --platform ios --relaunch, then wait --connected.
465
+ React Native 0.87+ needs agent-react-devtools installed as a dev dependency of the app project, then a one-time npx agent-react-devtools init there and a rebundle, before wait --connected can succeed. The npm exec package this wrapper runs is temporary and does not install it into the app. Run npx agent-react-devtools uninit when the task is done unless the user wants to keep the setup.
466
+ Verify an attached app with status or wait --connected before trusting any result. With 0 connected apps, count, errors, and get tree return empty results that look like a clean pass.
463
467
 
464
468
  Example:
465
469
  agent-device react-devtools status
@@ -479,7 +483,7 @@ Example:
479
483
  Device busy and ownership:
480
484
  DEVICE_IN_USE has two flavors. "already in use by session X" is this daemon: reuse it with --session X, or run close --session X first. "owned by session X in workspace Y" is another worktree's daemon holding the host-global device claim: it is never retriable — run the error's exact recovery command instead of retrying.
481
485
  Inspect ownership without any daemon: agent-device device status (add --stale for proven-dead owners; settle and release those with agent-device device release --stale). devices marks rows that are claimed, so pick an unclaimed device instead of contending.
482
- A live foreign owner is released only by closing its session from its own workspace or stopping its daemon: agent-device daemon stop --state-dir <owner state dir> (the error names the state dir). Never recover by hunting PIDs with ps/kill. boot/install/shutdown take the same claims as open and refuse foreign-claimed devices identically.
486
+ A live foreign owner is released by closing its session from its own workspace or stopping its daemon: agent-device daemon stop --state-dir <owner state dir> (the error names the state dir). The device itself can settle a claim: when it rebooted after that claim was taken, its app, runner, and accessibility session were destroyed, so open reconciles the owner's resources, takes the claim, and reports the release in warnings. Never recover by hunting PIDs with ps/kill. boot/install/shutdown take the same claims as open and refuse foreign-claimed devices identically; they do not ask the device about its boot.
483
487
 
484
488
  Use snapshot, screenshot, logs, network, perf frames, and perf memory for device/app runtime evidence. Use react-devtools when component internals or React rendering behavior matters.`},cdp:{summary:`React Native CDP targets, JS heap snapshots, and leak triage`,body:`agent-device help cdp
485
489
 
@@ -916,7 +920,7 @@ Rules:
916
920
  Findings must come from observed runtime behavior, not source reads.
917
921
  After each mutation, use the --settle diff as evidence when available; otherwise re-snapshot.
918
922
  Wait timeouts are integer milliseconds in the trailing positional: agent-device wait 'role=tab' 10000. Do not write duration suffixes such as 10s.
919
- scroll takes a selector-less direction+amount form: agent-device scroll down 3. Use --settle to wait for the UI to go quiet and get the settled diff.
923
+ scroll takes a selector-less direction+amount form: agent-device scroll down 0.8. One gesture cannot travel further than 0.8 of the viewport axis, so a larger amount saturates rather than covering more ground; to cross several screens use agent-device scroll down --until <selector> or scroll bottom. Use --settle to wait for the UI to go quiet and get the settled diff.
920
924
  Keep commands in the report reproducible; use selectors or refs from fresh snapshots, not guessed coordinates.
921
925
  Prefer refs for exploration and selectors for deterministic replay.
922
926
  Use logs, network, screenshot --overlay-refs, trace, perf frames, perf memory, native profiles, or react-devtools only when they add evidence to a specific issue.
@@ -955,33 +959,33 @@ Evidence:
955
959
 
956
960
  Report:
957
961
  Summarize what changed, exact validation commands, pass/fail observations, artifact paths, and residual risk.
958
- If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function w(e,t,n){let r=n.endsWith(`?`),i=r?n.slice(0,-1):n,a=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i),o=a||t.usageOverride!==void 0&&t.usageOverride.startsWith(`${e} ${i}`);return r?a?`[${i}]`:o?i:`[${i}]`:o?i:`<${i}>`}function T(e,t){return t.listUsageOverride?t.listUsageOverride:[e,...(t.positionalArgs??[]).map(n=>w(e,t,n))].join(` `)}function E(){return _()}function D(){return`agent-device help commands
962
+ If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function E(e,t,n){let r=n.endsWith(`?`),i=r?n.slice(0,-1):n,a=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i),o=a||t.usageOverride!==void 0&&t.usageOverride.startsWith(`${e} ${i}`);return r?a?`[${i}]`:o?i:`[${i}]`:o?i:`<${i}>`}function D(e,t){return t.listUsageOverride?t.listUsageOverride:[e,...(t.positionalArgs??[]).map(n=>E(e,t,n))].join(` `)}function O(){return y()}function k(){return`agent-device help commands
959
963
 
960
964
  Full command catalog. Use agent-device help <command> for exact flags and behavior.
961
965
 
962
- ${P(o().map(e=>{let t=l(e);return{name:e,schema:t,usage:T(e,t)}}))}
966
+ ${I(r().map(e=>{let t=c(e);return{name:e,schema:t,usage:D(e,t)}}))}
963
967
 
964
- ${j(`Device Selection (shared by device commands; help <command> lists each command's flags):`,k(n))}
968
+ ${N(`Device Selection (shared by device commands; help <command> lists each command's flags):`,j(i))}
965
969
 
966
- ${j(`Global Flags:`,k(r))}
970
+ ${N(`Global Flags:`,j(a))}
967
971
 
968
- ${N(`Configuration:`,y)}
972
+ ${F(`Configuration:`,x)}
969
973
 
970
- ${M(`Environment:`,b)}
974
+ ${P(`Environment:`,S)}
971
975
 
972
- ${N(`Examples:`,x)}
973
- `}function O(){return E()}function k(e){return t().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function A(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function j(e,t){return M(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function M(e,t){if(t.length===0)return`${e}\n (none)`;let n=Math.max(...t.map(e=>Math.min(e.label.length,26)))+2,r=[e];for(let e of t){let t=e.label.length<=26?e.label.padEnd(n):`${e.label} `;r.push(` ${t}${e.description}`)}return r.join(`
974
- `)}function N(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
975
- `)}function P(e){return M(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function F(e){let t=R(e);if(t)return t;let n=c(e);if(!n)return null;let r=g(e,n),a=A(k(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),o=[];a.length>0&&o.push(j(`Command flags:`,a));let s=o.length>0?`\n\n${o.join(`
976
+ ${F(`Examples:`,C)}
977
+ `}function A(){return O()}function j(e){return n().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function M(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function N(e,t){return P(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function P(e,t){if(t.length===0)return`${e}\n (none)`;let n=Math.max(...t.map(e=>Math.min(e.label.length,26)))+2,r=[e];for(let e of t){let t=e.label.length<=26?e.label.padEnd(n):`${e.label} `;r.push(` ${t}${e.description}`)}return r.join(`
978
+ `)}function F(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
979
+ `)}function I(e){return P(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function L(e){let t=B(e);if(t)return t;let n=l(e);if(!n)return null;let r=v(e,n),i=M(j(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),a=[];i.length>0&&a.push(N(`Command flags:`,i));let s=a.length>0?`\n\n${a.join(`
976
980
 
977
981
  `)}`:``;return`Usage:
978
982
  agent-device ${r}
979
983
 
980
- ${i(n.text)}${s}
981
- `}function I(e){return F(u(e))}function L(){return Object.keys(C)}function R(e){let t=C[e];return t?`${z(e,e===`commands`?D():t.body)}
984
+ ${o(n.text)}${s}
985
+ `}function R(e){return L(u(e))}function z(){return Object.keys(T)}function B(e){let t=T[e];return t?`${V(e,e===`commands`?k():t.body)}
982
986
 
983
987
  Related:
984
988
  agent-device help <command> command-specific flags
985
989
  agent-device help manual-qa routine QA loop
986
990
  agent-device help workflow full automation reference
987
- `:null}function z(e,t){let n=`agent-device help ${e}`;return t.startsWith(n)?`agent-device ${s()} — ${e}${t.slice(n.length)}`:t}export{I as i,v as n,L as r,O as t};
991
+ `:null}function V(e,t){let n=`agent-device help ${e}`;return t.startsWith(n)?`agent-device ${s()} — ${e}${t.slice(n.length)}`:t}export{R as i,b as n,z as r,A as t};
package/dist/src/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import{N as e,O as t,b as n,y as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{D as l,E as u,x as d}from"./registry.js";import{n as f,r as p}from"./agent-device-client.js";import{s as m,t as h}from"./sdk-batch.js";import{i as g,r as _,t as v}from"./catalog.js";import{a as y,i as b,l as ee,n as x,o as te,r as S}from"./diagnostics.js";import{d as ne}from"./exec.js";import{n as re}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as ie}from"./version.js";import{n as ae}from"./config.js";import{t as oe}from"./session-artifact-paths.js";import{i as se,n as ce,t as le}from"./command-schema.js";import{n as C,r as w,t as ue}from"./cli-config.js";import{t as de}from"./update-check.js";import{n as fe,r as pe,t as me}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{D as he,E as ge,O as _e,d as ve,k as ye,m as be,n as xe,w as Se}from"./connection-runtime.js";import{i as Ce}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as D}from"node:url";const O=`open <app> --relaunch`,k={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 A(e){if(e.length<=2)return[];let t=g(),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=we(e),i=t.map(t=>({name:t,distance:Te(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 we(e){return e.length<4?1:e.length<=6?2:3}function Te(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):Ee(e,t)}function Ee(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 j(e){let t=e.toLowerCase(),n=k[t]?.example;if(n)return n;let r=A(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const De=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),Oe=new Set([`--session-locked`,`--session-lock-conflicts`]);function ke(e){return De.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:Oe.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 M(e){let t={json:!1,help:!1,version:!1},n=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){n?a.push(l):(i=l,n=L(l));continue}if(Ne(n)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){n?a.push(l):(i=l,n=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(je(n,f))continue;let m=Pe(f,n);if(Me(n,m)){a.push(l);continue}if(!m){if(ze(n,a,l)){n?a.push(l):n=l;continue}throw new r(`INVALID_ARGS`,ke(f))}let h=Le(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;s.push({key:m.key,token:f})}return Ae(i,t),{command:n,positionals:a,flags:t,warnings:o,providedFlags:s}}function Ae(e,t){if(e)for(let n of me(e)?.impliedFlags??[])t[n]=!0}function je(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Me(e,t){return e===`react-devtools`?!t||!w(t.key,e):!1}function Ne(e){return e===`cdp`}function Pe(e,t){let n=l().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??u(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return u(e)}function Fe(e,t){let n=t?.strictFlags??!0,i=[...e.warnings],a=C({json:!1,help:!1,version:!1},t?.defaultFlags??{});if(C(a,e.flags),e.command&&!_(e.command)&&!a.help){let t=j(e.command),n=t?`Unknown command: ${e.command}. Did you mean ${t}?`:`Unknown command: ${e.command}`;throw new r(`INVALID_ARGS`,n)}let o=e.providedFlags.filter(t=>!w(t.key,e.command));if(o.length>0){let t=o.map(e=>e.token),s=He(e.command,t);if(n)throw new r(`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]);Ie(e),le(e.command,a);let s=Ve({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(ce(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new r(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Ie(e){if(e.command!==`back`)return;let t=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(t.map(e=>e.token)).size<=1))throw new r(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Le(e,t,n,i){if(e.setValue!==void 0){if(n!==void 0)throw new r(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(n!==void 0)throw new r(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(n!==void 0){if(n.trim().length===0)throw new r(`INVALID_ARGS`,`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Re(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=n??i;if(a===void 0||n===void 0&&F(a))throw new r(`INVALID_ARGS`,`Flag ${t} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:n===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new r(`INVALID_ARGS`,`Invalid ${P(t)}: ${a}`);return{value:a,consumeNext:n===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 r(`INVALID_ARGS`,`Invalid ${P(t)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:n===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return u(t)!==void 0}function Re(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 ze(e,t,n){if(!Be(n)||!e)return!1;let r=se(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Be(e){return/^-\d+(\.\d+)?$/.test(e)}function Ve(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 He(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 I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function Ue(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(e){let t=pe(e);if(t)throw new r(`INVALID_ARGS`,t);return fe(e)}function We(){return{renderedToStderr:!1}}function Ge(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function Ke(e){return re(e)}const qe={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,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand};async function R(e){let t={...e.flags},n=qe[e.command];return n&&await(await n())({...e,flags:t})?!0:Ke(e.command)?await Je({...e,command:e.command,flags:t}):!1}async function Je(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function Ye(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function Xe(e){return e===`ios-instance`}function Ze(e){return e[0]===`wait`&&e.includes(`--connected`)}function Qe(e,t,n){n===0||!Ze(e)||!Xe(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 z(e,t,n){return n||(e.push(t),``)}function B(e){if(!e?.metroProxyBaseUrl||!he(e.leaseBackend))return null;let t=[],n={serverBaseUrl:z(t,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:z(t,`metroBearerToken`,e.metroBearerToken),tenantId:z(t,`tenant`,e.tenant),runId:z(t,`runId`,e.runId),leaseId:z(t,`leaseId`,e.leaseId)};if(t.length>0)throw new r(`INVALID_ARGS`,`react-devtools remote bridge requires ${t.join(`, `)}.`,{missing:t});return n}async function $e(e,t,n){let{flags:r}=t,i=B(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 ye({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await _e({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 et(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?ve(n.leaseProvider).supportsDirectPortReverse&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function tt(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await $e(e,t,async()=>(et(e,t)&&await t.configureDirectPortReverse?.(),(await ne(`npm`,Ye(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return Qe(e,t.flags,i),i}const V=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,nt=`${h} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function rt(e){let t;try{t=JSON.parse(e)}catch{throw new r(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(t)||t.length===0)throw new r(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return t.map((e,t)=>it(e,t+1))}function it(e,t){let n=a(e,t,V),i=[`positionals`,`flags`].filter(e=>e in n);if(i.length>0){let e=i.map(e=>`"${e}"`).join(`, `);throw new r(`INVALID_ARGS`,`Batch step ${t} uses removed field(s): ${e}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:V})}d(n,[`command`,`input`,`runtime`],`Batch step ${t}`,V);let s=o(n.runtime,t);return{command:m(n.command,t,nt),input:c(n,t,V),...s===void 0?{}:{runtime:s}}}function H(e,t={}){let n=U(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function U(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??ot(t.AGENT_DEVICE_PLATFORM),r=ct(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:at(e.policyOverrides,t,r)}}function at(e,t,n){let r=e?.sessionLock??st(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function ot(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`ios`||t===`android`||t===`apple`)return t;throw new r(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function st(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`reject`||t===`strip`)return t;throw new r(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function ct(e){return typeof e==`string`&&e.trim().length>0}function lt(e,t){let n=M(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=ut(n.command)?be({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=C(ue({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Fe(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function ut(e){return e!==null}v.runtime;async function dt(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const W=(e,t={})=>import(`./error.js`).then(({printHumanError:n})=>n(e,t)),G=e=>import(`./json.js`).then(({printJson:t})=>t(e)),ft={sendToDaemon:p},pt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),mt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function K(e,t=ft){let n=x(),r=ie(),i=wt(e),a=e.includes(`--json`),o=Lt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await ee({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await ht(e,{version:r,jsonRequested:a,debugEnabled:i}),l=Z(s,o.providedFlags),u=await gt(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});q(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await T(await _t(u,t));return}if(s===`web`){let{runWebCommand:e}=await import(`./web.js`);await T(await e(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(de({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await vt(u,t),q(u.effectiveFlags),s===`cdp`){await T(await ge(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=yt(u);let e=await bt(u),n=We();await xt(u,f(J(u),{transport:It({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await St(e,u,d)}finally{d&&d()}})}function q(e){e.daemonAuthToken&&te(e.daemonAuthToken)}async function ht(e,n){let i;try{i=lt(e,{cwd:process.cwd(),env:process.env})}catch(e){S({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let r=t(e,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return n.jsonRequested?await G({success:!1,error:r}):await W(r,{showDetails:n.debugEnabled}),T(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${n.version}\n`),T(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return await W(new r(`INVALID_ARGS`,`help accepts at most one command.`)),T(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await I()}\n`),T(0);let t=await Ue(e);return t?(process.stdout.write(t),T(0)):(await W(new r(`INVALID_ARGS`,Tt(e))),process.stdout.write(`${await I()}\n`),T(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await I()}\n`),T(1))}async function gt(e,r){let i=new Set(e.providedFlags.map(e=>e.key));try{let t=U({policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),n=t.lockPolicy?{...e.flags}:H(e.flags,{policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),a=ae(n.stateDir),o=n.session??`default`,s=kt({command:r.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:n.remoteConfig,hasResolvedSession:n.session!==void 0}),c=s?Pt(n,s.flags,i):n;return{...r,binding:t,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=n(i),o=t(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return e.flags.json?await G({success:!1,error:o}):await W(o,{showDetails:r.debugOutputEnabled}),T(1)}}async function _t(t,n){let{daemonAuthToken:r,...i}=t.effectiveFlags;return await tt(t.positionals,{flags:{...i,leaseProvider:t.connectionDefaults?.connection?.leaseProvider},stateDir:t.daemonPaths.baseDir,session:t.effectiveFlags.session??t.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await dt({route:`react-devtools`,command:v.runtime,request:{positionals:[`port-reverse`],flags:{...i,leaseProvider:t.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:t.effectiveFlags.session??t.sessionName},transport:n.sendToDaemon,transportOptions:{authToken:r}});a.ok||e(a.error)}})}async function vt(e,t){if(e.command===`batch`){if(e.positionals.length>0)throw new r(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=Dt(e.flags)}if(jt(e.command)&&(e.effectiveFlags=(await Ce({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&At(e.command)){let n=f(J(e),{transport:Q(t.sendToDaemon)}),r=await xe({command:e.command,flags:e.effectiveFlags,client:n,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Ft(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Mt({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.
3
- `)}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 yt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Rt(e.daemonPaths.logPath):null}async function bt(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 xt(e,t,n,i){let{command:a,positionals:o,effectiveFlags:s}=e;if(a===`batch`){if(!e.parsedBatchSteps)throw new r(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let c=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:H(t.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await R({command:a,positionals:o,flags:{...s,batchSteps:c},client:t,debug:e.debugOutputEnabled,replayTestReporterRuntime:n,commandProgress:i}))return}else if(a===`runtime`)throw new r(`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 R({command:a,positionals:o,flags:s,client:t,debug:e.debugOutputEnabled,replayTestReporterRuntime:n,commandProgress:i}))return;throw new r(`INVALID_ARGS`,Et(a))}async function St(e,r,i){let a=n(e),o=t(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});if(r.command===`close`&&Ot(a)){r.effectiveFlags.json&&await G({success:!0,data:{closed:`session`,source:`no-daemon`}});return}r.effectiveFlags.json?await G({success:!1,error:o}):(await W(o,{showDetails:r.debugOutputEnabled}),r.debugOutputEnabled&&Ct(r,o)),i&&i(),await T(1)}const Y=64e3;function Ct(e,t){if(!e.effectiveFlags.daemonBaseUrl){X(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&X(`remote diagnostics`,oe(e.daemonPaths.baseDir,n))}function X(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
1
+ import{C as e,L as t,M as n,w as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{n as l,r as u}from"./agent-device-client.js";import{s as d,t as f,u as p}from"./sdk-batch.js";import{n as m,r as h}from"./back-mode.js";import{i as g,r as _,t as v}from"./catalog.js";import{x as ee}from"./registry.js";import{a as y,i as b,l as x,n as te,o as ne,r as S}from"./diagnostics.js";import{f as re}from"./exec.js";import{n as ie}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as ae}from"./version.js";import{n as oe}from"./config.js";import{t as se}from"./session-artifact-paths.js";import{r as ce,t as le}from"./command-schema.js";import{n as C,r as w,t as ue}from"./cli-config.js";import{t as de}from"./update-check.js";import{n as fe,r as pe,t as me}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{D as he,E as ge,O as _e,d as ve,k as ye,m as be,n as xe,w as Se}from"./connection-runtime.js";import{i as Ce}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as D}from"node:url";const O=`open <app> --relaunch`,k={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 A(e){if(e.length<=2)return[];let t=g(),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=we(e),i=t.map(t=>({name:t,distance:Te(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 we(e){return e.length<4?1:e.length<=6?2:3}function Te(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):Ee(e,t)}function Ee(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 j(e){let t=e.toLowerCase(),n=k[t]?.example;if(n)return n;let r=A(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const De=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),Oe=new Set([`--session-locked`,`--session-lock-conflicts`]);function ke(e){return De.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:Oe.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 M(t){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<t.length;o+=1){let l=t[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ne(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=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(je(r,f))continue;let m=Pe(f,r);if(Me(r,m)){a.push(l);continue}if(!m){if(ze(r,a,l)){r?a.push(l):r=l;continue}throw new e(`INVALID_ARGS`,ke(f))}let h=Le(m,f,p,t[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 Ae(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Ae(e,t){if(e)for(let n of me(e)?.impliedFlags??[])t[n]=!0}function je(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Me(e,t){return e===`react-devtools`?!t||!w(t.key,e):!1}function Ne(e){return e===`cdp`}function Pe(e,t){let n=h().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??m(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return m(e)}function Fe(t,n){let r=n?.strictFlags??!0,i=[...t.warnings],a=C({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(C(a,t.flags),t.command&&!_(t.command)&&!a.help){let n=j(t.command),r=n?`Unknown command: ${t.command}. Did you mean ${n}?`:`Unknown command: ${t.command}`;throw new e(`INVALID_ARGS`,r)}let o=t.providedFlags.filter(e=>!w(e.key,t.command));if(o.length>0){let n=o.map(e=>e.token),s=He(t.command,n);if(r)throw new e(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let e of Object.keys(a))a[e]!==void 0&&(w(e,t.command)||delete a[e]);Ie(t),p(t.command,a);let s=Ve({command:t.command,positionals:t.positionals,flags:a,warnings:i});if(le(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new e(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Ie(t){if(t.command!==`back`)return;let n=t.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new e(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Le(t,n,r,i){if(t.setValue!==void 0){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:t.setValue,consumeNext:!1}}if(t.type===`boolean`){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(t.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new e(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Re(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new e(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(t.type===`string`)return{value:a,consumeNext:r===void 0};if(t.type===`enum`){if(!t.enumValues?.includes(a))throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof t.min==`number`&&o<t.min||typeof t.max==`number`&&o>t.max)throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:t.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return m(t)!==void 0}function Re(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 ze(e,t,n){if(!Be(n)||!e)return!1;let r=ce(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Be(e){return/^-\d+(\.\d+)?$/.test(e)}function Ve(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 He(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 I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function Ue(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(t){let n=pe(t);if(n)throw new e(`INVALID_ARGS`,n);return fe(t)}function We(){return{renderedToStderr:!1}}function Ge(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function Ke(e){return ie(e)}const qe={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,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand};async function R(e){let t={...e.flags},n=qe[e.command];return n&&await(await n())({...e,flags:t})?!0:Ke(e.command)?await Je({...e,command:e.command,flags:t}):!1}async function Je(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function Ye(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function Xe(e){return e===`ios-instance`}function Ze(e){return e[0]===`wait`&&e.includes(`--connected`)}function Qe(e,t,n){n===0||!Ze(e)||!Xe(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 z(e,t,n){return n||(e.push(t),``)}function B(t){if(!t?.metroProxyBaseUrl||!he(t.leaseBackend))return null;let n=[],r={serverBaseUrl:z(n,`metroProxyBaseUrl`,t.metroProxyBaseUrl),bearerToken:z(n,`metroBearerToken`,t.metroBearerToken),tenantId:z(n,`tenant`,t.tenant),runId:z(n,`runId`,t.runId),leaseId:z(n,`leaseId`,t.leaseId)};if(n.length>0)throw new e(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function $e(e,t,n){let{flags:r}=t,i=B(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 ye({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await _e({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 et(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?ve(n.leaseProvider).supportsDirectPortReverse&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function tt(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await $e(e,t,async()=>(et(e,t)&&await t.configureDirectPortReverse?.(),(await re(`npm`,Ye(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return Qe(e,t.flags,i),i}const V=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,nt=`${f} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function rt(t){let n;try{n=JSON.parse(t)}catch{throw new e(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new e(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return n.map((e,t)=>it(e,t+1))}function it(t,n){let r=a(t,n,V),i=[`positionals`,`flags`].filter(e=>e in r);if(i.length>0){let t=i.map(e=>`"${e}"`).join(`, `);throw new e(`INVALID_ARGS`,`Batch step ${n} uses removed field(s): ${t}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:V})}ee(r,[`command`,`input`,`runtime`],`Batch step ${n}`,V);let s=o(r.runtime,n);return{command:d(r.command,n,nt),input:c(r,n,V),...s===void 0?{}:{runtime:s}}}function H(e,t={}){let n=U(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function U(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??ot(t.AGENT_DEVICE_PLATFORM),r=ct(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:at(e.policyOverrides,t,r)}}function at(e,t,n){let r=e?.sessionLock??st(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function ot(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new e(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${t}. Use ios, android, or apple.`)}}function st(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new e(`INVALID_ARGS`,`Invalid session lock mode: ${t}. Use reject or strip.`)}}function ct(e){return typeof e==`string`&&e.trim().length>0}function lt(e,t){let n=M(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=ut(n.command)?be({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=C(ue({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Fe(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function ut(e){return e!==null}v.runtime;async function dt(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const W=(e,t={})=>import(`./error.js`).then(({printHumanError:n})=>n(e,t)),G=e=>import(`./json.js`).then(({printJson:t})=>t(e)),ft={sendToDaemon:u},pt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),mt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function K(e,t=ft){let n=te(),r=ae(),i=wt(e),a=e.includes(`--json`),o=Lt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await x({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await ht(e,{version:r,jsonRequested:a,debugEnabled:i}),u=Z(s,o.providedFlags),d=await gt(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:u});q(d.effectiveFlags);let f=null;try{if(s===`react-devtools`){await T(await _t(d,t));return}if(s===`web`){let{runWebCommand:e}=await import(`./web.js`);await T(await e(c,{flags:d.effectiveFlags,stateDir:d.daemonPaths.baseDir}));return}if(de({command:s,currentVersion:r,stateDir:d.daemonPaths.baseDir,flags:d.effectiveFlags}),await vt(d,t),q(d.effectiveFlags),s===`cdp`){await T(await ge(c,{flags:d.effectiveFlags,runtime:d.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}f=yt(d);let e=await bt(d),n=We();await xt(d,l(J(d),{transport:It({command:s,flags:d.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await St(e,d,f)}finally{f&&f()}})}function q(e){e.daemonAuthToken&&ne(e.daemonAuthToken)}async function ht(t,r){let i;try{i=lt(t,{cwd:process.cwd(),env:process.env})}catch(e){S({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let t=n(e,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return r.jsonRequested?await G({success:!1,error:t}):await W(t,{showDetails:r.debugEnabled}),T(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),T(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return await W(new e(`INVALID_ARGS`,`help accepts at most one command.`)),T(1);let t=a?i.positionals[0]:i.command;if(!t)return process.stdout.write(`${await I()}\n`),T(0);let n=await Ue(t);return n?(process.stdout.write(n),T(0)):(await W(new e(`INVALID_ARGS`,Tt(t))),process.stdout.write(`${await I()}\n`),T(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await I()}\n`),T(1))}async function gt(e,t){let i=new Set(e.providedFlags.map(e=>e.key));try{let n=U({policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),r=n.lockPolicy?{...e.flags}:H(e.flags,{policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),a=oe(r.stateDir),o=r.session??`default`,s=kt({command:t.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?Pt(r,s.flags,i):r;return{...t,binding:n,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=r(i),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return e.flags.json?await G({success:!1,error:o}):await W(o,{showDetails:t.debugOutputEnabled}),T(1)}}async function _t(e,n){let{daemonAuthToken:r,...i}=e.effectiveFlags;return await tt(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 dt({route:`react-devtools`,command:v.runtime,request:{positionals:[`port-reverse`],flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},transport:n.sendToDaemon,transportOptions:{authToken:r}});a.ok||t(a.error)}})}async function vt(t,n){if(t.command===`batch`){if(t.positionals.length>0)throw new e(`INVALID_ARGS`,`batch does not accept positional arguments.`);t.parsedBatchSteps=Dt(t.flags)}if(jt(t.command)&&(t.effectiveFlags=(await Ce({command:t.command,flags:t.effectiveFlags,stateDir:t.daemonPaths.baseDir,env:process.env})).flags),t.effectiveFlags.remoteConfig&&At(t.command)){let e=l(J(t),{transport:Q(n.sendToDaemon)}),r=await xe({command:t.command,flags:t.effectiveFlags,client:e,runtime:t.resolvedRuntime,positionals:t.positionals,batchSteps:t.parsedBatchSteps,forceRuntimePrepare:Ft(t.explicitFlagKeys)});t.effectiveFlags=r.flags,t.resolvedRuntime=r.runtime,t.connectionMetadata=r.connection}Mt({command:t.command,flags:t.effectiveFlags,runtime:t.resolvedRuntime,explicitFlagKeys:t.explicitFlagKeys,hadConnectionDefaults:!!t.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.
3
+ `)}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 yt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Rt(e.daemonPaths.logPath):null}async function bt(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 xt(t,n,r,i){let{command:a,positionals:o,effectiveFlags:s}=t;if(a===`batch`){if(!t.parsedBatchSteps)throw new e(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let c=t.parsedBatchSteps.map((e,n)=>({...e,input:t.binding.lockPolicy&&t.flags.platform===void 0?{...e.input}:H(e.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await R({command:a,positionals:o,flags:{...s,batchSteps:c},client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return}else if(a===`runtime`)throw new e(`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 R({command:a,positionals:o,flags:s,client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return;throw new e(`INVALID_ARGS`,Et(a))}async function St(e,t,i){let a=r(e),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});if(t.command===`close`&&Ot(a)){t.effectiveFlags.json&&await G({success:!0,data:{closed:`session`,source:`no-daemon`}});return}t.effectiveFlags.json?await G({success:!1,error:o}):(await W(o,{showDetails:t.debugOutputEnabled}),t.debugOutputEnabled&&Ct(t,o)),i&&i(),await T(1)}const Y=64e3;function Ct(e,t){if(!e.effectiveFlags.daemonBaseUrl){X(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&X(`remote diagnostics`,se(e.daemonPaths.baseDir,n))}function X(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
4
4
  `),r=n.slice(Math.max(0,n.length-200)).join(`
5
- `);r.length>Y&&(r=r.slice(r.length-Y)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function wt(e){try{let t=M(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function Tt(e){let t=j(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Et(e){return _(e)?(S({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 Dt(e){let t=``;if(e.steps)t=e.steps;else if(e.stepsFile)try{t=E.readFileSync(e.stepsFile,`utf8`)}catch(t){let n=t instanceof Error?t.message:String(t);throw new r(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${n}`)}return rt(t)}function Ot(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 kt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:Se({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 At(e){return!mt.has(e)}function jt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Mt(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Nt(e.explicitFlagKeys)}function Nt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Pt(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 Ft(e){for(let t of pt)if(e.has(t))return!0;return!1}function It(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:Ge(e.commandProgress);return async(e,n)=>{let r={...n,onProgress:a};return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},r)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Lt(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}D(process.argv[1]??``).href===import.meta.url&&K(process.argv.slice(2)).catch(async e=>{let r=n(e);await W(t(r),{showDetails:!0}),await T(1)});function Rt(e){try{let t=E.existsSync(e)?E.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&E.existsSync(e))try{let n=E.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=E.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);E.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{E.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{K as runCli};
5
+ `);r.length>Y&&(r=r.slice(r.length-Y)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function wt(e){try{let t=M(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function Tt(e){let t=j(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Et(e){return _(e)?(S({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 Dt(t){let n=``;if(t.steps)n=t.steps;else if(t.stepsFile)try{n=E.readFileSync(t.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new e(`INVALID_ARGS`,`Failed to read --steps-file ${t.stepsFile}: ${r}`)}return rt(n)}function Ot(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 kt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:Se({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 At(e){return!mt.has(e)}function jt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Mt(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Nt(e.explicitFlagKeys)}function Nt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Pt(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 Ft(e){for(let t of pt)if(e.has(t))return!0;return!1}function It(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:Ge(e.commandProgress);return async(e,n)=>{let r={...n,onProgress:a};return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},r)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Lt(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}D(process.argv[1]??``).href===import.meta.url&&K(process.argv.slice(2)).catch(async e=>{let t=r(e);await W(n(t),{showDetails:!0}),await T(1)});function Rt(e){try{let t=E.existsSync(e)?E.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&E.existsSync(e))try{let n=E.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=E.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);E.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{E.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{K as runCli};
@@ -1 +1 @@
1
- import{y as e}from"./sdk-contracts.js";const t=[`primary`,`secondary`,`middle`];function n(e){return e?.clickButton??`primary`}function r(t){return t.button===`primary`?null:t.commandLabel===`click`?t.platform!==`macos`&&t.platform!==`linux`?new e(`UNSUPPORTED_OPERATION`,`click --button ${t.button} is supported only on macOS and Linux`):t.platform===`macos`&&t.button===`middle`?new e(`UNSUPPORTED_OPERATION`,`click --button middle is not supported by the macOS runner yet`):typeof t.count==`number`||typeof t.intervalMs==`number`||typeof t.holdMs==`number`||typeof t.jitterPx==`number`||t.doubleTap===!0?new e(`INVALID_ARGS`,`click --button ${t.button} does not support repeat or gesture modifier flags`):null:new e(`INVALID_ARGS`,`--button is supported only for click`)}function i(e){return e===`primary`?{}:{button:e}}export{n as i,i as n,r,t};
1
+ import{C as e}from"./sdk-contracts.js";const t=[`primary`,`secondary`,`middle`];function n(e){return e?.clickButton??`primary`}function r(t){return t.button===`primary`?null:t.commandLabel===`click`?t.platform!==`macos`&&t.platform!==`linux`?new e(`UNSUPPORTED_OPERATION`,`click --button ${t.button} is supported only on macOS and Linux`):t.platform===`macos`&&t.button===`middle`?new e(`UNSUPPORTED_OPERATION`,`click --button middle is not supported by the macOS runner yet`):typeof t.count==`number`||typeof t.intervalMs==`number`||typeof t.holdMs==`number`||typeof t.jitterPx==`number`||t.doubleTap===!0?new e(`INVALID_ARGS`,`click --button ${t.button} does not support repeat or gesture modifier flags`):null:new e(`INVALID_ARGS`,`--button is supported only for click`)}function i(e){return e===`primary`?{}:{button:e}}export{n as i,i as n,r,t};
@@ -1 +1 @@
1
- import{b as e,p as t,w as n,y as r}from"./owner-identity.js";import{l as i}from"./exec.js";import"./command.js";import"./process.js";import{a,c as o,d as s,f as c,h as l,i as u,l as d,m as f,o as p,p as m,r as h,s as g,t as _,u as v}from"./base-url.js";import y from"node:path";import b from"node:fs";import{createHash as x}from"node:crypto";import{fileURLToPath as S}from"node:url";const C=`companion-tunnel`;function w(e){return x(`sha256`).update(e).digest(`hex`)}function T(e){return e?.trim()?e.trim():void 0}function E(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 D(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function O(e,t,n,r){let i=r??y.join(e,`.agent-device`);if(!n)return{statePath:y.join(i,`${t.slug}.json`),logPath:y.join(i,`${t.slug}.log`)};let a=w(n).slice(0,12),o=y.join(i,t.slug);return{statePath:y.join(o,`${t.slug}-${a}.json`),logPath:y.join(o,`${t.slug}-${a}.log`)}}function k(e){try{let t=JSON.parse(b.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:T(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:T(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:T(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:T(typeof t.session==`string`?t.session:void 0),bridgeScope:E(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function A(e,t){b.mkdirSync(y.dirname(e),{recursive:!0}),b.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function j(e){b.mkdirSync(y.dirname(e),{recursive:!0}),b.closeSync(b.openSync(e,`a`))}function M(e){try{b.unlinkSync(e)}catch{}}function N(e){try{b.unlinkSync(e)}catch{}}function P(e){try{b.readdirSync(e).length===0&&b.rmdirSync(e)}catch{}}function F(e,t){let n=y.dirname(e.statePath),r=y.dirname(e.logPath);M(e.statePath),N(e.logPath),P(n),r!==n&&P(r),y.basename(n)===t.slug&&P(y.dirname(n))}function I(e,t){return e.includes(t.runArg)}function L(n,i){if(!t(n.pid))return!1;if(n.startTime){let t=e(n.pid);if(!t||t!==n.startTime)return!1}let a=r(n.pid);return!a||!I(a,i.definition)||!n.bridgeScope?!1:n.serverBaseUrl===_(i.serverBaseUrl)&&n.localBaseUrl===_(i.localBaseUrl)&&n.launchUrl===T(i.launchUrl)&&n.registerPath===T(i.registerPath)&&n.unregisterPath===T(i.unregisterPath)&&n.devicePort===i.devicePort&&n.session===T(i.session)&&D(n.bridgeScope,i.bridgeScope)&&n.tokenHash===w(i.bearerToken)}function R(e){return T(e.consumerKey)??T(e.profileKey)??null}function z(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function B(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function V(e,i){if(!t(e.pid))return;let a=r(e.pid);if(!(!a||!I(a,i))){try{process.kill(e.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await n(e.pid,1e3)){try{process.kill(e.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await n(e.pid,1e3)}}}function H(e,t){let n={...t};return n[s]=_(e.serverBaseUrl),n[h]=e.bearerToken,n[p]=_(e.localBaseUrl),n[m]=O(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[v]=e.bridgeScope.tenantId,n[d]=e.bridgeScope.runId,n[o]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[a]=e.launchUrl.trim():delete n[a],e.registerPath?.trim()?n[g]=e.registerPath.trim():delete n[g],e.unregisterPath?.trim()?n[f]=e.unregisterPath.trim():delete n[f],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[c]=e.session.trim():delete n[c],n}function U(e){let t=S(import.meta.url),n=y.extname(t)||`.js`,r=[y.join(y.dirname(t),`${C}${n}`),y.join(y.dirname(t),`internal`,`${C}${n}`)].find(e=>b.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function W(t,n){let a=U(t.definition),o=a.endsWith(`.ts`)?[`--experimental-strip-types`]:[];b.mkdirSync(y.dirname(n),{recursive:!0});let s=b.openSync(n,`a`),c=0;try{c=i(process.execPath,[...o,a,t.definition.runArg],{env:H(t,t.env??process.env),stdio:[`ignore`,s,s]})}finally{b.closeSync(s)}if(!Number.isInteger(c)||c<=0)throw Error(`Failed to start ${t.definition.displayName} process.`);return{pid:c,startTime:e(c)??void 0,command:r(c)??void 0,serverBaseUrl:_(t.serverBaseUrl),localBaseUrl:_(t.localBaseUrl),launchUrl:T(t.launchUrl),registerPath:T(t.registerPath),unregisterPath:T(t.unregisterPath),devicePort:t.devicePort,session:T(t.session),bridgeScope:t.bridgeScope,tokenHash:w(t.bearerToken),consumers:[]}}async function G(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(r&&L(r,e)){let e=z(r,t);return e!==r&&A(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await V(r,e.definition),F(n,e.definition)),j(n.statePath);let i;try{i=W(e,n.logPath),A(n.statePath,z(i,t))}catch(t){throw i&&await V(i,e.definition).catch(()=>{}),F(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function K(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(!r)return F(n,e.definition),{stopped:!1,statePath:n.statePath};let i=B(r,t);return i.consumers.length>0?(A(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await V(r,e.definition),F(n,e.definition),{stopped:!0,statePath:n.statePath})}const q={slug:`metro-companion`,runArg:l,displayName:`Metro companion`};async function J(e){return await G({...e,definition:q,registerPath:e.registerPath??`/api/metro/companion/register`})}async function Y(e){return await K({...e,definition:q})}export{K as i,Y as n,G as r,J as t};
1
+ import{T as e,p as t,x as n,y as r}from"./owner-identity.js";import{u as i}from"./exec.js";import"./command.js";import"./process.js";import{a,c as o,d as s,f as c,h as l,i as u,l as d,m as f,o as p,p as m,r as h,s as g,t as _,u as v}from"./base-url.js";import y from"node:path";import b from"node:fs";import{createHash as x}from"node:crypto";import{fileURLToPath as S}from"node:url";const C=`companion-tunnel`;function w(e){return x(`sha256`).update(e).digest(`hex`)}function T(e){return e?.trim()?e.trim():void 0}function E(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 D(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function O(e,t,n,r){let i=r??y.join(e,`.agent-device`);if(!n)return{statePath:y.join(i,`${t.slug}.json`),logPath:y.join(i,`${t.slug}.log`)};let a=w(n).slice(0,12),o=y.join(i,t.slug);return{statePath:y.join(o,`${t.slug}-${a}.json`),logPath:y.join(o,`${t.slug}-${a}.log`)}}function k(e){try{let t=JSON.parse(b.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:T(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:T(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:T(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:T(typeof t.session==`string`?t.session:void 0),bridgeScope:E(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function A(e,t){b.mkdirSync(y.dirname(e),{recursive:!0}),b.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function j(e){b.mkdirSync(y.dirname(e),{recursive:!0}),b.closeSync(b.openSync(e,`a`))}function M(e){try{b.unlinkSync(e)}catch{}}function N(e){try{b.unlinkSync(e)}catch{}}function P(e){try{b.readdirSync(e).length===0&&b.rmdirSync(e)}catch{}}function F(e,t){let n=y.dirname(e.statePath),r=y.dirname(e.logPath);M(e.statePath),N(e.logPath),P(n),r!==n&&P(r),y.basename(n)===t.slug&&P(y.dirname(n))}function I(e,t){return e.includes(t.runArg)}function L(e,i){if(!t(e.pid))return!1;if(e.startTime){let t=n(e.pid);if(!t||t!==e.startTime)return!1}let a=r(e.pid);return!a||!I(a,i.definition)||!e.bridgeScope?!1:e.serverBaseUrl===_(i.serverBaseUrl)&&e.localBaseUrl===_(i.localBaseUrl)&&e.launchUrl===T(i.launchUrl)&&e.registerPath===T(i.registerPath)&&e.unregisterPath===T(i.unregisterPath)&&e.devicePort===i.devicePort&&e.session===T(i.session)&&D(e.bridgeScope,i.bridgeScope)&&e.tokenHash===w(i.bearerToken)}function R(e){return T(e.consumerKey)??T(e.profileKey)??null}function z(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function B(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function V(n,i){if(!t(n.pid))return;let a=r(n.pid);if(!(!a||!I(a,i))){try{process.kill(n.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await e(n.pid,1e3)){try{process.kill(n.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await e(n.pid,1e3)}}}function H(e,t){let n={...t};return n[s]=_(e.serverBaseUrl),n[h]=e.bearerToken,n[p]=_(e.localBaseUrl),n[m]=O(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[v]=e.bridgeScope.tenantId,n[d]=e.bridgeScope.runId,n[o]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[a]=e.launchUrl.trim():delete n[a],e.registerPath?.trim()?n[g]=e.registerPath.trim():delete n[g],e.unregisterPath?.trim()?n[f]=e.unregisterPath.trim():delete n[f],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[c]=e.session.trim():delete n[c],n}function U(e){let t=S(import.meta.url),n=y.extname(t)||`.js`,r=[y.join(y.dirname(t),`${C}${n}`),y.join(y.dirname(t),`internal`,`${C}${n}`)].find(e=>b.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function W(e,t){let a=U(e.definition),o=a.endsWith(`.ts`)?[`--experimental-strip-types`]:[];b.mkdirSync(y.dirname(t),{recursive:!0});let s=b.openSync(t,`a`),c=0;try{c=i(process.execPath,[...o,a,e.definition.runArg],{env:H(e,e.env??process.env),stdio:[`ignore`,s,s]})}finally{b.closeSync(s)}if(!Number.isInteger(c)||c<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:c,startTime:n(c)??void 0,command:r(c)??void 0,serverBaseUrl:_(e.serverBaseUrl),localBaseUrl:_(e.localBaseUrl),launchUrl:T(e.launchUrl),registerPath:T(e.registerPath),unregisterPath:T(e.unregisterPath),devicePort:e.devicePort,session:T(e.session),bridgeScope:e.bridgeScope,tokenHash:w(e.bearerToken),consumers:[]}}async function G(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(r&&L(r,e)){let e=z(r,t);return e!==r&&A(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await V(r,e.definition),F(n,e.definition)),j(n.statePath);let i;try{i=W(e,n.logPath),A(n.statePath,z(i,t))}catch(t){throw i&&await V(i,e.definition).catch(()=>{}),F(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function K(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(!r)return F(n,e.definition),{stopped:!1,statePath:n.statePath};let i=B(r,t);return i.consumers.length>0?(A(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await V(r,e.definition),F(n,e.definition),{stopped:!0,statePath:n.statePath})}const q={slug:`metro-companion`,runArg:l,displayName:`Metro companion`};async function J(e){return await G({...e,definition:q,registerPath:e.registerPath??`/api/metro/companion/register`})}async function Y(e){return await K({...e,definition:q})}export{K as i,Y as n,G as r,J as t};
@@ -1 +1 @@
1
- import{b as e,y as t}from"./sdk-contracts.js";import{w as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{f as i,l as a}from"./exec.js";import{t as o}from"./timeouts.js";import"./file.js";import"./command.js";import"./retry.js";import"./process.js";import{t as s}from"./base-url.js";import{t as c}from"./client-metro-companion.js";import{n as l,r as u}from"./project-runtime.js";import{t as d}from"./runtime-transport-hints.js";import f from"node:path";import p from"node:fs";function m(e,t,n=`index.bundle`){let r=new URL(`${s(e)}/${n}`);return r.searchParams.set(`platform`,t),r.searchParams.set(`dev`,`true`),r.searchParams.set(`minify`,`false`),r.toString()}const h=8081,g=`.expo/.virtual-metro-entry.bundle`;function _(e,n){if(e==null||e===``)return n;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new t(`INVALID_ARGS`,`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}function v(e){let n=S(e.bundleUrl),r=n??e.runtime?.bundleUrl,i=!!n,a=!!S(r),o=d({metroHost:y(e,i,a),metroPort:b(e,i,a),bundleUrl:r});if(!o)throw new t(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=ee(r);return{reloadUrl:x(o,o.scheme,`${s}/reload`),messageSocketUrl:x(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function y(e,t,n){return S(e.metroHost)??(t?void 0:S(e.runtime?.metroHost))??(n?void 0:`localhost`)}function b(e,t,n){if(e.metroPort!==void 0)return _(e.metroPort,h);if(!t)return e.runtime?.metroPort??(n?void 0:h)}function ee(e){let t=S(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${g}`;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 x(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 S(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function C(e){return typeof e==`string`&&e.trim()?s(e.trim()):``}function w(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function T(e,t,n){return r(e,{env:t,cwd:n})}function E(e){try{return p.accessSync(e,p.constants.F_OK),!0}catch{return!1}}function D(e){try{return p.statSync(e).isDirectory()}catch{return!1}}function O(e){let n=f.join(e,`package.json`),r=u(e);if(!r)throw new t(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const k=[{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 te(e){let t=e;for(;;){for(let{file:e,command:n}of k)if(E(f.join(t,e)))return{command:n,installArgs:[`install`]};if(E(f.join(t,`.git`)))return null;let e=f.dirname(t);if(e===t)return null;t=e}}function A(e){return te(e)??{command:`npm`,installArgs:[`install`]}}function j(e,t){if(t!==`auto`)return t;let n=l(e);return n===`expo`||n===`repack`?n:`react-native`}function M(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function N(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>E(f.join(e,`${t}.config.${n}`)))}function P(e,t){return N(e,`rspack`)?`rspack`:N(e,`webpack`)?`webpack`:M(t,`@rspack/core`)?`rspack`:M(t,`webpack`)?`webpack`:`rspack`}function F(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 ne(e){return e===`expo`?g:`index.bundle`}function I(e,t,n){return{platform:t,bundleUrl:m(e,t,ne(n))}}function L(e,t){return{platform:t,metroHost:w(e?.metro_host),metroPort:e?.metro_port,bundleUrl:w(e?.metro_bundle_url),launchUrl:w(e?.launch_url)}}function R(e,t){if(D(f.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{i(n.command,n.installArgs,{cwd:e,env:t})}catch(e){throw z(e,n)}return{installed:!0,packageManager:n.command}}function z(n,r){let i=e(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 t(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function B(e){await o(e)}async function V(e,n,r={}){try{let t=await fetch(e,{headers:r,signal:AbortSignal.timeout(n)});return{ok:t.ok,status:t.status,body:await t.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new t(`COMMAND_FAILED`,`Timed out fetching ${e} after ${n}ms`):r}}async function H(e,t){try{let n=await V(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function U(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 W(e,n,r,i,o,s,c){let l=U(n,r,i,o);p.mkdirSync(f.dirname(s),{recursive:!0});let u=p.openSync(s,`a`),d=0;try{d=a(l.command,l.installArgs,{cwd:e,env:c,stdio:[`ignore`,u,u]})}finally{p.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new t(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function G(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 n(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await n(e,1e3)}}}function K(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function q(e,n){let r=new t(`COMMAND_FAILED`,e);return r.retryable=n,r}function J(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function Y(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function X(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:K(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`?q(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):q(t instanceof Error?t.message:String(t),!0)}let n=Z(await t.text(),t.status,e.baseUrl);if(!t.ok)throw q(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,J(t.status,n));return ie(n)}function Z(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 q(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,J(t,e))}}function re(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:L(e.ios_runtime,`ios`),androidRuntime:L(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 ie(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw q(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return re(t)}catch(e){throw q(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function Q(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 ae(e,n){if(!n?.iosRuntime.bundleUrl)throw new t(`COMMAND_FAILED`,Q(e,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function oe(e,n,r){let i=n||w(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||e&&w(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(e&&!a)throw new t(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!e&&i)throw new t(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(e&&a),proxyBaseUrl:e,proxyBearerToken:a}}function se(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new t(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return e}function ce(e,n){if(!(e||n))throw new t(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function le(e,t,n){return e.runtimeFilePath?T(e.runtimeFilePath,t,n):null}function ue(e,t,n,r){return T(e.logPath??f.join(r,`.agent-device`,`metro.log`),t,n)}function $(e){let t=e.env??process.env,n=process.cwd(),r=T(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=O(r),o=j(a,i)):o=i;let s=null;o===`repack`&&(a??=O(r),s=P(r,a));let c=C(e.publicBaseUrl),l=C(e.proxyBaseUrl);ce(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=oe(l,w(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:_(e.metroPort??8081,8081),listenHost:w(e.listenHost)??`0.0.0.0`,statusHost:w(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?se(e.bridgeScope):null,startupTimeoutMs:F(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:F(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:le(e,t,n),logPath:ue(e,t,n,r)}}async function de(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await H(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await B(i)}return!1}async function fe(e){let n=Date.now()+e.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let t=await X({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(t.probe.reachable!==!1)return t;r=t,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!Y(n))throw new t(`COMMAND_FAILED`,Q(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await B(a)}throw new t(`COMMAND_FAILED`,Q(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath))}async function pe(e){let n=`http://${e.statusHost}:${e.metroPort}/status`;if(e.reuseExisting&&await H(n,e.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=W(e.projectRoot,e.kind,e.repackBundler,e.metroPort,e.listenHost,e.logPath,e.env);if(await de(n,e.startupTimeoutMs,e.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await G(r.pid).catch(()=>{}),new t(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${e.startupTimeoutMs}ms. Check ${e.logPath}.`,{logPath:e.logPath})}async function me(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await X({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!Y(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await he(e,t,n,r,i)),ae(t.proxyBaseUrl,r),r}async function he(e,n,r,i,a){let o;try{o=(await c({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:w(e.launchUrl),profileKey:w(e.companionProfileKey),consumerKey:w(e.companionConsumerKey),env:n.env})).logPath}catch(e){throw new t(`COMMAND_FAILED`,Q(n.proxyBaseUrl,e instanceof Error?e.message:String(e),i,a),void 0,e)}try{return await fe({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 ge(e,t){return{baseIosRuntime:e?I(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?I(e,`android`,t):{platform:`android`}}}function _e(e,t){e&&(p.mkdirSync(f.dirname(e),{recursive:!0}),p.writeFileSync(e,JSON.stringify(t,null,2)))}async function ve(e={}){let t=$(e),n=t.installProjectDeps?R(t.projectRoot,t.env):{installed:!1},r=await pe(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ge(t.publicBaseUrl,t.kind),o=await me(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 _e(t.runtimeFilePath,l),l}function ye(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function be(e,n){await new Promise((r,i)=>{let a=new WebSocket(e),o=e=>{clearTimeout(s);try{a.close()}catch{}i(new t(`COMMAND_FAILED`,e))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${e} 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 ${e}`)})})}async function xe(e={}){let n=F(e.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=v(e),a=await V(r,n);if(a.ok&&!ye(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await be(i,n)}catch(e){throw new t(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},e instanceof Error?e:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{xe as n,m as r,ve as t};
1
+ import{C as e,w as t}from"./sdk-contracts.js";import{T as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{p as i,u as a}from"./exec.js";import{t as o}from"./timeouts.js";import"./file.js";import"./command.js";import"./retry.js";import"./process.js";import{t as s}from"./base-url.js";import{t as c}from"./client-metro-companion.js";import{n as l,r as u}from"./project-runtime.js";import{t as d}from"./runtime-transport-hints.js";import f from"node:path";import p from"node:fs";function m(e,t,n=`index.bundle`){let r=new URL(`${s(e)}/${n}`);return r.searchParams.set(`platform`,t),r.searchParams.set(`dev`,`true`),r.searchParams.set(`minify`,`false`),r.toString()}const h=8081,g=`.expo/.virtual-metro-entry.bundle`;function _(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 v(t){let n=S(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!S(r),o=d({metroHost:y(t,i,a),metroPort:b(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=ee(r);return{reloadUrl:x(o,o.scheme,`${s}/reload`),messageSocketUrl:x(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function y(e,t,n){return S(e.metroHost)??(t?void 0:S(e.runtime?.metroHost))??(n?void 0:`localhost`)}function b(e,t,n){if(e.metroPort!==void 0)return _(e.metroPort,h);if(!t)return e.runtime?.metroPort??(n?void 0:h)}function ee(e){let t=S(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${g}`;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 x(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 S(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function C(e){return typeof e==`string`&&e.trim()?s(e.trim()):``}function w(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function T(e,t,n){return r(e,{env:t,cwd:n})}function E(e){try{return p.accessSync(e,p.constants.F_OK),!0}catch{return!1}}function D(e){try{return p.statSync(e).isDirectory()}catch{return!1}}function O(t){let n=f.join(t,`package.json`),r=u(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const k=[{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 te(e){let t=e;for(;;){for(let{file:e,command:n}of k)if(E(f.join(t,e)))return{command:n,installArgs:[`install`]};if(E(f.join(t,`.git`)))return null;let e=f.dirname(t);if(e===t)return null;t=e}}function A(e){return te(e)??{command:`npm`,installArgs:[`install`]}}function j(e,t){if(t!==`auto`)return t;let n=l(e);return n===`expo`||n===`repack`?n:`react-native`}function M(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function N(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>E(f.join(e,`${t}.config.${n}`)))}function P(e,t){return N(e,`rspack`)?`rspack`:N(e,`webpack`)?`webpack`:M(t,`@rspack/core`)?`rspack`:M(t,`webpack`)?`webpack`:`rspack`}function F(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 ne(e){return e===`expo`?g:`index.bundle`}function I(e,t,n){return{platform:t,bundleUrl:m(e,t,ne(n))}}function L(e,t){return{platform:t,metroHost:w(e?.metro_host),metroPort:e?.metro_port,bundleUrl:w(e?.metro_bundle_url),launchUrl:w(e?.launch_url)}}function R(e,t){if(D(f.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{i(n.command,n.installArgs,{cwd:e,env:t})}catch(e){throw z(e,n)}return{installed:!0,packageManager:n.command}}function z(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 B(e){await o(e)}async function V(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 H(e,t){try{let n=await V(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function U(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 W(t,n,r,i,o,s,c){let l=U(n,r,i,o);p.mkdirSync(f.dirname(s),{recursive:!0});let u=p.openSync(s,`a`),d=0;try{d=a(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{p.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 G(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 n(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await n(e,1e3)}}}function K(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function q(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function J(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function Y(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function X(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:K(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`?q(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):q(t instanceof Error?t.message:String(t),!0)}let n=Z(await t.text(),t.status,e.baseUrl);if(!t.ok)throw q(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,J(t.status,n));return ie(n)}function Z(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 q(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,J(t,e))}}function re(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:L(e.ios_runtime,`ios`),androidRuntime:L(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 ie(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw q(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return re(t)}catch(e){throw q(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function Q(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 ae(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,Q(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function oe(t,n,r){let i=n||w(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&w(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 se(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 ce(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function le(e,t,n){return e.runtimeFilePath?T(e.runtimeFilePath,t,n):null}function ue(e,t,n,r){return T(e.logPath??f.join(r,`.agent-device`,`metro.log`),t,n)}function $(e){let t=e.env??process.env,n=process.cwd(),r=T(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=O(r),o=j(a,i)):o=i;let s=null;o===`repack`&&(a??=O(r),s=P(r,a));let c=C(e.publicBaseUrl),l=C(e.proxyBaseUrl);ce(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=oe(l,w(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:_(e.metroPort??8081,8081),listenHost:w(e.listenHost)??`0.0.0.0`,statusHost:w(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?se(e.bridgeScope):null,startupTimeoutMs:F(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:F(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:le(e,t,n),logPath:ue(e,t,n,r)}}async function de(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await H(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await B(i)}return!1}async function fe(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await X({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),!Y(n))throw new e(`COMMAND_FAILED`,Q(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 B(a)}throw new e(`COMMAND_FAILED`,Q(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function pe(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await H(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=W(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await de(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await G(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 me(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await X({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!Y(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await he(e,t,n,r,i)),ae(t.proxyBaseUrl,r),r}async function he(t,n,r,i,a){let o;try{o=(await c({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:w(t.launchUrl),profileKey:w(t.companionProfileKey),consumerKey:w(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,Q(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await fe({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 ge(e,t){return{baseIosRuntime:e?I(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?I(e,`android`,t):{platform:`android`}}}function _e(e,t){e&&(p.mkdirSync(f.dirname(e),{recursive:!0}),p.writeFileSync(e,JSON.stringify(t,null,2)))}async function ve(e={}){let t=$(e),n=t.installProjectDeps?R(t.projectRoot,t.env):{installed:!1},r=await pe(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ge(t.publicBaseUrl,t.kind),o=await me(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 _e(t.runtimeFilePath,l),l}function ye(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function be(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 xe(t={}){let n=F(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=v(t),a=await V(r,n);if(a.ok&&!ye(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await be(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{xe as n,m as r,ve as t};