agent-device 0.21.23 → 0.21.24

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 (258) hide show
  1. package/README.md +6 -6
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.apk → agent-device-android-ime-helper-0.21.24.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.24.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.manifest.json → agent-device-android-ime-helper-0.21.24.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.23.apk → agent-device-android-snapshot-helper-0.21.24.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.23.manifest.json → agent-device-android-snapshot-helper-0.21.24.manifest.json} +6 -6
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +12 -6
  9. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/RectResponseTests.swift +21 -0
  10. package/apple/snapshot-bridge/README.md +9 -7
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +56 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +14 -5
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +12 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +1 -1
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +29 -5
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +34 -10
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +19 -5
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +3 -3
  20. package/dist/src/adapter.js +1 -1
  21. package/dist/src/adb.js +1 -1
  22. package/dist/src/agent-browser-lifecycle.js +1 -1
  23. package/dist/src/agent-browser-process-record.js +1 -1
  24. package/dist/src/agent-browser-provider.js +1 -1
  25. package/dist/src/agent-device-client.js +2 -2
  26. package/dist/src/alert-runtime.js +1 -1
  27. package/dist/src/alert.js +1 -1
  28. package/dist/src/android-adb.d.ts +3 -2
  29. package/dist/src/android-input-ownership.js +1 -1
  30. package/dist/src/app-backend.js +1 -1
  31. package/dist/src/app-inventory.d.ts +4 -0
  32. package/dist/src/app-launch.js +1 -1
  33. package/dist/src/app-lifecycle.js +1 -1
  34. package/dist/src/app-log-runtime2.js +3 -3
  35. package/dist/src/app-resolution.js +2 -2
  36. package/dist/src/app-state-runtime.d.ts +15 -0
  37. package/dist/src/apple-runner-platform.js +1 -1
  38. package/dist/src/application-lifecycle-interaction.js +1 -1
  39. package/dist/src/aws-device-farm-connection.js +1 -0
  40. package/dist/src/back-mode.js +1 -1
  41. package/dist/src/backend-snapshot-options.js +1 -1
  42. package/dist/src/browserstack-connection.js +1 -0
  43. package/dist/src/browserstack-device-features.js +1 -0
  44. package/dist/src/browserstack.js +1 -0
  45. package/dist/src/cache.js +1 -1
  46. package/dist/src/cli-config.js +1 -1
  47. package/dist/src/cli-help.js +35 -19
  48. package/dist/src/cli-runner.js +1 -1
  49. package/dist/src/cli.js +3 -4
  50. package/dist/src/client-companion-tunnel.js +1 -0
  51. package/dist/src/client-metro-companion.js +1 -1
  52. package/dist/src/client-metro.js +1 -1
  53. package/dist/src/client-types.d.ts +7 -5
  54. package/dist/src/cloud-artifacts.d.ts +3 -2
  55. package/dist/src/command-metadata.js +1 -1
  56. package/dist/src/command-schema.js +1 -1
  57. package/dist/src/command-tools.js +2 -2
  58. package/dist/src/connection-runtime.js +1 -1
  59. package/dist/src/connection-verification.js +1 -0
  60. package/dist/src/connection.js +5 -5
  61. package/dist/src/contracts.d.ts +1 -1
  62. package/dist/src/daemon-client-lease-beat.js +1 -1
  63. package/dist/src/daemon-client-lifecycle.js +1 -1
  64. package/dist/src/daemon-client-transport.js +1 -1
  65. package/dist/src/daemon-http.js +1 -1
  66. package/dist/src/daemon-policy-file.js +1 -1
  67. package/dist/src/daemon-registration-owner.js +1 -1
  68. package/dist/src/device-claim-inspection.js +1 -1
  69. package/dist/src/device-input-state.d.ts +2 -15
  70. package/dist/src/device-readiness-runtime.js +1 -1
  71. package/dist/src/device-selection-resolver.js +1 -1
  72. package/dist/src/device.js +1 -1
  73. package/dist/src/device2.js +1 -1
  74. package/dist/src/device3.js +1 -1
  75. package/dist/src/dispatch-resolve.js +3 -3
  76. package/dist/src/doctor-facade.js +1 -1
  77. package/dist/src/durable-capture-resource.js +1 -1
  78. package/dist/src/durable-resource.js +1 -1
  79. package/dist/src/exec.js +1 -1
  80. package/dist/src/file.js +1 -1
  81. package/dist/src/find.js +1 -1
  82. package/dist/src/finders.js +1 -1
  83. package/dist/src/format.js +2 -1
  84. package/dist/src/gesture-admission.js +1 -1
  85. package/dist/src/gesture-plan-types.d.ts +2 -5
  86. package/dist/src/gesture-runtime.js +1 -1
  87. package/dist/src/human-control.js +1 -1
  88. package/dist/src/ime-rebind.js +1 -1
  89. package/dist/src/ime-settings-record.js +1 -0
  90. package/dist/src/ime-state.js +1 -1
  91. package/dist/src/index.d.ts +3 -3
  92. package/dist/src/input-actions.js +1 -1
  93. package/dist/src/input-actions2.js +1 -1
  94. package/dist/src/install-source2.js +1 -1
  95. package/dist/src/interaction-positionals.js +1 -1
  96. package/dist/src/interaction-ref-policy.js +1 -1
  97. package/dist/src/interaction.js +1 -1
  98. package/dist/src/interaction2.js +1 -1
  99. package/dist/src/interactor.js +5 -5
  100. package/dist/src/interactors.js +1 -1
  101. package/dist/src/internal/bin.js +1 -1
  102. package/dist/src/internal/daemon.js +1 -1
  103. package/dist/src/inventory2.js +1 -1
  104. package/dist/src/ios-snapshot-acquisition.js +1 -1
  105. package/dist/src/ios-snapshot-engine.js +1 -1
  106. package/dist/src/ios-snapshot-runtime.js +1 -1
  107. package/dist/src/launch-confirmation.js +1 -1
  108. package/dist/src/lease-scope.js +1 -1
  109. package/dist/src/lease.js +1 -1
  110. package/dist/src/limrun.d.ts +4 -555
  111. package/dist/src/load.js +1 -1
  112. package/dist/src/local-interactor-operation-set.js +1 -1
  113. package/dist/src/managed-device-scope.js +1 -1
  114. package/dist/src/manifest.js +1 -0
  115. package/dist/src/mechanics.js +16 -16
  116. package/dist/src/mobile-snapshot-semantics.js +1 -1
  117. package/dist/src/observation.js +1 -2
  118. package/dist/src/overlay.js +3 -3
  119. package/dist/src/owner-identity.js +3 -3
  120. package/dist/src/perf-facade.js +1 -1
  121. package/dist/src/perf-runtime-plan.js +1 -1
  122. package/dist/src/perf-target.js +1 -1
  123. package/dist/src/physical-device-control.js +1 -1
  124. package/dist/src/platform-request-scope.js +1 -1
  125. package/dist/src/platform-runtime-open-target.js +1 -1
  126. package/dist/src/platform-runtime-operation-host.js +4 -4
  127. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  128. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  129. package/dist/src/platform-runtime-unavailable.js +1 -1
  130. package/dist/src/platform-runtime.js +1 -1
  131. package/dist/src/platform-runtime2.js +1 -1
  132. package/dist/src/plugin.js +1 -0
  133. package/dist/src/plugins/webdriver.d.ts +111 -0
  134. package/dist/src/plugins/webdriver.js +1 -0
  135. package/dist/src/plugins.d.ts +2 -1
  136. package/dist/src/plugins2.js +1 -1
  137. package/dist/src/process-exit.js +1 -1
  138. package/dist/src/process.js +1 -1
  139. package/dist/src/provider-credential-fingerprint.js +1 -1
  140. package/dist/src/provider-device-admission.js +1 -1
  141. package/dist/src/provider-device-runtime.d.ts +556 -0
  142. package/dist/src/provider-policy.js +1 -0
  143. package/dist/src/provider-profile-fields.js +1 -1
  144. package/dist/src/provider-webdriver.js +1 -2
  145. package/dist/src/providers.js +1 -1
  146. package/dist/src/react-devtools.js +2 -0
  147. package/dist/src/react-native.js +1 -1
  148. package/dist/src/record-runtime.js +1 -1
  149. package/dist/src/record-trace.js +1 -1
  150. package/dist/src/recording.js +1 -1
  151. package/dist/src/registry.js +24 -24
  152. package/dist/src/remote-bridge.js +1 -0
  153. package/dist/src/remote-config-core.js +1 -0
  154. package/dist/src/remote-config.js +1 -1
  155. package/dist/src/remote-config2.js +1 -1
  156. package/dist/src/remote-connection-state.js +1 -0
  157. package/dist/src/replay.js +2 -2
  158. package/dist/src/request-admission.js +1 -1
  159. package/dist/src/request-runtime-binding.js +1 -1
  160. package/dist/src/result-serialization.js +1 -1
  161. package/dist/src/retry.js +1 -1
  162. package/dist/src/retry2.js +1 -0
  163. package/dist/src/runner-artifact-manifest.js +1 -1
  164. package/dist/src/runner-cache-metadata.js +2 -3
  165. package/dist/src/runner-cache-retention.js +1 -0
  166. package/dist/src/runner-cache-trim.js +1 -0
  167. package/dist/src/runner-client.js +1 -1
  168. package/dist/src/runner-dev-tools-security.js +1 -1
  169. package/dist/src/runner-device-readiness.js +1 -1
  170. package/dist/src/runner-device-set.js +1 -0
  171. package/dist/src/runner-disposal.js +1 -1
  172. package/dist/src/runner-error-classification.js +1 -1
  173. package/dist/src/runner-exchange.js +1 -1
  174. package/dist/src/runner-lease.js +1 -0
  175. package/dist/src/runner-operations-facade.js +1 -1
  176. package/dist/src/runner-session-types.js +1 -1
  177. package/dist/src/runner-start-budget.js +1 -1
  178. package/dist/src/runner-toolchain-probe.js +2 -0
  179. package/dist/src/runner.js +1 -1
  180. package/dist/src/runtime-deployment.js +1 -0
  181. package/dist/src/runtime.js +1 -1
  182. package/dist/src/runtime10.js +1 -2
  183. package/dist/src/runtime11.js +2 -0
  184. package/dist/src/runtime2.js +2 -5
  185. package/dist/src/runtime3.js +5 -1
  186. package/dist/src/runtime4.js +1 -5
  187. package/dist/src/runtime5.js +5 -1
  188. package/dist/src/runtime6.js +1 -1
  189. package/dist/src/runtime7.js +1 -1
  190. package/dist/src/runtime8.js +1 -1
  191. package/dist/src/runtime9.js +1 -1
  192. package/dist/src/screen-recording-transport.js +1 -1
  193. package/dist/src/screenshot-density.js +1 -1
  194. package/dist/src/screenshot3.js +2 -2
  195. package/dist/src/script.js +1 -1
  196. package/dist/src/scroll-gesture.js +1 -1
  197. package/dist/src/sdk-batch.js +2 -2
  198. package/dist/src/sdk-contracts.d.ts +20 -29
  199. package/dist/src/sdk-contracts.js +2 -2
  200. package/dist/src/sdk-device.js +1 -1
  201. package/dist/src/sdk-finders.d.ts +1 -1
  202. package/dist/src/sdk-finders.js +1 -1
  203. package/dist/src/sdk-remote-config.d.ts +4 -0
  204. package/dist/src/sdk-remote-config.js +1 -1
  205. package/dist/src/sdk-selectors.d.ts +1 -1
  206. package/dist/src/sdk-selectors.js +1 -1
  207. package/dist/src/selection.js +0 -0
  208. package/dist/src/selector-pipeline-policy.js +1 -1
  209. package/dist/src/selector-runtime.js +1 -1
  210. package/dist/src/selectors.js +1 -1
  211. package/dist/src/server.js +2 -2
  212. package/dist/src/session-snapshot.js +1 -1
  213. package/dist/src/session2.js +5 -5
  214. package/dist/src/simctl.js +1 -1
  215. package/dist/src/simulator-boot.js +1 -1
  216. package/dist/src/simulator-state.js +1 -1
  217. package/dist/src/simulator.js +1 -1
  218. package/dist/src/snapshot-capture-annotations.js +1 -1
  219. package/dist/src/snapshot-desktop-projection.js +1 -1
  220. package/dist/src/snapshot-private-evidence.js +1 -0
  221. package/dist/src/snapshot-runtime-binding.js +1 -1
  222. package/dist/src/snapshot-runtime.js +1 -1
  223. package/dist/src/snapshot-state.js +1 -1
  224. package/dist/src/snapshot4.js +1 -1
  225. package/dist/src/src2.js +1 -1
  226. package/dist/src/src3.js +1 -1
  227. package/dist/src/src4.js +1 -1
  228. package/dist/src/src5.js +1 -1
  229. package/dist/src/src6.js +1 -1
  230. package/dist/src/src7.js +1 -1
  231. package/dist/src/src8.js +20 -20
  232. package/dist/src/store.js +1 -1
  233. package/dist/src/target-evidence.js +1 -1
  234. package/dist/src/text-entry-focus.js +1 -1
  235. package/dist/src/tool-provider2.js +1 -1
  236. package/dist/src/touch-runtime2.js +1 -1
  237. package/dist/src/tree.js +1 -1
  238. package/dist/src/type-text-runtime.js +1 -1
  239. package/dist/src/video.js +1 -1
  240. package/package.json +15 -10
  241. package/server.json +2 -2
  242. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.23.apk.sha256 +0 -1
  243. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk.sha256 +0 -1
  244. package/dist/src/capabilities.js +0 -1
  245. package/dist/src/compatibility-policy.js +0 -1
  246. package/dist/src/daemon-artifacts.js +0 -1
  247. package/dist/src/device-claim-rule.js +0 -1
  248. package/dist/src/human-control-contract.js +0 -1
  249. package/dist/src/prepare-kind.js +0 -1
  250. package/dist/src/provider-device-runtimes.js +0 -1
  251. package/dist/src/screen-recording-admission-ledger.js +0 -1
  252. package/dist/src/screenshot-runtime.js +0 -1
  253. package/dist/src/session-routing.js +0 -1
  254. package/dist/src/session-runtime-admission.js +0 -1
  255. package/dist/src/timeouts.js +0 -1
  256. package/dist/src/touch-reference-frame.js +0 -1
  257. package/dist/src/vars.js +0 -2
  258. package/dist/src/viewport.js +0 -1
