agent-device 0.21.23 → 0.21.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.apk → agent-device-android-ime-helper-0.21.25.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.25.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.23.manifest.json → agent-device-android-ime-helper-0.21.25.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.25.manifest.json +16 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +12 -6
- package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/RectResponseTests.swift +21 -0
- package/apple/snapshot-bridge/README.md +9 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +159 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerHttpRequestFraming.swift +139 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerPeer.swift +41 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerListenerToken.swift +25 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +56 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +14 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +18 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +29 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +0 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +35 -13
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryConfirmation.swift +59 -26
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +19 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +50 -106
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +142 -54
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +4 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +21 -19
- package/dist/src/absence-observation-errors.js +1 -0
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +2 -2
- package/dist/src/adb.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/alert.js +1 -1
- package/dist/src/android-adb.d.ts +3 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android-system-surface-disclosure.js +1 -0
- package/dist/src/android-text-entry.js +1 -0
- package/dist/src/android.js +1 -1
- package/dist/src/app-backend.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-inventory.d.ts +4 -0
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +4 -3
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution-facade.js +1 -1
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state-runtime.d.ts +15 -0
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/aws-device-farm-connection.js +1 -0
- 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/browserstack-connection.js +1 -0
- package/dist/src/capture-disclosure.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +36 -17
- package/dist/src/cli-output.js +1 -1
- package/dist/src/cli-runner.js +3 -1
- package/dist/src/cli.js +3 -4
- package/dist/src/client-companion-tunnel.js +1 -0
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +15 -7
- package/dist/src/cloud-artifacts.d.ts +3 -2
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-metadata.js +73 -1
- package/dist/src/command-policy.js +1 -0
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection-verification.js +1 -0
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lease-beat.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-liveness-probe.js +1 -1
- package/dist/src/daemon-policy-file.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -1
- package/dist/src/daemon-registration.js +1 -1
- package/dist/src/daemon-resolution.js +3 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.d.ts +6 -17
- 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-selection-resolver.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +3 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/expo-dev-client-launch.js +1 -0
- package/dist/src/file.js +3 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan-types.d.ts +2 -5
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/human-control.js +1 -1
- package/dist/src/ime-rebind.js +1 -1
- package/dist/src/ime-state.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +2 -2
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-error.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-catalog.js +1 -1
- package/dist/src/interactor.js +5 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +5 -1
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +2 -2
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory6.js +1 -1
- package/dist/src/io.d.ts +2 -2
- package/dist/src/ios-client.js +1 -1
- package/dist/src/ios-settings.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-adapter.js +1 -1
- package/dist/src/ios-snapshot-engine.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/keyed-lock.js +1 -1
- package/dist/src/launch-confirmation.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +5 -564
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/load.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/log-stream.js +9 -9
- package/dist/src/mechanics.js +16 -16
- package/dist/src/metro.js +1 -1
- package/dist/src/metro2.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/observability.js +1 -1
- package/dist/src/observation.js +1 -2
- package/dist/src/open-target-resolution.js +1 -1
- package/dist/src/output-path.js +1 -1
- package/dist/src/overlay.js +1 -3
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
- package/dist/src/platform-runtime-apple-resources.js +1 -0
- package/dist/src/platform-runtime-claim-recovery.js +1 -0
- package/dist/src/platform-runtime-daemon-services.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plugin.js +1 -0
- package/dist/src/plugins/webdriver.d.ts +111 -0
- package/dist/src/plugins/webdriver.js +1 -0
- package/dist/src/plugins.d.ts +2 -1
- package/dist/src/plugins2.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-entry.js +1 -1
- package/dist/src/process-exit.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/provider-credential-fingerprint.js +1 -1
- package/dist/src/provider-device-admission.js +1 -1
- package/dist/src/provider-device-runtime.d.ts +556 -0
- package/dist/src/provider-policy.js +1 -0
- package/dist/src/provider-profile-fields.js +1 -1
- package/dist/src/provider-webdriver.js +1 -2
- package/dist/src/proxy.js +2 -2
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-devtools.js +2 -0
- package/dist/src/react-native-overlay2.js +3 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording.js +2 -2
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/remote-bridge.js +1 -0
- package/dist/src/remote-config-core.js +1 -0
- package/dist/src/remote-config.js +1 -1
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-backend-registry.js +1 -0
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay-maestro-backend.js +117 -0
- package/dist/src/replay-script-selection.js +1 -0
- package/dist/src/replay.js +1 -3
- package/dist/src/replay2.js +1 -0
- package/dist/src/reporting.js +3 -3
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-providers.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/retry2.js +1 -0
- package/dist/src/runner-artifact-manifest.js +1 -1
- package/dist/src/runner-cache-retention.js +1 -0
- package/dist/src/runner-cache-trim.js +1 -0
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-device-set.js +1 -0
- package/dist/src/runner-error-classification.js +3 -3
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-lease.js +1 -0
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-retention.js +1 -0
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner-startup-transport.js +1 -0
- package/dist/src/runner-toolchain-probe.js +2 -0
- package/dist/src/runner.js +2 -1
- package/dist/src/runtime-command-surface.js +1 -0
- package/dist/src/runtime-deployment.js +1 -0
- package/dist/src/runtime-factory.js +1 -0
- package/dist/src/runtime-session.js +1 -0
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +2 -1
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot3.js +5 -5
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +20 -29
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.d.ts +4 -2
- package/dist/src/sdk-remote-config.d.ts +4 -0
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +5 -6
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-pipeline-policy.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-replay-runtime-failure-response.js +1 -0
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -1
- package/dist/src/simctl-settings.js +1 -1
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator-state.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -1
- package/dist/src/snapshot-chrome.js +1 -0
- package/dist/src/snapshot-desktop-projection.js +1 -1
- package/dist/src/snapshot-evidence.js +1 -0
- package/dist/src/snapshot-node-lookup.js +1 -0
- package/dist/src/snapshot-occlusion.js +1 -0
- package/dist/src/snapshot-quality-verdict.js +1 -0
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/src.js +5 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +2 -1
- package/dist/src/store.js +1 -1
- package/dist/src/surface-snapshot2.js +1 -1
- package/dist/src/target-evidence-tree.js +1 -0
- package/dist/src/target-evidence.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/touch-runtime2.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/undici.js +8 -8
- package/dist/src/update-check.js +1 -1
- package/dist/src/vars.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/wait.js +1 -0
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/package.json +22 -19
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.23.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.manifest.json +0 -16
- package/dist/src/adb-transport.js +0 -1
- package/dist/src/alert-runtime.js +0 -1
- package/dist/src/app-deployment-resolution.js +0 -2
- package/dist/src/app-inventory-contract.js +0 -1
- package/dist/src/app-log-session-resource.js +0 -1
- package/dist/src/application-lifecycle-runtime.js +0 -1
- package/dist/src/auth-session.js +0 -1
- package/dist/src/cache.js +0 -1
- package/dist/src/capabilities.js +0 -1
- package/dist/src/capture.js +0 -1
- package/dist/src/catalog.js +0 -1
- package/dist/src/click-button.js +0 -1
- package/dist/src/client-metro-companion.js +0 -1
- package/dist/src/client-options.js +0 -3
- package/dist/src/compatibility-policy.js +0 -1
- package/dist/src/daemon-artifacts.js +0 -1
- package/dist/src/daemon-client-transport.js +0 -1
- package/dist/src/daemon-http.js +0 -1
- package/dist/src/device-claim-rule.js +0 -1
- package/dist/src/device-rotation.js +0 -1
- package/dist/src/device-session.js +0 -3
- package/dist/src/device2.js +0 -1
- package/dist/src/device3.js +0 -3
- package/dist/src/dispatch-resolve.js +0 -4
- package/dist/src/format.js +0 -1
- package/dist/src/gesture-plan-types.js +0 -1
- package/dist/src/host.js +0 -1
- package/dist/src/human-control-contract.js +0 -1
- package/dist/src/interaction-ref-policy.js +0 -1
- package/dist/src/interactor-operation-binding.js +0 -1
- package/dist/src/keyboard-actions.js +0 -1
- package/dist/src/lease-context.js +0 -1
- package/dist/src/lease-registry-scope.js +0 -1
- package/dist/src/lease-scope.js +0 -1
- package/dist/src/managed-device-scope.js +0 -1
- package/dist/src/observe-until.js +0 -1
- package/dist/src/output-common.js +0 -5
- package/dist/src/owner-identity.js +0 -3
- package/dist/src/path-resolution.js +0 -1
- package/dist/src/perf-runtime-plan.js +0 -1
- package/dist/src/platform-runtime-app-log-process.js +0 -1
- package/dist/src/platform-runtime-managed-owner.js +0 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +0 -1
- package/dist/src/png.js +0 -1
- package/dist/src/prepare-kind.js +0 -1
- package/dist/src/provider-device-runtimes.js +0 -1
- package/dist/src/provider-session-ownership.js +0 -2
- package/dist/src/providers.js +0 -1
- package/dist/src/registry.js +0 -68
- package/dist/src/request-admission.js +0 -1
- package/dist/src/request-cancellation.js +0 -1
- package/dist/src/request-progress-protocol.js +0 -1
- package/dist/src/runner-cache-metadata.js +0 -3
- package/dist/src/runner-disposal.js +0 -1
- package/dist/src/runner-session-types.js +0 -1
- package/dist/src/runtime-admission.js +0 -1
- package/dist/src/screen-recording-admission-ledger.js +0 -1
- package/dist/src/screen-recording-resource-recovery.js +0 -1
- package/dist/src/screenshot-result.js +0 -1
- package/dist/src/script.js +0 -1
- package/dist/src/scroll-command.js +0 -1
- package/dist/src/scroll-gesture.js +0 -1
- package/dist/src/scroll-indicator.js +0 -1
- package/dist/src/session-artifact-paths.js +0 -1
- package/dist/src/session-paths.js +0 -1
- package/dist/src/session-repair-tombstone.js +0 -1
- package/dist/src/session-routing.js +0 -1
- package/dist/src/session-snapshot.js +0 -1
- package/dist/src/snapshot4.js +0 -1
- package/dist/src/src4.js +0 -1
- package/dist/src/src5.js +0 -1
- package/dist/src/src6.js +0 -1
- package/dist/src/src7.js +0 -2
- package/dist/src/src8.js +0 -115
- package/dist/src/string-enum.js +0 -1
- package/dist/src/success-text.js +0 -1
- package/dist/src/timeouts.js +0 -1
- package/dist/src/touch-reference-frame.js +0 -1
- package/dist/src/transport.js +0 -3
- package/dist/src/ttl-memo.js +0 -1
- package/dist/src/verified-file.js +0 -1
- package/dist/src/viewport.js +0 -1
- package/dist/src/window-state.js +0 -1
- /package/dist/src/{doctor-output.js → doctor-lines.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}function De(e,t,n){let r=j({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&
|
|
1
|
+
import{P as e,Q as t,Y as n,Z as r,i}from"./sdk-contracts.js";import{V as a}from"./tv-remote.js";import{g as o,v as s}from"./sdk-batch-runner.js";import{a as c,n as l,t as u}from"./sdk-device.js";import{C as d,T as f,c as ee,f as te,m as p}from"./sdk-batch.js";import{B as m,E as ne,F as h,G as g,H as re,I as _,K as ie,L as v,M as ae,P as y,R as b,S as oe,U as se,_ as ce,b as x,d as le,g as ue,h as de,i as fe,n as S,p as pe,r as me,t as C,w as he,x as ge,y as _e,z as w}from"./command-metadata.js";import{n as ve,t as ye}from"./cli-output.js";import{r as T,t as E}from"./recording-stop-observation.js";import{r as D}from"./replay-divergence.js";import{n as O}from"./error.js";import{n as k,r as A,t as j}from"./cli-config.js";import{n as M}from"./result-serialization.js";const N=w({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]),P={record:{type:`object`,oneOf:[w({recording:h(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:y(),activeSessionApp:v(),showTouches:y()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:h(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:N},recordingBackend:m(),recordingScope:m(),recordOnlySession:y(),activeSessionApp:v(),durationMs:b(),capturedDurationMs:b(),recorder:_(E,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:_(T,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:y(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:v()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:h(`started`),outPath:m()},[`trace`,`outPath`]),w({trace:h(`stopped`),outPath:m(),artifacts:{type:`array`,items:N}},[`trace`,`outPath`,`artifacts`])]}},be=w({settled:y(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:oe,diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:_([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:y(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:y(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]);function F(e){return e.oneOf?{...e,oneOf:e.oneOf.map(F)}:{...e,properties:{...e.properties??{},settle:be}}}function xe(e){let t={...e};for(let e of Object.keys(t))p(e)&&(t[e]=F(t[e]));return t}const Se=xe({scroll:w({direction:_([`up`,`down`,`left`,`right`]),edge:_([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:y(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:_([`moved`,`at-edge`,`unchanged`,`unobserved`],"Directional scrolls only: what the owner observed after its gesture. `moved` means the content inside the scroller the swipe ran in differs from the tree the session stored immediately before the gesture; `at-edge` and `unchanged` mean it did not change, with no hidden content left to reveal and with no end-of-content signal to read, respectively; `unobserved` means the pair could not back a claim in either direction — nothing comparable was available (no stored tree, a capture from another lineage, a surface that never came to rest), or every difference sits outside the scroller that was swiped, which a changing status bar does on Android — so the reported distance rests on the gesture plan alone. The field is absent — which is never a claim that nothing moved — on the tiers that verify per pass (`scroll top`/`bottom`, `--until`), on a runtime bound without a capture, on a platform whose scroll dispatches no swipe (the Linux wheel), and where the caller already owns that observation (`--settle`, or a replay with `postGestureStabilization: false`).")},[`direction`]),...ne,...he,...ce,..._e,...x,...ue,...de,...ge,...P,...pe,...le}),Ce={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:c},target:{type:`string`,enum:l},kind:{type:`string`,enum:u},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},I={...Se,...Ce},we={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:g({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},L=Object.entries(we),R=new Set(L.map(([e])=>e)),Te=Object.fromEntries(L.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Ee(){return Object.fromEntries(L.map(([e,t])=>[e,t.schema]))}function z(e){return n(e)}function B(e){let n=[`Error (${e.code}): ${e.message}`];if(e.cause){let t=e.cause.code?`${e.cause.code} `:``;n.push(`Cause: ${t}${e.cause.message}`)}e.hint&&n.push(`Hint: ${e.hint}`);for(let t of a(e.details))n.push(`Warning: ${ae(t)}`);n.push(...O(t(e.details))),e.supportedOn&&n.push(`Supported on: ${e.supportedOn}`);let r=D(e.details);return r&&n.push(r),n.join(`
|
|
2
|
+
`)}function De(e,t,n){let r=j({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&A(t,e)&&(i[t]=a);return k(i,t)}const Oe={devices:async e=>({devices:e.map(M)}),apps:async e=>({apps:e})};async function ke(e,t){let n=Oe[e];return n?await n(t):t}function Ae(){let e=new Map;return{pinInput:(t,n,r)=>Ue(t,n,Pe(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>Fe(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);je(e,i,t),Ve(e,i,t)}}}function je(e,t,n){let i=n?.refsGeneration;typeof i==`number`&&U(e,t,r(n),i)}const V=new Set([`snapshot`,`find`]),Me=new Set(te.map(e=>e.name).filter(S).filter(e=>p(e))),Ne=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Pe(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function Fe(e,t,n,r,i){let a=H(r,i);if(Me.has(t)){Re(e,a,ze(n));return}V.has(t)&&(t===`find`?Le(e,a,n):Ie(e,a,n))}function Ie(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);U(e,t,i,r)}function Le(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);U(e,t,i,r)}function Re(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function ze(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),Be(i,n,r)}function Be(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Ve(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];He(i.refs,s),U(e,t,s,a)}function He(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Ue(e,t,n){return n===void 0||n.size===0?t:e===`wait`?We(t,n)??t:Ne.has(e)?Ge(t,n)??t:t}function We(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function Ge(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const Ke={config:g({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:g({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},qe=Object.fromEntries(me().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...se,...Te,...Ke,...qe}}function Je(){return fe().map(e=>{let t=e.name in I?I[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:it(e.name,re(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(t={}){let n=Ae();return{execute:async(r,i)=>{if(!S(r))throw new e(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=C(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new e(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=De(r,i,s),l=Qe(c),u=nt(c),d=n.pinInput(r,u,l.client.stateDir),f=await Xe(t,l.client);try{let e=await(t.runCommand??Ze)(f,r,d);return n.mergeCommandResult(r,e,l.client.stateDir,u.session),{isError:!1,structuredContent:await ke(r,e),content:[{type:`text`,text:await at({name:r,input:u,result:e,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=z(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:B(i)}]}}const Ye=K();async function Xe(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function Ze(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function Qe(e){return{client:$e(e),outputFormat:tt(e.mcpOutputFormat)}}function $e(t){let n=t.stateDir,r=t.includeCost,i=t.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new e(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=et(i);return o!==void 0&&(a.responseLevel=o),a}function et(t){if(t===void 0)return;let n=i.find(e=>e===t);if(n===void 0)throw new e(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function tt(t){if(t===void 0)return`optimized`;if(t!==`optimized`&&t!==`json`)throw new e(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return t}function nt(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!R.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?ie(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(s(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?rt(r,t,e,`${n}.${e}`):void 0)}}function rt(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let a=t[n],o=ee(t[i]);if(o===void 0||!s(a))return;let c=Y(o,C(o),a);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function it(e,t){let n=f(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function Q(e,t){let n=d(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Ee()}}}async function at(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await ye({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?ot(e.name,t):$(t?.data??e.result)}function ot(e,t){let n=t.text??``;if(!ve(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
|
|
3
3
|
`)?``:`
|
|
4
4
|
`}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{z as a,B as i,K as n,R as o,Je as r,Ye as t};
|
|
@@ -1 +1 @@
|
|
|
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{j 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};
|
|
1
|
+
import{P as e,d as t,l as n}from"./sdk-contracts.js";import{E as r,T as i,ct as a}from"./back-mode.js";import{k as o,o as s}from"./sdk-device.js";import{m as c}from"./command-metadata.js";import{t as l}from"./daemon-resolution.js";import{n as u}from"./metro2.js";import{r as d,t as f}from"./remote-config-core.js";import"./remote-config2.js";import{S as p,b as m,c as h,f as g,g as _,l as v,m as y,p as b,s as x,x as S,y as C}from"./cli.js";import{a as w,n as T}from"./provider-policy.js";function E(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 D(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 O=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),k=new Set([`open`]),A=new Set([r.open,r.install,r.reinstall,i.installSource]);async function j(t){let{command:n,flags:i,client:a}=t;if(!i.remoteConfig)return{flags:i,runtime:t.runtime};let o=l(i.stateDir).baseDir,s=d({configPath:i.remoteConfig,cwd:process.cwd(),env:process.env}),c={...S(s.profile),...i,remoteConfig:s.resolvedPath},u=_({stateDir:o,session:c.session??`default`});if(u&&u.remoteConfigPath!==s.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:u.session,activeRemoteConfig:u.remoteConfigPath,requestedRemoteConfig:s.resolvedPath});let f=u??de(c,s.resolvedPath,s.profile),p={...c,session:f.session},m=T(f.leaseProvider).supportsDeferredAppSelection,h=m&&n===r.open?t.positionals?.[0]:void 0;m&&delete p.providerApp;let g=ue(f.runtime,p.platform)??t.runtime,b=f,x=!u,C,w=P(b);if(w.shouldAllocate(n)){let e=await ie({command:n,client:a,state:f,nextState:b,nextFlags:p,initialApp:h,policy:w});b=e.state,x||=e.changed,C=e.acquiredLeaseForCleanup}let E=y({leaseBackend:b.leaseBackend,recordedPlatform:b.platform,requestedPlatform:p.platform});if(!E.ok)throw $({session:f.session,leaseBackend:b.leaseBackend,boundPlatform:E.boundPlatform,requestedPlatform:E.requestedPlatform,detail:`bound-connection`});b={...b,platform:E.platform},p.platform=E.platform;let D=await ee({command:n,flags:p,client:a,state:f,nextState:b,runtime:g,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return b=D.state,g=D.runtime,x||=D.changed,await re({changed:x,stateDir:o,state:b,client:a,acquiredLeaseForCleanup:C,preparedMetroCleanupOnFailure:D.preparedMetroCleanupOnFailure,metroCleanupToStop:D.metroCleanupToStop}),{flags:{...p,session:b.session,leaseId:b.leaseId,leaseBackend:b.leaseBackend,platform:b.platform??p.platform,target:b.target??p.target},runtime:g,connection:v(b)}}async function ee(t){let{command:n,flags:r,state:i,client:a}=t,o=te(t.nextState,r),s=t.runtime;if(!ce(n,r,t.batchSteps,t.positionals)||!X(r)||!ne(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 B(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!le(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 te(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function ne(e,t,n){return e===!0||!t||!Z(t,n)}async function re(e){if(e.changed)try{m({stateDir:e.stateDir,state:e.state})}catch(t){throw await V(e.preparedMetroCleanupOnFailure),await oe(e.client,e.state,e.acquiredLeaseForCleanup),t}await V(e.metroCleanupToStop)}async function ie(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Y(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&me(i,c.device);let l=s.leaseBackend??o??se(i,t);he(r,l);let u=y({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`});ge(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await fe(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,M(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:N(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function M(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function N(e,t,n,r){let i=b(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 P(e){if(e.leaseBackend===`macos-app`)return R;let t=T(e.leaseProvider);return t.leaseKind===`proxy`?L:t.supportsDeferredAppSelection?F:t.usesCloudWebDriverLease?z:I}const F={shouldAllocate:e=>e!==r.apps&&!O.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},I={shouldAllocate:e=>!O.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},L={shouldAllocate:e=>e!==`devices`&&!O.has(e),ttlMs:()=>3e5,resolveLeaseState:pe},R={shouldAllocate:e=>e!==`devices`&&!O.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`}}}},z={shouldAllocate:e=>!O.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function B(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:c(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 V(e){if(e)try{await u(e)}catch{}}async function H(e){try{await w({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}function U(e){return e.leaseBackend===`macos-app`}async function W(e,t,n){return!t.leaseId||U(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,...v(t)})}function G(e){let t=K(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 K(e,t,n){try{let{profile:r}=f({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&q(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function q(e,t){let n=h({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function ae(e,t,n){if(!t.leaseId||U(t))return;let r=G({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return J(t,`no credential known to belong to that endpoint was available`);try{await W(e,t,r.daemonAuthToken);return}catch{return J(t,`the release request failed`)}}function J(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 oe(e,t,n){if(n)try{let r=b(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Y(e){return e.leaseBackend??t(e.platform)}function se(t,n){let r=Y(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 ce(e,t,n,r=[]){return e===`cdp`?p(r)&&!!t.metroPublicBaseUrl:k.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return k.has(t)&&e.runtime===void 0})}function X(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Z(e,t){return!e.platform||!t||!n(t)||e.platform===t}function le(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ue(e,t){if(e)return Z(e,t)?e:void 0}function de(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&&T(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:g(n),daemon:h(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Y(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function fe(t,n,r,i,a,o){let s=v(n);if(n.leaseId&&n.leaseBackend===r){let e=await _e(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,providerDeviceType:a.providerDeviceType,providerProject:a.providerProject,providerBuild:a.providerBuild,providerSessionName:a.providerSessionName,...E(a),awsProjectArn:a.awsProjectArn,awsDeviceArn:a.awsDeviceArn,awsAppArn:a.awsAppArn,awsRegion:a.awsRegion,awsInteractionMode:a.awsInteractionMode}),acquired:!0}}async function pe(t){if(!A.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 Q(t.client,t.flags),r=C(n);return{state:{...t.state,deviceKey:x(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 me(e,t){let n=C(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 Q(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 he(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 ge(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 _e(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(a(e))return;throw e}}export{$ as connectionPlatformConflict,X as hasDeferredMetroConfig,j as materializeRemoteConnectionForCommand,ae as releasePreviousLease,W as releaseRemoteConnectionLease,Y as resolveRequestedLeaseBackend,V as stopMetroCleanup,H as stopReactDevtoolsCleanup,D as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{b as t,s as n}from"./runtime.js";import{l as r,o as i}from"./provider-webdriver.js";import{f as a}from"./store.js";import o from"node:path";async function s(n,r){let i=c(n.app),a={username:n.username,accessKey:n.accessKey},o=d(await u(n.devicesEndpoint??`https://api-cloud.browserstack.com/app-automate/devices.json`,a,r)).find(e=>e.device===n.deviceName&&e.os.toLowerCase()===n.platform&&t(e.osVersion,n.osVersion));if(!o)throw new e(`INVALID_ARGS`,`BrowserStack device "${n.deviceName}" with ${n.platform} ${n.osVersion} is not available.`,{hint:`Choose an exact device and OS version from the BrowserStack App Automate device list.`});let s=await l(i,n,a,r);return{provider:`browserstack`,service:`BrowserStack`,verificationMessage:s.status===`verified`?`Credentials, device, and uploaded app verified.`:`Credentials and device access verified; app availability is checked when the session is created.`,device:{status:`verified`,name:o.device,platform:n.platform,osVersion:o.osVersion},app:s}}function c(e){return i(e)??e}async function l(e,t,n,r){if(a(e)){let i=f(await u(t.appsEndpoint??`https://api-cloud.browserstack.com/app-automate/recent_apps?limit=100`,n,r)).find(t=>t.reference===e);return i?{status:`verified`,...i}:{status:`configured`,reference:e,message:`App reference was not found in the 100 most recent uploads; BrowserStack validates it when creating the session.`}}return/^https?:\/\//i.test(e)?{status:`configured`,reference:e,message:`Public app URL configured; BrowserStack validates it when creating the session.`}:{status:`configured`,name:o.basename(e),reference:e,message:`Local app artifact is ready and will be uploaded when creating the session.`}}async function u(e,t,r){return await n(e,{clientVersion:r,auth:t,hints:{service:`BrowserStack`,unauthorizedHint:`Check BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY.`,networkHint:`Check network access to api-cloud.browserstack.com and retry connect.`}})}function d(t){if(!Array.isArray(t))throw new e(`COMMAND_FAILED`,`BrowserStack device verification response was not a list.`);return t.flatMap(e=>{let t=p(e),n=t?.os_version;return t&&typeof t.device==`string`&&typeof t.os==`string`&&(typeof n==`string`||typeof n==`number`)?[{device:t.device,os:t.os,osVersion:String(n)}]:[]})}function f(t){let n=p(t);if(n&&Object.keys(n).length===0)return[];if(!Array.isArray(t))throw new e(`COMMAND_FAILED`,`BrowserStack app verification response was not a list.`);return t.flatMap(e=>{let t=p(e);return!t||typeof t.app_url!=`string`?[]:[{reference:t.app_url,...typeof t.app_name==`string`?{name:t.app_name}:{},...typeof t.app_version==`string`?{version:t.app_version}:{}}]})}function p(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}async function m(t,n){let i=r({runHostCommand:n,region:t.region}),[a,o,s]=await Promise.all([i(`get-project`,[`--arn`,t.projectArn]),i(`get-device`,[`--arn`,t.deviceArn]),t.appArn?i(`get-upload`,[`--arn`,t.appArn]):void 0]),c=g(a,`project`),l=g(o,`device`),u=_(l.platform);if(u!==t.platform)throw new e(`INVALID_ARGS`,`AWS Device Farm device "${v(l.name)??t.deviceArn}" is ${u}, not ${t.platform}.`);let d=t.appArn?h(g(s,`upload`),t):{status:`missing`,message:`No app upload is attached; AWS Device Farm does not support install after allocation. Reconnect with --aws-app-arn <arn>.`};return{provider:`aws-device-farm`,service:`AWS Device Farm`,verificationMessage:t.appArn?`Credentials, project, device, and app upload verified.`:`Credentials, project, and device verified.`,project:{name:v(c.name),reference:t.projectArn},device:{status:`verified`,name:v(l.name)??t.deviceArn,reference:t.deviceArn,platform:u,osVersion:v(l.os),availability:v(l.availability)},app:d}}function h(t,n){let r=v(t.status);if(r!==`SUCCEEDED`)throw new e(`COMMAND_FAILED`,`AWS Device Farm app upload is not ready (${r??`unknown status`}).`,{status:r,hint:`Wait for the upload to succeed or reconnect with a different --aws-app-arn.`});let i=n.platform===`android`?`ANDROID_APP`:`IOS_APP`,a=v(t.type);if(a!==i)throw new e(`INVALID_ARGS`,`AWS Device Farm app upload type is ${a??`unknown`}, expected ${i}.`);return{status:`verified`,name:v(t.name),reference:n.appArn}}function g(t,n){if(!t||typeof t!=`object`)throw new e(`COMMAND_FAILED`,`AWS Device Farm ${n} response was not an object.`);let r=t[n];if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`COMMAND_FAILED`,`AWS Device Farm response missed ${n}.`);return r}function _(t){if(t===`ANDROID`)return`android`;if(t===`IOS`)return`ios`;throw new e(`UNSUPPORTED_PLATFORM`,`AWS Device Farm device platform is ${String(t)}.`)}function v(e){return typeof e==`string`&&e.length>0?e:void 0}export{s as n,m as t};
|
package/dist/src/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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(
|
|
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{I as e,P as t,d as n}from"./sdk-contracts.js";import{t as r}from"./daemon-resolution.js";import{a as i}from"./version.js";import{r as a}from"./remote-config-core.js";import"./remote-config2.js";import{c as o}from"./device-shell.js";import{n as s,p as c}from"./src.js";import{n as l}from"./provider-webdriver.js";import{i as u,n as d,t as f}from"./provider-limrun-credentials.js";import{n as p,r as m}from"./provider-profile-fields.js";import{_ as h,b as ee,c as g,d as te,f as ne,g as _,h as re,i as ie,l as ae,m as oe,o as se,p as ce,u as le,v,x as y}from"./cli.js";import{t as b}from"./shared.js";import{n as x,r as S,t as ue}from"./provider-policy.js";import{connectionPlatformConflict as de,hasDeferredMetroConfig as fe,releasePreviousLease as pe,releaseRemoteConnectionLease as me,resolveRequestedLeaseBackend as C,stopMetroCleanup as w,stopReactDevtoolsCleanup as T,t as E}from"./connection-runtime.js";import{n as he}from"./load.js";import D from"node:crypto";import O from"node:fs";import k from"node:path";const ge=new Set([`daemonAuthToken`,`metroBearerToken`]);function A(e){let t=F(N(e.profile)),n=k.join(e.stateDir,`remote-connections`,`generated`);O.mkdirSync(n,{recursive:!0,mode:448});let r=k.join(n,`${I(e.provider)}-${P(t)}.json`);O.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{O.chmodSync(r,384)}catch{}return r}function j(n){try{return a(n)}catch(r){let i=e(r);throw new t(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function M(e){let t=j({configPath:A({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:L(e.provider)});return{flags:{...y(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function N(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!ge.has(e)))}function P(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function F(e){return Array.isArray(e)?e.map(F):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,F(t)])):e}function I(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function L(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function R(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function _e(e){let t=await ie({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await ve({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=R(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return M({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function ve(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return ye(await se(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function ye(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return be(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function be(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function xe(e){let n=e.env??process.env,r=Se({flags:e.flags}),i=u(n),a=d(r.leaseBackend)??`android`;if(!i?.apiKey&&!i?.instances?.[a])throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY, or ${f(a).join(`, `)} for an existing instance.`,{hint:`Set the credentials in the environment before running agent-device connect limrun.`});return M({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Se(e){let t=e.flags,n=Ce(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,...E(t)}}function Ce(e){if(p(e,c),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=C(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 we(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=R(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??C(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,...E(e.flags)};return M({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const z={cloud:{resolve:_e,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:we,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},limrun:{resolve:xe,verify:Oe}};function B(e){return Object.hasOwn(z,e)?z[e]:void 0}async function V(e,t,n){let r=l(e,t);return r?await n(r):await he(e,t,n)}async function Te(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:{...y(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...S(i,n)?{provider:i}:{}}}let r=e.provider??(ke(e.flags)?`proxy`:`cloud`),i={flags:e.flags,stateDir:e.stateDir,cwd:t,env:n},o=B(r);return{...o?await o.resolve(i):await V(r,n,async e=>await Ee(r,e,i)),provider:r}}async function Ee(e,r,i){let a=await r.resolve(i);if(a.profile.leaseProvider!==e)throw new t(`INVALID_ARGS`,`Provider connection profile must select its declared provider: ${e}`);let o=R(e,i.stateDir,i.flags.session,a.profile.device);return M({...i,...a,provider:e,profile:{tenant:i.flags.tenant??e,sessionIsolation:i.flags.sessionIsolation??`tenant`,runId:i.flags.runId??`${e}-${o}`,clientId:o,target:i.flags.target??`mobile`,session:i.flags.session,stateDir:i.stateDir,leaseBackend:i.flags.leaseBackend??n(a.profile.platform),...E(i.flags),...a.profile}})}async function De(e){if(!e.provider)return{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`};let t={flags:e.flags,env:process.env},n=B(e.provider);return n?await n.verify(t):await V(e.provider,t.env,async e=>await e.verify(t))}async function Oe(e){return await s({...u(e.env),clientVersion:i(),platform:m(e.flags.platform,`Limrun`)})}function ke(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 Ae(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??je();return{session:i,previous:n.session?_({stateDir:t,session:i}):null,remoteConfigHash:ne(r),daemon:g(n)}}function je(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=x(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 Me(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Ne(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(Le(n.device)),n.app&&o.push(Re(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:te(t.daemon?.baseUrl),liveSession:Pe(t),...Fe(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ie({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function Pe(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Fe(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 Ie(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function Le(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 Re(e,t){return t.status===`missing`?`App: ${qe(e)} — ${t.message??`Install or attach an app before open.`}`:`App: ${t.name??t.reference??`configured app`} — ${t.status===`verified`?`verified`:t.message??`configured`}`}function W(e,t){let n=ze(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function ze(e,t){let n=x(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:Ke()};if(x(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:Be(t)?Ge(e):[...He(t),...We(e).nextSteps],...Ve(t)?{notes:Ue(e,!r)}:{}}}function Be(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function Ve(e){return x(e?.provider).supportsArtifacts}function He(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 Ue(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 We(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function Ge(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 Ke(){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 ${o(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function qe(e){let t=x(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const Je=async({positionals:e,flags:t,client:n})=>{let i=r(t.stateDir).baseDir,a=ut(e);Ye(a,t);let o=await Te({provider:a,flags:t,stateDir:i}),s=o.flags,c=it(o.remoteConfigPath),l=Xe(s,c),u=Ae({stateDir:i,flags:s,remoteConfigPath:o.remoteConfigPath});Ze(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:C(s),connection:c,daemon:u.daemon});let d=await De(o),f=Qe({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});ee({stateDir:i,state:f});let p=await rt(n,i,s,u.previous,f),m=gt(s,f),h=Me(f,d);return await b(s,U({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p}),()=>Ne({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p})),!0};function Ye(e,n){if(!(!e||!n.remoteConfig))throw new t(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function Xe(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&&x(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 Ze(e,n){if(!(!e||dt(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 Qe(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=nt(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=$e(t,o,r),l=tt(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 $e(e,t,n){let r=ce(n??{},t??{}),i=t?.leaseBackend??C(e);return i===`macos-app`?et(e,t,r):{leaseId:t?.leaseId,leaseBackend:i,...r,deviceKey:t?.deviceKey??r.deviceKey}}function et(e,t,n){return{leaseId:e.leaseId??t?.leaseId,leaseBackend:`macos-app`,...n}}function tt(e,t,n,r,i){let a=oe({leaseBackend:r.leaseBackend,recordedPlatform:t?.platform,requestedPlatform:e.platform});if(!a.ok)throw de({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 nt(e,t){return!!(t&&!e.force)}async function rt(e,t,n,r,i){if(!(!r||!n.force)&&(await w(r.metro),await T({stateDir:t,state:r}),!(r.leaseId&&r.leaseId===i.leaseId)))return await pe(e,r,{nextDaemonBaseUrl:i.daemon?.baseUrl,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function it(e){let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return ae(t)}const at=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 w(i.metro),await T({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await me(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return v({stateDir:r,session:a}),await b(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>ot(a,o)),!0},Y=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=_t(i);return await b(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 ot(e,t){return[`Disconnected remote session "${e}".`,...st(t),...lt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
+
`)}function st(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=ct(e);return t?[t]:[]})}function ct(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 lt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function ut(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: ${ue()}.`)}}function X(e){let t=e.session??`default`,n=r(e.stateDir).baseDir;return{session:t,stateDir:n,state:_({stateDir:n,session:t})??(e.session?null:re({stateDir:n}))}}async function Z(e,t){await b(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function dt(e,t){return ft(e,t)&&pt(e,t)&&ht(e.daemon,t.daemon)}function ft(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 pt(e,t){return le(e,t.flags.platform)?[[e.leaseBackend,t.desiredLeaseBackend],[e.target,t.flags.target]].every(([e,t])=>t===void 0||e===t)&&mt(e,t.flags.leaseId)&&h(e,t.connection):!1}function mt(e,t){return e.leaseBackend!==`macos-app`||t===void 0||t===e.leaseId}function ht(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function gt(e,t){if(!t.runtime&&!(!fe(e)&&!$(t.remoteConfigPath)))return Q(t)}function _t(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=q(e,`agent-device metro prepare --remote-config ${o(e.remoteConfigPath)}`);return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function $(e){try{let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}export{Je as connectCommand,Y as connectionCommand,at as disconnectCommand};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U as centerOfRect, Z as defaultHintForCode, a as DaemonRequest, d as JsonRpcRequestEnvelope, et as normalizeError, f as LeaseBackend, o as DaemonResponse, q as DaemonError, 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{R as e,Y as t,b as n}from"./sdk-contracts.js";export{n as centerOfRect,e as defaultHintForCode,t as normalizeError};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{P as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{T as t,ct as n,dt as r,ot as i,vt as a}from"./back-mode.js";import{n as o,r as s}from"./diagnostics.js";import"./diagnostics2.js";import{c,u as l}from"./agent-device-client.js";import{T as u,an as d}from"./sdk-batch.js";const f=new Set([`LEASE_SCOPE_REQUIRED`,`LEASE_SCOPE_MISMATCH`]);function p(t){return n(t)||t instanceof e&&(f.has(t.details?.reason)||t.code===`INVALID_ARGS`)}async function m(e){let{heartbeat:t,callerSignal:n}=e;if(!t)return await e.task(new AbortController().signal);let r=new AbortController,a=new AbortController,o=i,c=h(o),l,u=!1,d=()=>{u=!0,l&&clearTimeout(l),a.abort()},f,m,v=new Promise((e,t)=>{m=t});n&&n.addEventListener(`abort`,d,{once:!0});let y=()=>{let e=e=>{u||(l&&clearTimeout(l),l=setTimeout(y,e))},n=e=>{if(f=e,u){s({level:`warn`,phase:`lease_lost_after_phase`,data:{message:e instanceof Error?e.message:String(e)}});return}r.abort(),m?.(e)},i=e=>{u||s({level:`warn`,phase:`lease_heartbeat_failed`,data:{message:e instanceof Error?e.message:String(e)}})};e(c),(async()=>{let r=o;try{let n=g(await t(r,a.signal));if(n===void 0||n===o)return;let i=h(n);o=n,c=i,e(i)}catch(e){if(p(e)){n(e);return}i(e)}})().catch(()=>void 0)};l=setTimeout(y,0),v.catch(()=>void 0);let b=await _((async()=>await Promise.race([e.task(r.signal),v]))());if(d(),n&&n.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,n){return{command:t.leaseHeartbeat,positionals:[],session:n.session,token:n.token,meta:{...a(e),sessionIsolation:n.sessionIsolation,requestId:n.requestId}}}function y(e,n,i){if(!l(e))return;let a=r(i);if(!a.leaseId)return;let s=d(u(t.leaseHeartbeat),{positionals:[]});return async(t,r)=>await c(e,v(a,{session:i.session,sessionIsolation:i.meta?.sessionIsolation,requestId:o(),token:e.token}),n.transportPreference,n.paths,s===void 0?t:Math.min(s,t),{signal:r})}export{y as buildUploadLeaseHeartbeat,m as runProtectedLeaseWork};
|
|
@@ -1 +1 @@
|
|
|
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};
|
|
1
|
+
import{P as e,Y as t}from"./sdk-contracts.js";import{E as n}from"./back-mode.js";import{r}from"./diagnostics.js";import"./diagnostics2.js";import{a as i,d as a,f as o,l as s,o as c,s as l,u}from"./agent-device-client.js";import{r as d,y as f}from"./file.js";import{i as p}from"./retry.js";import{n as m,r as ee,t as te}from"./daemon-resolution.js";import"./command.js";import"./process.js";import{a as ne,i as re,o as ie,r as h,s as g}from"./version.js";import"./retry2.js";import{c as _}from"./device-shell.js";import{i as v}from"./replay-divergence.js";import{a as y,i as b,n as ae,o as x,t as S}from"./daemon-registration-owner.js";import{n as oe}from"./daemon-registration.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=ie();function D(){let t=E.get(`local`);if(t)return t;let n=h(),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 e(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>C.existsSync(e))??i,o=w.join(n,g),s=r.some(e=>C.existsSync(e)),c=C.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 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=ne();if(e.version!==n)return e.version&&re(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)?ae():void 0;return{paths:a?.paths??te(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(t,n){let r=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=ee(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:m(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(t){let n={transport:`http`,token:t.remoteAuthToken??``,pid:0,baseUrl:t.remoteBaseUrl},r=await i(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 H(e,t={}){let{deadline:n}=t,r=d(e.paths.lockPath);if(r.state===`unproven`)throw W(e,r);let i=a(e.paths.infoPath);if(!i||!de(r,i)||t.waitForLiveStartup&&await U(i,n))return null;let o=await k(i,{onClientTransport:()=>G(i,e.transportPreference,n),onAnyAdvertisedTransport:()=>G(i,`auto`,n)});if(o.kind===`reuse`)return i;if(o.kind===`refuseNewer`)throw me(i,o,e.paths.baseDir);return J(n)<5e3?null:(he(i,o.reason,e.paths.baseDir),await fe(i,e.paths),null)}async function U(e,t){return f(e.pid)&&!await c(e,`auto`,J(t))}function de(e,t){return e.state===`absent`||oe(e,{pid:t.pid,startTime:t.processStartTime??null})}function W(t,n){return new e(`COMMAND_FAILED`,`Daemon registration ownership could not be verified.`,{reason:`daemon_registration_unproven`,inspection:n,stateDir:t.paths.baseDir,hint:o(s(t.paths),t.paths)})}async function fe(t,n){let r=await x({paths:n,observed:{pid:t.pid,startTime:t.processStartTime??null},mode:`graceful`});if(r.status===`retained`)throw new e(`COMMAND_FAILED`,`Daemon replacement could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:r,hint:r.error?.hint??o(s(n),n)})}async function G(e,t,n){if(await K(e,t,n))return!0;for(let i=1;i<=3;i+=1){if(!f(e.pid)||n!==void 0&&Date.now()>=n)return!1;if(await p(Math.min(200,J(n))),await K(e,t,n))return r({level:`warn`,phase:`daemon_probe_recovered`,data:{pid:e.pid,retry:i}}),!0}return!1}async function pe(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 ${_(n)}), then retry so a daemon starts with this policy.`})}async function K(e,t,n){try{return await c(e,t,J(n))}catch(e){if(l(e))return!1;throw e}}function me(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 ${_(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(t){let n=Date.now()+M,r=[],i,a=0;for(;a<2&&Date.now()<n;){a+=1;let e=await _e(t,n);if(`daemon`in e)return e.daemon;if(i=e,e.cleanup&&r.push(e.cleanup),!e.retry)break;await p(Math.min(150,Math.max(0,n-Date.now())))}let{startError:c,startupError:l,daemonProcess:u}=i??{},d=s(t.paths),f=ke(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:M,startupAttempts:a,cleanupResults:r,startError:c,startupError:l,daemonProcess:u,...f?{daemonLogTail:f}:{},metadataState:d,hint:o(d,t.paths)})}async function _e(e,n){let r;try{r=$(e)}catch(t){return await ve(e,t)}let i=await Ce(n,e,r);if(i.kind===`ready`)return{daemon:i.daemon};if(i.kind===`retry`)return{retry:!0};if(i.kind===`unproven`){let e=t(i.error);return{retry:!1,startError:e.message,startupError:e,daemonProcess:{pid:r.pid}}}let{cleanup:a,joined:o}=await q(e,r,n),s=Y(d(e.paths.lockPath));return{cleanup:a,retry:o&&i.kind===`early_exit`&&s,startError:i.kind===`early_exit`?Oe(i.exit):void 0,daemonProcess:i.kind===`early_exit`?i.exit:{pid:r.pid}}}async function ve(e,n){let r=e.ownedStateDir?await x({paths:e.paths,observed:null,mode:`graceful`,ownedStateDir:e.ownedStateDir,lockTimeoutMs:0}):await y({paths:e.paths,observed:null,lockTimeoutMs:0});return{cleanup:r,startError:t(n).message,retry:!e.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(n,i,a,o){if(!Z(n.command)||!i.startedByClient&&!a.ownedStateDir||u(i.info)||X(o)||Q(n,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 r({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:t(new e(`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:t(new e(`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===n.replay||e===n.test}function Q(e,t){return e.command!==n.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 p(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(t,n){let r;try{r=await H(t,{deadline:n,waitForLiveStartup:!0})}catch(t){if(t instanceof e&&t.details?.reason===`daemon_registration_unproven`)return{kind:`unproven`,error:t};throw t}if(Date.now()>=n)return null;if(r)return{kind:`ready`,daemon:{info:r,startedByClient:!1}};let i=d(t.paths.lockPath);return i.state===`unproven`?{kind:`unproven`,error:W(t,i)}:Y(i)?{kind:`retry`}:null}async function Ee(n,i,o){let s=a(n.paths.infoPath);if(!s||!De(s,i))return null;try{return await c(s,n.transportPreference,J(o))&&Date.now()<o?s:null}catch(a){let{cleanup:s,joined:c}=await q(n,i,o);throw r({level:`warn`,phase:`daemon_startup_observation_failed`,data:{stateDir:n.paths.baseDir,cleanup:s,joined:c,error:t(a)}}),a instanceof e&&(a.details={...a.details,stateDir:n.paths.baseDir,cleanupResults:[s],startupJoined:c}),a}}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 b({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(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 je(t,n){if(!t)return;let r=new URL(t).hostname;if(!Me(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 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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{T as e}from"./back-mode.js";import{n as t}from"./diagnostics.js";import"./diagnostics2.js";import{b as n,x as r}from"./daemon-resolution.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 n=o(t);return(async()=>{try{let t=(await r(`http:`)).request({host:`127.0.0.1`,port:String(e),path:`/health`,method:`GET`,agent:!1},e=>{e.resume(),n.settle(!0)});t.on(`error`,()=>n.settle(!1)),n.attach(()=>t.destroy()),t.end()}catch{n.settle(!1)}})(),n.leg}function c(e,t,r,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,r),d=``;return c.setEncoding(`utf8`),c.on(`connect`,()=>{c.write(`${JSON.stringify(u)}\n`)}),c.on(`data`,e=>{let t=n(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:e.sessionList,positionals:[],flags:{},meta:{requestId:t()}}}export{a as probeDaemonResponsive};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{P as t}from"./sdk-contracts.js";import{f as
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{P as t,U as n}from"./sdk-contracts.js";import{f as r}from"./sdk-batch.js";import i from"node:crypto";import a from"node:fs";import o from"node:path";var s=e({DAEMON_POLICY_ENV:()=>c,loadDaemonPolicy:()=>_,parseDaemonPolicy:()=>v,resolveDaemonPolicyCommandName:()=>h});const c=`AGENT_DEVICE_DAEMON_POLICY`,l=[`device-shutdown`],u=r,d=new Set(u.filter(e=>e.catalog.group===`internal`&&e.daemon!==void 0&&e.platformExecution.kind===`none`).map(e=>e.name)),f=new Map(u.flatMap(e=>{let{group:t,servesPublicCommand:n}=e.catalog;return t===`public`?[[e.name,e.name]]:t!==`internal`||d.has(e.name)?[]:[[e.name,n??e.name]]})),p=new Set(f.values()),m=new Set(u.filter(e=>e.catalog.group===`local-cli`).map(e=>e.name));function h(e){if(!d.has(e))return f.get(e)??e}const g=new Set([`version`,`devices`,`commands`,`capabilities`,`leases`]);function _(e=process.env){let t=e[c]?.trim();if(!t)return;let r=o.resolve(t),i;try{i=JSON.parse(a.readFileSync(r,`utf8`))}catch(e){throw E(r,`cannot read policy JSON: ${n(e)}`)}return v(i,r)}function v(e,t){let n=C(e,`policy`,t);for(let e of Object.keys(n))if(!g.has(e))throw E(t,`unknown key "${e}"`);if(n.version!==1)throw E(t,`"version" must be 1`);let r=n.devices===void 0?void 0:y(n.devices,t),a=n.commands===void 0?void 0:b(n.commands,t),o=n.capabilities===void 0?new Set:x(n.capabilities,t),s=n.leases===void 0?void 0:S(n.leases,t),c=JSON.stringify({devices:r?[...r].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:i.createHash(`sha256`).update(c).digest(`hex`),deviceIds:r,commands:a,deniedCapabilities:o,...s?{requiredLeaseBackend:s}:{}})}function y(e,t){let n=C(e,`devices`,t);T(n,[`allow`],`devices`,t);let r=w(n.allow,`devices.allow`,t);if(r.length===0)throw E(t,`"devices.allow" must not be empty`);return new Set(r.map((e,n)=>{let r=`devices.allow[${n}]`,i=C(e,r,t);T(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 E(t,`"${r}" must name exactly one "udid" or "serial"`);return a[0].trim()}))}function b(e,t){let n=C(e,`commands`,t);if(T(n,[`allow`,`deny`],`commands`,t),n.allow===void 0==(n.deny===void 0))throw E(t,`"commands" must set exactly one of "allow" or "deny"`);let r=n.allow===void 0?`deny`:`allow`,i=`commands.${r}`,a=w(n[r],i,t).map(e=>{if(typeof e==`string`&&m.has(e))throw E(t,`"${i}" names ${JSON.stringify(e)}, which runs in the client; name the daemon command it sends, such as "runtime"`);if(typeof e!=`string`||!p.has(e))throw E(t,`"${i}" names unknown command ${JSON.stringify(e)}`);return e});return Object.freeze({mode:r,names:new Set(a)})}function x(e,t){let n=C(e,`capabilities`,t);T(n,[`deny`],`capabilities`,t);let r=l;return new Set(w(n.deny,`capabilities.deny`,t).map(e=>{if(typeof e!=`string`||!r.includes(e))throw E(t,`"capabilities.deny" names unknown capability ${JSON.stringify(e)}`);return e}))}function S(e,t){let n=C(e,`leases`,t);if(T(n,[`require`],`leases`,t),n.require!==`macos-app`)throw E(t,`"leases.require" must be macos-app`);return n.require}function C(e,t,n){if(typeof e==`object`&&e&&!Array.isArray(e))return e;throw E(n,`"${t}" must be an object`)}function w(e,t,n){if(Array.isArray(e))return e;throw E(n,`"${t}" must be an array`)}function T(e,t,n,r){for(let i of Object.keys(e))if(!t.includes(i))throw E(r,`unknown key "${n}.${i}"`)}function E(e,n){return new t(`INVALID_ARGS`,`Invalid daemon policy ${e}: ${n}`,{policyPath:e,hint:`Fix the file named by ${c}, then start the daemon again.`})}export{_ as n,h as r,s as t};
|
|
@@ -1 +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{S as o,j 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=o(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 o=e&&r?`dual`:r?`http`:`socket`;i.assertHeld(),s({destination:t.infoPath,contents:JSON.stringify({...a,port:e,httpPort:r,transport:o,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{s({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
|
+
import{r as e}from"./rolldown-runtime.js";import{P as t,Y as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{D as o,E as s,c,d as l,i as u,k as d,n as f,r as p,y as m,z as h}from"./file.js";import{f as ee}from"./exec.js";import{i as g}from"./retry.js";import{t as _}from"./daemon-resolution.js";import"./command.js";import"./process.js";import"./retry2.js";import{i as te,n as v,r as y}from"./daemon-registration.js";import{r as b,t as x}from"./daemon-shutdown-report.js";import S from"node:fs";import C from"node:os";import w from"node:path";function T(e){return w.join(e,`repair-tombstone.json`)}function E(e,t){try{let n=O(e);return n?.owner===t&&n.expiresAt>Date.now()?n:void 0}catch{return}}function D(e,t){try{O(e)?.owner===t&&S.rmSync(e,{force:!0})}catch{}}function O(e){let t;try{t=S.readFileSync(e,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}return ne(t,e)}function ne(e,n){try{let t=JSON.parse(e);if(!re(t))throw Error(`Invalid repair tombstone fields`);return t}catch(e){throw new t(`COMMAND_FAILED`,`Repair evidence could not be inspected.`,{reason:`repair_evidence_invalid`,path:n},e instanceof Error?e:void 0)}}function re(e){let t=e;return Number.isFinite(t?.reapedAt)&&Number.isFinite(t?.expiresAt)&&typeof t?.owner==`string`&&(t.sourcePath===void 0||typeof t.sourcePath==`string`)&&ie(t.commitFailure)}function ie(e){let t=e;return e===void 0||typeof t?.code==`string`&&typeof t?.message==`string`}function ae(e){let t;try{t=S.readdirSync(e,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return;throw e}for(let n of t){if(!n.isDirectory())continue;let t=O(T(w.join(e,n.name)));if(t?.commitFailure&&t.expiresAt>Date.now())return{sessionName:n.name,tombstone:{...t,commitFailure:t.commitFailure}}}}async function k(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 oe=[/\/dist\/src\/daemon\.js($|[\s"'])/,/\/dist\/src\/internal\/daemon\.js($|[\s"'])/,/\/src\/daemon\.ts($|[\s"'])/];function A(e){let t=e.toLowerCase().replaceAll(`\\`,`/`);return oe.some(e=>e.test(t))}function j(e,t){if(!t||!m(e))return!1;let n=d(e);if(!n||n!==t)return!1;let r=o(e);return r?A(r):!1}function M(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 N(e,t){if(!c(e.pid))return{exited:!1,elapsedMs:0};let n=Date.now(),r=n+t.timeoutMs,i=t.pollMs??100,a=()=>{if(!m(e.pid))return!0;let t=s([e.pid]).get(e.pid);return!!(t?.state.startsWith(`Z`)||t?.startTime&&t.startTime!==e.startTime)},o=a();for(;!o&&Date.now()<r;)await g(Math.min(i,Math.max(0,r-Date.now()))),o=a();return{exited:o,elapsedMs:Date.now()-n}}async function P(e,t){if(!c(e.pid))return{status:`retained`,reason:`identity-unverified`};if(!e.startTime?.trim())return m(e.pid)?{status:`retained`,reason:`missing-start-time`}:{status:`not-running`};let n={pid:e.pid,startTime:e.startTime};if((await N(n,{timeoutMs:0})).exited)return{status:`exited`,identity:n,mode:`already-exited`};let r;if(t.mode===`graceful`){let e=await F(n,{signal:`SIGTERM`,timeoutMs:t.termTimeoutMs});if(e.status!==`survived`)return e;r=`SIGTERM`}let i=await F(n,{signal:`SIGKILL`,timeoutMs:t.killTimeoutMs,previousSignal:r});return i.status===`survived`?{status:`retained`,reason:`exit-timeout`}:i}async function F(e,t){let n=j(e.pid,e.startTime),r=n&&M(e.pid,t.signal),i=r?t.signal===`SIGTERM`?`graceful`:`forced`:t.previousSignal?`graceful`:`already-exited`;return(await N(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 I=e({DAEMON_STARTUP_EXIT_CODES:()=>L,createOwnedReplayStateDir:()=>G,launchDaemonProcess:()=>K,recoverAbandonedDaemonRegistration:()=>X,stopAndRetireDaemon:()=>J,tryAcquireDaemonRegistration:()=>R});const L=Object.freeze({busy:75,unproven:78});async function R(e){let t={...e},n=l(),r=u({lockDirPath:t.lockPath,owner:{...n,acquiredAtMs:Date.now()},description:`daemon registration`});if(r.status!==`acquired`)return r;let{acquisition:i}=r;try{i.assertHeld(),S.rmSync(b(t.baseDir),{force:!0})}catch(e){await B(i,e,t.logPath)}return{status:`acquired`,owner:Object.freeze({publish({socketPort:e,httpPort:r,...a}){i.assertHeld(),H(t.logPath);let o=e&&r?`dual`:r?`http`:`socket`;i.assertHeld(),h({destination:t.infoPath,contents:JSON.stringify({...a,port:e,httpPort:r,transport:o,pid:n.pid,processStartTime:n.startTime??void 0,stateDir:t.baseDir},null,2),mode:384})},async finish(e){let r;try{e&&V(t.baseDir,e,i),r=z(t.infoPath,n,i)}catch(e){return await B(i,e,t.logPath)}return await i.release(),r}})}}function z(e,t,n){n.assertHeld();let r=te(e,t);if(r.state!==`match`)return r;n.assertHeld();try{S.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)throw e}return{state:`removed`}}async function B(e,t,n){try{await e.release()}catch(e){await Q(n,`daemon_registration_release_failed`,e)}throw t}function V(e,t,n){let r=b(e),i=`${JSON.stringify(x(t))}\n`;n.assertHeld();try{h({destination:r,contents:i,mode:384})}catch{return}}function H(e){if(process.platform===`win32`){U(e);return}let t=S.openSync(e,`a`,384);try{S.ftruncateSync(t,0)}finally{S.closeSync(t)}}function U(e){let t;try{t=S.openSync(e,`r+`,384)}catch(n){if(n.code!==`ENOENT`)throw n;S.closeSync(S.openSync(e,`a`,384)),t=S.openSync(e,`r+`,384)}try{S.ftruncateSync(t,0)}finally{S.closeSync(t)}}const W=new WeakMap;function G(){let e=Object.freeze(_(S.mkdtempSync(w.join(C.tmpdir(),`agent-device-replay-daemon-`)))),t=Object.freeze({paths:e});return W.set(t,{paths:e,startups:[],sealed:!1}),t}function K(e){let n=e.ownedStateDir&&q(e.ownedStateDir,e.paths);if(n?.sealed)throw new t(`COMMAND_FAILED`,`Replay daemon startup admission is closed.`,{reason:`daemon_startup_admission_closed`});S.mkdirSync(e.paths.baseDir,{recursive:!0});let r=S.openSync(e.paths.logPath,`a`);try{let t=ee(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({...t,get startTime(){return a.startTime},readIdentity(){return se(i,a),{pid:t.pid,startTime:a.startTime??null}}}),joined:!1};return n&&n.startups.push(a),t.exited.then(()=>{a.joined=!0}),a.startTime=d(t.pid)??void 0,a.launch}finally{S.closeSync(r)}}function se(e,t){if(t.startTime||t.joined)return;let n=y(e.infoPath);if(n?.pid!==t.launch.pid||!n.startTime)return;let r=p(e.lockPath);v(r,n)&&(t.startTime=n.startTime)}function q(e,n){let r=W.get(e);if(!r||Object.entries(r.paths).some(([e,t])=>n[e]!==t))throw new t(`COMMAND_FAILED`,`Private replay directory ownership could not be verified.`,{reason:`daemon_private_state_unowned`});return r}async function J(e){let t,r=e.observed;try{if(e.ownedStateDir&&(t=q(e.ownedStateDir,e.paths),t.sealed=!0,r=ce(t,r),t.retirement))return await t.retirement}catch(r){return await $(t,e.startupJoinTimeoutMs??1e3),{status:`retained`,reason:`ownership-unproven`,removedInfo:!1,error:n(r)}}let i=Z({...e,observed:r},t=>P(t,{mode:e.mode,termTimeoutMs:e.termTimeoutMs??3e3,killTimeoutMs:e.killTimeoutMs??1e3}),t,e.startupJoinTimeoutMs??1e3);t&&(t.retirement=i);let a=await i;return t&&(a.status===`absent`||!a.removedStateDir)&&(t.retirement=void 0),a}function ce(e,t){if(!t){if(e.startups.length===0)return null;throw Y()}let n=e.startups.find(({launch:e})=>e.pid===t.pid);if(!n)throw Y();let{launch:r}=n,i=t.startTime?t:r.readIdentity();if(r.startTime&&r.startTime===i.startTime)return i;throw Y()}function Y(){return new t(`COMMAND_FAILED`,`The observed daemon is not an owned startup lifetime.`,{reason:`daemon_private_startup_unowned`})}async function X(e){return await Z(e,async e=>{if(!e.startTime?.trim())return{status:`retained`,reason:`missing-start-time`};let t={pid:e.pid,startTime:e.startTime};return(await N(t,{timeoutMs:0})).exited?{status:`exited`,identity:t,mode:`already-exited`}:{status:`retained`,reason:`identity-unverified`}})}async function Z(e,t,r,i=1e3){let a={...e.paths},o=e.observed&&{...e.observed},s,c;if(o)try{s=await t(o)}catch(e){c=n(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 le({...e,paths:a},s,r):{status:`retained`,reason:`startup-unconfirmed`,termination:s,removedInfo:!1}}async function le(e,t,r){let i=e.paths,a;try{a=await f({lockDirPath:i.lockPath,owner:{...l(),acquiredAtMs:Date.now()},description:`daemon registration retirement`,timeoutMs:e.lockTimeoutMs??1e3})}catch(e){let r=n(e);return{status:`retained`,reason:r.details?.reason===`process_lock_timeout`?`lock-busy`:`retirement-unconfirmed`,termination:t,removedInfo:!1,error:r}}let o={status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1};try{o=de(z(i.infoPath,t?.identity??null,a),t),o=fe(r,a,o)}catch(e){o={status:`retained`,reason:`retirement-unconfirmed`,termination:t,removedInfo:o.removedInfo,error:n(e)}}return await ue(a,o,i.logPath)}async function ue(e,t,r){try{await e.release()}catch(e){let i=t.status===`retained`?t.error:void 0;i&&await Q(r,`daemon_retirement_release_failed`,e),t={...t,status:`retained`,reason:`retirement-unconfirmed`,error:i??n(e)}}return t}function de(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,t,r){await k({logPath:e},()=>{a({level:`warn`,phase:t,data:{error:n(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 fe(e,t,r){if(!e||r.status!==`retired`&&(r.status!==`absent`||e.startups.length!==0))return r;try{t.assertHeld();let n=ae(e.paths.sessionsDir);return n?r.status===`retired`?{...r,removedStateDir:!1,repairCommitFailure:n}:{status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1,removedStateDir:!1,repairCommitFailure:n}:(t.assertHeld(),S.rmSync(e.paths.baseDir,{recursive:!0,force:!0}),{...r,removedStateDir:!0})}catch(e){return{...r,status:`retained`,reason:`retirement-unconfirmed`,removedStateDir:!1,error:n(e)}}}export{X as a,k as c,T as d,K as i,D as l,G as n,J as o,I as r,R as s,L as t,E as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{c as e,l as t,u as n}from"./file.js";import{t as r}from"./daemon-resolution.js";import"./process.js";import i from"node:fs";function a(e){let t=s(e);return t.status===`registered`?t.identity:null}function o(e,t){return e.state===`held`&&typeof t.startTime==`string`&&t.startTime.trim().length>0&&n(e.owner,t)}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(t){let n=t.pid;return e(n)?{pid:n,startTime:u(t.processStartTime)}:{pid:null,startTime:null}}function l(e,r){let i=s(e);return i.status===`registered`?r?t(i.identity,r)?{state:`replaced`,identity:i.identity}:n(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,3 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{F as t,L as n}from"./file.js";import{c as r,r as i}from"./version.js";import a from"node:crypto";import o from"node:fs";import s from"node:path";const c=`/agent-device`,l=`x-agent-device-tenant`,u=`x-agent-device-network-access`,d=`public-only`;function f(e){return p(e,c)}function p(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(t.replace(/^\/+/,``),n).toString()}function m(e){let t=e?.trim();return t?{authorization:`Bearer ${t}`,"x-agent-device-token":t}:{}}function h(e){let t=e?.trim();return t?{[l]:t}:{}}const g=`x-agent-device-instance`,_=`x-agent-device-upstream-instance`,v=`x-agent-device-instance-mismatch`;function y(e,t,n){return{jsonrpc:`2.0`,id:e,error:{code:-32001,message:t,data:n}}}function b(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}}}const x=`/tmp`;function S(e,t){return s.posix.join(x,`${E(e)}${T(t)}`)}function C(e){return s.posix.join(x,E(e))}function w(e,t,n){let r=T(n),i=s.posix.basename(e,r);return e===s.posix.join(x,`${i}${r}`)&&i.startsWith(`agent-device-${t}-`)&&/^\d+-[a-z0-9]+$/.test(i.slice(`agent-device-${t}-`.length))}function T(e){return e.startsWith(`.`)?e:`.${e}`}function E(e){return`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function D(e,t){let n=[],r=e+t.toString(),i=r.indexOf(`
|
|
2
|
+
`);for(;i!==-1;){let e=r.slice(0,i).trim();r=r.slice(i+1),e&&n.push(e),i=r.indexOf(`
|
|
3
|
+
`)}return{lines:n,buffer:r}}async function O(e){return e===`https:`?(await import(`node:https`)).default:(await import(`node:http`)).default}function k(e){return new Promise((t,n)=>{let r=``;e.setEncoding(`utf8`),e.on(`data`,e=>{r+=e}),e.on(`end`,()=>t(r)),e.on(`error`,n)})}async function A(t,n,r){let i=[],a=0;for await(let o of t){let t=Buffer.isBuffer(o)?o:Buffer.from(o);if(a+=t.length,a>n)throw new e(`INVALID_ARGS`,r);i.push(t)}return Buffer.concat(i)}function j(e,t){let n=a.createHash(`sha256`).update(e).digest(),r=a.createHash(`sha256`).update(t).digest();return a.timingSafeEqual(n,r)}function M(e){return e.meta?.requestProgress===`replay-test`||e.meta?.requestProgress===`command`}function N(e){return!!e&&typeof e==`object`&&e.type===`progress`&&!!e.event}function P(e){return!!e&&typeof e==`object`&&e.type===`response`&&!!e.response}function ee(e){return`${JSON.stringify({type:`progress`,event:e})}\n`}function F(e){return`${JSON.stringify({type:`response`,response:e})}\n`}function I(e){return`${JSON.stringify({type:`response`,response:e})}\n`}function L(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)}function R(e){let t=L(e);return t.length>0&&t!==`.`&&t!==`..`}function z(e,t){return n(e,{cwd:t})}function B(e){return s.join(e,`runner.log`)}function V(e,t){let n=L(t&&t.length>0?t:`unknown`);return s.join(e,`requests`,`${n}.ndjson`)}function H(e){return{path:V(e.sessionDir,e.requestId),ref:{session:e.session,requestId:e.requestId&&e.requestId.length>0?e.requestId:`unknown`}}}function U(e,t){return V(s.join(e,`remote-diagnostics`,L(t.session)),t.requestId)}function W(t,n){if(!R(n))throw new e(`INVALID_ARGS`,`Invalid session name ${JSON.stringify(n)}: a session name cannot be empty, ".", or "..".`);return s.join(t,L(n))}function G(e,t){return s.join(W(e,t),`app.log`)}function K(e,t){return s.join(W(e,t),`app-log.pid`)}function q(e,t={}){let n=J(e,t);return{baseDir:n,infoPath:s.join(n,`daemon.json`),lockPath:s.join(n,`daemon.lock`),logPath:s.join(n,`daemon.log`),allocationsDir:s.join(n,`allocations`),sessionsDir:s.join(n,`sessions`)}}function J(e,t){let r=(e??``).trim();return r?n(r,{env:t.env}):Y(t)}function Y(e={}){let n=s.join(t(`~`,{env:e.env}),`.agent-device`),a=e.projectRoot??i();return r(a)?s.join(n,`dev`,X(a)):n}function X(e){let t=Z(e),n=s.basename(t).replaceAll(/[^a-zA-Z0-9._-]+/g,`-`),r=a.createHash(`sha1`).update(t).digest(`hex`).slice(0,12);return`${n||`agent-device`}-${r}`}function Z(e){try{return o.realpathSync.native(e)}catch{return s.resolve(e)}}function Q(e){let t=(e??``).trim().toLowerCase();return t===`http`?`http`:t===`dual`?`dual`:`socket`}function $(e){let t=(e??``).trim().toLowerCase();return t===`auto`?`auto`:t===`socket`?`socket`:t===`http`?`http`:`auto`}export{l as A,w as B,k as C,v as D,g as E,h as F,p as I,y as L,b as M,m as N,u as O,f as P,C as R,A as S,c as T,F as _,G as a,D as b,H as c,z as d,R as f,ee as g,P as h,U as i,_ as j,d as k,V as l,N as m,Q as n,K as o,L as p,$ as r,W as s,q as t,B as u,I as v,j as w,O as x,M as y,S as z};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{P as e}from"./sdk-contracts.js";import{v as t}from"./sdk-batch-runner.js";import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{v as t}from"./sdk-batch-runner.js";import{p as n}from"./file.js";import{l as r,o as i}from"./exec.js";import"./command.js";import"./process.js";import{D as a,g as o,o as s,u as c,y as l}from"./host-file.js";import u from"node:path";const d=/^[0-9a-fA-F-]{32,36}$/;function f(e){if(!(!e||!d.test(e)))return e.replaceAll(`-`,``).toUpperCase()}function p(e,t){return`${e.uuid}:${m(t)}`}function m(e){return`0x${e.toString(16)}`}function h(e){return typeof e==`string`&&e.length>0?e:void 0}function g(...e){for(let t of e){let e=h(t);if(e)return e}}function _(e){let t=e.filter(e=>!!e);return t.length>0?t.join(` `):void 0}function v(e){try{let n=JSON.parse(e);return t(n)?n:null}catch{return null}}function y(e){if(typeof e==`number`&&Number.isSafeInteger(e))return e;if(typeof e==`string`){let t=e.startsWith(`0x`)?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function b(e,t,n){if(!Object.hasOwn(e,t))return;let r=y(e[t]);if(r!==void 0)return r;S(n,t)}function x(e,t,n){if(!Object.hasOwn(e,t))return;let r=ee(e[t]);if(r!==void 0)return r;S(n,t)}function ee(e){if(typeof e==`bigint`)return e;if(typeof e==`number`&&Number.isSafeInteger(e)||typeof e==`string`&&/^(?:0x[0-9a-fA-F]+|\d+)$/.test(e))return BigInt(e)}function S(t,n){throw new e(`INVALID_ARGS`,`Invalid ${t} numeric field: ${n}`,{hint:`Crash artifact numeric fields must be integer numbers or integer numeric strings.`})}function C(e){return e.length===1?e[0]:void 0}function w(e){return[...new Set(e)]}function te(e){let t=e.match(/^(.*) \+ (\d+)$/);return t?{symbol:t[1],location:Number(t[2])}:{symbol:e}}const ne=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;function re(e){return ie(e)??O(e)}function ie(e){let t=ae(e);if(!t)return null;let n=(Array.isArray(t.payload.usedImages)?t.payload.usedImages:[]).flatMap((e,t)=>D(e,t));if(n.length===0)return null;let r=oe(Array.isArray(t.payload.threads)?t.payload.threads:[],n);return{format:`ips`,images:n,addresses:r.map(({frame:e,...t})=>t),document:t,frameMatches:r,write:e=>T(t,r,e)}}function ae(e){let t=v(e);if(t)return{payload:t};let n=e.indexOf(`
|
|
2
2
|
`);if(n===-1)return null;let r=e.slice(0,n),i=v(e.slice(n+1));return i?{header:r,payload:i}:null}function oe(e,t){let n=new Map(t.map(e=>[e.index,e]));return e.flatMap((e,t)=>se(e).flatMap((e,r)=>ce(e,n,t,r)))}function se(e){return!t(e)||!Array.isArray(e.frames)?[]:e.frames.filter(t)}function ce(e,t,n,r){let i=b(e,`imageIndex`,`IPS frame`),a=x(e,`imageOffset`,`IPS frame`);if(i===void 0||a===void 0)return[];let o=t.get(i);return o?[{frame:e,frameIndex:r,threadIndex:n,image:o,address:o.base+a}]:[]}function T(e,t,n){for(let e of t){let t=n.get(p(e.image,e.address))?.text;t&&E(e.frame,t)}e.payload.agentDeviceSymbolication={tool:`agent-device debug symbols`,symbolicatedFrames:[...n.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}\n`;return e.header?`${e.header}\n${r}`:r}function E(e,t){let n=te(t);e.symbol=n.symbol,n.location!==void 0&&(e.symbolLocation=n.location)}function D(e,n){if(!t(e))return[];let r=f(h(e.uuid)),i=x(e,`base`,`IPS usedImages`);if(!r||i===void 0)return[];let a=h(e.path);return[{index:n,name:h(e.name)??(a?u.basename(a):`image-${n}`),uuid:r,arch:h(e.arch),base:i,path:a}]}function O(e){let t=e.split(`
|
|
3
3
|
`),n=k(t);if(n.length===0)return null;let r=M(t,n);return{format:`text`,images:n,addresses:r,lines:t,frameMatches:r,write(e){let n=new Map(r.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let i=n.get(r);if(!i)return t;let a=e.get(p(i.image,i.address))?.text;return!a||t.includes(a)?t:`${t} // ${a}`}).join(`
|
|
4
4
|
`)}}}function k(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=A(r);e&&t.push(e)}return t}function A(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=f(t[4]);if(!n)return null;let r=j(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function j(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&ne.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let i=u.basename(t);return{name:e.startsWith(i)?i:e}}function M(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=N(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function N(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=P(t,r,i);return a?{image:a,address:i}:null}function P(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>F(e,n))??C(r)}function F(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const I=1e4;async function L(e){return e.dsym&&e.searchPath?[K(e.cwd,e.dsym),...await R(K(e.cwd,e.searchPath))]:e.dsym?[K(e.cwd,e.dsym)]:e.searchPath?await R(K(e.cwd,e.searchPath)):[]}async function R(t){let n=[],r=0;async function i(a){if(n.length>=200)return;if(r+=1,r>I)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:I,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await z(a,t)).isDirectory()){a===t&&B(t);return}if(a.endsWith(`.dSYM`)){n.push(a);return}let s=await o(a,{withFileTypes:!0});for(let e of s)e.isDirectory()&&await i(u.join(a,e.name))}return await i(t),n}async function z(t,n){try{return await c(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function B(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function V(t,n){let r=(await Promise.all(w(t).map(e=>H(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function H(e,t){return await U(e),W(e,i(await r(t,[`--uuid`,e],{timeoutMs:15e3,allowFailure:!0}),`Failed to inspect dSYM UUIDs: ${e}`,{hint:`Verify the dSYM bundle is valid and readable.`}).stdout)}async function U(t){if(!((await c(t).catch(()=>null))?.isDirectory()&&t.endsWith(`.dSYM`)))throw new e(`INVALID_ARGS`,`Not a .dSYM bundle: ${t}`,{hint:`Pass the .dSYM bundle path, not the DWARF executable inside it.`})}function W(e,t){return t.split(`
|