agent-device 0.21.20 → 0.21.21
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.20.apk → agent-device-android-ime-helper-0.21.21.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.21.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.20.manifest.json → agent-device-android-ime-helper-0.21.21.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.21.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.21.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.20.manifest.json → agent-device-android-snapshot-helper-0.21.21.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/AppWindowScreenshot.swift +73 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/BackgroundInteraction.swift +557 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/GhostCursor.swift +141 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +107 -3
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +136 -22
- package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/BackgroundInteractionTests.swift +88 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +121 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +10 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +36 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +27 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +6 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +7 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +21 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +121 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +179 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryConfirmation.swift +119 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +8 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +23 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +59 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +112 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +25 -12
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +6 -1
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +43 -13
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/alert.js +1 -1
- package/dist/src/android-adb.d.ts +12 -0
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/app-backend.js +1 -0
- package/dist/src/app-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +2 -2
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-log-session-resource.js +1 -0
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +2 -2
- 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/back-mode.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/cache.js +1 -1
- package/dist/src/capabilities.js +1 -1
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +13 -5
- 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-options.js +3 -0
- package/dist/src/client-types.d.ts +88 -5
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/cloud-artifacts.d.ts +7 -2
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-artifacts.js +1 -0
- package/dist/src/daemon-client-lease-beat.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-liveness-probe.js +1 -0
- package/dist/src/daemon-client-transport.js +1 -1
- package/dist/src/daemon-http.js +1 -0
- package/dist/src/daemon-policy-file.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -0
- package/dist/src/daemon-registration.js +1 -1
- package/dist/src/daemon-resolution.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +2 -2
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +1 -1
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-readiness-runtime.js +1 -1
- package/dist/src/device-release.js +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -3
- package/dist/src/device3.js +3 -0
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +3 -3
- package/dist/src/dispatch-resolve.js +4 -1
- package/dist/src/display-inventory.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -0
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.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/host-file.js +1 -1
- package/dist/src/host.js +1 -1
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +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-source.d.ts +5 -0
- package/dist/src/install-source2.js +1 -1
- package/dist/src/instance-client.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -1
- package/dist/src/interactor.js +5 -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 +1 -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 +4 -4
- 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-client.js +4 -30
- package/dist/src/ios-settings.js +1 -0
- package/dist/src/ios-snapshot-engine.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/launch-confirmation.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-registry-scope.js +1 -0
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/legacy-xctest-device-set.js +1 -1
- package/dist/src/limrun-download-file.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +28 -2
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/load.js +1 -0
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/macos-facade.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +16 -16
- package/dist/src/observation.js +1 -1
- package/dist/src/observe-until.js +1 -1
- package/dist/src/overlay.js +2 -2
- package/dist/src/owner-identity.js +3 -3
- package/dist/src/path-resolution.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-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-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plugins.d.ts +9 -0
- package/dist/src/plugins.js +1 -0
- package/dist/src/plugins2.js +2 -0
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-size.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/project-runtime.js +1 -1
- package/dist/src/provider-credential-fingerprint.js +1 -0
- package/dist/src/provider-device-admission.js +1 -1
- package/dist/src/provider-device-runtimes.js +1 -0
- package/dist/src/provider-limrun-credentials.js +1 -0
- package/dist/src/provider-profile-fields.js +1 -0
- package/dist/src/provider-session-ownership.js +2 -2
- package/dist/src/provider-webdriver.js +2 -1
- package/dist/src/providers.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +39 -39
- 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 +5 -5
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-cancellation.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/runner-artifact-manifest.js +1 -1
- package/dist/src/runner-cache-metadata.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +2 -2
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-session-types.js +1 -1
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-admission.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +3 -3
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-result.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.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 +45 -2
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +33 -4
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +2 -2
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-artifact-paths.js +1 -1
- package/dist/src/session-repair-tombstone.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-stream.js +27 -0
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -1
- package/dist/src/simctl-settings-facade.js +1 -0
- package/dist/src/simctl-settings.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-diagnostics.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 +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/store.js +1 -0
- package/dist/src/string-enum.js +1 -1
- package/dist/src/surface-snapshot.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/target-evidence.js +1 -1
- package/dist/src/telemetry.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/toolchain-probe.js +2 -2
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/touch-runtime2.js +1 -1
- package/dist/src/transport.js +2 -2
- 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/vars.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/package.json +5 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.20.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk.sha256 +0 -1
- package/dist/src/api.js +0 -3
- package/dist/src/daemon-process.js +0 -1
- package/dist/src/multitouch-support.js +0 -1
- package/dist/src/parameterized-recorded-fill.js +0 -1
- package/dist/src/runner-startup-transport.js +0 -1
- package/dist/src/runner-xctestrun.js +0 -1
- package/dist/src/session-store.js +0 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as e,c as t,f as n,u as r}from"./sdk-contracts.js";import{C as i,E as a,S as o,o as s,s as c}from"./sdk-device.js";import{a as l,c as u,l as d,r as f}from"./lease-scope.js";import{n as p,t as m}from"./catalog.js";import{t as h}from"./sdk-remote-config.js";import{t as g}from"./prepare-kind.js";import{r as _}from"./diagnostics.js";import{k as v}from"./owner-identity.js";import{p as y}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as b}from"./base-url.js";import{i as te,r as ne}from"./client-metro-companion.js";import{n as re}from"./metro2.js";import{n as ie,r as x,t as ae}from"./remote-config2.js";import{n as S,t as C}from"./providers.js";import w from"node:path";import T from"node:fs";import E from"node:crypto";const oe={slug:`react-devtools-companion`,runArg:b,displayName:`React DevTools companion`};async function se(e){return await ne({...e,definition:oe,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function D(e){return await te({...e,definition:oe})}function O(e){return e===`android-instance`||e===`ios-instance`}function ce(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function le(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!le(e)}function ue(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function de(e){let t=e?.metroPublicBaseUrl?.trim();return t?ue(t):null}function fe(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=de(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function pe(e,t={}){let n=fe(e,t);return(await y(`npm`,ce(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function A(e){let t=i(e),n=r(t);return{platform:t,target:e.target,leaseBackend:n,identityFlag:n?c(t):void 0,id:e.id}}function me(e){return`${e.platform}:${e.target??`mobile`}:${e.id}`}function j(e){let t=[e.leaseBackend?n(e.leaseBackend):void 0,e.recordedPlatform].filter(e=>e!==void 0);if(t.some(e=>t.some(t=>o(e,t)))||o(e.requestedPlatform,t[0]??e.recordedPlatform))return{ok:!1,boundPlatform:t[0],requestedPlatform:e.requestedPlatform};let r=[...t,e.requestedPlatform].filter(e=>e!==void 0);return{ok:!0,platform:r.find(e=>e!==`apple`)??r[0]}}function he(e,t){return t!==void 0&&e.platform===void 0?!1:j({leaseBackend:e.leaseBackend,recordedPlatform:e.platform,requestedPlatform:t}).ok}function M(e){let t=z(e);if(!T.existsSync(t))return null;let n;try{n=JSON.parse(T.readFileSync(t,`utf8`))}catch(t){return W(e,t),null}return Se(n)?n:(W(e),null)}function N(e){let t=z({stateDir:e.stateDir,session:e.state.session});T.mkdirSync(w.dirname(t),{recursive:!0}),U(t,e.state),U(B(e.stateDir),{session:e.state.session})}function P(e){return{baseUrl:be(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function F(e){T.rmSync(z(e),{force:!0});let t=B(e.stateDir);H(e.stateDir)===e.session&&T.rmSync(t,{force:!0})}function ge(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?ie({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=M(t)??(t.allowActiveFallback?V({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&R(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=ye(i,t),o=l(i);return{runtime:i.runtime,connection:d(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...u(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function I(e){return d(l(e))}function L(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function _e(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function R(t){try{return E.createHash(`sha256`).update(T.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function z(e){return w.join(e.stateDir,`remote-connections`,`${xe(e.session)}.json`)}function B(e){return w.join(e,`remote-connections`,`.active-session.json`)}function V(e){let t=H(e.stateDir);return t?M({stateDir:e.stateDir,session:t}):null}function H(e){let t=B(e);if(T.existsSync(t))try{let e=JSON.parse(T.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function ve(e){if(e)return E.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function ye(e,t){try{return x({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function U(e,t){v({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function be(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function W(e,t){_({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),F(e)}function xe(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${E.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Se(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&Ce(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&we(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&Te(t.daemon)}function Ce(e,t){return t.every(t=>typeof e[t]==`string`)}function we(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function Te(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:Ee(e)}function Ee(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const De=h.map(e=>e.key);function G(e){let t={};for(let n of De){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Oe(e){return e.remoteConfig?{...G(x({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function ke(e){return e===`cloud`||e===`proxy`||K(e)}function K(e){return e===`limrun`||S(e)}function Ae(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function q(e){let t=K(e),n=S(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===C.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function J(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function je(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const Y=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),X=new Set([`open`]),Me=new Set([p.open,p.install,p.reinstall,m.installSource]);async function Ne(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=x({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...G(o.profile),...r,remoteConfig:o.resolvedPath},c=M({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??st(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=q(l.leaseProvider).supportsDeferredAppSelection,f=d&&n===p.open?t.positionals?.[0]:void 0;d&&delete u.providerApp;let m=ot(l.runtime,u.platform)??t.runtime,h=l,g=!c,_,v=Ve(h);if(v.shouldAllocate(n)){let e=await Re({command:n,client:i,state:l,nextState:h,nextFlags:u,initialApp:f,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=j({leaseBackend:h.leaseBackend,recordedPlatform:h.platform,requestedPlatform:u.platform});if(!y.ok)throw $({session:l.session,leaseBackend:h.leaseBackend,boundPlatform:y.boundPlatform,requestedPlatform:y.requestedPlatform,detail:`bound-connection`});h={...h,platform:y.platform},u.platform=y.platform;let b=await Pe({command:n,flags:u,client:i,state:l,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=b.state,m=b.runtime,g||=b.changed,await Le({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:b.preparedMetroCleanupOnFailure,metroCleanupToStop:b.metroCleanupToStop}),{flags:{...u,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??u.platform,target:h.target??u.target},runtime:m,connection:I(h)}}async function Pe(t){let{command:n,flags:r,state:i,client:a}=t,o=Fe(t.nextState,r),s=t.runtime;if(!nt(n,r,t.batchSteps,t.positionals)||!rt(r)||!Ie(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Ke(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!at(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function Fe(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ie(e,t,n){return e===!0||!t||!it(t,n)}async function Le(e){if(e.changed)try{N({stateDir:e.stateDir,state:e.state})}catch(t){throw await Z(e.preparedMetroCleanupOnFailure),await et(e.client,e.state,e.acquiredLeaseForCleanup),t}await Z(e.metroCleanupToStop)}async function Re(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&ut(i,c.device);let l=s.leaseBackend??o??tt(i,t);ft(r,l);let u=j({leaseBackend:l,recordedPlatform:s.platform,requestedPlatform:i.platform});if(!u.ok)throw $({session:r.session,leaseBackend:l,boundPlatform:u.boundPlatform,requestedPlatform:u.requestedPlatform,detail:`bound-connection`});pt(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await ct(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,ze(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:Be(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function ze(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Be(e,t,n,r){let i=L(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Ve(e){let t=q(e.leaseProvider);return t.leaseKind===`proxy`?We:t.supportsDeferredAppSelection?He:t.usesCloudWebDriverLease?Ge:Ue}const He={shouldAllocate:e=>e!==p.apps&&!Y.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ue={shouldAllocate:e=>!Y.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},We={shouldAllocate:e=>e!==`devices`&&!Y.has(e),ttlMs:()=>3e5,resolveLeaseState:lt},Ge={shouldAllocate:e=>!Y.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Ke(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:g(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Z(e){if(e)try{await re(e)}catch{}}async function qe(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function Je(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...I(t)}):{released:!1}}function Ye(e){let t=Xe(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Xe(e,t,n){try{let{profile:r}=ae({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&Ze(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function Ze(e,t){let n=P({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Qe(e,t,n){if(!t.leaseId)return;let r=Ye({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return $e(t,`no credential known to belong to that endpoint was available`);try{await Je(e,t,r.daemonAuthToken);return}catch{return $e(t,`the release request failed`)}}function $e(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function et(e,t,n){if(n)try{let r=L(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){return e.leaseBackend??r(e.platform)}function tt(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function nt(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:X.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return X.has(t)&&e.runtime===void 0})}function rt(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function it(e,n){return!e.platform||!n||!t(n)||e.platform===n}function at(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ot(e,t){if(e)return it(e,t)?e:void 0}function st(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&q(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:R(n),daemon:P(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function ct(e,t,n,r,i,a){let o=I(t);if(t.leaseId&&t.leaseBackend===n){let i=await mt(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...J(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function lt(t){if(!Me.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await dt(t.client,t.flags),r=A(n);return{state:{...t.state,deviceKey:me(r),leaseBackend:t.state.leaseBackend??t.leaseBackend??r.leaseBackend,platform:r.platform,target:t.state.target??r.target,updatedAt:new Date().toISOString()},device:n}}function ut(e,t){let n=A(t);e.platform=n.platform,e.target=n.target??e.target,n.identityFlag===`udid`&&(e.udid=n.id),n.identityFlag===`serial`&&(e.serial=n.id)}async function dt(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await a(n.map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $(t){return new e(`INVALID_ARGS`,t.detail===`bound-connection`?`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`:`The requested platform does not match the device this lease backend rents.`,{session:t.session,leaseBackend:t.leaseBackend,platform:t.boundPlatform,requestedPlatform:t.requestedPlatform,reason:`CONNECTION_PLATFORM_CONFLICT`})}function ft(t,n){if(t.leaseBackend&&t.leaseBackend!==n)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend})}function pt(t,n){if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function mt(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(f(e))return;throw e}}export{O as A,V as C,ge as D,F as E,D as M,N as O,j as S,_e as T,I as _,Je as a,R as b,qe as c,Ae as d,q as f,P as g,Oe as h,Qe as i,se as j,pe as k,J as l,G as m,rt as n,Q as o,ke as p,Ne as r,Z as s,$ as t,je as u,he as v,M as w,L as x,ve as y};
|
|
1
|
+
import{P as e,d as t,l as n,p as r}from"./sdk-contracts.js";import{r as i}from"./diagnostics.js";import"./diagnostics2.js";import{C as a,D as o,o as s,s as c,w as l}from"./sdk-device.js";import{a as u,c as d,l as f,r as p}from"./lease-scope.js";import{n as m,t as h}from"./catalog.js";import{t as g}from"./sdk-remote-config.js";import{t as _}from"./prepare-kind.js";import{A as v}from"./owner-identity.js";import{p as y}from"./exec.js";import"./file.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as b}from"./base-url.js";import{i as te,r as ne}from"./client-metro-companion.js";import{n as re}from"./metro2.js";import{n as ie,r as x,t as ae}from"./remote-config2.js";import{a as S,n as C}from"./providers.js";import w from"node:crypto";import T from"node:fs";import E from"node:path";const D={slug:`react-devtools-companion`,runArg:b,displayName:`React DevTools companion`};async function oe(e){return await ne({...e,definition:D,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 O(e){return await te({...e,definition:D})}function se(e){return e===`android-instance`||e===`ios-instance`}function ce(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function le(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function ue(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!le(e)}function de(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 fe(e){let t=e?.metroPublicBaseUrl?.trim();return t?de(t):null}function pe(t,n={}){if(!ue(t)||!n.flags?.metroProxyBaseUrl||!se(n.flags.leaseBackend))return t;let r=fe(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 me(e,t={}){let n=pe(e,t);return(await y(`npm`,ce(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function k(e){let n=l(e),r=t(n);return{platform:n,target:e.target,leaseBackend:r,identityFlag:r?c(n):void 0,id:e.id}}function he(e){return`${e.platform}:${e.target??`mobile`}:${e.id}`}function A(e){let t=[e.leaseBackend?r(e.leaseBackend):void 0,e.recordedPlatform].filter(e=>e!==void 0);if(t.some(e=>t.some(t=>a(e,t)))||a(e.requestedPlatform,t[0]??e.recordedPlatform))return{ok:!1,boundPlatform:t[0],requestedPlatform:e.requestedPlatform};let n=[...t,e.requestedPlatform].filter(e=>e!==void 0);return{ok:!0,platform:n.find(e=>e!==`apple`)??n[0]}}function ge(e,t){return t!==void 0&&e.platform===void 0?!1:A({leaseBackend:e.leaseBackend,recordedPlatform:e.platform,requestedPlatform:t}).ok}function j(e){let t=R(e);if(!T.existsSync(t))return null;let n;try{n=JSON.parse(T.readFileSync(t,`utf8`))}catch(t){return U(e,t),null}return Ce(n)?n:(U(e),null)}function M(e){let t=R({stateDir:e.stateDir,session:e.state.session});T.mkdirSync(E.dirname(t),{recursive:!0}),H(t,e.state),H(z(e.stateDir),{session:e.state.session})}function N(e){return{baseUrl:xe(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function P(e){T.rmSync(R(e),{force:!0});let t=z(e.stateDir);V(e.stateDir)===e.session&&T.rmSync(t,{force:!0})}function _e(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?ie({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=j(t)??(t.allowActiveFallback?B({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&L(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=be(i,t),o=u(i);return{runtime:i.runtime,connection:f(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...d(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function F(e){return f(u(e))}function I(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function ve(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function L(t){try{return w.createHash(`sha256`).update(T.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function R(e){return E.join(e.stateDir,`remote-connections`,`${Se(e.session)}.json`)}function z(e){return E.join(e,`remote-connections`,`.active-session.json`)}function B(e){let t=V(e.stateDir);return t?j({stateDir:e.stateDir,session:t}):null}function V(e){let t=z(e);if(T.existsSync(t))try{let e=JSON.parse(T.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function ye(e){if(e)return w.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function be(e,t){try{return x({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function H(e,t){v({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function xe(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 U(e,t){i({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),P(e)}function Se(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${w.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Ce(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&we(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&Te(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&Ee(t.daemon)}function we(e,t){return t.every(t=>typeof e[t]==`string`)}function Te(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function Ee(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:De(e)}function De(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 Oe=g.map(e=>e.key);function W(e){let t={};for(let n of Oe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function ke(e){return e.remoteConfig?{...W(x({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ae(e){return e===`cloud`||e===`proxy`||G(e)}function G(e){return e===`limrun`||S(e)}function je(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function K(e){let t=G(e),n=S(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===C.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function q(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Me(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 J=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),Ne=new Set([`open`]),Pe=new Set([m.open,m.install,m.reinstall,h.installSource]);async function Fe(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=x({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...W(o.profile),...r,remoteConfig:o.resolvedPath},c=j({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??lt(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=K(l.leaseProvider).supportsDeferredAppSelection,f=d&&n===m.open?t.positionals?.[0]:void 0;d&&delete u.providerApp;let p=ct(l.runtime,u.platform)??t.runtime,h=l,g=!c,_,v=Ue(h);if(v.shouldAllocate(n)){let e=await Be({command:n,client:i,state:l,nextState:h,nextFlags:u,initialApp:f,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=A({leaseBackend:h.leaseBackend,recordedPlatform:h.platform,requestedPlatform:u.platform});if(!y.ok)throw $({session:l.session,leaseBackend:h.leaseBackend,boundPlatform:y.boundPlatform,requestedPlatform:y.requestedPlatform,detail:`bound-connection`});h={...h,platform:y.platform},u.platform=y.platform;let b=await Ie({command:n,flags:u,client:i,state:l,nextState:h,runtime:p,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=b.state,p=b.runtime,g||=b.changed,await ze({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:b.preparedMetroCleanupOnFailure,metroCleanupToStop:b.metroCleanupToStop}),{flags:{...u,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??u.platform,target:h.target??u.target},runtime:p,connection:F(h)}}async function Ie(t){let{command:n,flags:r,state:i,client:a}=t,o=Le(t.nextState,r),s=t.runtime;if(!ot(n,r,t.batchSteps,t.positionals)||!Z(r)||!Re(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 Ye(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!st(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 Le(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Re(e,t,n){return e===!0||!t||!Q(t,n)}async function ze(e){if(e.changed)try{M({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await it(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Be(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??X(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&ft(i,c.device);let l=s.leaseBackend??o??at(i,t);mt(r,l);let u=A({leaseBackend:l,recordedPlatform:s.platform,requestedPlatform:i.platform});if(!u.ok)throw $({session:r.session,leaseBackend:l,boundPlatform:u.boundPlatform,requestedPlatform:u.requestedPlatform,detail:`bound-connection`});ht(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await ut(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,Ve(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:He(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function Ve(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function He(e,t,n,r){let i=I(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 Ue(e){if(e.leaseBackend===`macos-app`)return qe;let t=K(e.leaseProvider);return t.leaseKind===`proxy`?Ke:t.supportsDeferredAppSelection?We:t.usesCloudWebDriverLease?Je:Ge}const We={shouldAllocate:e=>e!==m.apps&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ge={shouldAllocate:e=>!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ke={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>3e5,resolveLeaseState:dt},qe={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async({state:t})=>{if(!t.leaseId||!t.deviceKey)throw new e(`INVALID_ARGS`,`A macos-app connection needs the leaseId and deviceKey the host allocated in its remote config.`);return{state:{...t,platform:`macos`}}}},Je={shouldAllocate:e=>!J.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Ye(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:_(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 re(e)}catch{}}async function Xe(e){try{await O({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}function Ze(e){return e.leaseBackend===`macos-app`}async function Qe(e,t,n){return!t.leaseId||Ze(t)?{released:!1}: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,...F(t)})}function $e(e){let t=et(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 et(e,t,n){try{let{profile:r}=ae({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&tt(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function tt(e,t){let n=N({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function nt(e,t,n){if(!t.leaseId||Ze(t))return;let r=$e({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return rt(t,`no credential known to belong to that endpoint was available`);try{await Qe(e,t,r.daemonAuthToken);return}catch{return rt(t,`the release request failed`)}}function rt(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 it(e,t,n){if(n)try{let r=I(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function X(e){return e.leaseBackend??t(e.platform)}function at(t,n){let r=X(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 ot(e,t,n,r=[]){return e===`cdp`?ue(r)&&!!t.metroPublicBaseUrl:Ne.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return Ne.has(t)&&e.runtime===void 0})}function Z(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Q(e,t){return!e.platform||!t||!n(t)||e.platform===t}function st(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ct(e,t){if(e)return Q(e,t)?e:void 0}function lt(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&&K(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:L(n),daemon:N(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??X(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function ut(t,n,r,i,a,o){let s=F(n);if(n.leaseId&&n.leaseBackend===r){let e=await gt(t,n.leaseId,{tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n)});if(e)return{lease:e,acquired:!1}}if(r===`macos-app`)throw new e(`UNAUTHORIZED`,`The host-allocated macos-app lease is no longer active.`,{reason:`LEASE_NOT_FOUND`,leaseId:n.leaseId,hint:`Ask the host for a new macos-app lease and update the remote config.`});return{lease:await t.leases.allocate({tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n),platform:n.platform??a.platform,target:n.target??a.target,device:a.device,udid:a.udid,serial:a.serial,providerApp:o??a.providerApp,providerOsVersion:a.providerOsVersion,providerProject:a.providerProject,providerBuild:a.providerBuild,providerSessionName:a.providerSessionName,...q(a),awsProjectArn:a.awsProjectArn,awsDeviceArn:a.awsDeviceArn,awsAppArn:a.awsAppArn,awsRegion:a.awsRegion,awsInteractionMode:a.awsInteractionMode}),acquired:!0}}async function dt(t){if(!Pe.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 pt(t.client,t.flags),r=k(n);return{state:{...t.state,deviceKey:he(r),leaseBackend:t.state.leaseBackend??t.leaseBackend??r.leaseBackend,platform:r.platform,target:t.state.target??r.target,updatedAt:new Date().toISOString()},device:n}}function ft(e,t){let n=k(t);e.platform=n.platform,e.target=n.target??e.target,n.identityFlag===`udid`&&(e.udid=n.id),n.identityFlag===`serial`&&(e.serial=n.id)}async function pt(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await o(n.map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $(t){return new e(`INVALID_ARGS`,t.detail===`bound-connection`?`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`:`The requested platform does not match the device this lease backend rents.`,{session:t.session,leaseBackend:t.leaseBackend,platform:t.boundPlatform,requestedPlatform:t.requestedPlatform,reason:`CONNECTION_PLATFORM_CONFLICT`})}function mt(t,n){if(t.leaseBackend&&t.leaseBackend!==n)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend})}function ht(t,n){if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function gt(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(p(e))return;throw e}}export{se as A,B as C,_e as D,P as E,O as M,M as O,A as S,ve as T,F as _,Qe as a,L as b,Xe as c,je as d,K as f,N as g,ke as h,nt as i,oe as j,me as k,q as l,W as m,Z as n,X as o,Ae as p,Fe as r,Y as s,$ as t,Me as u,ge as v,j as w,I as x,ye as y};
|
package/dist/src/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{N as e,P as t}from"./sdk-contracts.js";import{s as n}from"./device-shell.js";import{a as r}from"./version.js";import{t as i}from"./daemon-resolution.js";import{r as a}from"./remote-config2.js";import{n as o}from"./src.js";import{n as s,r as c,t as l}from"./provider-webdriver.js";import{t as u}from"./providers.js";import{C as d,E as f,O as ee,S as p,T as m,_ as h,a as te,b as ne,c as g,d as re,f as _,g as ie,i as ae,l as oe,m as v,n as se,o as y,p as b,s as x,t as ce,u as S,v as le,w as C,x as ue,y as de}from"./connection-runtime.js";import{o as fe,r as pe}from"./auth-session.js";import{t as w}from"./shared.js";import T from"node:path";import E from"node:fs";import D from"node:crypto";const me=new Set([`daemonAuthToken`,`metroBearerToken`]);function he(e){let t=k(_e(e.profile)),n=T.join(e.stateDir,`remote-connections`,`generated`);E.mkdirSync(n,{recursive:!0,mode:448});let r=T.join(n,`${ye(e.provider)}-${ve(t)}.json`);E.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{E.chmodSync(r,384)}catch{}return r}function ge(n){try{return a(n)}catch(r){let i=t(r);throw new e(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function O(e){let t=ge({configPath:he({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:be(e.provider)});return{flags:{...v(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function _e(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!me.has(e)))}function ve(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function k(e){return Array.isArray(e)?e.map(k):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,k(t)])):e}function ye(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function be(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function A(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function xe(e){let t=await pe({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await j({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=A(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return O({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function j(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return M(await fe(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function M(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=t.connection;if(!n||typeof n!=`object`)throw new e(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return Se(n.remoteConfigProfile);throw new e(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Se(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(t).length===0)throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return t}function N(e){let t=we(e.provider)(e),n=A(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??y(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...S(e.flags)};return O({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const Ce=[{provider:u.browserStack,buildProfileFields:Te},{provider:u.awsDeviceFarm,buildProfileFields:De}];function we(t){let n=Ce.find(e=>e.provider===t)?.buildProfileFields;if(n)return n;throw new e(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${t}".`)}function Te(e){return I(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),I(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:P(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:F(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:F(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ee(F(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...oe(e.flags)}}function Ee(t,n){if(t.startsWith(`bs://`)||/^https?:\/\//i.test(t))return t;let r=T.resolve(n,t);try{if(E.statSync(r).isFile())return r}catch{}throw new e(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function De(e){let{env:t,flags:n}=e;c(n,u.awsDeviceFarm);let r=P(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=L(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:L(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:R(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:R(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??s(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function P(t,n){if(t===`android`||t===`ios`)return t;throw new e(`INVALID_ARGS`,n)}function F(t,n){if(t)return t;throw new e(`INVALID_ARGS`,n)}function I(t,n,r){let i=t?.[n];if(i)return i;throw new e(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function L(e,t,n,r){return F(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Oe(t){let n=t.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new e(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=ke({flags:t.flags});return O({stateDir:t.stateDir,provider:`limrun`,profile:r,cwd:t.cwd,env:n,flags:t.flags})}function ke(e){let t=e.flags,n=Ae(t);return{stateDir:i(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...S(t)}}function Ae(t){if(t.platform!==`android`&&t.platform!==`ios`)throw new e(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(t.device!==void 0)throw new e(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=y(t),r=t.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new e(`INVALID_ARGS`,`connect limrun --platform ${t.platform} requires --lease-backend ${r}.`);return r}function je(t){let n=t.flags.daemonBaseUrl??t.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new e(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=A(t.stateDir,n,t.flags.session),i={daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`,daemonServerMode:t.flags.daemonServerMode,tenant:t.flags.tenant??`proxy`,sessionIsolation:t.flags.sessionIsolation??`tenant`,runId:t.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:t.flags.leaseBackend??y(t.flags),platform:t.flags.platform,target:t.flags.target,device:t.flags.device,udid:t.flags.udid,serial:t.flags.serial,iosSimulatorDeviceSet:t.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:t.flags.androidDeviceAllowlist,session:t.flags.session,...S(t.flags)};return O({stateDir:t.stateDir,provider:`proxy`,profile:i,cwd:t.cwd,env:t.env,flags:t.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`}})}const z={cloud:{resolve:xe,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:je,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>N({provider:`browserstack`,...e}),verify:Pe},"aws-device-farm":{resolve:e=>N({provider:`aws-device-farm`,...e}),verify:Fe},limrun:{resolve:Oe,verify:Ie}};async function Me(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=a({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...v(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...b(i)?{provider:i}:{}}}let r=e.provider??(Le(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Ne(e){return e.provider?await z[e.provider].verify({flags:e.flags,env:process.env}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function Pe(e){let{flags:t,env:n}=e;return await l.verifyConnection({provider:`browserstack`,username:B(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:V(t.platform,`BrowserStack`),deviceName:B(t.device,`BrowserStack profile missed device.`),osVersion:B(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:B(t.providerApp,`BrowserStack profile missed app.`)})}async function Fe(e){let{flags:t}=e;return await l.verifyConnection({provider:`aws-device-farm`,platform:V(t.platform,`AWS Device Farm`),projectArn:B(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:B(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function Ie(e){return await o({apiKey:B(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:r(),platform:V(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function Le(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function B(t,n){if(t!==void 0)return t;throw new e(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(t,n){if(t===`android`||t===`ios`)return t;throw new e(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function Re(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??ze();return{session:i,previous:n.session?C({stateDir:t,session:i}):null,remoteConfigHash:ne(r),daemon:ie(n)}}function ze(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=_(e.leaseProvider),r=n.leaseKind;if(r===`proxy`)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`};if(n.supportsDeferredAppSelection)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.`};if(r===`direct-device-provider`)return{status:`deferred`,nextSteps:G(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`};let i=e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``;return{status:`deferred`,nextSteps:q(e,[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`]),message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+i}}function Be(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...G(e,t)}}function Ve(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
-
`)}let a=
|
|
3
|
-
`)}function U(e){let{state:t,runtimePreparation:n,readiness:r,previousLeaseNotice:i}=e,a=H(t,r);return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:
|
|
4
|
-
`)),!0};function
|
|
5
|
-
`)}function
|
|
1
|
+
import{F as e,P as t}from"./sdk-contracts.js";import{a as n}from"./version.js";import{t as r}from"./daemon-resolution.js";import{r as i}from"./remote-config2.js";import{s as a}from"./device-shell.js";import{t as o}from"./device2.js";import{n as s}from"./src.js";import{a as c,i as l,n as u,r as d,t as f}from"./provider-webdriver.js";import{n as p,o as m}from"./providers.js";import{i as h,n as g,t as ee}from"./provider-limrun-credentials.js";import{n as _}from"./provider-profile-fields.js";import{C as te,E as ne,O as re,S as ie,T as ae,_ as oe,a as se,b as ce,c as v,d as le,f as y,g as ue,i as de,l as fe,m as b,n as pe,o as x,p as S,s as C,t as me,u as w,v as he,w as T,x as ge,y as _e}from"./connection-runtime.js";import{o as ve,r as ye}from"./auth-session.js";import{t as E}from"./shared.js";import D from"node:crypto";import O from"node:fs";import k from"node:path";const be=new Set([`daemonAuthToken`,`metroBearerToken`]);function xe(e){let t=M(j(e.profile)),n=k.join(e.stateDir,`remote-connections`,`generated`);O.mkdirSync(n,{recursive:!0,mode:448});let r=k.join(n,`${we(e.provider)}-${Ce(t)}.json`);O.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{O.chmodSync(r,384)}catch{}return r}function Se(n){try{return i(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 A(e){let t=Se({configPath:xe({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Te(e.provider)});return{flags:{...b(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function j(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!be.has(e)))}function Ce(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function M(e){return Array.isArray(e)?e.map(M):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,M(t)])):e}function we(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Te(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function N(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function Ee(e){let t=await ye({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await De({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=N(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return A({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 De(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 Oe(await ve(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function Oe(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 ke(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function ke(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 P(e){let t=je(e.provider);_(e.flags,u[e.provider]);let n=t(e),r=N(e.provider,e.stateDir,e.flags.session,n.device),i={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${r}`,leaseProvider:e.provider,clientId:r,leaseBackend:e.flags.leaseBackend??x(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...n,...w(e.flags)};return A({stateDir:e.stateDir,provider:e.provider,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,...n.providerApp?{extraFlags:{providerApp:n.providerApp}}:{}})}const Ae=[{provider:p.browserStack,buildProfileFields:Me},{provider:p.awsDeviceFarm,buildProfileFields:Pe}];function je(e){let n=Ae.find(t=>t.provider===e)?.buildProfileFields;if(n)return n;throw new t(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Me(e){return d(e.env??{},`connect browserstack`),{platform:F(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:I(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:I(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ne(I(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,...fe(e.flags)}}function Ne(e,n){if(/^https?:\/\//i.test(e))return e;let r=c(e);if(r!==void 0)return r;let i=k.resolve(n,e);try{if(O.statSync(i).isFile())return i}catch{}throw new t(`INVALID_ARGS`,`BrowserStack app file not found: ${i}`)}function Pe(e){let{env:t,flags:n}=e,r=F(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`])??l(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function F(e,n){if(e===`android`||e===`ios`)return e;throw new t(`INVALID_ARGS`,n)}function I(e,n){if(e)return e;throw new t(`INVALID_ARGS`,n)}function L(e,t,n,r){return I(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Fe(e){let n=e.env??process.env,r=Ie({flags:e.flags}),i=h(n),a=g(r.leaseBackend)??`android`;if(!i?.apiKey&&!i?.instances?.[a])throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY, or ${ee(a).join(`, `)} for an existing instance.`,{hint:`Set the credentials in the environment before running agent-device connect limrun.`});return A({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Ie(e){let t=e.flags,n=Le(t);return{stateDir:r(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,...w(t)}}function Le(e){if(_(e,o),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=x(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 Re(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=N(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??x(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,...w(e.flags)};return A({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:Ee,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Re,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>P({provider:`browserstack`,...e}),verify:Ve},"aws-device-farm":{resolve:e=>P({provider:`aws-device-farm`,...e}),verify:He},limrun:{resolve:Fe,verify:Ue}};async function ze(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=i({configPath:e.flags.remoteConfig,cwd:t,env:n}),a=r.profile.leaseProvider;return{flags:{...b(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...S(a)?{provider:a}:{}}}let r=e.provider??(We(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Be(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 Ve(e){let{flags:t,env:n}=e,r=m(n);return await f.verifyConnection({provider:`browserstack`,username:B(r.username,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(r.accessKey,`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 He(e){let{flags:t}=e;return await f.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 Ue(e){return await s({...h(e.env),clientVersion:n(),platform:V(e.flags.platform,`Limrun`)})}function We(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 Ge(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??Ke();return{session:i,previous:n.session?T({stateDir:t,session:i}):null,remoteConfigHash:ce(r),daemon:ue(n)}}function Ke(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=y(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 qe(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Je(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
+
`)}let a=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(Qe(n.device)),n.app&&o.push($e(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:_e(t.daemon?.baseUrl),liveSession:Ye(t),...Xe(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ze({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function Ye(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Xe(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 Ze(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function Qe(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 $e(e,t){return t.status===`missing`?`App: ${ct(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=et(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function et(e,t){let n=y(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:st()};if(y(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:tt(t)?ot(e):[...rt(t),...at(e).nextSteps],...nt(t)?{notes:it(e,!r)}:{}}}function tt(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function nt(e){return y(e?.provider).supportsArtifacts}function rt(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 it(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 at(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function ot(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 st(){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 ${a(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function ct(e){let t=y(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const lt=async({positionals:e,flags:t,client:n})=>{let i=r(t.stateDir).baseDir,a=Tt(e);ut(a,t);let o=await ze({provider:a,flags:t,stateDir:i}),s=o.flags,c=yt(o.remoteConfigPath),l=dt(s,c),u=Ge({stateDir:i,flags:s,remoteConfigPath:o.remoteConfigPath});ft(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:x(s),connection:c,daemon:u.daemon});let d=await Be(o),f=pt({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});re({stateDir:i,state:f});let p=await vt(n,i,s,u.previous,f),m=jt(s,f),h=qe(f,d);return await E(s,U({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p}),()=>Je({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p})),!0};function ut(e,n){if(!(!e||!n.remoteConfig))throw new t(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function dt(e,n){if(!e.tenant)throw new t(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&y(n?.leaseProvider).requiresRemoteDaemon)throw new t(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:e.tenant,runId:e.runId}}function ft(e,n){if(!(!e||Et(e,n))&&!n.flags.force)throw new t(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:n.session,remoteConfig:e.remoteConfigPath})}function pt(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=_t(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=mt(t,o,r),l=gt(t,o,s,c,i.session);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function mt(e,t,n){let r=ge(n??{},t??{}),i=t?.leaseBackend??x(e);return i===`macos-app`?ht(e,t,r):{leaseId:t?.leaseId,leaseBackend:i,...r,deviceKey:t?.deviceKey??r.deviceKey}}function ht(e,t,n){return{leaseId:e.leaseId??t?.leaseId,leaseBackend:`macos-app`,...n}}function gt(e,t,n,r,i){let a=ie({leaseBackend:r.leaseBackend,recordedPlatform:t?.platform,requestedPlatform:e.platform});if(!a.ok)throw me({session:i,leaseBackend:r.leaseBackend,boundPlatform:a.boundPlatform,requestedPlatform:a.requestedPlatform,detail:t?`bound-connection`:`requested-backend`});return{platform:a.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function _t(e,t){return!!(t&&!e.force)}async function vt(e,t,n,r,i){if(!(!r||!n.force)&&(await C(r.metro),await v({stateDir:t,state:r}),!(r.leaseId&&r.leaseId===i.leaseId)))return await de(e,r,{nextDaemonBaseUrl:i.daemon?.baseUrl,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function yt(e){let t=i({configPath:e,cwd:process.cwd(),env:process.env}).profile;return oe(t)}const bt=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=X(e);if(!i)return await Z(e,n),!0;let a=i.session,o;if(i.leaseId||i.runtime||i.metro)try{o=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await C(i.metro),await v({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await se(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return ne({stateDir:r,session:a}),await E(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>St(a,o)),!0},xt=async({positionals:e,flags:n})=>{if(e[0]!==`status`)throw new t(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=X(n);if(!i)return await Z(n,r),!0;let a=H(i),o=Mt(i);return await E(n,U({state:i,runtimePreparation:o}),()=>[`Configured remote session "${i.session}".`,`tenant=${i.tenant} runId=${i.runId} leaseId=${i.leaseId??`pending`} backend=${i.leaseBackend??`pending`}`,`remoteConfig=${i.remoteConfigPath}`,i.runtime?`metro=prepared`:`metro=not-prepared`,a?.message,o?.message].filter(e=>!!e).join(`
|
|
4
|
+
`)),!0};function St(e,t){return[`Disconnected remote session "${e}".`,...Ct(t),...wt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
+
`)}function Ct(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=Y(e);return t?[t]:[]})}function Y(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 wt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function Tt(e){let n=e[0];if(n!==void 0){if(e.length>1)throw new t(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(S(n))return n;throw new t(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${le()}.`)}}function X(e){let t=e.session??`default`,n=r(e.stateDir).baseDir;return{session:t,stateDir:n,state:T({stateDir:n,session:t})??(e.session?null:te({stateDir:n}))}}async function Z(e,t){await E(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function Et(e,t){return Dt(e,t)&&Ot(e,t)&&At(e.daemon,t.daemon)}function Dt(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 Ot(e,t){return he(e,t.flags.platform)?[[e.leaseBackend,t.desiredLeaseBackend],[e.target,t.flags.target]].every(([e,t])=>t===void 0||e===t)&&kt(e,t.flags.leaseId)&&ae(e,t.connection):!1}function kt(e,t){return e.leaseBackend!==`macos-app`||t===void 0||t===e.leaseId}function At(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function jt(e,t){if(!t.runtime&&!(!pe(e)&&!$(t.remoteConfigPath)))return Q(t)}function Mt(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=q(e,`agent-device metro prepare --remote-config ${a(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=i({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}export{lt as connectCommand,xt as connectionCommand,bt as disconnectCommand};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as normalizeError, H as centerOfRect, K as DaemonError, X as defaultHintForCode, a as DaemonRequest, d as JsonRpcRequestEnvelope, f as LeaseBackend, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, u as JsonRpcId, v as SessionRuntimeHints } from "./sdk-contracts.js";
|
|
2
2
|
export { type DaemonError, type DaemonInstallSource, type DaemonRequest, type DaemonResponse, type DaemonResponseData, type JsonRpcId, type JsonRpcRequestEnvelope, type LeaseBackend, type SessionRuntimeHints, centerOfRect, defaultHintForCode, normalizeError };
|
package/dist/src/contracts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{J as e,L as t,b as n}from"./sdk-contracts.js";export{n as centerOfRect,t as defaultHintForCode,e as normalizeError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{l as t}from"./exec.js";import{r as n,t as r}from"./output-path.js";import{l as i}from"./daemon-http.js";import"./command.js";import{i as a,n as o}from"./transport.js";import{createHash as s,randomUUID as c}from"node:crypto";import l from"node:fs";import u from"node:os";import d from"node:path";import{Transform as f,Writable as p}from"node:stream";import{pipeline as m}from"node:stream/promises";async function ee(e,t){let n=l.statSync(e),r=d.basename(e),i=n.isDirectory(),a=re(t)??ne(e,n),o=[];try{let t=i?await te(e,o):e,n=l.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await ie(t),sizeBytes:n.size,cleanup:()=>h(o)}}catch(e){throw h(o),e}}async function te(e,n){let r=l.mkdtempSync(d.join(u.tmpdir(),`agent-device-upload-${c()}-`));n.push(r);let i=d.join(r,`${d.basename(e)}.tar.gz`);return await t(`tar`,[`czf`,i,`-C`,d.dirname(e),d.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),i}function ne(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 re(e){return e===`ios`||e===`android`?e:void 0}function h(e){for(let t of e)l.rmSync(t,{recursive:!0,force:!0})}async function ie(t){let n=s(`sha256`),r=new p({write(e,t,r){n.update(e),r()}});return await m(l.createReadStream(t),r).catch(t=>{throw new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},t instanceof Error?t:void 0)}),n.digest(`hex`)}function g(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=y(i),c=Math.min(i,r+s);return new f({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 _(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${v(e)}\n`)}}function v(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${x(e.totalBytes)}) via ${b(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${x(e.transferredBytes)} of ${x(e.totalBytes)}`;case`progress`:return`Uploaded ${x(e.transferredBytes)} of ${x(e.totalBytes)} (${ae(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${b(e.to)} upload`}}function y(e){return Math.max(8388608,Math.ceil(e*.05))}function b(e){return e===`direct`?`direct`:`legacy`}function ae(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function x(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 S=3e5,C=`uploadStreamRetryable`;async function w(e){return await E({...e,url:e.url,redirectCount:0,startOffset:0})}function T(t){return t instanceof e&&t.details?.[C]===!0}async function E(t){let n=await o(t.url.protocol),r=l.statSync(t.payloadPath).size,i=se(t.headers,t.startOffset,r);return oe(t.progress,t.startOffset,r),await new Promise((o,s)=>{let c=!1,u=n.request({protocol:t.url.protocol,host:t.url.hostname,port:t.url.port,method:t.method,path:t.url.pathname+t.url.search,headers:i,...t.signal?{signal:t.signal}:{}},n=>{c=!0,a(n).then(i=>{clearTimeout(f);let a=n.statusCode??500,c=n.headers.location;if(c&&ce(a)){if(t.redirectCount>=5){s(new e(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:t.url.toString()}));return}let n=new URL(c,t.url);E({...t,url:n,redirectCount:t.redirectCount+1}).then(o,s);return}let l=le(a)?O(n.headers,r):void 0;if(l!==void 0){if(l>=r){o({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(l<=t.startOffset){s(new e(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:l,previousOffset:t.startOffset,url:t.url.toString()}));return}E({...t,startOffset:l}).then(o,s);return}o({statusCode:a,statusMessage:n.statusMessage,body:i})}).catch(s)}),f=setTimeout(()=>{u.destroy(),s(new e(`COMMAND_FAILED`,t.timeoutMessage,{timeoutMs:S,...t.timeoutHint?{hint:t.timeoutHint}:{},...D(t)}))},S);u.on(`error`,n=>{if(!c){if(clearTimeout(f),t.signal?.aborted){s(t.signal.reason);return}s(new e(`COMMAND_FAILED`,t.errorMessage,{...t.errorHint?{hint:t.errorHint}:{},...D(t)},n))}}),u.on(`close`,()=>clearTimeout(f)),m(l.createReadStream(t.payloadPath,{start:t.startOffset}),g({stage:t.progress?.stage??`legacy`,fileName:t.progress?.fileName??d.basename(t.payloadPath),startOffset:t.startOffset,totalBytes:r,onProgress:t.progress?.onProgress}),u).catch(t=>{if(c)return;u.destroy();let n=t instanceof Error?t:Error(String(t));s(new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function D(e){return e.retryable===!0?{[C]:!0}:{}}function oe(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function se(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function ce(e){return[301,302,303,307,308].includes(e)}function le(e){return e===308}function O(e,t){let n=k(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=A(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 k(e){let t=A(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function A(e){return Array.isArray(e)?e[0]:e}const j=3e4;async function M(e){let t=await ee(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=c();try{let i=await L({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r,signal:e.signal});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await N({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress,signal:e.signal})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await I({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})):await I({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})}finally{t.cleanup()}}async function N(e){let t=async t=>(await V(e.artifact,t,e.onProgress,e.signal),await H({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId,signal:e.signal}));try{return await t(e.preflight)}catch(n){if(e.signal?.aborted)throw n;return F(n)?await P(e,t):void 0}}async function P(e,t){let n=await L({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId,signal:e.signal});if(n?.kind===`cache-hit`)return n.uploadId;if(n?.kind===`direct-upload`)try{return await t(n)}catch{return}}function F(t){return t instanceof e?T(t):!0}async function I(t){let{normalizedBase:n,token:r,artifact:a}=t,o=new URL(`upload`,n),s={"content-type":a.contentType,"x-artifact-type":a.artifactType,"x-artifact-filename":a.fileName,"x-artifact-hash":a.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(s,i(r));let c=await w({url:o,method:`POST`,headers:s,payloadPath:a.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,signal:t.signal,progress:{stage:`legacy`,fileName:a.fileName,onProgress:t.onProgress}});try{let t=JSON.parse(c.body);if(!t.ok||!t.uploadId)throw new e(`COMMAND_FAILED`,`Upload failed: ${c.body}`);return t.uploadId}catch(t){throw t instanceof e?t:new e(`COMMAND_FAILED`,`Invalid upload response: ${c.body}`)}}async function L(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,i(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:R(e.signal,j),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(t=>{if(e.signal?.aborted)throw t});if(r?.ok)return z(await r.json().catch(()=>void 0))}function R(e,t){let n=AbortSignal.timeout(t);return e?AbortSignal.any([e,n]):n}function z(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(B(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function B(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function V(t,n,r,i){let a=await w({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:t.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,signal:i,progress:{stage:`direct`,fileName:t.fileName,onProgress:r}});if(a.statusCode<200||a.statusCode>=300)throw new e(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function H(t){let n=new URL(`upload/finalize`,t.normalizedBase),r={"content-type":`application/json`};Object.assign(r,i(t.token));let a=await fetch(n,{method:`POST`,headers:r,signal:R(t.signal,j),body:JSON.stringify({uploadId:t.uploadId})}).catch(n=>{throw t.signal?.aborted?n:new e(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},n)});if(!a.ok)throw new e(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:a.status,statusText:a.statusText});let o=await a.json().catch(()=>void 0);if(!o?.ok||!o.uploadId)throw new e(`COMMAND_FAILED`,`Invalid upload finalize response`);return o.uploadId}async function U(e,t,n){let r=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,a=e.meta?.installSource,o={},s,c=_();if(!we(t))return K({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o});W(e),i=G(e,r,i,o);let l=await pe(e,t,c,n);return l&&(a=l.installSource,s=l.uploadedArtifactId??s),e.command!==`install`&&e.command!==`reinstall`||(s=await ue(e,t,r,c,n)??s),K({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o})}function W(t){if(t.flags?.saveScript!==void 0)throw new e(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:t.command})}async function ue(e,t,n,r,i){let a=n.length===1?0:1,o=n[a];if(o===void 0)return;if(o.startsWith(`remote:`)){n[a]=o.slice(7);return}let s=fe(o,e.meta?.cwd);if(s)return await M({localPath:s,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r,signal:i})}function G(e,t,n,r){let i=me(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=de(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function de(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function fe(e,t){let n=d.isAbsolute(e)?e:d.resolve(t??process.cwd(),e);return l.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 pe(e,t,n,r){let i=e.meta?.installSource;if(e.command!==`install_source`||!i||i.kind!==`path`)return null;let a=i.path.trim();if(!a)return{installSource:i};if(a.startsWith(`remote:`))return{installSource:{...i,path:a.slice(7)}};let o=d.isAbsolute(a)?a:d.resolve(e.meta?.cwd??process.cwd(),a);if(!l.existsSync(o))return{installSource:{...i,path:o}};let s=await M({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n,signal:r});return{installSource:{...i,path:o},uploadedArtifactId:s}}function me(e,t){if(e.command===`screenshot`){let n=J(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:Q(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:Q(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!ge(e)&&e.flags?.platform===void 0)return null;let t=q(e),n=_e(J(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:Q(`recording`,d.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:he(e),flagKey:`artifactsDir`,flagPath:ve(`test-artifacts`)}:null}function he(e){let t=e.flags?.artifactsDir;return Y(X(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function q(e){return n(e.flags?.platform)}function ge(e){return X(e.positionals?.[1])||X(e.flags?.out)}function _e(e,t){return t.flags?.platform===`web`?r(e,q(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 Y(X(i)?i:a,e.meta?.cwd)}function Y(e,t){return d.isAbsolute(e)?e:d.resolve(t??process.cwd(),e)}function X(e){return typeof e==`string`&&e.trim().length>0}const Z=`/tmp`;function Q(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return d.posix.join(Z,`${$(e)}${n}`)}function ve(e){return d.posix.join(Z,$(e))}function ye(e,t,n){let r=d.posix.basename(e,n);return e===d.posix.join(Z,`${r}${n}`)&&r.startsWith(`agent-device-${t}-`)&&/^\d+-[a-z0-9]+$/.test(r.slice(`agent-device-${t}-`.length))}function $(e){return`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}async function be(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=xe(n,t),o=await Se({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 xe(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 d.resolve(t.meta?.cwd??process.cwd(),r)}async function Se(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(Ce(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 Ce(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function we(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}export{be as n,U as r,ye as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{n as t,r as n}from"./diagnostics.js";import"./diagnostics2.js";import{o as r,p as i,r as a,t as o}from"./lease-scope.js";import{T as s,on as c}from"./sdk-batch.js";import{t as l}from"./catalog.js";import{a as u,s as d}from"./daemon-client-transport.js";const f=new Set([`LEASE_SCOPE_REQUIRED`,`LEASE_SCOPE_MISMATCH`]);function p(t){return a(t)||t instanceof e&&(f.has(t.details?.reason)||t.code===`INVALID_ARGS`)}async function m(e){let{heartbeat:t,callerSignal:r}=e;if(!t)return await e.task(new AbortController().signal);let i=new AbortController,a=new AbortController,s=o,c=h(s),l,u=!1,d=()=>{u=!0,l&&clearTimeout(l),a.abort()},f,m,v=new Promise((e,t)=>{m=t});r&&r.addEventListener(`abort`,d,{once:!0});let y=()=>{let e=e=>{u||(l&&clearTimeout(l),l=setTimeout(y,e))},r=e=>{if(f=e,u){n({level:`warn`,phase:`lease_lost_after_phase`,data:{message:e instanceof Error?e.message:String(e)}});return}i.abort(),m?.(e)},o=e=>{u||n({level:`warn`,phase:`lease_heartbeat_failed`,data:{message:e instanceof Error?e.message:String(e)}})};e(c),(async()=>{let n=s;try{let r=g(await t(n,a.signal));if(r===void 0||r===s)return;let i=h(r);s=r,c=i,e(i)}catch(e){if(p(e)){r(e);return}o(e)}})().catch(()=>void 0)};l=setTimeout(y,0),v.catch(()=>void 0);let b=await _((async()=>await Promise.race([e.task(i.signal),v]))());if(d(),r&&r.removeEventListener(`abort`,d),f!==void 0)throw f;if(!b.ok)throw b.error;return b.value}function h(e){return Math.max(1e3,Math.floor(e/3))}function g(e){let t=e?.data?.lease,n=t?.expiresAt,r=t?.heartbeatAt;if(typeof n==`number`&&typeof r==`number`)return n>r?n-r:void 0}async function _(e){try{return{ok:!0,value:await e}}catch(e){return{ok:!1,error:e}}}function v(e,t){return{command:l.leaseHeartbeat,positionals:[],session:t.session,token:t.token,meta:{...i(e),sessionIsolation:t.sessionIsolation,requestId:t.requestId}}}function y(e,n,i){if(!d(e))return;let a=r(i);if(!a.leaseId)return;let o=c(s(l.leaseHeartbeat),{positionals:[]});return async(r,s)=>await u(e,v(a,{session:i.session,sessionIsolation:i.meta?.sessionIsolation,requestId:t(),token:e.token}),n.transportPreference,n.paths,o===void 0?r:Math.min(o,r),{signal:s})}export{y as buildUploadLeaseHeartbeat,m as runProtectedLeaseWork};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as e,q as t}from"./sdk-contracts.js";import{n}from"./catalog.js";import{r}from"./diagnostics.js";import{C as i,p as a}from"./owner-identity.js";import{f as o}from"./exec.js";import{t as s}from"./timeouts.js";import"./diagnostics2.js";import"./command.js";import{a as c,c as l,d as u,f as d,h as f,l as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x}from"./daemon-client-transport.js";import{i as S}from"./replay-divergence.js";import{s as C}from"./device-shell.js";import"./process.js";import"./retry.js";import{t as w}from"./session-repair-tombstone.js";import{a as T,i as ee,o as te,r as ne}from"./version.js";import{t as re}from"./ttl-memo.js";import{n as ie,r as ae,t as oe}from"./daemon-resolution.js";import{i as se,n as E}from"./code-signature.js";import D from"node:path";import O from"node:fs";import k from"node:os";import A from"node:net";const j=re();function M(){let t=j.get(`local`);if(t)return t;let n=ne(),r=[D.join(n,`dist`,`src`,`internal`,`daemon.js`),D.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new e(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>O.existsSync(e))??i,o=D.join(n,te),s=r.some(e=>O.existsSync(e)),c=O.existsSync(o);if(!s&&!c)throw new e(`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 j.set(`local`,l),l}async function N(){let e=M(),t=se(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:E(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function P(e,t){let n=T();if(e.version!==n)return e.version&&ee(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=F(await N(),e);return r?{kind:`replace`,reason:r}:await t.onClientTransport()?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function F(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:I(e,t):t.codeOrigin===`installed`?I(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function I(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const L=15e3,R=new A.BlockList;R.addSubnet(`127.0.0.0`,8,`ipv4`),R.addAddress(`::1`,`ipv6`),R.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function z(e,t){let n=B(e),r=V(e,t),i=H(e,r.remoteBaseUrl),a=U(e,n,r.rawBaseUrl),o=a?W():n;return{paths:oe(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function B(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function V(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=xe(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Se(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function H(t,n){let r=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=ae(r);if(n&&i===`socket`)throw new e(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:ie(a)}}function U(e,t,n){return X(e.command)&&!t&&!n}function W(){return O.mkdtempSync(D.join(k.tmpdir(),`agent-device-replay-daemon-`))}async function G(e){if(e.remoteBaseUrl)return await le(e);let t=await ce(e);return await ue(t.info,e.paths.baseDir),t}async function ce(e){let t=await K(e);return t?{info:t,startedByClient:!1}:(g(e.paths),await pe(e))}async function le(t){let n={transport:`http`,token:t.remoteAuthToken??``,pid:0,baseUrl:t.remoteBaseUrl},r=await b(n);if(r.reachable)return n.remoteInstanceId=r.instanceId,n.remoteUpstreamInstanceId=r.upstream?.instanceId,{info:n,startedByClient:!1};throw new e(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:t.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 K(e){let t=x(e.paths.infoPath);if(!t)return null;let n=await P(t,{onClientTransport:()=>q(t,e.transportPreference),onAnyAdvertisedTransport:()=>q(t,`auto`)});if(n.kind===`reuse`)return t;if(n.kind===`refuseNewer`)throw de(t,n,e.paths.baseDir);return fe(t,n.reason,e.paths.baseDir),await f(t),d(e.paths.infoPath),null}async function q(e,t){if(await J(e,t))return!0;for(let n=1;n<=3;n+=1){if(!a(e.pid))return!1;if(await s(200),await J(e,t))return r({level:`warn`,phase:`daemon_probe_recovered`,data:{pid:e.pid,retry:n}}),!0}return!1}async function ue(t,n){if(!process.env.AGENT_DEVICE_DAEMON_POLICY?.trim())return;let{loadDaemonPolicy:r}=await import(`./daemon-policy-file.js`).then(e=>e.t),i=r(process.env)?.digest;if(i!==t.policyDigest)throw new e(`COMMAND_FAILED`,`The running daemon does not enforce the daemon policy named by AGENT_DEVICE_DAEMON_POLICY.`,{reason:`DAEMON_POLICY_MISMATCH`,expectedPolicyDigest:i,daemonPolicyDigest:t.policyDigest??null,hint:`Stop the running daemon (agent-device daemon stop --state-dir ${C(n)}), then retry so a daemon starts with this policy.`})}async function J(e,t){try{return await h(e,t)}catch(e){if(v(e))return!1;throw e}}function de(t,n,r){let{daemonVersion:i,clientVersion:a}=n;return new e(`COMMAND_FAILED`,`Daemon (pid ${t.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:t.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${C(r)}`})}function fe(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 pe(t){let n=0,r=[],i,a;for(let e=1;e<=2;e+=1){let o;try{o=ye(t),a={pid:o.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await c(t.paths,`start_error`)),e<2){await s(150);continue}break}let l=await Q(L,t,o);if(l.kind===`ready`)return l.daemon;if(l.kind===`early_exit`){if(a=l.exit,i=$(l.exit),r.push(await c(t.paths,`start_error`)),e<2){await s(150);continue}break}if(await u(t.paths)){n+=1;continue}let d=y(t.paths),f=e<2,p=await c(t.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(p),p.retainedInfoProcess||p.retainedLockProcess){let e=await Q(L,t,o);if(e.kind===`ready`)return e.daemon;e.kind===`early_exit`&&(a=e.exit,i=$(e.exit));break}if(!f)break;!d.hasInfo&&!d.hasLock&&await s(150)}let o=y(t.paths),l=be(t.paths.logPath);throw new e(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:t.paths.baseDir,infoPath:t.paths.infoPath,lockPath:t.paths.lockPath,logPath:t.paths.logPath,startupTimeoutMs:L,startupAttempts:2,lockRecoveryCount:n,cleanupResults:r,startError:i,daemonProcess:a,...l?{daemonLogTail:l}:{},metadataState:o,hint:m(o,t.paths)})}async function me(e,t,n,i){if(!X(e.command)||!t.startedByClient&&!n.ownedStateDir||p(t.info)||Y(i)||Z(e,i))return i;let a={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},o=i;try{await f(t.info)}catch(e){a.error=e instanceof Error?e.message:String(e)}finally{let e=O.existsSync(n.paths.infoPath);d(n.paths.infoPath),a.removedInfo=e&&!O.existsSync(n.paths.infoPath);let t=O.existsSync(n.paths.lockPath);if(_(n.paths.lockPath),a.removedLock=t&&!O.existsSync(n.paths.lockPath),n.ownedStateDir){let e=w(n.paths.sessionsDir);e?o=he(i,e):(O.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),a.removedStateDir=!O.existsSync(n.paths.baseDir))}}return r({level:a.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:a}),o}function he(n,r){if(n&&!n.ok)return n;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,s=`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:t(new e(`REPAIR_COMMIT_FAILED`,s))}}function Y(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:S(e.error.details?.divergence)?.repairSessionHeld===!0}function ge(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function X(e){return e===n.replay||e===n.test}function Z(e,t){return e.command!==n.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function _e(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${C(t)}`]:[],...r?[`--session ${C(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Q(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){let e=x(t.paths.infoPath);if(e&&await h(e,t.transportPreference)){if(ve(e,n))return{kind:`ready`,daemon:{info:e,startedByClient:!0}};let r=await K(t);if(r)return{kind:`ready`,daemon:{info:r,startedByClient:!1}}}if(i&&!l(t.paths,i.pid))return{kind:`early_exit`,exit:i};await s(100)}return{kind:`timeout`}}function ve(e,t){return e.pid===t.pid&&t.startTime!==void 0&&e.processStartTime===t.startTime}function ye(e){let t=M(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};O.mkdirSync(e.paths.baseDir,{recursive:!0});let a=O.openSync(e.paths.logPath,`a`),s=O.openSync(e.paths.logPath,`a`);try{let e=o(process.execPath,n,{env:r,stdio:[`ignore`,a,s]});return{...e,startTime:i(e.pid)??void 0}}finally{O.closeSync(a),O.closeSync(s)}}function $(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function be(e){try{if(!O.existsSync(e))return;let t=O.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=O.openSync(e,`r`);try{let e=Buffer.alloc(n);O.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{O.closeSync(r)}}catch{return}}function xe(t){if(!t)return;let n;try{n=new URL(t)}catch(n){throw new e(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:t},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new e(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:t});return n.toString().replace(/\/+$/,``)}function Se(t,n){if(!t)return;let r=new URL(t).hostname;if(!Ce(r)&&!(typeof n==`string`&&n.trim().length>0))throw new e(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:t,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function Ce(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:A.isIPv4(t)?R.check(t,`ipv4`):A.isIPv6(t)?R.check(t,`ipv6`):!1}export{Z as a,G as i,ge as n,Y as o,me as r,z as s,_e as t};
|
|
1
|
+
import{J as e,P as t}from"./sdk-contracts.js";import{r as n}from"./diagnostics.js";import"./diagnostics2.js";import{n as r}from"./catalog.js";import{m as i}from"./owner-identity.js";import{t as a}from"./timeouts.js";import{r as o}from"./file.js";import"./command.js";import{c as s,i as c,l,n as u,o as d,s as f,t as p}from"./daemon-client-transport.js";import"./process.js";import{a as m,i as ee,o as te,r as ne}from"./version.js";import{t as re}from"./ttl-memo.js";import{n as ie,r as h,t as g}from"./daemon-resolution.js";import"./retry.js";import{s as _}from"./device-shell.js";import{i as v}from"./replay-divergence.js";import{n as y}from"./daemon-registration.js";import{a as b,i as ae,n as oe,o as x,t as S}from"./daemon-registration-owner.js";import{i as se,n as ce}from"./code-signature.js";import C from"node:fs";import w from"node:path";import T from"node:net";function le(e,t,n){let r=e.data??{},i=typeof r.session==`string`?r.session:void 0,a=[...n?[`--daemon-base-url ${_(ue(n))}`]:[],...t?[`--state-dir ${_(t)}`]:[],...i?[`--session ${_(i)}`]:[]];if(a.length===0)return e;let o=`This session's daemon was kept alive because its script left the session active; pass ${a.join(` `)} on your next command to reach it.`+(n?` If authentication is required, provide or configure --daemon-auth-token.`:``),s=typeof r.message==`string`?r.message:void 0;return{...e,data:{...r,hint:o,message:s?`${s} ${o}`:o}}}function ue(e){let t=new URL(e);return t.username=``,t.password=``,t.search=``,t.hash=``,t.toString().replace(/\/+$/,``)}const E=re();function D(){let e=E.get(`local`);if(e)return e;let n=ne(),r=[w.join(n,`dist`,`src`,`internal`,`daemon.js`),w.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>C.existsSync(e))??i,o=w.join(n,te),s=r.some(e=>C.existsSync(e)),c=C.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return E.set(`local`,l),l}async function O(){let e=D(),t=se(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:ce(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function k(e,t){let n=m();if(e.version!==n)return e.version&&ee(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=A(await O(),e);return r?{kind:`replace`,reason:r}:await t.onClientTransport()?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function A(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:j(e,t):t.codeOrigin===`installed`?j(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function j(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const M=15e3,N=new T.BlockList;N.addSubnet(`127.0.0.0`,8,`ipv4`),N.addAddress(`::1`,`ipv6`),N.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function P(e,t){let n=F(e),r=I(e,t),i=L(e,r.remoteBaseUrl),a=R(e,n,r.rawBaseUrl)?oe():void 0;return{paths:a?.paths??g(n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function F(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function I(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Ae(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return je(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function L(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=h(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:ie(a)}}function R(e,t,n){return Z(e.command)&&!t&&!n}async function z(e){if(e.remoteBaseUrl)return await V(e);let t=await B(e);return await pe(t.info,e.paths.baseDir),t}async function B(e){let t=await H(e);return t?{info:t,startedByClient:!1}:await ge(e)}async function V(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl},r=await p(n);if(r.reachable)return n.remoteInstanceId=r.instanceId,n.remoteUpstreamInstanceId=r.upstream?.instanceId,{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 H(e,t={}){let{deadline:n}=t,r=o(e.paths.lockPath);if(r.state===`unproven`)throw W(e,r);let i=s(e.paths.infoPath);if(!i||!de(r,i)||t.waitForLiveStartup&&await U(i,n))return null;let a=await k(i,{onClientTransport:()=>G(i,e.transportPreference,n),onAnyAdvertisedTransport:()=>G(i,`auto`,n)});if(a.kind===`reuse`)return i;if(a.kind===`refuseNewer`)throw me(i,a,e.paths.baseDir);return J(n)<5e3?null:(he(i,a.reason,e.paths.baseDir),await fe(i,e.paths),null)}async function U(e,t){return i(e.pid)&&!await u(e,`auto`,J(t))}function de(e,t){return e.state===`absent`||y(e,{pid:t.pid,startTime:t.processStartTime??null})}function W(e,n){return new t(`COMMAND_FAILED`,`Daemon registration ownership could not be verified.`,{reason:`daemon_registration_unproven`,inspection:n,stateDir:e.paths.baseDir,hint:l(d(e.paths),e.paths)})}async function fe(e,n){let r=await x({paths:n,observed:{pid:e.pid,startTime:e.processStartTime??null},mode:`graceful`});if(r.status===`retained`)throw new t(`COMMAND_FAILED`,`Daemon replacement could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:r,hint:r.error?.hint??l(d(n),n)})}async function G(e,t,r){if(await K(e,t,r))return!0;for(let o=1;o<=3;o+=1){if(!i(e.pid)||r!==void 0&&Date.now()>=r)return!1;if(await a(Math.min(200,J(r))),await K(e,t,r))return n({level:`warn`,phase:`daemon_probe_recovered`,data:{pid:e.pid,retry:o}}),!0}return!1}async function pe(e,n){if(!process.env.AGENT_DEVICE_DAEMON_POLICY?.trim())return;let{loadDaemonPolicy:r}=await import(`./daemon-policy-file.js`).then(e=>e.t),i=r(process.env)?.digest;if(i!==e.policyDigest)throw new t(`COMMAND_FAILED`,`The running daemon does not enforce the daemon policy named by AGENT_DEVICE_DAEMON_POLICY.`,{reason:`DAEMON_POLICY_MISMATCH`,expectedPolicyDigest:i,daemonPolicyDigest:e.policyDigest??null,hint:`Stop the running daemon (agent-device daemon stop --state-dir ${_(n)}), then retry so a daemon starts with this policy.`})}async function K(e,t,n){try{return await u(e,t,J(n))}catch(e){if(c(e))return!1;throw e}}function me(e,n,r){let{daemonVersion:i,clientVersion:a}=n;return new t(`COMMAND_FAILED`,`Daemon (pid ${e.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:e.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${_(r)}`})}function he(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 ge(e){let n=Date.now()+M,r=[],i,o=0;for(;o<2&&Date.now()<n;){o+=1;let t=await _e(e,n);if(`daemon`in t)return t.daemon;if(i=t,t.cleanup&&r.push(t.cleanup),!t.retry)break;await a(Math.min(150,Math.max(0,n-Date.now())))}let{startError:s,startupError:c,daemonProcess:u}=i??{},f=d(e.paths),p=ke(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:M,startupAttempts:o,cleanupResults:r,startError:s,startupError:c,daemonProcess:u,...p?{daemonLogTail:p}:{},metadataState:f,hint:l(f,e.paths)})}async function _e(t,n){let r;try{r=$(t)}catch(e){return await ve(t,e)}let i=await Ce(n,t,r);if(i.kind===`ready`)return{daemon:i.daemon};if(i.kind===`retry`)return{retry:!0};if(i.kind===`unproven`){let t=e(i.error);return{retry:!1,startError:t.message,startupError:t,daemonProcess:{pid:r.pid}}}let{cleanup:a,joined:s}=await q(t,r,n),c=Y(o(t.paths.lockPath));return{cleanup:a,retry:s&&i.kind===`early_exit`&&c,startError:i.kind===`early_exit`?Oe(i.exit):void 0,daemonProcess:i.kind===`early_exit`?i.exit:{pid:r.pid}}}async function ve(t,n){let r=t.ownedStateDir?await x({paths:t.paths,observed:null,mode:`graceful`,ownedStateDir:t.ownedStateDir,lockTimeoutMs:0}):await b({paths:t.paths,observed:null,lockTimeoutMs:0});return{cleanup:r,startError:e(n).message,retry:!t.ownedStateDir&&r.status!==`retained`}}async function q(e,t,n){return{cleanup:await x({paths:e.paths,observed:t.readIdentity(),mode:`graceful`,ownedStateDir:e.ownedStateDir,termTimeoutMs:Math.min(3e3,J(n)),killTimeoutMs:1e3,lockTimeoutMs:0}),joined:await ye(t)}}async function ye(e){let t;try{return await Promise.race([e.exited.then(()=>!0),new Promise(e=>{t=setTimeout(()=>e(!1),1e3)})])}finally{clearTimeout(t)}}function J(e){return e===void 0?1/0:Math.max(0,e-Date.now())}function Y(e){return e.state===`absent`||e.state===`held`&&(e.liveness===`owner-process-dead`||e.liveness===`owner-process-reused`)}async function be(r,i,a,o){if(!Z(r.command)||!i.startedByClient&&!a.ownedStateDir||f(i.info)||X(o)||Q(r,o))return o;let s=await x({paths:a.paths,observed:{pid:i.info.pid,startTime:i.info.processStartTime??null},mode:`graceful`,ownedStateDir:a.ownedStateDir});return n({level:s.status===`retained`?`warn`:`info`,phase:`daemon_replay_cleanup`,data:{pid:i.info.pid,...s}}),s.status!==`absent`&&s.repairCommitFailure?xe(o,s.repairCommitFailure,s.status===`retained`?s.error:void 0):s.status===`retained`&&o?.ok?{ok:!1,error:e(new t(`COMMAND_FAILED`,`Replay completed, but daemon cleanup could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:s,stateDir:a.paths.baseDir,hint:s.error?.hint??`State and diagnostics were retained at ${a.paths.baseDir}. Resolve the reported cleanup failure before retrying.`}))}:o}function xe(n,r,i){if(n&&!n.ok)return n;let{sessionName:a,tombstone:o}=r,s=o.sourcePath?`re-run: replay ${o.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,c=`The repair transaction for session "${a}" completed, but committing its healed script failed at teardown: ${o.commitFailure.message}. ${s}.`;return{ok:!1,error:e(new t(`REPAIR_COMMIT_FAILED`,c,i?{cleanupFailure:i}:void 0))}}function X(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:v(e.error.details?.divergence)?.repairSessionHeld===!0}function Se(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 Z(e){return e===r.replay||e===r.test}function Q(e,t){return e.command!==r.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}async function Ce(e,t,n){let r;for(n.exited.then(e=>{r=e});Date.now()<e;){if(r){let n=we(r);if(n===`unproven`)return{kind:`unproven`,error:W(t)};if(n===`failed`)return{kind:`early_exit`,exit:r};let i=await Te(t,e);if(i)return i}else{let i=await Ee(t,n,e);if(i&&!r)return{kind:`ready`,daemon:{info:i,startedByClient:!0}}}await a(Math.min(100,J(e)))}return{kind:`timeout`}}function we(e){if(e.error||e.signal)return`failed`;switch(e.exitCode){case S.busy:return`busy`;case S.unproven:return`unproven`;default:return`failed`}}async function Te(e,n){let r;try{r=await H(e,{deadline:n,waitForLiveStartup:!0})}catch(e){if(e instanceof t&&e.details?.reason===`daemon_registration_unproven`)return{kind:`unproven`,error:e};throw e}if(Date.now()>=n)return null;if(r)return{kind:`ready`,daemon:{info:r,startedByClient:!1}};let i=o(e.paths.lockPath);return i.state===`unproven`?{kind:`unproven`,error:W(e,i)}:Y(i)?{kind:`retry`}:null}async function Ee(r,i,a){let o=s(r.paths.infoPath);if(!o||!De(o,i))return null;try{return await u(o,r.transportPreference,J(a))&&Date.now()<a?o:null}catch(o){let{cleanup:s,joined:c}=await q(r,i,a);throw n({level:`warn`,phase:`daemon_startup_observation_failed`,data:{stateDir:r.paths.baseDir,cleanup:s,joined:c,error:e(o)}}),o instanceof t&&(o.details={...o.details,stateDir:r.paths.baseDir,cleanupResults:[s],startupJoined:c}),o}}function De(e,t){let n=t.readIdentity();return e.pid===n.pid&&n.startTime!==null&&e.processStartTime===n.startTime}function $(e){let t=D();return ae({paths:e.paths,serverMode:e.serverMode,ownedStateDir:e.ownedStateDir,args:t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath]})}function Oe(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 ke(e){try{if(!C.existsSync(e))return;let t=C.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=C.openSync(e,`r`);try{let e=Buffer.alloc(n);C.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{C.closeSync(r)}}catch{return}}function Ae(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 je(e,n){if(!e)return;let r=new URL(e).hostname;if(!Me(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 Me(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:T.isIPv4(t)?N.check(t,`ipv4`):T.isIPv6(t)?N.check(t,`ipv6`):!1}function Ne(e,t,n){return e.ok?Q(t,e)?le(e,n.ownedStateDir?n.paths.baseDir:void 0,n.remoteBaseUrl):e:n.ownedStateDir&&X(e)?Se(e,n.paths.baseDir):e}export{Ne as attachSessionAddressHints,be as cleanupDaemonAfterRequest,z as ensureDaemon,P as resolveClientSettings};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./diagnostics.js";import"./diagnostics2.js";import{t}from"./catalog.js";import{n,t as r}from"./transport.js";import i from"node:net";async function a(e,t={}){let n=Date.now()+1e3,r=[];return e.httpPort&&r.push(s(e.httpPort,n)),e.port&&r.push(c(e.port,e.token,t.session,n)),r.length!==0&&await new Promise(e=>{let t=r.length,n=n=>{if(n){for(let e of r)e.cancel();e(!0);return}--t===0&&e(!1)};for(let e of r)e.answer.then(n,()=>n(!1))})}function o(e){let t=!1,n,r=()=>{},i=new Promise(e=>{r=e}),a=setTimeout(()=>o(!1),Math.max(1,e-Date.now()));a.unref?.();function o(e){t||(t=!0,clearTimeout(a),n?.(),r(e))}return{leg:{answer:i,cancel:()=>o(!1)},settle:o,attach:e=>{n=e,t&&e()}}}function s(e,t){let r=o(t);return(async()=>{try{let t=(await n(`http:`)).request({host:`127.0.0.1`,port:String(e),path:`/health`,method:`GET`,agent:!1},e=>{e.resume(),r.settle(!0)});t.on(`error`,()=>r.settle(!1)),r.attach(()=>t.destroy()),t.end()}catch{r.settle(!1)}})(),r.leg}function c(e,t,n,a){let s=o(a),c;try{c=i.createConnection({host:`127.0.0.1`,port:e})}catch{return s.settle(!1),s.leg}s.attach(()=>c.destroy());let u=l(t,n),d=``;return c.setEncoding(`utf8`),c.on(`connect`,()=>{c.write(`${JSON.stringify(u)}\n`)}),c.on(`data`,e=>{let t=r(d,e);d=t.buffer,t.lines.length>0&&s.settle(!0)}),c.on(`error`,()=>s.settle(!1)),c.on(`close`,()=>s.settle(!1)),s.leg}function l(n,r){return{token:n,session:r||`default`,command:t.sessionList,positionals:[],flags:{},meta:{requestId:e()}}}export{a as probeDaemonResponsive};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{J as e,N as t,et as n,nt as r}from"./sdk-contracts.js";import{d as i,m as a,o}from"./lease-scope.js";import{T as s}from"./sdk-batch.js";import{n as c}from"./catalog.js";import{n as l,r as u}from"./diagnostics.js";import{l as d,m as f}from"./exec.js";import"./diagnostics2.js";import{r as p,t as m}from"./output-path.js";import{_ as h,f as ee,g as te,i as ne,m as g,n as _,s as re,t as v}from"./transport.js";import"./command.js";import{o as ie}from"./device-shell.js";import{a as ae}from"./version.js";import{t as oe}from"./daemon-resolution.js";import{n as se,t as y}from"./daemon-process.js";import{n as ce,o as le,t as ue}from"./request-progress-protocol.js";import{t as de}from"./session-artifact-paths.js";import b from"node:path";import x from"node:fs";import{createHash as fe,randomUUID as pe}from"node:crypto";import me from"node:os";import{Transform as he,Writable as ge}from"node:stream";import{pipeline as _e}from"node:stream/promises";import ve from"node:net";async function ye(e,t){let n=x.statSync(e),r=b.basename(e),i=n.isDirectory(),a=Se(t)??xe(e,n),o=[];try{let t=i?await be(e,o):e,n=x.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await Ce(t),sizeBytes:n.size,cleanup:()=>S(o)}}catch(e){throw S(o),e}}async function be(e,t){let n=x.mkdtempSync(b.join(me.tmpdir(),`agent-device-upload-${pe()}-`));t.push(n);let r=b.join(n,`${b.basename(e)}.tar.gz`);return await d(`tar`,[`czf`,r,`-C`,b.dirname(e),b.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function xe(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 Se(e){return e===`ios`||e===`android`?e:void 0}function S(e){for(let t of e)x.rmSync(t,{recursive:!0,force:!0})}async function Ce(e){let n=fe(`sha256`),r=new ge({write(e,t,r){n.update(e),r()}});return await _e(x.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 we(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=De(i),c=Math.min(i,r+s);return new he({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 Te(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Ee(e)}\n`)}}function Ee(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${w(e.totalBytes)}) via ${C(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${w(e.transferredBytes)} of ${w(e.totalBytes)}`;case`progress`:return`Uploaded ${w(e.transferredBytes)} of ${w(e.totalBytes)} (${Oe(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${C(e.to)} upload`}}function De(e){return Math.max(8388608,Math.ceil(e*.05))}function C(e){return e===`direct`?`direct`:`legacy`}function Oe(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function w(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 T=3e5,E=`uploadStreamRetryable`;async function D(e){return await O({...e,url:e.url,redirectCount:0,startOffset:0})}function ke(e){return e instanceof t&&e.details?.[E]===!0}async function O(e){let n=await _(e.url.protocol),r=x.statSync(e.payloadPath).size,i=je(e.headers,e.startOffset,r);return Ae(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,...e.signal?{signal:e.signal}:{}},n=>{s=!0,ne(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Me(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);O({...e,url:n,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Ne(s)?Pe(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}O({...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:T,...e.timeoutHint?{hint:e.timeoutHint}:{},...k(e)}))},T);c.on(`error`,n=>{if(!s){if(clearTimeout(l),e.signal?.aborted){o(e.signal.reason);return}o(new t(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...k(e)},n))}}),c.on(`close`,()=>clearTimeout(l)),_e(x.createReadStream(e.payloadPath,{start:e.startOffset}),we({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??b.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 k(e){return e.retryable===!0?{[E]:!0}:{}}function Ae(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function je(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Me(e){return[301,302,303,307,308].includes(e)}function Ne(e){return e===308}function Pe(e,t){let n=Fe(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=A(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 Fe(e){let t=A(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function A(e){return Array.isArray(e)?e[0]:e}const j=3e4;async function M(e){let t=await ye(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=pe();try{let i=await P({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r,signal:e.signal});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Ie({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress,signal:e.signal})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await N({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})):await N({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})}finally{t.cleanup()}}async function Ie(e){let t=async t=>(await He(e.artifact,t,e.onProgress,e.signal),await Ue({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId,signal:e.signal}));try{return await t(e.preflight)}catch(n){if(e.signal?.aborted)throw n;return Re(n)?await Le(e,t):void 0}}async function Le(e,t){let n=await P({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId,signal:e.signal});if(n?.kind===`cache-hit`)return n.uploadId;if(n?.kind===`direct-upload`)try{return await t(n)}catch{return}}function Re(e){return e instanceof t?ke(e):!0}async function N(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 D({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,signal:e.signal,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 P(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:ze(e.signal,j),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(t=>{if(e.signal?.aborted)throw t});if(r?.ok)return Be(await r.json().catch(()=>void 0))}function ze(e,t){let n=AbortSignal.timeout(t);return e?AbortSignal.any([e,n]):n}function Be(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(Ve(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Ve(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function He(e,n,r,i){let a=await D({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,signal:i,progress:{stage:`direct`,fileName:e.fileName,onProgress:r}});if(a.statusCode<200||a.statusCode>=300)throw new t(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function Ue(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:ze(e.signal,j),body:JSON.stringify({uploadId:e.uploadId})}).catch(n=>{throw e.signal?.aborted?n:new t(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},n)});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 We(e,t,n){let r=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,a=e.meta?.installSource,o={},s,c=Te();if(!ut(t))return Xe({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o});Ge(e),i=qe(e,r,i,o);let l=await Ze(e,t,c,n);return l&&(a=l.installSource,s=l.uploadedArtifactId??s),e.command!==`install`&&e.command!==`reinstall`||(s=await Ke(e,t,r,c,n)??s),Xe({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o})}function Ge(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 Ke(e,t,n,r,i){let a=n.length===1?0:1,o=n[a];if(o===void 0)return;if(o.startsWith(`remote:`)){n[a]=o.slice(7);return}let s=Ye(o,e.meta?.cwd);if(s)return await M({localPath:s,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r,signal:i})}function qe(e,t,n,r){let i=Qe(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=Je(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function Je(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function Ye(e,t){let n=b.isAbsolute(e)?e:b.resolve(t??process.cwd(),e);return x.existsSync(n)?n:void 0}function Xe(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function Ze(e,t,n,r){let i=e.meta?.installSource;if(e.command!==`install_source`||!i||i.kind!==`path`)return null;let a=i.path.trim();if(!a)return{installSource:i};if(a.startsWith(`remote:`))return{installSource:{...i,path:a.slice(7)}};let o=b.isAbsolute(a)?a:b.resolve(e.meta?.cwd??process.cwd(),a);if(!x.existsSync(o))return{installSource:{...i,path:o}};let s=await M({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n,signal:r});return{installSource:{...i,path:o},uploadedArtifactId:s}}function Qe(e,t){if(e.command===`screenshot`){let n=rt(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:I(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:I(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!tt(e)&&e.flags?.platform===void 0)return null;let t=et(e),n=nt(rt(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:I(`recording`,b.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:$e(e),flagKey:`artifactsDir`,flagPath:at(`test-artifacts`)}:null}function $e(e){let t=e.flags?.artifactsDir;return it(F(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function et(e){return p(e.flags?.platform)}function tt(e){return F(e.positionals?.[1])||F(e.flags?.out)}function nt(e,t){return t.flags?.platform===`web`?m(e,et(t)):e}function rt(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return it(F(i)?i:a,e.meta?.cwd)}function it(e,t){return b.isAbsolute(e)?e:b.resolve(t??process.cwd(),e)}function F(e){return typeof e==`string`&&e.trim().length>0}function I(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return b.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function at(e){return b.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function ot(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=st(n,t),o=await ct({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 st(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 b.resolve(t.meta?.cwd??process.cwd(),r)}async function ct(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(lt(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 lt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function ut(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const dt=3e3,ft=1e3;function pt(e){let t=Tt(e);if(!t||typeof t!=`object`)return null;let n=t,r=mt(n);if(!r)return null;let i=ht(n);return i?{token:r,...i,transport:_t(n.transport),pid:R(n.pid)??0,version:L(n.version),codeOrigin:gt(n.codeOrigin),codeSignature:L(n.codeSignature),processStartTime:L(n.processStartTime),policyDigest:L(n.policyDigest)}:null}function mt(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function ht(e){let t=R(e.port),n=R(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function gt(e){return e===`installed`||e===`checkout`?e:void 0}function _t(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function L(e){return typeof e==`string`?e:void 0}function R(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function z(e){let t=Tt(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 vt(e,t){let n=z(e.lockPath);return n!==null&&n.pid!==t&&y(n.pid,n.processStartTime)}function B(e){Et(e)}function V(e){Et(e)}function yt(e){let t=H(e);if(!t.hasLock||t.hasInfo)return;let n=z(e.lockPath);if(!n){V(e.lockPath);return}y(n.pid,n.processStartTime)||V(e.lockPath)}async function bt(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=x.existsSync(e.infoPath),n=pt(e.infoPath);if(n){let t=y(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await U(n),i.stoppedInfoProcess=!0),B(e.infoPath),i.removedInfo=!0)}else t&&(B(e.infoPath),i.removedInfo=!0);let a=x.existsSync(e.lockPath),o=z(e.lockPath);if(o){let t=y(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await se(o.pid,{termTimeoutMs:dt,killTimeoutMs:ft,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),V(e.lockPath),i.removedLock=!0)}else a&&(V(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 H(e){return{hasInfo:x.existsSync(e.infoPath),hasLock:x.existsSync(e.lockPath)}}async function xt(e){let t=H(e);if(!t.hasLock||t.hasInfo)return!1;let n=z(e.lockPath);return!n||!y(n.pid,n.processStartTime)?(V(e.lockPath),!0):!1}async function U(e){await se(e.pid,{termTimeoutMs:dt,killTimeoutMs:ft,expectedStartTime:e.processStartTime})}function St(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Ct(e,t=oe(process.env.AGENT_DEVICE_STATE_DIR)){let n=wt(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 wt(e){return`rm -f ${ie(e.infoPath)} ${ie(e.lockPath)}`}function Tt(e){if(!x.existsSync(e))return null;try{return JSON.parse(x.readFileSync(e,`utf8`))}catch{return null}}function Et(e){try{x.existsSync(e)&&x.unlinkSync(e)}catch{}}function W(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function Dt(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(W(e.req,n,r))}if(ue(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return ce(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(W(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Ot(e,t){return le(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function kt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=Dt({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(W(n,e)))})}function At(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=Dt({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=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(W(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 jt=1e4,Mt=8388608;function Nt(e,t){return h(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Pt(e){let{logPath:t,...n}=e;return n}async function Ft(e,t){let n=Pt(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return G(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=de(t.stateDir,r),a=await It({endpoint:t.endpoint,ref:r,destinationPath:e});return a?G(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return G(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function G(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function It(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Nt(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await _(i.protocol);return await x.promises.mkdir(b.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}x.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),...te(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=x.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Mt&&(s.destroy(),n.destroy(),o(`record exceeds ${Mt} 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 ${jt}ms`),s.destroy()},jt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function Lt(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=Rt(e);if(n.error){zt(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}Ut(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 Rt(e){return JSON.parse(e)}async function zt(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Bt(e);if(!n.baseUrl){a(Ht(s,o));return}a(Ht(await Ft(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Bt(t){let r=t.data??{},i=Vt(r.cause);return{code:n(r.code==null?void 0:String(r.code),`COMMAND_FAILED`),message:String(r.message??t.message??`Daemon RPC request failed`),cause:i,details:typeof r.details==`object`&&r.details?r.details:void 0,hint:typeof r.hint==`string`?r.hint:void 0,diagnosticId:typeof r.diagnosticId==`string`?r.diagnosticId:void 0,logPath:typeof r.logPath==`string`?r.logPath:void 0,diagnosticsRecord:e(r.diagnosticsRecord),retriable:typeof r.retriable==`boolean`?r.retriable:void 0,supportedOn:typeof r.supportedOn==`string`?r.supportedOn:void 0}}function Vt(e){return r(e)}function Ht(e,r){return new t(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:r},e.cause)}async function Ut(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await ot(e,t,n):n)}catch(e){i(e)}}function Wt(e,t){let n=e.meta?.requestId??l();return Gt(e.command)?{jsonrpc:`2.0`,id:n,method:Kt(e.command),params:{...qt(e,e.command,t),...e.command===`lease_allocate`?a(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Gt(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function Kt(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 qt(e,t,n){return i(o(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Jt=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],Yt=new Set([`apple`,`ios`,`macos`]);function Xt(e){return e!==void 0&&Yt.has(e)}function K(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:o,command:s,platform:c,session:l,action:d}=e,f=i?{terminated:0}:$t(),p=!i&&Zt(s),m=p?en(n,r):{forcedKill:!1},h=Xt(c)||f.terminated>0;return u({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:o,command:s,timedOutRunnerPidsTerminated:f.terminated,timedOutRunnerCleanupError:f.error,daemonPidReset:p?n.pid:void 0,daemonPidForceKilled:p?m.forcedKill:void 0,daemonPreservedAfterTimeout:!i&&!p,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:o,reason:`daemon_transport_timeout`,hint:Qt({remote:i,resetDaemon:p,command:s,appleCleanupEvidence:h,session:l,action:d})})}function Zt(e){return s(e).onTimeout===`reset-daemon`}function Qt(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i,session:a,action:o}=e;if(t)return r===c.record&&o===`stop`?`The remote daemon is still exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`:`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&r===c.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function $t(){let e=0;try{for(let t of Jt)f(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function en(e,t){let n=!1;try{y(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{U(e)}finally{B(t.infoPath),V(t.lockPath)}return{forcedKill:n}}const tn=3e3,nn=`daemon_endpoint_unavailable`;function rn(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&e.details?.reason===nn}function q(e){return new t(`COMMAND_FAILED`,e===`http`?`Daemon HTTP endpoint is unavailable`:`Daemon socket endpoint is unavailable`,{reason:nn,transport:e})}async function an(e,t){let n=_n(e,t);if(await J(e,n))return!0;let r=vn(e,t,n);return r?await J(e,r):!1}async function J(e,t){return t===`http`?await sn(e):await on(e.port)}function on(e){return e?new Promise(t=>{let n=!1,r=ve.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 sn(e){return ln(e).then(e=>e.reachable)}async function cn(e,n){let r=await ln(e,n);if(!e.baseUrl||!r.reachable)return r;let i=[r,r.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(i)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:ae(),remoteVersion:i.version,remoteService:i.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:i.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return r}async function ln(e,t){let n=e.baseUrl?h(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!n)return{reachable:!1};let r=new URL(n),i=await _(r.protocol),a=Math.min(e.baseUrl?tn:500,t??1/0);if(a<=0)return{reachable:!1,timedOut:!0};let o=AbortSignal.timeout(Math.ceil(a));return await new Promise(t=>{let n=e.baseUrl?g(e.token):{},s=()=>o.aborted?{reachable:!1,timedOut:!0}:{reachable:!1},c=i.request({protocol:r.protocol,host:r.hostname,port:r.port,path:r.pathname+r.search,method:`GET`,timeout:a,signal:o,headers:n},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,...un(n)})}),e.on(`error`,()=>t(s())),e.on(`aborted`,()=>t(s()))});c.on(`timeout`,()=>{c.destroy(),t({reachable:!1,timedOut:!0})}),c.on(`error`,()=>{t(s())}),c.end()})}function un(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?dn(t.upstream):void 0;return{...dn(t),...n?{upstream:n}:{}}}catch{return{}}}function dn(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,...typeof e.instanceId==`string`?{instanceId:e.instanceId}:{},...typeof e.hostArch==`string`?{hostArch:e.hostArch}:{}}}async function fn(e,t,n,r,i,a={}){let o=_n(e,n),s=typeof i==`number`?performance.now()+i:void 0;try{return await Y(e,t,r,i,o,a)}catch(c){if(e.baseUrl&&hn(c))return await pn(e,t,r,i,s,o,a);gn(c)&&$(e);let l=vn(e,n,o);if(!l||!yn(c,o))throw c;return await Y(e,t,r,i,l,a)}}async function pn(e,n,r,i,a,o,s){$(e);let c=mn(e,n,r,i,a),l=await cn(e,c);if(l.timedOut&&i!==void 0&&c!==void 0&&c<=tn)throw K({info:e,statePaths:r,...Z(n,!0,i)});let u=mn(e,n,r,i,a);if(!l.reachable)throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.baseUrl});e.remoteInstanceId=l.instanceId,e.remoteUpstreamInstanceId=l.upstream?.instanceId,Dn(e,l);try{return await Y(e,n,r,u,o,s)}catch(t){throw gn(t)&&$(e),t}}function mn(e,t,n,r,i){if(i===void 0||r===void 0)return;let a=i-performance.now();if(a>0)return a;throw K({info:e,statePaths:n,...Z(t,!0,r)})}function hn(e){return e instanceof t&&e.details?.reason===`remote_instance_mismatch`}function gn(e){return e instanceof t&&(e.details?.reason===`daemon_transport_failure`||e.details?.reason===`daemon_transport_timeout`||e.details?.reason===`daemon_response_read_failure`)}async function Y(e,t,n,r,i,a){return i===`http`?await Tn(e,t,n,r,a):await Sn(e,t,n,r,a)}function _n(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 bn(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>X(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function X(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 X(e,r)?r:null}function yn(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function bn(e,t){if(X(e,t))return t;throw q(t)}function xn(e,n,r,i={}){return u({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,reason:`daemon_transport_failure`,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 Sn(e,t,n,r,i){let a=e.port;if(!a)throw q(`socket`);return new Promise((o,s)=>{let c=!1,l=ve.createConnection({host:`127.0.0.1`,port:a},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof r==`number`?setTimeout(()=>{u=!0,l.destroy(),s(K({info:e,statePaths:n,...Z(t,!1,r)}))},r):void 0;kt(l,{req:t,onProgress:i.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,o(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})))})})}function Z(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}function Cn(e){return{...e.remoteInstanceId?{[re]:e.remoteInstanceId}:{},...e.remoteUpstreamInstanceId?{[ee]:e.remoteUpstreamInstanceId}:{}}}function wn(e,t){return e===409&&t[`x-agent-device-instance-mismatch`]===`true`}async function Tn(e,n,r,i,a){let o=e.baseUrl?new URL(h(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw q(`http`);let s=JSON.stringify(Wt(n,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&(Object.assign(c,g(e.token)),Object.assign(c,Cn(e)));let l=await _(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(wn(i.statusCode,i.headers??{})){i.resume(),m&&clearTimeout(m),d(new t(`COMMAND_FAILED`,`Remote daemon instance changed`,{reason:`remote_instance_mismatch`,daemonBaseUrl:e.baseUrl}));return}if(Ot(n,i.headers?.[`content-type`])){At(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:t=>{Lt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})}});return}ne(i).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId,reason:`daemon_response_read_failure`},e instanceof Error?e:void 0)}).then(t=>{m&&clearTimeout(m),Lt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(e)})}),p=St(e),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(K({info:e,statePaths:r,...Z(n,p,i)}))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(xn(e,n.meta?.requestId,p))}),f.write(s),f.end()})}let Q;function En(e,t){return e.baseUrl===t.baseUrl&&e.token===t.token&&e.pid===t.pid}function Dn(e,t){!t.instanceId||t.upstream&&!t.upstream.instanceId||(Q={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:Promise.resolve(t)})}function $(e){Q&&En(Q,e)&&(Q=void 0)}async function On(e){if(Q&&En(Q,e))return await Q.health;let t={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:cn(e)};Q=t;try{let e=await t.health;return(!e.reachable||!e.instanceId||e.upstream&&!e.upstream.instanceId)&&Q===t&&(Q=void 0),e}catch(e){throw Q===t&&(Q=void 0),e}}export{bt as a,vt as c,xt as d,B as f,We as g,U as h,fn as i,St as l,Ct as m,an as n,yt as o,V as p,rn as r,H as s,On as t,pt as u};
|
|
1
|
+
import{I as e,P as t,Y as n,at as r,rt as i}from"./sdk-contracts.js";import{n as a,r as o}from"./diagnostics.js";import"./diagnostics2.js";import{d as s,m as c,o as l}from"./lease-scope.js";import{T as u}from"./sdk-batch.js";import{n as d}from"./catalog.js";import{r as f}from"./owner-identity.js";import{d as p,f as m,l as h,n as g,s as _}from"./daemon-http.js";import{n as v}from"./daemon-artifacts.js";import{i as ee,n as y,t as b}from"./transport.js";import{n as x,o as te,t as ne}from"./request-progress-protocol.js";import{t as re}from"./session-artifact-paths.js";import"./process.js";import{a as ie}from"./version.js";import{t as ae}from"./daemon-resolution.js";import S from"node:fs";import oe from"node:path";import C from"node:net";function w(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function T(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(w(e.req,n,r))}if(ne(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return x(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(w(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function se(e,t){return te(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function ce(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=T({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=b(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(w(n,e)))})}function le(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=T({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=b(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(w(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 E=1e4,D=8388608;function ue(e,t){return m(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function de(e){let{logPath:t,...n}=e;return n}async function fe(e,t){let n=de(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return O(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=re(t.stateDir,r),a=await pe({endpoint:t.endpoint,ref:r,destinationPath:e});return a?O(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return O(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function O(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function pe(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(ue(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await y(i.protocol);return await S.promises.mkdir(oe.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}S.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...h(t.token),...p(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=S.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>D&&(s.destroy(),n.destroy(),o(`record exceeds ${D} 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 ${E}ms`),s.destroy()},E);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function k(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=me(e);if(n.error){he(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}ve(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 me(e){return JSON.parse(e)}async function he(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=ge(e);if(!n.baseUrl){a(A(s,o));return}a(A(await fe(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function ge(e){let t=e.data??{},r=_e(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:r,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:n(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function _e(e){return r(e)}function A(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 ve(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await v(e,t,n):n)}catch(e){i(e)}}function ye(e,t){let n=e.meta?.requestId??a();return be(e.command)?{jsonrpc:`2.0`,id:n,method:xe(e.command),params:{...Se(e,e.command,t),...e.command===`lease_allocate`?c(e.flags):{},...e.command===`lease_allocate`&&e.meta?.providerCredentialFingerprint?{providerCredentialFingerprint:e.meta.providerCredentialFingerprint}:{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function be(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function xe(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 Se(e,t,n){return s(l(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}async function Ce(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:s,command:c,platform:l,session:u,action:d}=e,f=!i&&we(c)?await(await import(`./daemon-client-liveness-probe.js`)).probeDaemonResponsive(n,{session:u}):void 0,p=f===!1,m;if(p){let{stopAndRetireDaemon:e}=await import(`./daemon-registration-owner.js`).then(e=>e.r);m=await e({paths:r,observed:{pid:n.pid,startTime:n.processStartTime??null},mode:`force`})}let h=m?.status===`retired`,g=m?.status===`retained`&&m.termination?.status!==`exited`;return o({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:s,command:c,daemonPidReset:h?n.pid:void 0,daemonPidForceKilled:h?Oe(m):void 0,daemonRetirement:m,daemonPreservedAfterTimeout:g||!i&&!p,daemonLivenessProbeAnswered:f,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:s,reason:`daemon_transport_timeout`,...m?{retirement:m,stateDir:r.baseDir}:{},hint:m?.status===`retained`?`The daemon could not be safely retired. State was retained at ${r.baseDir}. ${m.error?.hint??`Retry with --debug and inspect daemon diagnostics before retrying.`}`:De({remote:i,resetDaemon:h,command:c,applePlatformDeclared:Ee(l),session:u,action:d})})}function we(e){return u(e).onTimeout===`reset-daemon`}const Te=new Set([`apple`,`ios`,`macos`]);function Ee(e){return e!==void 0&&Te.has(e)}function De(e){let{remote:t,resetDaemon:n,command:r,applePlatformDeclared:i,session:a,action:o}=e;if(!n&&r===d.record&&o===`stop`)return`The ${t?`remote `:``}daemon may still be exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(n)return`Retry with --debug and check daemon diagnostics logs. The daemon did not answer the liveness probe and was reset after the timeout.`;let s=i&&r===d.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; the daemon was kept alive so the session can still be closed or inspected.${s}`}function Oe(e){if(!e||e.status===`absent`)return!1;let t=e.termination;return t?.status===`exited`&&t.mode===`forced`}function ke(e){let t=Ie(e);if(!t||typeof t!=`object`)return null;let n=t,r=Ae(n);if(!r)return null;let i=je(n);return i?{token:r,...i,transport:Ne(n.transport),pid:f(n.pid)?n.pid:0,version:j(n.version),codeOrigin:Me(n.codeOrigin),codeSignature:j(n.codeSignature),processStartTime:j(n.processStartTime),policyDigest:j(n.policyDigest)}:null}function Ae(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function je(e){let t=M(e.port),n=M(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Me(e){return e===`installed`||e===`checkout`?e:void 0}function Ne(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function j(e){return typeof e==`string`?e:void 0}function M(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function Pe(e){return{hasInfo:S.existsSync(e.infoPath),hasLock:S.existsSync(e.lockPath)}}function N(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Fe(e,t=ae(process.env.AGENT_DEVICE_STATE_DIR)){let n=[e.hasInfo?t.infoPath:null,e.hasLock?t.lockPath:null].filter(Boolean).join(` and `);return`Daemon startup did not establish a reachable owner. ${n?`State was retained at ${n}. `:``}Retry with --debug and inspect daemon diagnostics. Before upgrading, stop all older clients and daemons with their original CLI and prevent them from returning to this state directory. Unverified lock state requires confirming every user stopped before manual recovery; deleting metadata alone is not a safe reset.`}function Ie(e){if(!S.existsSync(e))return null;try{return JSON.parse(S.readFileSync(e,`utf8`))}catch{return null}}function P(t,n,r){return e({requestId:r,dispatched:n},t.reason)}function F(e,t){if(e?.aborted)throw P(e,`no`,t)}const Le={refuseIfAborted:()=>{},guard:async e=>await e()};function Re(e){let{signal:t,requestId:n}=e;return t?{refuseIfAborted(){if(t.aborted)throw P(t,`no`,n)},guard:async e=>{if(t.aborted)throw P(t,`no`,n);return await new Promise((r,i)=>{let a=()=>i(P(t,`unknown`,n));t.addEventListener(`abort`,a,{once:!0}),e().then(e=>{t.removeEventListener(`abort`,a),r(e)},e=>{t.removeEventListener(`abort`,a),i(e)})})}}:Le}const I=3e3,L=`daemon_endpoint_unavailable`;function ze(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&e.details?.reason===L}function R(e){return new t(`COMMAND_FAILED`,e===`http`?`Daemon HTTP endpoint is unavailable`:`Daemon socket endpoint is unavailable`,{reason:L,transport:e})}async function Be(e,t,n){let r=Date.now()+(n??1/0),i=q(e,t),a=Y(e,t,i);return await z(e,i,(r-Date.now())/(a?2:1))?Date.now()<r:a?await z(e,a,r-Date.now())&&Date.now()<r:!1}async function z(e,t,n){return t===`http`?await He(e,n):await Ve(e.port,n)}function Ve(e,t=500){return!e||t<=0?Promise.resolve(!1):new Promise(n=>{let r=!1,i=C.createConnection({host:`127.0.0.1`,port:e},()=>{a(!0)}),a=e=>{r||(r=!0,i.destroy(),n(e))};i.setTimeout(Math.min(500,Math.ceil(t))),i.on(`timeout`,()=>{a(!1)}),i.on(`error`,()=>{a(!1)})})}function He(e,t){return V(e,t).then(e=>e.reachable)}async function B(e,n,r){let i=await V(e,n,r);if(!e.baseUrl||!i.reachable)return i;let a=[i,i.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(a)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:ie(),remoteVersion:a.version,remoteService:a.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:a.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return i}function Ue(e){return e.baseUrl?m(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null}async function V(e,t,n){let r=Ue(e);if(!r)return{reachable:!1};let i=new URL(r),a=Math.min(e.baseUrl?I:500,t??1/0);if(a<=0)return{reachable:!1,timedOut:!0};let o=performance.now()+a,s=AbortSignal.timeout(Math.ceil(a)),c=n?AbortSignal.any([s,n]):s,l=await Promise.race([y(i.protocol),new Promise(e=>{c.addEventListener(`abort`,()=>e(null),{once:!0})})]),u=()=>We(s,o);return!l||H(c,o)?u():await new Promise(t=>{let n=e.baseUrl?h(e.token):{},r=l.request({protocol:i.protocol,host:i.hostname,port:i.port,path:i.pathname+i.search,method:`GET`,timeout:a,signal:c,headers:n},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t(H(s,o)?{reachable:!1,timedOut:!0}:{reachable:r<500,statusCode:r,...Ge(n)})}),e.on(`error`,()=>t(u())),e.on(`aborted`,()=>t(u()))});r.on(`timeout`,()=>{r.destroy(),t({reachable:!1,timedOut:!0})}),r.on(`error`,()=>{t(u())}),r.end()})}function We(e,t){return H(e,t)?{reachable:!1,timedOut:!0}:{reachable:!1}}function H(e,t){return e.aborted||performance.now()>=t}function Ge(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?U(t.upstream):void 0;return{...U(t),...n?{upstream:n}:{}}}catch{return{}}}function U(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,...typeof e.instanceId==`string`?{instanceId:e.instanceId}:{},...typeof e.hostArch==`string`?{hostArch:e.hostArch}:{}}}async function Ke(e,n,r,i,a,o={}){try{return await qe(e,n,r,i,a,o)}catch(r){if(!(r instanceof t)||r.details?.reason!==`daemon_transport_timeout`)throw r;let a=r.details.timeoutMs;throw typeof a==`number`?await Ce({info:e,statePaths:i,...$e(n,N(e),a)}):r}}async function qe(e,t,n,r,i,a={}){let o=q(e,n),s=typeof i==`number`?performance.now()+i:void 0;F(a.signal,t.meta?.requestId);try{return await K(e,t,r,i,o,a)}catch(c){if(e.baseUrl&&Ye(c))return await Je(e,t,r,i,s,o,a);G(c)&&$(e);let l=Y(e,n,o);if(!l||!Xe(c,o))throw c;return await K(e,t,r,i,l,a)}}async function Je(e,n,r,i,a,o,s){$(e);let c=W(n,i,a),l=await B(e,c,s.signal);F(s.signal,n.meta?.requestId);let u=W(n,i,a,l.timedOut?c:void 0);if(!l.reachable)throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.baseUrl});e.remoteInstanceId=l.instanceId,e.remoteUpstreamInstanceId=l.upstream?.instanceId,it(e,l);try{return await K(e,n,r,u,o,s)}catch(t){throw G(t)&&$(e),t}}function W(e,t,n,r){if(n===void 0||t===void 0)return;let i=n-performance.now();if(i>0&&(r===void 0||r>I))return i;throw Z(t,e.meta?.requestId)}function Ye(e){return e instanceof t&&e.details?.reason===`remote_instance_mismatch`}function G(e){return e instanceof t&&(e.details?.reason===`daemon_transport_failure`||e.details?.reason===`daemon_transport_timeout`||e.details?.reason===`daemon_response_read_failure`)}async function K(e,t,n,r,i,a){return i===`http`?await nt(e,t,n,r,a):await Qe(e,t,r,a)}function q(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 Ze(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>J(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function J(e,t){return t===`http`?!!e.httpPort:!!e.port}function Y(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return J(e,r)?r:null}function Xe(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function Ze(e,t){if(J(e,t))return t;throw R(t)}function X(e,n,r,i={}){return o({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,reason:`daemon_transport_failure`,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 Qe(e,t,n,r){let i=e.port;if(!i)throw R(`socket`);let a=r.signal;return F(a,t.meta?.requestId),new Promise((e,o)=>{let s=!1,c=!1,l=C.createConnection({host:`127.0.0.1`,port:i},()=>{if(a?.aborted){c=!0,d(a);return}s=!0,l.write(`${JSON.stringify(t)}\n`)}),u=typeof n==`number`?setTimeout(()=>{c||(c=!0,p(),o(Z(n,t.meta?.requestId)),l.destroy())},n):void 0,d=e=>{p(),u&&clearTimeout(u),l.destroy(),o(P(e,s?`unknown`:`no`,t.meta?.requestId))},f=()=>{c||(c=!0,d(a))},p=()=>{a&&a.removeEventListener(`abort`,f)};a&&a.addEventListener(`abort`,f,{once:!0}),ce(l,{req:t,onProgress:r.onProgress,isSettled:()=>c,clearTimeout:()=>{u&&clearTimeout(u)},resolve:t=>{c=!0,p(),e(t)},reject:e=>{c=!0,p(),o(e)}}),l.on(`error`,e=>{c||(c=!0,u&&clearTimeout(u),p(),o(X(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:s})))})})}function Z(e,n){return new t(`COMMAND_FAILED`,`Daemon request timed out`,{reason:`daemon_transport_timeout`,timeoutMs:e,requestId:n})}function $e(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}function et(e){return{...e.remoteInstanceId?{[g]:e.remoteInstanceId}:{},...e.remoteUpstreamInstanceId?{[_]:e.remoteUpstreamInstanceId}:{}}}function tt(e,t){return e===409&&t[`x-agent-device-instance-mismatch`]===`true`}async function nt(e,n,r,i,a){let o=e.baseUrl?new URL(m(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw R(`http`);let s=JSON.stringify(ye(n,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&(Object.assign(c,h(e.token)),Object.assign(c,et(e)));let l=await y(o.protocol),u=a.signal;return F(u,n.meta?.requestId),await new Promise((d,f)=>{let p=!1,m=!1,h=()=>{u&&u.removeEventListener(`abort`,x)},g=e=>{p||(p=!0,h(),d(e))},_=e=>{p||(p=!0,h(),f(e))},v=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(tt(i.statusCode,i.headers??{})){i.resume(),b&&clearTimeout(b),_(new t(`COMMAND_FAILED`,`Remote daemon instance changed`,{reason:`remote_instance_mismatch`,daemonBaseUrl:e.baseUrl}));return}if(se(n,i.headers?.[`content-type`])){le(i,{req:n,onProgress:a.onProgress,reject:_,clearTimeout:()=>{b&&clearTimeout(b)},handleResponseBody:t=>{k(t,{info:e,req:n,stateDir:r.baseDir,resolve:g,reject:_})}});return}ee(i).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId,reason:`daemon_response_read_failure`},e instanceof Error?e:void 0)}).then(t=>{b&&clearTimeout(b),k(t,{info:e,req:n,stateDir:r.baseDir,resolve:g,reject:_})}).catch(e=>{b&&clearTimeout(b),_(e)})}),y=N(e),b=typeof i==`number`?setTimeout(()=>{_(Z(i,n.meta?.requestId)),v.destroy()},i):void 0,x=()=>{p||(b&&clearTimeout(b),_(P(u,m?`unknown`:`no`,n.meta?.requestId)),v.destroy())};u&&u.addEventListener(`abort`,x,{once:!0}),v.on(`error`,e=>{b&&clearTimeout(b),!p&&_(X(e,n.meta?.requestId,y))}),v.write(s),v.end(),m=!0})}let Q;function rt(e,t){return e.baseUrl===t.baseUrl&&e.token===t.token&&e.pid===t.pid}function it(e,t){!t.instanceId||t.upstream&&!t.upstream.instanceId||(Q={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:Promise.resolve(t)})}function $(e){Q&&rt(Q,e)&&(Q=void 0)}async function at(e){if(Q&&rt(Q,e))return await Q.health;let t={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:B(e)};Q=t;try{let e=await t.health;return(!e.reachable||!e.instanceId||e.upstream&&!e.upstream.instanceId)&&Q===t&&(Q=void 0),e}catch(e){throw Q===t&&(Q=void 0),e}}export{Ke as a,ke as c,ze as i,Fe as l,Be as n,Pe as o,Re as r,N as s,at as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=`/agent-device`,t=`x-agent-device-tenant`,n=`x-agent-device-network-access`,r=`public-only`;function i(t){return a(t,e)}function a(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(t.replace(/^\/+/,``),n).toString()}function o(e){let t=e?.trim();return t?{authorization:`Bearer ${t}`,"x-agent-device-token":t}:{}}function s(e){let n=e?.trim();return n?{[t]:n}:{}}const c=`x-agent-device-instance`,l=`x-agent-device-upstream-instance`,u=`x-agent-device-instance-mismatch`;function d(e,t,n){return{jsonrpc:`2.0`,id:e,error:{code:-32001,message:t,data:n}}}function f(e,t,n={}){return{ok:!0,service:e,version:t,rpcProtocolVersion:2,...n.instanceId===void 0?{}:{instanceId:n.instanceId},...n.hostArch===void 0?{}:{hostArch:n.hostArch},...n.leaseBackends===void 0?{}:{leaseBackends:n.leaseBackends},...n.upstream===void 0?{}:{upstream:n.upstream}}}export{r as a,f as c,s as d,a as f,n as i,o as l,c as n,t as o,d as p,u as r,l as s,e as t,i as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{P as t}from"./sdk-contracts.js";import{f as n}from"./sdk-batch.js";import r from"node:crypto";import i from"node:fs";import a from"node:path";var o=e({DAEMON_POLICY_ENV:()=>s,loadDaemonPolicy:()=>g,parseDaemonPolicy:()=>_,resolveDaemonPolicyCommandName:()=>m});const s=`AGENT_DEVICE_DAEMON_POLICY`,c=[`device-shutdown`],l=n,u=new Set(l.filter(e=>e.catalog.group===`internal`&&e.daemon!==void 0&&e.platformExecution.kind===`none`).map(e=>e.name)),d=new Map(l.flatMap(e=>{let{group:t,servesPublicCommand:n}=e.catalog;return t===`public`?[[e.name,e.name]]:t!==`internal`||u.has(e.name)?[]:[[e.name,n??e.name]]})),f=new Set(d.values()),p=new Set(l.filter(e=>e.catalog.group===`local-cli`).map(e=>e.name));function m(e){if(!u.has(e))return d.get(e)??e}const h=new Set([`version`,`devices`,`commands`,`capabilities`,`leases`]);function g(e=process.env){let t=e[s]?.trim();if(!t)return;let n=a.resolve(t),r;try{r=JSON.parse(i.readFileSync(n,`utf8`))}catch(e){throw T(n,`cannot read policy JSON: ${E(e)}`)}return _(r,n)}function _(e,t){let n=S(e,`policy`,t);for(let e of Object.keys(n))if(!h.has(e))throw T(t,`unknown key "${e}"`);if(n.version!==1)throw T(t,`"version" must be 1`);let i=n.devices===void 0?void 0:v(n.devices,t),a=n.commands===void 0?void 0:y(n.commands,t),o=n.capabilities===void 0?new Set:b(n.capabilities,t),s=n.leases===void 0?void 0:x(n.leases,t),c=JSON.stringify({devices:i?[...i].sort():null,commands:a?{mode:a.mode,names:[...a.names].sort()}:null,capabilities:[...o].sort(),...s?{leases:{require:s}}:{}});return Object.freeze({sourcePath:t,digest:r.createHash(`sha256`).update(c).digest(`hex`),deviceIds:i,commands:a,deniedCapabilities:o,...s?{requiredLeaseBackend:s}:{}})}function v(e,t){let n=S(e,`devices`,t);w(n,[`allow`],`devices`,t);let r=C(n.allow,`devices.allow`,t);if(r.length===0)throw T(t,`"devices.allow" must not be empty`);return new Set(r.map((e,n)=>{let r=`devices.allow[${n}]`,i=S(e,r,t);w(i,[`udid`,`serial`],r,t);let a=[i.udid,i.serial].filter(e=>e!==void 0);if(a.length!==1||typeof a[0]!=`string`||!a[0].trim())throw T(t,`"${r}" must name exactly one "udid" or "serial"`);return a[0].trim()}))}function y(e,t){let n=S(e,`commands`,t);if(w(n,[`allow`,`deny`],`commands`,t),n.allow===void 0==(n.deny===void 0))throw T(t,`"commands" must set exactly one of "allow" or "deny"`);let r=n.allow===void 0?`deny`:`allow`,i=`commands.${r}`,a=C(n[r],i,t).map(e=>{if(typeof e==`string`&&p.has(e))throw T(t,`"${i}" names ${JSON.stringify(e)}, which runs in the client; name the daemon command it sends, such as "runtime"`);if(typeof e!=`string`||!f.has(e))throw T(t,`"${i}" names unknown command ${JSON.stringify(e)}`);return e});return Object.freeze({mode:r,names:new Set(a)})}function b(e,t){let n=S(e,`capabilities`,t);w(n,[`deny`],`capabilities`,t);let r=c;return new Set(C(n.deny,`capabilities.deny`,t).map(e=>{if(typeof e!=`string`||!r.includes(e))throw T(t,`"capabilities.deny" names unknown capability ${JSON.stringify(e)}`);return e}))}function x(e,t){let n=S(e,`leases`,t);if(w(n,[`require`],`leases`,t),n.require!==`macos-app`)throw T(t,`"leases.require" must be macos-app`);return n.require}function S(e,t,n){if(typeof e==`object`&&e&&!Array.isArray(e))return e;throw T(n,`"${t}" must be an object`)}function C(e,t,n){if(Array.isArray(e))return e;throw T(n,`"${t}" must be an array`)}function w(e,t,n,r){for(let i of Object.keys(e))if(!t.includes(i))throw T(r,`unknown key "${n}.${i}"`)}function T(e,n){return new t(`INVALID_ARGS`,`Invalid daemon policy ${e}: ${n}`,{policyPath:e,hint:`Fix the file named by ${s}, then start the daemon again.`})}function E(e){return e instanceof Error?e.message:String(e)}export{g as n,m as r,o as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{J as t,P as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{A as o,S as s,m as c,o as l,r as u,w as d,x as f}from"./owner-identity.js";import{f as p}from"./exec.js";import{t as m}from"./timeouts.js";import{i as h,n as g,r as _}from"./file.js";import"./command.js";import"./process.js";import{t as v}from"./daemon-resolution.js";import"./retry.js";import{n as y}from"./session-repair-tombstone.js";import{i as b,n as x,r as S}from"./daemon-registration.js";import{r as C,t as w}from"./daemon-shutdown-report.js";import T from"node:fs";import E from"node:os";import D from"node:path";async function O(e,t){let{logPath:n,command:a=`daemon`,debug:o=!0}=e;return await i({command:a,session:`daemon`,logPath:n,debug:o},async()=>{try{return await t()}finally{r({force:!0})}})}const k=[/\/dist\/src\/daemon\.js($|[\s"'])/,/\/dist\/src\/internal\/daemon\.js($|[\s"'])/,/\/src\/daemon\.ts($|[\s"'])/];function A(e){let t=e.toLowerCase().replaceAll(`\\`,`/`);return k.some(e=>e.test(t))}function ee(e,t){if(!t||!c(e))return!1;let n=d(e);if(!n||n!==t)return!1;let r=s(e);return r?A(r):!1}function te(e,t){try{return process.kill(e,t),!0}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return!1;throw e}}async function j(e,t){if(!u(e.pid))return{exited:!1,elapsedMs:0};let n=Date.now(),r=n+t.timeoutMs,i=t.pollMs??100,a=()=>{if(!c(e.pid))return!0;let t=f([e.pid]).get(e.pid);return!!(t?.state.startsWith(`Z`)||t?.startTime&&t.startTime!==e.startTime)},o=a();for(;!o&&Date.now()<r;)await m(Math.min(i,Math.max(0,r-Date.now()))),o=a();return{exited:o,elapsedMs:Date.now()-n}}async function M(e,t){if(!u(e.pid))return{status:`retained`,reason:`identity-unverified`};if(!e.startTime?.trim())return c(e.pid)?{status:`retained`,reason:`missing-start-time`}:{status:`not-running`};let n={pid:e.pid,startTime:e.startTime};if((await j(n,{timeoutMs:0})).exited)return{status:`exited`,identity:n,mode:`already-exited`};let r;if(t.mode===`graceful`){let e=await N(n,{signal:`SIGTERM`,timeoutMs:t.termTimeoutMs});if(e.status!==`survived`)return e;r=`SIGTERM`}let i=await N(n,{signal:`SIGKILL`,timeoutMs:t.killTimeoutMs,previousSignal:r});return i.status===`survived`?{status:`retained`,reason:`exit-timeout`}:i}async function N(e,t){let n=ee(e.pid,e.startTime),r=n&&te(e.pid,t.signal),i=r?t.signal===`SIGTERM`?`graceful`:`forced`:t.previousSignal?`graceful`:`already-exited`;return(await j(e,{timeoutMs:i===`already-exited`?0:t.timeoutMs})).exited?{status:`exited`,identity:e,mode:i}:r?{status:`survived`}:{status:`retained`,signal:t.signal,reason:n?`signal-failed`:`identity-unverified`}}var P=e({DAEMON_STARTUP_EXIT_CODES:()=>F,createOwnedReplayStateDir:()=>H,launchDaemonProcess:()=>U,recoverAbandonedDaemonRegistration:()=>Y,stopAndRetireDaemon:()=>K,tryAcquireDaemonRegistration:()=>I});const F=Object.freeze({busy:75,unproven:78});async function I(e){let t={...e},n=l(),r=h({lockDirPath:t.lockPath,owner:{...n,acquiredAtMs:Date.now()},description:`daemon registration`});if(r.status!==`acquired`)return r;let{acquisition:i}=r;try{i.assertHeld(),T.rmSync(C(t.baseDir),{force:!0})}catch(e){await R(i,e,t.logPath)}return{status:`acquired`,owner:Object.freeze({publish({socketPort:e,httpPort:r,...a}){i.assertHeld(),B(t.logPath);let s=e&&r?`dual`:r?`http`:`socket`;i.assertHeld(),o({destination:t.infoPath,contents:JSON.stringify({...a,port:e,httpPort:r,transport:s,pid:n.pid,processStartTime:n.startTime??void 0,stateDir:t.baseDir},null,2),mode:384})},async finish(e){let r;try{e&&z(t.baseDir,e,i),r=L(t.infoPath,n,i)}catch(e){return await R(i,e,t.logPath)}return await i.release(),r}})}}function L(e,t,n){n.assertHeld();let r=b(e,t);if(r.state!==`match`)return r;n.assertHeld();try{T.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)throw e}return{state:`removed`}}async function R(e,t,n){try{await e.release()}catch(e){await Q(n,`daemon_registration_release_failed`,e)}throw t}function z(e,t,n){let r=C(e),i=`${JSON.stringify(w(t))}\n`;n.assertHeld();try{o({destination:r,contents:i,mode:384})}catch{return}}function B(e){let t=T.openSync(e,`a`,384);try{T.ftruncateSync(t,0)}finally{T.closeSync(t)}}const V=new WeakMap;function H(){let e=Object.freeze(v(T.mkdtempSync(D.join(E.tmpdir(),`agent-device-replay-daemon-`)))),t=Object.freeze({paths:e});return V.set(t,{paths:e,startups:[],sealed:!1}),t}function U(e){let t=e.ownedStateDir&&G(e.ownedStateDir,e.paths);if(t?.sealed)throw new n(`COMMAND_FAILED`,`Replay daemon startup admission is closed.`,{reason:`daemon_startup_admission_closed`});T.mkdirSync(e.paths.baseDir,{recursive:!0});let r=T.openSync(e.paths.logPath,`a`);try{let n=p(process.execPath,e.args,{env:{...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode},stdio:[`ignore`,r,r]}),i={...e.paths},a={launch:Object.freeze({...n,get startTime(){return a.startTime},readIdentity(){return W(i,a),{pid:n.pid,startTime:a.startTime??null}}}),joined:!1};return t&&t.startups.push(a),n.exited.then(()=>{a.joined=!0}),a.startTime=d(n.pid)??void 0,a.launch}finally{T.closeSync(r)}}function W(e,t){if(t.startTime||t.joined)return;let n=S(e.infoPath);if(n?.pid!==t.launch.pid||!n.startTime)return;let r=_(e.lockPath);x(r,n)&&(t.startTime=n.startTime)}function G(e,t){let r=V.get(e);if(!r||Object.entries(r.paths).some(([e,n])=>t[e]!==n))throw new n(`COMMAND_FAILED`,`Private replay directory ownership could not be verified.`,{reason:`daemon_private_state_unowned`});return r}async function K(e){let n,r=e.observed;try{if(e.ownedStateDir&&(n=G(e.ownedStateDir,e.paths),n.sealed=!0,r=q(n,r),n.retirement))return await n.retirement}catch(r){return await $(n,e.startupJoinTimeoutMs??1e3),{status:`retained`,reason:`ownership-unproven`,removedInfo:!1,error:t(r)}}let i=X({...e,observed:r},t=>M(t,{mode:e.mode,termTimeoutMs:e.termTimeoutMs??3e3,killTimeoutMs:e.killTimeoutMs??1e3}),n,e.startupJoinTimeoutMs??1e3);n&&(n.retirement=i);let a=await i;return n&&(a.status===`absent`||!a.removedStateDir)&&(n.retirement=void 0),a}function q(e,t){if(!t){if(e.startups.length===0)return null;throw J()}let n=e.startups.find(({launch:e})=>e.pid===t.pid);if(!n)throw J();let{launch:r}=n,i=t.startTime?t:r.readIdentity();if(r.startTime&&r.startTime===i.startTime)return i;throw J()}function J(){return new n(`COMMAND_FAILED`,`The observed daemon is not an owned startup lifetime.`,{reason:`daemon_private_startup_unowned`})}async function Y(e){return await X(e,async e=>{if(!e.startTime?.trim())return{status:`retained`,reason:`missing-start-time`};let t={pid:e.pid,startTime:e.startTime};return(await j(t,{timeoutMs:0})).exited?{status:`exited`,identity:t,mode:`already-exited`}:{status:`retained`,reason:`identity-unverified`}})}async function X(e,n,r,i=1e3){let a={...e.paths},o=e.observed&&{...e.observed},s,c;if(o)try{s=await n(o)}catch(e){c=t(e)}let l=await $(r,i);return c?{status:`retained`,reason:`stop-failed`,removedInfo:!1,error:c}:s&&s.status!==`exited`?{status:`retained`,reason:`exit-unconfirmed`,termination:s,removedInfo:!1}:l?await Z({...e,paths:a},s,r):{status:`retained`,reason:`startup-unconfirmed`,termination:s,removedInfo:!1}}async function Z(e,n,r){let i=e.paths,a;try{a=await g({lockDirPath:i.lockPath,owner:{...l(),acquiredAtMs:Date.now()},description:`daemon registration retirement`,timeoutMs:e.lockTimeoutMs??1e3})}catch(e){let r=t(e);return{status:`retained`,reason:r.details?.reason===`process_lock_timeout`?`lock-busy`:`retirement-unconfirmed`,termination:n,removedInfo:!1,error:r}}let o={status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1};try{o=re(L(i.infoPath,n?.identity??null,a),n),o=ie(r,a,o)}catch(e){o={status:`retained`,reason:`retirement-unconfirmed`,termination:n,removedInfo:o.removedInfo,error:t(e)}}return await ne(a,o,i.logPath)}async function ne(e,n,r){try{await e.release()}catch(e){let i=n.status===`retained`?n.error:void 0;i&&await Q(r,`daemon_retirement_release_failed`,e),n={...n,status:`retained`,reason:`retirement-unconfirmed`,error:i??t(e)}}return n}function re(e,t){return t&&(e.state===`removed`||e.state===`absent`)?{status:`retired`,termination:t,removedInfo:e.state===`removed`}:e.state===`absent`?{status:`absent`,removedInfo:!1}:{status:`retained`,termination:t,removedInfo:!1,reason:e.state===`replaced`?`registration-replaced`:e.state===`unreadable`?`metadata-unreadable`:`ownership-unproven`}}async function Q(e,n,r){await O({logPath:e},()=>{a({level:`warn`,phase:n,data:{error:t(r)}})})}async function $(e,t){if(!e||e.startups.every(e=>e.joined))return!0;let n;try{return await Promise.race([Promise.all(e.startups.map(({launch:e})=>e.exited)).then(()=>!0),new Promise(e=>{n=setTimeout(()=>e(!1),t)})])}finally{n&&clearTimeout(n)}}function ie(e,n,r){if(!e||r.status!==`retired`&&(r.status!==`absent`||e.startups.length!==0))return r;try{n.assertHeld();let t=y(e.paths.sessionsDir);return t?r.status===`retired`?{...r,removedStateDir:!1,repairCommitFailure:t}:{status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1,removedStateDir:!1,repairCommitFailure:t}:(n.assertHeld(),T.rmSync(e.paths.baseDir,{recursive:!0,force:!0}),{...r,removedStateDir:!0})}catch(e){return{...r,status:`retained`,reason:`retirement-unconfirmed`,removedStateDir:!1,error:t(e)}}}export{Y as a,O as c,U as i,H as n,K as o,P as r,I as s,F as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{a as e,i as t,r as n}from"./owner-identity.js";import"./process.js";import{t as r}from"./daemon-resolution.js";import i from"node:fs";function a(e){let t=s(e);return t.status===`registered`?t.identity:null}function o(t,n){return t.state===`held`&&typeof n.startTime==`string`&&n.startTime.trim().length>0&&e(t.owner,n)}function s(e){let t;try{t=i.readFileSync(e,`utf8`)}catch(e){let t=e?.code;return t===`ENOENT`||t===`ENOTDIR`?{status:`absent`}:{status:`unreadable`}}let n;try{n=c(JSON.parse(t))}catch{return{status:`ownerless`}}return n.pid===null?{status:`ownerless`}:{status:`registered`,identity:{pid:n.pid,startTime:n.startTime}}}function c(e){let t=e.pid;return n(t)?{pid:t,startTime:u(e.processStartTime)}:{pid:null,startTime:null}}function l(n,r){let i=s(n);return i.status===`registered`?r?t(i.identity,r)?{state:`replaced`,identity:i.identity}:e(i.identity,r)&&i.identity.startTime!==null?{state:`match`}:{state:`unproven`}:{state:`unproven`}:{state:i.status}}function u(e){return typeof e==`string`&&e.trim().length>0?e:null}function d(e){if(e.pid===process.pid)return!1;let n=a(r(e.stateDir).infoPath);return n!==null&&t(n,e)}export{l as i,o as n,a as r,d as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-resolution.js";import"./file.js";import{r as n,s as r}from"./version.js";import i from"node:
|
|
1
|
+
import{n as e,t}from"./path-resolution.js";import"./file.js";import{r as n,s as r}from"./version.js";import i from"node:crypto";import a from"node:fs";import o from"node:path";function s(e,t={}){let n=c(e,t);return{baseDir:n,infoPath:o.join(n,`daemon.json`),lockPath:o.join(n,`daemon.lock`),logPath:o.join(n,`daemon.log`),allocationsDir:o.join(n,`allocations`),sessionsDir:o.join(n,`sessions`)}}function c(t,n){let r=(t??``).trim();return r?e(r,{env:n.env}):l(n)}function l(e={}){let i=o.join(t(`~`,{env:e.env}),`.agent-device`),a=e.projectRoot??n();return r(a)?o.join(i,`dev`,u(a)):i}function u(e){let t=d(e),n=o.basename(t).replaceAll(/[^a-zA-Z0-9._-]+/g,`-`),r=i.createHash(`sha1`).update(t).digest(`hex`).slice(0,12);return`${n||`agent-device`}-${r}`}function d(e){try{return a.realpathSync.native(e)}catch{return o.resolve(e)}}function f(e){let t=(e??``).trim().toLowerCase();return t===`http`?`http`:t===`dual`?`dual`:`socket`}function p(e){let t=(e??``).trim().toLowerCase();return t===`auto`?`auto`:t===`socket`?`socket`:t===`http`?`http`:`auto`}export{f as n,p as r,s as t};
|