agent-device 0.21.0 → 0.21.1
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.0.apk → agent-device-android-ime-helper-0.21.1.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.1.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.0.manifest.json → agent-device-android-ime-helper-0.21.1.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.0.apk → agent-device-android-snapshot-helper-0.21.1.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.1.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.0.manifest.json → agent-device-android-snapshot-helper-0.21.1.manifest.json} +6 -6
- package/apple/snapshot-bridge/README.md +58 -1
- package/apple/snapshot-bridge/SnapshotBridge.m +6 -0
- package/apple/snapshot-bridge/SnapshotBridgeCapture.h +25 -0
- package/apple/snapshot-bridge/SnapshotBridgeCapture.m +138 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +1 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +32 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +15 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +72 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +63 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +668 -82
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +14 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +39 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1065 -223
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +290 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +10 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +249 -61
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +101 -42
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -13
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +51 -43
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +71 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +144 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +13 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +216 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +206 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +289 -42
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +92 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +617 -122
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +79 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +71 -71
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +83 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +67 -67
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +17 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +30 -30
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +31 -31
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +101 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +19 -19
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +55 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +26 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +125 -75
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +9 -9
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +9 -9
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +4 -4
- 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/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +1 -1
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-input-ownership.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-contract.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +2 -2
- package/dist/src/app-lifecycle.js +3 -3
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apple-runner-platform.js +1 -0
- 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.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +25 -21
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +4 -4
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +27 -13
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-tools.js +2 -2
- package/dist/src/command.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-rule.js +1 -1
- 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/device2.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor2.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/generic-settle.js +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +2 -2
- package/dist/src/install-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.js +5 -5
- 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 +2 -2
- 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-runtime.js +1 -1
- package/dist/src/ios-system-surface.js +1 -0
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +1 -1
- 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 +16 -16
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/observation.js +1 -1
- package/dist/src/open-target-resolution.js +1 -0
- package/dist/src/owner-identity.js +3 -3
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +2 -2
- package/dist/src/perf-process-identity.js +1 -0
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.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 +2 -2
- package/dist/src/platform-runtime-runtime-hints.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-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-worker-contract.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/provider-device-runtime.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/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +37 -36
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +9 -8
- 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/retry.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- 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 +3 -3
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -4
- 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-live-handle.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/screenshot-density.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +3 -3
- package/dist/src/script.js +1 -1
- 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 +44 -1
- 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.d.ts +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +69 -13
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-observation.js +1 -0
- 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-target-evidence.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-quality-backend-capabilities.js +1 -1
- package/dist/src/snapshot-quality-verdict.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/src7.js +2 -2
- package/dist/src/src8.js +2 -2
- package/dist/src/string-enum.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/tool-provider.js +2 -2
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/toolchain-probe.js +1 -1
- package/dist/src/touch-reference-frame.js +1 -0
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/transport.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/video.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/dist/src/window-state.js +1 -0
- package/package.json +3 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.0.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk.sha256 +0 -1
- package/dist/src/back-mode.js +0 -1
- package/dist/src/format.js +0 -2
- package/dist/src/platform-runtime-apple-resources.js +0 -1
- package/dist/src/runner-selector-query.js +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{A as e,O as t,j as n,n as r,y as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{C as s,S as c,_ as l,b as u,g as d,h as f,y as ee}from"./registry.js";import{i as p,t as m}from"./sdk-device.js";import{C as te,c as ne,f as h,u as re,x as ie}from"./sdk-batch.js";import{t as ae}from"./back-mode.js";import{t as oe}from"./session.js";import"./device.js";import{t as se}from"./device-rotation.js";import{t as ce}from"./tv-remote.js";import{i as le,n as g,r as ue,t as _}from"./command-metadata.js";import{r as de}from"./replay-divergence.js";import{t as fe}from"./cli-output.js";import{n as pe,r as me,t as v}from"./cli-config.js";import{n as he}from"./result-serialization.js";const y=[`simulator`,`emulator`,`device`];function b(e){return{type:`number`,...e?{description:e}:{}}}function x(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function S(e){return{type:`string`,const:e}}function C(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function w(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const T={type:`array`,items:{type:`string`}},E=w({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=w({field:l(),artifactType:l(),path:l(),localPath:l(),fileName:l()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return w({targetKind:x([`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:l(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:l(`Selector expression when the target was a selector.`),selectorChain:T,refLabel:l(),targetHittable:f(),hint:l(),warning:l(),message:l(),evidence:A,resolution:ge,cost:E,maestroNonHittableCoordinateFallbackAllowed:f(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:f(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:S(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=w({diagnosticRef:l(`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:l(`UTF-8 truncated to 256 bytes.`),label:l(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),ge={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`unique`)},[`source`,`phase`,`kind`]),w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:x([`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`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`exact`)},[`source`,`phase`,`kind`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`label-fallback`)},[`source`,`phase`,`kind`]),w({source:S(`direct-ios`),kind:S(`not-observed`)},[`source`,`kind`])]},A=w({foregroundApp:l(`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:l(`Order-independent digest of the post-action node multiset.`),changedFromBefore:f(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure.`)},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),_e=w({settled:f(`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:w({ref:l(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:l(),ref:l(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:f(`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:w({ref:l(`Plain ref body (e12) minted from the stored settled tree.`),role:l(),label:l()},[`ref`,`role`])},tailTruncated:f(`Present (true) when tail candidates exceeded the response cap.`),hint:l()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),j={platform:x(p),target:x(m),device:l(`Human-readable device name.`),id:l(`Stable device id.`),kind:x(y)},M=[`platform`,`target`,`device`,`id`,`kind`],ve=w({success:f(),exitCode:b(),stdout:l(),stderr:l(),error:d(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function N(e){return e.oneOf?{...e,oneOf:e.oneOf.map(N)}:{...e,properties:{...e.properties??{},settle:_e}}}function ye(e){let t={...e};for(let e of Object.keys(t))h(e)&&(t[e]=N(t[e]));return t}const P=O({properties:{evidence:A,button:x([`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:f(`Whether the command requested a double-tap action.`)}}),F={text:l(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:A},be=w({resourceId:C(`Android resource id of the exact field that changed.`),className:C(`Android class name of the exact field that changed.`),packageName:C(`Android package name that owns the exact field.`),rect:w({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.`),xe=ye({press:P,click:P,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:F,required:[`text`]}),not:w({},[`verification`])},O({properties:{...F,verification:S(`unconfirmed`),requested:l(`Literal text requested by the fill command.`),before:C(`Raw target text captured before the fill.`),after:C(`Raw target text captured after the fill.`),target:be},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:S(`longpress`)}}),hover:O({properties:{gesture:S(`hover`)}}),find:w({ref:l(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:f(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:l(`Text value returned by find get_text.`),node:d(`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:d(`One listed match with its snapshot ref and node.`)},locator:l(`Locator kind used for the find action.`),query:l(`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:l(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:w({...j,booted:{type:`boolean`,const:!0}},[...M,`booted`]),shutdown:w({...j,shutdown:ve},[...M,`shutdown`]),viewport:w({width:b(),height:b(),message:l()},[`width`,`height`,`message`]),back:w({action:S(`back`),mode:x(ae),message:l()},[`action`,`mode`,`message`]),home:w({action:S(`home`),message:l()},[`action`,`message`]),orientation:w({action:S(`orientation`),orientation:x(se),message:l()},[`action`,`orientation`,`message`]),"app-switcher":w({action:S(`app-switcher`),message:l()},[`action`,`message`]),"tv-remote":w({action:S(`tv-remote`),button:x(ce),durationMs:b(),message:l()},[`action`,`button`,`message`]),wait:w({waitedMs:b(),kind:S(`selector`),text:l(),selector:l(),captures:b(),nodeCount:b(),hint:l(),warning:l()},[`waitedMs`]),scroll:w({direction:x([`up`,`down`,`left`,`right`]),edge:x([`top`,`bottom`]),passes:b(`Edge scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:l()},[`direction`]),prepare:w({action:S(`ios-runner`),platform:x(p),deviceId:l(),deviceName:l(),kind:x(y),durationMs:b(),runner:w({},[]),cache:x([`exact`,`restore-key`,`miss`,`external`]),artifact:x([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:l(),recoveryReason:l(),failureReason:l(),timing:w({totalMs:b(),additiveParts:w({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:w({connectMs:{type:`array`,items:S(`buildMs`)},healthCheckMs:{type:`array`,items:l()}},[`healthCheckMs`]),note:l()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:l()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[w({platform:S(`ios`),bundleId:l(),message:l()},[`platform`,`bundleId`,`message`]),w({platform:S(`android`),package:l(),action:l(),extrasCount:b(),message:l()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":w({event:l(),eventUrl:l(),transport:S(`deep-link`),message:l()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[w({action:S(`read`),text:l()},[`action`,`text`]),w({action:S(`write`),textLength:b(),message:l()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[w({platform:x([`ios`,`macos`]),appName:l(),appBundleId:l(),source:S(`session`),surface:x(oe),device_udid:l(`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`]),w({platform:S(`android`),package:l(),activity:l()},[`platform`,`package`,`activity`])]},keyboard:w({platform:x([`android`,`ios`]),action:x([`status`,`dismiss`,`enter`]),visible:f(),wasVisible:f(),dismissed:f(),attempts:b(),inputType:l(),type:x([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:l(),focusedPackage:l(),focusedResourceId:l(),inputOwner:x([`app`,`ime`,`unknown`]),message:l()},[`platform`,`action`]),doctor:w({status:x([`pass`,`warn`,`fail`,`info`]),summary:l(),kind:x([`auto`,`react-native`,`expo`,`repack`]),platform:l(),target:x(m),targetApp:l(),metro:w({host:l(),port:b()},[`host`,`port`]),checks:{type:`array`,items:w({id:l(),status:x([`pass`,`warn`,`fail`,`info`]),summary:l(),hint:l(),command:l(),evidence:d()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:w({mode:S(`snapshot`),baselineInitialized:f(),summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:l(),ref:l()},[`kind`,`text`])},warnings:T},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:w({replayed:b(),healed:b(),session:l(),sessionActive:f(`True iff the session is still active — the script had no terminal close.`),artifactPaths:T,snapshotDiagnostics:d(),message:l()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:w({total:b(),executed:b(),passed:b(),failed:b(),skipped:b(),notRun:b(),durationMs:b(),failures:{type:`array`,items:d()},tests:{type:`array`,items:d()},snapshotDiagnostics:d()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[w({recording:S(`started`),outPath:l(),sessionStateDir:l(),recordingBackend:l(),recordingScope:l(),recordOnlySession:f(),activeSessionApp:d(),showTouches:f()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:S(`stopped`),outPath:l(),telemetryPath:l(),artifacts:{type:`array`,items:D},recordingBackend:l(),recordingScope:l(),recordOnlySession:f(),activeSessionApp:d(),durationMs:b(),showTouches:f(),warning:l(),overlayWarning:l(),chunks:{type:`array`,items:d()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:S(`started`),outPath:l()},[`trace`,`outPath`]),w({trace:S(`stopped`),outPath:l(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]}}),Se={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:p},target:{type:`string`,enum:m},kind:{type:`string`,enum:y},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`]}},I={...xe,...Se},Ce={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:c({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.`}}},L=Object.entries(Ce),R=new Set(L.map(([e])=>e)),we=Object.fromEntries(L.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Te(){return Object.fromEntries(L.map(([e,t])=>[e,t.schema]))}function z(e){return t(e)}function B(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}`),t.push(...Ee(n(e.details))),e.supportedOn&&t.push(`Supported on: ${e.supportedOn}`);let r=de(e.details);return r&&t.push(r),t.join(`
|
|
2
|
-
`)}function
|
|
1
|
+
import{C as e,F as t,M as n,P as r,n as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{C as s,_ as c,b as l,g as u,s as d,v as f,w as ee,x as te}from"./registry.js";import{i as p,t as m}from"./sdk-device.js";import{C as ne,c as re,f as h,u as ie,x as ae}from"./sdk-batch.js";import{t as oe}from"./session.js";import"./device.js";import{t as se}from"./device-rotation.js";import{t as ce}from"./tv-remote.js";import{i as le,n as g,r as ue,t as _}from"./command-metadata.js";import{r as de}from"./replay-divergence.js";import{t as fe}from"./cli-output.js";import{n as pe,r as me,t as he}from"./cli-config.js";import{n as ge}from"./result-serialization.js";const v=[`simulator`,`emulator`,`device`];function y(e){return{type:`number`,...e?{description:e}:{}}}function b(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function x(e){return{type:`string`,const:e}}function S(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function C(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const w={type:`array`,items:{type:`string`}},T=C({wallClockMs:y(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:y(`Number of real runner round-trips made while serving the request.`),nodeCount:y(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),E=C({field:f(),artifactType:f(),path:f(),localPath:f(),fileName:f()},[`field`]);function D(e={}){let t=e.properties??{},n=e.required??[];return C({targetKind:b([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:y(`Resolved interaction x coordinate when available.`),y:y(`Resolved interaction y coordinate when available.`),referenceWidth:y(`Reference frame width for visualizing the interaction point.`),referenceHeight:y(`Reference frame height for visualizing the interaction point.`),ref:f(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:f(`Selector expression when the target was a selector.`),selectorChain:w,refLabel:f(),targetHittable:u(),hint:f(),warning:f(),message:f(),evidence:A,resolution:_e,cost:T,maestroNonHittableCoordinateFallbackAllowed:u(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:u(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:x(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const O=C({diagnosticRef:f(`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:f(`UTF-8 truncated to 256 bytes.`),label:f(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),_e={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[C({source:x(`runtime`),phase:x(`pre-action`),kind:x(`unique`)},[`source`,`phase`,`kind`]),C({source:x(`runtime`),phase:x(`pre-action`),kind:x(`disambiguated`),matchCount:y(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:O,tiebreak:b([`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:O}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),C({source:x(`ref`),phase:x(`pre-action`),kind:x(`exact`)},[`source`,`phase`,`kind`]),C({source:x(`ref`),phase:x(`pre-action`),kind:x(`label-fallback`)},[`source`,`phase`,`kind`]),C({source:x(`direct-ios`),kind:x(`not-observed`)},[`source`,`kind`])]},k=C({from:f(`Surface the pre-action baseline described: a host bundle id, or app.`),to:f(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:f(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in sheet) was presented over the app, or left it.`),A=C({foregroundApp:f(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:y(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:y(`Subset of nodeCount the platform reports as hittable.`),digest:f(`Order-independent digest of the post-action node multiset.`),changedFromBefore:u(`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:k},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),ve=C({settled:u(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:y(),captures:y(),quietMs:y(),timeoutMs:y(),refsGeneration:y(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:C({ref:f(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:k,diff:C({summary:C({additions:y(),removals:y(),unchanged:y()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:C({kind:b([`added`,`removed`]),text:f(),ref:f(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:u(`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:C({ref:f(`Plain ref body (e12) minted from the stored settled tree.`),role:f(),label:f()},[`ref`,`role`])},tailTruncated:u(`Present (true) when tail candidates exceeded the response cap.`),hint:f()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),j={platform:b(p),target:b(m),device:f(`Human-readable device name.`),id:f(`Stable device id.`),kind:b(v)},M=[`platform`,`target`,`device`,`id`,`kind`],ye=C({success:u(),exitCode:y(),stdout:f(),stderr:f(),error:c(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function N(e){return e.oneOf?{...e,oneOf:e.oneOf.map(N)}:{...e,properties:{...e.properties??{},settle:ve}}}function be(e){let t={...e};for(let e of Object.keys(t))h(e)&&(t[e]=N(t[e]));return t}const P=D({properties:{evidence:A,button:b([`secondary`,`middle`]),count:y(`Number of press/click repetitions.`),intervalMs:y(`Delay between repeated press/click actions.`),holdMs:y(`Hold duration for each action.`),jitterPx:y(`Randomization radius in pixels.`),doubleTap:u(`Whether the command requested a double-tap action.`)}}),F={text:f(`Text submitted to the field.`),delayMs:y(`Delay between typed characters in milliseconds.`),evidence:A},xe=C({resourceId:S(`Android resource id of the exact field that changed.`),className:S(`Android class name of the exact field that changed.`),packageName:S(`Android package name that owns the exact field.`),rect:C({x:y(),y:y(),width:y(),height:y()},[`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.`),Se=be({press:P,click:P,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:[{...D({properties:F,required:[`text`]}),not:C({},[`verification`])},D({properties:{...F,verification:x(`unconfirmed`),requested:f(`Literal text requested by the fill command.`),before:S(`Raw target text captured before the fill.`),after:S(`Raw target text captured after the fill.`),target:xe},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:D({properties:{durationMs:y(),gesture:x(`longpress`)}}),hover:D({properties:{gesture:x(`hover`)}}),find:C({ref:f(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:y(`ADR 0014 ref frame epoch for read-only find actions.`),found:u(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:y(`Milliseconds waited for a read-only find condition.`),text:f(`Text value returned by find get_text.`),node:c(`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:c(`One listed match with its snapshot ref and node.`)},locator:f(`Locator kind used for the find action.`),query:f(`Query argument used for the find action.`),x:y(`Resolved x coordinate for mutating find actions.`),y:y(`Resolved y coordinate for mutating find actions.`),message:f(`Diagnostic message for mutating find actions.`),cost:T},[],`Daemon response data for the find command.`),boot:C({...j,booted:{type:`boolean`,const:!0}},[...M,`booted`]),shutdown:C({...j,shutdown:ye},[...M,`shutdown`]),viewport:C({width:y(),height:y(),message:f()},[`width`,`height`,`message`]),back:C({action:x(`back`),mode:b(d),message:f()},[`action`,`mode`,`message`]),home:C({action:x(`home`),message:f()},[`action`,`message`]),orientation:C({action:x(`orientation`),orientation:b(se),message:f(),confirmed:u(),warning:f()},[`action`,`orientation`,`message`]),"app-switcher":C({action:x(`app-switcher`),message:f()},[`action`,`message`]),"tv-remote":C({action:x(`tv-remote`),button:b(ce),durationMs:y(),message:f()},[`action`,`button`,`message`]),wait:C({waitedMs:y(),kind:x(`selector`),text:f(),selector:f(),captures:y(),nodeCount:y(),hint:f(),warning:f()},[`waitedMs`]),scroll:C({direction:b([`up`,`down`,`left`,`right`]),edge:b([`top`,`bottom`]),until:f(`Until scrolls only: the selector the passes stopped on.`),passes:y(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:y(),pixels:y(),durationMs:y(),message:f()},[`direction`]),prepare:C({action:x(`ios-runner`),platform:b(p),deviceId:f(),deviceName:f(),kind:b(v),durationMs:y(),runner:C({},[]),cache:b([`exact`,`restore-key`,`miss`,`external`]),artifact:b([`valid`,`rebuilt`]),buildMs:y(),connectMs:y(),healthCheckMs:y(),xctestrunPath:f(),recoveryReason:f(),failureReason:f(),timing:C({totalMs:y(),additiveParts:C({buildMs:y(),connectAfterBuildMs:y(),healthCheckMs:y()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:C({connectMs:{type:`array`,items:x(`buildMs`)},healthCheckMs:{type:`array`,items:f()}},[`healthCheckMs`]),note:f()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:f()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[C({platform:x(`ios`),bundleId:f(),message:f()},[`platform`,`bundleId`,`message`]),C({platform:x(`android`),package:f(),action:f(),extrasCount:y(),message:f()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":C({event:f(),eventUrl:f(),transport:x(`deep-link`),message:f()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[C({action:x(`read`),text:f()},[`action`,`text`]),C({action:x(`write`),textLength:y(),message:f()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[C({platform:b([`ios`,`macos`]),appName:f(),appBundleId:f(),source:x(`session`),surface:b(oe),device_udid:f(`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`]),C({platform:x(`android`),package:f(),activity:f()},[`platform`,`package`,`activity`])]},keyboard:C({platform:b([`android`,`ios`]),action:b([`status`,`dismiss`,`enter`]),visible:u(),wasVisible:u(),dismissed:u(),attempts:y(),inputType:f(),type:b([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:f(),focusedPackage:f(),focusedResourceId:f(),inputOwner:b([`app`,`ime`,`unknown`]),message:f()},[`platform`,`action`]),doctor:C({status:b([`pass`,`warn`,`fail`,`info`]),summary:f(),kind:b([`auto`,`react-native`,`expo`,`repack`]),platform:f(),target:b(m),targetApp:f(),metro:C({host:f(),port:y()},[`host`,`port`]),checks:{type:`array`,items:C({id:f(),status:b([`pass`,`warn`,`fail`,`info`]),summary:f(),hint:f(),command:f(),evidence:c()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:C({mode:x(`snapshot`),baselineInitialized:u(),summary:C({additions:y(),removals:y(),unchanged:y()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:C({kind:b([`added`,`removed`]),text:f(),ref:f()},[`kind`,`text`])},warnings:w},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:C({replayed:y(),healed:y(),session:f(),sessionActive:u(`True iff the session is still active — the script had no terminal close.`),artifactPaths:w,snapshotDiagnostics:c(),message:f()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:C({total:y(),executed:y(),passed:y(),failed:y(),skipped:y(),notRun:y(),durationMs:y(),failures:{type:`array`,items:c()},tests:{type:`array`,items:c()},snapshotDiagnostics:c()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[C({recording:x(`started`),outPath:f(),sessionStateDir:f(),recordingBackend:f(),recordingScope:f(),recordOnlySession:u(),activeSessionApp:c(),showTouches:u()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),C({recording:x(`stopped`),outPath:f(),telemetryPath:f(),artifacts:{type:`array`,items:E},recordingBackend:f(),recordingScope:f(),recordOnlySession:u(),activeSessionApp:c(),durationMs:y(),showTouches:u(),warning:f(),overlayWarning:f(),chunks:{type:`array`,items:c()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[C({trace:x(`started`),outPath:f()},[`trace`,`outPath`]),C({trace:x(`stopped`),outPath:f(),artifacts:{type:`array`,items:E}},[`trace`,`outPath`,`artifacts`])]}}),Ce={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:p},target:{type:`string`,enum:m},kind:{type:`string`,enum:v},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`]}},I={...Se,...Ce},we={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:s({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.`}}},L=Object.entries(we),R=new Set(L.map(([e])=>e)),Te=Object.fromEntries(L.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Ee(){return Object.fromEntries(L.map(([e,t])=>[e,t.schema]))}function z(e){return n(e)}function B(e){let n=[`Error (${e.code}): ${e.message}`];if(e.cause){let t=e.cause.code?`${e.cause.code} `:``;n.push(`Cause: ${t}${e.cause.message}`)}e.hint&&n.push(`Hint: ${e.hint}`),n.push(...De(t(e.details))),e.supportedOn&&n.push(`Supported on: ${e.supportedOn}`);let r=de(e.details);return r&&n.push(r),n.join(`
|
|
2
|
+
`)}function De(e){return e.flatMap(e=>{if(e.kind===`element-match`){let t=e.matches-e.candidates.length;return[`Candidates:`,...e.candidates.map(t=>` ${Oe(t,e.refsGeneration)}`),...t>0?[` +${t} more`]:[]]}return[`Devices:`,...e.devices.map(e=>` ${e.id} ${e.name}`)]})}function Oe(e,t){return t===void 0?e:e.replace(/^@(e\d+)(?=\s|$)/,`@$1~s${t}`)}function ke(e,t,n){let r=he({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&me(t,e)&&(i[t]=a);return pe(i,t)}const Ae={devices:async e=>({devices:e.map(ge)}),apps:async e=>({apps:e})};async function je(e,t){let n=Ae[e];return n?await n(t):t}function V(){let e=new Map;return{pinInput:(t,n,r)=>Ge(t,n,Ie(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>Le(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);Me(e,i,t),Ue(e,i,t)}}}function Me(e,t,n){let i=n?.refsGeneration;typeof i==`number`&&U(e,t,r(n),i)}const Ne=new Set([`snapshot`,`find`]),Pe=new Set(ie.map(e=>e.name).filter(g).filter(e=>h(e))),Fe=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Ie(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function Le(e,t,n,r,i){let a=H(r,i);if(Pe.has(t)){Be(e,a,Ve(n));return}Ne.has(t)&&(t===`find`?ze(e,a,n):Re(e,a,n))}function Re(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);U(e,t,i,r)}function ze(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);U(e,t,i,r)}function Be(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function Ve(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),He(i,n,r)}function He(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 Ue(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];We(i.refs,s),U(e,t,s,a)}function We(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Ge(e,t,n){return n===void 0||n.size===0?t:e===`wait`?Ke(t,n)??t:Fe.has(e)?qe(t,n)??t:t}function Ke(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function qe(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(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 Je={config:s({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:s({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},Ye=Object.fromEntries(ue().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...te,...Te,...Je,...Ye}}function Xe(){return le().map(e=>{let t=e.name in I?I[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:ot(e.name,l(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(t={}){let n=V();return{execute:async(r,i)=>{if(!g(r))throw new e(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=_(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new e(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=ke(r,i,s),l=et(c),u=it(c),d=n.pinInput(r,u,l.client.stateDir),f=await Qe(t,l.client);try{let e=await(t.runCommand??$e)(f,r,d);return n.mergeCommandResult(r,e,l.client.stateDir,u.session),{isError:!1,structuredContent:await je(r,e),content:[{type:`text`,text:await st({name:r,input:u,result:e,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=z(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:B(i)}]}}const Ze=K();async function Qe(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 $e(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function et(e){return{client:tt(e),outputFormat:rt(e.mcpOutputFormat)}}function tt(t){let n=t.stateDir,r=t.includeCost,i=t.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new e(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=nt(i);return o!==void 0&&(a.responseLevel=o),a}function nt(t){if(t===void 0)return;let n=i.find(e=>e===t);if(n===void 0)throw new e(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function rt(t){if(t===void 0)return`optimized`;if(t!==`optimized`&&t!==`json`)throw new e(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return t}function it(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!R.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(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`?ee(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(a(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?at(r,t,e,`${n}.${e}`):void 0)}}function at(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let o=t[n],s=re(t[i]);if(s===void 0||!a(o))return;let c=Y(s,_(s),o);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function ot(e,t){let n=ne(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 Q(e,t){let n=ae(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Ee()}}}async function st(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await fe({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?t.text:$(t?.data??e.result)}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{z as a,B as i,K as n,R as o,Xe as r,Ze as t};
|
package/dist/src/command.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{a as t,c as n,d as r,f as i,
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{a as t,c as n,d as r,f as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g}from"./exec.js";const _=/^[A-Za-z0-9_@%+=:,./-]+$/;function v(e){return`'${e.replaceAll(`'`,String.raw`'\''`)}'`}function y(e){return _.test(e)?e:v(e)}var b=e({coerceExecResult:()=>h,execFailureDetails:()=>u,isCommandTimeoutError:()=>p,isExecutablePath:()=>s,requireExecSuccess:()=>t,resolveExecutableOverridePath:()=>d,resolveFileOverridePath:()=>m,runCmd:()=>n,runCmdBackground:()=>c,runCmdDetached:()=>g,runCmdDetachedMonitored:()=>r,runCmdStreaming:()=>i,runCmdSync:()=>f,shellQuote:()=>v,shellQuoteIfNeeded:()=>y,whichCmd:()=>l,withCommandExecutorOverride:()=>o,withoutCommandExecutorOverride:()=>a});export{v as n,y as r,b as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e,y as t}from"./sdk-contracts.js";import{a as n,l as r,v as i,x 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{d as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{n as ee}from"./config.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(e,n={}){if(!k(e)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return e;let r=se(n.flags);if(!r)throw new t(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...e,`--url`,r]}async function 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(e){let n=e.validateRemoteConfigHash??!0,r=e.remoteConfig?te({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,i=A(e)??(e.allowActiveFallback?z({stateDir:e.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new t(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,e),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(e){try{return T.createHash(`sha256`).update(w.readFileSync(e)).digest(`hex`)}catch(n){throw new t(`INVALID_ARGS`,`Remote config file not found: ${e}`,{cause:n instanceof Error?n.message:String(n)})}}function 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,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(e){let{command:n,flags:r,client:i}=e;if(!r.remoteConfig)return{flags:r,runtime:e.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 t(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?e.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??e.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:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.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(e){let{command:n,flags:r,state:i,client:a}=e,o=ke(e.nextState,r),s=e.runtime;if(!Je(n,r,e.batchSteps,e.positionals)||!$(r)||!Ae(e.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new t(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await 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?e.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(e,n,r,i,a){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if(e.platform!==`ios`&&e.platform!==`android`)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:e.metroProjectRoot,kind:f(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:a,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:e.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function 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(e,n){let r=Q(e);if(r)return r;throw new t(`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(t,n){return!t.platform||!n||!e(n)||t.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(e,n,r={}){if(!e.tenant)throw new t(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new t(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:e.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??Q(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.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(e){if(!Ee.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new t(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(e.client,e.flags),r=rt(n);return{state:{...e.state,deviceKey:r,leaseBackend:e.state.leaseBackend??e.leaseBackend??it(n),platform:e.state.platform??n.platform,target:e.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,r(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(e,t){let r=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(r.map(e=>({...n(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(r(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(e,n,r){if(e.leaseBackend&&e.leaseBackend!==r)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:e.session,leaseBackend:e.leaseBackend});if(e.platform&&n.platform&&e.platform!==n.platform)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:e.session,platform:e.platform});if(e.target&&n.target&&e.target!==n.target)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:e.session,target:e.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(e){return!(e instanceof t)||e.code!==`UNAUTHORIZED`?!1:e.details?.reason===`LEASE_NOT_FOUND`||e.details?.reason===`LEASE_EXPIRED`||e.details?.reason===`LEASE_REVOKED`}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{C as e,o as t}from"./sdk-contracts.js";import{a as n,l as r,v as i,x 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{n as ee}from"./config.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,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,r(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(e,t){let r=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(r.map(e=>({...n(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(r(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};
|
package/dist/src/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{b as e,y as t}from"./sdk-contracts.js";import{r as n}from"./command.js";import{r}from"./version.js";import{n as i}from"./config.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=e(r);throw new t(`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(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return be(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function be(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function 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(e){let n=N.find(t=>t.provider===e)?.buildProfileFields;if(n)return n;throw new t(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}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(e,n){if(e.startsWith(`bs://`)||/^https?:\/\//i.test(e))return e;let r=E.resolve(n,e);try{if(D.statSync(r).isFile())return r}catch{}throw new t(`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(e,n){if(e===`android`||e===`ios`)return e;throw new t(`INVALID_ARGS`,n)}function F(e,n){if(e)return e;throw new t(`INVALID_ARGS`,n)}function I(e,n,r){let i=e?.[n];if(i)return i;throw new t(`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(e){let n=e.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=Ee({flags:e.flags});return k({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.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(e){if(e.platform!==`android`&&e.platform!==`ios`)throw new t(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(e.device!==void 0)throw new t(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=h(e),r=e.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new t(`INVALID_ARGS`,`connect limrun --platform ${e.platform} requires --lease-backend ${r}.`);return r}function Oe(e){let n=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new t(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=j(e.stateDir,n,e.flags.session),i={daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??h(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...b(e.flags)};return k({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const 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(e,n){if(e!==void 0)return e;throw new t(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(e,n){if(e===`android`||e===`ios`)return e;throw new t(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function 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(`
|
|
1
|
+
import{C as e,w as t}from"./sdk-contracts.js";import{r as n}from"./command.js";import{r}from"./version.js";import{n as i}from"./config.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
2
|
`)}let a=G(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(He(n.device)),n.app&&o.push(Ue(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:m(t.daemon?.baseUrl),liveSession:ze(t),...Be(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ve({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function ze(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Be(e,t){return e?{verification:{status:G(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 Ve(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function He(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 Ue(e,t){return t.status===`missing`?`App: ${Qe(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 W(e,t){let n=We(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function We(e,t){let n=v(e.leaseProvider).leaseKind;if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${J(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:Ze()};if(v(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:Ge(t)?Xe(e):[...qe(t),...Ye(e).nextSteps],...Ke(t)?{notes:Je(e,!r)}:{}}}function Ge(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function Ke(e){return v(e?.provider).supportsArtifacts}function qe(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 Je(e,t){return[...t?[`Use the installed package or bundle identifier in open, not the app artifact name.`]:[],`After close, run ${q(e,`agent-device artifacts --json`)} for provider video and logs.`]}function Ye(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function Xe(e){let t=J(e.platform);return[`agent-device install ${t} <app-path-or-url>`,`agent-device open ${t} --relaunch`]}function G(e){return`status`in e?e.status:`verified`}function Ze(){return[`agent-device open <package-or-bundle-id> --relaunch`,`agent-device snapshot -i`,`agent-device close`,`agent-device artifacts --json`]}function K(e,t){return t.map(t=>q(e,t))}function q(e,t){return`${t} --session ${n(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function Qe(e){let t=v(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const $e=async({positionals:e,flags:t,client:n})=>{let r=i(t.stateDir).baseDir,a=ht(e);et(a,t);let o=await ke({provider:a,flags:t,stateDir:r}),s=o.flags,c=ct(o.remoteConfigPath),l=tt(s,c),u=Fe({stateDir:r,flags:s,remoteConfigPath:o.remoteConfigPath});nt(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:h(s),connection:c,daemon:u.daemon});let d=await Ae(o),f=rt({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});p({stateDir:r,state:f});let m=await st(n,r,s,u.previous,f.daemon?.baseUrl),g=bt(s,f),_=Le(f,d);return await T(s,U({state:f,runtimePreparation:g,readiness:_,previousLeaseNotice:m}),()=>Re({state:f,runtimePreparation:g,readiness:_,previousLeaseNotice:m})),!0};function et(
|
|
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:m(t.daemon?.baseUrl),liveSession:ze(t),...Be(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ve({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function ze(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Be(e,t){return e?{verification:{status:G(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 Ve(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function He(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 Ue(e,t){return t.status===`missing`?`App: ${Qe(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 W(e,t){let n=We(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function We(e,t){let n=v(e.leaseProvider).leaseKind;if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${J(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:Ze()};if(v(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:Ge(t)?Xe(e):[...qe(t),...Ye(e).nextSteps],...Ke(t)?{notes:Je(e,!r)}:{}}}function Ge(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function Ke(e){return v(e?.provider).supportsArtifacts}function qe(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 Je(e,t){return[...t?[`Use the installed package or bundle identifier in open, not the app artifact name.`]:[],`After close, run ${q(e,`agent-device artifacts --json`)} for provider video and logs.`]}function Ye(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function Xe(e){let t=J(e.platform);return[`agent-device install ${t} <app-path-or-url>`,`agent-device open ${t} --relaunch`]}function G(e){return`status`in e?e.status:`verified`}function Ze(){return[`agent-device open <package-or-bundle-id> --relaunch`,`agent-device snapshot -i`,`agent-device close`,`agent-device artifacts --json`]}function K(e,t){return t.map(t=>q(e,t))}function q(e,t){return`${t} --session ${n(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function Qe(e){let t=v(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const $e=async({positionals:e,flags:t,client:n})=>{let r=i(t.stateDir).baseDir,a=ht(e);et(a,t);let o=await ke({provider:a,flags:t,stateDir:r}),s=o.flags,c=ct(o.remoteConfigPath),l=tt(s,c),u=Fe({stateDir:r,flags:s,remoteConfigPath:o.remoteConfigPath});nt(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:h(s),connection:c,daemon:u.daemon});let d=await Ae(o),f=rt({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});p({stateDir:r,state:f});let m=await st(n,r,s,u.previous,f.daemon?.baseUrl),g=bt(s,f),_=Le(f,d);return await T(s,U({state:f,runtimePreparation:g,readiness:_,previousLeaseNotice:m}),()=>Re({state:f,runtimePreparation:g,readiness:_,previousLeaseNotice:m})),!0};function et(t,n){if(!(!t||!n.remoteConfig))throw new e(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function tt(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&&v(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 nt(t,n){if(!(!t||gt(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 rt(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=ot(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=it(t,o,r),l=at(t,o,s);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function it(e,t,n){let r=se(n??{},t??{});return{leaseId:t?.leaseId,leaseBackend:t?.leaseBackend??h(e),...r,deviceKey:t?.deviceKey??r.deviceKey}}function at(e,t,n){return{platform:e.platform??t?.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function ot(e,t){return!!(t&&!e.force)}async function st(e,t,n,r,i){if(!(!r||!n.force))return await x(r.metro),await C({stateDir:t,state:r}),await re(e,r,{nextDaemonBaseUrl:i,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function ct(e){let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return ee(t)}const lt=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=Y(e);if(!i)return await X(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 C({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await ne(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return d({stateDir:r,session:a}),await T(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>dt(a,o)),!0},ut=async({positionals:t,flags:n})=>{if(t[0]!==`status`)throw new e(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=Y(n);if(!i)return await X(n,r),!0;let a=H(i),o=Z(i);return await T(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
4
|
`)),!0};function dt(e,t){return[`Disconnected remote session "${e}".`,...ft(t),...mt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
-
`)}function ft(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=pt(e);return t?[t]:[]})}function pt(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 mt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function ht(
|
|
5
|
+
`)}function ft(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=pt(e);return t?[t]:[]})}function pt(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 mt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function ht(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(y(n))return n;throw new e(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${ae()}.`)}}function Y(e){let t=e.session??`default`,n=i(e.stateDir).baseDir;return{session:t,stateDir:n,state:w({stateDir:n,session:t})??(e.session?null:g({stateDir:n}))}}async function X(e,t){await T(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function gt(e,t){return _t(e,t)&&vt(e,t)&&yt(e.daemon,t.daemon)}function _t(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 vt(e,t){return[[e.leaseBackend,t.desiredLeaseBackend],[e.platform,t.flags.platform],[e.target,t.flags.target]].every(([e,t])=>t===void 0||e===t)&&f(e,t.connection)}function yt(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function bt(e,t){if(!t.runtime&&!(!ie(e)&&!$(t.remoteConfigPath)))return Q(t)}function Z(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=q(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{$e as connectCommand,ut as connectionCommand,lt as disconnectCommand};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as DaemonError, G as normalizeError, H as defaultHintForCode, a as DaemonRequest, d as JsonRpcRequestEnvelope, f as LeaseBackend, j as centerOfRect, 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{E as e,M as t,p as n}from"./sdk-contracts.js";export{n as centerOfRect,e as defaultHintForCode,t as normalizeError};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as e,O as t,P as n,k as r,y as i}from"./sdk-contracts.js";import{a,u as o}from"./lease-scope.js";import{C as s}from"./sdk-batch.js";import{n as c}from"./catalog.js";import{n as l,r as u}from"./diagnostics.js";import{f as d,s as f,u as p}from"./exec.js";import{t as m}from"./timeouts.js";import"./diagnostics2.js";import{r as ee,t as te}from"./output-path.js";import{d as h,i as ne,m as g,n as _,p as re,t as v}from"./transport.js";import{n as y,r as b}from"./command.js";import{i as ie}from"./replay-divergence.js";import"./retry.js";import{n as ae,r as x}from"./version.js";import{t as oe}from"./ttl-memo.js";import{t as se}from"./session-repair-tombstone.js";import{i as ce,n as le,r as ue}from"./config.js";import{n as de}from"./code-signature.js";import{n as fe,t as S}from"./daemon-process.js";import{n as pe,o as me,t as he}from"./request-progress-protocol.js";import{t as ge}from"./session-artifact-paths.js";import C from"node:path";import w from"node:fs";import{createHash as _e,randomUUID as ve}from"node:crypto";import ye from"node:os";import{Transform as be,Writable as xe}from"node:stream";import{pipeline as Se}from"node:stream/promises";import T from"node:net";async function Ce(e,t){let n=w.statSync(e),r=C.basename(e),i=n.isDirectory(),a=Ee(t)??Te(e,n),o=[];try{let t=i?await we(e,o):e,n=w.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await Oe(t),sizeBytes:n.size,cleanup:()=>De(o)}}catch(e){throw De(o),e}}async function we(e,t){let n=w.mkdtempSync(C.join(ye.tmpdir(),`agent-device-upload-${ve()}-`));t.push(n);let r=C.join(n,`${C.basename(e)}.tar.gz`);return await f(`tar`,[`czf`,r,`-C`,C.dirname(e),C.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function Te(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 Ee(e){return e===`ios`||e===`android`?e:void 0}function De(e){for(let t of e)w.rmSync(t,{recursive:!0,force:!0})}async function Oe(e){let t=_e(`sha256`),n=new xe({write(e,n,r){t.update(e),r()}});return await Se(w.createReadStream(e),n).catch(e=>{throw new i(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),t.digest(`hex`)}function ke(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Me(i),c=Math.min(i,r+s);return new be({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 Ae(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${je(e)}\n`)}}function je(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${E(e.totalBytes)}) via ${Ne(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)} (${Pe(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${Ne(e.to)} upload`}}function Me(e){return Math.max(8388608,Math.ceil(e*.05))}function Ne(e){return e===`direct`?`direct`:`legacy`}function Pe(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 Fe=3e5,Ie=`uploadStreamRetryable`;async function Le(e){return await D({...e,url:e.url,redirectCount:0,startOffset:0})}function Re(e){return e instanceof i&&e.details?.[Ie]===!0}async function D(e){let t=await _(e.url.protocol),n=w.statSync(e.payloadPath).size,r=Ve(e.headers,e.startOffset,n);return Be(e.progress,e.startOffset,n),await new Promise((a,o)=>{let s=!1,c=t.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:r},t=>{s=!0,ne(t).then(r=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&He(s)){if(e.redirectCount>=5){o(new i(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);D({...e,url:t,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Ue(s)?We(t.headers,n):void 0;if(u!==void 0){if(u>=n){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new i(`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:t.statusMessage,body:r})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new i(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:Fe,...e.timeoutHint?{hint:e.timeoutHint}:{},...ze(e)}))},Fe);c.on(`error`,t=>{s||(clearTimeout(l),o(new i(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...ze(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),Se(w.createReadStream(e.payloadPath,{start:e.startOffset}),ke({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??C.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:n,onProgress:e.progress?.onProgress}),c).catch(e=>{if(s)return;c.destroy();let t=e instanceof Error?e:Error(String(e));o(new i(`COMMAND_FAILED`,`Failed to read local artifact`,{},t))})})}function ze(e){return e.retryable===!0?{[Ie]:!0}:{}}function Be(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Ve(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function He(e){return[301,302,303,307,308].includes(e)}function Ue(e){return e===308}function We(e,t){let n=Ge(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Ke(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 Ge(e){let t=Ke(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Ke(e){return Array.isArray(e)?e[0]:e}const qe=3e4;async function Je(e){let t=await Ce(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=ve();try{let i=await O({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 Ze({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Ze({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Ye(e){let t=async t=>(await et(e.artifact,t,e.onProgress),await tt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Xe(n))return;let r=await O({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 i?Re(e):!0}async function Ze(e){let{normalizedBase:t,token:n,artifact:r}=e,a=new URL(`upload`,t),o={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,h(n));let s=await Le({url:a,method:`POST`,headers:o,payloadPath:r.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:r.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new i(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof i?e:new i(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function O(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:AbortSignal.timeout(qe),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 Qe(await r.json().catch(()=>void 0))}function Qe(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($e(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function $e(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function et(e,t,n){let r=await Le({url:new URL(t.url),method:`PUT`,headers:t.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:n}});if(r.statusCode<200||r.statusCode>=300)throw new i(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:r.statusCode,statusMessage:r.statusMessage})}async function tt(e){let t=new URL(`upload/finalize`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,h(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(qe),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new i(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!r.ok)throw new i(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:r.status,statusText:r.statusText});let a=await r.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new i(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function nt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=Ae();if(!vt(t))return k({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});rt(e),r=at(e,n,r,a);let c=await ct(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await it(e,t,n,s)??o),k({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function rt(e){if(e.flags?.saveScript!==void 0)throw new i(`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 it(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=st(a,e.meta?.cwd);if(o)return await Je({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function at(e,t,n,r){let i=lt(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=ot(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function ot(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function st(e,t){let n=C.isAbsolute(e)?e:C.resolve(t??process.cwd(),e);return w.existsSync(n)?n:void 0}function k(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 ct(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=C.isAbsolute(i)?i:C.resolve(e.meta?.cwd??process.cwd(),i);if(!w.existsSync(a))return{installSource:{...r,path:a}};let o=await Je({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function lt(e,t){if(e.command===`screenshot`){let n=j(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:P(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:P(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!dt(e)&&e.flags?.platform===void 0)return null;let t=A(e),n=ft(j(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:P(`recording`,C.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:ut(e),flagKey:`artifactsDir`,flagPath:pt(`test-artifacts`)}:null}function ut(e){let t=e.flags?.artifactsDir;return M(N(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function A(e){return ee(e.flags?.platform)}function dt(e){return N(e.positionals?.[1])||N(e.flags?.out)}function ft(e,t){return t.flags?.platform===`web`?te(e,A(t)):e}function j(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return M(N(i)?i:a,e.meta?.cwd)}function M(e,t){return C.isAbsolute(e)?e:C.resolve(t??process.cwd(),e)}function N(e){return typeof e==`string`&&e.trim().length>0}function P(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return C.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function pt(e){return C.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function mt(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=ht(n,t),o=await gt({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 ht(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 C.resolve(t.meta?.cwd??process.cwd(),r)}async function gt(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(_t(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 _t(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function vt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const F=oe();function I(){let e=F.get(`local`);if(e)return e;let t=ae(),n=[C.join(t,`dist`,`src`,`internal`,`daemon.js`),C.join(t,`dist`,`src`,`daemon.js`)],r=n[0];if(r===void 0)throw new i(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=n.find(e=>w.existsSync(e))??r,o=C.join(t,`src`,`daemon.ts`),s=n.some(e=>w.existsSync(e)),c=w.existsSync(o);if(!s&&!c)throw new i(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:n,srcPath:o});let l={root:t,distPath:a,distPaths:n,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return F.set(`local`,l),l}async function yt(){let e=I();if(!e.useSrc)return de(e.distPath,e.root);let{resolveCachedDaemonCodeSignature:t}=await import(`./code-signature-cache.js`);return t(e.srcPath,e.root)}const L=3e3,R=1e3;function z(e){let t=Ot(e);if(!t||typeof t!=`object`)return null;let n=t,r=bt(n);if(!r)return null;let i=xt(n);return i?{token:r,...i,transport:St(n.transport),pid:V(n.pid)??0,version:B(n.version),codeSignature:B(n.codeSignature),processStartTime:B(n.processStartTime)}:null}function bt(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function xt(e){let t=V(e.port),n=V(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function St(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function B(e){return typeof e==`string`?e:void 0}function V(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function H(e){let t=Ot(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 U(e){kt(e)}function W(e){kt(e)}function Ct(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let n=H(e.lockPath);if(!n){W(e.lockPath);return}S(n.pid,n.processStartTime)||W(e.lockPath)}async function G(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=w.existsSync(e.infoPath),n=z(e.infoPath);if(n){let t=S(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await q(n),i.stoppedInfoProcess=!0),U(e.infoPath),i.removedInfo=!0)}else t&&(U(e.infoPath),i.removedInfo=!0);let a=w.existsSync(e.lockPath),o=H(e.lockPath);if(o){let t=S(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await fe(o.pid,{termTimeoutMs:L,killTimeoutMs:R,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),W(e.lockPath),i.removedLock=!0)}else a&&(W(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:w.existsSync(e.infoPath),hasLock:w.existsSync(e.lockPath)}}async function wt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let n=H(e.lockPath);return!n||!S(n.pid,n.processStartTime)?(W(e.lockPath),!0):!1}async function q(e){await fe(e.pid,{termTimeoutMs:L,killTimeoutMs:R,expectedStartTime:e.processStartTime})}function Tt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Et(e,t=le(process.env.AGENT_DEVICE_STATE_DIR)){let n=Dt(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 Dt(e){return`rm -f ${y(e.infoPath)} ${y(e.lockPath)}`}function Ot(e){if(!w.existsSync(e))return null;try{return JSON.parse(w.readFileSync(e,`utf8`))}catch{return null}}function kt(e){try{w.existsSync(e)&&w.unlinkSync(e)}catch{}}function J(e,t,n){return new i(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:t},n instanceof Error?n:void 0)}function At(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(he(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return pe(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 jt(e,t){return me(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function Mt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=At({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 Nt(e,t){let{req:n,handleResponseBody:r,reject:a,clearTimeout:o}=t,s=``,c=!1,l=At({req:n,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),r(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.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}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(J(n,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new i(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0)))})}const Pt=1e4,Ft=8388608;function It(e,t){return g(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Lt(e){let{logPath:t,...n}=e;return n}async function Rt(e,t){let n=Lt(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=ge(t.stateDir,r),a=await zt({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 zt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(It(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await _(i.protocol);return await w.promises.mkdir(C.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}w.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),...re(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=w.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Ft&&(s.destroy(),n.destroy(),o(`record exceeds ${Ft} 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 ${Pt}ms`),s.destroy()},Pt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function Bt(e,t){let{info:n,req:r,stateDir:a,resolve:o,reject:s}=t;try{let t=Vt(e);if(t.error){Ht(t.error,{info:n,req:r,stateDir:a,reject:s});return}if(!t.result||typeof t.result!=`object`){s(new i(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:r.meta?.requestId}));return}Kt(n,r,t.result,o,s)}catch(t){s(new i(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function Vt(e){return JSON.parse(e)}async function Ht(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Ut(e);if(!n.baseUrl){a(Gt(s,o));return}a(Gt(await Rt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Ut(e){let t=e.data??{},i=Wt(t.cause);return{code:n(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:i,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:r(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function Wt(t){return e(t)}function Gt(e,t){return new i(n(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:t},e.cause)}async function Kt(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await mt(e,t,n):n)}catch(e){i(e)}}function qt(e,t){let n=e.meta?.requestId??l();return Jt(e.command)?{jsonrpc:`2.0`,id:n,method:Yt(e.command),params:{...Xt(e,e.command,t),...e.command===`lease_allocate`&&typeof e.flags?.providerApp==`string`?{providerApp:e.flags.providerApp}:{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Jt(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function Yt(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 Xt(e,t,n){return o(a(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Zt=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],Qt=new Set([`apple`,`ios`,`macos`]);function $t(e){return e!==void 0&&Qt.has(e)}function en(e,t,n,r,a,o,s){let c=a?{terminated:0}:rn(),l=!a&&tn(r),d=l?an(e,t):{forcedKill:!1},f=$t(s)||c.terminated>0;return u({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:n,command:r,timedOutRunnerPidsTerminated:c.terminated,timedOutRunnerCleanupError:c.error,daemonPidReset:l?e.pid:void 0,daemonPidForceKilled:l?d.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!l,daemonBaseUrl:e.baseUrl}}),new i(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:n,hint:nn({remote:a,resetDaemon:l,command:r,appleCleanupEvidence:f})})}function tn(e){return s(e).onTimeout===`reset-daemon`}function nn(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i}=e;if(t)return`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 rn(){let e=0;try{for(let t of Zt)d(`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 an(e,t){let n=!1;try{S(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{q(e)}finally{U(t.infoPath),W(t.lockPath)}return{forcedKill:n}}const on=`Daemon HTTP endpoint is unavailable`,sn=`Daemon socket endpoint is unavailable`;async function cn(e,t){let n=X(e,t);if(await ln(e,n))return!0;let r=vn(e,t,n);return r?await ln(e,r):!1}async function ln(e,t){return t===`http`?await dn(e):await un(e.port)}function un(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 dn(e){return pn(e).then(e=>e.reachable)}async function fn(e){let t=await pn(e);if(!e.baseUrl||!t.reachable)return t;let n=[t,t.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(n)throw new i(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:x(),remoteVersion:n.version,remoteService:n.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:n.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return t}async function pn(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,...mn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function mn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?hn(t.upstream):void 0;return{...hn(t),...n?{upstream:n}:{}}}catch{return{}}}function hn(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 gn(e,t,n,r,i,a={}){let o=X(e,n);try{return await _n(e,t,r,i,o,a)}catch(s){let c=vn(e,n,o);if(!c||!yn(s,o))throw s;return await _n(e,t,r,i,c,a)}}async function _n(e,t,n,r,i,a){return i===`http`?await Cn(e,t,n,r,a):await Sn(e,t,n,r,a)}function X(e,t){if(e.baseUrl){if(t===`socket`)throw new i(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return bn(e,t);let n=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>Z(e,t));if(n)return n;throw new i(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function Z(e,t){return t===`http`?!!e.httpPort:!!e.port}function vn(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return Z(e,r)?r:null}function yn(e,t){return t===`socket`&&e instanceof i&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function bn(e,t){if(Z(e,t))return t;throw new i(`COMMAND_FAILED`,t===`http`?on:sn)}function xn(e,t,n,r={}){return u({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new i(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...r,requestId:t,hint:n?`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 Sn(e,t,n,r,a){let o=e.port;if(!o)throw new i(`COMMAND_FAILED`,sn);return new Promise((i,s)=>{let c=!1,l=T.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof r==`number`?setTimeout(()=>{u=!0,l.destroy(),s(en(e,n,t.meta?.requestId,t.command,!1,r,t.flags?.platform))},r):void 0;Mt(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,i(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(xn(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function Cn(e,t,n,r,a){let o=e.baseUrl?new URL(g(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new i(`COMMAND_FAILED`,on);let s=JSON.stringify(qt(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&Object.assign(c,h(e.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},r=>{if(jt(t,r.headers?.[`content-type`])){Nt(r,{req:t,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:r=>Bt(r,{info:e,req:t,stateDir:n.baseDir,resolve:u,reject:d})});return}ne(r).then(r=>{m&&clearTimeout(m),Bt(r,{info:e,req:t,stateDir:n.baseDir,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(new i(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),p=Tt(e),m=typeof r==`number`?setTimeout(()=>{f.destroy(),d(en(e,n,t.meta?.requestId,t.command,p,r,t.flags?.platform))},r):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(xn(e,t.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 wn(e,t){let n=Tn(e),r=En(e,t),i=Dn(e,r.remoteBaseUrl),a=On(e,n,r.rawBaseUrl),o=a?kn():n;return{paths:le(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function Tn(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function En(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Yn(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Xn(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function Dn(e,t){let n=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=ce(n);if(t&&r===`socket`)throw new i(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(n===`dual`?`dual`:void 0);return{preference:r,serverMode:ue(a)}}function On(e,t,n){return Hn(e.command)&&!t&&!n}function kn(){return w.mkdtempSync(C.join(ye.tmpdir(),`agent-device-replay-daemon-`))}async function An(e){if(e.remoteBaseUrl)return await jn(e);let t=await Mn(e);return t?{info:t,startedByClient:!1}:(Ct(e.paths),await Ln(e))}async function jn(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await fn(t)).reachable)return{info:t,startedByClient:!1};throw new i(`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 Mn(e){let t=z(e.paths.infoPath);if(!t)return null;let n=await Fn(t,await Nn(t,e.transportPreference));return n?(In(t,n,e.paths.baseDir),await q(t),U(e.paths.infoPath),null):t}async function Nn(e,t){try{return await cn(e,t)}catch(e){if(Pn(e))return!1;throw e}}function Pn(e){return e instanceof i&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}async function Fn(e,t){if(e.version!==x())return`version mismatch (client v${x()})`;if(e.codeSignature!==await yt())return`code-signature mismatch`;if(!t)return`unreachable`}function In(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 Ln(e){let t=0,n=[],r,a;for(let i=1;i<=2;i+=1){let o;try{o=Kn(e),a={pid:o.pid}}catch(t){if(r=t instanceof Error?t.message:String(t),n.push(await G(e.paths,`start_error`)),i<2){await m(150);continue}break}let s=await Gn(Q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,r=qn(s.exit),n.push(await G(e.paths,`start_error`)),i<2){await m(150);continue}break}if(await wt(e.paths)){t+=1;continue}let c=K(e.paths),l=i<2,u=await G(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(n.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Gn(Q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,r=qn(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await m(150)}let o=K(e.paths),s=Jn(e.paths.logPath);throw new i(`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:t,cleanupResults:n,startError:r,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:Et(o,e.paths)})}async function Rn(e,t,n,r){if(!Hn(e.command)||!t.startedByClient&&!n.ownedStateDir||Tt(t.info)||Bn(r)||Un(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await q(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=w.existsSync(n.paths.infoPath);U(n.paths.infoPath),i.removedInfo=e&&!w.existsSync(n.paths.infoPath);let t=w.existsSync(n.paths.lockPath);if(W(n.paths.lockPath),i.removedLock=t&&!w.existsSync(n.paths.lockPath),n.ownedStateDir){let e=se(n.paths.sessionsDir);e?a=zn(r,e):(w.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!w.existsSync(n.paths.baseDir))}}return u({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function zn(e,n){if(e&&!e.ok)return e;let{sessionName:r,tombstone:a}=n,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 "${r}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:t(new i(`REPAIR_COMMIT_FAILED`,s))}}function Bn(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:ie(e.error.details?.divergence)?.repairSessionHeld===!0}function Vn(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 Hn(e){return e===c.replay||e===c.test}function Un(e,t){return e.command!==c.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Wn(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 Gn(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=z(t.paths.infoPath);if(e&&await cn(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await m(100)}return{kind:`timeout`}}function Kn(e){let t=I(),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};w.mkdirSync(e.paths.baseDir,{recursive:!0});let i=w.openSync(e.paths.logPath,`a`),a=w.openSync(e.paths.logPath,`a`);try{return p(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{w.closeSync(i),w.closeSync(a)}}function qn(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 Jn(e){try{if(!w.existsSync(e))return;let t=w.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=w.openSync(e,`r`);try{let e=Buffer.alloc(n);w.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{w.closeSync(r)}}catch{return}}function Yn(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new i(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new i(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function Xn(e,t){if(!e)return;let n=new URL(e).hostname;if(!Zn(n)&&!(typeof t==`string`&&t.trim().length>0))throw new i(`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 Zn(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{Un as a,gn as c,An as i,nt as l,Vn as n,Bn as o,Rn as r,wn as s,Wn as t};
|
|
1
|
+
import{B as e,C as t,M as n,N as r,R as i}from"./sdk-contracts.js";import{a,p as o,u as s}from"./lease-scope.js";import{C 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 ne,m as _,n as v,p as re,t as y}from"./transport.js";import{n as b,r as ie}from"./command.js";import{i as ae}from"./replay-divergence.js";import"./retry.js";import{n as oe,r as x}from"./version.js";import{t as se}from"./ttl-memo.js";import{t as ce}from"./session-repair-tombstone.js";import{i as le,n as ue,r as de}from"./config.js";import{n as fe}from"./code-signature.js";import{n as pe,t as S}from"./daemon-process.js";import{n as me,o as he,t as ge}from"./request-progress-protocol.js";import{t as _e}from"./session-artifact-paths.js";import C from"node:path";import w from"node:fs";import{createHash as ve,randomUUID as ye}from"node:crypto";import be from"node:os";import{Transform as xe,Writable as Se}from"node:stream";import{pipeline as Ce}from"node:stream/promises";import T from"node:net";async function we(e,t){let n=w.statSync(e),r=C.basename(e),i=n.isDirectory(),a=De(t)??Ee(e,n),o=[];try{let t=i?await Te(e,o):e,n=w.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await ke(t),sizeBytes:n.size,cleanup:()=>Oe(o)}}catch(e){throw Oe(o),e}}async function Te(e,t){let n=w.mkdtempSync(C.join(be.tmpdir(),`agent-device-upload-${ye()}-`));t.push(n);let r=C.join(n,`${C.basename(e)}.tar.gz`);return await f(`tar`,[`czf`,r,`-C`,C.dirname(e),C.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function Ee(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 De(e){return e===`ios`||e===`android`?e:void 0}function Oe(e){for(let t of e)w.rmSync(t,{recursive:!0,force:!0})}async function ke(e){let n=ve(`sha256`),r=new Se({write(e,t,r){n.update(e),r()}});return await Ce(w.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 Ae(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Ne(i),c=Math.min(i,r+s);return new xe({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 je(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Me(e)}\n`)}}function Me(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${E(e.totalBytes)}) via ${Pe(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)} (${Fe(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${Pe(e.to)} upload`}}function Ne(e){return Math.max(8388608,Math.ceil(e*.05))}function Pe(e){return e===`direct`?`direct`:`legacy`}function Fe(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 Ie=3e5,Le=`uploadStreamRetryable`;async function Re(e){return await D({...e,url:e.url,redirectCount:0,startOffset:0})}function ze(e){return e instanceof t&&e.details?.[Le]===!0}async function D(e){let n=await v(e.url.protocol),r=w.statSync(e.payloadPath).size,i=He(e.headers,e.startOffset,r);return Ve(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,ne(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Ue(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=We(s)?Ge(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:Ie,...e.timeoutHint?{hint:e.timeoutHint}:{},...Be(e)}))},Ie);c.on(`error`,n=>{s||(clearTimeout(l),o(new t(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...Be(e)},n)))}),c.on(`close`,()=>clearTimeout(l)),Ce(w.createReadStream(e.payloadPath,{start:e.startOffset}),Ae({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??C.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 Be(e){return e.retryable===!0?{[Le]:!0}:{}}function Ve(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function He(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Ue(e){return[301,302,303,307,308].includes(e)}function We(e){return e===308}function Ge(e,t){let n=Ke(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=qe(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 Ke(e){let t=qe(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function qe(e){return Array.isArray(e)?e[0]:e}const Je=3e4;async function Ye(e){let t=await we(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=ye();try{let i=await O({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Xe({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 Qe({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Qe({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Xe(e){let t=async t=>(await tt(e.artifact,t,e.onProgress),await nt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Ze(n))return;let r=await O({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 Ze(e){return e instanceof t?ze(e):!0}async function Qe(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 Re({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 O(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(Je),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 $e(await r.json().catch(()=>void 0))}function $e(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(et(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function et(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function tt(e,n,r){let i=await Re({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 nt(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(Je),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 rt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=je();if(!yt(t))return k({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});it(e),r=ot(e,n,r,a);let c=await lt(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await at(e,t,n,s)??o),k({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function it(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 at(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=ct(a,e.meta?.cwd);if(o)return await Ye({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function ot(e,t,n,r){let i=ut(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=st(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function st(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function ct(e,t){let n=C.isAbsolute(e)?e:C.resolve(t??process.cwd(),e);return w.existsSync(n)?n:void 0}function k(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 lt(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=C.isAbsolute(i)?i:C.resolve(e.meta?.cwd??process.cwd(),i);if(!w.existsSync(a))return{installSource:{...r,path:a}};let o=await Ye({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function ut(e,t){if(e.command===`screenshot`){let n=j(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:P(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:P(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!ft(e)&&e.flags?.platform===void 0)return null;let t=A(e),n=pt(j(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:P(`recording`,C.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:dt(e),flagKey:`artifactsDir`,flagPath:mt(`test-artifacts`)}:null}function dt(e){let t=e.flags?.artifactsDir;return M(N(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function A(e){return ee(e.flags?.platform)}function ft(e){return N(e.positionals?.[1])||N(e.flags?.out)}function pt(e,t){return t.flags?.platform===`web`?te(e,A(t)):e}function j(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return M(N(i)?i:a,e.meta?.cwd)}function M(e,t){return C.isAbsolute(e)?e:C.resolve(t??process.cwd(),e)}function N(e){return typeof e==`string`&&e.trim().length>0}function P(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return C.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function mt(e){return C.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function ht(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=gt(n,t),o=await _t({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 gt(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 C.resolve(t.meta?.cwd??process.cwd(),r)}async function _t(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(vt(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 vt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function yt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const F=se();function I(){let e=F.get(`local`);if(e)return e;let n=oe(),r=[C.join(n,`dist`,`src`,`internal`,`daemon.js`),C.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=>w.existsSync(e))??i,o=C.join(n,`src`,`daemon.ts`),s=r.some(e=>w.existsSync(e)),c=w.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 F.set(`local`,l),l}async function bt(){let e=I();if(!e.useSrc)return fe(e.distPath,e.root);let{resolveCachedDaemonCodeSignature:t}=await import(`./code-signature-cache.js`);return t(e.srcPath,e.root)}const L=3e3,R=1e3;function z(e){let t=kt(e);if(!t||typeof t!=`object`)return null;let n=t,r=xt(n);if(!r)return null;let i=St(n);return i?{token:r,...i,transport:Ct(n.transport),pid:V(n.pid)??0,version:B(n.version),codeSignature:B(n.codeSignature),processStartTime:B(n.processStartTime)}:null}function xt(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function St(e){let t=V(e.port),n=V(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Ct(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function B(e){return typeof e==`string`?e:void 0}function V(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function H(e){let t=kt(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 U(e){At(e)}function W(e){At(e)}function wt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let n=H(e.lockPath);if(!n){W(e.lockPath);return}S(n.pid,n.processStartTime)||W(e.lockPath)}async function G(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=w.existsSync(e.infoPath),n=z(e.infoPath);if(n){let t=S(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await q(n),i.stoppedInfoProcess=!0),U(e.infoPath),i.removedInfo=!0)}else t&&(U(e.infoPath),i.removedInfo=!0);let a=w.existsSync(e.lockPath),o=H(e.lockPath);if(o){let t=S(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await pe(o.pid,{termTimeoutMs:L,killTimeoutMs:R,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),W(e.lockPath),i.removedLock=!0)}else a&&(W(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 K(e){return{hasInfo:w.existsSync(e.infoPath),hasLock:w.existsSync(e.lockPath)}}async function Tt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let n=H(e.lockPath);return!n||!S(n.pid,n.processStartTime)?(W(e.lockPath),!0):!1}async function q(e){await pe(e.pid,{termTimeoutMs:L,killTimeoutMs:R,expectedStartTime:e.processStartTime})}function Et(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Dt(e,t=ue(process.env.AGENT_DEVICE_STATE_DIR)){let n=Ot(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 Ot(e){return`rm -f ${b(e.infoPath)} ${b(e.lockPath)}`}function kt(e){if(!w.existsSync(e))return null;try{return JSON.parse(w.readFileSync(e,`utf8`))}catch{return null}}function At(e){try{w.existsSync(e)&&w.unlinkSync(e)}catch{}}function J(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function jt(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(ge(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return me(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 Mt(e,t){return he(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function Nt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=jt({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=y(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 Pt(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=jt({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=y(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(J(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 Ft=1e4,It=8388608;function Lt(e,t){return _(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Rt(e){let{logPath:t,...n}=e;return n}async function zt(e,t){let n=Rt(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=_e(t.stateDir,r),a=await Bt({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 Bt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Lt(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await v(i.protocol);return await w.promises.mkdir(C.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}w.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),...re(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=w.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>It&&(s.destroy(),n.destroy(),o(`record exceeds ${It} 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 ${Ft}ms`),s.destroy()},Ft);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function Vt(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=Ht(e);if(n.error){Ut(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}qt(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 Ht(e){return JSON.parse(e)}async function Ut(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Wt(e);if(!n.baseUrl){a(Kt(s,o));return}a(Kt(await zt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Wt(e){let t=e.data??{},n=Gt(t.cause);return{code:i(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:r(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function Gt(t){return e(t)}function Kt(e,n){return new t(i(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 qt(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await ht(e,t,n):n)}catch(e){i(e)}}function Jt(e,t){let n=e.meta?.requestId??u();return Yt(e.command)?{jsonrpc:`2.0`,id:n,method:Xt(e.command),params:{...Zt(e,e.command,t),...e.command===`lease_allocate`?o(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Yt(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function Xt(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 Zt(e,t,n){return s(a(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Qt=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],$t=new Set([`apple`,`ios`,`macos`]);function en(e){return e!==void 0&&$t.has(e)}function tn(e,n,r,i,a,o,s){let c=a?{terminated:0}:an(),l=!a&&nn(i),u=l?on(e,n):{forcedKill:!1},f=en(s)||c.terminated>0;return d({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:r,command:i,timedOutRunnerPidsTerminated:c.terminated,timedOutRunnerCleanupError:c.error,daemonPidReset:l?e.pid:void 0,daemonPidForceKilled:l?u.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!l,daemonBaseUrl:e.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:r,hint:rn({remote:a,resetDaemon:l,command:i,appleCleanupEvidence:f})})}function nn(e){return c(e).onTimeout===`reset-daemon`}function rn(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i}=e;if(t)return`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 an(){let e=0;try{for(let t of Qt)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 on(e,t){let n=!1;try{S(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{q(e)}finally{U(t.infoPath),W(t.lockPath)}return{forcedKill:n}}const sn=`Daemon HTTP endpoint is unavailable`,cn=`Daemon socket endpoint is unavailable`;async function ln(e,t){let n=vn(e,t);if(await un(e,n))return!0;let r=yn(e,t,n);return r?await un(e,r):!1}async function un(e,t){return t===`http`?await fn(e):await dn(e.port)}function dn(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 fn(e){return mn(e).then(e=>e.reachable)}async function pn(e){let n=await mn(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:x(),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 mn(e){let t=e.baseUrl?_(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 v(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,...hn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function hn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?gn(t.upstream):void 0;return{...gn(t),...n?{upstream:n}:{}}}catch{return{}}}function gn(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 _n(e,t,n,r,i,a={}){let o=vn(e,n);try{return await X(e,t,r,i,o,a)}catch(s){let c=yn(e,n,o);if(!c||!bn(s,o))throw s;return await X(e,t,r,i,c,a)}}async function X(e,t,n,r,i,a){return i===`http`?await wn(e,t,n,r,a):await Cn(e,t,n,r,a)}function vn(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 xn(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 yn(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return Z(e,r)?r:null}function bn(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function xn(e,n){if(Z(e,n))return n;throw new t(`COMMAND_FAILED`,n===`http`?sn:cn)}function Sn(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 Cn(e,n,r,i,a){let o=e.port;if(!o)throw new t(`COMMAND_FAILED`,cn);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(tn(e,r,n.meta?.requestId,n.command,!1,i,n.flags?.platform))},i):void 0;Nt(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(Sn(e,n.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function wn(e,n,r,i,a){let o=e.baseUrl?new URL(_(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new t(`COMMAND_FAILED`,sn);let s=JSON.stringify(Jt(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 v(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(Mt(n,i.headers?.[`content-type`])){Pt(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:t=>Vt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})});return}ne(i).then(t=>{m&&clearTimeout(m),Vt(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=Et(e),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(tn(e,r,n.meta?.requestId,n.command,p,i,n.flags?.platform))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(Sn(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 Tn(e,t){let n=En(e),r=Dn(e,t),i=On(e,r.remoteBaseUrl),a=kn(e,n,r.rawBaseUrl),o=a?An():n;return{paths:ue(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function En(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function Dn(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Xn(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Zn(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function On(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=le(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:de(a)}}function kn(e,t,n){return Un(e.command)&&!t&&!n}function An(){return w.mkdtempSync(C.join(be.tmpdir(),`agent-device-replay-daemon-`))}async function jn(e){if(e.remoteBaseUrl)return await Mn(e);let t=await Nn(e);return t?{info:t,startedByClient:!1}:(wt(e.paths),await Rn(e))}async function Mn(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await pn(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 Nn(e){let t=z(e.paths.infoPath);if(!t)return null;let n=await In(t,await Pn(t,e.transportPreference));return n?(Ln(t,n,e.paths.baseDir),await q(t),U(e.paths.infoPath),null):t}async function Pn(e,t){try{return await ln(e,t)}catch(e){if(Fn(e))return!1;throw e}}function Fn(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}async function In(e,t){if(e.version!==x())return`version mismatch (client v${x()})`;if(e.codeSignature!==await bt())return`code-signature mismatch`;if(!t)return`unreachable`}function Ln(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 Rn(e){let n=0,r=[],i,a;for(let t=1;t<=2;t+=1){let o;try{o=qn(e),a={pid:o.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await G(e.paths,`start_error`)),t<2){await h(150);continue}break}let s=await Kn(Q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=Jn(s.exit),r.push(await G(e.paths,`start_error`)),t<2){await h(150);continue}break}if(await Tt(e.paths)){n+=1;continue}let c=K(e.paths),l=t<2,u=await G(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Kn(Q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=Jn(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await h(150)}let o=K(e.paths),s=Yn(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:Dt(o,e.paths)})}async function zn(e,t,n,r){if(!Un(e.command)||!t.startedByClient&&!n.ownedStateDir||Et(t.info)||Vn(r)||Wn(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await q(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=w.existsSync(n.paths.infoPath);U(n.paths.infoPath),i.removedInfo=e&&!w.existsSync(n.paths.infoPath);let t=w.existsSync(n.paths.lockPath);if(W(n.paths.lockPath),i.removedLock=t&&!w.existsSync(n.paths.lockPath),n.ownedStateDir){let e=ce(n.paths.sessionsDir);e?a=Bn(r,e):(w.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!w.existsSync(n.paths.baseDir))}}return d({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Bn(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 Vn(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:ae(e.error.details?.divergence)?.repairSessionHeld===!0}function Hn(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 Un(e){return e===l.replay||e===l.test}function Wn(e,t){return e.command!==l.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Gn(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${ie(t)}`]:[],...r?[`--session ${ie(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 Kn(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=z(t.paths.infoPath);if(e&&await ln(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await h(100)}return{kind:`timeout`}}function qn(e){let t=I(),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};w.mkdirSync(e.paths.baseDir,{recursive:!0});let i=w.openSync(e.paths.logPath,`a`),a=w.openSync(e.paths.logPath,`a`);try{return p(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{w.closeSync(i),w.closeSync(a)}}function Jn(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 Yn(e){try{if(!w.existsSync(e))return;let t=w.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=w.openSync(e,`r`);try{let e=Buffer.alloc(n);w.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{w.closeSync(r)}}catch{return}}function Xn(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 Zn(e,n){if(!e)return;let r=new URL(e).hostname;if(!Qn(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 Qn(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{Wn as a,_n as c,jn as i,rt as l,Hn as n,Vn as o,zn as r,Tn as s,Gn as t};
|
package/dist/src/daemon.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{C as e}from"./sdk-contracts.js";import{p as t}from"./owner-identity.js";import{t as n}from"./timeouts.js";import"./retry.js";import{n as r}from"./config.js";import"./process.js";import{i,r as a,t as o}from"./daemon-process.js";import{n as s}from"./daemon-registration.js";import{n as c}from"./daemon-shutdown-report.js";import{t as l}from"./shared.js";import u from"node:fs";async function d(n){let r=s(n.paths.infoPath);if(!r)return h();if(!r.startTime){if(!t(r.pid))return h();throw new e(`COMMAND_FAILED`,`Refusing to stop a daemon without a verified process start-time identity.`,{pid:r.pid})}if(!o(r.pid,r.startTime)){if(!t(r.pid))return h();throw new e(`COMMAND_FAILED`,`Refusing to stop a daemon whose PID or start-time identity could not be verified.`,{pid:r.pid,processStartTime:r.startTime})}let a={pid:r.pid,startTime:r.startTime};if(!f(r.pid,`SIGTERM`))return h();let{exited:c}=await i(a,{timeoutMs:n.graceTimeoutMs??1e4});if(c)return await m(n.paths,1e3),{stopped:!0,mode:`graceful`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],claimsSuperseded:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]};o(r.pid,r.startTime)&&f(r.pid,`SIGKILL`);let{exited:l}=await i(a,{timeoutMs:n.killTimeoutMs??2e3});if(!l)throw new e(`COMMAND_FAILED`,`Daemon did not exit after SIGKILL.`,{pid:r.pid});return{stopped:!0,mode:`forced`,cleanupConfidence:`unknown`,claimsReleased:[],claimsOrphaned:[],claimsSuperseded:[],providerReleases:{status:`unknown`,released:[],pending:null},warnings:[`The daemon was force-killed before provider lease state could be finalized. Provider allocations may remain active.`]}}function f(n,r){if(a(n,r))return!0;if(!t(n))return!1;throw new e(`COMMAND_FAILED`,`Daemon could not be signaled with ${r}.`,{pid:n,signal:r})}function p(e){let t=s(e);return t?.startTime?{pid:t.pid,processStartTime:t.startTime}:null}async function m(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!u.existsSync(e.infoPath)&&!u.existsSync(e.lockPath))return;await n(25)}}function h(){return{stopped:!1,mode:`not-running`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],claimsSuperseded:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]}}function g(){return Object.freeze({cleanup:async e=>{let{cleanupRunnerLeasesForOwner:t}=await import(`./runner-operations-facade.js`);await t(e)}})}const _=g(),v=async({positionals:t,flags:n})=>{if(t[0]!==`stop`||t.length!==1)throw new e(`INVALID_ARGS`,`daemon accepts only: stop`);let i=r(n.stateDir),a=p(i.infoPath),o=await d({paths:i}),s=y(o,o.mode===`graceful`?c(i.baseDir):null),u=n.clean===!0&&a!==null&&s.stopped;u&&await _.cleanup({pid:a.pid,startTime:a.processStartTime});let f={...s,clean:u};return await l(n,f,()=>S(f)),!0};function y(e,t){return e.mode!==`graceful`||t?t?{...e,providerReleases:{status:`completed`,...t.providerReleases},claimsReleased:t.claims.released,claimsOrphaned:t.claims.orphaned,claimsSuperseded:t.claims.superseded,warnings:[...e.warnings,...b(t.claims.superseded),...x(t.claims.orphaned)]}:e:{...e,cleanupConfidence:`unknown`,providerReleases:{status:`unknown`,released:[],pending:null},warnings:[...e.warnings,`The graceful shutdown report is unavailable, so provider cleanup state is unknown. Provider allocations may remain active.`]}}function b(e){return e.length===0?[]:[`Another owner had already claimed ${e.map(e=>e.deviceId).join(`, `)} before this daemon released it, so those devices are now owned elsewhere.`]}function x(e){return e.length===0?[]:[`Ownership of ${e.map(e=>e.deviceId).join(`, `)} was not released cleanly; the claim now blocks other owners until it is settled. Inspect with: agent-device device status --stale, then release with: agent-device device release --stale.`]}function S(e){return[e.stopped?`Daemon stopped (${e.mode}).`:`No running daemon found.`,e.clean?`Retained runner cleanup completed.`:null,...e.warnings].filter(e=>!!e).join(`
|
|
2
2
|
`)}export{v as daemonCommand};
|