agent-device 0.21.24 → 0.21.25
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.
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.25.apk +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.25.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.24.manifest.json → agent-device-android-ime-helper-0.21.25.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.manifest.json +16 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +159 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerHttpRequestFraming.swift +139 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerPeer.swift +41 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerToken.swift +25 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +18 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +0 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryConfirmation.swift +59 -26
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +47 -103
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +142 -54
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +4 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +21 -19
- package/dist/src/absence-observation-errors.js +1 -0
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +2 -2
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android-system-surface-disclosure.js +1 -0
- package/dist/src/android-text-entry.js +1 -0
- package/dist/src/android.js +1 -1
- package/dist/src/app-backend.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +4 -3
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution-facade.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/aws-device-farm-connection.js +1 -1
- package/dist/src/back-mode.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/browserstack-connection.js +1 -1
- package/dist/src/capture-disclosure.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +17 -14
- package/dist/src/cli-output.js +1 -1
- package/dist/src/cli-runner.js +3 -1
- package/dist/src/cli.js +3 -3
- package/dist/src/client-companion-tunnel.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +8 -2
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-metadata.js +73 -1
- package/dist/src/command-policy.js +1 -0
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection-verification.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lease-beat.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-liveness-probe.js +1 -1
- package/dist/src/daemon-policy-file.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -1
- package/dist/src/daemon-registration.js +1 -1
- package/dist/src/daemon-resolution.js +3 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.d.ts +5 -3
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-readiness-runtime.js +1 -1
- package/dist/src/device-release.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +3 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/expo-dev-client-launch.js +1 -0
- package/dist/src/file.js +3 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/human-control.js +1 -1
- package/dist/src/ime-rebind.js +1 -1
- package/dist/src/ime-state.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +2 -2
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-error.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-catalog.js +1 -1
- package/dist/src/interactor.js +5 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +5 -1
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +2 -2
- package/dist/src/inventory6.js +1 -1
- package/dist/src/io.d.ts +2 -2
- package/dist/src/ios-client.js +1 -1
- package/dist/src/ios-settings.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-adapter.js +1 -1
- package/dist/src/ios-snapshot-engine.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/keyed-lock.js +1 -1
- package/dist/src/launch-confirmation.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +2 -10
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/load.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/log-stream.js +9 -9
- package/dist/src/mechanics.js +16 -16
- package/dist/src/metro.js +1 -1
- package/dist/src/metro2.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/observability.js +1 -1
- package/dist/src/open-target-resolution.js +1 -1
- package/dist/src/output-path.js +1 -1
- package/dist/src/overlay.js +1 -3
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
- package/dist/src/platform-runtime-apple-resources.js +1 -0
- package/dist/src/platform-runtime-claim-recovery.js +1 -0
- package/dist/src/platform-runtime-daemon-services.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plugin.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-entry.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/provider-credential-fingerprint.js +1 -1
- package/dist/src/provider-device-admission.js +1 -1
- package/dist/src/provider-policy.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.js +2 -2
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native-overlay2.js +3 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording.js +2 -2
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/remote-config-core.js +1 -1
- package/dist/src/replay-backend-registry.js +1 -0
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay-maestro-backend.js +117 -0
- package/dist/src/replay-script-selection.js +1 -0
- package/dist/src/replay.js +1 -3
- package/dist/src/replay2.js +1 -0
- package/dist/src/reporting.js +3 -3
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-providers.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/runner-cache-retention.js +1 -1
- package/dist/src/runner-cache-trim.js +1 -1
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-device-set.js +1 -1
- package/dist/src/runner-error-classification.js +3 -3
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-retention.js +1 -0
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner-startup-transport.js +1 -0
- package/dist/src/runner-toolchain-probe.js +1 -1
- package/dist/src/runner.js +2 -1
- package/dist/src/runtime-command-surface.js +1 -0
- package/dist/src/runtime-deployment.js +1 -1
- package/dist/src/runtime-factory.js +1 -0
- package/dist/src/runtime-session.js +1 -0
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +2 -1
- package/dist/src/runtime10.js +2 -1
- package/dist/src/runtime2.js +5 -2
- package/dist/src/runtime3.js +1 -5
- package/dist/src/runtime4.js +5 -1
- package/dist/src/runtime5.js +1 -5
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -0
- package/dist/src/screenshot3.js +5 -5
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +1 -1
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.d.ts +4 -2
- package/dist/src/sdk-selectors.d.ts +4 -5
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-pipeline-policy.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-replay-runtime-failure-response.js +1 -0
- package/dist/src/session-runtime-admission.js +1 -0
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -1
- package/dist/src/simctl-settings.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-chrome.js +1 -0
- package/dist/src/snapshot-desktop-projection.js +1 -1
- package/dist/src/snapshot-evidence.js +1 -0
- package/dist/src/snapshot-node-lookup.js +1 -0
- package/dist/src/snapshot-occlusion.js +1 -0
- package/dist/src/snapshot-quality-verdict.js +1 -0
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/src.js +5 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +2 -1
- package/dist/src/store.js +1 -1
- package/dist/src/surface-snapshot2.js +1 -1
- package/dist/src/target-evidence-tree.js +1 -0
- package/dist/src/target-evidence.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/touch-runtime2.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/undici.js +8 -8
- package/dist/src/update-check.js +1 -1
- package/dist/src/vars.js +2 -0
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/wait.js +1 -0
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/package.json +9 -11
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.24.apk +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.24.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.manifest.json +0 -16
- package/dist/src/adb-transport.js +0 -1
- package/dist/src/alert-runtime.js +0 -1
- package/dist/src/app-deployment-resolution.js +0 -2
- package/dist/src/app-inventory-contract.js +0 -1
- package/dist/src/app-log-session-resource.js +0 -1
- package/dist/src/application-lifecycle-runtime.js +0 -1
- package/dist/src/auth-session.js +0 -1
- package/dist/src/browserstack-device-features.js +0 -1
- package/dist/src/browserstack.js +0 -1
- package/dist/src/cache.js +0 -1
- package/dist/src/capture.js +0 -1
- package/dist/src/catalog.js +0 -1
- package/dist/src/click-button.js +0 -1
- package/dist/src/client-metro-companion.js +0 -1
- package/dist/src/client-options.js +0 -3
- package/dist/src/daemon-client-transport.js +0 -1
- package/dist/src/daemon-http.js +0 -1
- package/dist/src/device-rotation.js +0 -1
- package/dist/src/device-session.js +0 -3
- package/dist/src/device2.js +0 -1
- package/dist/src/device3.js +0 -3
- package/dist/src/dispatch-resolve.js +0 -4
- package/dist/src/format.js +0 -2
- package/dist/src/gesture-plan-types.js +0 -1
- package/dist/src/host.js +0 -1
- package/dist/src/ime-settings-record.js +0 -1
- package/dist/src/interaction-ref-policy.js +0 -1
- package/dist/src/interactor-operation-binding.js +0 -1
- package/dist/src/keyboard-actions.js +0 -1
- package/dist/src/lease-context.js +0 -1
- package/dist/src/lease-registry-scope.js +0 -1
- package/dist/src/lease-scope.js +0 -1
- package/dist/src/managed-device-scope.js +0 -1
- package/dist/src/manifest.js +0 -1
- package/dist/src/observe-until.js +0 -1
- package/dist/src/output-common.js +0 -5
- package/dist/src/owner-identity.js +0 -3
- package/dist/src/path-resolution.js +0 -1
- package/dist/src/perf-runtime-plan.js +0 -1
- package/dist/src/platform-runtime-app-log-process.js +0 -1
- package/dist/src/platform-runtime-managed-owner.js +0 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +0 -1
- package/dist/src/png.js +0 -1
- package/dist/src/provider-session-ownership.js +0 -2
- package/dist/src/providers.js +0 -1
- package/dist/src/registry.js +0 -68
- package/dist/src/remote-connection-state.js +0 -1
- package/dist/src/request-admission.js +0 -1
- package/dist/src/request-cancellation.js +0 -1
- package/dist/src/request-progress-protocol.js +0 -1
- package/dist/src/runner-cache-metadata.js +0 -2
- package/dist/src/runner-disposal.js +0 -1
- package/dist/src/runner-session-types.js +0 -1
- package/dist/src/runtime-admission.js +0 -1
- package/dist/src/runtime11.js +0 -2
- package/dist/src/screen-recording-resource-recovery.js +0 -1
- package/dist/src/screenshot-result.js +0 -1
- package/dist/src/script.js +0 -1
- package/dist/src/scroll-command.js +0 -1
- package/dist/src/scroll-gesture.js +0 -1
- package/dist/src/scroll-indicator.js +0 -1
- package/dist/src/session-artifact-paths.js +0 -1
- package/dist/src/session-paths.js +0 -1
- package/dist/src/session-repair-tombstone.js +0 -1
- package/dist/src/session-snapshot.js +0 -1
- package/dist/src/snapshot-private-evidence.js +0 -1
- package/dist/src/snapshot4.js +0 -1
- package/dist/src/src4.js +0 -1
- package/dist/src/src5.js +0 -1
- package/dist/src/src6.js +0 -1
- package/dist/src/src7.js +0 -2
- package/dist/src/src8.js +0 -115
- package/dist/src/string-enum.js +0 -1
- package/dist/src/success-text.js +0 -1
- package/dist/src/transport.js +0 -3
- package/dist/src/ttl-memo.js +0 -1
- package/dist/src/verified-file.js +0 -1
- package/dist/src/window-state.js +0 -1
- /package/dist/src/{doctor-output.js → doctor-lines.js} +0 -0
package/dist/src/back-mode.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,t}from"./sdk-contracts.js";import{o as n}from"./capture.js";import{i as r}from"./sdk-device.js";import{t as i}from"./recording-scope.js";import{c as a,l as o}from"./sdk-remote-config.js";import{t as s}from"./session.js";import{c}from"./observability.js";const l=[{key:`keyframes`,names:[`--keyframes`],type:`string`,usageLabel:`--keyframes <json>`,usageDescription:`Fold: timed {atMs, angle} keyframes; final atMs is motion duration (up to 60000ms)`,projectConfig:!1,recorded:!0},{key:`count`,names:[`--count`],type:`int`,min:1,max:200,usageLabel:`--count <n>`,usageDescription:`Repeat count for press/swipe series`,projectConfig:!0,recorded:!0},{key:`pointerCount`,names:[`--pointer-count`],type:`int`,min:1,max:2,usageLabel:`--pointer-count <1|2>`,usageDescription:`Gesture pan: number of touch pointers (default 1)`,projectConfig:!0,recorded:!0},{key:`fps`,names:[`--fps`],type:`int`,min:1,max:120,usageLabel:`--fps <n>`,usageDescription:`Record: target frames per second (iOS physical device runner); also lowers the touch-overlay rate, which never exceeds 30`,projectConfig:!0,recorded:!0},{key:`quality`,names:[`--quality`],type:`string`,usageLabel:`--quality <medium|high>`,usageDescription:`Record: output quality preset; Android maps this to screenrecord bitrate, Limrun sessions map medium to recorder quality 5 and high to 8; Apple export always preserves the captured resolution, so it has no effect there. Legacy numeric values 5-7 map to medium; 8-10 map to high`,projectConfig:!0,recorded:!0},{key:`hideTouches`,names:[`--hide-touches`],type:`boolean`,usageLabel:`--hide-touches`,usageDescription:`Record: skip touch-overlay post-processing for faster raw benchmark videos`,projectConfig:!0,recorded:!0},{key:`recordingScope`,names:[`--scope`],type:`enum`,enumValues:i,usageLabel:`--scope <app|device|system>`,usageDescription:`Record: app requires an active app session; device/system records the whole screen`,projectConfig:!0,recorded:!1},{key:`intervalMs`,names:[`--interval-ms`],type:`int`,min:0,max:1e4,usageLabel:`--interval-ms <ms>`,usageDescription:`Delay between press iterations`,projectConfig:!0,recorded:!0},{key:`delayMs`,names:[`--delay-ms`],type:`int`,min:0,max:1e4,usageLabel:`--delay-ms <ms>`,usageDescription:`Delay between typed characters`,projectConfig:!0,recorded:!0},{key:`recordAs`,names:[`--record-as`],type:`string`,usageLabel:`--record-as <VAR>`,usageDescription:"Fill: send the live text but publish ${VAR} in an armed .ad recording",projectConfig:!0,recorded:!1},{key:`durationMs`,names:[`--duration-ms`],type:`int`,min:0,max:1e4,usageLabel:`--duration-ms <ms>`,usageDescription:`Scroll: pace the gesture over this duration when supported`,projectConfig:!0,recorded:!1},{key:`holdMs`,names:[`--hold-ms`],type:`int`,min:0,max:1e4,usageLabel:`--hold-ms <ms>`,usageDescription:`Press hold duration for each iteration`,projectConfig:!0,recorded:!0},{key:`jitterPx`,names:[`--jitter-px`],type:`int`,min:0,max:100,usageLabel:`--jitter-px <n>`,usageDescription:`Deterministic coordinate jitter radius for press`,projectConfig:!0,recorded:!0},{key:`pixels`,names:[`--pixels`],type:`int`,min:1,max:1e5,usageLabel:`--pixels <n>`,usageDescription:`Scroll: explicit gesture distance in pixels`,projectConfig:!0,recorded:!1},{key:`until`,names:[`--until`],type:`string`,usageLabel:`--until <selector>`,usageDescription:`Scroll: repeat passes until the selector is visible on screen`,projectConfig:!0,recorded:!0},{key:`doubleTap`,names:[`--double-tap`],type:`boolean`,usageLabel:`--double-tap`,usageDescription:`Use double-tap gesture per press iteration`,projectConfig:!0,recorded:!0},{key:`verify`,names:[`--verify`],type:`boolean`,usageLabel:`--verify`,usageDescription:`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot`,projectConfig:!0,recorded:!1},{key:`settle`,names:[`--settle`],type:`boolean`,usageLabel:`--settle`,usageDescription:`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response (best-effort; never fails the action)`,projectConfig:!0,recorded:!1},{key:`settleQuietMs`,names:[`--settle-quiet`],type:`int`,min:0,usageLabel:`--settle-quiet <ms>`,usageDescription:`Settle: quiet window the UI must hold to count as settled (default 500ms)`,projectConfig:!0,recorded:!1},{key:`clickButton`,names:[`--button`],type:`enum`,enumValues:[`primary`,`secondary`,`middle`],usageLabel:`--button primary|secondary|middle`,usageDescription:`Click: choose mouse button (middle reserved for future macOS support)`,projectConfig:!0,recorded:!0},{key:`backMode`,names:[`--in-app`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`in-app`,usageLabel:`--in-app`,usageDescription:`Back: use app-provided back UI when available`,projectConfig:!0,recorded:!1},{key:`backMode`,names:[`--system`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`system`,usageLabel:`--system`,usageDescription:`Back: use system back input or gesture when available`,projectConfig:!0,recorded:!1},{key:`pauseMs`,names:[`--pause-ms`],type:`int`,min:0,max:1e4,usageLabel:`--pause-ms <ms>`,usageDescription:`Delay between swipe iterations`,projectConfig:!0,recorded:!0},{key:`pattern`,names:[`--pattern`],type:`enum`,enumValues:[`one-way`,`ping-pong`],usageLabel:`--pattern one-way|ping-pong`,usageDescription:`Swipe repeat pattern`,projectConfig:!0,recorded:!0},{key:`verbose`,names:[`--debug`,`--verbose`,`-v`],type:`boolean`,usageLabel:`--debug, --verbose, -v`,usageDescription:`Enable debug diagnostics; test --verbose prints per-test step timings without debug logs`,projectConfig:!0,recorded:!0},{key:`cost`,names:[`--cost`],type:`boolean`,usageLabel:`--cost`,usageDescription:`Include per-command wall-clock latency (cost.wallClockMs) in the response`,projectConfig:!0,recorded:!1},{key:`responseLevel`,names:[`--level`],type:`enum`,enumValues:e,usageLabel:`--level digest|default|full`,usageDescription:`Response detail level: digest (token-cheap), default (today), or full. Default keeps the wire shape unchanged.`,projectConfig:!0,recorded:!1},{key:`json`,names:[`--json`],type:`boolean`,usageLabel:`--json`,usageDescription:`JSON output`,projectConfig:!0,recorded:!1},{key:`help`,names:[`--help`,`-h`],type:`boolean`,usageLabel:`--help, -h`,usageDescription:`Print help and exit`,projectConfig:!1,recorded:!1},{key:`version`,names:[`--version`,`-V`],type:`boolean`,usageLabel:`--version, -V`,usageDescription:`Print version and exit`,projectConfig:!1,recorded:!1},{key:`snapshotDiff`,names:[`--diff`],type:`boolean`,usageLabel:`--diff`,usageDescription:`Snapshot: show structural diff against the previous session baseline`,projectConfig:!0,recorded:!1},{key:`saveScript`,names:[`--save-script`],type:`booleanOrString`,usageLabel:`--save-script [path]`,usageDescription:`Arm evidence capture on open, publish the armed recording on close; close --save-script alone (without an armed open) is rejected — start with open --save-script, or use session save-script mid-session. Optional custom output path.`,projectConfig:!1,recorded:!0},{key:`networkInclude`,names:[`--include`],type:`enum`,enumValues:[`summary`,`headers`,`body`,`all`],usageLabel:`--include summary|headers|body|all`,usageDescription:`Network: include headers, bodies, or both in output`,projectConfig:!0,recorded:!1},{key:`shutdown`,names:[`--shutdown`],type:`boolean`,usageLabel:`--shutdown`,usageDescription:`close: shutdown associated simulator/emulator after ending session`,projectConfig:!0,recorded:!1},{key:`relaunch`,names:[`--relaunch`],type:`boolean`,usageLabel:`--relaunch`,usageDescription:`open: terminate app process before launching it`,projectConfig:!0,recorded:!0},{key:`foreground`,names:[`--foreground`],type:`boolean`,usageLabel:`--foreground`,usageDescription:`open: keep normal app/device selection and return an initial snapshot; without an app, resolve the sole running app on the sole booted iOS simulator`,inputDescription:`Include an initial interactive snapshot in a fresh open response. With no app argument, discover the sole running app on the sole booted iOS simulator; ambiguous environments fail closed.`,projectConfig:!1,recorded:!1},{key:`restart`,names:[`--restart`],type:`boolean`,usageLabel:`--restart`,usageDescription:`logs clear: stop active stream, clear logs, then start streaming again`,projectConfig:!0,recorded:!1},{key:`retainPaths`,names:[`--retain-paths`],type:`boolean`,usageLabel:`--retain-paths`,usageDescription:`install-from-source: keep materialized artifact paths after install`,projectConfig:!0,recorded:!1},{key:`retentionMs`,names:[`--retention-ms`],type:`int`,min:1,usageLabel:`--retention-ms <ms>`,usageDescription:`install-from-source: retention TTL for materialized artifact paths`,projectConfig:!0,recorded:!1},{key:`noRecord`,names:[`--no-record`],type:`boolean`,usageLabel:`--no-record`,usageDescription:`Do not record this action`,projectConfig:!0,recorded:!0},{key:`record`,names:[`--record`],type:`boolean`,usageLabel:`--record`,usageHidden:!0,usageDescription:`Force-record this action even though its command is observation-only and would otherwise be excluded from a repair-armed heal by default (mutually exclusive with --no-record)`,projectConfig:!0,recorded:!0}],u=[{key:`config`,names:[`--config`],type:`string`,usageLabel:`--config <path>`,usageDescription:`Load CLI defaults from a specific config file (required for connection/provider defaults outside user config)`,projectConfig:!1,recorded:!1},{key:`remoteConfig`,names:[`--remote-config`],type:`string`,usageLabel:`--remote-config <path>`,usageDescription:`Load remote host + Metro workflow settings from a specific profile file`,projectConfig:!1,recorded:!1},{key:`stateDir`,names:[`--state-dir`],type:`string`,usageLabel:`--state-dir <path>`,usageDescription:`Daemon state directory (defaults to ~/.agent-device for packages, or a worktree-scoped dev dir from source)`,projectConfig:!1,recorded:!1},{key:`daemonBaseUrl`,names:[`--daemon-base-url`],type:`string`,usageLabel:`--daemon-base-url <url>`,usageDescription:`Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)`,projectConfig:!1,recorded:!1},{key:`daemonAuthToken`,names:[`--daemon-auth-token`],type:`string`,usageLabel:`--daemon-auth-token <token>`,usageDescription:`Remote HTTP daemon or proxy auth token (sent as request token and bearer header)`,projectConfig:!1,recorded:!1},{key:`daemonTransport`,names:[`--daemon-transport`],type:`enum`,enumValues:[`auto`,`socket`,`http`],usageLabel:`--daemon-transport auto|socket|http`,usageDescription:`Daemon client transport preference`,projectConfig:!1,recorded:!1},{key:`daemonServerMode`,names:[`--daemon-server-mode`],type:`enum`,enumValues:[`socket`,`http`,`dual`],usageLabel:`--daemon-server-mode socket|http|dual`,usageDescription:`Daemon server mode used when spawning daemon`,projectConfig:!1,recorded:!1},{key:`proxyHost`,names:[`--host`],type:`string`,usageLabel:`--host <host>`,usageDescription:`Proxy: host interface to bind (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`proxyPort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`Proxy: TCP port to bind (default: 0, choose a free port)`,projectConfig:!1,recorded:!1},{key:`tenant`,names:[`--tenant`],type:`string`,usageLabel:`--tenant <id>`,usageDescription:`Tenant scope identifier for isolated daemon sessions`,projectConfig:!1,recorded:!1},{key:`sessionIsolation`,names:[`--session-isolation`],type:`enum`,enumValues:[`none`,`tenant`],usageLabel:`--session-isolation none|tenant`,usageDescription:`Session isolation strategy (tenant prefixes session namespace)`,projectConfig:!1,recorded:!1},{key:`runId`,names:[`--run-id`],type:`string`,usageLabel:`--run-id <id>`,usageDescription:`Run identifier used for tenant lease admission checks`,projectConfig:!1,recorded:!1},{key:`leaseId`,names:[`--lease-id`],type:`string`,usageLabel:`--lease-id <id>`,usageDescription:`Lease identifier bound to tenant/run admission scope`,projectConfig:!1,recorded:!1},{key:`leaseBackend`,names:[`--lease-backend`],type:`enum`,enumValues:t,usageLabel:`--lease-backend ${t.join(`|`)}`,usageDescription:`Lease backend for remote tenant connection admission`,projectConfig:!1,recorded:!1},{key:`provider`,names:[`--provider`],type:`string`,usageLabel:`--provider <name>`,usageDescription:`Cloud provider name for provider-scoped commands`,projectConfig:!1,recorded:!1},{key:`providerSessionId`,names:[`--provider-session`],type:`string`,usageLabel:`--provider-session <id>`,usageDescription:`Cloud provider session id or ARN`,projectConfig:!1,recorded:!1},{key:`providerApp`,names:[`--provider-app`],type:`string`,usageLabel:`--provider-app <ref-or-path>`,usageDescription:`Cloud provider app reference or local app path used when creating hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`providerOsVersion`,names:[`--provider-os-version`,`--os-version`],type:`string`,usageLabel:`--provider-os-version <version>`,usageDescription:`Hosted cloud provider OS version, for example 17 or 14.0`,projectConfig:!1,recorded:!1},{key:`providerDeviceType`,names:[`--provider-device-type`],type:`enum`,enumValues:o,usageLabel:`--provider-device-type real|virtual`,usageDescription:`TestMu AI device pool: real devices or virtual devices (emulators and simulators). Defaults to virtual`,projectConfig:!1,recorded:!1},{key:`providerProject`,names:[`--provider-project`],type:`string`,usageLabel:`--provider-project <name>`,usageDescription:`Hosted cloud provider project label`,projectConfig:!1,recorded:!1},{key:`providerBuild`,names:[`--provider-build`],type:`string`,usageLabel:`--provider-build <name>`,usageDescription:`Hosted cloud provider build label`,projectConfig:!1,recorded:!1},{key:`providerSessionName`,names:[`--provider-session-name`],type:`string`,usageLabel:`--provider-session-name <name>`,usageDescription:`Hosted cloud provider session label`,projectConfig:!1,recorded:!1},{key:`providerDeviceOrientation`,names:[`--provider-device-orientation`,`--device-orientation`],type:`enum`,enumValues:a,usageLabel:`--provider-device-orientation portrait|landscape`,usageDescription:`Screen orientation a hosted cloud provider session starts in. Set this rather than rotating after launch: a session that boots landscape renders login webviews landscape`,projectConfig:!1,recorded:!1},{key:`providerGeoLocation`,names:[`--provider-geo-location`,`--geo-location`],type:`string`,usageLabel:`--provider-geo-location <country>`,usageDescription:`Hosted cloud provider IP geolocation country code, for example US`,projectConfig:!1,recorded:!1},{key:`providerTimezone`,names:[`--provider-timezone`,`--timezone`],type:`string`,usageLabel:`--provider-timezone <zone>`,usageDescription:`Hosted cloud provider device time zone, for example New_York`,projectConfig:!1,recorded:!1},{key:`providerAppiumVersion`,names:[`--provider-appium-version`,`--appium-version`],type:`string`,usageLabel:`--provider-appium-version <version>`,usageDescription:`Hosted cloud provider Appium server version, for example 3.2.0. Without it each provider starts its own default (Appium 1.x on BrowserStack)`,projectConfig:!1,recorded:!1},{key:`providerLanguage`,names:[`--provider-language`,`--language`],type:`string`,usageLabel:`--provider-language <language>`,usageDescription:`Hosted cloud provider app language, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerLocale`,names:[`--provider-locale`,`--locale`],type:`string`,usageLabel:`--provider-locale <locale>`,usageDescription:`Hosted cloud provider device locale, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerNetworkProfile`,names:[`--provider-network-profile`,`--network-profile`],type:`string`,usageLabel:`--provider-network-profile <profile>`,usageDescription:`Hosted cloud provider named network condition profile, for example 4g-lte-advanced-good. Mutually exclusive with --provider-custom-network`,projectConfig:!1,recorded:!1},{key:`providerCustomNetwork`,names:[`--provider-custom-network`,`--custom-network`],type:`string`,usageLabel:`--provider-custom-network <shape>`,usageDescription:`Hosted cloud provider custom network shape. Mutually exclusive with --provider-network-profile`,projectConfig:!1,recorded:!1},{key:`providerNoResignApp`,names:[`--provider-no-resign-app`],type:`boolean`,usageLabel:`--provider-no-resign-app`,usageDescription:`iOS only: keep an Enterprise-signed app as uploaded instead of letting the provider re-sign it, which strips entitlements such as push notifications`,projectConfig:!1,recorded:!1},{key:`awsProjectArn`,names:[`--aws-project-arn`],type:`string`,usageLabel:`--aws-project-arn <arn>`,usageDescription:`AWS Device Farm project ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsDeviceArn`,names:[`--aws-device-arn`],type:`string`,usageLabel:`--aws-device-arn <arn>`,usageDescription:`AWS Device Farm device ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsAppArn`,names:[`--aws-app-arn`],type:`string`,usageLabel:`--aws-app-arn <arn>`,usageDescription:`AWS Device Farm app ARN attached to hosted remote access sessions`,projectConfig:!1,recorded:!1},{key:`awsRegion`,names:[`--aws-region`],type:`string`,usageLabel:`--aws-region <region>`,usageDescription:`AWS region for Device Farm API calls`,projectConfig:!1,recorded:!1},{key:`awsInteractionMode`,names:[`--aws-interaction-mode`],type:`enum`,enumValues:[`INTERACTIVE`,`NO_VIDEO`,`VIDEO_ONLY`],usageLabel:`--aws-interaction-mode INTERACTIVE|NO_VIDEO|VIDEO_ONLY`,usageDescription:`AWS Device Farm remote access interaction mode`,projectConfig:!1,recorded:!1},{key:`force`,names:[`--force`,`--overwrite`],type:`boolean`,usageLabel:`--force, --overwrite`,usageDescription:`Force replacement of existing state (connect: replace an active connection; --save-script: overwrite an existing target instead of refusing)`,projectConfig:!0,recorded:!0},{key:`clean`,names:[`--clean`],type:`boolean`,usageLabel:`--clean`,usageDescription:`Daemon stop: remove retained runner processes and leases after stopping`,projectConfig:!0,recorded:!1},{key:`noLogin`,names:[`--no-login`],type:`boolean`,usageLabel:`--no-login`,usageDescription:`Connect: fail instead of starting implicit cloud login`,projectConfig:!0,recorded:!1},{key:`sessionLock`,names:[`--session-lock`],type:`enum`,enumValues:[`reject`,`strip`],usageLabel:`--session-lock reject|strip`,usageDescription:`Lock bound-session device routing for this CLI invocation and nested batch steps; strip drops conflicting platform/scope selectors only, and a selector naming a different device always fails`,projectConfig:!0,recorded:!1}],d=[{key:`platform`,names:[`--platform`],type:`enum`,enumValues:r,usageLabel:`--platform ${r.join(`|`)}`,usageDescription:"Platform to target (`apple` aliases the Apple automation backend)",projectConfig:!0,recorded:!0},{key:`target`,names:[`--target`],type:`enum`,enumValues:[`mobile`,`tv`,`desktop`],usageLabel:`--target mobile|tv|desktop`,usageDescription:`Device target class to match`,projectConfig:!0,recorded:!1},{key:`device`,names:[`--device`],type:`string`,usageLabel:`--device <name>`,usageDescription:`Device name to target (a UDID belongs in --udid, a serial in --serial)`,projectConfig:!0,recorded:!0},{key:`udid`,names:[`--udid`],type:`string`,usageLabel:`--udid <udid>`,usageDescription:`Apple device or simulator UDID; the only selector that pins one device when several share a --device name`,projectConfig:!0,recorded:!0},{key:`serial`,names:[`--serial`],type:`string`,usageLabel:`--serial <serial>`,usageDescription:`Android, HarmonyOS, or Vega VVD serial`,projectConfig:!0,recorded:!0},{key:`stale`,names:[`--stale`],type:`boolean`,usageLabel:`--stale`,usageDescription:`Device status: show only claims with a provably stale owner`,projectConfig:!0,recorded:!1},{key:`surface`,names:[`--surface`],type:`enum`,enumValues:s,usageLabel:`--surface app|frontmost-app|desktop|menubar`,usageDescription:`macOS session surface for open (defaults to app)`,projectConfig:!0,recorded:!0},{key:`headless`,names:[`--headless`],type:`boolean`,usageLabel:`--headless`,usageDescription:`Boot: launch Android emulator without a GUI window`,projectConfig:!0,recorded:!1},{key:`targetApp`,names:[`--app`,`--target-app`],type:`string`,usageLabel:`--app <id-or-name>`,usageDescription:`Target an app without opening it: doctor verifies an installed app by id or name; settings applies an app-scoped change (permission, iOS location) to a bundle id or package`,projectConfig:!1,recorded:!1},{key:`metroHost`,names:[`--metro-host`],type:`string`,usageLabel:`--metro-host <host>`,usageDescription:`Session-scoped Metro/debug host hint`,projectConfig:!1,recorded:!0},{key:`metroPort`,names:[`--metro-port`],type:`int`,min:1,max:65535,usageLabel:`--metro-port <port>`,usageDescription:`Session-scoped Metro/debug port hint; on an emulator/simulator the host defaults to the loopback alias, physical devices still need --metro-host`,projectConfig:!1,recorded:!0},{key:`metroProjectRoot`,names:[`--project-root`],type:`string`,usageLabel:`--project-root <path>`,usageDescription:`metro prepare: React Native project root (default: cwd)`,projectConfig:!1,recorded:!1},{key:`kind`,names:[`--kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`,...c],usageLabel:`--kind <kind>`,usageDescription:`Kind selector for commands that support it, such as metro prepare or perf artifact collectors`,projectConfig:!0,recorded:!1},{key:`perfTemplate`,names:[`--template`],type:`string`,usageLabel:`--template <name>`,usageDescription:`Perf xctrace template name, for example Time Profiler`,projectConfig:!0,recorded:!1},{key:`metroKind`,names:[`--metro-kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`],usageLabel:`--metro-kind auto|react-native|expo|repack`,usageDescription:`metro prepare: detect or force the React Native dev-server launcher kind`,projectConfig:!1,recorded:!1},{key:`metroPublicBaseUrl`,names:[`--public-base-url`],type:`string`,usageLabel:`--public-base-url <url>`,usageDescription:`metro prepare: public base URL used for direct dev-server bundle hints`,projectConfig:!1,recorded:!1},{key:`metroProxyBaseUrl`,names:[`--proxy-base-url`],type:`string`,usageLabel:`--proxy-base-url <url>`,usageDescription:`metro prepare: optional bridge origin for remote dev-server access`,projectConfig:!1,recorded:!1},{key:`metroBearerToken`,names:[`--bearer-token`],type:`string`,usageLabel:`--bearer-token <token>`,usageDescription:`metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)`,projectConfig:!1,recorded:!1},{key:`metroPreparePort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`metro prepare: local dev-server port (default: 8081)`,projectConfig:!1,recorded:!1},{key:`metroListenHost`,names:[`--listen-host`],type:`string`,usageLabel:`--listen-host <host>`,usageDescription:`metro prepare: host dev server listens on (default: 0.0.0.0)`,projectConfig:!1,recorded:!1},{key:`metroStatusHost`,names:[`--status-host`],type:`string`,usageLabel:`--status-host <host>`,usageDescription:`metro prepare: host used for local dev-server /status polling (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`metroStartupTimeoutMs`,names:[`--startup-timeout-ms`],type:`int`,min:1,usageLabel:`--startup-timeout-ms <ms>`,usageDescription:`metro prepare: timeout while waiting for the dev server to become ready`,projectConfig:!1,recorded:!1},{key:`metroProbeTimeoutMs`,names:[`--probe-timeout-ms`],type:`int`,min:1,usageLabel:`--probe-timeout-ms <ms>`,usageDescription:`metro prepare: timeout for /status and proxy bridge calls`,projectConfig:!1,recorded:!1},{key:`metroRuntimeFile`,names:[`--runtime-file`],type:`string`,usageLabel:`--runtime-file <path>`,usageDescription:`metro prepare: optional file path to persist the JSON result`,projectConfig:!1,recorded:!1},{key:`metroNoReuseExisting`,names:[`--no-reuse-existing`],type:`boolean`,usageLabel:`--no-reuse-existing`,usageDescription:`metro prepare: always start a fresh Metro process`,projectConfig:!1,recorded:!1},{key:`metroNoInstallDeps`,names:[`--no-install-deps`],type:`boolean`,usageLabel:`--no-install-deps`,usageDescription:`metro prepare: skip package-manager install when node_modules is missing`,projectConfig:!1,recorded:!1},{key:`bundleUrl`,names:[`--bundle-url`],type:`string`,usageLabel:`--bundle-url <url>`,usageDescription:`Session-scoped bundle URL hint`,projectConfig:!1,recorded:!0},{key:`launchUrl`,names:[`--launch-url`],type:`string`,usageLabel:`--launch-url <url>`,usageDescription:`Session-scoped deep link / launch URL hint`,projectConfig:!0,recorded:!0},{key:`iosSimulatorDeviceSet`,names:[`--ios-simulator-device-set`],type:`string`,usageLabel:`--ios-simulator-device-set <path>`,usageDescription:`Scope iOS simulator discovery/commands to this simulator device set`,projectConfig:!1,recorded:!1},{key:`iosXctestrunFile`,names:[`--ios-xctestrun-file`],type:`string`,usageLabel:`--ios-xctestrun-file <path>`,usageDescription:`Use an externally built iOS XCTest runner .xctestrun artifact`,projectConfig:!1,recorded:!1},{key:`iosXctestDerivedDataPath`,names:[`--ios-xctest-derived-data-path`],type:`string`,usageLabel:`--ios-xctest-derived-data-path <path>`,usageDescription:`Derived data path for external iOS XCTest runner execution`,projectConfig:!1,recorded:!1},{key:`iosXctestEnvDir`,names:[`--ios-xctest-env-dir`],type:`string`,usageLabel:`--ios-xctest-env-dir <path>`,usageDescription:`Writable directory for per-session iOS XCTest runner env overlays`,projectConfig:!1,recorded:!1},{key:`testIme`,names:[`--test-ime`],type:`boolean`,usageLabel:`--test-ime`,usageDescription:`open/test/replay: activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices; on test/replay it applies to the sessions the flow opens)`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--no-test-ime`],type:`boolean`,setValue:!1,usageLabel:`--no-test-ime`,usageDescription:`open/test/replay: keep the real Android keyboard even on emulators (opt out of the headless test IME; on test/replay it applies to the sessions the flow opens)`,projectConfig:!0,recorded:!1},{key:`androidDeviceAllowlist`,names:[`--android-device-allowlist`],type:`string`,usageLabel:`--android-device-allowlist <serials>`,usageDescription:`Comma/space separated Android serial allowlist for discovery/selection`,projectConfig:!1,recorded:!1},{key:`remote`,names:[`--remote`],type:`boolean`,usageLabel:`--remote`,usageDescription:`Doctor: check remote connection setup instead of local device inventory`,projectConfig:!0,recorded:!1},{key:`activity`,names:[`--activity`],type:`string`,usageLabel:`--activity <component>`,usageDescription:`Android app launch activity (package/Activity); not for URL opens`,projectConfig:!0,recorded:!1},{key:`launchConsole`,names:[`--launch-console`],type:`string`,usageLabel:`--launch-console <path>`,usageDescription:`open: capture the initial iOS simulator launch console window to a file`,projectConfig:!1,recorded:!1},{key:`launchArgs`,names:[`--launch-args`],type:`string`,multiple:!0,usageLabel:`--launch-args <arg>`,usageDescription:`open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag.`,projectConfig:!0,recorded:!1},{key:`header`,names:[`--header`],type:`string`,multiple:!0,usageLabel:`--header <name:value>`,usageDescription:`install-from-source: repeatable HTTP header for URL downloads`,projectConfig:!1,recorded:!1},{key:`githubActionsArtifact`,names:[`--github-actions-artifact`],type:`string`,usageLabel:`--github-actions-artifact <owner/repo:artifact>`,usageDescription:`install-from-source: GitHub Actions artifact resolved by a remote daemon`,projectConfig:!1,recorded:!1},{key:`installSource`,names:[],type:`string`,projectConfig:!1,recorded:!1},{key:`session`,names:[`--session`],type:`string`,usageLabel:`--session <name>`,usageDescription:`Named session (implicit default is scoped to this workspace + platform)`,projectConfig:!0,recorded:!1}],f=[{key:`replayUpdate`,names:[`--update`,`-u`],type:`boolean`,usageLabel:`--update, -u`,usageDescription:`Replay: retired as a rewrite (ADR 0012) — never edits the .ad file; every divergence already carries ranked selector suggestions, --update or not`,projectConfig:!0,recorded:!1},{key:`replayFrom`,names:[`--from`],type:`int`,min:1,usageLabel:`--from <n>`,usageDescription:`Replay: resume at 1-based plan step n, skipping 1..n-1 without executing them (requires --plan-digest; see a divergence report's resume field). replay only, not test`,projectConfig:!0,recorded:!1},{key:`replayPlanDigest`,names:[`--plan-digest`],type:`string`,usageLabel:`--plan-digest <sha256>`,usageDescription:`Replay: the plan digest a --from resume must match (from a prior divergence report); mismatch, edits, or include/platform-expansion changes fail INVALID_ARGS before any action`,projectConfig:!0,recorded:!1},{key:`replayKeepSession`,names:[`--keep-session`],type:`boolean`,usageLabel:`--keep-session`,usageDescription:`Replay: leave the session active by suppressing exactly an authored terminal close in a native .ad script; replay only, not test or Maestro YAML`,projectConfig:!0,recorded:!1},{key:`replayMaestro`,names:[`--maestro`],type:`boolean`,usageLabel:`--maestro`,usageDescription:`Replay: treat input as a supported Maestro YAML subset; unsupported syntax fails loudly. See agent-device help maestro for commands and boundaries`,projectConfig:!0,recorded:!1},{key:`replayEnv`,names:[`-e`,`--env`],type:`string`,multiple:!0,usageLabel:`-e KEY=VALUE, --env KEY=VALUE`,usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)",projectConfig:!1,recorded:!1},{key:`failFast`,names:[`--fail-fast`],type:`boolean`,usageLabel:`--fail-fast`,usageDescription:`Test: stop the suite after the first failing script; with sharding, each shard stops independently`,projectConfig:!0,recorded:!1},{key:`timeoutMs`,names:[`--timeout`],type:`int`,min:1,usageLabel:`--timeout <ms>`,usageDescription:`Boot/Open/Prepare: startup budget covering the device boot (and runner preparation for prepare). Replay/Snapshot/Test: maximum wall-clock time for the command or attempt. With --settle: the settle-wait deadline (default 10s)`,projectConfig:!0,recorded:!1},{key:`waitMs`,names:[`--wait`],type:`int`,min:100,max:12e4,usageLabel:`--wait <ms>`,usageDescription:`Open: wait up to n ms for a device another session is holding before failing with DEVICE_IN_USE`,inputDescription:`Block this open for up to n milliseconds (100-120000) while another session holds the device, then fail with DEVICE_IN_USE naming that session. Only session contention is waited for: a device claim held by another workspace is refused at once with its recovery command. A device that never frees, or is taken again while this open waits, costs the full budget, which extends this command's timeout envelope rather than eating into it.`,projectConfig:!1,recorded:!1},{key:`retries`,names:[`--retries`],type:`int`,min:0,max:3,usageLabel:`--retries <n>`,usageDescription:`Test: retry each failed script up to n additional times`,projectConfig:!0,recorded:!1},{key:`recordVideo`,names:[`--record-video`],type:`boolean`,usageLabel:`--record-video`,usageDescription:`Test: record each replay attempt to recording.mp4 in its attempt artifacts`,projectConfig:!0,recorded:!1},{key:`artifactsDir`,names:[`--artifacts-dir`],type:`string`,usageLabel:`--artifacts-dir <path>`,usageDescription:`Test: root directory for suite artifacts`,projectConfig:!1,recorded:!1},{key:`reporter`,names:[`--reporter`],type:`string`,multiple:!0,usageLabel:`--reporter <name-or-path>`,usageDescription:`Test: add a replay suite reporter; use default, junit:<path>, or a custom reporter path (repeatable)`,projectConfig:!1,recorded:!1},{key:`reportJunit`,names:[`--report-junit`],type:`string`,usageLabel:`--report-junit <path>`,usageDescription:`Test: compatibility alias for --reporter junit:<path>`,projectConfig:!1,recorded:!1},{key:`shardAll`,names:[`--shard-all`],type:`int`,min:1,usageLabel:`--shard-all <n>`,usageDescription:`Test: run the full suite on each of n devices; combine with --device id1,id2 for explicit connected devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`shardSplit`,names:[`--shard-split`],type:`int`,min:1,usageLabel:`--shard-split <n>`,usageDescription:`Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`steps`,names:[`--steps`],type:`string`,usageLabel:`--steps <json>`,usageDescription:`Batch: JSON array of {"command","input"} steps`,projectConfig:!1,recorded:!1},{key:`stepsFile`,names:[`--steps-file`],type:`string`,usageLabel:`--steps-file <path>`,usageDescription:`Batch: read steps JSON from file`,projectConfig:!1,recorded:!1},{key:`batchOnError`,names:[`--on-error`],type:`enum`,enumValues:[`stop`],usageLabel:`--on-error stop`,usageDescription:`Batch: stop when a step fails`,projectConfig:!0,recorded:!1},{key:`batchMaxSteps`,names:[`--max-steps`],type:`int`,min:1,max:1e3,usageLabel:`--max-steps <n>`,usageDescription:`Batch: maximum number of allowed steps`,projectConfig:!0,recorded:!1},{key:`appsFilter`,names:[`--all`],type:`enum`,enumValues:[`user-installed`,`all`],setValue:`all`,usageLabel:`--all`,usageDescription:`Apps: include system/OEM apps`,projectConfig:!0,recorded:!1},{key:`snapshotInteractiveOnly`,names:[`-i`],type:`boolean`,usageLabel:`-i`,usageDescription:`Snapshot: interactive elements only`,projectConfig:!0,recorded:!0},{key:`snapshotDepth`,names:[`--depth`,`-d`],type:`int`,min:0,usageLabel:`--depth, -d <depth>`,usageDescription:`Snapshot: limit snapshot depth`,projectConfig:!0,recorded:!0},{key:`snapshotScope`,names:[`--scope`,`-s`],type:`string`,usageLabel:`--scope, -s <scope>`,usageDescription:`Snapshot: scope snapshot to label/identifier`,projectConfig:!0,recorded:!0},{key:`snapshotRaw`,names:[`--raw`],type:`boolean`,usageLabel:`--raw`,usageDescription:`Snapshot: raw node output`,projectConfig:!0,recorded:!0},{key:`snapshotCustomActions`,names:[`--actions`],type:`boolean`,usageLabel:`--actions`,usageDescription:`Snapshot: name the affordances merged inside an element (iOS sim); not directly invokable — reach them via the detail screen, labeled children, or coordinates`,inputDescription:`Name the affordances an element merged away (iOS UIAccessibilityCustomAction, React Native accessibilityActions) — a card whose reply/options controls are not separate elements still lists them here. The names are for PLANNING, not invocation: there is no API to trigger them, so reach the affordance through the element detail screen, through the same control exposed as a labeled element elsewhere, or by coordinates from its rect. iOS simulator only; costs one accessibility round trip per merged element.`,projectConfig:!0,recorded:!0},{key:`snapshotObserveOnly`,names:[`--observe-only`],type:`boolean`,usageLabel:`--observe-only`,usageDescription:`Snapshot: observe the iOS session app without activation or foreground repair`,inputDescription:`iOS only. Refuse instead of activating or repairing the session app. Reports XCUIApplication state, which does not prove screen ownership (#2696).`,projectConfig:!1,recorded:!1},{key:`snapshotForceFull`,names:[`--force-full`],type:`boolean`,usageLabel:`--force-full`,usageDescription:`Snapshot: re-emit the full tree even when unchanged`,projectConfig:!0,recorded:!1},{key:`findFirst`,names:[`--first`],type:`boolean`,usageLabel:`--first`,usageDescription:`Find: pick the first match when ambiguous`,projectConfig:!0,recorded:!1},{key:`findLast`,names:[`--last`],type:`boolean`,usageLabel:`--last`,usageDescription:`Find: pick the last match when ambiguous`,projectConfig:!0,recorded:!1},{key:`out`,names:[`--out`],type:`string`,usageLabel:`--out <path>`,usageDescription:`Output path`,projectConfig:!1,recorded:!0},{key:`artifact`,names:[`--artifact`],type:`string`,usageLabel:`--artifact <path>`,usageDescription:`Debug symbols: Apple crash artifact path (.ips, .crash, or .log)`,projectConfig:!1,recorded:!1},{key:`dsym`,names:[`--dsym`],type:`string`,usageLabel:`--dsym <path>`,usageDescription:`Debug symbols: matching .dSYM bundle path`,projectConfig:!1,recorded:!1},{key:`searchPath`,names:[`--search-path`],type:`string`,usageLabel:`--search-path <dir>`,usageDescription:`Debug symbols: directory to scan for matching .dSYM bundles`,projectConfig:!1,recorded:!1},{key:`overlayRefs`,names:[`--overlay-refs`],type:`boolean`,usageLabel:`--overlay-refs`,usageDescription:`Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide`,projectConfig:!0,recorded:!1},...n,{key:`baseline`,names:[`--baseline`,`-b`],type:`string`,usageLabel:`--baseline, -b <path>`,usageDescription:`Diff screenshot: path to baseline image file`,projectConfig:!0,recorded:!1},{key:`threshold`,names:[`--threshold`],type:`string`,usageLabel:`--threshold <0-1>`,usageDescription:`Diff screenshot: color distance threshold (default 0.1)`,projectConfig:!0,recorded:!1}],p=[...u,...d,...l,...f],m=new Map;for(let e of p)for(let t of e.names)m.set(t,e);function h(e){return m.get(e)}function g(){return p}function _(e){return p.filter(t=>t.key===e)}function v(){return new Set(p.filter(e=>e.projectConfig).map(e=>e.key))}function y(){return new Set(p.filter(e=>e.recorded).map(e=>e.key))}const b=[`in-app`,`system`];export{v as a,_ as i,h as n,y as o,g as r,b as t};
|
|
1
|
+
import{M as e,P as t,S as n,i as r,t as i}from"./sdk-contracts.js";import{K as a,W as o,Z as s,gt as c,ht as l,lt as u,mt as d,z as f}from"./tv-remote.js";import{A as p,m}from"./sdk-batch-runner.js";import{i as h}from"./sdk-device.js";import{Ir as g,Mr as ee,_ as te,er as ne,qn as re,rr as ie,tr as ae}from"./sdk-batch.js";import{i as oe}from"./recording-export-quality.js";import{t as se}from"./recording-scope.js";import{c as ce,l as le}from"./sdk-remote-config.js";import{t as ue}from"./session.js";import{c as de}from"./observability.js";import fe from"node:path";function _(e,n){let r=e===void 0?NaN:Number(e);if(!Number.isInteger(r)||r<1)throw new t(`INVALID_ARGS`,`viewport ${n} must be a positive integer`);return r}function pe(e){if(e.length!==2)throw new t(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);return{width:_(e[0],`width`),height:_(e[1],`height`)}}const me=[`leaseId`,`tenantId`,`runId`,`clientId`,`deviceKey`];function he(e){return p({tenantId:e.meta?.tenantId??y(e.flags,`tenant`),runId:e.meta?.runId??y(e.flags,`runId`),leaseId:e.meta?.leaseId??y(e.flags,`leaseId`),leaseTtlMs:e.meta?.leaseTtlMs,leaseRetainOnClose:e.meta?.leaseRetainOnClose,leaseBackend:e.meta?.leaseBackend,leaseProvider:e.meta?.leaseProvider??y(e.flags,`leaseProvider`)??y(e.flags,`provider`),deviceKey:e.meta?.deviceKey??y(e.flags,`deviceKey`),clientId:e.meta?.clientId??y(e.flags,`clientId`)})}function ge(e){return p({tenantId:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseTtlMs:e.leaseTtlMs??e.ttlMs,leaseRetainOnClose:e.retainOnClose,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider??e.provider,deviceKey:e.deviceKey,clientId:e.clientId})}function _e(e){return p({tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId,leaseTtlMs:e.leaseTtlMs,leaseRetainOnClose:e.leaseRetainOnClose,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})}function ve(e){return p({tenant:e.tenantId,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId})}function ye(e){return p({tenantId:e.tenantId??``,runId:e.runId??``,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId,ttlMs:e.leaseTtlMs,retainOnClose:e.leaseRetainOnClose})}function be(e){return Ae(e)}function xe(e){let{ttlMs:t,...n}=Ae(e);return n}function Se(e,t,n){let r=p({...n.includeTokenParam?{token:n.token}:{},session:n.session,tenantId:e.tenantId,runId:e.runId,leaseProvider:e.leaseProvider,clientId:e.clientId,deviceKey:e.deviceKey});switch(t){case`lease_allocate`:return{...r,...p({ttlMs:e.leaseTtlMs,retainOnClose:e.leaseRetainOnClose,backend:e.leaseBackend})};case`lease_heartbeat`:return{...r,...p({leaseId:e.leaseId,ttlMs:e.leaseTtlMs})};case`lease_release`:return{...r,...p({leaseId:e.leaseId})}}}const Ce=[`platform`,`device`,`providerApp`,`providerOsVersion`,`providerDeviceType`,`providerProject`,`providerBuild`,`providerSessionName`,`providerDeviceOrientation`,`providerGeoLocation`,`providerTimezone`,`providerAppiumVersion`,`providerLanguage`,`providerLocale`,`providerNetworkProfile`,`providerCustomNetwork`,`providerNoResignApp`,`awsProjectArn`,`awsDeviceArn`,`awsAppArn`,`awsRegion`,`awsInteractionMode`];function we(e){let t={};for(let n of Ce){let r=e?.[n];(typeof r==`string`||typeof r==`boolean`)&&(t[n]=r)}return t}function Te(e){let t=p({leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId});return Object.keys(t).length>0?t:void 0}function v(e){return e.leaseProvider===`proxy`}function Ee(e){return v(e)?me.filter(t=>!e[t]):[]}const De=5e3,Oe=new Set([`LEASE_NOT_FOUND`,`LEASE_EXPIRED`,`LEASE_REVOKED`]);function ke(e){return typeof e==`object`&&!!e&&e.code===`UNAUTHORIZED`&&Oe.has(e.details?.reason)}function Ae(e){return p({leaseId:e.leaseId??``,tenantId:e.tenantId,runId:e.runId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey,clientId:e.clientId,ttlMs:e.leaseTtlMs})}function y(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}const b=[`pan`,`fling`,`swipe`,`pinch`,`rotate`,`transform`,`drag`];function x(e){let n=Me(e),r=T(n,`kind`,b);if(r===`pan`)return{kind:r,origin:C(n,`origin`),delta:C(n,`delta`),pointerCount:m(n,`pointerCount`,{min:1,max:2}),durationMs:S(n)};if(r===`drag`)return je(n);if(n.pointerCount!==void 0)throw new t(`INVALID_ARGS`,`pointerCount is supported only for gesture pan`);if(r===`fling`){if(n.durationMs!==void 0)throw new t(`INVALID_ARGS`,`gesture fling does not accept durationMs; use gesture pan for timed movement`);return{kind:r,direction:T(n,`direction`,a),origin:C(n,`origin`),distance:m(n,`distance`,{min:0})}}if(r===`swipe`){if(n.durationMs!==void 0)throw new t(`INVALID_ARGS`,`gesture swipe does not accept durationMs; use gesture pan for timed movement`);return{kind:r,preset:T(n,`preset`,s)}}if(r===`pinch`)return{kind:r,scale:w(n,`scale`),origin:Ne(n,`origin`)};if(r===`rotate`){if(n.velocity!==void 0)throw new t(`INVALID_ARGS`,`gesture rotate does not accept velocity; rotation pacing derives from degrees`);return{kind:r,degrees:w(n,`degrees`),origin:Ne(n,`origin`)}}return{kind:r,origin:C(n,`origin`),delta:C(n,`delta`),scale:w(n,`scale`),degrees:w(n,`degrees`),durationMs:S(n)}}function je(e){let n=m(e,`sourceHoldMs`,{min:1,max:1e4}),r=m(e,`moveMs`,{min:16,max:1e4}),i=m(e,`destinationHoldMs`,{min:0,max:1e4});if((n??800)+(r??500)+(i??0)>1e4)throw new t(`INVALID_ARGS`,`gesture drag total duration must be at most ${o}`);return{kind:`drag`,source:Pe(e,`source`),destination:Pe(e,`destination`),sourceHoldMs:n,moveMs:r,destinationHoldMs:i}}function S(e){let n=m(e,`durationMs`);if(n!==void 0){if(n<16||n>1e4)throw new t(`INVALID_ARGS`,`Expected durationMs to be an integer between 16 and ${o}.`);return n}}function Me(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`INVALID_ARGS`,`gesture requires structured object input`);return e}function C(e,t){let n=Me(e[t]);return{x:w(n,`x`),y:w(n,`y`)}}function Ne(e,t){return e[t]===void 0?void 0:C(e,t)}function w(e,n){let r=e[n];if(typeof r!=`number`||!Number.isFinite(r))throw new t(`INVALID_ARGS`,`Expected ${n} to be a finite number.`);return r}function Pe(e,n){let r=e[n];if(typeof r!=`string`||r.trim().length===0)throw new t(`INVALID_ARGS`,`Expected ${n} to be a non-empty string.`);return r.trim()}function T(e,n,r){let i=e[n];if(typeof i!=`string`||!r.includes(i))throw new t(`INVALID_ARGS`,`Expected ${n} to be one of: ${r.join(`, `)}.`);return i}const Fe={swipe:{max:4,usage:`swipe accepts 4 arguments: x1 y1 x2 y2`,retired:{positional:`durationMs`,migrate:Ie}},"gesture pan":{max:5,usage:`gesture pan accepts at most 5 arguments: x y dx dy [durationMs]`},"gesture fling":{max:4,usage:`gesture fling accepts at most 4 arguments: direction x y [distance]`,retired:{positional:`durationMs`,migrate:(e,t)=>`use "${t}", or gesture pan for timed movement.`}},"gesture swipe":{max:1,usage:`gesture swipe accepts 1 argument: preset`,retired:{positional:`durationMs`,migrate:(e,t)=>`use "${t}", or gesture pan for timed movement.`}},"gesture pinch":{max:3,usage:`gesture pinch accepts at most 3 arguments: scale [x] [y]`},"gesture rotate":{max:3,usage:`gesture rotate accepts at most 3 arguments: degrees [x] [y]`,retired:{positional:`velocity`,migrate:(e,t)=>`use "${t}"; rotation pacing derives from degrees.`}},"gesture transform":{max:7,usage:`gesture transform accepts at most 7 arguments: x y dx dy scale degrees [durationMs]`},"gesture drag":{max:5,usage:`gesture drag accepts at most 5 arguments: source destination [sourceHoldMs] [moveMs] [destinationHoldMs]`}};function Ie(e,t){let[n,r,i,a,o]=e,s=Le(n,i),c=Le(r,a);return s===void 0||c===void 0?`use "gesture pan x1 y1 dx dy durationMs" for the same timed drag, or "${t}" for a default-duration swipe.`:`use "gesture pan ${n} ${r} ${s} ${c} ${o}" for the same timed drag, or "${t}" for a default-duration swipe.`}function Le(e,t){let n=Number(t)-Number(e);return Number.isFinite(n)?n:void 0}function E(e,t){let n=Fe[e];if(t.length<=n.max)return;let r=n.retired;if(!r||t.length!==n.max+1||!Re(t[n.max]))return{usage:n.usage};let i=`${e} ${t.slice(0,n.max).join(` `)}`;return{usage:n.usage,migration:`The trailing ${r.positional} positional was removed: ${r.migrate(t,i)}`}}function Re(e){return e===void 0||e.trim().length===0?!1:e.startsWith("${")||Number.isFinite(Number(e))}function ze(e){if(!(!e||typeof e!=`object`||Array.isArray(e))&&e.durationMs!==void 0)throw new t(`INVALID_ARGS`,`swipe does not accept durationMs; use gesture pan for timed movement`)}function Be(e,t){let n=t?`${e.usage} (${t})`:e.usage;return e.migration?`${n}. ${e.migration}`:`${n}.`}function D(e,n){let r=E(e,n);if(r)throw new t(`INVALID_ARGS`,Be(r))}function Ve(e,t,n){let r=He(e,t);return r?Be(r,n):void 0}function He(e,t){if(e===`swipe`)return E(`swipe`,t);if(e!==`gesture`)return;let n=`gesture ${t[0]}`;if(Object.hasOwn(Fe,n))return E(n,t.slice(1))}function Ue(e){return{origin:{x:Number(e[0]),y:Number(e[1])},delta:{x:Number(e[2]),y:Number(e[3])}}}function O(e,t){let n=e[0],r=e.slice(1);switch(n){case`pan`:{D(`gesture pan`,r);let{origin:e,delta:i}=Ue(r);return x({kind:n,origin:e,delta:i,pointerCount:t,durationMs:k(r[4])})}case`fling`:return D(`gesture fling`,r),x({kind:n,direction:r[0],origin:{x:Number(r[1]),y:Number(r[2])},distance:k(r[3])});case`swipe`:return D(`gesture swipe`,r),x({kind:n,preset:r[0]});case`pinch`:return D(`gesture pinch`,r),x({kind:n,scale:Number(r[0]),origin:A(r[1],r[2])});case`rotate`:return D(`gesture rotate`,r),x({kind:n,degrees:Number(r[0]),origin:A(r[1],r[2])});case`transform`:{D(`gesture transform`,r);let{origin:e,delta:t}=Ue(r);return x({kind:n,origin:e,delta:t,scale:Number(r[4]),degrees:Number(r[5]),durationMs:k(r[6])})}case`drag`:return D(`gesture drag`,r),x({kind:n,source:r[0],destination:r[1],sourceHoldMs:k(r[2]),moveMs:k(r[3]),destinationHoldMs:k(r[4])});default:return x({kind:n})}}function We(e){if(e[0]!==`drag`)return;let t=O(e);return t.kind===`drag`?t:void 0}function Ge(e){switch(e.kind){case`pan`:return j([e.kind,e.origin.x,e.origin.y,e.delta.x,e.delta.y,e.durationMs]);case`fling`:return j([e.kind,e.direction,e.origin.x,e.origin.y,e.distance]);case`swipe`:return[e.kind,e.preset];case`pinch`:return j([e.kind,e.scale,e.origin?.x,e.origin?.y]);case`rotate`:return e.origin?j([e.kind,e.degrees,e.origin.x,e.origin.y]):[e.kind,String(e.degrees)];case`transform`:return j([e.kind,e.origin.x,e.origin.y,e.delta.x,e.delta.y,e.scale,e.degrees,e.durationMs]);case`drag`:return[e.kind,e.source,e.destination,String(e.sourceHoldMs??800),String(e.moveMs??500),String(e.destinationHoldMs??0)]}}function Ke(e,t={}){return D(`swipe`,e),{from:{x:Number(e[0]),y:Number(e[1])},to:{x:Number(e[2]),y:Number(e[3])},...t.count===void 0?{}:{count:t.count},...t.pauseMs===void 0?{}:{pauseMs:t.pauseMs},...t.pattern===void 0?{}:{pattern:t.pattern}}}function qe(e){switch(e.kind){case`pan`:return{gesture:{intent:`pan`,origin:e.origin,delta:e.delta,pointerCount:e.pointerCount,durationMs:e.durationMs}};case`fling`:return{gesture:{intent:`fling`,direction:e.direction,origin:e.origin,distance:e.distance}};case`swipe`:return{gesture:{intent:`fling`,preset:e.preset}};case`pinch`:return{gesture:{intent:`pinch`,origin:e.origin,scale:e.scale}};case`rotate`:return{gesture:{intent:`rotate`,origin:e.origin,degrees:e.degrees}};case`transform`:return{gesture:{intent:`transform`,origin:e.origin,delta:e.delta,scale:e.scale,degrees:e.degrees,durationMs:e.durationMs}};case`drag`:throw new t(`INVALID_ARGS`,`gesture drag targets must be resolved before coordinate normalization`)}}function Je(e){return e.kind===`drag`?{intent:`drag`,source:e.source,destination:e.destination,sourceHoldMs:e.sourceHoldMs,moveMs:e.moveMs,destinationHoldMs:e.destinationHoldMs}:qe(e).gesture}function Ye(e){return{gesture:{intent:`fling`,from:e.from,to:e.to}}}function k(e){return e===void 0?void 0:Number(e)}function A(e,n){if(e===void 0!=(n===void 0))throw new t(`INVALID_ARGS`,`gesture origin requires both x and y coordinates`);return e===void 0?void 0:{x:Number(e),y:Number(n)}}function j(e){return e.filter(e=>e!==void 0).map(String)}const Xe={ios:!0,android:!0,harmonyos:!0};function Ze(e){return typeof e==`string`&&Object.hasOwn(Xe,e)}function M(t){return t.startsWith(`@`)?e(t)?.base??t:t}const N=/^-?\d+(\.\d+)?$/,Qe=/^[^\s"'\\][^\s"\\]*$/,$e=new Map([[`--count`,`count`],[`--interval-ms`,`intervalMs`],[`--hold-ms`,`holdMs`],[`--jitter-px`,`jitterPx`]]),et=new Map([[`--count`,`count`],[`--pause-ms`,`pauseMs`]]),tt=new Map([[`--pointer-count`,`pointerCount`]]),nt=new Map([[`--delay-ms`,`delayMs`]]),P={scroll:new Map([[`--until`,{key:`until`,kind:`string`}]]),wait:new Map([[`--raw`,{key:`snapshotRaw`,kind:`boolean`}],[`--depth`,{key:`snapshotDepth`,kind:`int`}],[`--scope`,{key:`snapshotScope`,kind:`string`}]])};Object.keys(P);function rt(e,t){let n=[],r={},i=P[e];for(let e=0;e<t.length;e+=1){let a=t[e],o=i.get(a),s=t[e+1];if(o===void 0||o.kind!==`boolean`&&s===void 0){n.push(a);continue}if(o.kind===`boolean`){Object.assign(r,{[o.key]:!0});continue}if(o.kind===`int`){let e=K(s);if(e===null){n.push(a);continue}Object.assign(r,{[o.key]:e})}else Object.assign(r,{[o.key]:s});e+=1}return{positionals:n,flags:r}}function F(e){return e===`click`||e===`press`}function it(e){return F(e)||e===`longpress`||e===`hover`}function I(e){return e===`type`||e===`fill`}function L(e){return B(e,at)}function R(e){return JSON.stringify(e)}function z(e){return B(e,V)}function B(e,t){return t(e)?e:R(e)}function at(e){return V(e)&&e.startsWith(`@`)||N.test(e)}function V(e){return Qe.test(e)}const ot=new Set([`fill`,`type`]);function st(e){if(!ot.has(e.command)){let t=(e.positionals??[]).map(e=>L(e));return[e.command,...t].join(` `)}let t=ct(e).map(e=>L(e)).join(` `);return[e.command,t,`<text>`].filter(e=>e.length>0).join(` `)}function ct(e){if(e.command===`type`)return[];let t=e.positionals??[],n=t[0];return n===void 0?[]:n.startsWith(`@`)?[n]:t.length>=3&&N.test(n)&&N.test(t[1]??``)?[n,t[1]]:[n]}function H(e,t){let n=t.flags??{};if(F(t.command)){typeof n.count==`number`&&e.push(`--count`,String(n.count)),typeof n.intervalMs==`number`&&e.push(`--interval-ms`,String(n.intervalMs)),typeof n.holdMs==`number`&&e.push(`--hold-ms`,String(n.holdMs)),typeof n.jitterPx==`number`&&e.push(`--jitter-px`,String(n.jitterPx)),n.doubleTap===!0&&e.push(`--double-tap`);let t=n.clickButton;t&&t!==`primary`&&e.push(`--button`,t);return}if(t.command===`swipe`){typeof n.count==`number`&&e.push(`--count`,String(n.count)),typeof n.pauseMs==`number`&&e.push(`--pause-ms`,String(n.pauseMs)),(n.pattern===`one-way`||n.pattern===`ping-pong`)&&e.push(`--pattern`,n.pattern);return}if(t.command===`gesture`){typeof n.pointerCount==`number`&&e.push(`--pointer-count`,String(n.pointerCount));return}I(t.command)&&typeof n.delayMs==`number`&&e.push(`--delay-ms`,String(n.delayMs))}function U(e,t){t&&(Ze(t.platform)&&e.push(`--platform`,t.platform),typeof t.metroHost==`string`&&t.metroHost.length>0&&e.push(`--metro-host`,z(t.metroHost)),typeof t.metroPort==`number`&&e.push(`--metro-port`,String(t.metroPort)),typeof t.bundleUrl==`string`&&t.bundleUrl.length>0&&e.push(`--bundle-url`,z(t.bundleUrl)),typeof t.launchUrl==`string`&&t.launchUrl.length>0&&e.push(`--launch-url`,z(t.launchUrl)))}function lt(e,t){let[n,...r]=t.positionals??[];n&&e.push(z(n));for(let t of r)e.push(L(t));typeof t.flags?.fps==`number`&&e.push(`--fps`,String(t.flags.fps)),(typeof t.flags?.quality==`number`||typeof t.flags?.quality==`string`)&&e.push(`--quality`,String(t.flags.quality)),t.flags?.hideTouches&&e.push(`--hide-touches`)}function ut(e,t){t.flags?.snapshotInteractiveOnly&&e.push(`-i`),typeof t.flags?.snapshotDepth==`number`&&e.push(`-d`,String(t.flags.snapshotDepth)),t.flags?.snapshotScope&&e.push(`-s`,L(t.flags.snapshotScope)),t.flags?.snapshotRaw&&e.push(`--raw`)}function dt(e,t){for(let n of t.positionals??[])e.push(L(n));let n=t.flags?.screenshotCropOn;typeof n==`string`&&n.length>0&&e.push(`--crop-on`,z(n)),l(e,t.flags)}function ft(e,t,n={}){let r=t.positionals??[],i=n.includeAllPositionals?r:r.slice(0,1);for(let t of i)e.push(z(t));U(e,t.flags)}function pt(e,t){for(let n of t.positionals??[])e.push(L(t.command===`wait`?M(n):n));t.command===`fold`&&t.flags?.keyframes!==void 0&&e.push(`--keyframes`,L(t.flags.keyframes)),t.command===`scroll`&&typeof t.flags?.until==`string`&&e.push(`--until`,L(t.flags.until)),t.command===`wait`&&mt(e,t.flags),H(e,t)}function mt(e,t){t&&(t.snapshotRaw===!0&&e.push(`--raw`),typeof t.snapshotDepth==`number`&&e.push(`--depth`,String(t.snapshotDepth)),typeof t.snapshotScope==`string`&&e.push(`--scope`,L(t.snapshotScope)))}function W(e,t){let n=[],r={},i=F(e)?$e:e===`swipe`?et:e===`gesture`?tt:I(e)?nt:void 0;for(let a=0;a<t.length;a+=1){let o=t[a];if(F(e)&&o===`--double-tap`){r.doubleTap=!0;continue}let s=t[a+1];if(e===`fold`&&o===`--keyframes`&&s!==void 0){r.keyframes=s,a+=1;continue}if(F(e)&&o===`--button`&&s!==void 0){let e=s;(e===`primary`||e===`secondary`||e===`middle`)&&(r.clickButton=e),a+=1;continue}let c=i?.get(o);if(c&&s!==void 0){let e=K(s);if(e!==null){r[c]=e,a+=1;continue}}if(e===`swipe`&&o===`--pattern`&&s!==void 0){let e=s;(e===`one-way`||e===`ping-pong`)&&(r.pattern=e),a+=1;continue}n.push(o)}return{positionals:n,flags:r}}function G(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let i=e[r],a=e[r+1];if(i===`--platform`&&a!==void 0){let e=a;Ze(e)&&(n.platform=e),r+=1;continue}if(i===`--metro-host`&&a!==void 0){n.metroHost=a,r+=1;continue}if(i===`--metro-port`&&a!==void 0){let e=K(a);e!==null&&(n.metroPort=e),r+=1;continue}if(i===`--bundle-url`&&a!==void 0){n.bundleUrl=a,r+=1;continue}if(i===`--launch-url`&&a!==void 0){n.launchUrl=a,r+=1;continue}t.push(i)}return{positionals:t,flags:n}}function K(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function ht(e){let t;for(let n of e){if(n.command===`runtime`&&typeof n.flags.platform==`string`){t=n.flags.platform;continue}if(n.command===`open`)return n.runtime?.platform??t}return t}function gt(e,t){for(let n of t.positionals??[])e.push(L(n));t.flags?.relaunch&&e.push(`--relaunch`),t.flags?.surface!==void 0&&e.push(`--surface`,t.flags.surface),t.flags?.testIme===!0?e.push(`--test-ime`):t.flags?.testIme===!1&&e.push(`--no-test-ime`),U(e,t.runtime)}function _t(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let i=e[r];if(i===`--surface`){n.surface=bt(e[r+1]),r+=1;continue}if(i===`--relaunch`){n.relaunch=!0;continue}if(i===`--test-ime`){n.testIme=!0;continue}if(i===`--no-test-ime`){n.testIme=!1;continue}t.push(i)}let r=G(t);return{positionals:r.positionals,flags:n,runtime:xt(r.flags)?r.flags:void 0}}const vt={app:!0,"frontmost-app":!0,desktop:!0,menubar:!0};function yt(e){return Object.hasOwn(vt,e)}function bt(e){let n=e?.trim().toLowerCase();if(n!==void 0&&yt(n))return n;throw new t(`INVALID_ARGS`,`Invalid surface: ${e}. Use ${Object.keys(vt).join(`|`)}.`)}function xt(e){return!!(e.platform||e.metroHost||e.metroPort!==void 0||e.bundleUrl||e.launchUrl)}const St=/^[A-Z_][A-Z0-9_]*$/,Ct=new Set(h.filter(e=>e!==`web`)),wt=new Set([`mobile`,`tv`,`desktop`]);function Tt(e){let n=[],r=[],i=e.split(/\r?\n/),a=!1,o,s=(e,n,r)=>{let i=e.kind===`multiple`?`targets-v1`:`target-v1`;throw new t(`INVALID_ARGS`,`${i} annotation on line ${e.line} must be immediately followed by its action line (line ${n+1} ${r}).`)};for(let[e,c]of i.entries()){let i=c.trim();if(i.length===0){o&&s(o,e,`is blank`);continue}if(i.startsWith(`#`)){let t=ne(i);if(t.kind===`v1`){o&&s(o,e,`is another target annotation`),o={kind:`multiple`,evidence:t.evidence,line:e+1};continue}let n=ae(i);if(n.kind===`v1`){o&&s(o,e,`is another target annotation`),o={kind:`single`,evidence:n.evidence,line:e+1};continue}o&&s(o,e,`is a comment`);continue}if(Dt(i)){if(o&&s(o,e,`is an env directive`),a)throw new t(`INVALID_ARGS`,`env directives must precede all actions (line ${e+1}).`);continue}let l=jt(c);if(!l){o&&s(o,e,`did not parse as an action`);continue}let u=Ve(l.command,l.positionals??[],`line ${e+1}`);if(u)throw new t(`INVALID_ARGS`,u);o&&=(o.kind===`single`?l.targetEvidence=o.evidence:l.targetEvidences=o.evidence,void 0),n.push(l),r.push(e+1),a=!0}if(o){let e=o.kind===`multiple`?`targets-v1`:`target-v1`;throw new t(`INVALID_ARGS`,`${e} annotation on line ${o.line} must be immediately followed by its action line (end of script reached).`)}return{actions:n,actionLines:r}}function Et(e){let t=e.split(/\r?\n/),n={};for(let[e,r]of t.entries()){let t=r.trim();if(t.length===0||t.startsWith(`#`))continue;if(Dt(t)){At(n,t,e+1);continue}if(!t.startsWith(`context `))break;let i=t.match(/(?:^|\s)platform=([^\s]+)/);if(i){let e=i[1];e&&Ct.has(e)&&q(n,`platform`,e)}let a=t.match(/(?:^|\s)target=([^\s]+)/);if(a){let e=a[1];e&&wt.has(e)&&q(n,`target`,e)}let o=t.match(/(?:^|\s)timeout=(\d+)/);if(o){let e=Number(o[1]);Number.isFinite(e)&&e>=1&&q(n,`timeoutMs`,Math.floor(e))}let s=t.match(/(?:^|\s)retries=(\d+)/);if(s){let e=Number(s[1]);Number.isFinite(e)&&e>=0&&q(n,`retries`,Math.floor(e))}}return n}function Dt(e){return e===`env`||e.startsWith(`env `)||e.startsWith(`env `)}function Ot(e,n){let r=e.slice(3).replace(/^[\s]+/,``),i=r.indexOf(`=`);if(i<=0)throw new t(`INVALID_ARGS`,`Invalid env directive on line ${n}: expected "env KEY=VALUE".`);let a=r.slice(0,i);if(!St.test(a))throw new t(`INVALID_ARGS`,`Invalid env key "${a}" on line ${n}: keys must be uppercase letters, digits, and underscores (e.g. APP_ID).`);if(a.startsWith(`AD_`))throw new t(`INVALID_ARGS`,`Invalid env key "${a}" on line ${n}: the AD_* namespace is reserved for built-in variables. Rename ${a} to avoid the AD_ prefix.`);return{key:a,value:kt(r.slice(i+1),n)}}function kt(e,n){if(e.length===0)return``;if(e.startsWith(`"`))try{let t=JSON.parse(e);if(typeof t!=`string`)throw Error(`not a string literal`);return t}catch{throw new t(`INVALID_ARGS`,`Invalid quoted env value on line ${n}.`)}return e}function At(e,n,r){let{key:i,value:a}=Ot(n,r),o=e.env??{};if(Object.prototype.hasOwnProperty.call(o,i))throw new t(`INVALID_ARGS`,`Duplicate env directive "${i}" on line ${r}.`);o[i]=a,e.env=o}function q(e,n,r){let i=e[n];if(i!==void 0){let e=i===r?`Duplicate replay test metadata "${n}" in context header.`:`Conflicting replay test metadata "${n}" in context header: ${String(i)} vs ${String(r)}.`;throw new t(`INVALID_ARGS`,e)}e[n]=r}function jt(e){let n=e.trim();if(n.length===0||n.startsWith(`#`))return null;let[r,...i]=Nt(n);if(r===void 0||r===`context`)return null;let a={ts:Date.now(),command:r,positionals:[],flags:{}};if(r===`snapshot`){a.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if(t===`-i`){a.flags.snapshotInteractiveOnly=!0;continue}if(t!==`-c`){if(t===`--raw`){a.flags.snapshotRaw=!0;continue}if(t===`--force-full`){a.flags.snapshotForceFull=!0;continue}if((t===`-d`||t===`--depth`)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(a.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if((t===`-s`||t===`--scope`)&&e+1<i.length){a.flags.snapshotScope=i[e+1],e+=1;continue}if(t===`--backend`&&e+1<i.length){e+=1;continue}}}return a}if(r===`open`){let e=_t(i);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a.runtime=e.runtime,a}if(r===`runtime`){let e=G(i);return a.positionals=e.positionals,Object.assign(a.flags,e.flags),a}if(F(r)){let e=W(r,i);Object.assign(a.flags,e.flags);let t=e.positionals[0];if(t===void 0)return a;if(t.startsWith(`@`))return a.positionals=[M(t)],e.positionals[1]&&(a.result={refLabel:e.positionals[1]}),a;let n=e.positionals[0],o=e.positionals[1];return J(n)&&J(o)&&e.positionals.length>=2?(a.positionals=[n,o],a):(a.positionals=[e.positionals.join(` `)],a)}if(r===`fill`){let e=W(r,i);if(Object.assign(a.flags,e.flags),!Mt(e.positionals))return a.positionals=e.positionals,a;let[t,n,...o]=e.positionals;if(J(t)&&J(n))return a.positionals=[t,n,o.join(` `)],a;let[s,c,...l]=e.positionals;if(s.startsWith(`@`)){let e=M(s);return l.length>0?(a.positionals=[e,l.join(` `)],a.result={refLabel:c},a):(a.positionals=[e,c],a)}return a.positionals=[s,[c,...l].join(` `)],a}if(r===`get`){let e=i[0],t=i[1];return e===void 0||t===void 0?(a.positionals=i,a):t.startsWith(`@`)?(a.positionals=[e,M(t)],i[2]&&(a.result={refLabel:i[2]}),a):(a.positionals=[e,i.slice(1).join(` `)],a)}if(r===`swipe`||r===`type`||r===`gesture`||r===`fold`){let e=W(r,i);return Object.assign(a.flags,e.flags),a.positionals=e.positionals,a}if(r===`record`){let e=[];for(let n=0;n<i.length;n+=1){let r=i[n];if(r===u.cliToken)throw new t(`INVALID_ARGS`,u.migration.record);if(r===`--hide-touches`){a.flags.hideTouches=!0;continue}if(r===`--fps`&&n+1<i.length){let e=Number(i[n+1]);Number.isFinite(e)&&(a.flags.fps=Math.floor(e)),n+=1;continue}if(r===`--quality`&&n+1<i.length){let e=i[n+1],t=oe(e);t!==void 0&&(a.flags.quality=t),n+=1;continue}e.push(r)}return a.positionals=e,a}if(r===`screenshot`){let e=[];for(let t=0;t<i.length;t+=1){let n=i[t],r=c({args:i,index:t,flags:a.flags});if(r.handled){t=r.nextIndex;continue}e.push(n)}return a.positionals=e,a}if(r===`scroll`||r===`wait`){let e=rt(r,i);return Object.assign(a.flags,e.flags),a.positionals=e.positionals.map(e=>M(e)),a}return a.positionals=r===`longpress`||r===`hover`?i.map(e=>M(e)):i,a}function Mt(e){return e.length>=2}function J(e){return e?!Number.isNaN(Number(e)):!1}function Nt(e){let t=[],n=0;for(;n<e.length&&(n=Pt(e,n),!(n>=e.length));){let r=e[n]===`"`?Ft(e,n):It(e,n)??Vt(e,n);t.push(r.value),n=r.nextCursor}return t}function Pt(e,t){let n=t;for(;n<e.length&&/\s/.test(e.charAt(n));)n+=1;return n}function Ft(e,n){let r=n+1,i=!1,a=r;for(;a<e.length;a+=1){let t=e.charAt(a);if(t===`"`&&!i)break;if(i){i=!1;continue}i=t===`\\`}if(a>=e.length)throw new t(`INVALID_ARGS`,`Invalid replay script line: ${e}`);let o=e.slice(n,a+1),s;try{s=JSON.parse(o)}catch{throw new t(`INVALID_ARGS`,`Invalid quoted value ${o} in replay script line: ${e}`,{hint:`Quoted replay values are JSON strings: escape backslashes, quotes, tabs, and newlines (\\\\, \\", \\t, \\n).`})}return{value:s,nextCursor:a+1}}function It(e,t){if(e[t]!==`'`)return null;let n=Lt(e,t+1);return n===-1||!zt(e,n+1)?null:{value:Bt(e.slice(t+1,n)),nextCursor:n+1}}function Lt(e,t){let n=t;for(;n<e.length;){let t=e.indexOf(`'`,n);if(t===-1)return-1;if(!Rt(e,t))return t;n=t+1}return-1}function Rt(e,t){let n=0;for(;t>0&&e.charAt(t-1)===`\\`;)n+=1,--t;return n%2==1}function zt(e,t){return t>=e.length||/\s/.test(e.charAt(t))}function Bt(e){return e.replaceAll(String.raw`\'`,`'`)}function Vt(e,t){let n=t;for(;n<e.length&&!/\s/.test(e.charAt(n));)n+=1;return{value:e.slice(t,n),nextCursor:n}}function Ht(e){let t=fe.extname(e).toLowerCase();return t===`.yaml`||t===`.yml`}function Ut(e,t){return`Maestro YAML requires explicit --maestro routing: ${e} ${t} --maestro`}function Wt(e){return`Unsupported replay backend "${e}".`}function Gt(e){return e===`maestro`}function Kt(e,t){return t===`maestro`&&Ht(e)?`maestro`:`ad`}const qt=Y(`public`),Jt=Y(`internal`),Yt=Y(`local-cli`),Xt={help:`help`};function Zt(){return[...Object.values(qt),...Object.values(Yt)].sort()}function Qt(e){return Object.values(Xt).includes(e)||Object.values(Jt).includes(e)?!0:Zt().includes(e)}function Y(e){let t={};for(let[n,r]of te(e))t[n]=r;return t}const $t=[{key:`keyframes`,names:[`--keyframes`],type:`string`,usageLabel:`--keyframes <json>`,usageDescription:`Fold: timed {atMs, angle} keyframes; final atMs is motion duration (up to 60000ms)`,projectConfig:!1,recorded:!0},{key:`count`,names:[`--count`],type:`int`,min:1,max:200,usageLabel:`--count <n>`,usageDescription:`Repeat count for press/swipe series`,projectConfig:!0,recorded:!0},{key:`pointerCount`,names:[`--pointer-count`],type:`int`,min:1,max:2,usageLabel:`--pointer-count <1|2>`,usageDescription:`Gesture pan: number of touch pointers (default 1)`,projectConfig:!0,recorded:!0},{key:`fps`,names:[`--fps`],type:`int`,min:1,max:120,usageLabel:`--fps <n>`,usageDescription:`Record: target frames per second (iOS physical device runner); also lowers the touch-overlay rate, which never exceeds 30`,projectConfig:!0,recorded:!0},{key:`quality`,names:[`--quality`],type:`string`,usageLabel:`--quality <medium|high>`,usageDescription:`Record: output quality preset; Android maps this to screenrecord bitrate, Limrun sessions map medium to recorder quality 5 and high to 8; Apple export always preserves the captured resolution, so it has no effect there. Legacy numeric values 5-7 map to medium; 8-10 map to high`,projectConfig:!0,recorded:!0},{key:`hideTouches`,names:[`--hide-touches`],type:`boolean`,usageLabel:`--hide-touches`,usageDescription:`Record: skip touch-overlay post-processing for faster raw benchmark videos`,projectConfig:!0,recorded:!0},{key:`recordingScope`,names:[`--scope`],type:`enum`,enumValues:se,usageLabel:`--scope <app|device|system>`,usageDescription:`Record: app requires an active app session; device/system records the whole screen`,projectConfig:!0,recorded:!1},{key:`intervalMs`,names:[`--interval-ms`],type:`int`,min:0,max:1e4,usageLabel:`--interval-ms <ms>`,usageDescription:`Delay between press iterations`,projectConfig:!0,recorded:!0},{key:`delayMs`,names:[`--delay-ms`],type:`int`,min:0,max:1e4,usageLabel:`--delay-ms <ms>`,usageDescription:`Delay between typed characters`,projectConfig:!0,recorded:!0},{key:`recordAs`,names:[`--record-as`],type:`string`,usageLabel:`--record-as <VAR>`,usageDescription:"Fill: send the live text but publish ${VAR} in an armed .ad recording",projectConfig:!0,recorded:!1},{key:`textStdin`,names:[`--text-stdin`],type:`boolean`,usageLabel:`--text-stdin`,usageDescription:`Fill: read the text from stdin (max 64 KiB, one trailing newline removed) instead of argv`,projectConfig:!1,recorded:!1},{key:`durationMs`,names:[`--duration-ms`],type:`int`,min:0,max:1e4,usageLabel:`--duration-ms <ms>`,usageDescription:`Scroll: pace the gesture over this duration when supported`,projectConfig:!0,recorded:!1},{key:`holdMs`,names:[`--hold-ms`],type:`int`,min:0,max:1e4,usageLabel:`--hold-ms <ms>`,usageDescription:`Press hold duration for each iteration`,projectConfig:!0,recorded:!0},{key:`jitterPx`,names:[`--jitter-px`],type:`int`,min:0,max:100,usageLabel:`--jitter-px <n>`,usageDescription:`Deterministic coordinate jitter radius for press`,projectConfig:!0,recorded:!0},{key:`pixels`,names:[`--pixels`],type:`int`,min:1,max:1e5,usageLabel:`--pixels <n>`,usageDescription:`Scroll: explicit gesture distance in pixels`,projectConfig:!0,recorded:!1},{key:`until`,names:[`--until`],type:`string`,usageLabel:`--until <selector>`,usageDescription:`Scroll: repeat passes until the selector is visible on screen`,projectConfig:!0,recorded:!0},{key:`doubleTap`,names:[`--double-tap`],type:`boolean`,usageLabel:`--double-tap`,usageDescription:`Use double-tap gesture per press iteration`,projectConfig:!0,recorded:!0},{key:`verify`,names:[`--verify`],type:`boolean`,usageLabel:`--verify`,usageDescription:`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot`,projectConfig:!0,recorded:!1},{key:`settle`,names:[`--settle`],type:`boolean`,usageLabel:`--settle`,usageDescription:`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response (best-effort; never fails the action)`,projectConfig:!0,recorded:!1},{key:`settleQuietMs`,names:[`--settle-quiet`],type:`int`,min:0,usageLabel:`--settle-quiet <ms>`,usageDescription:`Settle: quiet window the UI must hold to count as settled (default 500ms)`,projectConfig:!0,recorded:!1},{key:`clickButton`,names:[`--button`],type:`enum`,enumValues:[`primary`,`secondary`,`middle`],usageLabel:`--button primary|secondary|middle`,usageDescription:`Click: choose mouse button (middle reserved for future macOS support)`,projectConfig:!0,recorded:!0},{key:`backMode`,names:[`--in-app`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`in-app`,usageLabel:`--in-app`,usageDescription:`Back: use app-provided back UI when available`,projectConfig:!0,recorded:!1},{key:`backMode`,names:[`--system`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`system`,usageLabel:`--system`,usageDescription:`Back: use system back input or gesture when available`,projectConfig:!0,recorded:!1},{key:`pauseMs`,names:[`--pause-ms`],type:`int`,min:0,max:1e4,usageLabel:`--pause-ms <ms>`,usageDescription:`Delay between swipe iterations`,projectConfig:!0,recorded:!0},{key:`pattern`,names:[`--pattern`],type:`enum`,enumValues:[`one-way`,`ping-pong`],usageLabel:`--pattern one-way|ping-pong`,usageDescription:`Swipe repeat pattern`,projectConfig:!0,recorded:!0},{key:`verbose`,names:[`--debug`,`--verbose`,`-v`],type:`boolean`,usageLabel:`--debug, --verbose, -v`,usageDescription:`Enable debug diagnostics; test --verbose prints per-test step timings without debug logs`,projectConfig:!0,recorded:!0},{key:`cost`,names:[`--cost`],type:`boolean`,usageLabel:`--cost`,usageDescription:`Include per-command wall-clock latency (cost.wallClockMs) in the response`,projectConfig:!0,recorded:!1},{key:`responseLevel`,names:[`--level`],type:`enum`,enumValues:r,usageLabel:`--level digest|default|full`,usageDescription:`Response detail level: digest (token-cheap), default (today), or full. Default keeps the wire shape unchanged.`,projectConfig:!0,recorded:!1},{key:`json`,names:[`--json`],type:`boolean`,usageLabel:`--json`,usageDescription:`JSON output`,projectConfig:!0,recorded:!1},{key:`help`,names:[`--help`,`-h`],type:`boolean`,usageLabel:`--help, -h`,usageDescription:`Print help and exit`,projectConfig:!1,recorded:!1},{key:`version`,names:[`--version`,`-V`],type:`boolean`,usageLabel:`--version, -V`,usageDescription:`Print version and exit`,projectConfig:!1,recorded:!1},{key:`snapshotDiff`,names:[`--diff`],type:`boolean`,usageLabel:`--diff`,usageDescription:`Snapshot: show structural diff against the previous session baseline`,projectConfig:!0,recorded:!1},{key:`saveScript`,names:[`--save-script`],type:`booleanOrString`,usageLabel:`--save-script [path]`,usageDescription:`Arm evidence capture on open, publish the armed recording on close; close --save-script alone (without an armed open) is rejected — start with open --save-script, or use session save-script mid-session. Optional custom output path.`,projectConfig:!1,recorded:!0},{key:`networkInclude`,names:[`--include`],type:`enum`,enumValues:[`summary`,`headers`,`body`,`all`],usageLabel:`--include summary|headers|body|all`,usageDescription:`Network: include headers, bodies, or both in output`,projectConfig:!0,recorded:!1},{key:`shutdown`,names:[`--shutdown`],type:`boolean`,usageLabel:`--shutdown`,usageDescription:`close: shutdown associated simulator/emulator after ending session`,projectConfig:!0,recorded:!1},{key:`relaunch`,names:[`--relaunch`],type:`boolean`,usageLabel:`--relaunch`,usageDescription:`open: terminate app process before launching it`,projectConfig:!0,recorded:!0},{key:`foreground`,names:[`--foreground`],type:`boolean`,usageLabel:`--foreground`,usageDescription:`open: keep normal app/device selection and return an initial snapshot; without an app, resolve the sole running app on the sole booted iOS simulator`,inputDescription:`Include an initial interactive snapshot in a fresh open response. With no app argument, discover the sole running app on the sole booted iOS simulator; ambiguous environments fail closed.`,projectConfig:!1,recorded:!1},{key:`restart`,names:[`--restart`],type:`boolean`,usageLabel:`--restart`,usageDescription:`logs clear: stop active stream, clear logs, then start streaming again`,projectConfig:!0,recorded:!1},{key:`retainPaths`,names:[`--retain-paths`],type:`boolean`,usageLabel:`--retain-paths`,usageDescription:`install-from-source: keep materialized artifact paths after install`,projectConfig:!0,recorded:!1},{key:`retentionMs`,names:[`--retention-ms`],type:`int`,min:1,usageLabel:`--retention-ms <ms>`,usageDescription:`install-from-source: retention TTL for materialized artifact paths`,projectConfig:!0,recorded:!1},{key:`noRecord`,names:[`--no-record`],type:`boolean`,usageLabel:`--no-record`,usageDescription:`Do not record this action`,projectConfig:!0,recorded:!0},{key:`record`,names:[`--record`],type:`boolean`,usageLabel:`--record`,usageHidden:!0,usageDescription:`Force-record this action even though its command is observation-only and would otherwise be excluded from a repair-armed heal by default (mutually exclusive with --no-record)`,projectConfig:!0,recorded:!0}],en=[{key:`config`,names:[`--config`],type:`string`,usageLabel:`--config <path>`,usageDescription:`Load CLI defaults from a specific config file (required for connection/provider defaults outside user config)`,projectConfig:!1,recorded:!1},{key:`remoteConfig`,names:[`--remote-config`],type:`string`,usageLabel:`--remote-config <path>`,usageDescription:`Load remote host + Metro workflow settings from a specific profile file`,projectConfig:!1,recorded:!1},{key:`stateDir`,names:[`--state-dir`],type:`string`,usageLabel:`--state-dir <path>`,usageDescription:`Daemon state directory (defaults to ~/.agent-device for packages, or a worktree-scoped dev dir from source)`,projectConfig:!1,recorded:!1},{key:`daemonBaseUrl`,names:[`--daemon-base-url`],type:`string`,usageLabel:`--daemon-base-url <url>`,usageDescription:`Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)`,projectConfig:!1,recorded:!1},{key:`daemonAuthToken`,names:[`--daemon-auth-token`],type:`string`,usageLabel:`--daemon-auth-token <token>`,usageDescription:`Remote HTTP daemon or proxy auth token (sent as request token and bearer header)`,projectConfig:!1,recorded:!1},{key:`daemonTransport`,names:[`--daemon-transport`],type:`enum`,enumValues:[`auto`,`socket`,`http`],usageLabel:`--daemon-transport auto|socket|http`,usageDescription:`Daemon client transport preference`,projectConfig:!1,recorded:!1},{key:`daemonServerMode`,names:[`--daemon-server-mode`],type:`enum`,enumValues:[`socket`,`http`,`dual`],usageLabel:`--daemon-server-mode socket|http|dual`,usageDescription:`Daemon server mode used when spawning daemon`,projectConfig:!1,recorded:!1},{key:`proxyHost`,names:[`--host`],type:`string`,usageLabel:`--host <host>`,usageDescription:`Proxy: host interface to bind (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`proxyPort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`Proxy: TCP port to bind (default: 0, choose a free port)`,projectConfig:!1,recorded:!1},{key:`tenant`,names:[`--tenant`],type:`string`,usageLabel:`--tenant <id>`,usageDescription:`Tenant scope identifier for isolated daemon sessions`,projectConfig:!1,recorded:!1},{key:`sessionIsolation`,names:[`--session-isolation`],type:`enum`,enumValues:[`none`,`tenant`],usageLabel:`--session-isolation none|tenant`,usageDescription:`Session isolation strategy (tenant prefixes session namespace)`,projectConfig:!1,recorded:!1},{key:`runId`,names:[`--run-id`],type:`string`,usageLabel:`--run-id <id>`,usageDescription:`Run identifier used for tenant lease admission checks`,projectConfig:!1,recorded:!1},{key:`leaseId`,names:[`--lease-id`],type:`string`,usageLabel:`--lease-id <id>`,usageDescription:`Lease identifier bound to tenant/run admission scope`,projectConfig:!1,recorded:!1},{key:`leaseBackend`,names:[`--lease-backend`],type:`enum`,enumValues:i,usageLabel:`--lease-backend ${i.join(`|`)}`,usageDescription:`Lease backend for remote tenant connection admission`,projectConfig:!1,recorded:!1},{key:`provider`,names:[`--provider`],type:`string`,usageLabel:`--provider <name>`,usageDescription:`Cloud provider name for provider-scoped commands`,projectConfig:!1,recorded:!1},{key:`providerSessionId`,names:[`--provider-session`],type:`string`,usageLabel:`--provider-session <id>`,usageDescription:`Cloud provider session id or ARN`,projectConfig:!1,recorded:!1},{key:`providerApp`,names:[`--provider-app`],type:`string`,usageLabel:`--provider-app <ref-or-path>`,usageDescription:`Cloud provider app reference or local app path used when creating hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`providerOsVersion`,names:[`--provider-os-version`,`--os-version`],type:`string`,usageLabel:`--provider-os-version <version>`,usageDescription:`Hosted cloud provider OS version, for example 17 or 14.0`,projectConfig:!1,recorded:!1},{key:`providerDeviceType`,names:[`--provider-device-type`],type:`enum`,enumValues:le,usageLabel:`--provider-device-type real|virtual`,usageDescription:`TestMu AI device pool: real devices or virtual devices (emulators and simulators). Defaults to virtual`,projectConfig:!1,recorded:!1},{key:`providerProject`,names:[`--provider-project`],type:`string`,usageLabel:`--provider-project <name>`,usageDescription:`Hosted cloud provider project label`,projectConfig:!1,recorded:!1},{key:`providerBuild`,names:[`--provider-build`],type:`string`,usageLabel:`--provider-build <name>`,usageDescription:`Hosted cloud provider build label`,projectConfig:!1,recorded:!1},{key:`providerSessionName`,names:[`--provider-session-name`],type:`string`,usageLabel:`--provider-session-name <name>`,usageDescription:`Hosted cloud provider session label`,projectConfig:!1,recorded:!1},{key:`providerDeviceOrientation`,names:[`--provider-device-orientation`,`--device-orientation`],type:`enum`,enumValues:ce,usageLabel:`--provider-device-orientation portrait|landscape`,usageDescription:`Screen orientation a hosted cloud provider session starts in. Set this rather than rotating after launch: a session that boots landscape renders login webviews landscape`,projectConfig:!1,recorded:!1},{key:`providerGeoLocation`,names:[`--provider-geo-location`,`--geo-location`],type:`string`,usageLabel:`--provider-geo-location <country>`,usageDescription:`Hosted cloud provider IP geolocation country code, for example US`,projectConfig:!1,recorded:!1},{key:`providerTimezone`,names:[`--provider-timezone`,`--timezone`],type:`string`,usageLabel:`--provider-timezone <zone>`,usageDescription:`Hosted cloud provider device time zone, for example New_York`,projectConfig:!1,recorded:!1},{key:`providerAppiumVersion`,names:[`--provider-appium-version`,`--appium-version`],type:`string`,usageLabel:`--provider-appium-version <version>`,usageDescription:`Hosted cloud provider Appium server version, for example 3.2.0. Without it each provider starts its own default (Appium 1.x on BrowserStack)`,projectConfig:!1,recorded:!1},{key:`providerLanguage`,names:[`--provider-language`,`--language`],type:`string`,usageLabel:`--provider-language <language>`,usageDescription:`Hosted cloud provider app language, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerLocale`,names:[`--provider-locale`,`--locale`],type:`string`,usageLabel:`--provider-locale <locale>`,usageDescription:`Hosted cloud provider device locale, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerNetworkProfile`,names:[`--provider-network-profile`,`--network-profile`],type:`string`,usageLabel:`--provider-network-profile <profile>`,usageDescription:`Hosted cloud provider named network condition profile, for example 4g-lte-advanced-good. Mutually exclusive with --provider-custom-network`,projectConfig:!1,recorded:!1},{key:`providerCustomNetwork`,names:[`--provider-custom-network`,`--custom-network`],type:`string`,usageLabel:`--provider-custom-network <shape>`,usageDescription:`Hosted cloud provider custom network shape. Mutually exclusive with --provider-network-profile`,projectConfig:!1,recorded:!1},{key:`providerNoResignApp`,names:[`--provider-no-resign-app`],type:`boolean`,usageLabel:`--provider-no-resign-app`,usageDescription:`iOS only: keep an Enterprise-signed app as uploaded instead of letting the provider re-sign it, which strips entitlements such as push notifications`,projectConfig:!1,recorded:!1},{key:`awsProjectArn`,names:[`--aws-project-arn`],type:`string`,usageLabel:`--aws-project-arn <arn>`,usageDescription:`AWS Device Farm project ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsDeviceArn`,names:[`--aws-device-arn`],type:`string`,usageLabel:`--aws-device-arn <arn>`,usageDescription:`AWS Device Farm device ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsAppArn`,names:[`--aws-app-arn`],type:`string`,usageLabel:`--aws-app-arn <arn>`,usageDescription:`AWS Device Farm app ARN attached to hosted remote access sessions`,projectConfig:!1,recorded:!1},{key:`awsRegion`,names:[`--aws-region`],type:`string`,usageLabel:`--aws-region <region>`,usageDescription:`AWS region for Device Farm API calls`,projectConfig:!1,recorded:!1},{key:`awsInteractionMode`,names:[`--aws-interaction-mode`],type:`enum`,enumValues:[`INTERACTIVE`,`NO_VIDEO`,`VIDEO_ONLY`],usageLabel:`--aws-interaction-mode INTERACTIVE|NO_VIDEO|VIDEO_ONLY`,usageDescription:`AWS Device Farm remote access interaction mode`,projectConfig:!1,recorded:!1},{key:`force`,names:[`--force`,`--overwrite`],type:`boolean`,usageLabel:`--force, --overwrite`,usageDescription:`Force replacement of existing state (connect: replace an active connection; --save-script: overwrite an existing target instead of refusing)`,projectConfig:!0,recorded:!0},{key:`clean`,names:[`--clean`],type:`boolean`,usageLabel:`--clean`,usageDescription:`Daemon stop: remove retained runner processes and leases after stopping`,projectConfig:!0,recorded:!1},{key:`noLogin`,names:[`--no-login`],type:`boolean`,usageLabel:`--no-login`,usageDescription:`Connect: fail instead of starting implicit cloud login`,projectConfig:!0,recorded:!1},{key:`sessionLock`,names:[`--session-lock`],type:`enum`,enumValues:[`reject`,`strip`],usageLabel:`--session-lock reject|strip`,usageDescription:`Lock bound-session device routing for this CLI invocation and nested batch steps; strip drops conflicting platform/scope selectors only, and a selector naming a different device always fails`,projectConfig:!0,recorded:!1}],tn=[{key:`platform`,names:[`--platform`],type:`enum`,enumValues:h,usageLabel:`--platform ${h.join(`|`)}`,usageDescription:"Platform to target (`apple` aliases the Apple automation backend)",projectConfig:!0,recorded:!0},{key:`target`,names:[`--target`],type:`enum`,enumValues:[`mobile`,`tv`,`desktop`],usageLabel:`--target mobile|tv|desktop`,usageDescription:`Device target class to match`,projectConfig:!0,recorded:!1},{key:`device`,names:[`--device`],type:`string`,usageLabel:`--device <name>`,usageDescription:`Device name to target (a UDID belongs in --udid, a serial in --serial)`,projectConfig:!0,recorded:!0},{key:`udid`,names:[`--udid`],type:`string`,usageLabel:`--udid <udid>`,usageDescription:`Apple device or simulator UDID; the only selector that pins one device when several share a --device name`,projectConfig:!0,recorded:!0},{key:`serial`,names:[`--serial`],type:`string`,usageLabel:`--serial <serial>`,usageDescription:`Android, HarmonyOS, or Vega VVD serial`,projectConfig:!0,recorded:!0},{key:`stale`,names:[`--stale`],type:`boolean`,usageLabel:`--stale`,usageDescription:`Device status: show only claims with a provably stale owner`,projectConfig:!0,recorded:!1},{key:`surface`,names:[`--surface`],type:`enum`,enumValues:ue,usageLabel:`--surface app|frontmost-app|desktop|menubar`,usageDescription:`macOS session surface for open (defaults to app)`,projectConfig:!0,recorded:!0},{key:`headless`,names:[`--headless`],type:`boolean`,usageLabel:`--headless`,usageDescription:`Boot: launch Android emulator without a GUI window`,projectConfig:!0,recorded:!1},{key:`targetApp`,names:[`--app`,`--target-app`],type:`string`,usageLabel:`--app <id-or-name>`,usageDescription:`Target an app without opening it: doctor verifies an installed app by id or name; settings applies an app-scoped change (permission, iOS location) to a bundle id or package`,projectConfig:!1,recorded:!1},{key:`metroHost`,names:[`--metro-host`],type:`string`,usageLabel:`--metro-host <host>`,usageDescription:`Session-scoped Metro/debug host hint`,projectConfig:!1,recorded:!0},{key:`metroPort`,names:[`--metro-port`],type:`int`,min:1,max:65535,usageLabel:`--metro-port <port>`,usageDescription:`Session-scoped Metro/debug port hint; on an emulator/simulator the host defaults to the loopback alias, physical devices still need --metro-host`,projectConfig:!1,recorded:!0},{key:`metroProjectRoot`,names:[`--project-root`],type:`string`,usageLabel:`--project-root <path>`,usageDescription:`metro prepare: React Native project root (default: cwd)`,projectConfig:!1,recorded:!1},{key:`kind`,names:[`--kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`,...de],usageLabel:`--kind <kind>`,usageDescription:`Kind selector for commands that support it, such as metro prepare or perf artifact collectors`,projectConfig:!0,recorded:!1},{key:`perfTemplate`,names:[`--template`],type:`string`,usageLabel:`--template <name>`,usageDescription:`Perf xctrace template name, for example Time Profiler`,projectConfig:!0,recorded:!1},{key:`metroKind`,names:[`--metro-kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`],usageLabel:`--metro-kind auto|react-native|expo|repack`,usageDescription:`metro prepare: detect or force the React Native dev-server launcher kind`,projectConfig:!1,recorded:!1},{key:`metroPublicBaseUrl`,names:[`--public-base-url`],type:`string`,usageLabel:`--public-base-url <url>`,usageDescription:`metro prepare: public base URL used for direct dev-server bundle hints`,projectConfig:!1,recorded:!1},{key:`metroProxyBaseUrl`,names:[`--proxy-base-url`],type:`string`,usageLabel:`--proxy-base-url <url>`,usageDescription:`metro prepare: optional bridge origin for remote dev-server access`,projectConfig:!1,recorded:!1},{key:`metroBearerToken`,names:[`--bearer-token`],type:`string`,usageLabel:`--bearer-token <token>`,usageDescription:`metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)`,projectConfig:!1,recorded:!1},{key:`metroPreparePort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`metro prepare: local dev-server port (default: 8081)`,projectConfig:!1,recorded:!1},{key:`metroListenHost`,names:[`--listen-host`],type:`string`,usageLabel:`--listen-host <host>`,usageDescription:`metro prepare: host dev server listens on (default: 0.0.0.0)`,projectConfig:!1,recorded:!1},{key:`metroStatusHost`,names:[`--status-host`],type:`string`,usageLabel:`--status-host <host>`,usageDescription:`metro prepare: host used for local dev-server /status polling (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`metroStartupTimeoutMs`,names:[`--startup-timeout-ms`],type:`int`,min:1,usageLabel:`--startup-timeout-ms <ms>`,usageDescription:`metro prepare: timeout while waiting for the dev server to become ready`,projectConfig:!1,recorded:!1},{key:`metroProbeTimeoutMs`,names:[`--probe-timeout-ms`],type:`int`,min:1,usageLabel:`--probe-timeout-ms <ms>`,usageDescription:`metro prepare: timeout for /status and proxy bridge calls`,projectConfig:!1,recorded:!1},{key:`metroRuntimeFile`,names:[`--runtime-file`],type:`string`,usageLabel:`--runtime-file <path>`,usageDescription:`metro prepare: optional file path to persist the JSON result`,projectConfig:!1,recorded:!1},{key:`metroNoReuseExisting`,names:[`--no-reuse-existing`],type:`boolean`,usageLabel:`--no-reuse-existing`,usageDescription:`metro prepare: always start a fresh Metro process`,projectConfig:!1,recorded:!1},{key:`metroNoInstallDeps`,names:[`--no-install-deps`],type:`boolean`,usageLabel:`--no-install-deps`,usageDescription:`metro prepare: skip package-manager install when node_modules is missing`,projectConfig:!1,recorded:!1},{key:`bundleUrl`,names:[`--bundle-url`],type:`string`,usageLabel:`--bundle-url <url>`,usageDescription:`Session-scoped bundle URL hint`,projectConfig:!1,recorded:!0},{key:`launchUrl`,names:[`--launch-url`],type:`string`,usageLabel:`--launch-url <url>`,usageDescription:`Session-scoped deep link / launch URL hint`,projectConfig:!0,recorded:!0},{key:`iosSimulatorDeviceSet`,names:[`--ios-simulator-device-set`],type:`string`,usageLabel:`--ios-simulator-device-set <path>`,usageDescription:`Scope iOS simulator discovery/commands to this simulator device set`,projectConfig:!1,recorded:!1},{key:`iosXctestrunFile`,names:[`--ios-xctestrun-file`],type:`string`,usageLabel:`--ios-xctestrun-file <path>`,usageDescription:`Use an externally built iOS XCTest runner .xctestrun artifact`,projectConfig:!1,recorded:!1},{key:`iosXctestDerivedDataPath`,names:[`--ios-xctest-derived-data-path`],type:`string`,usageLabel:`--ios-xctest-derived-data-path <path>`,usageDescription:`Derived data path for external iOS XCTest runner execution`,projectConfig:!1,recorded:!1},{key:`iosXctestEnvDir`,names:[`--ios-xctest-env-dir`],type:`string`,usageLabel:`--ios-xctest-env-dir <path>`,usageDescription:`Writable directory for per-session iOS XCTest runner env overlays`,projectConfig:!1,recorded:!1},{key:`testIme`,names:[`--test-ime`],type:`boolean`,usageLabel:`--test-ime`,usageDescription:`open/test/replay: activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices; on test/replay it applies to the sessions the flow opens)`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--no-test-ime`],type:`boolean`,setValue:!1,usageLabel:`--no-test-ime`,usageDescription:`open/test/replay: keep the real Android keyboard even on emulators (opt out of the headless test IME; on test/replay it applies to the sessions the flow opens)`,projectConfig:!0,recorded:!1},{key:`androidDeviceAllowlist`,names:[`--android-device-allowlist`],type:`string`,usageLabel:`--android-device-allowlist <serials>`,usageDescription:`Comma/space separated Android serial allowlist for discovery/selection`,projectConfig:!1,recorded:!1},{key:`remote`,names:[`--remote`],type:`boolean`,usageLabel:`--remote`,usageDescription:`Doctor: check remote connection setup instead of local device inventory`,projectConfig:!0,recorded:!1},{key:`activity`,names:[`--activity`],type:`string`,usageLabel:`--activity <component>`,usageDescription:`Android launch activity (package/Class, .Class, or Class) or HarmonyOS ability name; not for URL opens`,projectConfig:!0,recorded:!1},{key:`launchConsole`,names:[`--launch-console`],type:`string`,usageLabel:`--launch-console <path>`,usageDescription:`open: capture the initial iOS simulator launch console window to a file`,projectConfig:!1,recorded:!1},{key:`launchArgs`,names:[`--launch-args`],type:`string`,multiple:!0,usageLabel:`--launch-args <arg>`,usageDescription:`open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag.`,projectConfig:!0,recorded:!1},{key:`header`,names:[`--header`],type:`string`,multiple:!0,usageLabel:`--header <name:value>`,usageDescription:`install-from-source: repeatable HTTP header for URL downloads`,projectConfig:!1,recorded:!1},{key:`githubActionsArtifact`,names:[`--github-actions-artifact`],type:`string`,usageLabel:`--github-actions-artifact <owner/repo:artifact>`,usageDescription:`install-from-source: GitHub Actions artifact resolved by a remote daemon`,projectConfig:!1,recorded:!1},{key:`installSource`,names:[],type:`string`,projectConfig:!1,recorded:!1},{key:`session`,names:[`--session`],type:`string`,usageLabel:`--session <name>`,usageDescription:`Named session (implicit default is scoped to this workspace + platform)`,projectConfig:!0,recorded:!1}],nn=[{key:`replayUpdate`,names:[`--update`,`-u`],type:`boolean`,usageLabel:`--update, -u`,usageDescription:`Replay: retired as a rewrite (ADR 0012) — never edits the .ad file; every divergence already carries ranked selector suggestions, --update or not`,projectConfig:!0,recorded:!1},{key:`replayFrom`,names:[`--from`],type:`int`,min:1,usageLabel:`--from <n>`,usageDescription:`Replay: resume at 1-based plan step n, skipping 1..n-1 without executing them (requires --plan-digest; see a divergence report's resume field). replay only, not test`,projectConfig:!0,recorded:!1},{key:`replayPlanDigest`,names:[`--plan-digest`],type:`string`,usageLabel:`--plan-digest <sha256>`,usageDescription:`Replay: the plan digest a --from resume must match (from a prior divergence report); mismatch, edits, or include/platform-expansion changes fail INVALID_ARGS before any action`,projectConfig:!0,recorded:!1},{key:`replayKeepSession`,names:[`--keep-session`],type:`boolean`,usageLabel:`--keep-session`,usageDescription:`Replay: leave the session active by suppressing exactly an authored terminal close in a native .ad script; replay only, not test or Maestro YAML`,projectConfig:!0,recorded:!1},{key:`replayMaestro`,names:[`--maestro`],type:`boolean`,usageLabel:`--maestro`,usageDescription:`Replay: treat input as a supported Maestro YAML subset; unsupported syntax fails loudly. See agent-device help maestro for commands and boundaries`,projectConfig:!0,recorded:!1},{key:`replayEnv`,names:[`-e`,`--env`],type:`string`,multiple:!0,usageLabel:`-e KEY=VALUE, --env KEY=VALUE`,usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)",projectConfig:!1,recorded:!1},{key:`failFast`,names:[`--fail-fast`],type:`boolean`,usageLabel:`--fail-fast`,usageDescription:`Test: stop the suite after the first failing script; with sharding, each shard stops independently`,projectConfig:!0,recorded:!1},{key:`timeoutMs`,names:[`--timeout`],type:`int`,min:1,usageLabel:`--timeout <ms>`,usageDescription:`Boot/Open/Prepare: startup budget covering the device boot (and runner preparation for prepare). Replay/Snapshot/Test: maximum wall-clock time for the command or attempt. With --settle: the settle-wait deadline (default 10s)`,projectConfig:!0,recorded:!1},{key:`waitMs`,names:[`--wait`],type:`int`,min:100,max:12e4,usageLabel:`--wait <ms>`,usageDescription:`Open: wait up to n ms for a device another session is holding before failing with DEVICE_IN_USE`,inputDescription:`Block this open for up to n milliseconds (100-120000) while another session holds the device, then fail with DEVICE_IN_USE naming that session. Only session contention is waited for: a device claim held by another workspace is refused at once with its recovery command. A device that never frees, or is taken again while this open waits, costs the full budget, which extends this command's timeout envelope rather than eating into it.`,projectConfig:!1,recorded:!1},{key:`retries`,names:[`--retries`],type:`int`,min:0,max:3,usageLabel:`--retries <n>`,usageDescription:`Test: retry each failed script up to n additional times`,projectConfig:!0,recorded:!1},{key:`recordVideo`,names:[`--record-video`],type:`boolean`,usageLabel:`--record-video`,usageDescription:`Test: record each replay attempt to recording.mp4 in its attempt artifacts`,projectConfig:!0,recorded:!1},{key:`artifactsDir`,names:[`--artifacts-dir`],type:`string`,usageLabel:`--artifacts-dir <path>`,usageDescription:`Test: root directory for suite artifacts`,projectConfig:!1,recorded:!1},{key:`reporter`,names:[`--reporter`],type:`string`,multiple:!0,usageLabel:`--reporter <name-or-path>`,usageDescription:`Test: add a replay suite reporter; use default, junit:<path>, or a custom reporter path (repeatable)`,projectConfig:!1,recorded:!1},{key:`reportJunit`,names:[`--report-junit`],type:`string`,usageLabel:`--report-junit <path>`,usageDescription:`Test: compatibility alias for --reporter junit:<path>`,projectConfig:!1,recorded:!1},{key:`shardAll`,names:[`--shard-all`],type:`int`,min:1,usageLabel:`--shard-all <n>`,usageDescription:`Test: run the full suite on each of n devices; combine with --device id1,id2 for explicit connected devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`shardSplit`,names:[`--shard-split`],type:`int`,min:1,usageLabel:`--shard-split <n>`,usageDescription:`Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`steps`,names:[`--steps`],type:`string`,usageLabel:`--steps <json>`,usageDescription:`Batch: JSON array of {"command","input"} steps`,projectConfig:!1,recorded:!1},{key:`stepsFile`,names:[`--steps-file`],type:`string`,usageLabel:`--steps-file <path>`,usageDescription:`Batch: read steps JSON from file`,projectConfig:!1,recorded:!1},{key:`batchOnError`,names:[`--on-error`],type:`enum`,enumValues:[`stop`],usageLabel:`--on-error stop`,usageDescription:`Batch: stop when a step fails`,projectConfig:!0,recorded:!1},{key:`batchMaxSteps`,names:[`--max-steps`],type:`int`,min:1,max:1e3,usageLabel:`--max-steps <n>`,usageDescription:`Batch: maximum number of allowed steps`,projectConfig:!0,recorded:!1},{key:`appsFilter`,names:[`--all`],type:`enum`,enumValues:[`user-installed`,`all`],setValue:`all`,usageLabel:`--all`,usageDescription:`Apps: include system/OEM apps`,projectConfig:!0,recorded:!1},{key:`snapshotInteractiveOnly`,names:[`-i`],type:`boolean`,usageLabel:`-i`,usageDescription:`Snapshot: interactive elements only`,projectConfig:!0,recorded:!0},{key:`snapshotDepth`,names:[`--depth`,`-d`],type:`int`,min:0,usageLabel:`--depth, -d <depth>`,usageDescription:`Snapshot: limit snapshot depth`,projectConfig:!0,recorded:!0},{key:`snapshotScope`,names:[`--scope`,`-s`],type:`string`,usageLabel:`--scope, -s <scope>`,usageDescription:`Snapshot: scope snapshot to label/identifier`,projectConfig:!0,recorded:!0},{key:`snapshotRaw`,names:[`--raw`],type:`boolean`,usageLabel:`--raw`,usageDescription:`Snapshot: raw node output`,projectConfig:!0,recorded:!0},{key:`snapshotCustomActions`,names:[`--actions`],type:`boolean`,usageLabel:`--actions`,usageDescription:`Snapshot: name the affordances merged inside an element (iOS sim); not directly invokable — reach them via the detail screen, labeled children, or coordinates`,inputDescription:`Name the affordances an element merged away (iOS UIAccessibilityCustomAction, React Native accessibilityActions) — a card whose reply/options controls are not separate elements still lists them here. The names are for PLANNING, not invocation: there is no API to trigger them, so reach the affordance through the element detail screen, through the same control exposed as a labeled element elsewhere, or by coordinates from its rect. iOS simulator only; costs one accessibility round trip per merged element.`,projectConfig:!0,recorded:!0},{key:`snapshotObserveOnly`,names:[`--observe-only`],type:`boolean`,usageLabel:`--observe-only`,usageDescription:`Snapshot: observe the iOS session app without activation or foreground repair`,inputDescription:`iOS only. Refuse instead of activating or repairing the session app. Reports XCUIApplication state, which does not prove screen ownership (#2696).`,projectConfig:!1,recorded:!1},{key:`snapshotForceFull`,names:[`--force-full`],type:`boolean`,usageLabel:`--force-full`,usageDescription:`Snapshot: re-emit the full tree even when unchanged`,projectConfig:!0,recorded:!1},{key:`findFirst`,names:[`--first`],type:`boolean`,usageLabel:`--first`,usageDescription:`Find: pick the first match when ambiguous`,projectConfig:!0,recorded:!1},{key:`findLast`,names:[`--last`],type:`boolean`,usageLabel:`--last`,usageDescription:`Find: pick the last match when ambiguous`,projectConfig:!0,recorded:!1},{key:`out`,names:[`--out`],type:`string`,usageLabel:`--out <path>`,usageDescription:`Output path`,projectConfig:!1,recorded:!0},{key:`artifact`,names:[`--artifact`],type:`string`,usageLabel:`--artifact <path>`,usageDescription:`Debug symbols: Apple crash artifact path (.ips, .crash, or .log)`,projectConfig:!1,recorded:!1},{key:`dsym`,names:[`--dsym`],type:`string`,usageLabel:`--dsym <path>`,usageDescription:`Debug symbols: matching .dSYM bundle path`,projectConfig:!1,recorded:!1},{key:`searchPath`,names:[`--search-path`],type:`string`,usageLabel:`--search-path <dir>`,usageDescription:`Debug symbols: directory to scan for matching .dSYM bundles`,projectConfig:!1,recorded:!1},{key:`overlayRefs`,names:[`--overlay-refs`],type:`boolean`,usageLabel:`--overlay-refs`,usageDescription:`Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide`,projectConfig:!0,recorded:!1},...d,{key:`baseline`,names:[`--baseline`,`-b`],type:`string`,usageLabel:`--baseline, -b <path>`,usageDescription:`Diff screenshot: path to baseline image file`,projectConfig:!0,recorded:!1},{key:`threshold`,names:[`--threshold`],type:`string`,usageLabel:`--threshold <0-1>`,usageDescription:`Diff screenshot: color distance threshold (default 0.1)`,projectConfig:!0,recorded:!1}],X=[...en,...tn,...$t,...nn],rn=new Map;for(let e of X)for(let t of e.names)rn.set(t,e);function an(e){return rn.get(e)}function on(){return X}function sn(e){return X.filter(t=>t.key===e)}function cn(){return new Set(X.filter(e=>e.projectConfig).map(e=>e.key))}function ln(){return new Set(X.filter(e=>e.recorded).map(e=>e.key))}function un(e){let t=Z(e.label),n=Z(e.value),r=Z(e.identifier),i=gn(r)?r:``;return hn(e.type??``)?n||t||i:t||n||i}function dn(e,t){if(t===`text-view`||t===`text-field`||t===`search`)return!0;let n=g(e.type??``),r=`${e.role??``} ${e.subrole??``}`.toLowerCase();return n.includes(`textview`)||n.includes(`textarea`)||n.includes(`textfield`)||n.includes(`securetextfield`)||n.includes(`searchfield`)||n.includes(`edittext`)||r.includes(`text area`)||r.includes(`text field`)}function fn(e){let t=e.replaceAll(/\s+/g,` `).trim();return t.length<=48?t:`${t.slice(0,45)}...`}function pn(e,t){let n=un(e),r=dn(e,t);return{text:n,isLargeSurface:r,shouldSummarize:r&&mn(n)}}function mn(e){return e?e.length>80||/[\r\n]/.test(e):!1}function Z(e){return typeof e==`string`?e.trim():``}function hn(e){let t=g(e);return t.includes(`textfield`)||t.includes(`securetextfield`)||t.includes(`searchfield`)||t.includes(`edittext`)||t.includes(`textview`)||t.includes(`textarea`)}function gn(e){return e?!/^[\w.]+:id\/[\w.-]+$/i.test(e)&&!/^_?NS:\d+$/i.test(e):!1}function _n(e,t={}){let r=[],i=[];for(let a of e){let e=a.depth??0,o=a.label?.trim()||a.value?.trim()||a.identifier?.trim()||``,s=n(a.type??`Element`),c=a.inheritsLabel===!0||a.inheritsIdentifier===!0;if(s===`group`&&!o&&!c)continue;for(;r.length>0&&e<=r.at(-1);)r.pop();let l=r.length;r.push(e),i.push({node:a,depth:l,type:s,text:Q(a,l,!1,s,t)})}return i}function Q(e,t,r,i,a={}){let o=i??n(e.type??`Element`),s=pn(e,o),c=Tn(e,o,a,s),l=` `.repeat(t),u=e.ref?`@${e.ref}`:``,d=En(e,o,a,s);!c&&(e.inheritsLabel===!0||e.inheritsIdentifier===!0)&&d.push(`same label as parent`);let f=d.map(e=>` [${e}]`).join(``),p=c?` "${c}"`:``,m=yn(e);return r?`${l}${u} [${o}]${f}${m}`.trimEnd():`${l}${u} [${o}]${p}${f}${m}`.trimEnd()}function vn(e){return{matches:e.length,candidates:e.slice(0,5).map(e=>Q(e,0,!1))}}function yn(e){let t=e.actions?.filter(e=>e.trim().length>0);return!t||t.length===0?``:` actions: [${t.map(e=>`"${kn(bn(e))}"`).join(`, `)}]`}function bn(e){return e.replaceAll(/\s+/g,` `).replaceAll(/[\u0000-\u001f\u007f-\u009f]/g,``).trim()}function $(e,t){let n=e.label?.trim();if(n&&Cn(t,n))return``;let r=e.value?.trim();if(Sn(t)){if(r)return r;if(n)return n}else if(n)return n;if(r)return r;let i=e.identifier?.trim();return!i||wn(i)&&(t===`group`||t===`image`||t===`list`||t===`collection`)?``:i}function xn(e){let t=[];return e.enabled===!1&&t.push(`disabled`),e.selected===!0&&t.push(`selected`),e.checked!==void 0&&t.push(e.checked?`checked`:`unchecked`),t}function Sn(e){return e===`text-field`||e===`text-view`||e===`search`}function Cn(e,t){return e!==`scroll-area`&&e!==`list`&&e!==`collection`&&e!==`table`?!1:f(t)}function wn(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function Tn(e,t,n,r){return!n.summarizeTextSurfaces||!r.shouldSummarize?$(e,t):Dn(e,t,r.text)||$(e,t)}function En(e,t,n,r){let i=[...xn(e),...e.presentationHints??[]];return!n.summarizeTextSurfaces||(e.focused===!0&&i.push(`focused`),Sn(t)&&i.push(`editable`),On(e,t)&&i.push(`scrollable`),!r.shouldSummarize)?An(i):(i.push(`preview:"${kn(fn(r.text))}"`),i.push(`truncated`),An(i))}function Dn(e,t,n){let r=Z(e.label);if(r&&r!==n)return r;let i=Z(e.identifier);if(i&&!wn(i)&&i!==n)return i;switch(t){case`text`:case`text-view`:return`Text view`;case`text-field`:return`Text field`;case`search`:return`Search field`;default:return``}}function On(e,t){if(t===`scroll-area`)return!0;let n=(e.type??``).toLowerCase(),r=`${e.role??``} ${e.subrole??``}`.toLowerCase();return n.includes(`scroll`)||r.includes(`scroll`)}function kn(e){return e.replaceAll(`\\`,String.raw`\\`).replaceAll(`"`,String.raw`\"`)}function An(e){return[...new Set(e)]}const jn={state:`sparse`,backend:`tree`,reason:`legacy iOS capture exposed only the application root`,reasonCode:`sparse-tree`},Mn={sparse:`capture was sparse`,truncated:`capture was truncated`,unsettled:`the surface was still changing after a gesture`};function Nn(e){return typeof e==`string`&&Object.hasOwn(Mn,e)}function Pn(e){if(e.scope!==void 0)return`scope`;if(e.depth!==void 0)return`depth`}function Fn(e,t=`is`){let n=`${t} absent`;return e===`scope`?`${n} does not support --scope; it requires an unscoped capture`:`${n} does not support --depth; it requires a full-depth capture`}function In(e,t){let n=t[0]?zn(t[0]):void 0,r=t.length;if(e.truncated===!0)return{kind:`truncated`,matches:r,...n?{firstMatch:n}:{}};let i=Ln(e);return i?{kind:`sparse`,matches:r,...n?{firstMatch:n}:{},quality:{state:i.state,backend:i.backend,...i.reason?{reason:i.reason}:{},...i.reasonCode?{reasonCode:i.reasonCode}:{}}}:r===0?{kind:e.postGestureOutcome?.kind===`unsettled`?`unsettled`:`absent`,matches:0}:{kind:`present`,matches:r,firstMatch:n}}function Ln(e){let t=e.snapshotQuality;return t?.state===`sparse`?{state:t.state,backend:t.backend,...t.reason?{reason:t.reason}:{},...t.reasonCode?{reasonCode:t.reasonCode}:{}}:Rn(e)?jn:void 0}function Rn(e){return e.snapshotQuality||e.backend!==`xctest`||e.nodes.length!==1?!1:g(e.nodes[0]?.type??``)===`application`}function zn(e){let t=re(e),n=ie(ee(e),256);return{...t,...n&&n!==t.label?{text:n}:{}}}const Bn=[`primary`,`secondary`,`middle`];function Vn(e){return e?.clickButton??`primary`}function Hn(e){return e.button===`primary`?null:e.commandLabel===`click`?e.platform!==`macos`&&e.platform!==`linux`?new t(`UNSUPPORTED_OPERATION`,`click --button ${e.button} is supported only on macOS and Linux`):e.platform===`macos`&&e.button===`middle`?new t(`UNSUPPORTED_OPERATION`,`click --button middle is not supported by the macOS runner yet`):typeof e.count==`number`||typeof e.intervalMs==`number`||typeof e.holdMs==`number`||typeof e.jitterPx==`number`||e.doubleTap===!0?new t(`INVALID_ARGS`,`click --button ${e.button} does not support repeat or gesture modifier flags`):null:new t(`INVALID_ARGS`,`--button is supported only for click`)}function Un(e){return e===`primary`?{}:{button:e}}const Wn=[`in-app`,`system`];export{O as $,Gt as A,lt as B,cn as C,Qt as D,qt as E,Tt as F,st as G,dt as H,Et as I,F as J,L as K,gt as L,Kt as M,Wt as N,Zt as O,St as P,We as Q,ht as R,sn as S,Jt as T,H as U,ft as V,ut as W,M as X,it as Y,ze as Z,xn as _,xe as _t,Vn as a,x as at,an as b,pe as bt,Pn as c,ke as ct,Nn as d,he as dt,Ge as et,Ln as f,ye as ft,Q as g,Se as gt,vn as h,be as ht,Hn as i,b as it,Ut as j,Ht as k,In as l,v as lt,$ as m,Te as mt,Bn as n,Ye as nt,Mn as o,De as ot,_n as p,ve as pt,R as q,Un as r,Ke as rt,Fn as s,Ee as st,Wn as t,Je as tt,Rn as u,ge as ut,un as v,_e as vt,ln as w,on as x,hn as y,we as yt,pt as z};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{I as e}from"./sdk-contracts.js";function t(t){let n=t.error?e(t.error):null,r=t.context?.platform,i=t.context?.phase;if(n?.code===`TOOL_MISSING`)return r===`android`?`ADB_TRANSPORT_UNAVAILABLE`:`IOS_TOOL_MISSING`;let a=n?.details??{},o=typeof a.message==`string`?a.message:void 0,s=typeof a.stdout==`string`?a.stdout:void 0,c=typeof a.stderr==`string`?a.stderr:void 0,l=a.boot&&typeof a.boot==`object`?a.boot:null,u=a.bootstatus&&typeof a.bootstatus==`object`?a.bootstatus:null,d=[t.message,n?.message,t.stdout,t.stderr,o,s,c,typeof l?.stdout==`string`?l.stdout:void 0,typeof l?.stderr==`string`?l.stderr:void 0,typeof u?.stdout==`string`?u.stdout:void 0,typeof u?.stderr==`string`?u.stderr:void 0].filter(Boolean).join(`
|
|
2
2
|
`).toLowerCase();return r===`ios`&&d.includes(`0xe8008012`)?`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:r===`ios`&&(d.includes(`provisioning profile`)||d.includes(`embedded profile`))?`BOOT_COMMAND_FAILED`:r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:n?.code===`COMMAND_FAILED`||d.length>0?`BOOT_COMMAND_FAILED`:`UNKNOWN`}function n(e){switch(e){case`IOS_BOOT_TIMEOUT`:return`Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.`;case`IOS_RUNNER_CONNECT_TIMEOUT`:return`Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.`;case`IOS_RUNNER_OWNED_BY_OTHER_DAEMON`:return`Close the owning agent-device session or stop its daemon with retained-runner cleanup before retrying.`;case`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:return`The XCTest runner cannot be installed on this device: its provisioning profile does not cover it. Register the device with the signing team (Xcode > Settings > Accounts, or add its UDID to the provisioning profile) and retry. Retrying without that will keep failing.`;case`ANDROID_BOOT_TIMEOUT`:return`Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.`;case`ADB_TRANSPORT_UNAVAILABLE`:return`Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.`;case`CI_RESOURCE_STARVATION_SUSPECTED`:return`CI machine may be resource constrained; reduce parallel jobs or use a larger runner.`;case`IOS_TOOL_MISSING`:return`Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.`;case`BOOT_COMMAND_FAILED`:return`Inspect command stderr/stdout for the failing boot phase and retry after environment validation.`;default:return`Retry once and inspect verbose logs for the failing phase.`}}export{t as n,n as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as e,f as t,y as n}from"./
|
|
1
|
+
import{d as e,f as t,y as n}from"./runtime.js";import{a as r,i,o as a,s as o}from"./provider-webdriver.js";import{l as s}from"./store.js";import{i as c,n as l,r as u}from"./provider-profile-fields.js";import{n as d}from"./connection-verification.js";const f=s.browserStack,p=`BrowserStack`,m=`connect ${f}`;function h(n){return{resolve:({flags:a,cwd:s})=>{l(a,r),o(n.env,m);let c=t(a,f),u=e(a.device,f,`--device <name>`),d=e(a.providerOsVersion,f,`--provider-os-version <version>`),p=g(e(a.providerApp,f,`--provider-app <bs://app-id-or-local-path>`),s);return{profile:{leaseProvider:f,platform:c,device:u,providerOsVersion:d,providerApp:p,providerProject:a.providerProject,providerBuild:a.providerBuild,providerSessionName:a.providerSessionName,...i(a)},extraFlags:{providerApp:p}}},verify:async({flags:e})=>await d({...o(n.env,m),platform:u(e.platform,p),deviceName:c(e.device,`BrowserStack profile missed device.`),osVersion:c(e.providerOsVersion,`BrowserStack profile missed OS version.`),app:c(e.providerApp,`BrowserStack profile missed app.`)},n.clientVersion)}}function g(e,t){return/^https?:\/\//i.test(e)?e:a(e)??n(e,t,p)}export{h as createBrowserStackConnection};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{_ as t}from"./selector-pipeline-policy.js";import{n}from"./ios-system-surface.js";import{t as r}from"./ios-target-activation.js";import{t as i}from"./command-policy.js";import{n as a}from"./android-system-surface-disclosure.js";function o(t,n={}){let r=n.plural===!0?`do`:`does`;return{resolveInput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} ${r} not create temporary files`)}}}function s(e,t={}){return{artifacts:o(e,t),policy:i()}}function c(e,t){return e===void 0?t:(e.targetActivation??=t.targetActivation,e.postGestureOutcome??=t.postGestureOutcome,t)}function l(e,t){let r=t?.iosSystemSurfaceBundleId?n(t.iosSystemSurfaceBundleId):a(t);return r?p(e,r,`warning`):e}function u(e,t,n,r){if(!n)return e;let i=p(e,r(n),`warnings`);return i.ok?{...i,data:{...i.data,[t]:n}}:{...i,error:{...i.error,details:{...i.error.details,[t]:n}}}}function d(e,t){return u(e,`targetActivation`,t?.targetActivation,r)}function f(e){let{response:n,consumedTree:r,captureProof:i}=e;return d(u(l(n,r),`postGestureOutcome`,r?.postGestureOutcome,t),i)}function p(e,t,n){if(m(e,t))return e;if(!e.ok){let n=e.error.hint??e.error.details?.hint;return{...e,error:{...e.error,hint:h(n,t)}}}return n===`warnings`?{...e,data:{...e.data,warnings:[...g(e.data?.warnings),t]}}:{...e,data:{...e.data,warning:h(e.data?.warning,t)}}}function m(e,t){return(e.ok?[e.data?.warning,...g(e.data?.warnings)]:[e.error.hint]).some(e=>typeof e==`string`&&e.includes(t))}function h(e,t){return typeof e==`string`&&e.trim()!==``?`${e}\n${t}`:t}function g(e){return Array.isArray(e)?e.filter(e=>e!==void 0):[]}export{s as i,f as n,d as r,c as t};
|
package/dist/src/cli-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{P as e}from"./sdk-contracts.js";import{t}from"./
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{lt as t}from"./tv-remote.js";import{v as n}from"./sdk-batch-runner.js";import{C as r,O as i,x as a}from"./back-mode.js";import{a as o,s}from"./sdk-remote-config.js";import{k as c,v as l}from"./command-metadata.js";import{I as u,L as d}from"./file.js";import{n as f}from"./command-schema.js";import p from"node:fs";import m from"node:path";const h=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`,`textStdin`]),g=new Set([`appsFilter`,`iosSimulatorDeviceSet`,`textStdin`]),_=C(),v=new Map(_.map(e=>[e.key,e]));function y(e){return v.get(e)}function b(e){return _.filter(t=>t.configurable&&t.supportsCommand(e))}function x(e,t){return y(e)?.supportsCommand(t)??!1}function S(e,t,n,r){return s(E(e),t,n,r)}function C(){let e=new Map;for(let t of a()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of c)t.set(e,new Set([`*`]));for(let e of i()){let n=f(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!h.has(e),env:{names:g.has(e)?[]:[o(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>w(e.key,t.key))}function w(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function T(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function E(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=T(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}function D(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}function O(e){let t=e.env??process.env;return D(D({},M(A(e.cwd,e.cliFlags.config,t))),I(t,e.command))}const k=r();function A(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:j(r,e,n),required:!0,source:`explicit`}]:[{path:u(n),required:!1,source:`user`},{path:m.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function j(e,t,n){return d(e,{cwd:t,env:n})}function M(e){let t={};for(let n of e)D(t,N(n));return t}function N(t){let{path:r,required:i}=t;if(!p.existsSync(r)){if(i)throw new e(`INVALID_ARGS`,`Config file not found: ${r}`);return{}}let a;try{a=p.readFileSync(r,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${r}`,{cause:t instanceof Error?t.message:String(t)})}let o;try{o=JSON.parse(a)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${r}`,{cause:t instanceof Error?t.message:String(t)})}if(!n(o))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${r}`);return P(o,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${r}`})}function P(n,r){let i={},a=Object.entries(n).filter(([e])=>e!==`plugins`||r.source!==`user`);for(let[n,o]of a){let a=n,s=y(a);if(!s)throw n===t.flagKey?new e(`INVALID_ARGS`,`Config key "${n}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${n}" in ${r.label}.`);if(!s.configurable)throw new e(`INVALID_ARGS`,`Config key "${n}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!k.has(a))throw new e(`INVALID_ARGS`,`Config key "${n}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(a===`installSource`){i.installSource=l(o,r.label);continue}i[a]=S(s,o,r.label,n)}return i}const F=new Set([`screenshot`,`record`]);function I(n,r){let i=n[t.envVar];if(r!==null&&F.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of b(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=S(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{D as n,x as r,O as t};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
2
|
-
`)}function h(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function g(e){return
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{O as t,x as n}from"./back-mode.js";import{_r as r}from"./sdk-batch.js";import{O as i,V as a,f as o,k as s}from"./command-metadata.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 n().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.
|
|
@@ -172,7 +172,7 @@ Stabilizers:
|
|
|
172
172
|
Text-entry quirks:
|
|
173
173
|
iOS Allow Paste cannot be exercised under XCUITest; prefill with clipboard write "some text" instead and test the system prompt manually.
|
|
174
174
|
Android Gboard handwriting/stylus UI can capture text in an IME-owned input instead of the app field. If fill reports that input was captured by the keyboard/IME, use the diagnostic targetInput/actualInput details, inspect keyboard status/get if needed, and switch or disable handwriting outside the command plan before retrying. Do not keep retrying fill/type against the same field while the IME owns focus. If the exact target changes but app-owned formatting prevents raw equality, fill succeeds with verification: "unconfirmed" plus target-bound requested/before/after evidence; inspect that evidence instead of retrying the same mutation.
|
|
175
|
-
iOS accessibility-driven fill
|
|
175
|
+
iOS accessibility-driven fill types the replacement once and never clears and retypes a read-back mismatch. Exact settled text confirms the entry. A value containing only characters in order from the post-clear value plus the request fails with TEXT_ENTRY_MISMATCH, including plain dropped characters and unchanged values; legitimate trimming or masks can also hit this limit ("5" into "$0.00" displaying "$0.05"). Other settled values return verification: "unconfirmed" with requested/before/after/target evidence, including grouping ("00 062 91 77" for "000629177"), currency ("$10.00" for "1000"), and OTP summaries. Missing, reordered, duplicated or stale text can also be unconfirmed, so assert the expected value with a value selector, get/is, or the resulting screen before continuing. For single-line fills ending in a submit key, any non-matching value observed on the same target succeeds unverified, including partial or cleared text; this exception skips dropped-character checks because the submit may change the field. Assert the resulting screen. Multiline fields compare newlines as content. Unreadable or removed fields remain unverified. The coordinate-driven fill route still requires an exact match. Only retry fill with --delay-ms 80 after TEXT_ENTRY_MISMATCH and inspection shows the field needs correction.
|
|
176
176
|
|
|
177
177
|
React Native internals:
|
|
178
178
|
If the question is about React Native performance, profiling, props, state, hooks, render causes, slow components, or rerenders, use help react-devtools instead of inferring from screenshots or logs.`}},C={dogfood:{summary:`Exploratory QA workflow with reproducible evidence`,body:`agent-device help dogfood
|
|
@@ -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 ${
|
|
274
|
+
All ${t().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: ${
|
|
297
|
+
Prefer refs, then id/label/role selectors. Selector keys: ${r.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.
|
|
@@ -420,6 +420,9 @@ Reusable open-to-destination scripts:
|
|
|
420
420
|
export AD_VAR_PASSWORD='<secret>'
|
|
421
421
|
agent-device fill 'id="password"' "$AD_VAR_PASSWORD" --record-as PASSWORD
|
|
422
422
|
The live app receives the value; recording state and the published script contain only \${PASSWORD}. Reuse the same name for repeated values; --record-as is fill-only, requires an armed recording, and is mutually exclusive with --no-record. Replay with AD_VAR_PASSWORD still set, or pass --env PASSWORD=<value>. Do not record passwords/tokens without --record-as; their literal text is written to the .ad target.
|
|
423
|
+
To keep the value out of the CLI's argv as well, pipe it in with --text-stdin instead of a text argument:
|
|
424
|
+
printf %s "$AD_VAR_PASSWORD" | agent-device fill 'id="password"' --text-stdin --record-as PASSWORD
|
|
425
|
+
--text-stdin reads at most 64 KiB, removes exactly one trailing newline, and refuses a terminal, empty input, invalid UTF-8, or an extra text argument. While recording is armed, --record-as publishes \${VAR} and --no-record leaves the step out; passing neither is an error. Without an armed recording the step is not recorded. It is not available inside batch steps.
|
|
423
426
|
|
|
424
427
|
Replay divergence and repair:
|
|
425
428
|
A failing replay/test step returns REPLAY_DIVERGENCE with a bounded report (screen digest, ranked selector suggestions, resume). Fix app state, then resume with replay --from <n> --plan-digest <sha256> (both from the report's resume field) to continue without re-running earlier steps; resume never re-executes skipped steps, so app state there is the caller's responsibility. --from is replay-only; test rejects it. The digest binds the script, includes, effective --platform/--target, and per-action runtime/identity; native .ad interpolation is late-bound so changing only its values keeps the digest, while Maestro environment substitution can change it.
|
|
@@ -662,7 +665,7 @@ React Native dev loop:
|
|
|
662
665
|
Multiple local worktrees can reuse one native iOS simulator build by running each worktree's dev server on a different port and opening the same installed app on different simulators with explicit runtime hints:
|
|
663
666
|
agent-device open "React Navigation Example" --platform ios --device "iPhone 17" --session rn-a --metro-host 127.0.0.1 --metro-port 8081 --relaunch
|
|
664
667
|
agent-device open "React Navigation Example" --platform ios --device "iPhone 17 Pro" --session rn-b --metro-host 127.0.0.1 --metro-port 8082 --relaunch
|
|
665
|
-
iOS simulator opens write React Native's per-simulator debug server settings before launch
|
|
668
|
+
iOS simulator opens write bare React Native's per-simulator debug server settings before launch. Detected Expo development clients receive their server URL through a launch link instead. Use separate sessions/devices, close both sessions when done, and rebuild only for native changes or dependency changes that affect the binary. One simulator cannot run two copies of the same bundle id.
|
|
666
669
|
Expo Go/dev clients are host shells. Use provided project URLs, verify with snapshot -i after opening, and ask instead of inventing app ids or URLs. Help workflow owns the full Expo URL command shapes.
|
|
667
670
|
|
|
668
671
|
Overlays and busy RN UIs:
|
|
@@ -747,7 +750,7 @@ Android physical-device prerequisites:
|
|
|
747
750
|
Runner and daemon lifecycle (applies to simulators too):
|
|
748
751
|
open without --relaunch is idempotent-foreground for an already-running app (it brings the process forward; it does not restart it). open --relaunch restarts the app; on iOS simulators this collapses to one simctl launch --terminate-running-process call instead of a separate terminate-then-launch.
|
|
749
752
|
No runner read launches a session app that is not running: snapshot, wait, is, get, a reading find, and an interaction's leading reads (a gesture's viewport read, the capture that resolves a selector click/fill) answer the retriable APP_NOT_RUNNING instead of bare-launching over a launch SpringBoard still holds behind its deep-link confirmation. Only open, activate, and a command that mutates without a leading read bring a stopped app up.
|
|
750
|
-
close keeps a healthy iOS simulator XCTest runner warm by default so the next open on that simulator (same udid in the same simulator set) skips the runner build, unless --shutdown was requested, the session was recording, or the session held a device lease. A retained runner auto-stops after an idle window (default 5 minutes); set AGENT_DEVICE_IOS_RUNNER_IDLE_STOP_MS to override, or 0 to disable idle stop and retain until daemon exit.
|
|
753
|
+
close keeps a healthy iOS simulator XCTest runner warm by default so the next open on that simulator (same udid in the same simulator set) skips the runner build, unless --shutdown was requested, the session was recording, or the session held a device lease. A retained runner auto-stops after an idle window (default 5 minutes); set AGENT_DEVICE_IOS_RUNNER_IDLE_STOP_MS to override, or 0 to disable idle stop and retain until daemon exit. Only a ready runner with an observed listener is retained; close retires unfinished prewarm recovery. Losing the retained listener stops that generation, and daemon shutdown stops idle retained runners rather than handing them off without supervision.
|
|
751
754
|
Each AGENT_DEVICE_STATE_DIR runs its own daemon. It self-exits after an idle window (default 5 minutes, matching the runner idle-stop default) once it has no open sessions, no in-flight requests, and no active recording; set AGENT_DEVICE_DAEMON_IDLE_TIMEOUT_MS to override, or 0 to disable idle reap.
|
|
752
755
|
On a machine shared by several agents, set AGENT_DEVICE_SESSION_IDLE_TIMEOUT_MS to also expire an individual session that has taken a host-global device claim and then received no commands for that long; the claim is released and the next command on that session answers SESSION_NOT_FOUND with details.reason SESSION_IDLE_EXPIRED naming the window and the device. Off by default, because on a shared host "idle" and "thinking" are indistinguishable: only set it where an abandoned claim blocking every other agent is the worse failure. Sessions holding a remote lease or any active capture (recording, logs, audio, performance, or trace) are never expired this way.
|
|
753
756
|
A stale iOS runner lease — its owner process dead, or its AGENT_DEVICE_STATE_DIR deleted — is reclaimed automatically instead of failing with "is already owned by another agent-device daemon". A live owner's runner is also reclaimed when the requesting daemon holds the host-global device claim for that device: claims are exclusive, so holding one proves the runner's owner released the device and merely kept the runner warm. The error remains only for owners outside claim arbitration (a pre-claims build, or daemons pointed at different claim stores).
|
|
@@ -778,7 +781,7 @@ Rules:
|
|
|
778
781
|
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
782
|
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
783
|
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:
|
|
784
|
+
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
|
|
782
785
|
|
|
783
786
|
Remote connection providers use the same lifecycle:
|
|
784
787
|
connect -> install/open -> commands -> close -> disconnect
|
|
@@ -995,25 +998,25 @@ Rules:
|
|
|
995
998
|
|
|
996
999
|
Full command catalog. Use agent-device help <command> for exact flags and behavior.
|
|
997
1000
|
|
|
998
|
-
${B(
|
|
1001
|
+
${B(t().map(e=>{let t=l(e);return{name:e,schema:t,usage:j(e,t)}}))}
|
|
999
1002
|
|
|
1000
1003
|
${L(`Device Selection (shared by device commands; help <command> lists each command's flags):`,F(i))}
|
|
1001
1004
|
|
|
1002
|
-
${L(`Global Flags:`,F(
|
|
1005
|
+
${L(`Global Flags:`,F(s))}
|
|
1003
1006
|
|
|
1004
1007
|
${z(`Configuration:`,E)}
|
|
1005
1008
|
|
|
1006
1009
|
${R(`Environment:`,D)}
|
|
1007
1010
|
|
|
1008
1011
|
${z(`Examples:`,O)}
|
|
1009
|
-
`}function P(){return M()}function F(e){return
|
|
1012
|
+
`}function P(){return M()}function F(e){return n().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(`
|
|
1010
1013
|
`)}function z(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
|
|
1011
|
-
`)}function B(e){return R(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function V(e){let
|
|
1014
|
+
`)}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(`
|
|
1012
1015
|
|
|
1013
1016
|
`)}`:``;return`Usage:
|
|
1014
|
-
agent-device ${
|
|
1017
|
+
agent-device ${r}
|
|
1015
1018
|
|
|
1016
|
-
${
|
|
1019
|
+
${a(n.text)}${s}
|
|
1017
1020
|
`}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)}
|
|
1018
1021
|
|
|
1019
1022
|
Related:
|
package/dist/src/cli-output.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{N as e,a as t,u as n}from"./command-metadata.js";const r=t(),i=new Set(n().filter(e=>e.parseableOutput===!0).map(e=>e.name));async function a(t){let n=await r[t.name]?.({input:t.input??{},result:t.result,progress:t.progress});if(n!==void 0)return e(n,t.result,i.has(t.name)?`stderr`:`text`)}function o(e){return i.has(e)}export{o as n,a as t};
|
package/dist/src/cli-runner.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{o as t}from"./diagnostics.js";import"./diagnostics2.js";import{C as n,o as r}from"./command-metadata.js";import{t as i}from"./cli-output.js";import{n as a}from"./command-surface.js";const o=65536;async function s(t){if(t.isTTY)throw new e(`INVALID_ARGS`,`fill --text-stdin reads piped input, but stdin is a terminal.`,{reason:`fill_text_stdin_tty`,hint:`Pipe the text in, for example: printf %s "$PASSWORD" | agent-device fill @e3 --text-stdin`});let n=[],r=0,i=``;for await(let a of t){let t=u(i,a);if(i=t.held,r+=d(t.piece),r>65536)throw new e(`INVALID_ARGS`,`fill --text-stdin accepts at most ${o} bytes of input.`,{reason:`fill_text_stdin_too_large`,maxBytes:o});n.push(f(t.piece))}if(i)throw m();let a=h(p(Buffer.concat(n)));if(a===``)throw new e(`INVALID_ARGS`,`fill --text-stdin received no text.`,{reason:`fill_text_stdin_empty`,hint:`Check that the piped value is set. To clear a field, pass an empty text argument instead: fill @e3 ""`});return a}const c=/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/,l=/[\uD800-\uDBFF]$/;function u(e,t){if(typeof t!=`string`){if(e)throw m();return{piece:t,held:``}}let n=e+t;return l.test(n)?{piece:n.slice(0,-1),held:n.slice(-1)}:{piece:n,held:``}}function d(e){return typeof e==`string`?Buffer.byteLength(e,`utf8`):e.byteLength}function f(e){if(typeof e!=`string`)return e;if(c.test(e))throw m();return Buffer.from(e,`utf8`)}function p(e){try{return new TextDecoder(`utf-8`,{fatal:!0,ignoreBOM:!0}).decode(e)}catch{throw m()}}function m(){return new e(`INVALID_ARGS`,`fill --text-stdin input is not valid UTF-8.`,{reason:`fill_text_stdin_invalid_utf8`})}function h(e){return e.endsWith(`\r
|
|
2
|
+
`)?e.slice(0,-2):e.endsWith(`
|
|
3
|
+
`)?e.slice(0,-1):e}const g=r();function _(e,t,r){let i=g[e];if(!i)throw Error(`Missing CLI reader for command: ${e}`);return{...i(t,r),...n(e,r)}}async function v(e){return(await y(e)).result}async function y(e){let n=_(e.command,e.positionals,e.flags);if(e.flags.textStdin){let e=await s(process.stdin);t(e),n.text=e}let r=await a(e.client,e.command,n);return{result:r,cliOutput:await i({name:e.command,input:n,result:r,progress:e.commandProgress})}}export{y as n,v as t};
|