@@ -1,5 +1,5 @@
1
- import{r as e}from"./rolldown-runtime.js";import{vr as t}from"./sdk-batch.js";import{i as n}from"./catalog.js";import{r}from"./back-mode.js";import{C as i,P as a,c as o,w as s}from"./registry.js";import{a as c}from"./version.js";import{n as l,r as u}from"./command-schema.js";import{n as d}from"./cli-command-aliases.js";const f=[`Flows: launchApp (with clearState, permissions, and Apple-only launch arguments; permissions apply after state clearing but before launch, and a launchApp without permissions touches nothing — there is no silent all: allow default); setPermissions (mid-flow permission grants, denials, and resets; all resolves in the backend — one simctl call on iOS, the declared permissions on Android — with specific entries overriding after it); runFlow file/inline; runFlow.when and repeat.while conditions (platform, visible, notVisible, and true, all re-evaluated before every repeat iteration); onFlowStart/onFlowComplete; repeat with times, while, or both; 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.`],p=[`Permissions: every entry is one settings permission call, applied in order with all first; the step stops at the first entry the selected platform refuses, earlier entries stay applied, and the error names what landed. Android’s only allow level is while-in-use, so location: inuse and location: never mean allow and deny there, while location: always and photos: limited are Apple-only and fail. On iOS, which service a runtime changes is simctl privacy’s own verdict: current runtimes refuse a targeted notifications change and leave notifications untouched under all.`,`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 and condition true: fields (runFlow.when and repeat.while share one evaluator) are evaluated as JavaScript (flow env and prior output leaves are string-typed); a true: field that is a boolean, a maestro.platform comparison, or plain literal text after ${VAR} lookups is decided without JavaScript, with the assertTrue falsy table for literal text. Other fields stay literal or ${VAR} lookup-only — assertTrue supports literals and bare lookups, 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, evalScript, and JavaScript condition true: fields 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 and true: fields that need JavaScript are 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 m(){return[`Supported subset:`,...f.map(e=>` - ${e}`),``,`Boundaries:`,...p.map(e=>` - ${e}`)].join(`
2
- `)}function h(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function g(e){return r().filter(t=>t.key===e)}function _(e){if(!e.usageHidden)return e.usageLabel??e.names[0]}function v(e){return(e??[]).flatMap(e=>g(e).map(_).filter(e=>e!==void 0).map(e=>`[${e}]`))}function y(e,t){return[t.usageOverride??[e,...(t.positionalArgs??[]).map(h)].join(` `),...v(t.usageFlags??t.allowedFlags)].join(` `)}const b=`Wait failure contract:
1
+ import{r as e}from"./rolldown-runtime.js";import{F as t,T as n,c as r,w as i}from"./registry.js";import{yr as a}from"./sdk-batch.js";import{i as o}from"./catalog.js";import{r as s}from"./back-mode.js";import{a as c}from"./version.js";import{n as l,r as u}from"./command-schema.js";import{n as d}from"./cli-command-aliases.js";const f=[`Flows: launchApp (with clearState, permissions, and Apple-only launch arguments; permissions apply after state clearing but before launch, and a launchApp without permissions touches nothing — there is no silent all: allow default); setPermissions (mid-flow permission grants, denials, and resets; all resolves in the backend — one simctl call on iOS, the declared permissions on Android — with specific entries overriding after it); runFlow file/inline; runFlow.when and repeat.while conditions (platform, visible, notVisible, and true, all re-evaluated before every repeat iteration); onFlowStart/onFlowComplete; repeat with times, while, or both; 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.`],p=[`Permissions: every entry is one settings permission call, applied in order with all first; the step stops at the first entry the selected platform refuses, earlier entries stay applied, and the error names what landed. Android’s only allow level is while-in-use, so location: inuse and location: never mean allow and deny there, while location: always and photos: limited are Apple-only and fail. On iOS, which service a runtime changes is simctl privacy’s own verdict: current runtimes refuse a targeted notifications change and leave notifications untouched under all.`,`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 and condition true: fields (runFlow.when and repeat.while share one evaluator) are evaluated as JavaScript (flow env and prior output leaves are string-typed); a true: field that is a boolean, a maestro.platform comparison, or plain literal text after ${VAR} lookups is decided without JavaScript, with the assertTrue falsy table for literal text. Other fields stay literal or ${VAR} lookup-only — assertTrue supports literals and bare lookups, 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, evalScript, and JavaScript condition true: fields 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 and true: fields that need JavaScript are 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 m(){return[`Supported subset:`,...f.map(e=>` - ${e}`),``,`Boundaries:`,...p.map(e=>` - ${e}`)].join(`
2
+ `)}function h(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function g(e){return s().filter(t=>t.key===e)}function _(e){if(!e.usageHidden)return e.usageLabel??e.names[0]}function v(e){return(e??[]).flatMap(e=>g(e).map(_).filter(e=>e!==void 0).map(e=>`[${e}]`))}function y(e,t){return[t.usageOverride??[e,...(t.positionalArgs??[]).map(h)].join(` `),...v(t.usageFlags??t.allowedFlags)].join(` `)}const b=`Wait failure contract:
3
3
  Read --json error.details.reason.
4
4
  wait_target_absent: readable capture, no match.
5
5
  wait_target_present: absence timeout; details.matches/firstMatch.
@@ -271,7 +271,7 @@ Report:
271
271
  If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function w(){return`agent-device <command> [args] [--json]
272
272
 
273
273
  Automates iOS, Android, macOS, TV, and web apps for AI agents.
274
- All ${n().length} commands: agent-device help commands
274
+ All ${o().length} commands: agent-device help commands
275
275
 
276
276
  Start:
277
277
  When starting a task with a known app, first run:
@@ -294,7 +294,7 @@ Loop:
294
294
  Targets:
295
295
  Copy refs exactly: @e12, @e12~s4. Keep @ and any ~sN pin; refs go stale
296
296
  after mutations. A literal @handle is label="@handle", not a bare ref.
297
- Prefer refs, then id/label/role selectors. Selector keys: ${t.join(` `)}.
297
+ Prefer refs, then id/label/role selectors. Selector keys: ${a.join(` `)}.
298
298
  Coordinates are last resort: after snapshot -i shows no semantic target, or a
299
299
  sparse/AX-unavailable warning says its refs and selectors are invalid.
300
300
  Then screenshot, press <x> <y>, and re-snapshot on the changed screen.
@@ -352,7 +352,7 @@ Snapshots and refs:
352
352
 
353
353
  Selectors:
354
354
  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.
355
- Mutating selector ambiguity: press/click/fill/longpress collapse duplicate accessibility wrappers only when every match is one ancestor-descendant chain resolving to the same actionable node. Matches in distinct subtrees fail with AMBIGUOUS_MATCH and a bounded candidate list; geometry never chooses a winner. Retry one printed candidate ref (pinned to refsGeneration) or narrow the selector with role/id/longer text. Read-only commands and replay suggestions retain their declared resolution policies.
355
+ Mutating selector ambiguity: press/click/fill/longpress collapse duplicate accessibility wrappers only when every match is one ancestor-descendant chain resolving to the same actionable node. Matches in distinct subtrees fail with AMBIGUOUS_MATCH and a bounded candidate list; geometry never chooses a winner. Retry one printed candidate ref (pinned to refsGeneration) or narrow the selector with role/id/longer text. Uniqueness-based reads (is except exists/absent, get attrs) share that failure shape.
356
356
  hittable: false on a resolved element does not block dispatch (iOS AX flags are unreliable on deep RN trees); press/fill/click return targetHittable: false plus a hint -- verify or re-target, not a failure.
357
357
 
358
358
  Text entry:
@@ -778,7 +778,7 @@ Rules:
778
778
  Do not hard-code Edit/Done/Add Widget or other SpringBoard label text into a plan as a fixed assumption; take them from the latest snapshot -i so the plan survives iOS version/locale differences.
779
779
  A real system permission alert can appear mid-flow; it composes with this workflow normally, so handle it with alert wait/accept/dismiss or by pressing the visible label like any other step.
780
780
  Prefer refs/selectors from the fresh snapshot for every step except the two documented coordinate fallbacks (empty-space long-press to enter edit mode, and the gallery search-result tap).
781
- This topic covers what already works by opening SpringBoard as the session app. It does not yet cover keeping an app session open while alternating individual commands against SpringBoard, or Live Activity/Dynamic Island semantics; those land separately.`},foldable:o,remote:{summary:`Direct proxy, cloud profiles, and remote config`,body:`agent-device help remote
781
+ This topic covers what already works by opening SpringBoard as the session app. It does not yet cover keeping an app session open while alternating individual commands against SpringBoard, or Live Activity/Dynamic Island semantics; those land separately.`},foldable:r,remote:{summary:`Direct proxy, cloud profiles, and remote config`,body:`agent-device help remote
782
782
 
783
783
  Remote connection providers use the same lifecycle:
784
784
  connect -> install/open -> commands -> close -> disconnect
@@ -789,17 +789,18 @@ Providers:
789
789
  Direct proxy: agent-device connect proxy --daemon-base-url <proxy-agent-device-url> stores the shared proxy profile and client identity.
790
790
  BrowserStack: agent-device connect browserstack verifies credentials, the exact device, and a bs:// app reference, then stores a local provider profile. It does not create an App Automate session.
791
791
  AWS Device Farm: agent-device connect aws-device-farm verifies credentials and the exact project, device, and optional app upload, then stores a local provider profile. It does not create a remote access session.
792
+ TestMu AI: agent-device connect testmu verifies credentials and the exact virtual device (emulator or simulator) or, with --provider-device-type real, real device and OS version, then stores a local provider profile. --provider-app takes an lt:// app reference, an https URL, or a local path: connect looks an lt:// id up among your uploads for that device pool, while URL and local sources are uploaded and validated when open creates the session. It does not create a hub session.
792
793
  Limrun: agent-device connect limrun verifies access to the selected iOS or Android instance service, then stores a local provider profile. It does not create an instance.
793
794
 
794
795
  After direct-provider connect:
795
796
  Read the printed Device, App, Next, and workflow-note lines. They are also available as verification/device/app/liveSession/nextSteps/notes in --json output.
796
- BrowserStack and AWS Device Farm create the hosted session on open. open needs the installed package or bundle identifier, not the app artifact name or ARN.
797
+ BrowserStack, AWS Device Farm, and TestMu AI create the hosted session on open. open needs the installed package or bundle identifier, not the app artifact name, ARN, or lt:// id.
797
798
  Before provider allocation, apps lists compatible uploaded app assets without creating an instance when the selected provider exposes a catalog. open <exact-asset-name> creates the instance with that asset, resolves its installed app id, and launches it. install remains available when the app comes from a fresh local path or URL.
798
799
  AWS Device Farm cannot install after allocation. If connect reports no attached app, run its printed reconnect command, which includes --session <name> --force, before open.
799
800
  Do not run devices as a pre-open catalog probe for direct providers; it can allocate the deferred provider session. Limrun is the exception for apps: before allocation it lists uploaded assets for the selected platform.
800
801
 
801
802
  Device cloud interfaces:
802
- CLI is the canonical bootstrap path: connect limrun/browserstack/aws-device-farm, then use normal open/snapshot/click/close/artifacts/disconnect commands.
803
+ CLI is the canonical bootstrap path: connect limrun/browserstack/aws-device-farm/testmu, then use normal open/snapshot/click/close/artifacts/disconnect commands.
803
804
  JavaScript can skip persisted connect state by passing leaseProvider plus provider fields to createAgentDeviceClient or per-command options.
804
805
  MCP exposes operational tools such as open, snapshot, click, close, and artifacts. It does not expose connect/disconnect; run CLI connect first in the same state dir before relying on MCP tools.
805
806
 
@@ -829,6 +830,20 @@ Cloud profile flow:
829
830
  agent-device snapshot
830
831
  agent-device disconnect
831
832
 
833
+ TestMu AI virtual-device flow (emulators and simulators):
834
+ agent-device plugins add @agent-device/testmu
835
+ export LT_USERNAME=... LT_ACCESS_KEY=...
836
+ agent-device connect testmu --platform ios --device "iPhone 16" --provider-os-version 18.0 --provider-app lt://APP-id
837
+ agent-device open com.example.app
838
+ agent-device snapshot -i
839
+ agent-device close
840
+ agent-device artifacts --json
841
+ agent-device disconnect
842
+
843
+ TestMu AI real-device flow:
844
+ agent-device connect testmu --provider-device-type real --platform ios --device "iPhone 16" --provider-os-version 18 --provider-app ./MyApp.ipa
845
+ Real iOS devices are listed by major OS version (18, not 18.0) and install a signed .ipa. Real and virtual devices have separate upload APIs, so pass an lt:// id uploaded for the pool you connect to.
846
+
832
847
  BrowserStack hosted-device flow:
833
848
  BROWSERSTACK_USERNAME=... BROWSERSTACK_ACCESS_KEY=...
834
849
  agent-device connect browserstack --platform android --device "Google Pixel 8" --provider-os-version 14.0 --provider-app bs://app-id
@@ -877,13 +892,13 @@ Rules:
877
892
  Use connect without --remote-config when the cloud control plane owns the connection profile.
878
893
  Prefer connect --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
879
894
  Use agent-device proxy for direct tunnel access to a Mac you control. Expose the printed proxy URL through cloudflared/ngrok, then run agent-device connect proxy with the tunnel URL and printed token before normal commands.
880
- Use Limrun, BrowserStack, and AWS Device Farm through local provider profiles; they do not accept a remote agent-device daemon URL.
881
- Device cloud credentials must be available before the command starts. Limrun uses LIMRUN_API_KEY, or the LIM_*_INSTANCE_* variables for an existing instance. BrowserStack uses BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY. AWS Device Farm uses the AWS CLI credential chain, including CI-provided AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN, AWS profiles, or web identity role variables.
882
- A local daemon keeps the Limrun and BrowserStack credentials it started with. When the shell holds different ones, the first command that allocates a lease refuses with reason provider-credentials-changed; run agent-device daemon stop with the same --state-dir, then rerun the command. A shell that sets none of them uses the daemon's. A daemon with an HTTP auth hook serves remote callers and does not compare.
895
+ Use Limrun, BrowserStack, AWS Device Farm, and TestMu AI through local provider profiles; they do not accept a remote agent-device daemon URL.
896
+ Device cloud credentials must be available before the command starts. Limrun uses LIMRUN_API_KEY, or the LIM_*_INSTANCE_* variables for an existing instance. BrowserStack uses BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY. TestMu AI uses LT_USERNAME and LT_ACCESS_KEY. AWS Device Farm uses the AWS CLI credential chain, including CI-provided AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN, AWS profiles, or web identity role variables.
897
+ A local daemon keeps the Limrun, BrowserStack, and TestMu AI credentials it started with. When the shell holds different ones, the first command that allocates a lease refuses with reason provider-credentials-changed; run agent-device daemon stop with the same --state-dir, then rerun the command. A shell that sets none of them uses the daemon's. A daemon with an HTTP auth hook serves remote callers and does not compare.
883
898
  Direct-provider connect performs read-only provider calls and saves active connection state only after verification succeeds. It never creates a device, instance, App Automate session, or AWS remote access session.
884
899
  connect without --session always creates a fresh remote session and prints that session in its next-step commands. Concurrent callers must pass the returned --session on every command; the ambient active connection is only a single-workflow convenience.
885
900
  To replace an existing connection, pass its returned session explicitly with --session <name> --force. --force without --session creates another fresh session and does not release or overwrite an unrelated active connection.
886
- Prefer short-lived AWS role credentials in CI. Generated connection profiles store app/device selectors and ARNs, not Limrun API keys or instance tokens, BrowserStack access keys, or AWS credentials.
901
+ Prefer short-lived AWS role credentials in CI. Generated connection profiles store app/device selectors and ARNs, not Limrun API keys or instance tokens, BrowserStack or TestMu AI access keys, or AWS credentials.
887
902
  Limrun Android supports direct ADB port reverse for local Metro. Limrun iOS requires a public Metro/React DevTools URL because it cannot reach local host ports directly.
888
903
  After closing a device cloud session, run agent-device artifacts --json to retrieve provider video/log/dashboard URLs when the provider has made them available.
889
904
  connect proxy stores the connection profile and client identity. Proxy device leases are acquired on open and expire after five minutes without commands; devices may inspect proxy inventory without allocating.
@@ -928,7 +943,8 @@ Rules:
928
943
  Context menus are not ambient UI: secondary-click a visible target, then re-snapshot and use the new menu-item refs.
929
944
  Do not let iOS simulator-set scoping hide macOS desktop targets.
930
945
  Prefer refs/selectors over raw coordinates.
931
- macOS snapshot rects are window-space; use current refs or overlay refs instead of guessing coordinates.`},web:{summary:`Minimal browser workflow with the managed web backend`,body:`agent-device help web
946
+ macOS snapshot rects are window-space; use current refs or overlay refs instead of guessing coordinates.
947
+ On the default XCTest backend a read (snapshot, get, find) of a session app that sits behind other windows is answered from where it sits, without raising the app; interactions and a window-level screenshot of that app still bring it forward.`},web:{summary:`Minimal browser workflow with the managed web backend`,body:`agent-device help web
932
948
 
933
949
  Use --platform web only for the minimal browser command loop exposed through agent-device.
934
950
 
@@ -979,25 +995,25 @@ Rules:
979
995
 
980
996
  Full command catalog. Use agent-device help <command> for exact flags and behavior.
981
997
 
982
- ${B(n().map(e=>{let t=l(e);return{name:e,schema:t,usage:j(e,t)}}))}
998
+ ${B(o().map(e=>{let t=l(e);return{name:e,schema:t,usage:j(e,t)}}))}
983
999
 
984
1000
  ${L(`Device Selection (shared by device commands; help <command> lists each command's flags):`,F(i))}
985
1001
 
986
- ${L(`Global Flags:`,F(s))}
1002
+ ${L(`Global Flags:`,F(n))}
987
1003
 
988
1004
  ${z(`Configuration:`,E)}
989
1005
 
990
1006
  ${R(`Environment:`,D)}
991
1007
 
992
1008
  ${z(`Examples:`,O)}
993
- `}function P(){return M()}function F(e){return r().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function I(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function L(e,t){return R(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function R(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(`
1009
+ `}function P(){return M()}function F(e){return s().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function I(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function L(e,t){return R(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function R(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(`
994
1010
  `)}function z(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
995
- `)}function B(e){return R(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function V(e){let t=W(e);if(t)return t;let n=u(e);if(!n)return null;let r=y(e,n),i=I(F(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),o=[];i.length>0&&o.push(L(`Command flags:`,i));let s=o.length>0?`\n\n${o.join(`
1011
+ `)}function B(e){return R(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function V(e){let n=W(e);if(n)return n;let r=u(e);if(!r)return null;let i=y(e,r),a=I(F(new Set(r.allowedFlags??[])),r.flagDescriptionOverrides),o=[];a.length>0&&o.push(L(`Command flags:`,a));let s=o.length>0?`\n\n${o.join(`
996
1012
 
997
1013
  `)}`:``;return`Usage:
998
- agent-device ${r}
1014
+ agent-device ${i}
999
1015
 
1000
- ${a(n.text)}${s}
1016
+ ${t(r.text)}${s}
1001
1017
  `}function H(e){return V(d(e))}function U(){return Object.keys(k)}function W(e){let t=k[e];return t?`${G(e,e===`commands`?N():t.body)}
1002
1018
 
1003
1019
  Related:
@@ -1 +1 @@
1
- import{n as e,v as t}from"./registry.js";import{t as n}from"./cli-output.js";import{n as r}from"./command-surface.js";const i=e();function a(e,n,r){let a=i[e];if(!a)throw Error(`Missing CLI reader for command: ${e}`);return{...a(n,r),...t(e,r)}}async function o(e){return(await s(e)).result}async function s(e){let t=a(e.command,e.positionals,e.flags),i=await r(e.client,e.command,t);return{result:i,cliOutput:await n({name:e.command,input:t,result:i,progress:e.commandProgress})}}export{s as n,o as t};
1
+ import{n as e,y as t}from"./registry.js";import{t as n}from"./cli-output.js";import{n as r}from"./command-surface.js";const i=e();function a(e,n,r){let a=i[e];if(!a)throw Error(`Missing CLI reader for command: ${e}`);return{...a(n,r),...t(e,r)}}async function o(e){return(await s(e)).result}async function s(e){let t=a(e.command,e.positionals,e.flags),i=await r(e.client,e.command,t);return{result:i,cliOutput:await n({name:e.command,input:t,result:i,progress:e.commandProgress})}}export{s as n,o as t};
package/dist/src/cli.js CHANGED
@@ -1,5 +1,4 @@
1
- import{F as e,J as t,P as n,nt as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,f as o,s,u as c}from"./sdk-batch-runner.js";import{a as l,i as u,l as d,n as f,o as p,r as m}from"./diagnostics.js";import"./diagnostics2.js";import{n as h,r as g}from"./agent-device-client.js";import{s as ee,t as te,u as ne}from"./sdk-batch.js";import{i as re,r as _,t as v}from"./catalog.js";import{n as y,r as b}from"./back-mode.js";import{L as ie}from"./registry.js";import{p as ae}from"./exec.js";import{n as oe}from"./command-metadata.js";import"./command.js";import{t as se}from"./session-artifact-paths.js";import{a as ce}from"./version.js";import{t as le}from"./daemon-resolution.js";import{r as x,t as ue}from"./command-schema.js";import{i as S,r as C,t as de}from"./cli-config.js";import{t as fe}from"./update-check.js";import{n as pe,r as me,t as he}from"./cli-command-aliases.js";import{exitAfterFlush as w}from"./process-exit.js";import{A as ge,D as _e,M as ve,f as ye,h as be,j as xe,k as Se,r as Ce}from"./connection-runtime.js";import{i as we}from"./auth-session.js";import T from"node:fs";import{pathToFileURL as Te}from"node:url";const E=`open <app> --relaunch`,Ee={start:{command:`open`,example:E},restart:{command:`open`,example:E},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 D(e){if(e.length<=2)return[];let t=re(),n=t.filter(t=>t.startsWith(e));return n.length>0?n.sort(O).slice(0,3):k(e,t)}function O(e,t){return e.length-t.length||e.localeCompare(t)}function k(e,t){let n=t.map(t=>({name:t,distance:Oe(e,t)})).filter(t=>t.distance<=De(e));if(n.length===0)return[];let r=Math.min(...n.map(e=>e.distance));return n.filter(e=>e.distance===r).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function De(e){return e.length<4?1:e.length<=6?2:3}function Oe(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):ke(e,t)}function ke(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 A(e){let t=e.toLowerCase(),n=Ee[t]?.example;if(n)return n;let r=D(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const Ae=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),je=new Set([`--session-locked`,`--session-lock-conflicts`]),Me={"--output":`--out`,"--path":`--out`};function Ne(e,t){let n=e.toLowerCase(),r=Me[n];if(r&&Pe(r,t))return r;let i=Fe(n,t);if(i.length!==0)return i.length===1?i[0]:`one of: ${i.join(`, `)}`}function Pe(e,t){let n=b().find(t=>t.names.includes(e));return n?S(n.key,t):!1}function Fe(e,t){let n=j(e);if(n.length<=2)return[];let r=Ie(t),i=r.filter(e=>j(e).startsWith(n));return i.length>0?i.sort(O).slice(0,3):k(n,r.map(e=>j(e))).map(e=>`--${e}`)}function Ie(e){let t=new Set;for(let n of b()){if(!S(n.key,e))continue;let r=n.names[0];r&&t.add(r)}return[...t]}function j(e){return e.replace(/^--?/,``)}function Le(e,t){let n=e.toLowerCase();if(Ae.has(n))return`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${E}.`;if(je.has(n))return`Unknown flag: ${e}. Use --session-lock reject|strip instead.`;if(n===i.cliToken)return`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`;let r=Ne(e,t);return r?`Unknown flag: ${e}. Did you mean ${r}?`:`Unknown flag: ${e}`}function M(e){let t={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ve(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(ze(r,f))continue;let m=He(f,r);if(Be(r,m)){a.push(l);continue}if(!m){if(qe(r,a,l)){r?a.push(l):r=l;continue}throw new n(`INVALID_ARGS`,Le(f,r))}let h=Ge(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 Re(i,t),{command:r,positionals:a,flags:t,warnings:o,providedFlags:s}}function Re(e,t){if(e)for(let n of he(e)?.impliedFlags??[])t[n]=!0}function ze(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Be(e,t){return e===`react-devtools`?!t||!S(t.key,e):!1}function Ve(e){return e===`cdp`}function He(e,t){let n=b().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??y(e);if(t){let e=n.find(e=>S(e.key,t));if(e)return e}return y(e)}function Ue(e,t){let r=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=A(e.command),r=t?`Unknown command: ${e.command}. Did you mean ${t}?`:`Unknown command: ${e.command}`;throw new n(`INVALID_ARGS`,r)}let o=e.providedFlags.filter(t=>!S(t.key,e.command));if(o.length>0){let t=o.map(e=>e.token),s=$e(e.command,t);if(r)throw new n(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}let s=Ze(e);if(s.length>0){let t=Qe(e.command,e.positionals[0],s);if(r)throw new n(`INVALID_ARGS`,t);i.push(t);for(let e of s)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(S(t,e.command)||delete a[t]);Xe(e,a),We(e),ne(e.command,a);let c=Ye({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(ue(c.command,c.positionals),c.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new n(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return c}function We(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 n(`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 Ge(e,t,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new n(`INVALID_ARGS`,`Flag ${t} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Ke(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new n(`INVALID_ARGS`,`Flag ${t} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new n(`INVALID_ARGS`,`Invalid ${P(t)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new n(`INVALID_ARGS`,`Invalid ${P(t)}: ${a}`);return{value:e.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 y(t)!==void 0}function Ke(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 qe(e,t,n){if(!Je(n)||!e)return!1;let r=x(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 Je(e){return/^-\d+(\.\d+)?$/.test(e)}function Ye(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 Xe(e,t){let n=x(e.command)?.explicitOnlyFlags;if(n===void 0)return;let r=new Set(e.providedFlags.map(e=>e.key));for(let e of n)r.has(e)||delete t[e]}function Ze(e){let t=x(e.command)?.flagsByAction,n=e.positionals[0];if(t===void 0||n===void 0||!Object.hasOwn(t,n))return[];let r=t[n];if(r===void 0)return[];let i=new Set(Object.values(t).flat());return e.providedFlags.filter(e=>i.has(e.key)&&!r.includes(e.key))}function Qe(e,t,n){return`${e} ${t} does not read ${n.map(e=>e.token).join(`, `)}. Run \`${e} ${t} --help\` for the options it reads.`}function $e(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 et(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(e){let t=me(e);if(t)throw new n(`INVALID_ARGS`,t);return pe(e)}function tt(){return{renderedToStderr:!1}}function nt(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function rt(e){return oe(e)}const it={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,plugins:async()=>(await import(`./plugins2.js`)).pluginsCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device3.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,record:async()=>(await import(`./recording.js`)).recordingCommand};async function R(e){let t={...e.flags},n=it[e.command];return n&&await(await n())({...e,flags:t})?!0:rt(e.command)?await at({...e,command:e.command,flags:t}):!1}async function at(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function ot(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function st(e){return e===`ios-instance`}function ct(e){return e[0]===`wait`&&e.includes(`--connected`)}function lt(e,t,n){n===0||!ct(e)||!st(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 ut(e){if(!e?.metroProxyBaseUrl||!ge(e.leaseBackend))return null;let t=[],r={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 n(`INVALID_ARGS`,`react-devtools remote bridge requires ${t.join(`, `)}.`,{missing:t});return r}async function dt(e,t,n){let{flags:r}=t,i=ut(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 ve({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await xe({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 ft(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?ye(n.leaseProvider).supportsDirectPortReverse&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function pt(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await dt(e,t,async()=>(ft(e,t)&&await t.configureDirectPortReverse?.(),(await ae(`npm`,ot(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return lt(e,t.flags,i),i}const B=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,mt=`${te} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function ht(e){let t;try{t=JSON.parse(e)}catch{throw new n(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(t)||t.length===0)throw new n(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return t.map((e,t)=>gt(e,t+1))}function gt(e,t){let r=o(e,t,B),i=[`positionals`,`flags`].filter(e=>e in r);if(i.length>0){let e=i.map(e=>`"${e}"`).join(`, `);throw new n(`INVALID_ARGS`,`Batch step ${t} uses removed field(s): ${e}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:B})}ie(r,[`command`,`input`,`runtime`],`Batch step ${t}`,B);let s=c(r.runtime,t);return{command:ee(r.command,t,mt),input:a(r,t,B),...s===void 0?{}:{runtime:s}}}function V(e,t={}){let n=H(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function H(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??vt(t.AGENT_DEVICE_PLATFORM),r=bt(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:_t(e.policyOverrides,t,r)}}function _t(e,t,n){let r=e?.sessionLock??yt(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function vt(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`ios`||t===`android`||t===`apple`)return t;throw new n(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function yt(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`reject`||t===`strip`)return t;throw new n(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function bt(e){return typeof e==`string`&&e.trim().length>0}function xt(e,t){let n=M(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=St(n.command)?be({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=C(de({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Ue(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function St(e){return e!==null}v.runtime;async function Ct(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const U=(e,t={})=>import(`./error.js`).then(e=>e.t).then(({printHumanError:n})=>n(e,t)),W=e=>import(`./json.js`).then(({printJson:t})=>t(e)),wt={sendToDaemon:g},Tt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),Et=new Set([`connect`,`connection`,`close`,`daemon`,`plugins`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function G(e,t=wt){let n=f(),r=ce(),i=It(e),a=e.includes(`--json`),o=Jt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await d({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await Dt(e,{version:r,jsonRequested:a,debugEnabled:i}),l=Z(s,o.providedFlags),u=await Ot(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});K(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await w(await kt(u,t));return}if(s===`web`){let{runWebCommand:e}=await import(`./web.js`);await w(await e(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(fe({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await At(u,t),K(u.effectiveFlags),s===`cdp`){await w(await Se(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=jt(u);let e=await Mt(u),n=tt();await Nt(u,h(q(u),{transport:qt({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await Pt(e,u,d)}finally{d&&d()}})}function K(e){e.daemonAuthToken&&p(e.daemonAuthToken)}async function Dt(e,r){let i;try{i=xt(e,{cwd:process.cwd(),env:process.env})}catch(e){m({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let n=t(e,{diagnosticId:l().diagnosticId,logPath:u({force:!0})?.path});return r.jsonRequested?await W({success:!1,error:n}):await U(n,{showDetails:r.debugEnabled}),w(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),w(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return await U(new n(`INVALID_ARGS`,`help accepts at most one command.`)),w(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await I()}\n`),w(0);let t=await et(e);return t?(process.stdout.write(t),w(0)):(await U(new n(`INVALID_ARGS`,X(e))),process.stdout.write(`${await I()}\n`),w(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await I()}\n`),w(1))}async function Ot(n,r){let i=new Set(n.providedFlags.map(e=>e.key));try{let e=H({policyOverrides:n.flags,configuredPlatform:n.flags.platform,configuredSession:n.flags.session}),t=e.lockPolicy?{...n.flags}:V(n.flags,{policyOverrides:n.flags,configuredPlatform:n.flags.platform,configuredSession:n.flags.session}),a=le(t.stateDir),o=t.session??`default`,s=Bt({command:r.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:t.remoteConfig,hasResolvedSession:t.session!==void 0}),c=s?Gt(t,s.flags,i):t;return{...r,binding:e,flags:t,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(i),o=t(a,{diagnosticId:l().diagnosticId,logPath:u({force:!0})?.path});return n.flags.json?await W({success:!1,error:o}):await U(o,{showDetails:r.debugOutputEnabled}),w(1)}}async function kt(e,t){let{daemonAuthToken:n,...i}=e.effectiveFlags;return await pt(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 Ct({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:t.sendToDaemon,transportOptions:{authToken:n}});a.ok||r(a.error)}})}async function At(e,t){if(e.command===`batch`){if(e.positionals.length>0)throw new n(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=Rt(e.flags)}if(Ht(e.command)&&(e.effectiveFlags=(await we({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&Vt(e.command)){let n=h(q(e),{transport:Q(t.sendToDaemon)}),r=await Ce({command:e.command,flags:e.effectiveFlags,client:n,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Kt(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Ut({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 q(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,providerAppiumVersion:t.providerAppiumVersion,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 jt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Yt(e.daemonPaths.logPath):null}async function Mt(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 Nt(e,t,r,i){let{command:a,positionals:o,effectiveFlags:s}=e;if(a===`batch`){if(!e.parsedBatchSteps)throw new n(`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}:V(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:r,commandProgress:i}))return}else if(a===`runtime`)throw new n(`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:r,commandProgress:i}))return;throw new n(`INVALID_ARGS`,Lt(a))}async function Pt(n,r,i){let a=e(n),o=t(a,{diagnosticId:l().diagnosticId,logPath:u({force:!0})?.path});if(r.command===`close`&&zt(a)){r.effectiveFlags.json&&await W({success:!0,data:{closed:`session`,source:`no-daemon`}});return}r.effectiveFlags.json?await W({success:!1,error:o}):(await U(o,{showDetails:r.debugOutputEnabled}),r.debugOutputEnabled&&Ft(r,o)),i&&i(),await w(1)}const J=64e3;function Ft(e,t){if(!e.effectiveFlags.daemonBaseUrl){Y(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&Y(`remote diagnostics`,se(e.daemonPaths.baseDir,n))}function Y(e,t){try{if(T.existsSync(t)){let n=T.readFileSync(t,`utf8`).split(`
1
+ import{F as e,J as t,P as n,nt as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,f as o,s,u as c}from"./sdk-batch-runner.js";import{R as l}from"./registry.js";import{a as u,i as d,l as f,n as p,o as m,r as h}from"./diagnostics.js";import"./diagnostics2.js";import{n as g,r as ee}from"./agent-device-client.js";import{s as te,t as ne,u as re}from"./sdk-batch.js";import{i as ie,r as _,t as v}from"./catalog.js";import{n as y,r as b}from"./back-mode.js";import{n as ae}from"./command-metadata.js";import{t as oe}from"./session-artifact-paths.js";import{a as se}from"./version.js";import{t as x}from"./daemon-resolution.js";import{r as S,t as ce}from"./command-schema.js";import{i as C,r as w,t as le}from"./cli-config.js";import{t as ue}from"./update-check.js";import{n as de,r as fe,t as pe}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{_ as me,m as he,v as ge}from"./remote-connection-state.js";import{i as _e}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as ve}from"node:url";const D=`open <app> --relaunch`,ye={start:{command:`open`,example:D},restart:{command:`open`,example:D},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 be(e){if(e.length<=2)return[];let t=ie(),n=t.filter(t=>t.startsWith(e));return n.length>0?n.sort(O).slice(0,3):k(e,t)}function O(e,t){return e.length-t.length||e.localeCompare(t)}function k(e,t){let n=t.map(t=>({name:t,distance:Se(e,t)})).filter(t=>t.distance<=xe(e));if(n.length===0)return[];let r=Math.min(...n.map(e=>e.distance));return n.filter(e=>e.distance===r).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function xe(e){return e.length<4?1:e.length<=6?2:3}function Se(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):A(e,t)}function A(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=ye[t]?.example;if(n)return n;let r=be(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const Ce=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),we=new Set([`--session-locked`,`--session-lock-conflicts`]),Te={"--output":`--out`,"--path":`--out`};function Ee(e,t){let n=e.toLowerCase(),r=Te[n];if(r&&De(r,t))return r;let i=Oe(n,t);if(i.length!==0)return i.length===1?i[0]:`one of: ${i.join(`, `)}`}function De(e,t){let n=b().find(t=>t.names.includes(e));return n?C(n.key,t):!1}function Oe(e,t){let n=M(e);if(n.length<=2)return[];let r=ke(t),i=r.filter(e=>M(e).startsWith(n));return i.length>0?i.sort(O).slice(0,3):k(n,r.map(e=>M(e))).map(e=>`--${e}`)}function ke(e){let t=new Set;for(let n of b()){if(!C(n.key,e))continue;let r=n.names[0];r&&t.add(r)}return[...t]}function M(e){return e.replace(/^--?/,``)}function Ae(e,t){let n=e.toLowerCase();if(Ce.has(n))return`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${D}.`;if(we.has(n))return`Unknown flag: ${e}. Use --session-lock reject|strip instead.`;if(n===i.cliToken)return`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`;let r=Ee(e,t);return r?`Unknown flag: ${e}. Did you mean ${r}?`:`Unknown flag: ${e}`}function N(e){let t={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=R(l));continue}if(Pe(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=R(l));continue}let[f,p]=u?P(l):[l,void 0];if(Me(r,f))continue;let m=Fe(f,r);if(Ne(r,m)){a.push(l);continue}if(!m){if(Be(r,a,l)){r?a.push(l):r=l;continue}throw new n(`INVALID_ARGS`,Ae(f,r))}let h=Re(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 je(i,t),{command:r,positionals:a,flags:t,warnings:o,providedFlags:s}}function je(e,t){if(e)for(let n of pe(e)?.impliedFlags??[])t[n]=!0}function Me(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Ne(e,t){return e===`react-devtools`?!t||!C(t.key,e):!1}function Pe(e){return e===`cdp`}function Fe(e,t){let n=b().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??y(e);if(t){let e=n.find(e=>C(e.key,t));if(e)return e}return y(e)}function Ie(e,t){let r=t?.strictFlags??!0,i=[...e.warnings],a=w({json:!1,help:!1,version:!1},t?.defaultFlags??{});if(w(a,e.flags),e.command&&!_(e.command)&&!a.help){let t=j(e.command),r=t?`Unknown command: ${e.command}. Did you mean ${t}?`:`Unknown command: ${e.command}`;throw new n(`INVALID_ARGS`,r)}let o=e.providedFlags.filter(t=>!C(t.key,e.command));if(o.length>0){let t=o.map(e=>e.token),s=Ke(e.command,t);if(r)throw new n(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}let s=We(e);if(s.length>0){let t=Ge(e.command,e.positionals[0],s);if(r)throw new n(`INVALID_ARGS`,t);i.push(t);for(let e of s)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(C(t,e.command)||delete a[t]);Ue(e,a),Le(e),re(e.command,a);let c=He({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(ce(c.command,c.positionals),c.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new n(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return c}function Le(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 n(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function P(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Re(e,t,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new n(`INVALID_ARGS`,`Flag ${t} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||I(i)?{value:!0,consumeNext:!1}:ze(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&I(a))throw new n(`INVALID_ARGS`,`Flag ${t} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new n(`INVALID_ARGS`,`Invalid ${F(t)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new n(`INVALID_ARGS`,`Invalid ${F(t)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function F(e){return e.replace(/^-+/,``)}function I(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?P(e):[e,void 0];return y(t)!==void 0}function ze(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 Be(e,t,n){if(!Ve(n)||!e)return!1;let r=S(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Ve(e){return/^-\d+(\.\d+)?$/.test(e)}function He(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 Ue(e,t){let n=S(e.command)?.explicitOnlyFlags;if(n===void 0)return;let r=new Set(e.providedFlags.map(e=>e.key));for(let e of n)r.has(e)||delete t[e]}function We(e){let t=S(e.command)?.flagsByAction,n=e.positionals[0];if(t===void 0||n===void 0||!Object.hasOwn(t,n))return[];let r=t[n];if(r===void 0)return[];let i=new Set(Object.values(t).flat());return e.providedFlags.filter(e=>i.has(e.key)&&!r.includes(e.key))}function Ge(e,t,n){return`${e} ${t} does not read ${n.map(e=>e.token).join(`, `)}. Run \`${e} ${t} --help\` for the options it reads.`}function Ke(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 L(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function qe(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(R(e))}function R(e){let t=fe(e);if(t)throw new n(`INVALID_ARGS`,t);return de(e)}function Je(){return{renderedToStderr:!1}}function Ye(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function Xe(e){return ae(e)}const Ze={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,plugins:async()=>(await import(`./plugins2.js`)).pluginsCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device3.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,record:async()=>(await import(`./recording.js`)).recordingCommand};async function z(e){let t={...e.flags},n=Ze[e.command];return n&&await(await n())({...e,flags:t})?!0:Xe(e.command)?await Qe({...e,command:e.command,flags:t}):!1}async function Qe(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}const B=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,$e=`${ne} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function et(e){let t;try{t=JSON.parse(e)}catch{throw new n(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(t)||t.length===0)throw new n(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return t.map((e,t)=>tt(e,t+1))}function tt(e,t){let r=o(e,t,B),i=[`positionals`,`flags`].filter(e=>e in r);if(i.length>0){let e=i.map(e=>`"${e}"`).join(`, `);throw new n(`INVALID_ARGS`,`Batch step ${t} uses removed field(s): ${e}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:B})}l(r,[`command`,`input`,`runtime`],`Batch step ${t}`,B);let s=c(r.runtime,t);return{command:te(r.command,t,$e),input:a(r,t,B),...s===void 0?{}:{runtime:s}}}function V(e,t={}){let n=H(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function H(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??rt(t.AGENT_DEVICE_PLATFORM),r=at(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:nt(e.policyOverrides,t,r)}}function nt(e,t,n){let r=e?.sessionLock??it(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function rt(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`ios`||t===`android`||t===`apple`)return t;throw new n(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function it(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`reject`||t===`strip`)return t;throw new n(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function at(e){return typeof e==`string`&&e.trim().length>0}function ot(e,t){let n=N(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=st(n.command)?me({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=w(le({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Ie(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function st(e){return e!==null}v.runtime;async function ct(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const U=(e,t={})=>import(`./error.js`).then(e=>e.t).then(({printHumanError:n})=>n(e,t)),W=e=>import(`./json.js`).then(({printJson:t})=>t(e)),lt={sendToDaemon:ee},ut=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),dt=new Set([`connect`,`connection`,`close`,`daemon`,`plugins`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function G(e,t=lt){let n=p(),r=se(),i=xt(e),a=e.includes(`--json`),o=Nt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await f({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await ft(e,{version:r,jsonRequested:a,debugEnabled:i}),l=Z(s,o.providedFlags),u=await pt(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});K(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await T(await mt(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(ue({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await ht(u,t),K(u.effectiveFlags),s===`cdp`){await T(await ge(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=gt(u);let e=await _t(u),n=Je();await vt(u,g(q(u),{transport:Mt({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await yt(e,u,d)}finally{d&&d()}})}function K(e){e.daemonAuthToken&&m(e.daemonAuthToken)}async function ft(e,r){let i;try{i=ot(e,{cwd:process.cwd(),env:process.env})}catch(e){h({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let n=t(e,{diagnosticId:u().diagnosticId,logPath:d({force:!0})?.path});return r.jsonRequested?await W({success:!1,error:n}):await U(n,{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 U(new n(`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 L()}\n`),T(0);let t=await qe(e);return t?(process.stdout.write(t),T(0)):(await U(new n(`INVALID_ARGS`,St(e))),process.stdout.write(`${await L()}\n`),T(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await L()}\n`),T(1))}async function pt(n,r){let i=new Set(n.providedFlags.map(e=>e.key));try{let e=H({policyOverrides:n.flags,configuredPlatform:n.flags.platform,configuredSession:n.flags.session}),t=e.lockPolicy?{...n.flags}:V(n.flags,{policyOverrides:n.flags,configuredPlatform:n.flags.platform,configuredSession:n.flags.session}),a=x(t.stateDir),o=t.session??`default`,s=Tt({command:r.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:t.remoteConfig,hasResolvedSession:t.session!==void 0}),c=s?At(t,s.flags,i):t;return{...r,binding:e,flags:t,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(i),o=t(a,{diagnosticId:u().diagnosticId,logPath:d({force:!0})?.path});return n.flags.json?await W({success:!1,error:o}):await U(o,{showDetails:r.debugOutputEnabled}),T(1)}}async function mt(e,t){let{runReactDevtoolsCommand:n}=await import(`./react-devtools.js`),{daemonAuthToken:i,...a}=e.effectiveFlags;return await n(e.positionals,{flags:{...a,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let n=await ct({route:`react-devtools`,command:v.runtime,request:{positionals:[`port-reverse`],flags:{...a,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},transport:t.sendToDaemon,transportOptions:{authToken:i}});n.ok||r(n.error)}})}async function ht(e,t){if(e.command===`batch`){if(e.positionals.length>0)throw new n(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=Ct(e.flags)}if(Dt(e.command)&&(e.effectiveFlags=(await _e({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&Et(e.command)){let n=g(q(e),{transport:Q(t.sendToDaemon)}),{materializeRemoteConnectionForCommand:r}=await import(`./connection-runtime.js`),i=await r({command:e.command,flags:e.effectiveFlags,client:n,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:jt(e.explicitFlagKeys)});e.effectiveFlags=i.flags,e.resolvedRuntime=i.runtime,e.connectionMetadata=i.connection}Ot({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.
2
+ `)}function q(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,providerDeviceType:t.providerDeviceType,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerAppiumVersion:t.providerAppiumVersion,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 gt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Pt(e.daemonPaths.logPath):null}async function _t(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 vt(e,t,r,i){let{command:a,positionals:o,effectiveFlags:s}=e;if(a===`batch`){if(!e.parsedBatchSteps)throw new n(`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}:V(t.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await z({command:a,positionals:o,flags:{...s,batchSteps:c},client:t,debug:e.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return}else if(a===`runtime`)throw new n(`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 z({command:a,positionals:o,flags:s,client:t,debug:e.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return;throw new n(`INVALID_ARGS`,X(a))}async function yt(n,r,i){let a=e(n),o=t(a,{diagnosticId:u().diagnosticId,logPath:d({force:!0})?.path});if(r.command===`close`&&wt(a)){r.effectiveFlags.json&&await W({success:!0,data:{closed:`session`,source:`no-daemon`}});return}r.effectiveFlags.json?await W({success:!1,error:o}):(await U(o,{showDetails:r.debugOutputEnabled}),r.debugOutputEnabled&&bt(r,o)),i&&i(),await T(1)}const J=64e3;function bt(e,t){if(!e.effectiveFlags.daemonBaseUrl){Y(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&Y(`remote diagnostics`,oe(e.daemonPaths.baseDir,n))}function Y(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
4
3
  `),r=n.slice(Math.max(0,n.length-200)).join(`
5
- `);r.length>J&&(r=r.slice(r.length-J)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function It(e){try{let t=M(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function X(e){let t=A(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Lt(e){return _(e)?(m({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 Rt(e){let t=``;if(e.steps)t=e.steps;else if(e.stepsFile)try{t=T.readFileSync(e.stepsFile,`utf8`)}catch(t){let r=t instanceof Error?t.message:String(t);throw new n(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return ht(t)}function zt(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 Bt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`plugins`||e.command===`proxy`?null:_e({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 Vt(e){return!Et.has(e)}function Ht(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`plugins`&&e!==`device`&&e!==`proxy`}function Ut(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Wt(e.explicitFlagKeys)}function Wt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Gt(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 Kt(e){for(let t of Tt)if(e.has(t))return!0;return!1}function qt(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:nt(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 Jt(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}Te(process.argv[1]??``).href===import.meta.url&&G(process.argv.slice(2)).catch(async n=>{let r=e(n);await U(t(r),{showDetails:!0}),await w(1)});function Yt(e){try{let t=T.existsSync(e)?T.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&T.existsSync(e))try{let n=T.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=T.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);T.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{T.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{G as runCli};
4
+ `);r.length>J&&(r=r.slice(r.length-J)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function xt(e){try{let t=N(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function St(e){let t=j(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function X(e){return _(e)?(h({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 Ct(e){let t=``;if(e.steps)t=e.steps;else if(e.stepsFile)try{t=E.readFileSync(e.stepsFile,`utf8`)}catch(t){let r=t instanceof Error?t.message:String(t);throw new n(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return et(t)}function wt(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 Tt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`plugins`||e.command===`proxy`?null:he({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 Et(e){return!dt.has(e)}function Dt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`plugins`&&e!==`device`&&e!==`proxy`}function Ot(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:kt(e.explicitFlagKeys)}function kt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function At(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 jt(e){for(let t of ut)if(e.has(t))return!0;return!1}function Mt(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:Ye(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 Nt(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`--session=`)){let e=n.slice(10).trim();return e.length>0?e:null}if(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}ve(process.argv[1]??``).href===import.meta.url&&G(process.argv.slice(2)).catch(async n=>{let r=e(n);await U(t(r),{showDetails:!0}),await T(1)});function Pt(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{G as runCli};
@@ -0,0 +1 @@
1
+ import{O as e,S as t,m as n,w as r}from"./owner-identity.js";import{d as i}from"./exec.js";import"./command.js";import"./process.js";import{a,c as o,d as s,f as c,i as l,l as u,m as d,o as f,p,r as m,s as h,t as g,u as _}from"./base-url.js";import{createHash as v}from"node:crypto";import y from"node:fs";import b from"node:path";import{fileURLToPath as x}from"node:url";const S=`companion-tunnel`;function C(e){return v(`sha256`).update(e).digest(`hex`)}function w(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function T(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 E(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function D(e,t,n,r){let i=r??b.join(e,`.agent-device`);if(!n)return{statePath:b.join(i,`${t.slug}.json`),logPath:b.join(i,`${t.slug}.log`)};let a=C(n).slice(0,12),o=b.join(i,t.slug);return{statePath:b.join(o,`${t.slug}-${a}.json`),logPath:b.join(o,`${t.slug}-${a}.log`)}}function O(e){try{let t=JSON.parse(y.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:w(t.launchUrl),registerPath:w(t.registerPath),unregisterPath:w(t.unregisterPath),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:w(t.session),bridgeScope:T(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function k(e,t){y.mkdirSync(b.dirname(e),{recursive:!0}),y.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function A(e){y.mkdirSync(b.dirname(e),{recursive:!0}),y.closeSync(y.openSync(e,`a`))}function j(e){try{y.unlinkSync(e)}catch{}}function M(e){try{y.readdirSync(e).length===0&&y.rmdirSync(e)}catch{}}function N(e,t){let n=b.dirname(e.statePath),r=b.dirname(e.logPath);j(e.statePath),j(e.logPath),M(n),r!==n&&M(r),b.basename(n)===t.slug&&M(b.dirname(n))}function P(e,t){return e.includes(t.runArg)}function F(e,i){if(!n(e.pid))return!1;if(e.startTime){let t=r(e.pid);if(!t||t!==e.startTime)return!1}let a=t(e.pid);return!a||!P(a,i.definition)||!e.bridgeScope?!1:e.serverBaseUrl===g(i.serverBaseUrl)&&e.localBaseUrl===g(i.localBaseUrl)&&e.launchUrl===w(i.launchUrl)&&e.registerPath===w(i.registerPath)&&e.unregisterPath===w(i.unregisterPath)&&e.devicePort===i.devicePort&&e.session===w(i.session)&&E(e.bridgeScope,i.bridgeScope)&&e.tokenHash===C(i.bearerToken)}function I(e){return w(e.consumerKey)??w(e.profileKey)??null}function L(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function R(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function z(r,i){if(!n(r.pid))return;let a=t(r.pid);if(!(!a||!P(a,i))){try{process.kill(r.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await e(r.pid,1e3)){try{process.kill(r.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await e(r.pid,1e3)}}}function B(e,t,n){n===void 0?delete e[t]:e[t]=n}function V(e,t){let n={...t};return n[s]=g(e.serverBaseUrl),n[m]=e.bearerToken,n[f]=g(e.localBaseUrl),n[p]=D(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[_]=e.bridgeScope.tenantId,n[u]=e.bridgeScope.runId,n[o]=e.bridgeScope.leaseId,B(n,a,w(e.launchUrl)),B(n,h,w(e.registerPath)),B(n,d,w(e.unregisterPath)),B(n,l,e.devicePort===void 0?void 0:String(e.devicePort)),B(n,c,w(e.session)),n}function H(e){let t=x(import.meta.url),n=b.extname(t)||`.js`,r=[b.join(b.dirname(t),`${S}${n}`),b.join(b.dirname(t),`internal`,`${S}${n}`)].find(e=>y.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function U(e,n){let a=H(e.definition),o=a.endsWith(`.ts`)?[`--experimental-strip-types`]:[];y.mkdirSync(b.dirname(n),{recursive:!0});let s=y.openSync(n,`a`),c=0;try{c=i(process.execPath,[...o,a,e.definition.runArg],{env:V(e,e.env??process.env),stdio:[`ignore`,s,s]})}finally{y.closeSync(s)}if(!Number.isInteger(c)||c<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:c,startTime:r(c)??void 0,command:t(c)??void 0,serverBaseUrl:g(e.serverBaseUrl),localBaseUrl:g(e.localBaseUrl),launchUrl:w(e.launchUrl),registerPath:w(e.registerPath),unregisterPath:w(e.unregisterPath),devicePort:e.devicePort,session:w(e.session),bridgeScope:e.bridgeScope,tokenHash:C(e.bearerToken),consumers:[]}}async function W(e){let t=I(e),n=D(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=O(n.statePath);if(r&&F(r,e)){let e=L(r,t);return e!==r&&k(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await z(r,e.definition),N(n,e.definition)),A(n.statePath);let i;try{i=U(e,n.logPath),k(n.statePath,L(i,t))}catch(t){throw i&&await z(i,e.definition).catch(()=>{}),N(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function G(e){let t=I(e),n=D(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=O(n.statePath);if(!r)return N(n,e.definition),{stopped:!1,statePath:n.statePath};let i=R(r,t);return i.consumers.length>0?(k(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await z(r,e.definition),N(n,e.definition),{stopped:!0,statePath:n.statePath})}export{G as n,W as t};
@@ -1 +1 @@
1
- import{O as e,S as t,m as n,w as r}from"./owner-identity.js";import{d 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{createHash as y}from"node:crypto";import b from"node:fs";import x from"node:path";import{fileURLToPath as S}from"node:url";const C=`companion-tunnel`;function w(e){return y(`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??x.join(e,`.agent-device`);if(!n)return{statePath:x.join(i,`${t.slug}.json`),logPath:x.join(i,`${t.slug}.log`)};let a=w(n).slice(0,12),o=x.join(i,t.slug);return{statePath:x.join(o,`${t.slug}-${a}.json`),logPath:x.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(x.dirname(e),{recursive:!0}),b.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function j(e){b.mkdirSync(x.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=x.dirname(e.statePath),r=x.dirname(e.logPath);M(e.statePath),N(e.logPath),P(n),r!==n&&P(r),x.basename(n)===t.slug&&P(x.dirname(n))}function I(e,t){return e.includes(t.runArg)}function L(e,i){if(!n(e.pid))return!1;if(e.startTime){let t=r(e.pid);if(!t||t!==e.startTime)return!1}let a=t(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(r,i){if(!n(r.pid))return;let a=t(r.pid);if(!(!a||!I(a,i))){try{process.kill(r.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await e(r.pid,1e3)){try{process.kill(r.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await e(r.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=x.extname(t)||`.js`,r=[x.join(x.dirname(t),`${C}${n}`),x.join(x.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,n){let a=U(e.definition),o=a.endsWith(`.ts`)?[`--experimental-strip-types`]:[];b.mkdirSync(x.dirname(n),{recursive:!0});let s=b.openSync(n,`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:r(c)??void 0,command:t(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
+ import{h as e}from"./base-url.js";import{n as t,t as n}from"./client-companion-tunnel.js";const r={slug:`metro-companion`,runArg:e,displayName:`Metro companion`};async function i(e){return await n({...e,definition:r,registerPath:e.registerPath??`/api/metro/companion/register`})}async function a(e){return await t({...e,definition:r})}export{a as n,i as t};
@@ -1 +1 @@
1
- import{F as e,P as t}from"./sdk-contracts.js";import{O as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{d as i,m as a}from"./exec.js";import{t as o}from"./timeouts.js";import"./file.js";import"./command.js";import"./process.js";import"./retry.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:fs";import p from"node:path";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 f.accessSync(e,f.constants.F_OK),!0}catch{return!1}}function D(e){try{return f.statSync(e).isDirectory()}catch{return!1}}function O(e){let n=p.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(p.join(t,e)))return{command:n,installArgs:[`install`]};if(E(p.join(t,`.git`)))return null;let e=p.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(p.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(p.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{a(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,a,o,s,c){let l=U(n,r,a,o);f.mkdirSync(p.dirname(s),{recursive:!0});let u=f.openSync(s,`a`),d=0;try{d=i(l.command,l.installArgs,{cwd:e,env:c,stdio:[`ignore`,u,u]})}finally{f.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??p.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&&(f.mkdirSync(p.dirname(e),{recursive:!0}),f.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{F as e,P as t}from"./sdk-contracts.js";import{O as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{d as i,m as a}from"./exec.js";import{i as o}from"./retry.js";import"./file.js";import"./command.js";import"./process.js";import"./retry2.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:fs";import p from"node:path";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 f.accessSync(e,f.constants.F_OK),!0}catch{return!1}}function D(e){try{return f.statSync(e).isDirectory()}catch{return!1}}function O(e){let n=p.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(p.join(t,e)))return{command:n,installArgs:[`install`]};if(E(p.join(t,`.git`)))return null;let e=p.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(p.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(p.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{a(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,a,o,s,c){let l=U(n,r,a,o);f.mkdirSync(p.dirname(s),{recursive:!0});let u=f.openSync(s,`a`),d=0;try{d=i(l.command,l.installArgs,{cwd:e,env:c,stdio:[`ignore`,u,u]})}finally{f.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??p.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&&(f.mkdirSync(p.dirname(e),{recursive:!0}),f.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,7 +1,8 @@
1
- import { B as SnapshotViewportSize, D as IosTargetActivation, E as AppleApplicationState, K as DaemonError, L as SnapshotQualityVerdict, M as SnapshotCommandOptionFields, N as SnapshotKeyboardBandFact, P as SnapshotNode, S as DeviceTarget, T as PublicPlatform, V as SnapshotVisibility, Y as NormalizedError, _ as SessionIsolationMode, a as DaemonRequest, f as LeaseBackend, g as ResponseLevel, i as DaemonLockPolicy, m as NetworkIncludeMode, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as SessionRuntimeHints, w as PlatformSelector, x as DeviceKind, y as AppleOS, z as SnapshotUnchanged } from "./sdk-contracts.js";
2
- import { n as GesturePointerCount, s as AppsFilter } from "./gesture-plan-types.js";
3
- import { A as BackMode, C as SwipePattern, D as FoldPose, E as DeviceRotation, O as FoldScreenCoordinateSpace, S as ScrollInputDirection, T as TransformGestureParams, _ as TextSizeCategory, c as SnapshotDiagnosticsSummary, d as MOBILE_PERMISSION_TARGETS, f as PermissionAction, i as AndroidSnapshotBackendMetadata, k as SetFoldPoseInput, l as SessionSurface, o as FindLocator, p as PermissionMode, r as CloudProviderSessionResult, s as ScreenshotResultData, t as AgentArtifactsResult, u as MACOS_PERMISSION_TARGETS, v as TvRemoteButton, w as SwipePreset, x as ScrollDirection, y as ScrollCommandResult } from "./cloud-artifacts.js";
1
+ import { B as SnapshotUnchanged, D as IosSnapshotObservation, E as AppleApplicationState, F as SnapshotNode, H as SnapshotVisibility, N as SnapshotCommandOptionFields, O as IosTargetActivation, P as SnapshotKeyboardBandFact, R as SnapshotQualityVerdict, S as DeviceTarget, T as PublicPlatform, V as SnapshotViewportSize, X as NormalizedError, _ as SessionIsolationMode, a as DaemonRequest, f as LeaseBackend, g as ResponseLevel, i as DaemonLockPolicy, m as NetworkIncludeMode, o as DaemonResponse, q as DaemonError, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as SessionRuntimeHints, w as PlatformSelector, x as DeviceKind, y as AppleOS } from "./sdk-contracts.js";
2
+ import { t as AppsFilter } from "./app-inventory.js";
3
+ import { A as SetFoldPoseInput, C as ScrollInputDirection, D as DeviceRotation, E as TransformGestureParams, O as FoldPose, S as ScrollDirection, T as SwipePreset, a as AndroidSnapshotBackendMetadata, b as ScrollCommandResult, c as ScreenshotResultData, d as MACOS_PERMISSION_TARGETS, f as MOBILE_PERMISSION_TARGETS, i as CloudProviderSessionResult, j as BackMode, k as FoldScreenCoordinateSpace, l as SnapshotDiagnosticsSummary, m as PermissionMode, p as PermissionAction, s as FindLocator, t as AgentArtifactsResult, u as SessionSurface, v as TextSizeCategory, w as SwipePattern, y as TvRemoteButton } from "./cloud-artifacts.js";
4
4
  import { _ as PressCommandResponseData, f as ClickCommandResponseData, g as LongPressCommandResponseData, h as HoverCommandResponseData, m as FindCommandResponseData, p as FillCommandResponseData, v as SettleObservation, y as ClickButton } from "./sdk-selectors.js";
5
+ import { n as GesturePointerCount } from "./gesture-plan-types.js";
5
6
  import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
6
7
  import { t as BatchRunResult } from "./sdk-batch-runner.js";
7
8
  //#region packages/contracts/src/json.d.ts
@@ -57,7 +58,7 @@ type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProf
57
58
  iosXctestDerivedDataPath?: string;
58
59
  iosXctestEnvDir?: string;
59
60
  };
60
- type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerAppiumVersion' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'> & {
61
+ type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerDeviceType' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerAppiumVersion' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'> & {
61
62
  /**
62
63
  * Cancels this one call. Already aborted: the call rejects without sending anything
63
64
  * (`details.dispatched: 'no'`). Aborted in flight: the request's connection closes, the daemon
@@ -363,8 +364,9 @@ type SnapshotCaptureAnnotations = {
363
364
  warnings?: string[];
364
365
  /** The Apple runner re-activated the session app while serving this capture (#2682). */
365
366
  targetActivation?: IosTargetActivation;
367
+ observation?: IosSnapshotObservation;
366
368
  };
367
- type PublicSnapshotCaptureAnnotations = Pick<SnapshotCaptureAnnotations, 'androidSnapshot' | 'warnings' | 'targetActivation'> & {
369
+ type PublicSnapshotCaptureAnnotations = Pick<SnapshotCaptureAnnotations, 'androidSnapshot' | 'warnings' | 'targetActivation' | 'observation'> & {
368
370
  snapshotQuality?: SnapshotQualityVerdict;
369
371
  };
370
372
  //#endregion
@@ -1,4 +1,4 @@
1
- import { B as SnapshotViewportSize, L as SnapshotQualityVerdict, P as SnapshotNode, R as SnapshotState, T as PublicPlatform, j as ScreenshotOverlayRef, n as DaemonArtifactType } from "./sdk-contracts.js";
1
+ import { D as IosSnapshotObservation, F as SnapshotNode, M as ScreenshotOverlayRef, R as SnapshotQualityVerdict, T as PublicPlatform, V as SnapshotViewportSize, n as DaemonArtifactType, z as SnapshotState } from "./sdk-contracts.js";
2
2
  import { v as SettleObservation } from "./sdk-selectors.js";
3
3
  //#region packages/contracts/src/back-mode.d.ts
4
4
  declare const BACK_MODES: readonly ['in-app', 'system'];
@@ -295,6 +295,7 @@ type BackendSnapshotResult = {
295
295
  };
296
296
  quality?: SnapshotQualityVerdict;
297
297
  warnings?: string[];
298
+ observation?: IosSnapshotObservation;
298
299
  };
299
300
  type AndroidSnapshotBackendMetadata = {
300
301
  backend: 'android-helper';
@@ -399,4 +400,4 @@ type CloudArtifactProvider = {
399
400
  listCloudArtifacts?: (query: CloudArtifactsQuery) => Promise<CloudArtifactsResult | undefined>;
400
401
  };
401
402
  //#endregion
402
- export { BackMode as A, SwipePattern as C, FoldPose as D, DeviceRotation as E, FoldScreenCoordinateSpace as O, ScrollInputDirection as S, TransformGestureParams as T, TextSizeCategory as _, BackendSnapshotResult as a, ScrollExecutionOptions as b, SnapshotDiagnosticsSummary as c, MOBILE_PERMISSION_TARGETS as d, PermissionAction as f, SettingOptions as g, ReadableSetting as h, AndroidSnapshotBackendMetadata as i, SetFoldPoseInput as k, SessionSurface as l, ReadSettingResult as m, CloudArtifactProvider as n, FindLocator as o, PermissionMode as p, CloudProviderSessionResult as r, ScreenshotResultData as s, AgentArtifactsResult as t, MACOS_PERMISSION_TARGETS as u, TvRemoteButton as v, SwipePreset as w, ScrollDirection as x, ScrollCommandResult as y };
403
+ export { SetFoldPoseInput as A, ScrollInputDirection as C, DeviceRotation as D, TransformGestureParams as E, FoldPose as O, ScrollDirection as S, SwipePreset as T, SettingOptions as _, AndroidSnapshotBackendMetadata as a, ScrollCommandResult as b, ScreenshotResultData as c, MACOS_PERMISSION_TARGETS as d, MOBILE_PERMISSION_TARGETS as f, ReadableSetting as g, ReadSettingResult as h, CloudProviderSessionResult as i, BackMode as j, FoldScreenCoordinateSpace as k, SnapshotDiagnosticsSummary as l, PermissionMode as m, CloudArtifactProvider as n, BackendSnapshotResult as o, PermissionAction as p, CloudArtifactsResult as r, FindLocator as s, AgentArtifactsResult as t, SessionSurface as u, TextSizeCategory as v, SwipePattern as w, ScrollExecutionOptions as x, TvRemoteButton as y };
@@ -1 +1 @@
1
- import{v as e}from"./sdk-batch.js";import{o as t}from"./registry.js";const n=t(),r=new Map(n.map(e=>[e.name,e]));function i(){return[...n]}function a(){return e().map(e=>{let t=s(e);if(!t)throw Error(`Missing command metadata for MCP-exposed command: ${e}`);return t})}function o(e){return r.has(e)}function s(e){return r.get(e)}export{a as i,o as n,i as r,s as t};
1
+ import{o as e}from"./registry.js";import{v as t}from"./sdk-batch.js";const n=e(),r=new Map(n.map(e=>[e.name,e]));function i(){return[...n]}function a(){return t().map(e=>{let t=s(e);if(!t)throw Error(`Missing command metadata for MCP-exposed command: ${e}`);return t})}function o(e){return r.has(e)}function s(e){return r.get(e)}export{a as i,o as n,i as r,s as t};
@@ -1,4 +1,4 @@
1
- import{P as e}from"./sdk-contracts.js";import{S as t,T as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={plugins:{text:{summary:`Manage installed provider plugins`,description:`Install, list, update, or remove npm provider plugins in AGENT_DEVICE_HOME (default ~/.agent-device). Changes take effect after restarting the local daemon. Use --json for structured results.`},usageOverride:`plugins list|add <package[@version]>|update <package>|remove <package>`,listUsageOverride:`plugins`,positionalArgs:[`list|add|update|remove`,`package?`],supportedFlags:[]},cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
1
+ import{P as e}from"./sdk-contracts.js";import{C as t,E as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={plugins:{text:{summary:`Manage installed provider plugins`,description:`Install, list, update, or remove npm provider plugins in AGENT_DEVICE_HOME (default ~/.agent-device). Changes take effect after restarting the local daemon. Use --json for structured results.`},usageOverride:`plugins list|add <package[@version]>|update <package>|remove <package>`,listUsageOverride:`plugins`,positionalArgs:[`list|add|update|remove`,`package?`],supportedFlags:[]},cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [provider] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerDeviceType.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
2
2
 
3
3
  Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
4
4