agent-device 0.21.14 → 0.21.16
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.14.apk → agent-device-android-ime-helper-0.21.16.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.16.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.14.manifest.json → agent-device-android-ime-helper-0.21.16.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.16.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.16.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.14.manifest.json → agent-device-android-snapshot-helper-0.21.16.manifest.json} +6 -6
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +84 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerMainOwnedState.swift +27 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +10 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +21 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +40 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +179 -91
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -49
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +11 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +136 -29
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +4 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +6 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +8 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +56 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +18 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +9 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +5 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +2 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +245 -41
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +47 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +7 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +115 -111
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +17 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +8 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +12 -11
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +7 -4
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +15 -8
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +1 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +26 -9
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -0
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +1 -1
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.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/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.d.ts +1 -8
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android-snapshot-quality.js +1 -0
- package/dist/src/android-system-chrome.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-runtime2.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/capture-disclosure.js +1 -1
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +3 -2
- package/dist/src/cli.js +4 -4
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +103 -96
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +3 -3
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lease-beat.js +1 -0
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-transport.js +1 -0
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +15 -2
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.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/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/format.js +1 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan-types.d.ts +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/helper.js +2 -2
- package/dist/src/host.js +1 -1
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact-facade.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -1
- package/dist/src/interactor.js +5 -4
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-engine.js +1 -0
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-download-file.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +16 -3
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +17 -17
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/native-build-cache.js +1 -1
- package/dist/src/observation.js +1 -1
- package/dist/src/overlay.js +3 -0
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/perf.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-managed-owner.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 +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-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/png-crop-bytes.js +1 -1
- package/dist/src/png-size.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/provider-session-ownership.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +36 -36
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +1 -1
- package/dist/src/reporting.js +1 -1
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.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-artifact-manifest.js +1 -0
- package/dist/src/runner-cache-metadata.js +3 -2
- 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-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +3 -3
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +1 -3
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- 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/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.d.ts +13 -6
- package/dist/src/scroll-command.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +38 -10
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +4 -4
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -1
- package/dist/src/snapshot-desktop-projection.js +1 -1
- 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/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src4.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/stop-sequence.js +1 -1
- package/dist/src/string-enum.js +1 -1
- package/dist/src/surface-snapshot.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/transport.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/verified-file.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.14.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk.sha256 +0 -1
- package/dist/src/absence-observation-errors.js +0 -1
- package/dist/src/runner-presentation.js +0 -1
- package/dist/src/semantic-index.js +0 -1
- package/dist/src/snapshot-scope.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{B as e,O as t,R as n,V as r,r as i}from"./sdk-contracts.js";import{_ as a,h as o}from"./sdk-batch-runner.js";import{i as s,t as c}from"./sdk-device.js";import{S as l,c as u,d,p as f,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{D as p,O as re,S as m,T as ie,_ as h,b as g,g as _,s as ae,v,w as oe,x as y,y as b}from"./registry.js";import{n as se}from"./success-text.js";import{t as ce}from"./output-common.js";import"./device.js";import{r as le,t as ue}from"./device-rotation.js";import{t as de}from"./tv-remote.js";import{i as fe,n as x,r as pe,t as S}from"./command-metadata.js";import{r as me}from"./replay-divergence.js";import{n as he,t as ge}from"./cli-output.js";import{r as _e,t as ve}from"./recording-stop-observation.js";import{t as ye}from"./fold-runtime.js";import{n as be}from"./error.js";import{n as xe,r as Se,t as Ce}from"./cli-config.js";import{n as we}from"./result-serialization.js";const C=[`simulator`,`emulator`,`device`];function w(e){return{type:`string`,const:e}}function T(e){return{type:[`string`,`null`],...e?{description:e}:{}}}const E=g({wallClockMs:b(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:b(`Number of real runner round-trips made while serving the request.`),nodeCount:b(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),D=g({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return g({targetKind:h([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:b(`Resolved interaction x coordinate when available.`),y:b(`Resolved interaction y coordinate when available.`),referenceWidth:b(`Reference frame width for visualizing the interaction point.`),referenceHeight:b(`Reference frame height for visualizing the interaction point.`),ref:m(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:m(`Selector expression when the target was a selector.`),selectorChain:y(),refLabel:m(),targetHittable:_(),hint:m(),warning:m(),message:m(),evidence:j,resolution:Te,cost:E,maestroNonHittableCoordinateFallbackAllowed:_(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:_(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:w(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=g({diagnosticRef:m(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:m(`UTF-8 truncated to 256 bytes.`),label:m(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),Te={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[g({source:w(`runtime`),phase:w(`pre-action`),kind:w(`unique`)},[`source`,`phase`,`kind`]),g({source:w(`runtime`),phase:w(`pre-action`),kind:w(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:h([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:k}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),g({source:w(`ref`),phase:w(`pre-action`),kind:w(`exact`)},[`source`,`phase`,`kind`]),g({source:w(`ref`),phase:w(`pre-action`),kind:w(`label-fallback`)},[`source`,`phase`,`kind`]),g({source:w(`direct-ios`),kind:w(`not-observed`)},[`source`,`kind`])]},A=g({from:m(`Surface the pre-action baseline described: a host bundle id, or app.`),to:m(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:m(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),j=g({foregroundApp:m(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:b(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:b(`Subset of nodeCount the platform reports as hittable.`),digest:m(`Order-independent digest of the post-action node multiset.`),changedFromBefore:_(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:A},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),Ee=g({settled:_(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:g({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:A,diff:g({summary:g({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:g({kind:h([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:_(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:g({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:_(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),M={platform:h(s),target:h(c),device:m(`Human-readable device name.`),id:m(`Stable device id.`),kind:h(C)},N=[`platform`,`target`,`device`,`id`,`kind`],De=g({success:_(),exitCode:b(),stdout:m(),stderr:m(),error:v(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function P(e){return e.oneOf?{...e,oneOf:e.oneOf.map(P)}:{...e,properties:{...e.properties??{},settle:Ee}}}function Oe(e){let t={...e};for(let e of Object.keys(t))f(e)&&(t[e]=P(t[e]));return t}const F=O({properties:{evidence:j,button:h([`secondary`,`middle`]),count:b(`Number of press/click repetitions.`),intervalMs:b(`Delay between repeated press/click actions.`),holdMs:b(`Hold duration for each action.`),jitterPx:b(`Randomization radius in pixels.`),doubleTap:_(`Whether the command requested a double-tap action.`)}}),I={text:m(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:j},ke=g({resourceId:T(`Android resource id of the exact field that changed.`),className:T(`Android class name of the exact field that changed.`),packageName:T(`Android package name that owns the exact field.`),rect:g({x:b(),y:b(),width:b(),height:b()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),Ae=Oe({press:F,click:F,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...O({properties:I,required:[`text`]}),not:g({},[`verification`])},O({properties:{...I,verification:w(`unconfirmed`),requested:m(`Literal text requested by the fill command.`),before:T(`Raw target text captured before the fill.`),after:T(`Raw target text captured after the fill.`),target:ke},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:w(`longpress`)}}),hover:O({properties:{gesture:w(`hover`)}}),find:g({ref:m(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:_(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:m(`Text value returned by find get_text.`),node:v(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:v(`One listed match with its snapshot ref and node.`)},locator:m(`Locator kind used for the find action.`),query:m(`Query argument used for the find action.`),x:b(`Resolved x coordinate for mutating find actions.`),y:b(`Resolved y coordinate for mutating find actions.`),message:m(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:g({...M,booted:{type:`boolean`,const:!0}},[...N,`booted`]),shutdown:g({...M,shutdown:De},[...N,`shutdown`]),viewport:g({width:b(),height:b(),message:m()},[`width`,`height`,`message`]),back:g({action:w(`back`),mode:h(te),message:m()},[`action`,`mode`,`message`]),home:g({action:w(`home`),message:m()},[`action`,`message`]),orientation:g({action:w(`orientation`),orientation:h(ue),message:m(),confirmed:_(),warning:m()},[`action`,`orientation`,`message`]),"app-switcher":g({action:w(`app-switcher`),message:m()},[`action`,`message`]),fold:g({action:w(`fold`),pose:h(le),hingeAngleDegrees:b(`Hinge angle CoreDevice read back after the pose settled.`),screen:g({display:m(`CoreDevice name of the panel the device now lights.`),coordinateSpace:w(ye),widthPt:b(`Panel width in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`),heightPt:b(`Panel height in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`)},[`display`,`coordinateSpace`,`widthPt`,`heightPt`]),message:m()},[`action`,`pose`,`hingeAngleDegrees`,`message`]),"action-button":g({action:w(`action-button`),message:m()},[`action`,`message`]),"tv-remote":g({action:w(`tv-remote`),button:h(de),durationMs:b(),message:m()},[`action`,`button`,`message`]),wait:g({waitedMs:b(),kind:w(`selector`),text:m(),selector:m(),captures:b(),nodeCount:b(),hint:m(),warning:m()},[`waitedMs`]),scroll:g({direction:h([`up`,`down`,`left`,`right`]),edge:h([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:_(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:h([`moved`,`at-edge`,`unchanged`,`unobserved`],"Directional scrolls only: what the owner observed after its gesture. `moved` means the content inside the scroller the swipe ran in differs from the tree the session stored immediately before the gesture; `at-edge` and `unchanged` mean it did not change, with no hidden content left to reveal and with no end-of-content signal to read, respectively; `unobserved` means the pair could not back a claim in either direction — nothing comparable was available (no stored tree, a capture from another lineage, a surface that never came to rest), or every difference sits outside the scroller that was swiped, which a changing status bar does on Android — so the reported distance rests on the gesture plan alone. The field is absent — which is never a claim that nothing moved — on the tiers that verify per pass (`scroll top`/`bottom`, `--until`), on a runtime bound without a capture, on a platform whose scroll dispatches no swipe (the Linux wheel), and where the caller already owns that observation (`--settle`, or a replay with `postGestureStabilization: false`).")},[`direction`]),prepare:g({action:w(`ios-runner`),platform:h(s),deviceId:m(),deviceName:m(),kind:h(C),durationMs:b(),runner:g({},[]),cache:h([`exact`,`restore-key`,`miss`,`external`]),artifact:h([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:m(),recoveryReason:m(),failureReason:m(),timing:g({totalMs:b(),additiveParts:g({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:g({connectMs:{type:`array`,items:w(`buildMs`)},healthCheckMs:{type:`array`,items:m()}},[`healthCheckMs`]),note:m()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:m()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[g({platform:w(`ios`),bundleId:m(),message:m()},[`platform`,`bundleId`,`message`]),g({platform:w(`android`),package:m(),action:m(),extrasCount:b(),message:m()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":g({event:m(),eventUrl:m(),transport:w(`deep-link`),message:m()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[g({action:w(`read`),text:m()},[`action`,`text`]),g({action:w(`write`),textLength:b(),message:m()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[g({platform:h([`ios`,`macos`]),appName:m(),appBundleId:m(),source:w(`session`),surface:h(ne),device_udid:m(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),g({platform:w(`android`),package:m(),activity:m()},[`platform`,`package`,`activity`])]},keyboard:g({platform:h([`android`,`ios`]),action:h([`status`,`dismiss`,`enter`]),visible:_(),wasVisible:_(),dismissed:_(),attempts:b(),inputType:m(),type:h([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:m(),focusedPackage:m(),focusedResourceId:m(),inputOwner:h([`app`,`ime`,`unknown`]),message:m()},[`platform`,`action`]),doctor:g({status:h([`pass`,`warn`,`fail`,`info`]),summary:m(),kind:h([`auto`,`react-native`,`expo`,`repack`]),platform:m(),target:h(c),targetApp:m(),metro:g({host:m(),port:b()},[`host`,`port`]),checks:{type:`array`,items:g({id:m(),status:h([`pass`,`warn`,`fail`,`info`]),summary:m(),hint:m(),command:m(),evidence:v()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:g({mode:w(`snapshot`),baselineInitialized:_(),summary:g({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:g({kind:h([`added`,`removed`]),text:m(),ref:m()},[`kind`,`text`])},warnings:y()},[`mode`,`baselineInitialized`,`summary`,`lines`]),record:{type:`object`,oneOf:[g({recording:w(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:_(),activeSessionApp:v(),showTouches:_()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),g({recording:w(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:D},recordingBackend:m(),recordingScope:m(),recordOnlySession:_(),activeSessionApp:v(),durationMs:b(),capturedDurationMs:b(),recorder:h(ve,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:h(_e,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:_(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:v()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[g({trace:w(`started`),outPath:m()},[`trace`,`outPath`]),g({trace:w(`stopped`),outPath:m(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]},...ae}),je={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:C},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},L={...Ae,...je},Me={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:p({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},R=Object.entries(Me),z=new Set(R.map(([e])=>e)),Ne=Object.fromEntries(R.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Pe(){return Object.fromEntries(R.map(([e,t])=>[e,t.schema]))}function B(e){return n(e)}function V(e){let t=[`Error (${e.code}): ${e.message}`];if(e.cause){let n=e.cause.code?`${e.cause.code} `:``;t.push(`Cause: ${n}${e.cause.message}`)}e.hint&&t.push(`Hint: ${e.hint}`);for(let n of se(e.details))t.push(`Warning: ${ce(n)}`);t.push(...be(r(e.details))),e.supportedOn&&t.push(`Supported on: ${e.supportedOn}`);let n=me(e.details);return n&&t.push(n),t.join(`
|
|
2
|
-
`)}function Fe(e,t,n){let r=Ce({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&Se(t,e)&&(i[t]=a);return xe(i,t)}const Ie={devices:async e=>({devices:e.map(we)}),apps:async e=>({apps:e})};async function Le(e,t){let n=Ie[e];return n?await n(t):t}function Re(){let e=new Map;return{pinInput:(t,n,r)=>Qe(t,n,Ue(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>We(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=
|
|
1
|
+
import{G as e,H as t,M as n,W as r,p as i,r as a}from"./sdk-contracts.js";import{_ as o,h as s}from"./sdk-batch-runner.js";import{i as c,t as l}from"./sdk-device.js";import{S as u,c as d,d as f,p,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{D as m,O as re,S as h,T as ie,_ as g,b as _,g as v,s as ae,v as y,w as oe,x as b,y as x}from"./registry.js";import{n as se}from"./success-text.js";import{t as ce}from"./output-common.js";import"./device.js";import{r as le,t as ue}from"./device-rotation.js";import{t as de}from"./tv-remote.js";import{i as fe,n as S,r as pe,t as C}from"./command-metadata.js";import{r as me}from"./replay-divergence.js";import{n as he,t as ge}from"./cli-output.js";import{r as _e,t as ve}from"./recording-stop-observation.js";import{t as ye}from"./fold-runtime.js";import{n as be}from"./error.js";import{n as xe,r as Se,t as Ce}from"./cli-config.js";import{n as we}from"./result-serialization.js";const w=[`simulator`,`emulator`,`device`];function T(e){return{type:`string`,const:e}}function E(e){return{type:[`string`,`null`],...e?{description:e}:{}}}const D=_({wallClockMs:x(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:x(`Number of real runner round-trips made while serving the request.`),nodeCount:x(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),O=_({field:h(),artifactType:h(),path:h(),localPath:h(),fileName:h()},[`field`]);function k(e={}){let t=e.properties??{},n=e.required??[];return _({targetKind:g([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:x(`Resolved interaction x coordinate when available.`),y:x(`Resolved interaction y coordinate when available.`),referenceWidth:x(`Reference frame width for visualizing the interaction point.`),referenceHeight:x(`Reference frame height for visualizing the interaction point.`),ref:h(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:h(`Selector expression when the target was a selector.`),selectorChain:b(),refLabel:h(),targetHittable:v(),hint:h(),warning:h(),message:h(),evidence:M,resolution:Te,cost:D,maestroNonHittableCoordinateFallbackAllowed:v(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:v(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:T(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const A=_({diagnosticRef:h(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:h(`UTF-8 truncated to 256 bytes.`),label:h(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),Te={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[_({source:T(`runtime`),phase:T(`pre-action`),kind:T(`unique`)},[`source`,`phase`,`kind`]),_({source:T(`runtime`),phase:T(`pre-action`),kind:T(`disambiguated`),matchCount:x(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:A,tiebreak:g([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:A}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),_({source:T(`ref`),phase:T(`pre-action`),kind:T(`exact`)},[`source`,`phase`,`kind`]),_({source:T(`ref`),phase:T(`pre-action`),kind:T(`label-fallback`)},[`source`,`phase`,`kind`]),_({source:T(`direct-ios`),kind:T(`not-observed`)},[`source`,`kind`])]},j=_({from:h(`Surface the pre-action baseline described: a host bundle id, or app.`),to:h(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:h(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),M=_({foregroundApp:h(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:x(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:x(`Subset of nodeCount the platform reports as hittable.`),digest:h(`Order-independent digest of the post-action node multiset.`),changedFromBefore:v(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:j},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),Ee=_({settled:v(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:x(),captures:x(),quietMs:x(),timeoutMs:x(),refsGeneration:x(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:_({ref:h(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:j,diff:_({summary:_({additions:x(),removals:x(),unchanged:x()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:_({kind:g([`added`,`removed`]),text:h(),ref:h(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:v(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:_({ref:h(`Plain ref body (e12) minted from the stored settled tree.`),role:h(),label:h()},[`ref`,`role`])},tailTruncated:v(`Present (true) when tail candidates exceeded the response cap.`),hint:h()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),N={platform:g(c),target:g(l),device:h(`Human-readable device name.`),id:h(`Stable device id.`),kind:g(w)},P=[`platform`,`target`,`device`,`id`,`kind`],De=_({success:v(),exitCode:x(),stdout:h(),stderr:h(),error:y(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function F(e){return e.oneOf?{...e,oneOf:e.oneOf.map(F)}:{...e,properties:{...e.properties??{},settle:Ee}}}function Oe(e){let t={...e};for(let e of Object.keys(t))p(e)&&(t[e]=F(t[e]));return t}const I=k({properties:{evidence:M,button:g([`secondary`,`middle`]),count:x(`Number of press/click repetitions.`),intervalMs:x(`Delay between repeated press/click actions.`),holdMs:x(`Hold duration for each action.`),jitterPx:x(`Randomization radius in pixels.`),doubleTap:v(`Whether the command requested a double-tap action.`)}}),L={text:h(`Text submitted to the field.`),delayMs:x(`Delay between typed characters in milliseconds.`),evidence:M},ke=_({resourceId:E(`Android resource id of the exact field that changed.`),className:E(`Android class name of the exact field that changed.`),packageName:E(`Android package name that owns the exact field.`),rect:_({x:x(),y:x(),width:x(),height:x()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),Ae=Oe({press:I,click:I,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...k({properties:L,required:[`text`]}),not:_({},[`verification`])},k({properties:{...L,verification:T(`unconfirmed`),requested:h(`Literal text requested by the fill command.`),before:E(`Raw target text captured before the fill.`),after:E(`Raw target text captured after the fill.`),target:ke},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:k({properties:{durationMs:x(),gesture:T(`longpress`)}}),hover:k({properties:{gesture:T(`hover`)}}),find:_({ref:h(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:x(`ADR 0014 ref frame epoch for read-only find actions.`),found:v(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:x(`Milliseconds waited for a read-only find condition.`),text:h(`Text value returned by find get_text.`),node:y(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:y(`One listed match with its snapshot ref and node.`)},locator:h(`Locator kind used for the find action.`),query:h(`Query argument used for the find action.`),x:x(`Resolved x coordinate for mutating find actions.`),y:x(`Resolved y coordinate for mutating find actions.`),message:h(`Diagnostic message for mutating find actions.`),cost:D},[],`Daemon response data for the find command.`),boot:_({...N,booted:{type:`boolean`,const:!0}},[...P,`booted`]),shutdown:_({...N,shutdown:De},[...P,`shutdown`]),viewport:_({width:x(),height:x(),message:h()},[`width`,`height`,`message`]),back:_({action:T(`back`),mode:g(te),message:h()},[`action`,`mode`,`message`]),home:_({action:T(`home`),message:h()},[`action`,`message`]),orientation:_({action:T(`orientation`),orientation:g(ue),message:h(),confirmed:v(),warning:h()},[`action`,`orientation`,`message`]),"app-switcher":_({action:T(`app-switcher`),message:h()},[`action`,`message`]),fold:_({action:T(`fold`),pose:g(le),hingeAngleDegrees:x(`Hinge angle CoreDevice read back after the pose settled.`),screen:_({display:h(`CoreDevice name of the panel the device now lights.`),coordinateSpace:T(ye),widthPt:x(`Panel width in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`),heightPt:x(`Panel height in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`)},[`display`,`coordinateSpace`,`widthPt`,`heightPt`]),message:h()},[`action`,`pose`,`hingeAngleDegrees`,`message`]),"action-button":_({action:T(`action-button`),message:h()},[`action`,`message`]),"tv-remote":_({action:T(`tv-remote`),button:g(de),durationMs:x(),message:h()},[`action`,`button`,`message`]),wait:_({waitedMs:x(),kind:T(`selector`),text:h(),selector:h(),captures:x(),nodeCount:x(),hint:h(),warning:h()},[`waitedMs`]),scroll:_({direction:g([`up`,`down`,`left`,`right`]),edge:g([`top`,`bottom`]),until:h(`Until scrolls only: the selector the passes stopped on.`),passes:x(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:x(),pixels:x(),durationMs:x(),message:h(),keyboardAvoided:v(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:x(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:g([`moved`,`at-edge`,`unchanged`,`unobserved`],"Directional scrolls only: what the owner observed after its gesture. `moved` means the content inside the scroller the swipe ran in differs from the tree the session stored immediately before the gesture; `at-edge` and `unchanged` mean it did not change, with no hidden content left to reveal and with no end-of-content signal to read, respectively; `unobserved` means the pair could not back a claim in either direction — nothing comparable was available (no stored tree, a capture from another lineage, a surface that never came to rest), or every difference sits outside the scroller that was swiped, which a changing status bar does on Android — so the reported distance rests on the gesture plan alone. The field is absent — which is never a claim that nothing moved — on the tiers that verify per pass (`scroll top`/`bottom`, `--until`), on a runtime bound without a capture, on a platform whose scroll dispatches no swipe (the Linux wheel), and where the caller already owns that observation (`--settle`, or a replay with `postGestureStabilization: false`).")},[`direction`]),prepare:_({action:T(`ios-runner`),platform:g(c),deviceId:h(),deviceName:h(),kind:g(w),durationMs:x(),runner:_({},[]),cache:g([`exact`,`miss`,`external`]),artifact:g([`valid`,`rebuilt`]),buildMs:x(),connectMs:x(),healthCheckMs:x(),xctestrunPath:h(),recoveryReason:h(),failureReason:h(),timing:_({totalMs:x(),additiveParts:_({buildMs:x(),connectAfterBuildMs:x(),healthCheckMs:x()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:_({connectMs:{type:`array`,items:T(`buildMs`)},healthCheckMs:{type:`array`,items:h()}},[`healthCheckMs`]),note:h()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:h()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[_({platform:T(`ios`),bundleId:h(),message:h()},[`platform`,`bundleId`,`message`]),_({platform:T(`android`),package:h(),action:h(),extrasCount:x(),message:h()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":_({event:h(),eventUrl:h(),transport:T(`deep-link`),message:h()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[_({action:T(`read`),text:h()},[`action`,`text`]),_({action:T(`write`),textLength:x(),message:h()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[_({platform:g([`ios`,`macos`]),appName:h(),appBundleId:h(),source:g([`session`,`runner`],`runner when a live runner read the session app state; session when the record alone answered.`),state:g(i,`The session app XCUIApplication state as a live runner reads it; absent with source session.`),surface:g(ne),device_udid:h(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),_({platform:T(`android`),package:h(),activity:h()},[`platform`,`package`,`activity`])]},keyboard:_({platform:g([`android`,`ios`]),action:g([`status`,`dismiss`,`enter`]),visible:v(),wasVisible:v(),dismissed:v(),attempts:x(),inputType:h(),type:g([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:h(),focusedPackage:h(),focusedResourceId:h(),inputOwner:g([`app`,`ime`,`unknown`]),message:h()},[`platform`,`action`]),doctor:_({status:g([`pass`,`warn`,`fail`,`info`]),summary:h(),kind:g([`auto`,`react-native`,`expo`,`repack`]),platform:h(),target:g(l),targetApp:h(),metro:_({host:h(),port:x()},[`host`,`port`]),checks:{type:`array`,items:_({id:h(),status:g([`pass`,`warn`,`fail`,`info`]),summary:h(),hint:h(),command:h(),evidence:y()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:_({mode:T(`snapshot`),baselineInitialized:v(),summary:_({additions:x(),removals:x(),unchanged:x()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:_({kind:g([`added`,`removed`]),text:h(),ref:h()},[`kind`,`text`])},warnings:b()},[`mode`,`baselineInitialized`,`summary`,`lines`]),record:{type:`object`,oneOf:[_({recording:T(`started`),outPath:h(),sessionStateDir:h(),recordingBackend:h(),recordingScope:h(),recordOnlySession:v(),activeSessionApp:y(),showTouches:v()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),_({recording:T(`stopped`),outPath:h(),telemetryPath:h(),artifacts:{type:`array`,items:O},recordingBackend:h(),recordingScope:h(),recordOnlySession:v(),activeSessionApp:y(),durationMs:x(),capturedDurationMs:x(),recorder:g(ve,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:g(_e,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:v(),warning:h(),overlayWarning:h(),chunks:{type:`array`,items:y()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[_({trace:T(`started`),outPath:h()},[`trace`,`outPath`]),_({trace:T(`stopped`),outPath:h(),artifacts:{type:`array`,items:O}},[`trace`,`outPath`,`artifacts`])]},...ae}),je={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:c},target:{type:`string`,enum:l},kind:{type:`string`,enum:w},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},R={...Ae,...je},Me={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:m({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},z=Object.entries(Me),B=new Set(z.map(([e])=>e)),Ne=Object.fromEntries(z.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Pe(){return Object.fromEntries(z.map(([e,t])=>[e,t.schema]))}function V(e){return t(e)}function H(t){let n=[`Error (${t.code}): ${t.message}`];if(t.cause){let e=t.cause.code?`${t.cause.code} `:``;n.push(`Cause: ${e}${t.cause.message}`)}t.hint&&n.push(`Hint: ${t.hint}`);for(let e of se(t.details))n.push(`Warning: ${ce(e)}`);n.push(...be(e(t.details))),t.supportedOn&&n.push(`Supported on: ${t.supportedOn}`);let r=me(t.details);return r&&n.push(r),n.join(`
|
|
2
|
+
`)}function Fe(e,t,n){let r=Ce({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&Se(t,e)&&(i[t]=a);return xe(i,t)}const Ie={devices:async e=>({devices:e.map(we)}),apps:async e=>({apps:e})};async function Le(e,t){let n=Ie[e];return n?await n(t):t}function Re(){let e=new Map;return{pinInput:(t,n,r)=>Qe(t,n,Ue(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>We(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=U(n,r);ze(e,i,t),Xe(e,i,t)}}}function ze(e,t,n){let i=n?.refsGeneration;typeof i==`number`&&W(e,t,r(n),i)}const Be=new Set([`snapshot`,`find`]),Ve=new Set(f.map(e=>e.name).filter(S).filter(e=>p(e))),He=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Ue(e,t,n){return e.get(U(t,n))}function U(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function We(e,t,n,r,i){let a=U(r,i);if(Ve.has(t)){qe(e,a,Je(n));return}Be.has(t)&&(t===`find`?Ke(e,a,n):Ge(e,a,n))}function Ge(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);W(e,t,i,r)}function Ke(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);W(e,t,i,r)}function qe(e,t,n){n?.refsGeneration!==void 0&&W(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function Je(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function W(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),Ye(i,n,r)}function Ye(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Xe(e,t,n){let r=s(n?.divergence),i=s(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let o=[];Ze(i.refs,o),W(e,t,o,a)}function Ze(e,t){if(Array.isArray(e))for(let n of e){let e=s(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Qe(e,t,n){return n===void 0||n.size===0?t:e===`wait`?$e(t,n)??t:He.has(e)?et(t,n)??t:t}function $e(e,t){if(typeof e.ref!=`string`)return;let n=G(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function et(e,t){let n=s(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=G(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function G(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const tt={config:m({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:m({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},nt=Object.fromEntries(pe().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function K(e){return{...e.inputAudience,...ie,...Ne,...tt,...nt}}function rt(){return fe().map(e=>{let t=e.name in R?R[e.name]:void 0,n=Y(e.name,e);return{name:e.name,description:pt(e.name,oe(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function q(e={}){let t=Re();return{execute:async(r,i)=>{if(!S(r))throw new n(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=C(r),o=X(r,a,i)??Z(a.inputSchema,i,r);if(o)return await J(new n(`INVALID_ARGS`,o),t,void 0,i.session);let s=$(r,a.inputSchema).properties,c=Fe(r,i,s),l=st(c),u=dt(c),d=t.pinInput(r,u,l.client.stateDir),f=await at(e,l.client);try{let n=await(e.runCommand??ot)(f,r,d);return t.mergeCommandResult(r,n,l.client.stateDir,u.session),{isError:!1,structuredContent:await Le(r,n),content:[{type:`text`,text:await mt({name:r,input:u,result:n,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await J(e,t,l.client.stateDir,u.session)}}}}async function J(e,t,n,r){let i=V(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:H(i)}]}}const it=q();async function at(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function ot(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function st(e){return{client:ct(e),outputFormat:ut(e.mcpOutputFormat)}}function ct(e){let t=e.stateDir,r=e.includeCost,i=e.responseLevel,a={};if(t!==void 0){if(typeof t!=`string`||t.length===0)throw new n(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=t}if(r!==void 0){if(typeof r!=`boolean`)throw new n(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=lt(i);return o!==void 0&&(a.responseLevel=o),a}function lt(e){if(e===void 0)return;let t=a.find(t=>t===e);if(t===void 0)throw new n(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return t}function ut(e){if(e===void 0)return`optimized`;if(e!==`optimized`&&e!==`json`)throw new n(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return e}function dt(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!B.has(e)))}function Y(e,t){let n=K(t),r=$(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function X(e,t,n){let r=Y(e,t).properties,i=K(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?re(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function Z(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Q(t,(t,r)=>Z(e.items,t,`${n}[${r}]`));if(o(t))return Q(e.oneOf??[],e=>Z(e,t,n))??Q(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?ft(r,t,e,`${n}.${e}`):void 0)}}function ft(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return Z(e,t[n],r);let a=t[n],s=d(t[i]);if(s===void 0||!o(a))return;let c=X(s,C(s),a);return c===void 0?void 0:`${r}: ${c}`}function Q(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function pt(e,t){let n=ee(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function $(e,t){let n=u(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Pe()}}}async function mt(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return gt(e.result);let t=await ge({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?ht(e.name,t):gt(t?.data??e.result)}function ht(e,t){let n=t.text??``;if(!he(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
|
|
3
3
|
`)?``:`
|
|
4
|
-
`}${r}`}function
|
|
4
|
+
`}${r}`}function gt(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{V as a,H as i,q as n,B as o,rt as r,it as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{O as e,c as t}from"./sdk-contracts.js";import{C as n,a as r,b as i,d as a}from"./sdk-device.js";import{c as o,i as s,s as c}from"./lease-scope.js";import{n as l,t as u}from"./catalog.js";import{t as d}from"./sdk-remote-config.js";import{t as f}from"./prepare-kind.js";import{r as p}from"./diagnostics.js";import{D as m}from"./owner-identity.js";import{f as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as g}from"./base-url.js";import{i as _,r as v}from"./client-metro-companion.js";import{n as y}from"./metro2.js";import{n as te,r as b,t as ne}from"./remote-config2.js";import{n as x,t as S}from"./providers.js";import C from"node:path";import w from"node:fs";import T from"node:crypto";const E={slug:`react-devtools-companion`,runArg:g,displayName:`React DevTools companion`};async function re(e){return await v({...e,definition:E,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function D(e){return await _({...e,definition:E})}function O(e){return e===`android-instance`||e===`ios-instance`}function ie(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ae(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ae(e)}function oe(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function se(e){let t=e?.metroPublicBaseUrl?.trim();return t?oe(t):null}function ce(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=se(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function le(e,t={}){let n=ce(e,t);return(await h(`npm`,ie(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function A(e){let t=L(e);if(!w.existsSync(t))return null;let n;try{n=JSON.parse(w.readFileSync(t,`utf8`))}catch(t){return H(e,t),null}return ge(n)?n:(H(e),null)}function j(e){let t=L({stateDir:e.stateDir,session:e.state.session});w.mkdirSync(C.dirname(t),{recursive:!0}),V(t,e.state),V(R(e.stateDir),{session:e.state.session})}function M(e){return{baseUrl:me(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function N(e){w.rmSync(L(e),{force:!0});let t=R(e.stateDir);B(e.stateDir)===e.session&&w.rmSync(t,{force:!0})}function ue(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=A(t)??(t.allowActiveFallback?z({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,t),l=s(i);return{runtime:i.runtime,connection:o(l),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...c(l),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function P(e){return o(s(e))}function F(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function de(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function I(t){try{return T.createHash(`sha256`).update(w.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function L(e){return C.join(e.stateDir,`remote-connections`,`${he(e.session)}.json`)}function R(e){return C.join(e,`remote-connections`,`.active-session.json`)}function z(e){let t=B(e.stateDir);return t?A({stateDir:e.stateDir,session:t}):null}function B(e){let t=R(e);if(w.existsSync(t))try{let e=JSON.parse(w.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function fe(e){if(e)return T.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function pe(e,t){try{return b({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function V(e,t){m({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function me(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function H(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),N(e)}function he(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${T.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function ge(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&_e(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ve(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ye(t.daemon)}function _e(e,t){return t.every(t=>typeof e[t]==`string`)}function ve(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ye(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:be(e)}function be(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const xe=d.map(e=>e.key);function U(e){let t={};for(let n of xe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Se(e){return e.remoteConfig?{...U(b({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ce(e){return e===`cloud`||e===`proxy`||W(e)}function W(e){return e===`limrun`||x(e)}function we(){return[`cloud`,`proxy`,S.browserStack,S.awsDeviceFarm,`limrun`].join(`, `)}function G(e){let t=W(e),n=x(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===S.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function K(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Te(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const q=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),J=new Set([`open`]),Ee=new Set([l.open,l.install,l.reinstall,u.installSource]);async function De(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=b({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...U(o.profile),...r,remoteConfig:o.resolvedPath},c=A({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?t.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??t.runtime,h=u,g=!c,_,v=Fe(h);if(v.shouldAllocate(n)){let e=await Me({command:n,client:i,state:u,nextState:h,nextFlags:d,initialApp:p,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=await Oe({command:n,flags:d,client:i,state:u,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=y.state,m=y.runtime,g||=y.changed,await je({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:y.preparedMetroCleanupOnFailure,metroCleanupToStop:y.metroCleanupToStop}),{flags:{...d,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??d.platform,target:h.target??d.target},runtime:m,connection:P(h)}}async function Oe(t){let{command:n,flags:r,state:i,client:a}=t,o=ke(t.nextState,r),s=t.runtime;if(!Je(n,r,t.batchSteps,t.positionals)||!$(r)||!Ae(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Be(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Xe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function ke(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ae(e,t,n){return e===!0||!t||!Ye(t,n)}async function je(e){if(e.changed)try{j({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await Ke(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Me(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&tt(i,c.device);let l=s.leaseBackend??o??qe(i,t);at(r,i,l);let u=await $e(n,s,l,a,i,e.initialApp),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Ne(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Pe(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Ne(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Pe(e,t,n,r){let i=F(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Fe(e){let t=G(e.leaseProvider);return t.leaseKind===`proxy`?Re:t.supportsDeferredAppSelection?Ie:t.usesCloudWebDriverLease?ze:Le}const Ie={shouldAllocate:e=>e!==l.apps&&!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Le={shouldAllocate:e=>!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Re={shouldAllocate:e=>e!==`devices`&&!q.has(e),ttlMs:()=>3e5,resolveLeaseState:et},ze={shouldAllocate:e=>!q.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Be(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:f(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await y(e)}catch{}}async function Ve(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function X(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...P(t)}):{released:!1}}function He(e){let t=Ue(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ue(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&We(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function We(e,t){let n=M({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ge(e,t,n){if(!t.leaseId)return;let r=He({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Z(t,`no credential known to belong to that endpoint was available`);try{await X(e,t,r.daemonAuthToken);return}catch{return Z(t,`the release request failed`)}}function Z(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Ke(e,t,n){if(n)try{let r=F(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function qe(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function Je(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:J.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return J.has(t)&&e.runtime===void 0})}function $(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Ye(e,n){return!e.platform||!n||!t(n)||e.platform===n}function Xe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ze(e,t){if(e)return Ye(e,t)?e:void 0}function Qe(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function $e(e,t,n,r,i,a){let o=P(t);if(t.leaseId&&t.leaseBackend===n){let i=await ot(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...K(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function et(t){if(!Ee.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(t.client,t.flags),r=rt(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??it(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function tt(e,t){if(e.platform=t.platform,e.target=t.target??e.target,a(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(e,t){let i=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await n(i.map(e=>({...r(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function rt(e){return`${i(e)}:${e.target??`mobile`}:${e.id}`}function it(e){if(a(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{N as C,O as D,le as E,re as O,de as S,j as T,fe as _,Q as a,z as b,K as c,G as d,Ce as f,P as g,M as h,X as i,D as k,Te as l,Se as m,De as n,Y as o,U as p,Ge as r,Ve as s,$ as t,we as u,I as v,ue as w,A as x,F as y};
|
|
1
|
+
import{M as e,c as t,f as n,u as r}from"./sdk-contracts.js";import{S as i,T as a,a as o,o as s,x as c}from"./sdk-device.js";import{a as l,c as u,l as d,r as f}from"./lease-scope.js";import{n as p,t as m}from"./catalog.js";import{t as h}from"./sdk-remote-config.js";import{t as g}from"./prepare-kind.js";import{r as _}from"./diagnostics.js";import{D as v}from"./owner-identity.js";import{f as y}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as b}from"./base-url.js";import{i as te,r as ne}from"./client-metro-companion.js";import{n as re}from"./metro2.js";import{n as ie,r as x,t as ae}from"./remote-config2.js";import{n as S,t as C}from"./providers.js";import w from"node:path";import T from"node:fs";import E from"node:crypto";const oe={slug:`react-devtools-companion`,runArg:b,displayName:`React DevTools companion`};async function se(e){return await ne({...e,definition:oe,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function D(e){return await te({...e,definition:oe})}function O(e){return e===`android-instance`||e===`ios-instance`}function ce(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function le(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!le(e)}function ue(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function de(e){let t=e?.metroPublicBaseUrl?.trim();return t?ue(t):null}function fe(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=de(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function pe(e,t={}){let n=fe(e,t);return(await y(`npm`,ce(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function A(e){let t=i(e),n=r(t);return{platform:t,target:e.target,leaseBackend:n,identityFlag:n?s(t):void 0,id:e.id}}function me(e){return`${e.platform}:${e.target??`mobile`}:${e.id}`}function j(e){let t=[e.leaseBackend?n(e.leaseBackend):void 0,e.recordedPlatform].filter(e=>e!==void 0);if(t.some(e=>t.some(t=>c(e,t)))||c(e.requestedPlatform,t[0]??e.recordedPlatform))return{ok:!1,boundPlatform:t[0],requestedPlatform:e.requestedPlatform};let r=[...t,e.requestedPlatform].filter(e=>e!==void 0);return{ok:!0,platform:r.find(e=>e!==`apple`)??r[0]}}function he(e,t){return t!==void 0&&e.platform===void 0?!1:j({leaseBackend:e.leaseBackend,recordedPlatform:e.platform,requestedPlatform:t}).ok}function M(e){let t=z(e);if(!T.existsSync(t))return null;let n;try{n=JSON.parse(T.readFileSync(t,`utf8`))}catch(t){return W(e,t),null}return Se(n)?n:(W(e),null)}function N(e){let t=z({stateDir:e.stateDir,session:e.state.session});T.mkdirSync(w.dirname(t),{recursive:!0}),U(t,e.state),U(B(e.stateDir),{session:e.state.session})}function P(e){return{baseUrl:be(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function F(e){T.rmSync(z(e),{force:!0});let t=B(e.stateDir);H(e.stateDir)===e.session&&T.rmSync(t,{force:!0})}function ge(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?ie({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=M(t)??(t.allowActiveFallback?V({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&R(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=ye(i,t),o=l(i);return{runtime:i.runtime,connection:d(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...u(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function I(e){return d(l(e))}function L(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function _e(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function R(t){try{return E.createHash(`sha256`).update(T.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function z(e){return w.join(e.stateDir,`remote-connections`,`${xe(e.session)}.json`)}function B(e){return w.join(e,`remote-connections`,`.active-session.json`)}function V(e){let t=H(e.stateDir);return t?M({stateDir:e.stateDir,session:t}):null}function H(e){let t=B(e);if(T.existsSync(t))try{let e=JSON.parse(T.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function ve(e){if(e)return E.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function ye(e,t){try{return x({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function U(e,t){v({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function be(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function W(e,t){_({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),F(e)}function xe(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${E.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Se(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&Ce(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&we(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&Te(t.daemon)}function Ce(e,t){return t.every(t=>typeof e[t]==`string`)}function we(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function Te(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:Ee(e)}function Ee(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const De=h.map(e=>e.key);function G(e){let t={};for(let n of De){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Oe(e){return e.remoteConfig?{...G(x({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function ke(e){return e===`cloud`||e===`proxy`||K(e)}function K(e){return e===`limrun`||S(e)}function Ae(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function q(e){let t=K(e),n=S(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===C.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function J(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function je(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const Y=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),X=new Set([`open`]),Me=new Set([p.open,p.install,p.reinstall,m.installSource]);async function Ne(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=x({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...G(o.profile),...r,remoteConfig:o.resolvedPath},c=M({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??st(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=q(l.leaseProvider).supportsDeferredAppSelection,f=d&&n===p.open?t.positionals?.[0]:void 0;d&&delete u.providerApp;let m=ot(l.runtime,u.platform)??t.runtime,h=l,g=!c,_,v=Ve(h);if(v.shouldAllocate(n)){let e=await Re({command:n,client:i,state:l,nextState:h,nextFlags:u,initialApp:f,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=j({leaseBackend:h.leaseBackend,recordedPlatform:h.platform,requestedPlatform:u.platform});if(!y.ok)throw $({session:l.session,leaseBackend:h.leaseBackend,boundPlatform:y.boundPlatform,requestedPlatform:y.requestedPlatform,detail:`bound-connection`});h={...h,platform:y.platform},u.platform=y.platform;let b=await Pe({command:n,flags:u,client:i,state:l,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=b.state,m=b.runtime,g||=b.changed,await Le({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:b.preparedMetroCleanupOnFailure,metroCleanupToStop:b.metroCleanupToStop}),{flags:{...u,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??u.platform,target:h.target??u.target},runtime:m,connection:I(h)}}async function Pe(t){let{command:n,flags:r,state:i,client:a}=t,o=Fe(t.nextState,r),s=t.runtime;if(!nt(n,r,t.batchSteps,t.positionals)||!rt(r)||!Ie(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Ke(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!at(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function Fe(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ie(e,t,n){return e===!0||!t||!it(t,n)}async function Le(e){if(e.changed)try{N({stateDir:e.stateDir,state:e.state})}catch(t){throw await Z(e.preparedMetroCleanupOnFailure),await et(e.client,e.state,e.acquiredLeaseForCleanup),t}await Z(e.metroCleanupToStop)}async function Re(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&ut(i,c.device);let l=s.leaseBackend??o??tt(i,t);ft(r,l);let u=j({leaseBackend:l,recordedPlatform:s.platform,requestedPlatform:i.platform});if(!u.ok)throw $({session:r.session,leaseBackend:l,boundPlatform:u.boundPlatform,requestedPlatform:u.requestedPlatform,detail:`bound-connection`});pt(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await ct(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,ze(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:Be(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function ze(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Be(e,t,n,r){let i=L(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Ve(e){let t=q(e.leaseProvider);return t.leaseKind===`proxy`?We:t.supportsDeferredAppSelection?He:t.usesCloudWebDriverLease?Ge:Ue}const He={shouldAllocate:e=>e!==p.apps&&!Y.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ue={shouldAllocate:e=>!Y.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},We={shouldAllocate:e=>e!==`devices`&&!Y.has(e),ttlMs:()=>3e5,resolveLeaseState:lt},Ge={shouldAllocate:e=>!Y.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Ke(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:g(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Z(e){if(e)try{await re(e)}catch{}}async function qe(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function Je(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...I(t)}):{released:!1}}function Ye(e){let t=Xe(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Xe(e,t,n){try{let{profile:r}=ae({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&Ze(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function Ze(e,t){let n=P({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Qe(e,t,n){if(!t.leaseId)return;let r=Ye({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return $e(t,`no credential known to belong to that endpoint was available`);try{await Je(e,t,r.daemonAuthToken);return}catch{return $e(t,`the release request failed`)}}function $e(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function et(e,t,n){if(n)try{let r=L(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){return e.leaseBackend??r(e.platform)}function tt(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function nt(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:X.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return X.has(t)&&e.runtime===void 0})}function rt(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function it(e,n){return!e.platform||!n||!t(n)||e.platform===n}function at(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ot(e,t){if(e)return it(e,t)?e:void 0}function st(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&q(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:R(n),daemon:P(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function ct(e,t,n,r,i,a){let o=I(t);if(t.leaseId&&t.leaseBackend===n){let i=await mt(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...J(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function lt(t){if(!Me.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await dt(t.client,t.flags),r=A(n);return{state:{...t.state,deviceKey:me(r),leaseBackend:t.state.leaseBackend??t.leaseBackend??r.leaseBackend,platform:r.platform,target:t.state.target??r.target,updatedAt:new Date().toISOString()},device:n}}function ut(e,t){let n=A(t);e.platform=n.platform,e.target=n.target??e.target,n.identityFlag===`udid`&&(e.udid=n.id),n.identityFlag===`serial`&&(e.serial=n.id)}async function dt(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await a(n.map(e=>({...o(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $(t){return new e(`INVALID_ARGS`,t.detail===`bound-connection`?`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`:`The requested platform does not match the device this lease backend rents.`,{session:t.session,leaseBackend:t.leaseBackend,platform:t.boundPlatform,requestedPlatform:t.requestedPlatform,reason:`CONNECTION_PLATFORM_CONFLICT`})}function ft(t,n){if(t.leaseBackend&&t.leaseBackend!==n)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend})}function pt(t,n){if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function mt(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(f(e))return;throw e}}export{O as A,V as C,ge as D,F as E,D as M,N as O,j as S,_e as T,I as _,Je as a,R as b,qe as c,Ae as d,q as f,P as g,Oe as h,Qe as i,se as j,pe as k,J as l,G as m,rt as n,Q as o,ke as p,Ne as r,Z as s,$ as t,je as u,he as v,M as w,L as x,ve as y};
|
package/dist/src/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{O as e,k as t}from"./sdk-contracts.js";import{s as n}from"./device-shell.js";import{a as r}from"./version.js";import{t as i}from"./daemon-resolution.js";import{r as a}from"./remote-config2.js";import{n as o}from"./src.js";import{n as s,r as c,t as l}from"./provider-webdriver.js";import{t as u}from"./providers.js";import{C as d,S as f,T as p,_ as m,a as h,b as g,c as _,d as v,f as y,g as ee,h as te,i as ne,l as b,o as x,p as S,r as re,s as C,t as ie,u as ae,v as oe,x as w,y as se}from"./connection-runtime.js";import{o as ce,r as le}from"./auth-session.js";import{t as T}from"./shared.js";import E from"node:path";import D from"node:fs";import O from"node:crypto";const ue=new Set([`daemonAuthToken`,`metroBearerToken`]);function de(e){let t=A(pe(e.profile)),n=E.join(e.stateDir,`remote-connections`,`generated`);D.mkdirSync(n,{recursive:!0,mode:448});let r=E.join(n,`${he(e.provider)}-${me(t)}.json`);D.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{D.chmodSync(r,384)}catch{}return r}function fe(n){try{return a(n)}catch(r){let i=t(r);throw new e(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function k(e){let t=fe({configPath:de({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:ge(e.provider)});return{flags:{...S(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function pe(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!ue.has(e)))}function me(e){return O.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function A(e){return Array.isArray(e)?e.map(A):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,A(t)])):e}function he(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function ge(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function j(...e){return O.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function _e(e){let t=await le({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await ve({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=j(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return k({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function ve(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return ye(await ce(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function ye(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=t.connection;if(!n||typeof n!=`object`)throw new e(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return be(n.remoteConfigProfile);throw new e(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function be(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(t).length===0)throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return t}function M(e){let t=xe(e.provider)(e),n=j(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??h(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...b(e.flags)};return k({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const N=[{provider:u.browserStack,buildProfileFields:Se},{provider:u.awsDeviceFarm,buildProfileFields:we}];function xe(t){let n=N.find(e=>e.provider===t)?.buildProfileFields;if(n)return n;throw new e(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${t}".`)}function Se(e){return I(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),I(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:P(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:F(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:F(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ce(F(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,..._(e.flags)}}function Ce(t,n){if(t.startsWith(`bs://`)||/^https?:\/\//i.test(t))return t;let r=E.resolve(n,t);try{if(D.statSync(r).isFile())return r}catch{}throw new e(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function we(e){let{env:t,flags:n}=e;c(n,u.awsDeviceFarm);let r=P(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=L(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:L(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:R(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:R(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??s(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function P(t,n){if(t===`android`||t===`ios`)return t;throw new e(`INVALID_ARGS`,n)}function F(t,n){if(t)return t;throw new e(`INVALID_ARGS`,n)}function I(t,n,r){let i=t?.[n];if(i)return i;throw new e(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function L(e,t,n,r){return F(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Te(t){let n=t.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new e(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=Ee({flags:t.flags});return k({stateDir:t.stateDir,provider:`limrun`,profile:r,cwd:t.cwd,env:n,flags:t.flags})}function Ee(e){let t=e.flags,n=De(t);return{stateDir:i(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...b(t)}}function De(t){if(t.platform!==`android`&&t.platform!==`ios`)throw new e(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(t.device!==void 0)throw new e(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=h(t),r=t.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new e(`INVALID_ARGS`,`connect limrun --platform ${t.platform} requires --lease-backend ${r}.`);return r}function Oe(t){let n=t.flags.daemonBaseUrl??t.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new e(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=j(t.stateDir,n,t.flags.session),i={daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`,daemonServerMode:t.flags.daemonServerMode,tenant:t.flags.tenant??`proxy`,sessionIsolation:t.flags.sessionIsolation??`tenant`,runId:t.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:t.flags.leaseBackend??h(t.flags),platform:t.flags.platform,target:t.flags.target,device:t.flags.device,udid:t.flags.udid,serial:t.flags.serial,iosSimulatorDeviceSet:t.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:t.flags.androidDeviceAllowlist,session:t.flags.session,...b(t.flags)};return k({stateDir:t.stateDir,provider:`proxy`,profile:i,cwd:t.cwd,env:t.env,flags:t.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`}})}const z={cloud:{resolve:_e,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Oe,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>M({provider:`browserstack`,...e}),verify:je},"aws-device-farm":{resolve:e=>M({provider:`aws-device-farm`,...e}),verify:Me},limrun:{resolve:Te,verify:Ne}};async function ke(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=a({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...S(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...y(i)?{provider:i}:{}}}let r=e.provider??(Pe(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Ae(e){return e.provider?await z[e.provider].verify({flags:e.flags,env:process.env}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function je(e){let{flags:t,env:n}=e;return await l.verifyConnection({provider:`browserstack`,username:B(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:V(t.platform,`BrowserStack`),deviceName:B(t.device,`BrowserStack profile missed device.`),osVersion:B(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:B(t.providerApp,`BrowserStack profile missed app.`)})}async function Me(e){let{flags:t}=e;return await l.verifyConnection({provider:`aws-device-farm`,platform:V(t.platform,`AWS Device Farm`),projectArn:B(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:B(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function Ne(e){return await o({apiKey:B(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:r(),platform:V(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function Pe(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function B(t,n){if(t!==void 0)return t;throw new e(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(t,n){if(t===`android`||t===`ios`)return t;throw new e(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function Fe(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??Ie();return{session:i,previous:n.session?w({stateDir:t,session:i}):null,remoteConfigHash:oe(r),daemon:te(n)}}function Ie(){return`adc-${O.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=v(e.leaseProvider),r=n.leaseKind;if(r===`proxy`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`};if(n.supportsDeferredAppSelection)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.`};if(r===`direct-device-provider`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`};let i=e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``;return{status:`deferred`,nextSteps:K(e,[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`]),message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+i}}function Le(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Re(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
-
`)}let a=
|
|
3
|
-
`)}function U(e){let{state:t,runtimePreparation:n,readiness:r,previousLeaseNotice:i}=e,a=H(t,r);return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:
|
|
4
|
-
`)),!0};function
|
|
5
|
-
`)}function
|
|
1
|
+
import{M as e,N as t}from"./sdk-contracts.js";import{s as n}from"./device-shell.js";import{a as r}from"./version.js";import{t as i}from"./daemon-resolution.js";import{r as a}from"./remote-config2.js";import{n as o}from"./src.js";import{n as s,r as c,t as l}from"./provider-webdriver.js";import{t as u}from"./providers.js";import{C as d,E as f,O as ee,S as p,T as m,_ as h,a as te,b as ne,c as g,d as re,f as _,g as ie,i as ae,l as oe,m as v,n as se,o as y,p as b,s as x,t as ce,u as S,v as le,w as C,x as ue,y as de}from"./connection-runtime.js";import{o as fe,r as pe}from"./auth-session.js";import{t as w}from"./shared.js";import T from"node:path";import E from"node:fs";import D from"node:crypto";const me=new Set([`daemonAuthToken`,`metroBearerToken`]);function he(e){let t=k(_e(e.profile)),n=T.join(e.stateDir,`remote-connections`,`generated`);E.mkdirSync(n,{recursive:!0,mode:448});let r=T.join(n,`${ye(e.provider)}-${ve(t)}.json`);E.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{E.chmodSync(r,384)}catch{}return r}function ge(n){try{return a(n)}catch(r){let i=t(r);throw new e(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function O(e){let t=ge({configPath:he({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:be(e.provider)});return{flags:{...v(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function _e(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!me.has(e)))}function ve(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function k(e){return Array.isArray(e)?e.map(k):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,k(t)])):e}function ye(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function be(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function A(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function xe(e){let t=await pe({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await j({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=A(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return O({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function j(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return M(await fe(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function M(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=t.connection;if(!n||typeof n!=`object`)throw new e(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return Se(n.remoteConfigProfile);throw new e(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Se(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(t).length===0)throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return t}function N(e){let t=we(e.provider)(e),n=A(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??y(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...S(e.flags)};return O({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const Ce=[{provider:u.browserStack,buildProfileFields:Te},{provider:u.awsDeviceFarm,buildProfileFields:De}];function we(t){let n=Ce.find(e=>e.provider===t)?.buildProfileFields;if(n)return n;throw new e(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${t}".`)}function Te(e){return I(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),I(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:P(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:F(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:F(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ee(F(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...oe(e.flags)}}function Ee(t,n){if(t.startsWith(`bs://`)||/^https?:\/\//i.test(t))return t;let r=T.resolve(n,t);try{if(E.statSync(r).isFile())return r}catch{}throw new e(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function De(e){let{env:t,flags:n}=e;c(n,u.awsDeviceFarm);let r=P(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=L(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:L(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:R(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:R(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??s(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function P(t,n){if(t===`android`||t===`ios`)return t;throw new e(`INVALID_ARGS`,n)}function F(t,n){if(t)return t;throw new e(`INVALID_ARGS`,n)}function I(t,n,r){let i=t?.[n];if(i)return i;throw new e(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function L(e,t,n,r){return F(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Oe(t){let n=t.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new e(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=ke({flags:t.flags});return O({stateDir:t.stateDir,provider:`limrun`,profile:r,cwd:t.cwd,env:n,flags:t.flags})}function ke(e){let t=e.flags,n=Ae(t);return{stateDir:i(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...S(t)}}function Ae(t){if(t.platform!==`android`&&t.platform!==`ios`)throw new e(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(t.device!==void 0)throw new e(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=y(t),r=t.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new e(`INVALID_ARGS`,`connect limrun --platform ${t.platform} requires --lease-backend ${r}.`);return r}function je(t){let n=t.flags.daemonBaseUrl??t.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new e(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=A(t.stateDir,n,t.flags.session),i={daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`,daemonServerMode:t.flags.daemonServerMode,tenant:t.flags.tenant??`proxy`,sessionIsolation:t.flags.sessionIsolation??`tenant`,runId:t.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:t.flags.leaseBackend??y(t.flags),platform:t.flags.platform,target:t.flags.target,device:t.flags.device,udid:t.flags.udid,serial:t.flags.serial,iosSimulatorDeviceSet:t.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:t.flags.androidDeviceAllowlist,session:t.flags.session,...S(t.flags)};return O({stateDir:t.stateDir,provider:`proxy`,profile:i,cwd:t.cwd,env:t.env,flags:t.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`}})}const z={cloud:{resolve:xe,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:je,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>N({provider:`browserstack`,...e}),verify:Pe},"aws-device-farm":{resolve:e=>N({provider:`aws-device-farm`,...e}),verify:Fe},limrun:{resolve:Oe,verify:Ie}};async function Me(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=a({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...v(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...b(i)?{provider:i}:{}}}let r=e.provider??(Le(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Ne(e){return e.provider?await z[e.provider].verify({flags:e.flags,env:process.env}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function Pe(e){let{flags:t,env:n}=e;return await l.verifyConnection({provider:`browserstack`,username:B(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:V(t.platform,`BrowserStack`),deviceName:B(t.device,`BrowserStack profile missed device.`),osVersion:B(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:B(t.providerApp,`BrowserStack profile missed app.`)})}async function Fe(e){let{flags:t}=e;return await l.verifyConnection({provider:`aws-device-farm`,platform:V(t.platform,`AWS Device Farm`),projectArn:B(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:B(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function Ie(e){return await o({apiKey:B(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:r(),platform:V(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function Le(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function B(t,n){if(t!==void 0)return t;throw new e(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(t,n){if(t===`android`||t===`ios`)return t;throw new e(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function Re(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??ze();return{session:i,previous:n.session?C({stateDir:t,session:i}):null,remoteConfigHash:ne(r),daemon:ie(n)}}function ze(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=_(e.leaseProvider),r=n.leaseKind;if(r===`proxy`)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`};if(n.supportsDeferredAppSelection)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.`};if(r===`direct-device-provider`)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`};let i=e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``;return{status:`deferred`,nextSteps:q(e,[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`]),message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+i}}function Be(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...G(e,t)}}function Ve(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
+
`)}let a=K(n),o=[`${a===`verified`?`Connected`:`Configured`} successfully with ${n.service}.`,`${a===`verified`?`Verified`:`Status`}: ${n.verificationMessage}`];return n.project&&o.push(`Project: ${n.project.name??n.project.reference} — verified`),n.device&&o.push(We(n.device)),n.app&&o.push(Ge(t,n.app)),o.push(n.preparationMessage),o.push(`Next:`),o.push(...n.nextSteps.map(e=>` ${e}`)),o.push(...n.notes??[]),r&&o.push(r.message),i&&o.push(i.message),o.join(`
|
|
3
|
+
`)}function U(e){let{state:t,runtimePreparation:n,readiness:r,previousLeaseNotice:i}=e,a=H(t,r);return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:de(t.daemon?.baseUrl),liveSession:W(t),...He(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ue({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function W(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function He(e,t){return e?{verification:{status:K(e),service:e.service,message:e.verificationMessage,...e.project?{project:e.project}:{}},...e.device?{device:e.device}:{},...e.app?{app:e.app}:{},nextSteps:e.nextSteps??t?.nextSteps??[],...e.notes?{notes:e.notes}:{}}:{}}function Ue(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function We(e){let t=`osVersion`in e?e.osVersion:void 0,n=[e.platform,t].filter(Boolean).join(` `),r=n?` (${n})`:``;return e.status===`deferred`?`Device: ${e.name??`Provider-selected device`} — allocated on first device command`:`Device: ${e.name??e.reference??`Configured device`}${r} — verified`}function Ge(e,t){return t.status===`missing`?`App: ${et(e)} — ${t.message??`Install or attach an app before open.`}`:`App: ${t.name??t.reference??`configured app`} — ${t.status===`verified`?`verified`:t.message??`configured`}`}function G(e,t){let n=Ke(e,t);return{...n,nextSteps:q(e,n.nextSteps)}}function Ke(e,t){let n=_(e.leaseProvider).leaseKind;if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${Y(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:$e()};if(_(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:qe(t)?Qe(e):[...Ye(t),...Ze(e).nextSteps],...Je(t)?{notes:Xe(e,!r)}:{}}}function qe(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function Je(e){return _(e?.provider).supportsArtifacts}function Ye(e){return e?.app?.status!==`missing`||!e.project?.reference||!e.device?.reference?[]:[`agent-device connect aws-device-farm --platform ${e.device.platform} --aws-project-arn ${e.project.reference} --aws-device-arn ${e.device.reference} --aws-app-arn <arn> --force`]}function Xe(e,t){return[...t?[`Use the installed package or bundle identifier in open, not the app artifact name.`]:[],`After close, run ${J(e,`agent-device artifacts --json`)} for provider video and logs.`]}function Ze(e){return{nextSteps:[`agent-device open ${Y(e.platform)} --relaunch`]}}function Qe(e){let t=Y(e.platform);return[`agent-device install ${t} <app-path-or-url>`,`agent-device open ${t} --relaunch`]}function K(e){return`status`in e?e.status:`verified`}function $e(){return[`agent-device open <package-or-bundle-id> --relaunch`,`agent-device snapshot -i`,`agent-device close`,`agent-device artifacts --json`]}function q(e,t){return t.map(t=>J(e,t))}function J(e,t){return`${t} --session ${n(e.session)}`}function Y(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function et(e){let t=_(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const tt=async({positionals:e,flags:t,client:n})=>{let r=i(t.stateDir).baseDir,a=_t(e);nt(a,t);let o=await Me({provider:a,flags:t,stateDir:r}),s=o.flags,c=ut(o.remoteConfigPath),l=rt(s,c),u=Re({stateDir:r,flags:s,remoteConfigPath:o.remoteConfigPath});it(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:y(s),connection:c,daemon:u.daemon});let d=await Ne(o),f=at({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});ee({stateDir:r,state:f});let p=await lt(n,r,s,u.previous,f.daemon?.baseUrl),m=St(s,f),h=Be(f,d);return await w(s,U({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p}),()=>Ve({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p})),!0};function nt(t,n){if(!(!t||!n.remoteConfig))throw new e(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function rt(t,n){if(!t.tenant)throw new e(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&_(n?.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:t.tenant,runId:t.runId}}function it(t,n){if(!(!t||vt(t,n))&&!n.flags.force)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:n.session,remoteConfig:t.remoteConfigPath})}function at(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=ct(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=ot(t,o,r),l=st(t,o,s,c,i.session);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function ot(e,t,n){let r=ue(n??{},t??{});return{leaseId:t?.leaseId,leaseBackend:t?.leaseBackend??y(e),...r,deviceKey:t?.deviceKey??r.deviceKey}}function st(e,t,n,r,i){let a=p({leaseBackend:r.leaseBackend,recordedPlatform:t?.platform,requestedPlatform:e.platform});if(!a.ok)throw ce({session:i,leaseBackend:r.leaseBackend,boundPlatform:a.boundPlatform,requestedPlatform:a.requestedPlatform,detail:t?`bound-connection`:`requested-backend`});return{platform:a.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function ct(e,t){return!!(t&&!e.force)}async function lt(e,t,n,r,i){if(!(!r||!n.force))return await x(r.metro),await g({stateDir:t,state:r}),await ae(e,r,{nextDaemonBaseUrl:i,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function ut(e){let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return h(t)}const dt=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=X(e);if(!i)return await Z(e,n),!0;let a=i.session,o;if(i.leaseId||i.runtime||i.metro)try{o=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await x(i.metro),await g({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await te(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return f({stateDir:r,session:a}),await w(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>pt(a,o)),!0},ft=async({positionals:t,flags:n})=>{if(t[0]!==`status`)throw new e(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=X(n);if(!i)return await Z(n,r),!0;let a=H(i),o=Ct(i);return await w(n,U({state:i,runtimePreparation:o}),()=>[`Configured remote session "${i.session}".`,`tenant=${i.tenant} runId=${i.runId} leaseId=${i.leaseId??`pending`} backend=${i.leaseBackend??`pending`}`,`remoteConfig=${i.remoteConfigPath}`,i.runtime?`metro=prepared`:`metro=not-prepared`,a?.message,o?.message].filter(e=>!!e).join(`
|
|
4
|
+
`)),!0};function pt(e,t){return[`Disconnected remote session "${e}".`,...mt(t),...gt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
+
`)}function mt(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=ht(e);return t?[t]:[]})}function ht(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.message==`string`&&t.message.length!==0)return`Provider release warning${typeof t.code==`string`&&t.code.length>0?` (${t.code})`:``}: ${t.message}`}function gt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function _t(t){let n=t[0];if(n!==void 0){if(t.length>1)throw new e(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(b(n))return n;throw new e(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${re()}.`)}}function X(e){let t=e.session??`default`,n=i(e.stateDir).baseDir;return{session:t,stateDir:n,state:C({stateDir:n,session:t})??(e.session?null:d({stateDir:n}))}}async function Z(e,t){await w(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function vt(e,t){return yt(e,t)&&bt(e,t)&&xt(e.daemon,t.daemon)}function yt(e,t){return[[e.remoteConfigPath,t.remoteConfigPath],[e.remoteConfigHash,t.remoteConfigHash],[e.session,t.session],[e.tenant,t.flags.tenant],[e.runId,t.flags.runId]].every(([e,t])=>e===t)}function bt(e,t){return le(e,t.flags.platform)?[[e.leaseBackend,t.desiredLeaseBackend],[e.target,t.flags.target]].every(([e,t])=>t===void 0||e===t)&&m(e,t.connection):!1}function xt(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function St(e,t){if(!t.runtime&&!(!se(e)&&!$(t.remoteConfigPath)))return Q(t)}function Ct(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=J(e,`agent-device metro prepare --remote-config ${n(e.remoteConfigPath)}`);return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function $(e){try{let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}export{tt as connectCommand,ft as connectionCommand,dt as disconnectCommand};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as DaemonError, Q as normalizeError, V as centerOfRect, Y as defaultHintForCode, a as DaemonRequest, d as JsonRpcRequestEnvelope, f as LeaseBackend, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, u as JsonRpcId, v as SessionRuntimeHints } from "./sdk-contracts.js";
|
|
2
2
|
export { type DaemonError, type DaemonInstallSource, type DaemonRequest, type DaemonResponse, type DaemonResponseData, type JsonRpcId, type JsonRpcRequestEnvelope, type LeaseBackend, type SessionRuntimeHints, centerOfRect, defaultHintForCode, normalizeError };
|
package/dist/src/contracts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{F as e,H as t,y as n}from"./sdk-contracts.js";export{n as centerOfRect,e as defaultHintForCode,t as normalizeError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{M as e}from"./sdk-contracts.js";import{o as t,p as n,r,t as i}from"./lease-scope.js";import{an as a,w as o}from"./sdk-batch.js";import{t as s}from"./catalog.js";import{n as c,r as l}from"./diagnostics.js";import"./diagnostics2.js";import{a as u,l as d}from"./daemon-client-transport.js";const f=new Set([`LEASE_SCOPE_REQUIRED`,`LEASE_SCOPE_MISMATCH`]);function p(t){return r(t)||t instanceof e&&(f.has(t.details?.reason)||t.code===`INVALID_ARGS`)}async function m(e){let{heartbeat:t}=e;if(!t)return await e.task(new AbortController().signal);let n=new AbortController,r=i,a=h(r),o,s=!1,c,u,d=new Promise((e,t)=>{u=t}),f=()=>{let e=e=>{s||(o&&clearTimeout(o),o=setTimeout(f,e))};e(a),(async()=>{let i=r;try{let n=g(await t(i));if(n===void 0||n===r)return;let o=h(n);r=n,a=o,e(o)}catch(e){if(p(e)){if(c=e,s){l({level:`warn`,phase:`lease_lost_after_phase`,data:{message:e instanceof Error?e.message:String(e)}});return}n.abort(),u?.(e);return}l({level:`warn`,phase:`lease_heartbeat_failed`,data:{message:e instanceof Error?e.message:String(e)}})}})().catch(()=>void 0)};o=setTimeout(f,0),d.catch(()=>void 0);let m=await _((async()=>await Promise.race([e.task(n.signal),d]))());if(s=!0,o&&clearTimeout(o),c!==void 0)throw c;if(!m.ok)throw m.error;return m.value}function h(e){return Math.max(1e3,Math.floor(e/3))}function g(e){let t=e?.data?.lease,n=t?.expiresAt,r=t?.heartbeatAt;if(typeof n==`number`&&typeof r==`number`)return n>r?n-r:void 0}async function _(e){try{return{ok:!0,value:await e}}catch(e){return{ok:!1,error:e}}}function v(e,t){return{command:s.leaseHeartbeat,positionals:[],session:t.session,token:t.token,meta:{...n(e),sessionIsolation:t.sessionIsolation,requestId:t.requestId}}}function y(e,n,r){if(!d(e))return;let i=t(r);if(!i.leaseId)return;let l=a(o(s.leaseHeartbeat),{positionals:[]});return async t=>await u(e,v(i,{session:r.session,sessionIsolation:r.meta?.sessionIsolation,requestId:c(),token:e.token}),n.transportPreference,n.paths,l===void 0?t:Math.min(l,t))}export{y as buildUploadLeaseHeartbeat,m as runProtectedLeaseWork};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{K as e,O as t,R as n,W as r,z as i}from"./sdk-contracts.js";import{a,p as o,u as s}from"./lease-scope.js";import{w as c}from"./sdk-batch.js";import{n as l}from"./catalog.js";import{n as u,r as d}from"./diagnostics.js";import{c as f,d as p,p as m}from"./exec.js";import{t as h}from"./timeouts.js";import"./diagnostics2.js";import{r as ee,t as te}from"./output-path.js";import{d as g,i as _,m as v,n as y,p as ne,t as re}from"./transport.js";import"./command.js";import{i as ie}from"./replay-divergence.js";import{o as ae,s as b}from"./device-shell.js";import"./retry.js";import{t as oe}from"./session-repair-tombstone.js";import{a as se,i as ce,o as le,r as ue}from"./version.js";import{t as de}from"./ttl-memo.js";import{n as fe,r as pe,t as me}from"./daemon-resolution.js";import{i as he,n as ge}from"./code-signature.js";import{n as _e,t as x}from"./daemon-process.js";import{n as ve,o as ye,t as be}from"./request-progress-protocol.js";import{t as xe}from"./session-artifact-paths.js";import S from"node:path";import C from"node:fs";import{createHash as Se,randomUUID as Ce}from"node:crypto";import we from"node:os";import{Transform as Te,Writable as Ee}from"node:stream";import{pipeline as w}from"node:stream/promises";import T from"node:net";async function De(e,t){let n=C.statSync(e),r=S.basename(e),i=n.isDirectory(),a=Ae(t)??ke(e,n),o=[];try{let t=i?await Oe(e,o):e,n=C.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await Me(t),sizeBytes:n.size,cleanup:()=>je(o)}}catch(e){throw je(o),e}}async function Oe(e,t){let n=C.mkdtempSync(S.join(we.tmpdir(),`agent-device-upload-${Ce()}-`));t.push(n);let r=S.join(n,`${S.basename(e)}.tar.gz`);return await f(`tar`,[`czf`,r,`-C`,S.dirname(e),S.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function ke(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function Ae(e){return e===`ios`||e===`android`?e:void 0}function je(e){for(let t of e)C.rmSync(t,{recursive:!0,force:!0})}async function Me(e){let n=Se(`sha256`),r=new Ee({write(e,t,r){n.update(e),r()}});return await w(C.createReadStream(e),r).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),n.digest(`hex`)}function Ne(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Ie(i),c=Math.min(i,r+s);return new Te({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function Pe(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Fe(e)}\n`)}}function Fe(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${E(e.totalBytes)}) via ${Le(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${E(e.transferredBytes)} of ${E(e.totalBytes)}`;case`progress`:return`Uploaded ${E(e.transferredBytes)} of ${E(e.totalBytes)} (${Re(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${Le(e.to)} upload`}}function Ie(e){return Math.max(8388608,Math.ceil(e*.05))}function Le(e){return e===`direct`?`direct`:`legacy`}function Re(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function E(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const ze=3e5,Be=`uploadStreamRetryable`;async function Ve(e){return await D({...e,url:e.url,redirectCount:0,startOffset:0})}function He(e){return e instanceof t&&e.details?.[Be]===!0}async function D(e){let n=await y(e.url.protocol),r=C.statSync(e.payloadPath).size,i=We(e.headers,e.startOffset,r);return Ue(e.progress,e.startOffset,r),await new Promise((a,o)=>{let s=!1,c=n.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i},n=>{s=!0,_(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Ge(s)){if(e.redirectCount>=5){o(new t(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let n=new URL(c,e.url);D({...e,url:n,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Ke(s)?qe(n.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new t(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}D({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:n.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new t(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:ze,...e.timeoutHint?{hint:e.timeoutHint}:{},...O(e)}))},ze);c.on(`error`,n=>{s||(clearTimeout(l),o(new t(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...O(e)},n)))}),c.on(`close`,()=>clearTimeout(l)),w(C.createReadStream(e.payloadPath,{start:e.startOffset}),Ne({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??S.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:r,onProgress:e.progress?.onProgress}),c).catch(e=>{if(s)return;c.destroy();let n=e instanceof Error?e:Error(String(e));o(new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function O(e){return e.retryable===!0?{[Be]:!0}:{}}function Ue(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function We(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Ge(e){return[301,302,303,307,308].includes(e)}function Ke(e){return e===308}function qe(e,t){let n=Je(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=k(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function Je(e){let t=k(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function k(e){return Array.isArray(e)?e[0]:e}const A=3e4;async function j(e){let t=await De(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=Ce();try{let i=await N({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Ye({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await M({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await M({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Ye(e){let t=async t=>(await $e(e.artifact,t,e.onProgress),await et({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Xe(n))return;let r=await N({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function Xe(e){return e instanceof t?He(e):!0}async function M(e){let{normalizedBase:n,token:r,artifact:i}=e,a=new URL(`upload`,n),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,g(r));let s=await Ve({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new t(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof t?e:new t(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function N(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,g(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(A),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return Ze(await r.json().catch(()=>void 0))}function Ze(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Qe(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Qe(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function $e(e,n,r){let i=await Ve({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:e.fileName,onProgress:r}});if(i.statusCode<200||i.statusCode>=300)throw new t(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function et(e){let n=new URL(`upload/finalize`,e.normalizedBase),r={"content-type":`application/json`};Object.assign(r,g(e.token));let i=await fetch(n,{method:`POST`,headers:r,signal:AbortSignal.timeout(A),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!i.ok)throw new t(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new t(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function tt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=Pe();if(!_t(t))return P({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});nt(e),r=it(e,n,r,a);let c=await st(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await rt(e,t,n,s)??o),P({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function nt(e){if(e.flags?.saveScript!==void 0)throw new t(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:e.command})}async function rt(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=ot(a,e.meta?.cwd);if(o)return await j({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function it(e,t,n,r){let i=ct(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=at(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function at(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function ot(e,t){let n=S.isAbsolute(e)?e:S.resolve(t??process.cwd(),e);return C.existsSync(n)?n:void 0}function P(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function st(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=S.isAbsolute(i)?i:S.resolve(e.meta?.cwd??process.cwd(),i);if(!C.existsSync(a))return{installSource:{...r,path:a}};let o=await j({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function ct(e,t){if(e.command===`screenshot`){let n=I(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:z(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:z(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!ut(e)&&e.flags?.platform===void 0)return null;let t=F(e),n=dt(I(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:z(`recording`,S.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:lt(e),flagKey:`artifactsDir`,flagPath:ft(`test-artifacts`)}:null}function lt(e){let t=e.flags?.artifactsDir;return L(R(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function F(e){return ee(e.flags?.platform)}function ut(e){return R(e.positionals?.[1])||R(e.flags?.out)}function dt(e,t){return t.flags?.platform===`web`?te(e,F(t)):e}function I(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return L(R(i)?i:a,e.meta?.cwd)}function L(e,t){return S.isAbsolute(e)?e:S.resolve(t??process.cwd(),e)}function R(e){return typeof e==`string`&&e.trim().length>0}function z(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return S.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function ft(e){return S.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function pt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=mt(n,t),o=await ht({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta,isDirectory:n.artifactType===`test-artifacts`});i[n.field]=o,a.push({...n,localPath:o})}return i.artifacts=a,{ok:!0,data:i}}function mt(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return S.resolve(t.meta?.cwd??process.cwd(),r)}async function ht(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(gt(e.baseUrl,e.artifactId)),token:e.token,artifactId:e.artifactId,destinationPath:e.destinationPath,requestScope:e.requestScope,...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs},...e.isDirectory===void 0?{}:{isDirectory:e.isDirectory}})}function gt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function _t(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const vt=de();function yt(){let e=vt.get(`local`);if(e)return e;let n=ue(),r=[S.join(n,`dist`,`src`,`internal`,`daemon.js`),S.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>C.existsSync(e))??i,o=S.join(n,le),s=r.some(e=>C.existsSync(e)),c=C.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return vt.set(`local`,l),l}async function bt(){let e=yt(),t=he(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:ge(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function xt(e,t){let n=se();if(e.version!==n)return e.version&&ce(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=St(await bt(),e);return r?{kind:`replace`,reason:r}:t.viaClientTransport?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function St(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:Ct(e,t):t.codeOrigin===`installed`?Ct(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function Ct(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const wt=3e3,Tt=1e3;function B(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t,r=Et(n);if(!r)return null;let i=Dt(n);return i?{token:r,...i,transport:kt(n.transport),pid:H(n.pid)??0,version:V(n.version),codeOrigin:Ot(n.codeOrigin),codeSignature:V(n.codeSignature),processStartTime:V(n.processStartTime)}:null}function Et(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function Dt(e){let t=H(e.port),n=H(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Ot(e){return e===`installed`||e===`checkout`?e:void 0}function kt(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function V(e){return typeof e==`string`?e:void 0}function H(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function U(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function W(e){It(e)}function G(e){It(e)}function At(e){let t=q(e);if(!t.hasLock||t.hasInfo)return;let n=U(e.lockPath);if(!n){G(e.lockPath);return}x(n.pid,n.processStartTime)||G(e.lockPath)}async function K(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=C.existsSync(e.infoPath),n=B(e.infoPath);if(n){let t=x(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await J(n),i.stoppedInfoProcess=!0),W(e.infoPath),i.removedInfo=!0)}else t&&(W(e.infoPath),i.removedInfo=!0);let a=C.existsSync(e.lockPath),o=U(e.lockPath);if(o){let t=x(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await _e(o.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),G(e.lockPath),i.removedLock=!0)}else a&&(G(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return d({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function q(e){return{hasInfo:C.existsSync(e.infoPath),hasLock:C.existsSync(e.lockPath)}}async function jt(e){let t=q(e);if(!t.hasLock||t.hasInfo)return!1;let n=U(e.lockPath);return!n||!x(n.pid,n.processStartTime)?(G(e.lockPath),!0):!1}async function J(e){await _e(e.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:e.processStartTime})}function Mt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Nt(e,t=me(process.env.AGENT_DEVICE_STATE_DIR)){let n=Pt(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function Pt(e){return`rm -f ${ae(e.infoPath)} ${ae(e.lockPath)}`}function Ft(e){if(!C.existsSync(e))return null;try{return JSON.parse(C.readFileSync(e,`utf8`))}catch{return null}}function It(e){try{C.existsSync(e)&&C.unlinkSync(e)}catch{}}function Y(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function Lt(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(Y(e.req,n,r))}if(be(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return ve(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(Y(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Rt(e,t){return ye(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function zt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=Lt({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=re(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(Y(n,e)))})}function Bt(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=Lt({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=re(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(Y(r,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},e instanceof Error?e:void 0)))})}const Vt=1e4,Ht=8388608;function Ut(e,t){return v(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Wt(e){let{logPath:t,...n}=e;return n}async function Gt(e,t){let n=Wt(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return X(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=xe(t.stateDir,r),a=await Kt({endpoint:t.endpoint,ref:r,destinationPath:e});return a?X(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return X(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function X(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function Kt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Ut(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await y(i.protocol);return await C.promises.mkdir(S.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}C.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...g(t.token),...ne(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=C.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Ht&&(s.destroy(),n.destroy(),o(`record exceeds ${Ht} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${Vt}ms`),s.destroy()},Vt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function qt(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=Jt(e);if(n.error){Yt(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new t(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}$t(r,i,n.result,o,s)}catch(n){s(new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},n instanceof Error?n:void 0))}}function Jt(e){return JSON.parse(e)}async function Yt(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Xt(e);if(!n.baseUrl){a(Qt(s,o));return}a(Qt(await Gt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Xt(e){let t=e.data??{},n=Zt(t.cause);return{code:r(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:n,details:typeof t.details==`object`&&t.details?t.details:void 0,hint:typeof t.hint==`string`?t.hint:void 0,diagnosticId:typeof t.diagnosticId==`string`?t.diagnosticId:void 0,logPath:typeof t.logPath==`string`?t.logPath:void 0,diagnosticsRecord:i(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function Zt(t){return e(t)}function Qt(e,n){return new t(r(e.code,`COMMAND_FAILED`),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,logPathUnavailable:e.logPathUnavailable,diagnosticsRecord:e.diagnosticsRecord,retriable:e.retriable,supportedOn:e.supportedOn,requestId:n},e.cause)}async function $t(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await pt(e,t,n):n)}catch(e){i(e)}}function en(e,t){let n=e.meta?.requestId??u();return tn(e.command)?{jsonrpc:`2.0`,id:n,method:nn(e.command),params:{...rn(e,e.command,t),...e.command===`lease_allocate`?o(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function tn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function nn(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function rn(e,t,n){return s(a(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const an=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],on=new Set([`apple`,`ios`,`macos`]);function sn(e){return e!==void 0&&on.has(e)}function cn(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:o,command:s,platform:c,session:l,action:u}=e,f=i?{terminated:0}:dn(),p=!i&&ln(s),m=p?fn(n,r):{forcedKill:!1},h=sn(c)||f.terminated>0;return d({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:o,command:s,timedOutRunnerPidsTerminated:f.terminated,timedOutRunnerCleanupError:f.error,daemonPidReset:p?n.pid:void 0,daemonPidForceKilled:p?m.forcedKill:void 0,daemonPreservedAfterTimeout:!i&&!p,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:o,hint:un({remote:i,resetDaemon:p,command:s,appleCleanupEvidence:h,session:l,action:u})})}function ln(e){return c(e).onTimeout===`reset-daemon`}function un(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i,session:a,action:o}=e;if(t)return r===l.record&&o===`stop`?`The remote daemon is still exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`:`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&r===l.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function dn(){let e=0;try{for(let t of an)m(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function fn(e,t){let n=!1;try{x(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{J(e)}finally{W(t.infoPath),G(t.lockPath)}return{forcedKill:n}}const pn=`Daemon HTTP endpoint is unavailable`,mn=`Daemon socket endpoint is unavailable`;async function hn(e,t){let n=Tn(e,t);if(await gn(e,n))return!0;let r=En(e,t,n);return r?await gn(e,r):!1}async function gn(e,t){return t===`http`?await vn(e):await _n(e.port)}function _n(e){return e?new Promise(t=>{let n=!1,r=T.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function vn(e){return bn(e).then(e=>e.reachable)}async function yn(e){let n=await bn(e);if(!e.baseUrl||!n.reachable)return n;let r=[n,n.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(r)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:se(),remoteVersion:r.version,remoteService:r.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:r.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return n}async function bn(e){let t=e.baseUrl?v(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await y(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?g(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...xn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function xn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?Sn(t.upstream):void 0;return{...Sn(t),...n?{upstream:n}:{}}}catch{return{}}}function Sn(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0}}async function Cn(e,t,n,r,i,a={}){let o=Tn(e,n);try{return await wn(e,t,r,i,o,a)}catch(s){let c=En(e,n,o);if(!c||!Dn(s,o))throw s;return await wn(e,t,r,i,c,a)}}async function wn(e,t,n,r,i,a){return i===`http`?await Mn(e,t,n,r,a):await An(e,t,n,r,a)}function Tn(e,n){if(e.baseUrl){if(n===`socket`)throw new t(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(n===`http`||n===`socket`)return On(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>Z(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function Z(e,t){return t===`http`?!!e.httpPort:!!e.port}function En(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return Z(e,r)?r:null}function Dn(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function On(e,n){if(Z(e,n))return n;throw new t(`COMMAND_FAILED`,n===`http`?pn:mn)}function kn(e,n,r,i={}){return d({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:e instanceof Error?e.message:String(e)}}),new t(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},e instanceof Error?e:void 0)}async function An(e,n,r,i,a){let o=e.port;if(!o)throw new t(`COMMAND_FAILED`,mn);return new Promise((t,s)=>{let c=!1,l=T.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(n)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(cn({info:e,statePaths:r,...jn(n,!1,i)}))},i):void 0;zt(l,{req:n,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,t(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(kn(e,n.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}function jn(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}async function Mn(e,n,r,i,a){let o=e.baseUrl?new URL(v(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new t(`COMMAND_FAILED`,pn);let s=JSON.stringify(en(n,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&Object.assign(c,g(e.token));let l=await y(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(Rt(n,i.headers?.[`content-type`])){Bt(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:t=>qt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})});return}_(i).then(t=>{m&&clearTimeout(m),qt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0))})}),p=Mt(e),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(cn({info:e,statePaths:r,...jn(n,p,i)}))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(kn(e,n.meta?.requestId,p))}),f.write(s),f.end()})}const Q=15e3,$=new T.BlockList;$.addSubnet(`127.0.0.0`,8,`ipv4`),$.addAddress(`::1`,`ipv6`),$.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function Nn(e,t){let n=Pn(e),r=Fn(e,t),i=In(e,r.remoteBaseUrl),a=Ln(e,n,r.rawBaseUrl),o=a?Rn():n;return{paths:me(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function Pn(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function Fn(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=ir(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return ar(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function In(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=pe(r);if(n&&i===`socket`)throw new t(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:fe(a)}}function Ln(e,t,n){return Zn(e.command)&&!t&&!n}function Rn(){return C.mkdtempSync(S.join(we.tmpdir(),`agent-device-replay-daemon-`))}async function zn(e){if(e.remoteBaseUrl)return await Bn(e);let t=await Vn(e);return t?{info:t,startedByClient:!1}:(At(e.paths),await Kn(e))}async function Bn(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await yn(n)).reachable)return{info:n,startedByClient:!1};throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function Vn(e){let t=B(e.paths.infoPath);if(!t)return null;let n=await Hn(t,e.transportPreference),r=await xt(t,{viaClientTransport:n,onAnyAdvertisedTransport:async()=>n||await Hn(t,`auto`)});if(r.kind===`reuse`)return t;if(r.kind===`refuseNewer`)throw Wn(t,r,e.paths.baseDir);return Gn(t,r.reason,e.paths.baseDir),await J(t),W(e.paths.infoPath),null}async function Hn(e,t){try{return await hn(e,t)}catch(e){if(Un(e))return!1;throw e}}function Un(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Wn(e,n,r){let{daemonVersion:i,clientVersion:a}=n;return new t(`COMMAND_FAILED`,`Daemon (pid ${e.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:e.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${b(r)}`})}function Gn(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function Kn(e){let n=0,r=[],i,a;for(let t=1;t<=2;t+=1){let o;try{o=tr(e),a={pid:o.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await K(e.paths,`start_error`)),t<2){await h(150);continue}break}let s=await er(Q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=nr(s.exit),r.push(await K(e.paths,`start_error`)),t<2){await h(150);continue}break}if(await jt(e.paths)){n+=1;continue}let c=q(e.paths),l=t<2,u=await K(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await er(Q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=nr(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await h(150)}let o=q(e.paths),s=rr(e.paths.logPath);throw new t(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:Q,startupAttempts:2,lockRecoveryCount:n,cleanupResults:r,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:Nt(o,e.paths)})}async function qn(e,t,n,r){if(!Zn(e.command)||!t.startedByClient&&!n.ownedStateDir||Mt(t.info)||Yn(r)||Qn(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await J(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=C.existsSync(n.paths.infoPath);W(n.paths.infoPath),i.removedInfo=e&&!C.existsSync(n.paths.infoPath);let t=C.existsSync(n.paths.lockPath);if(G(n.paths.lockPath),i.removedLock=t&&!C.existsSync(n.paths.lockPath),n.ownedStateDir){let e=oe(n.paths.sessionsDir);e?a=Jn(r,e):(C.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!C.existsSync(n.paths.baseDir))}}return d({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Jn(e,r){if(e&&!e.ok)return e;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,s=`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:n(new t(`REPAIR_COMMIT_FAILED`,s))}}function Yn(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:ie(e.error.details?.divergence)?.repairSessionHeld===!0}function Xn(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Zn(e){return e===l.replay||e===l.test}function Qn(e,t){return e.command!==l.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function $n(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${b(t)}`]:[],...r?[`--session ${b(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function er(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=B(t.paths.infoPath);if(e&&await hn(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await h(100)}return{kind:`timeout`}}function tr(e){let t=yt(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};C.mkdirSync(e.paths.baseDir,{recursive:!0});let i=C.openSync(e.paths.logPath,`a`),a=C.openSync(e.paths.logPath,`a`);try{return p(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{C.closeSync(i),C.closeSync(a)}}function nr(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function rr(e){try{if(!C.existsSync(e))return;let t=C.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=C.openSync(e,`r`);try{let e=Buffer.alloc(n);C.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{C.closeSync(r)}}catch{return}}function ir(e){if(!e)return;let n;try{n=new URL(e)}catch(n){throw new t(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new t(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return n.toString().replace(/\/+$/,``)}function ar(e,n){if(!e)return;let r=new URL(e).hostname;if(!or(r)&&!(typeof n==`string`&&n.trim().length>0))throw new t(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function or(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:T.isIPv4(t)?$.check(t,`ipv4`):T.isIPv6(t)?$.check(t,`ipv6`):!1}export{Qn as a,Cn as c,zn as i,tt as l,Xn as n,Yn as o,qn as r,Nn as s,$n as t};
|
|
1
|
+
import{H as e,M as t}from"./sdk-contracts.js";import{n}from"./catalog.js";import{r}from"./diagnostics.js";import{d as i}from"./exec.js";import{t as a}from"./timeouts.js";import"./diagnostics2.js";import"./command.js";import{c as o,d as s,f as c,h as l,i as u,l as d,m as f,o as p,p as m,r as h,s as ee,u as g}from"./daemon-client-transport.js";import{i as _}from"./replay-divergence.js";import{s as v}from"./device-shell.js";import"./retry.js";import{t as y}from"./session-repair-tombstone.js";import{a as b,i as x,o as te,r as S}from"./version.js";import{t as C}from"./ttl-memo.js";import{n as w,r as T,t as E}from"./daemon-resolution.js";import{i as ne,n as re}from"./code-signature.js";import D from"node:path";import O from"node:fs";import ie from"node:os";import k from"node:net";const A=C();function j(){let e=A.get(`local`);if(e)return e;let n=S(),r=[D.join(n,`dist`,`src`,`internal`,`daemon.js`),D.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>O.existsSync(e))??i,o=D.join(n,te),s=r.some(e=>O.existsSync(e)),c=O.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return A.set(`local`,l),l}async function M(){let e=j(),t=ne(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:re(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function N(e,t){let n=b();if(e.version!==n)return e.version&&x(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=P(await M(),e);return r?{kind:`replace`,reason:r}:t.viaClientTransport?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function P(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:F(e,t):t.codeOrigin===`installed`?F(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function F(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const I=15e3,L=new k.BlockList;L.addSubnet(`127.0.0.0`,8,`ipv4`),L.addAddress(`::1`,`ipv6`),L.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function R(e,t){let n=z(e),r=B(e,t),i=V(e,r.remoteBaseUrl),a=H(e,n,r.rawBaseUrl),o=a?U():n;return{paths:E(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function z(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function B(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=me(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return he(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function V(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=T(r);if(n&&i===`socket`)throw new t(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:w(a)}}function H(e,t,n){return X(e.command)&&!t&&!n}function U(){return O.mkdtempSync(D.join(ie.tmpdir(),`agent-device-replay-daemon-`))}async function ae(e){if(e.remoteBaseUrl)return await W(e);let t=await G(e);return t?{info:t,startedByClient:!1}:(ee(e.paths),await se(e))}async function W(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await u(n)).reachable)return{info:n,startedByClient:!1};throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function G(e){let t=g(e.paths.infoPath);if(!t)return null;let n=await K(t,e.transportPreference),r=await N(t,{viaClientTransport:n,onAnyAdvertisedTransport:async()=>n||await K(t,`auto`)});if(r.kind===`reuse`)return t;if(r.kind===`refuseNewer`)throw J(t,r,e.paths.baseDir);return oe(t,r.reason,e.paths.baseDir),await l(t),c(e.paths.infoPath),null}async function K(e,t){try{return await h(e,t)}catch(e){if(q(e))return!1;throw e}}function q(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function J(e,n,r){let{daemonVersion:i,clientVersion:a}=n;return new t(`COMMAND_FAILED`,`Daemon (pid ${e.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:e.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${v(r)}`})}function oe(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function se(e){let n=0,r=[],i,c;for(let t=1;t<=2;t+=1){let l;try{l=fe(e),c={pid:l.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await p(e.paths,`start_error`)),t<2){await a(150);continue}break}let u=await Q(I,e,l);if(u.kind===`ready`)return{info:u.info,startedByClient:!0};if(u.kind===`early_exit`){if(c=u.exit,i=$(u.exit),r.push(await p(e.paths,`start_error`)),t<2){await a(150);continue}break}if(await s(e.paths)){n+=1;continue}let d=o(e.paths),f=t<2,m=await p(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(m),m.retainedInfoProcess||m.retainedLockProcess){let t=await Q(I,e,l);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(c=t.exit,i=$(t.exit));break}if(!f)break;!d.hasInfo&&!d.hasLock&&await a(150)}let l=o(e.paths),u=pe(e.paths.logPath);throw new t(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:I,startupAttempts:2,lockRecoveryCount:n,cleanupResults:r,startError:i,daemonProcess:c,...u?{daemonLogTail:u}:{},metadataState:l,hint:f(l,e.paths)})}async function ce(e,t,n,i){if(!X(e.command)||!t.startedByClient&&!n.ownedStateDir||d(t.info)||Y(i)||Z(e,i))return i;let a={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},o=i;try{await l(t.info)}catch(e){a.error=e instanceof Error?e.message:String(e)}finally{let e=O.existsSync(n.paths.infoPath);c(n.paths.infoPath),a.removedInfo=e&&!O.existsSync(n.paths.infoPath);let t=O.existsSync(n.paths.lockPath);if(m(n.paths.lockPath),a.removedLock=t&&!O.existsSync(n.paths.lockPath),n.ownedStateDir){let e=y(n.paths.sessionsDir);e?o=le(i,e):(O.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),a.removedStateDir=!O.existsSync(n.paths.baseDir))}}return r({level:a.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:a}),o}function le(n,r){if(n&&!n.ok)return n;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,s=`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:e(new t(`REPAIR_COMMIT_FAILED`,s))}}function Y(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:_(e.error.details?.divergence)?.repairSessionHeld===!0}function ue(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function X(e){return e===n.replay||e===n.test}function Z(e,t){return e.command!==n.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function de(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${v(t)}`]:[],...r?[`--session ${v(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Q(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=g(t.paths.infoPath);if(e&&await h(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await a(100)}return{kind:`timeout`}}function fe(e){let t=j(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};O.mkdirSync(e.paths.baseDir,{recursive:!0});let a=O.openSync(e.paths.logPath,`a`),o=O.openSync(e.paths.logPath,`a`);try{return i(process.execPath,n,{env:r,stdio:[`ignore`,a,o]})}finally{O.closeSync(a),O.closeSync(o)}}function $(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function pe(e){try{if(!O.existsSync(e))return;let t=O.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=O.openSync(e,`r`);try{let e=Buffer.alloc(n);O.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{O.closeSync(r)}}catch{return}}function me(e){if(!e)return;let n;try{n=new URL(e)}catch(n){throw new t(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new t(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return n.toString().replace(/\/+$/,``)}function he(e,n){if(!e)return;let r=new URL(e).hostname;if(!ge(r)&&!(typeof n==`string`&&n.trim().length>0))throw new t(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function ge(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:k.isIPv4(t)?L.check(t,`ipv4`):k.isIPv6(t)?L.check(t,`ipv6`):!1}export{Z as a,ae as i,ue as n,Y as o,ce as r,R as s,de as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{M as e,U as t,Y as n,Z as r}from"./sdk-contracts.js";import{d as i,m as a,o}from"./lease-scope.js";import{w as s}from"./sdk-batch.js";import{n as c}from"./catalog.js";import{n as l,r as u}from"./diagnostics.js";import{c as d,p as f}from"./exec.js";import"./diagnostics2.js";import{r as p,t as m}from"./output-path.js";import{d as h,i as ee,m as g,n as _,p as te,t as v}from"./transport.js";import"./command.js";import{o as y}from"./device-shell.js";import{a as ne}from"./version.js";import{t as re}from"./daemon-resolution.js";import{n as ie,t as b}from"./daemon-process.js";import{n as ae,o as oe,t as se}from"./request-progress-protocol.js";import{t as ce}from"./session-artifact-paths.js";import x from"node:path";import S from"node:fs";import{createHash as le,randomUUID as C}from"node:crypto";import ue from"node:os";import{Transform as de,Writable as fe}from"node:stream";import{pipeline as w}from"node:stream/promises";import T from"node:net";async function pe(e,t){let n=S.statSync(e),r=x.basename(e),i=n.isDirectory(),a=ge(t)??he(e,n),o=[];try{let t=i?await me(e,o):e,n=S.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await _e(t),sizeBytes:n.size,cleanup:()=>E(o)}}catch(e){throw E(o),e}}async function me(e,t){let n=S.mkdtempSync(x.join(ue.tmpdir(),`agent-device-upload-${C()}-`));t.push(n);let r=x.join(n,`${x.basename(e)}.tar.gz`);return await d(`tar`,[`czf`,r,`-C`,x.dirname(e),x.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function he(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function ge(e){return e===`ios`||e===`android`?e:void 0}function E(e){for(let t of e)S.rmSync(t,{recursive:!0,force:!0})}async function _e(t){let n=le(`sha256`),r=new fe({write(e,t,r){n.update(e),r()}});return await w(S.createReadStream(t),r).catch(t=>{throw new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},t instanceof Error?t:void 0)}),n.digest(`hex`)}function ve(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=xe(i),c=Math.min(i,r+s);return new de({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function ye(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${be(e)}\n`)}}function be(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${O(e.totalBytes)}) via ${D(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${O(e.transferredBytes)} of ${O(e.totalBytes)}`;case`progress`:return`Uploaded ${O(e.transferredBytes)} of ${O(e.totalBytes)} (${Se(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${D(e.to)} upload`}}function xe(e){return Math.max(8388608,Math.ceil(e*.05))}function D(e){return e===`direct`?`direct`:`legacy`}function Se(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function O(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const Ce=3e5,we=`uploadStreamRetryable`;async function Te(e){return await k({...e,url:e.url,redirectCount:0,startOffset:0})}function Ee(t){return t instanceof e&&t.details?.[we]===!0}async function k(t){let n=await _(t.url.protocol),r=S.statSync(t.payloadPath).size,i=ke(t.headers,t.startOffset,r);return Oe(t.progress,t.startOffset,r),await new Promise((a,o)=>{let s=!1,c=n.request({protocol:t.url.protocol,host:t.url.hostname,port:t.url.port,method:t.method,path:t.url.pathname+t.url.search,headers:i,...t.signal?{signal:t.signal}:{}},n=>{s=!0,ee(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Ae(s)){if(t.redirectCount>=5){o(new e(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:t.url.toString()}));return}let n=new URL(c,t.url);k({...t,url:n,redirectCount:t.redirectCount+1}).then(a,o);return}let u=je(s)?Me(n.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=t.startOffset){o(new e(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:t.startOffset,url:t.url.toString()}));return}k({...t,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:n.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new e(`COMMAND_FAILED`,t.timeoutMessage,{timeoutMs:Ce,...t.timeoutHint?{hint:t.timeoutHint}:{},...De(t)}))},Ce);c.on(`error`,n=>{if(!s){if(clearTimeout(l),t.signal?.aborted){o(t.signal.reason);return}o(new e(`COMMAND_FAILED`,t.errorMessage,{...t.errorHint?{hint:t.errorHint}:{},...De(t)},n))}}),c.on(`close`,()=>clearTimeout(l)),w(S.createReadStream(t.payloadPath,{start:t.startOffset}),ve({stage:t.progress?.stage??`legacy`,fileName:t.progress?.fileName??x.basename(t.payloadPath),startOffset:t.startOffset,totalBytes:r,onProgress:t.progress?.onProgress}),c).catch(t=>{if(s)return;c.destroy();let n=t instanceof Error?t:Error(String(t));o(new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function De(e){return e.retryable===!0?{[we]:!0}:{}}function Oe(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function ke(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Ae(e){return[301,302,303,307,308].includes(e)}function je(e){return e===308}function Me(e,t){let n=Ne(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Pe(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function Ne(e){let t=Pe(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Pe(e){return Array.isArray(e)?e[0]:e}const Fe=3e4;async function Ie(e){let t=await pe(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=C();try{let i=await A({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r,signal:e.signal});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Le({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress,signal:e.signal})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await Be({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})):await Be({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})}finally{t.cleanup()}}async function Le(e){let t=async t=>(await Ue(e.artifact,t,e.onProgress,e.signal),await We({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId,signal:e.signal}));try{return await t(e.preflight)}catch(n){if(e.signal?.aborted)throw n;return ze(n)?await Re(e,t):void 0}}async function Re(e,t){let n=await A({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId,signal:e.signal});if(n?.kind===`cache-hit`)return n.uploadId;if(n?.kind===`direct-upload`)try{return await t(n)}catch{return}}function ze(t){return t instanceof e?Ee(t):!0}async function Be(t){let{normalizedBase:n,token:r,artifact:i}=t,a=new URL(`upload`,n),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,h(r));let s=await Te({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,signal:t.signal,progress:{stage:`legacy`,fileName:i.fileName,onProgress:t.onProgress}});try{let t=JSON.parse(s.body);if(!t.ok||!t.uploadId)throw new e(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return t.uploadId}catch(t){throw t instanceof e?t:new e(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function A(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,h(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:j(e.signal,Fe),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(t=>{if(e.signal?.aborted)throw t});if(r?.ok)return Ve(await r.json().catch(()=>void 0))}function j(e,t){let n=AbortSignal.timeout(t);return e?AbortSignal.any([e,n]):n}function Ve(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(He(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function He(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Ue(t,n,r,i){let a=await Te({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:t.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,signal:i,progress:{stage:`direct`,fileName:t.fileName,onProgress:r}});if(a.statusCode<200||a.statusCode>=300)throw new e(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function We(t){let n=new URL(`upload/finalize`,t.normalizedBase),r={"content-type":`application/json`};Object.assign(r,h(t.token));let i=await fetch(n,{method:`POST`,headers:r,signal:j(t.signal,Fe),body:JSON.stringify({uploadId:t.uploadId})}).catch(n=>{throw t.signal?.aborted?n:new e(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},n)});if(!i.ok)throw new e(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new e(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Ge(e,t,n){let r=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,a=e.meta?.installSource,o={},s,c=ye();if(!st(t))return M({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o});Ke(e),i=Je(e,r,i,o);let l=await Ze(e,t,c,n);return l&&(a=l.installSource,s=l.uploadedArtifactId??s),e.command!==`install`&&e.command!==`reinstall`||(s=await qe(e,t,r,c,n)??s),M({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o})}function Ke(t){if(t.flags?.saveScript!==void 0)throw new e(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:t.command})}async function qe(e,t,n,r,i){let a=n.length===1?0:1,o=n[a];if(o===void 0)return;if(o.startsWith(`remote:`)){n[a]=o.slice(7);return}let s=Xe(o,e.meta?.cwd);if(s)return await Ie({localPath:s,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r,signal:i})}function Je(e,t,n,r){let i=Qe(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=Ye(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function Ye(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function Xe(e,t){let n=x.isAbsolute(e)?e:x.resolve(t??process.cwd(),e);return S.existsSync(n)?n:void 0}function M(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function Ze(e,t,n,r){let i=e.meta?.installSource;if(e.command!==`install_source`||!i||i.kind!==`path`)return null;let a=i.path.trim();if(!a)return{installSource:i};if(a.startsWith(`remote:`))return{installSource:{...i,path:a.slice(7)}};let o=x.isAbsolute(a)?a:x.resolve(e.meta?.cwd??process.cwd(),a);if(!S.existsSync(o))return{installSource:{...i,path:o}};let s=await Ie({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n,signal:r});return{installSource:{...i,path:o},uploadedArtifactId:s}}function Qe(e,t){if(e.command===`screenshot`){let n=P(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:L(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:L(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!et(e)&&e.flags?.platform===void 0)return null;let t=N(e),n=tt(P(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:L(`recording`,x.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:$e(e),flagKey:`artifactsDir`,flagPath:nt(`test-artifacts`)}:null}function $e(e){let t=e.flags?.artifactsDir;return F(I(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function N(e){return p(e.flags?.platform)}function et(e){return I(e.positionals?.[1])||I(e.flags?.out)}function tt(e,t){return t.flags?.platform===`web`?m(e,N(t)):e}function P(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return F(I(i)?i:a,e.meta?.cwd)}function F(e,t){return x.isAbsolute(e)?e:x.resolve(t??process.cwd(),e)}function I(e){return typeof e==`string`&&e.trim().length>0}function L(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return x.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function nt(e){return x.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function rt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=it(n,t),o=await at({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta,isDirectory:n.artifactType===`test-artifacts`});i[n.field]=o,a.push({...n,localPath:o})}return i.artifacts=a,{ok:!0,data:i}}function it(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return x.resolve(t.meta?.cwd??process.cwd(),r)}async function at(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(ot(e.baseUrl,e.artifactId)),token:e.token,artifactId:e.artifactId,destinationPath:e.destinationPath,requestScope:e.requestScope,...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs},...e.isDirectory===void 0?{}:{isDirectory:e.isDirectory}})}function ot(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function st(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const R=3e3,z=1e3;function B(e){let t=vt(e);if(!t||typeof t!=`object`)return null;let n=t,r=ct(n);if(!r)return null;let i=lt(n);return i?{token:r,...i,transport:dt(n.transport),pid:H(n.pid)??0,version:V(n.version),codeOrigin:ut(n.codeOrigin),codeSignature:V(n.codeSignature),processStartTime:V(n.processStartTime)}:null}function ct(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function lt(e){let t=H(e.port),n=H(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function ut(e){return e===`installed`||e===`checkout`?e:void 0}function dt(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function V(e){return typeof e==`string`?e:void 0}function H(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function U(e){let t=vt(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function W(e){yt(e)}function G(e){yt(e)}function ft(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let n=U(e.lockPath);if(!n){G(e.lockPath);return}b(n.pid,n.processStartTime)||G(e.lockPath)}async function pt(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=S.existsSync(e.infoPath),n=B(e.infoPath);if(n){let t=b(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await q(n),i.stoppedInfoProcess=!0),W(e.infoPath),i.removedInfo=!0)}else t&&(W(e.infoPath),i.removedInfo=!0);let a=S.existsSync(e.lockPath),o=U(e.lockPath);if(o){let t=b(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await ie(o.pid,{termTimeoutMs:R,killTimeoutMs:z,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),G(e.lockPath),i.removedLock=!0)}else a&&(G(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return u({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function K(e){return{hasInfo:S.existsSync(e.infoPath),hasLock:S.existsSync(e.lockPath)}}async function mt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let n=U(e.lockPath);return!n||!b(n.pid,n.processStartTime)?(G(e.lockPath),!0):!1}async function q(e){await ie(e.pid,{termTimeoutMs:R,killTimeoutMs:z,expectedStartTime:e.processStartTime})}function ht(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function gt(e,t=re(process.env.AGENT_DEVICE_STATE_DIR)){let n=_t(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function _t(e){return`rm -f ${y(e.infoPath)} ${y(e.lockPath)}`}function vt(e){if(!S.existsSync(e))return null;try{return JSON.parse(S.readFileSync(e,`utf8`))}catch{return null}}function yt(e){try{S.existsSync(e)&&S.unlinkSync(e)}catch{}}function J(t,n,r){return new e(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:t.meta?.requestId,line:n},r instanceof Error?r:void 0)}function bt(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(J(e.req,n,r))}if(se(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return ae(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(J(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function xt(e,t){return oe(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function St(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=bt({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=v(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(J(n,e)))})}function Ct(t,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=bt({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});t.setEncoding(`utf8`),t.on(`data`,e=>{if(c)return;let t=v(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),t.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(J(r,e)))}),t.on(`error`,t=>{c||(c=!0,o(),a(new e(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},t instanceof Error?t:void 0)))})}const wt=1e4,Tt=8388608;function Et(e,t){return g(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Dt(e){let{logPath:t,...n}=e;return n}async function Ot(e,t){let n=Dt(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return Y(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=ce(t.stateDir,r),a=await kt({endpoint:t.endpoint,ref:r,destinationPath:e});return a?Y(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return Y(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function Y(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function kt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Et(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await _(i.protocol);return await S.promises.mkdir(x.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}S.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...h(t.token),...te(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=S.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Tt&&(s.destroy(),n.destroy(),o(`record exceeds ${Tt} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${wt}ms`),s.destroy()},wt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function At(t,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=jt(t);if(n.error){Mt(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new e(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}It(r,i,n.result,o,s)}catch(n){s(new e(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:t},n instanceof Error?n:void 0))}}function jt(e){return JSON.parse(e)}async function Mt(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Nt(e);if(!n.baseUrl){a(Ft(s,o));return}a(Ft(await Ot(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Nt(e){let r=e.data??{},i=Pt(r.cause);return{code:n(r.code==null?void 0:String(r.code),`COMMAND_FAILED`),message:String(r.message??e.message??`Daemon RPC request failed`),cause:i,details:typeof r.details==`object`&&r.details?r.details:void 0,hint:typeof r.hint==`string`?r.hint:void 0,diagnosticId:typeof r.diagnosticId==`string`?r.diagnosticId:void 0,logPath:typeof r.logPath==`string`?r.logPath:void 0,diagnosticsRecord:t(r.diagnosticsRecord),retriable:typeof r.retriable==`boolean`?r.retriable:void 0,supportedOn:typeof r.supportedOn==`string`?r.supportedOn:void 0}}function Pt(e){return r(e)}function Ft(t,r){return new e(n(t.code,`COMMAND_FAILED`),t.message,{...t.details??{},hint:t.hint,diagnosticId:t.diagnosticId,logPath:t.logPath,logPathUnavailable:t.logPathUnavailable,diagnosticsRecord:t.diagnosticsRecord,retriable:t.retriable,supportedOn:t.supportedOn,requestId:r},t.cause)}async function It(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await rt(e,t,n):n)}catch(e){i(e)}}function Lt(e,t){let n=e.meta?.requestId??l();return Rt(e.command)?{jsonrpc:`2.0`,id:n,method:zt(e.command),params:{...Bt(e,e.command,t),...e.command===`lease_allocate`?a(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Rt(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function zt(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Bt(e,t,n){return i(o(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Vt=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],Ht=new Set([`apple`,`ios`,`macos`]);function Ut(e){return e!==void 0&&Ht.has(e)}function Wt(t){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:o,command:s,platform:c,session:l,action:d}=t,f=i?{terminated:0}:qt(),p=!i&&Gt(s),m=p?Jt(n,r):{forcedKill:!1},h=Ut(c)||f.terminated>0;return u({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:o,command:s,timedOutRunnerPidsTerminated:f.terminated,timedOutRunnerCleanupError:f.error,daemonPidReset:p?n.pid:void 0,daemonPidForceKilled:p?m.forcedKill:void 0,daemonPreservedAfterTimeout:!i&&!p,daemonBaseUrl:n.baseUrl}}),new e(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:o,hint:Kt({remote:i,resetDaemon:p,command:s,appleCleanupEvidence:h,session:l,action:d})})}function Gt(e){return s(e).onTimeout===`reset-daemon`}function Kt(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i,session:a,action:o}=e;if(t)return r===c.record&&o===`stop`?`The remote daemon is still exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`:`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&r===c.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function qt(){let e=0;try{for(let t of Vt)f(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function Jt(e,t){let n=!1;try{b(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{q(e)}finally{W(t.infoPath),G(t.lockPath)}return{forcedKill:n}}const X=`Daemon HTTP endpoint is unavailable`,Z=`Daemon socket endpoint is unavailable`;async function Yt(e,t){let n=on(e,t);if(await Xt(e,n))return!0;let r=$(e,t,n);return r?await Xt(e,r):!1}async function Xt(e,t){return t===`http`?await Qt(e):await Zt(e.port)}function Zt(e){return e?new Promise(t=>{let n=!1,r=T.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function Qt(e){return en(e).then(e=>e.reachable)}async function $t(t){let n=await en(t);if(!t.baseUrl||!n.reachable)return n;let r=[n,n.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(r)throw new e(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:t.baseUrl,clientVersion:ne(),remoteVersion:r.version,remoteService:r.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:r.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return n}async function en(e){let t=e.baseUrl?g(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await _(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?h(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...tn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function tn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?nn(t.upstream):void 0;return{...nn(t),...n?{upstream:n}:{}}}catch{return{}}}function nn(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0}}async function rn(e,t,n,r,i,a={}){let o=on(e,n);try{return await an(e,t,r,i,o,a)}catch(s){let c=$(e,n,o);if(!c||!sn(s,o))throw s;return await an(e,t,r,i,c,a)}}async function an(e,t,n,r,i,a){return i===`http`?await fn(e,t,n,r,a):await un(e,t,n,r,a)}function on(t,n){if(t.baseUrl){if(n===`socket`)throw new e(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:t.baseUrl});return`http`}if(n===`http`||n===`socket`)return cn(t,n);let r=(t.transport===`socket`||t.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(e=>Q(t,e));if(r)return r;throw new e(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function Q(e,t){return t===`http`?!!e.httpPort:!!e.port}function $(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return Q(e,r)?r:null}function sn(t,n){return n===`socket`&&t instanceof e&&t.code===`COMMAND_FAILED`&&t.message===`Failed to communicate with daemon`&&t.details?.daemonSocketRequestWritten===!1}function cn(t,n){if(Q(t,n))return n;throw new e(`COMMAND_FAILED`,n===`http`?X:Z)}function ln(t,n,r,i={}){return u({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:t instanceof Error?t.message:String(t)}}),new e(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},t instanceof Error?t:void 0)}async function un(t,n,r,i,a){let o=t.port;if(!o)throw new e(`COMMAND_FAILED`,Z);return new Promise((e,s)=>{let c=!1,l=T.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(n)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(Wt({info:t,statePaths:r,...dn(n,!1,i)}))},i):void 0;St(l,{req:n,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:t=>{u=!0,e(t)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(ln(e,n.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}function dn(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}async function fn(t,n,r,i,a){let o=t.baseUrl?new URL(g(t.baseUrl,`rpc`)):t.httpPort?new URL(`http://127.0.0.1:${t.httpPort}/rpc`):null;if(!o)throw new e(`COMMAND_FAILED`,X);let s=JSON.stringify(Lt(n,{includeTokenParam:!t.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};t.baseUrl&&Object.assign(c,h(t.token));let l=await _(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(xt(n,i.headers?.[`content-type`])){Ct(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:e=>At(e,{info:t,req:n,stateDir:r.baseDir,resolve:u,reject:d})});return}ee(i).then(e=>{m&&clearTimeout(m),At(e,{info:t,req:n,stateDir:r.baseDir,resolve:u,reject:d})}).catch(t=>{m&&clearTimeout(m),d(new e(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},t instanceof Error?t:void 0))})}),p=ht(t),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(Wt({info:t,statePaths:r,...dn(n,p,i)}))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(ln(e,n.meta?.requestId,p))}),f.write(s),f.end()})}export{rn as a,K as c,mt as d,W as f,Ge as g,q as h,$t as i,ht as l,gt as m,Z as n,pt as o,G as p,Yt as r,ft as s,X as t,B as u};
|