agent-device 0.21.20 → 0.21.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.20.apk → agent-device-android-ime-helper-0.21.22.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.22.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.20.manifest.json → agent-device-android-ime-helper-0.21.22.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.20.manifest.json → agent-device-android-snapshot-helper-0.21.22.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/AppWindowScreenshot.swift +73 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/BackgroundInteraction.swift +557 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/GhostCursor.swift +141 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +107 -3
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +136 -22
- package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/BackgroundInteractionTests.swift +88 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +121 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +10 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +36 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +27 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +6 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +7 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +21 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +121 -17
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +179 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryConfirmation.swift +119 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +8 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +23 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputProbe.swift +59 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +112 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +25 -12
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +6 -1
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +43 -13
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/alert.js +1 -1
- package/dist/src/android-adb.d.ts +12 -0
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/app-backend.js +1 -0
- package/dist/src/app-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +2 -2
- package/dist/src/app-lifecycle2.js +1 -1
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-log-session-resource.js +1 -0
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +2 -2
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/back-mode.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/cache.js +1 -1
- package/dist/src/capabilities.js +1 -1
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +13 -5
- package/dist/src/cli.js +4 -4
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-options.js +3 -0
- package/dist/src/client-types.d.ts +88 -5
- package/dist/src/clipboard-shell-response.js +1 -1
- package/dist/src/cloud-artifacts.d.ts +7 -2
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/code-signature.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-artifacts.js +1 -0
- package/dist/src/daemon-client-lease-beat.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-liveness-probe.js +1 -0
- package/dist/src/daemon-client-transport.js +1 -1
- package/dist/src/daemon-http.js +1 -0
- package/dist/src/daemon-policy-file.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -0
- package/dist/src/daemon-registration.js +1 -1
- package/dist/src/daemon-resolution.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +2 -2
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +1 -1
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-readiness-runtime.js +1 -1
- package/dist/src/device-release.js +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device-shell.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -3
- package/dist/src/device3.js +3 -0
- package/dist/src/devicectl.js +1 -1
- package/dist/src/diagnostics.js +3 -3
- package/dist/src/dispatch-resolve.js +4 -1
- package/dist/src/display-inventory.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -0
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host-file.js +1 -1
- package/dist/src/host.js +1 -1
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +2 -2
- package/dist/src/install-artifact-facade.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source.d.ts +5 -0
- package/dist/src/install-source2.js +1 -1
- package/dist/src/instance-client.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -1
- package/dist/src/interactor.js +5 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +1 -2
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.js +1 -1
- package/dist/src/inventory.js +4 -4
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/ios-client.js +4 -30
- package/dist/src/ios-settings.js +1 -0
- package/dist/src/ios-snapshot-engine.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/launch-confirmation.js +1 -1
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-registry-scope.js +1 -0
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/legacy-xctest-device-set.js +1 -1
- package/dist/src/limrun-download-file.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +28 -2
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/load.js +1 -0
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/macos-facade.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +16 -16
- package/dist/src/observation.js +1 -1
- package/dist/src/observe-until.js +1 -1
- package/dist/src/overlay.js +2 -2
- package/dist/src/owner-identity.js +3 -3
- package/dist/src/path-resolution.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/perf.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +2 -2
- package/dist/src/platform-runtime-runtime-hints.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plugins.d.ts +9 -0
- package/dist/src/plugins.js +1 -0
- package/dist/src/plugins2.js +2 -0
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-size.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/project-runtime.js +1 -1
- package/dist/src/provider-credential-fingerprint.js +1 -0
- package/dist/src/provider-device-admission.js +1 -1
- package/dist/src/provider-device-runtimes.js +1 -0
- package/dist/src/provider-limrun-credentials.js +1 -0
- package/dist/src/provider-profile-fields.js +1 -0
- package/dist/src/provider-session-ownership.js +2 -2
- package/dist/src/provider-webdriver.js +2 -1
- package/dist/src/providers.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +39 -39
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +5 -5
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-cancellation.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/runner-artifact-manifest.js +1 -1
- package/dist/src/runner-cache-metadata.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +2 -2
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-session-types.js +1 -1
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-admission.js +1 -1
- package/dist/src/runtime-transport-hints.js +1 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/runtime10.js +2 -2
- package/dist/src/runtime2.js +3 -3
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -1
- package/dist/src/screenshot-result.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +45 -2
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +33 -4
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +2 -2
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-artifact-paths.js +1 -1
- package/dist/src/session-repair-tombstone.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-stream.js +27 -0
- package/dist/src/session.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/settings2.js +1 -1
- package/dist/src/simctl-settings-facade.js +1 -0
- package/dist/src/simctl-settings.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-diagnostics.js +1 -1
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/store.js +1 -0
- package/dist/src/string-enum.js +1 -1
- package/dist/src/surface-snapshot.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/target-evidence.js +1 -1
- package/dist/src/telemetry.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/toolchain-probe.js +2 -2
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/touch-runtime2.js +1 -1
- package/dist/src/transport.js +2 -2
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/vars.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/package.json +5 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.20.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk.sha256 +0 -1
- package/dist/src/api.js +0 -3
- package/dist/src/daemon-process.js +0 -1
- package/dist/src/multitouch-support.js +0 -1
- package/dist/src/parameterized-recorded-fill.js +0 -1
- package/dist/src/runner-startup-transport.js +0 -1
- package/dist/src/runner-xctestrun.js +0 -1
- package/dist/src/session-store.js +0 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e,S as t,m as n,w as r}from"./owner-identity.js";import{d as i}from"./exec.js";import"./command.js";import"./process.js";import{a,c as o,d as s,f as c,h as l,i as u,l as d,m as f,o as p,p as m,r as h,s as g,t as _,u as v}from"./base-url.js";import{createHash as y}from"node:crypto";import b from"node:fs";import x from"node:path";import{fileURLToPath as S}from"node:url";const C=`companion-tunnel`;function w(e){return y(`sha256`).update(e).digest(`hex`)}function T(e){return e?.trim()?e.trim():void 0}function E(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(typeof t.tenantId==`string`&&typeof t.runId==`string`&&typeof t.leaseId==`string`)return{tenantId:t.tenantId,runId:t.runId,leaseId:t.leaseId}}function D(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function O(e,t,n,r){let i=r??x.join(e,`.agent-device`);if(!n)return{statePath:x.join(i,`${t.slug}.json`),logPath:x.join(i,`${t.slug}.log`)};let a=w(n).slice(0,12),o=x.join(i,t.slug);return{statePath:x.join(o,`${t.slug}-${a}.json`),logPath:x.join(o,`${t.slug}-${a}.log`)}}function k(e){try{let t=JSON.parse(b.readFileSync(e,`utf8`));if(!Number.isInteger(t.pid)||Number(t.pid)<=0||typeof t.serverBaseUrl!=`string`||typeof t.localBaseUrl!=`string`||typeof t.tokenHash!=`string`||t.tokenHash.length===0)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>typeof e==`string`&&e.length>0):[];return{pid:Number(t.pid),startTime:typeof t.startTime==`string`?t.startTime:void 0,command:typeof t.command==`string`?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:T(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:T(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:T(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:T(typeof t.session==`string`?t.session:void 0),bridgeScope:E(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function A(e,t){b.mkdirSync(x.dirname(e),{recursive:!0}),b.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function j(e){b.mkdirSync(x.dirname(e),{recursive:!0}),b.closeSync(b.openSync(e,`a`))}function M(e){try{b.unlinkSync(e)}catch{}}function N(e){try{b.unlinkSync(e)}catch{}}function P(e){try{b.readdirSync(e).length===0&&b.rmdirSync(e)}catch{}}function F(e,t){let n=x.dirname(e.statePath),r=x.dirname(e.logPath);M(e.statePath),N(e.logPath),P(n),r!==n&&P(r),x.basename(n)===t.slug&&P(x.dirname(n))}function I(e,t){return e.includes(t.runArg)}function L(e,i){if(!n(e.pid))return!1;if(e.startTime){let t=r(e.pid);if(!t||t!==e.startTime)return!1}let a=t(e.pid);return!a||!I(a,i.definition)||!e.bridgeScope?!1:e.serverBaseUrl===_(i.serverBaseUrl)&&e.localBaseUrl===_(i.localBaseUrl)&&e.launchUrl===T(i.launchUrl)&&e.registerPath===T(i.registerPath)&&e.unregisterPath===T(i.unregisterPath)&&e.devicePort===i.devicePort&&e.session===T(i.session)&&D(e.bridgeScope,i.bridgeScope)&&e.tokenHash===w(i.bearerToken)}function R(e){return T(e.consumerKey)??T(e.profileKey)??null}function z(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function B(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function V(r,i){if(!n(r.pid))return;let a=t(r.pid);if(!(!a||!I(a,i))){try{process.kill(r.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await e(r.pid,1e3)){try{process.kill(r.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await e(r.pid,1e3)}}}function H(e,t){let n={...t};return n[s]=_(e.serverBaseUrl),n[h]=e.bearerToken,n[p]=_(e.localBaseUrl),n[m]=O(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[v]=e.bridgeScope.tenantId,n[d]=e.bridgeScope.runId,n[o]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[a]=e.launchUrl.trim():delete n[a],e.registerPath?.trim()?n[g]=e.registerPath.trim():delete n[g],e.unregisterPath?.trim()?n[f]=e.unregisterPath.trim():delete n[f],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[c]=e.session.trim():delete n[c],n}function U(e){let t=S(import.meta.url),n=x.extname(t)||`.js`,r=[x.join(x.dirname(t),`${C}${n}`),x.join(x.dirname(t),`internal`,`${C}${n}`)].find(e=>b.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function W(e,n){let a=U(e.definition),o=a.endsWith(`.ts`)?[`--experimental-strip-types`]:[];b.mkdirSync(x.dirname(n),{recursive:!0});let s=b.openSync(n,`a`),c=0;try{c=i(process.execPath,[...o,a,e.definition.runArg],{env:H(e,e.env??process.env),stdio:[`ignore`,s,s]})}finally{b.closeSync(s)}if(!Number.isInteger(c)||c<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:c,startTime:r(c)??void 0,command:t(c)??void 0,serverBaseUrl:_(e.serverBaseUrl),localBaseUrl:_(e.localBaseUrl),launchUrl:T(e.launchUrl),registerPath:T(e.registerPath),unregisterPath:T(e.unregisterPath),devicePort:e.devicePort,session:T(e.session),bridgeScope:e.bridgeScope,tokenHash:w(e.bearerToken),consumers:[]}}async function G(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(r&&L(r,e)){let e=z(r,t);return e!==r&&A(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await V(r,e.definition),F(n,e.definition)),j(n.statePath);let i;try{i=W(e,n.logPath),A(n.statePath,z(i,t))}catch(t){throw i&&await V(i,e.definition).catch(()=>{}),F(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function K(e){let t=R(e),n=O(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=k(n.statePath);if(!r)return F(n,e.definition),{stopped:!1,statePath:n.statePath};let i=B(r,t);return i.consumers.length>0?(A(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await V(r,e.definition),F(n,e.definition),{stopped:!0,statePath:n.statePath})}const q={slug:`metro-companion`,runArg:l,displayName:`Metro companion`};async function J(e){return await G({...e,definition:q,registerPath:e.registerPath??`/api/metro/companion/register`})}async function Y(e){return await K({...e,definition:q})}export{K as i,Y as n,G as r,J as t};
|
package/dist/src/client-metro.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as e,P as t}from"./sdk-contracts.js";import{E as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{d as i,m as a}from"./exec.js";import{t as o}from"./timeouts.js";import"./file.js";import"./command.js";import"./process.js";import"./retry.js";import{t as s}from"./base-url.js";import{t as c}from"./client-metro-companion.js";import{n as l,r as u}from"./project-runtime.js";import{t as d}from"./runtime-transport-hints.js";import f from"node:path";import p from"node:fs";function m(e,t,n=`index.bundle`){let r=new URL(`${s(e)}/${n}`);return r.searchParams.set(`platform`,t),r.searchParams.set(`dev`,`true`),r.searchParams.set(`minify`,`false`),r.toString()}const h=8081,g=`.expo/.virtual-metro-entry.bundle`;function _(t,n){if(t==null||t===``)return n;let r=Number.parseInt(String(t),10);if(!Number.isInteger(r)||r<1||r>65535)throw new e(`INVALID_ARGS`,`Invalid Metro port: ${String(t)}. Use 1-65535.`);return r}function v(t){let n=S(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!S(r),o=d({metroHost:y(t,i,a),metroPort:b(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=ee(r);return{reloadUrl:x(o,o.scheme,`${s}/reload`),messageSocketUrl:x(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function y(e,t,n){return S(e.metroHost)??(t?void 0:S(e.runtime?.metroHost))??(n?void 0:`localhost`)}function b(e,t,n){if(e.metroPort!==void 0)return _(e.metroPort,h);if(!t)return e.runtime?.metroPort??(n?void 0:h)}function ee(e){let t=S(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${g}`;if(r.endsWith(i))return r.slice(0,-i.length);let a=r.lastIndexOf(`/`);return(a>=0?r.slice(a+1):r).endsWith(`.bundle`)&&a>0?r.slice(0,a):``}function x(e,t,n){let r=new URL(`${t}://localhost`);return r.hostname=e.host,r.port=String(e.port),r.pathname=n,r.toString()}function S(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function C(e){return typeof e==`string`&&e.trim()?s(e.trim()):``}function w(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function T(e,t,n){return r(e,{env:t,cwd:n})}function E(e){try{return p.accessSync(e,p.constants.F_OK),!0}catch{return!1}}function D(e){try{return p.statSync(e).isDirectory()}catch{return!1}}function O(t){let n=f.join(t,`package.json`),r=u(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const k=[{file:`pnpm-lock.yaml`,command:`pnpm`},{file:`yarn.lock`,command:`yarn`},{file:`bun.lock`,command:`bun`},{file:`bun.lockb`,command:`bun`},{file:`package-lock.json`,command:`npm`}];function te(e){let t=e;for(;;){for(let{file:e,command:n}of k)if(E(f.join(t,e)))return{command:n,installArgs:[`install`]};if(E(f.join(t,`.git`)))return null;let e=f.dirname(t);if(e===t)return null;t=e}}function A(e){return te(e)??{command:`npm`,installArgs:[`install`]}}function j(e,t){if(t!==`auto`)return t;let n=l(e);return n===`expo`||n===`repack`?n:`react-native`}function M(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function N(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>E(f.join(e,`${t}.config.${n}`)))}function P(e,t){return N(e,`rspack`)?`rspack`:N(e,`webpack`)?`webpack`:M(t,`@rspack/core`)?`rspack`:M(t,`webpack`)?`webpack`:`rspack`}function F(e,t,n){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);return Number.isInteger(r)?Math.max(r,n):t}function ne(e){return e===`expo`?g:`index.bundle`}function I(e,t,n){return{platform:t,bundleUrl:m(e,t,ne(n))}}function L(e,t){return{platform:t,metroHost:w(e?.metro_host),metroPort:e?.metro_port,bundleUrl:w(e?.metro_bundle_url),launchUrl:w(e?.launch_url)}}function R(e,t){if(D(f.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{a(n.command,n.installArgs,{cwd:e,env:t})}catch(e){throw z(e,n)}return{installed:!0,packageManager:n.command}}function z(n,r){let i=t(n),a=`Dependency install failed using detected package manager "${r.command}". If dependencies are already installed (for example via a monorepo root install), pass --no-install-deps to skip this step, or install manually with "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new e(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function B(e){await o(e)}async function V(t,n,r={}){try{let e=await fetch(t,{headers:r,signal:AbortSignal.timeout(n)});return{ok:e.ok,status:e.status,body:await e.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new e(`COMMAND_FAILED`,`Timed out fetching ${t} after ${n}ms`):r}}async function H(e,t){try{let n=await V(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function U(e,t,n,r){return e===`expo`?{command:`npx`,installArgs:[`expo`,`start`,`--host`,`lan`,`--port`,String(n)]}:e===`repack`?{command:`npx`,installArgs:[`react-native`,t===`webpack`?`webpack-start`:`rspack-start`,`--host`,r,`--port`,String(n)]}:{command:`npx`,installArgs:[`react-native`,`start`,`--host`,r,`--port`,String(n)]}}function W(t,n,r,a,o,s,c){let l=U(n,r,a,o);p.mkdirSync(f.dirname(s),{recursive:!0});let u=p.openSync(s,`a`),d=0;try{d=i(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{p.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new e(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function G(e){if(!(!Number.isInteger(e)||e<=0)){try{process.kill(e,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await n(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await n(e,1e3)}}}function K(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function q(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function J(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function Y(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function X(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:K(e.baseUrl,e.bearerToken),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?q(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):q(t instanceof Error?t.message:String(t),!0)}let n=Z(await t.text(),t.status,e.baseUrl);if(!t.ok)throw q(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,J(t.status,n));return ie(n)}function Z(e,t,n){if(!e)return{};try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Expected a JSON object`);return t}catch(r){let i=e.slice(0,200);throw q(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,J(t,e))}}function re(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:L(e.ios_runtime,`ios`),androidRuntime:L(e.android_runtime,`android`),upstream:{bundleUrl:e.upstream.bundle_url??``,host:e.upstream.host??``,port:e.upstream.port??0,statusUrl:e.upstream.status_url??``},probe:{reachable:e.probe.reachable,statusCode:e.probe.status_code,latencyMs:e.probe.latency_ms,detail:e.probe.detail}}}function ie(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw q(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return re(t)}catch(e){throw q(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function Q(e,t,n,r,i){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&a.push(`bridgeError=${t}`),n?.probe.reachable===!1&&a.push(`bridgeProbe=${n.probe.detail||`unreachable (status ${n.probe.statusCode||0})`}`),r&&r!==t&&a.push(`initialBridgeError=${r}`),i&&a.push(`metroCompanionLog=${i}`),a.join(` `)}function ae(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,Q(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function oe(t,n,r){let i=n||w(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&w(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(t&&!a)throw new e(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!t&&i)throw new e(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(t&&a),proxyBaseUrl:t,proxyBearerToken:a}}function se(t){if(!t?.tenantId||!t.runId||!t.leaseId)throw new e(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return t}function ce(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function le(e,t,n){return e.runtimeFilePath?T(e.runtimeFilePath,t,n):null}function ue(e,t,n,r){return T(e.logPath??f.join(r,`.agent-device`,`metro.log`),t,n)}function $(e){let t=e.env??process.env,n=process.cwd(),r=T(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=O(r),o=j(a,i)):o=i;let s=null;o===`repack`&&(a??=O(r),s=P(r,a));let c=C(e.publicBaseUrl),l=C(e.proxyBaseUrl);ce(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=oe(l,w(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:_(e.metroPort??8081,8081),listenHost:w(e.listenHost)??`0.0.0.0`,statusHost:w(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?se(e.bridgeScope):null,startupTimeoutMs:F(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:F(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:le(e,t,n),logPath:ue(e,t,n,r)}}async function de(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await H(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await B(i)}return!1}async function fe(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await X({baseUrl:t.baseUrl,bearerToken:t.bearerToken,scope:t.scope,runtime:t.runtime,timeoutMs:t.probeTimeoutMs});if(e.probe.reachable!==!1)return e;r=e,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!Y(n))throw new e(`COMMAND_FAILED`,Q(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await B(a)}throw new e(`COMMAND_FAILED`,Q(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function pe(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await H(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=W(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await de(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await G(r.pid).catch(()=>{}),new e(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${t.startupTimeoutMs}ms. Check ${t.logPath}.`,{logPath:t.logPath})}async function me(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await X({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!Y(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await he(e,t,n,r,i)),ae(t.proxyBaseUrl,r),r}async function he(t,n,r,i,a){let o;try{o=(await c({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:w(t.launchUrl),profileKey:w(t.companionProfileKey),consumerKey:w(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,Q(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await fe({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ge(e,t){return{baseIosRuntime:e?I(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?I(e,`android`,t):{platform:`android`}}}function _e(e,t){e&&(p.mkdirSync(f.dirname(e),{recursive:!0}),p.writeFileSync(e,JSON.stringify(t,null,2)))}async function ve(e={}){let t=$(e),n=t.installProjectDeps?R(t.projectRoot,t.env):{installed:!1},r=await pe(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ge(t.publicBaseUrl,t.kind),o=await me(e,t),s=o?.iosRuntime??i,c=o?.androidRuntime??a,l={projectRoot:t.projectRoot,kind:t.kind,dependenciesInstalled:n.installed,packageManager:n.packageManager??null,started:r.started,reused:r.reused,pid:r.pid,logPath:t.logPath,statusUrl:r.statusUrl,runtimeFilePath:t.runtimeFilePath,iosRuntime:s,androidRuntime:c,bridge:o};return _e(t.runtimeFilePath,l),l}function ye(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function be(t,n){await new Promise((r,i)=>{let a=new WebSocket(t),o=t=>{clearTimeout(s);try{a.close()}catch{}i(new e(`COMMAND_FAILED`,t))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${t} after ${n}ms`)},n);a.addEventListener(`open`,()=>{a.send(JSON.stringify({version:2,method:`reload`}));let e=()=>{if(a.bufferedAmount===0){clearTimeout(s),a.close(),r();return}setTimeout(e,20)};e()}),a.addEventListener(`error`,()=>{o(`Failed to reach the dev server message socket at ${t}`)})})}async function xe(t={}){let n=F(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=v(t),a=await V(r,n);if(a.ok&&!ye(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await be(i,n)}catch(t){throw new e(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},t instanceof Error?t:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{xe as n,m as r,ve as t};
|
|
1
|
+
import{F as e,P as t}from"./sdk-contracts.js";import{D as n}from"./owner-identity.js";import{n as r}from"./path-resolution.js";import{d as i,m as a}from"./exec.js";import{t as o}from"./timeouts.js";import"./file.js";import"./command.js";import"./process.js";import"./retry.js";import{t as s}from"./base-url.js";import{t as c}from"./client-metro-companion.js";import{n as l,r as u}from"./project-runtime.js";import{t as d}from"./runtime-transport-hints.js";import f from"node:fs";import p from"node:path";function m(e,t,n=`index.bundle`){let r=new URL(`${s(e)}/${n}`);return r.searchParams.set(`platform`,t),r.searchParams.set(`dev`,`true`),r.searchParams.set(`minify`,`false`),r.toString()}const h=8081,g=`.expo/.virtual-metro-entry.bundle`;function _(e,n){if(e==null||e===``)return n;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new t(`INVALID_ARGS`,`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}function v(e){let n=S(e.bundleUrl),r=n??e.runtime?.bundleUrl,i=!!n,a=!!S(r),o=d({metroHost:y(e,i,a),metroPort:b(e,i,a),bundleUrl:r});if(!o)throw new t(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=ee(r);return{reloadUrl:x(o,o.scheme,`${s}/reload`),messageSocketUrl:x(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function y(e,t,n){return S(e.metroHost)??(t?void 0:S(e.runtime?.metroHost))??(n?void 0:`localhost`)}function b(e,t,n){if(e.metroPort!==void 0)return _(e.metroPort,h);if(!t)return e.runtime?.metroPort??(n?void 0:h)}function ee(e){let t=S(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${g}`;if(r.endsWith(i))return r.slice(0,-i.length);let a=r.lastIndexOf(`/`);return(a>=0?r.slice(a+1):r).endsWith(`.bundle`)&&a>0?r.slice(0,a):``}function x(e,t,n){let r=new URL(`${t}://localhost`);return r.hostname=e.host,r.port=String(e.port),r.pathname=n,r.toString()}function S(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function C(e){return typeof e==`string`&&e.trim()?s(e.trim()):``}function w(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function T(e,t,n){return r(e,{env:t,cwd:n})}function E(e){try{return f.accessSync(e,f.constants.F_OK),!0}catch{return!1}}function D(e){try{return f.statSync(e).isDirectory()}catch{return!1}}function O(e){let n=p.join(e,`package.json`),r=u(e);if(!r)throw new t(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const k=[{file:`pnpm-lock.yaml`,command:`pnpm`},{file:`yarn.lock`,command:`yarn`},{file:`bun.lock`,command:`bun`},{file:`bun.lockb`,command:`bun`},{file:`package-lock.json`,command:`npm`}];function te(e){let t=e;for(;;){for(let{file:e,command:n}of k)if(E(p.join(t,e)))return{command:n,installArgs:[`install`]};if(E(p.join(t,`.git`)))return null;let e=p.dirname(t);if(e===t)return null;t=e}}function A(e){return te(e)??{command:`npm`,installArgs:[`install`]}}function j(e,t){if(t!==`auto`)return t;let n=l(e);return n===`expo`||n===`repack`?n:`react-native`}function M(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function N(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>E(p.join(e,`${t}.config.${n}`)))}function P(e,t){return N(e,`rspack`)?`rspack`:N(e,`webpack`)?`webpack`:M(t,`@rspack/core`)?`rspack`:M(t,`webpack`)?`webpack`:`rspack`}function F(e,t,n){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);return Number.isInteger(r)?Math.max(r,n):t}function ne(e){return e===`expo`?g:`index.bundle`}function I(e,t,n){return{platform:t,bundleUrl:m(e,t,ne(n))}}function L(e,t){return{platform:t,metroHost:w(e?.metro_host),metroPort:e?.metro_port,bundleUrl:w(e?.metro_bundle_url),launchUrl:w(e?.launch_url)}}function R(e,t){if(D(p.join(e,`node_modules`)))return{installed:!1};let n=A(e);try{a(n.command,n.installArgs,{cwd:e,env:t})}catch(e){throw z(e,n)}return{installed:!0,packageManager:n.command}}function z(n,r){let i=e(n),a=`Dependency install failed using detected package manager "${r.command}". If dependencies are already installed (for example via a monorepo root install), pass --no-install-deps to skip this step, or install manually with "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new t(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function B(e){await o(e)}async function V(e,n,r={}){try{let t=await fetch(e,{headers:r,signal:AbortSignal.timeout(n)});return{ok:t.ok,status:t.status,body:await t.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new t(`COMMAND_FAILED`,`Timed out fetching ${e} after ${n}ms`):r}}async function H(e,t){try{let n=await V(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function U(e,t,n,r){return e===`expo`?{command:`npx`,installArgs:[`expo`,`start`,`--host`,`lan`,`--port`,String(n)]}:e===`repack`?{command:`npx`,installArgs:[`react-native`,t===`webpack`?`webpack-start`:`rspack-start`,`--host`,r,`--port`,String(n)]}:{command:`npx`,installArgs:[`react-native`,`start`,`--host`,r,`--port`,String(n)]}}function W(e,n,r,a,o,s,c){let l=U(n,r,a,o);f.mkdirSync(p.dirname(s),{recursive:!0});let u=f.openSync(s,`a`),d=0;try{d=i(l.command,l.installArgs,{cwd:e,env:c,stdio:[`ignore`,u,u]})}finally{f.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new t(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function G(e){if(!(!Number.isInteger(e)||e<=0)){try{process.kill(e,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await n(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await n(e,1e3)}}}function K(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function q(e,n){let r=new t(`COMMAND_FAILED`,e);return r.retryable=n,r}function J(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function Y(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function X(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:K(e.baseUrl,e.bearerToken),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?q(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):q(t instanceof Error?t.message:String(t),!0)}let n=Z(await t.text(),t.status,e.baseUrl);if(!t.ok)throw q(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,J(t.status,n));return ie(n)}function Z(e,t,n){if(!e)return{};try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Expected a JSON object`);return t}catch(r){let i=e.slice(0,200);throw q(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,J(t,e))}}function re(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:L(e.ios_runtime,`ios`),androidRuntime:L(e.android_runtime,`android`),upstream:{bundleUrl:e.upstream.bundle_url??``,host:e.upstream.host??``,port:e.upstream.port??0,statusUrl:e.upstream.status_url??``},probe:{reachable:e.probe.reachable,statusCode:e.probe.status_code,latencyMs:e.probe.latency_ms,detail:e.probe.detail}}}function ie(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw q(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return re(t)}catch(e){throw q(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function Q(e,t,n,r,i){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&a.push(`bridgeError=${t}`),n?.probe.reachable===!1&&a.push(`bridgeProbe=${n.probe.detail||`unreachable (status ${n.probe.statusCode||0})`}`),r&&r!==t&&a.push(`initialBridgeError=${r}`),i&&a.push(`metroCompanionLog=${i}`),a.join(` `)}function ae(e,n){if(!n?.iosRuntime.bundleUrl)throw new t(`COMMAND_FAILED`,Q(e,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function oe(e,n,r){let i=n||w(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||e&&w(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(e&&!a)throw new t(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!e&&i)throw new t(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(e&&a),proxyBaseUrl:e,proxyBearerToken:a}}function se(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new t(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return e}function ce(e,n){if(!(e||n))throw new t(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function le(e,t,n){return e.runtimeFilePath?T(e.runtimeFilePath,t,n):null}function ue(e,t,n,r){return T(e.logPath??p.join(r,`.agent-device`,`metro.log`),t,n)}function $(e){let t=e.env??process.env,n=process.cwd(),r=T(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=O(r),o=j(a,i)):o=i;let s=null;o===`repack`&&(a??=O(r),s=P(r,a));let c=C(e.publicBaseUrl),l=C(e.proxyBaseUrl);ce(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=oe(l,w(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:_(e.metroPort??8081,8081),listenHost:w(e.listenHost)??`0.0.0.0`,statusHost:w(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?se(e.bridgeScope):null,startupTimeoutMs:F(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:F(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:le(e,t,n),logPath:ue(e,t,n,r)}}async function de(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await H(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await B(i)}return!1}async function fe(e){let n=Date.now()+e.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let t=await X({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(t.probe.reachable!==!1)return t;r=t,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!Y(n))throw new t(`COMMAND_FAILED`,Q(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await B(a)}throw new t(`COMMAND_FAILED`,Q(e.baseUrl,i,r,e.initialBridgeError,e.companionLogPath))}async function pe(e){let n=`http://${e.statusHost}:${e.metroPort}/status`;if(e.reuseExisting&&await H(n,e.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=W(e.projectRoot,e.kind,e.repackBundler,e.metroPort,e.listenHost,e.logPath,e.env);if(await de(n,e.startupTimeoutMs,e.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await G(r.pid).catch(()=>{}),new t(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${e.startupTimeoutMs}ms. Check ${e.logPath}.`,{logPath:e.logPath})}async function me(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await X({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!Y(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await he(e,t,n,r,i)),ae(t.proxyBaseUrl,r),r}async function he(e,n,r,i,a){let o;try{o=(await c({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:w(e.launchUrl),profileKey:w(e.companionProfileKey),consumerKey:w(e.companionConsumerKey),env:n.env})).logPath}catch(e){throw new t(`COMMAND_FAILED`,Q(n.proxyBaseUrl,e instanceof Error?e.message:String(e),i,a),void 0,e)}try{return await fe({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ge(e,t){return{baseIosRuntime:e?I(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?I(e,`android`,t):{platform:`android`}}}function _e(e,t){e&&(f.mkdirSync(p.dirname(e),{recursive:!0}),f.writeFileSync(e,JSON.stringify(t,null,2)))}async function ve(e={}){let t=$(e),n=t.installProjectDeps?R(t.projectRoot,t.env):{installed:!1},r=await pe(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ge(t.publicBaseUrl,t.kind),o=await me(e,t),s=o?.iosRuntime??i,c=o?.androidRuntime??a,l={projectRoot:t.projectRoot,kind:t.kind,dependenciesInstalled:n.installed,packageManager:n.packageManager??null,started:r.started,reused:r.reused,pid:r.pid,logPath:t.logPath,statusUrl:r.statusUrl,runtimeFilePath:t.runtimeFilePath,iosRuntime:s,androidRuntime:c,bridge:o};return _e(t.runtimeFilePath,l),l}function ye(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function be(e,n){await new Promise((r,i)=>{let a=new WebSocket(e),o=e=>{clearTimeout(s);try{a.close()}catch{}i(new t(`COMMAND_FAILED`,e))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${e} after ${n}ms`)},n);a.addEventListener(`open`,()=>{a.send(JSON.stringify({version:2,method:`reload`}));let e=()=>{if(a.bufferedAmount===0){clearTimeout(s),a.close(),r();return}setTimeout(e,20)};e()}),a.addEventListener(`error`,()=>{o(`Failed to reach the dev server message socket at ${e}`)})})}async function xe(e={}){let n=F(e.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=v(e),a=await V(r,n);if(a.ok&&!ye(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await be(i,n)}catch(e){throw new t(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},e instanceof Error?e:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{xe as n,m as r,ve as t};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{A as t,C as n,D as r,E as i,F as a,M as o,N as s,O as c,P as l,S as u,T as d,_ as f,b as p,f as m,g as h,h as g,j as _,k as v,m as ee,v as te,w as y,x as ne,y as re}from"./session-stream.js";import{i as ie,r as b}from"./ios-client.js";import"./instance-client.js";import{promises as ae}from"fs";import"net";import oe from"os";import x,{basename as se}from"path";import ce,{createHash as le}from"crypto";import"child_process";function S(e,t,n,r,i){if(r===`m`)throw TypeError(`Private method is not writable`);if(r===`a`&&!i)throw TypeError(`Private accessor was defined without a setter`);if(typeof t==`function`?e!==t||!i:!t.has(e))throw TypeError(`Cannot write private member to an object whose class did not declare it`);return r===`a`?i.call(e,n):i?i.value=n:t.set(e,n),n}function C(e,t,n,r){if(n===`a`&&!r)throw TypeError(`Private accessor was defined without a getter`);if(typeof t==`function`?e!==t||!r:!t.has(e))throw TypeError(`Cannot read private member from an object whose class did not declare it`);return n===`m`?r:n===`a`?r.call(e):r?r.value:t.get(e)}let ue=function(){let{crypto:e}=globalThis;if(e?.randomUUID)return ue=e.randomUUID.bind(e),e.randomUUID();let t=new Uint8Array(1),n=e?()=>e.getRandomValues(t)[0]:()=>Math.random()*255&255;return`10000000-1000-4000-8000-100000000000`.replace(/[018]/g,e=>(e^n()&15>>e/4).toString(16))};const de=/^[a-z][a-z0-9+.-]*:/i,fe=e=>de.test(e);let w=e=>(w=Array.isArray,w(e)),pe=w;function me(e){return typeof e==`object`?e??{}:{}}function he(e){if(!e)return!0;for(let t in e)return!1;return!0}function ge(e,t){return Object.prototype.hasOwnProperty.call(e,t)}const _e=(e,t)=>{if(typeof t!=`number`||!Number.isInteger(t))throw new v(`${e} must be an integer`);if(t<0)throw new v(`${e} must be a positive integer`);return t},ve=e=>{try{return JSON.parse(e)}catch{return}},T=`0.49.3`;function ye(){return typeof Deno<`u`&&Deno.build!=null?`deno`:typeof EdgeRuntime<`u`?`edge`:Object.prototype.toString.call(globalThis.process===void 0?0:globalThis.process)===`[object process]`?`node`:`unknown`}const be=()=>{let e=ye();if(e===`deno`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":E(Deno.build.os),"X-Stainless-Arch":Se(Deno.build.arch),"X-Stainless-Runtime":`deno`,"X-Stainless-Runtime-Version":typeof Deno.version==`string`?Deno.version:Deno.version?.deno??`unknown`};if(typeof EdgeRuntime<`u`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`other:${EdgeRuntime}`,"X-Stainless-Runtime":`edge`,"X-Stainless-Runtime-Version":globalThis.process.version};if(e===`node`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":E(globalThis.process.platform??`unknown`),"X-Stainless-Arch":Se(globalThis.process.arch??`unknown`),"X-Stainless-Runtime":`node`,"X-Stainless-Runtime-Version":globalThis.process.version??`unknown`};let t=xe();return t?{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`browser:${t.browser}`,"X-Stainless-Runtime-Version":t.version}:{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`unknown`,"X-Stainless-Runtime-Version":`unknown`}};function xe(){if(typeof navigator>`u`||!navigator)return null;for(let{key:e,pattern:t}of[{key:`edge`,pattern:/Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`chrome`,pattern:/Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`firefox`,pattern:/Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`safari`,pattern:/(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/}]){let n=t.exec(navigator.userAgent);if(n)return{browser:e,version:`${n[1]||0}.${n[2]||0}.${n[3]||0}`}}return null}const Se=e=>e===`x32`?`x32`:e===`x86_64`||e===`x64`?`x64`:e===`arm`?`arm`:e===`aarch64`||e===`arm64`?`arm64`:e?`other:${e}`:`unknown`,E=e=>(e=e.toLowerCase(),e.includes(`ios`)?`iOS`:e===`android`?`Android`:e===`darwin`?`MacOS`:e===`win32`?`Windows`:e===`freebsd`?`FreeBSD`:e===`openbsd`?`OpenBSD`:e===`linux`?`Linux`:e?`Other:${e}`:`Unknown`);let Ce;const we=()=>Ce??=be();function Te(){if(typeof fetch<`u`)return p.fetch;throw Error("`fetch` is not defined as a global; Either pass `fetch` to the client, `new Limrun({ fetch })` or polyfill the global, `globalThis.fetch = fetch`")}function Ee(...e){let t=globalThis.ReadableStream;if(t===void 0)throw Error("`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`");return new t(...e)}function De(e){let t=Symbol.asyncIterator in e?e[Symbol.asyncIterator]():e[Symbol.iterator]();return Ee({start(){},async pull(e){let{done:n,value:r}=await t.next();n?e.close():e.enqueue(r)},async cancel(){await t.return?.()}})}async function Oe(e){if(typeof e!=`object`||!e)return;if(e[Symbol.asyncIterator]){await e[Symbol.asyncIterator]().return?.();return}let t=e.getReader(),n=t.cancel();t.releaseLock(),await n}const ke=({headers:e,body:t})=>({bodyHeaders:{"content-type":`application/json`},body:JSON.stringify(t)});function Ae(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>{if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`)return`${encodeURIComponent(e)}=${encodeURIComponent(t)}`;if(t===null)return`${encodeURIComponent(e)}=`;throw new v(`Cannot stringify type ${typeof t}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`)}).join(`&`)}const D={off:0,error:200,warn:300,info:400,debug:500},O=(e,t,n)=>{if(e){if(ge(D,e))return e;M(n).warn(`${t} was set to ${JSON.stringify(e)}, expected one of ${JSON.stringify(Object.keys(D))}`)}};function k(){}function A(e,t,n){return!t||D[e]>D[n]?k:t[e].bind(t)}const je={error:k,warn:k,info:k,debug:k};let j=new WeakMap;function M(e){let t=e.logger,n=e.logLevel??`off`;if(!t)return je;let r=j.get(t);if(r&&r[0]===n)return r[1];let i={error:A(`error`,t,n),warn:A(`warn`,t,n),info:A(`info`,t,n),debug:A(`debug`,t,n)};return j.set(t,[n,i]),i}const N=e=>(e.options&&(e.options={...e.options},delete e.options.headers),e.headers&&=Object.fromEntries((e.headers instanceof Headers?[...e.headers]:Object.entries(e.headers)).map(([e,t])=>[e,e.toLowerCase()===`authorization`||e.toLowerCase()===`api-key`||e.toLowerCase()===`x-api-key`||e.toLowerCase()===`cookie`||e.toLowerCase()===`set-cookie`?`***`:t])),`retryOfRequestLogID`in e&&(e.retryOfRequestLogID&&(e.retryOf=e.retryOfRequestLogID),delete e.retryOfRequestLogID),e);async function P(e,t){let{response:n,requestLogID:r,retryOfRequestLogID:i,startTime:a}=t,o=await(async()=>{if(n.status===204)return null;if(t.options.__binaryResponse)return n;let e=n.headers.get(`content-type`)?.split(`;`)[0]?.trim();return e?.includes(`application/json`)||e?.endsWith(`+json`)?n.headers.get(`content-length`)===`0`?void 0:await n.json():await n.text()})();return M(e).debug(`[${r}] response parsed`,N({retryOfRequestLogID:i,url:n.url,status:n.status,body:o,durationMs:Date.now()-a})),o}var F,I=class e extends Promise{constructor(e,t,n=P){super(e=>{e(null)}),this.responsePromise=t,this.parseResponse=n,F.set(this,void 0),S(this,F,e,`f`)}_thenUnwrap(t){return new e(C(this,F,`f`),this.responsePromise,async(e,n)=>t(await this.parseResponse(e,n),n))}asResponse(){return this.responsePromise.then(e=>e.response)}async withResponse(){let[e,t]=await Promise.all([this.parse(),this.asResponse()]);return{data:e,response:t}}parse(){return this.parsedPromise||=this.responsePromise.then(e=>this.parseResponse(C(this,F,`f`),e)),this.parsedPromise}then(e,t){return this.parse().then(e,t)}catch(e){return this.parse().catch(e)}finally(e){return this.parse().finally(e)}};F=new WeakMap;var L,Me=class{constructor(e,t,n,r){L.set(this,void 0),S(this,L,e,`f`),this.options=r,this.response=t,this.body=n}hasNextPage(){return this.getPaginatedItems().length?this.nextPageRequestOptions()!=null:!1}async getNextPage(){let e=this.nextPageRequestOptions();if(!e)throw new v("No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.");return await C(this,L,`f`).requestAPIList(this.constructor,e)}async*iterPages(){let e=this;for(yield e;e.hasNextPage();)e=await e.getNextPage(),yield e}async*[(L=new WeakMap,Symbol.asyncIterator)](){for await(let e of this.iterPages())for(let t of e.getPaginatedItems())yield t}},Ne=class extends I{constructor(e,t,n){super(e,t,async(e,t)=>new n(e,t.response,await P(e,t),t.options))}async*[Symbol.asyncIterator](){let e=await this;for await(let t of e)yield t}},R=class extends Me{constructor(e,t,n,r){super(e,t,n,r),this.items=n||[]}getPaginatedItems(){return this.items??[]}nextPageRequestOptions(){let e=this.getPaginatedItems();if(!(typeof this.options.query==`object`&&`endingBefore`in(this.options.query||{}))){let t=e[e.length-1]?.metadata.id;return t?{...this.options,query:{...me(this.options.query),startingAfter:t}}:null}let t=e[0]?.metadata.id;return t?{...this.options,query:{...me(this.options.query),endingBefore:t}}:null}};const Pe=()=>{if(typeof File>`u`){let{process:e}=globalThis,t=typeof e?.versions?.node==`string`&&parseInt(e.versions.node.split(`.`))<20;throw Error("`File` is not defined as a global, which is required for file uploads."+(t?" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.":``))}};function z(e,t,n){return Pe(),new File(e,t??`unknown_file`,n)}function Fe(e){return(typeof e==`object`&&!!e&&(`name`in e&&e.name&&String(e.name)||`url`in e&&e.url&&String(e.url)||`filename`in e&&e.filename&&String(e.filename)||`path`in e&&e.path&&String(e.path))||``).split(/[\\/]/).pop()||void 0}const Ie=e=>typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`,Le=e=>typeof e==`object`&&!!e&&typeof e.size==`number`&&typeof e.type==`string`&&typeof e.text==`function`&&typeof e.slice==`function`&&typeof e.arrayBuffer==`function`,Re=e=>typeof e==`object`&&!!e&&typeof e.name==`string`&&typeof e.lastModified==`number`&&Le(e),ze=e=>typeof e==`object`&&!!e&&typeof e.url==`string`&&typeof e.blob==`function`;async function Be(e,t,n){if(Pe(),e=await e,Re(e))return e instanceof File?e:z([await e.arrayBuffer()],e.name);if(ze(e)){let r=await e.blob();return t||=new URL(e.url).pathname.split(/[\\/]/).pop(),z(await B(r),t,n)}let r=await B(e);if(t||=Fe(e),!n?.type){let e=r.find(e=>typeof e==`object`&&`type`in e&&e.type);typeof e==`string`&&(n={...n,type:e})}return z(r,t,n)}async function B(e){let t=[];if(typeof e==`string`||ArrayBuffer.isView(e)||e instanceof ArrayBuffer)t.push(e);else if(Le(e))t.push(e instanceof Blob?e:await e.arrayBuffer());else if(Ie(e))for await(let n of e)t.push(...await B(n));else{let t=e?.constructor?.name;throw Error(`Unexpected data type: ${typeof e}${t?`; constructor: ${t}`:``}${Ve(e)}`)}return t}function Ve(e){return typeof e!=`object`||!e?``:`; props: [${Object.getOwnPropertyNames(e).map(e=>`"${e}"`).join(`, `)}]`}var V=class{constructor(e){this._client=e}},He=class extends V{get(e,t){return this._client.get(`/v1/analytics`,{query:e,...t})}getInstances(e,t){return this._client.get(`/v1/analytics/instances`,{query:e,...t})}};const Ue=Symbol(`brand.privateNullableHeaders`);function*We(e){if(!e)return;if(Ue in e){let{values:t,nulls:n}=e;yield*t.entries();for(let e of n)yield[e,null];return}let t=!1,n;e instanceof Headers?n=e.entries():pe(e)?n=e:(t=!0,n=Object.entries(e??{}));for(let e of n){let n=e[0];if(typeof n!=`string`)throw TypeError(`expected header name to be a string`);let r=pe(e[1])?e[1]:[e[1]],i=!1;for(let e of r)e!==void 0&&(t&&!i&&(i=!0,yield[n,null]),yield[n,e])}}const H=e=>{let t=new Headers,n=new Set;for(let r of e){let e=new Set;for(let[i,a]of We(r)){let r=i.toLowerCase();e.has(r)||(t.delete(i),e.add(r)),a===null?(t.delete(i),n.add(r)):(t.append(i,a),n.delete(r))}}return{[Ue]:!0,values:t,nulls:n}};function Ge(e){return e.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g,encodeURIComponent)}const Ke=Object.freeze(Object.create(null)),U=((e=Ge)=>function(t,...n){if(t.length===1)return t[0];let r=!1,i=[],a=t.reduce((t,a,o)=>{/[?#]/.test(a)&&(r=!0);let s=n[o],c=(r?encodeURIComponent:e)(``+s);return o!==n.length&&(s==null||typeof s==`object`&&s.toString===Object.getPrototypeOf(Object.getPrototypeOf(s.hasOwnProperty??Ke)??Ke)?.toString)&&(c=s+``,i.push({start:t.length+a.length,length:c.length,error:`Value of type ${Object.prototype.toString.call(s).slice(8,-1)} is not a valid path parameter`})),t+a+(o===n.length?``:c)},``),o=a.split(/[?#]/,1)[0],s=/(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi,c;for(;(c=s.exec(o))!==null;)i.push({start:c.index,length:c[0].length,error:`Value "${c[0]}" can\'t be safely passed as a path parameter`});if(i.sort((e,t)=>e.start-t.start),i.length>0){let e=0,t=i.reduce((t,n)=>{let r=` `.repeat(n.start-e),i=`^`.repeat(n.length);return e=n.start+n.length,t+r+i},``);throw new v(`Path parameters result in path with invalid segments:\n${i.map(e=>e.error).join(`
|
|
2
|
+
`)}\n${a}\n${t}`)}return a})(Ge);var W=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/gradle_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/gradle_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/gradle_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/gradle_instances/${e}`,t)}},qe=class extends V{create(e,t){return this._client.post(`/v1/scoped_tokens`,{body:e,...t})}},Je=class extends V{list(e={},t){return this._client.get(`/v1/assets`,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/assets/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t={},n){return this._client.get(U`/v1/assets/${e}`,{query:t,...n})}getOrCreate(e,t){return this._client.put(`/v1/assets`,{body:e,...t})}};function Ye(e,t){if(!t)return{body:e};let n=0;return{body:new ReadableStream({pull(r){if(n>=e.length){r.close();return}let i=e.subarray(n,Math.min(n+262144,e.length));n+=i.length,r.enqueue(i),t(n,e.length)}}),duplex:`half`}}var Xe=class extends Je{async getOrUpload(e,t){let n=await this.getOrCreate({name:e.name??se(e.path),kind:e.kind??`App`,...e.platform&&{platform:e.platform},...e.ttl&&{ttl:e.ttl},...e.uploadOptions},t),r=await ae.readFile(e.path),i=le(`md5`).update(r).digest(`hex`);if(n.md5&&n.md5===i)return{id:n.id,name:n.name,signedDownloadUrl:n.signedDownloadUrl,kind:n.kind,...n.platform&&{platform:n.platform},md5:n.md5,...n.expiresAt&&{expiresAt:n.expiresAt}};let a=await p.fetch(n.signedUploadUrl,{headers:{...e.onUploadProgress&&{"Content-Length":r.length.toString()},"Content-Type":`application/octet-stream`},method:`PUT`,...Ye(r,e.onUploadProgress)});if(a.status!==200)throw Error(`Failed to upload asset: ${a.status} ${await a.text()}`);return{id:n.id,name:n.name,signedDownloadUrl:n.signedDownloadUrl,kind:n.kind,...n.platform&&{platform:n.platform},md5:i,...n.expiresAt&&{expiresAt:n.expiresAt}}}},Ze=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/ios_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/ios_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/ios_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/ios_instances/${e}`,t)}},Qe=class extends Ze{listSessionArtifacts(e,t,n){return this._client.get(U`/v1/ios_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},$e=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/android_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/android_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/android_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/android_instances/${e}`,t)}},et=class extends $e{listSessionArtifacts(e,t,n){return this._client.get(U`/v1/android_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},tt=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/xcode_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/xcode_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/xcode_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/xcode_instances/${e}`,t)}},nt=class extends Error{constructor(e){super(`Instance ${e} was gone before it reported any cache status`),this.instanceId=e,this.name=`XcodeCacheGoneError`}},rt=class extends Error{constructor(e,t,n){super(`Timed out after ${Math.round(t/1e3)}s waiting for the cache ${e} to finish`+(n?` (last phase: ${n[e].phase})`:``)),this.side=e,this.timeoutMs=t,this.cache=n,this.name=`XcodeCacheTimeoutError`}};const it={restore:12e5,save:72e4};function at(e){return e===`disabled`||e===`unsupported`||e===`restored`||e===`skipped`||e===`failed`}function ot(e){return e===`disabled`||e===`published`||e===`skipped`||e===`failed`||e===`timed_out`}function st(e,t){return t===`restore`?at(e.restore.phase):ot(e.save.phase)}function ct(e,t={}){let n=t.side??`restore`,r=t.timeoutMs??it[n],i=e.baseURL;for(;i.endsWith(`/`);)i=i.slice(0,-1);let a=`${i}/v1/xcode_instances/${encodeURIComponent(e.instanceId)}/cache`;return new Promise((i,o)=>{let s,c=``,l=!1,u=e=>{if(!l){l=!0,clearTimeout(d),t.signal?.removeEventListener(`abort`,f);try{g.close()}catch{}e()}},d=setTimeout(()=>u(()=>o(new rt(n,r,s))),r),f=()=>u(()=>o(t.signal?.reason??Error(`aborted`))),m=!1,h=()=>{m||l||(m=!0,p.fetch(a,{headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`application/json`}}).then(async t=>{if(m=!1,t.status!==404){await t.text().catch(()=>void 0);return}u(()=>s?i({cache:s,gone:!0}):o(new nt(e.instanceId)))}).catch(()=>{m=!1}))},g=re({url:a,fetch:async(t,n)=>{let r=await p.fetch(t,n);return r.status===404&&u(()=>s?i({cache:s,gone:!0}):o(new nt(e.instanceId))),r},onConnect:()=>t.onOpen?.(),headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`text/event-stream`},onMessage:e=>{if(e.event!==`cache`&&e.event!==`gone`)return;let r;try{r=JSON.parse(typeof e.data==`string`?e.data:String(e.data))}catch(e){u(()=>o(Error(`Cache stream sent unreadable data: ${e}`)));return}if(s=r,e.event===`gone`){h();return}let a=`${r.restore.phase}/${r.restore.reason??``}|${r.save.phase}/${r.save.reason??``}`;a!==c&&(c=a,t.onUpdate?.(r)),st(r,n)&&u(()=>i({cache:r,gone:!1}))}});if(t.signal?.aborted){f();return}t.signal?.addEventListener(`abort`,f,{once:!0})})}function lt(e,t){let n=x.resolve(e),r=`limsync-cache-${x.basename(n)}-${ce.createHash(`sha1`).update(n).digest(`hex`).slice(0,8)}`;return{cacheKey:r,basisCacheDir:t??x.join(oe.tmpdir(),r)}}function G(e,t,n,r){return e.getOrCreate({name:t,ttl:n||`336h`,...r}).catch(e=>{let n=`Failed to create upload URL for asset '${t}': ${e instanceof Error?e.message:e}`;throw Error(n,{cause:e})})}const ut=[`none`,`error`,`warn`,`info`,`debug`];function dt(e,t){let n=ut.indexOf(t),r=e=>n>=ut.indexOf(e);return(t,n)=>{r(t)&&(t===`error`||t===`warn`?console[t](e,n):console.log(e,n))}}const ft=/^[A-Z0-9_]+$/,pt=4096,mt=65536;function ht(e){let t=Object.entries(e);if(t.length>32)throw Error(`too many build settings: got ${t.length}, max 32`);let n=0;for(let[e,r]of t){if(!ft.test(e))throw Error(`invalid build setting key "${e}": keys must match ^[A-Z0-9_]+$`);if(typeof r!=`string`)throw Error(`invalid build setting value for "${e}": value must be a string`);let t=Buffer.byteLength(r,`utf8`);if(t>pt)throw Error(`build setting value for "${e}" is too large: got ${t} bytes, max ${pt} bytes`);if(n+=Buffer.byteLength(e,`utf8`)+t,n>mt)throw Error(`build settings payload is too large: max ${mt} bytes`)}}const gt=e=>new Promise(t=>setTimeout(t,e)),_t=/failed: (?:502|503|504)\b|\bEOF\b|ECONNRESET|ECONNREFUSED|socket hang up|fetch failed/i;function vt(e){let t=e instanceof Error?e.message:String(e);return _t.test(t)}async function yt(e,t={}){let n=t.sleep??gt,r=t.attempts??5,i=t.retryOn??vt,a;for(let o=1;o<=r;o++)try{return await e()}catch(e){if(!i(e))throw e;if(a=e,o<r){let r=e instanceof Error?e.message:String(e);t.log?.(`Retrying after error (${r.trim()})...`),await n(2e3*o)}}throw a}function bt(e){if(e===``||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`))throw Error(`invalid sandbox home path from server: ${e}`);let t=e.split(`/`);if(t.some(e=>e===``||e===`.`||e===`..`))throw Error(`invalid sandbox home path from server: ${e}`);return t.join(`/`)}async function xt(e,t){let n=await J(await p.fetch(`${e}/info`,{method:`GET`,headers:{Authorization:`Bearer ${t}`}}),`GET /info`);if(!n.homeDir)throw Error(`GET /info response is missing homeDir`);return{homeDir:bt(n.homeDir),...n.xcode?{xcode:n.xcode}:{}}}function St(e){let t=new URL(e);if(t.protocol===`https:`)t.protocol=`wss:`;else if(t.protocol===`http:`)t.protocol=`ws:`;else throw Error(`Unsupported apiUrl protocol for rbe tunnel: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,``)}/rbe/tunnel`,t.search=``,t.hash=``,t.toString()}var Ct=class extends v{constructor(e){super(`Remote build execution is not available on this Xcode instance (${e} returned 404). Its limbuild may predate RBE support, or you may be targeting the wrong environment (for example production instead of staging).`),this.name=`RbeUnsupportedError`}},wt=class extends v{constructor(e){super(`Xcode version selection is not available on this sandbox (${e} returned 404): its daemon predates Xcode selection. Create a new sandbox, or omit the Xcode version to build with its default.`),this.name=`XcodeSelectionUnsupportedError`}};function Tt(e,t){return q(e,t,e=>new wt(e))}function K(e,t){return q(e,t,e=>new Ct(e))}async function q(e,t,n){if(e.status===404)throw await e.text().catch(()=>void 0),n(t);return J(e,t)}async function J(e,t){let n=await e.text();if(!e.ok)throw g(t,e.status,n,e.headers);if(!n.trim())throw Error(`${t} returned an empty response`);return JSON.parse(n)}var Et=class extends tt{listBuildLogs(e,t){return this._client.get(U`/v1/xcode_instances/${e}/build_logs`,t)}listBazelBuildLogs(e,t){return this._client.get(U`/v1/xcode_instances/${e}/bazel_build_logs`,t)}create(e,t){return super.create(e,t)}getCache(e,t){return this._client.get(U`/v1/xcode_instances/${e}/cache`,t)}bindCacheKey(e,t,n){return this._client.put(U`/v1/xcode_instances/${e}/cache`,{body:{key:t},...n})}followCache(e,t){let n=this._client.apiKey;if(!n)throw Error(`Following cache status needs an API key on the client`);return ct({baseURL:this._client.baseURL,apiKey:n,instanceId:e},t)}async createClient(e){let t,n;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,n=e.instance.status.token}else t=e.apiUrl,n=e.token;let r=dt(`[XcodeInstance]`,e.logLevel??`info`),i=this._client,a,o=()=>(a??=xt(t,n),a),s=async e=>{let r,i;if(`status`in e){if(!e.status.apiUrl)throw Error(`Simulator instance not ready: apiUrl is not available`);r=e.status.apiUrl,i=e.status.token}else r=e.apiUrl,i=e.token;return J(await p.fetch(`${t}/simulator`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({apiUrl:r,token:i})}),`POST /simulator`)},c=async e=>{try{return await i.iosInstances.delete(e),!0}catch{return!1}};return{async sync(e,i){let{cacheKey:a,basisCacheDir:s}=lt(e,i?.basisCacheDir),c=i?.additionalFiles&&i.additionalFiles.length>0?await o():void 0,l=i?.additionalFiles?.map(e=>({localPath:e.localPath,remotePath:c&&e.remotePath.startsWith(`~/`)?`${c.homeDir}/${e.remotePath.slice(2)}`:e.remotePath})),u={apiUrl:t,token:n,udid:a,install:i?.install??!0,ignoreFn:await b(e,{basisCacheDir:s,log:r,xcodeDefaults:!0,...i?.include?{include:i.include}:{},...i?.ignore?{additional:i.ignore}:{}}),basisCacheDir:s,watch:i?.watch??!0,launchMode:`ForegroundIfRunning`,log:r,syncSymlinks:!0,...l?{additionalFiles:l}:{},...i?.onSyncComplete?{onSyncComplete:i.onSyncComplete}:{}},d=await ee(e,u),f={};return d.bytesSent!==void 0&&(f.bytesSent=d.bytesSent),d.stopWatching&&(f.stopWatching=d.stopWatching),f},xcodebuild(e,a){if(a?.reactNative?.devServerURL&&e?.configuration===`Release`)throw Error(`reactNative.devServerURL is only supported for Debug builds`);if(e?.onlyTesting?.length&&e?.skipTesting?.length)throw Error(`onlyTesting and skipTesting are mutually exclusive; pass one`);if((e?.onlyTesting?.length||e?.skipTesting?.length)&&e?.action!==`build-for-testing`)throw Error(`onlyTesting/skipTesting require action: 'build-for-testing'`);if(e?.runTests===!1&&e?.action!==`build-for-testing`)throw Error(`runTests: false requires action: 'build-for-testing'`);if(e?.action===`build-for-testing`&&e.sdk!==void 0&&e.sdk!==`iphonesimulator`)throw Error(`action: 'build-for-testing' requires the iphonesimulator sdk`);a?.buildSettings&&ht(a.buildSettings);let o={command:`xcodebuild`,...e&&{xcodebuild:e},...a?.xcodegen&&{xcodegen:a.xcodegen},...a?.reactNative&&{reactNative:a.reactNative},...a?.signing&&{signing:a.signing},...a?.cloudSigning&&{cloudSigning:a.cloudSigning},...a?.appstore&&{testflight:a.appstore},...a?.buildSettings&&{buildSettings:a.buildSettings},...a?.env?.length&&{env:a.env},...a?.gitInit!==void 0&&{gitInit:a.gitInit},...a?.logProcessor&&{logProcessor:a.logProcessor},...a?.webhook&&{webhook:a.webhook}},s={apiUrl:t,token:n,log:r,...a?.onXctestEvent&&{onXctestEvent:a.onXctestEvent}};if(a?.upload&&`assetName`in a.upload){let e=G(i.assets,a.upload.assetName,a.upload.ttl,a.upload.uploadOptions).then(e=>(o.signedUploadUrl=e.signedUploadUrl,o.assetId=e.id,o.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},o));return f(e,s)}return a?.upload&&`signedUploadUrl`in a.upload&&(o.signedUploadUrl=a.upload.signedUploadUrl),f(o,s)},run(e,i){if(e.trim()===``)throw Error(`commandLine must not be empty`);if(i?.timeoutSeconds!==void 0&&(!Number.isInteger(i.timeoutSeconds)||i.timeoutSeconds<1||i.timeoutSeconds>21600))throw Error(`timeoutSeconds must be an integer between 1 and 21600`);let a={command:`run`,commandLine:e,cwd:i?.cwd??`.`,...i?.env&&{env:i.env},...i?.timeoutSeconds!==void 0&&{timeoutSeconds:i.timeoutSeconds}};return f(a,{apiUrl:t,token:n,log:r})},async getSimulator(){return J(await p.fetch(`${t}/simulator`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /simulator`)},attachSimulator:s,attachNewSimulator:async()=>{let e=await i.iosInstances.create({wait:!0});try{await s(e)}catch(t){throw await c(e.metadata.id),t}return{iosInstanceId:e.metadata.id,simulator:e}},deleteSimulator:c,async getXcode(){return Tt(await p.fetch(`${t}/xcode`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /xcode`)},async setXcode(e){return Tt(await p.fetch(`${t}/xcode`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({version:e})}),`POST /xcode`)},getInfo:()=>xt(t,n),async startRbe(e){return K(await p.fetch(`${t}/rbe`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify(e??{})}),`POST /rbe`)},async getRbe(){return K(await p.fetch(`${t}/rbe`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe`)},async stopRbe(){return K(await p.fetch(`${t}/rbe`,{method:`DELETE`,headers:{Authorization:`Bearer ${n}`}}),`DELETE /rbe`)},async startRbeTunnel(r){return m(St(t),n,r?.host??`127.0.0.1`,r?.port??8980,{mode:`multiplexed`,logLevel:r?.logLevel??e.logLevel??`info`})},async uploadLatestRbeBuild(e){let r,a;if(e.assetName!==void 0){if(!e.assetName)throw Error(`assetName must not be empty`);let t=await G(i.assets,e.assetName,e.ttl);r=t.signedUploadUrl,a=t.signedDownloadUrl}else r=e.signedUploadUrl;return{...await yt(async()=>{let e=await p.fetchLongRequest(`${t}/rbe/upload`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({signedUploadUrl:r})});if(e.status===404)throw await e.text().catch(()=>void 0),Error(`POST /rbe/upload returned 404: the instance may no longer exist, or its limbuild predates RBE upload support. Recreate the instance and retry.`);return J(e,`POST /rbe/upload`)},{retryOn:e=>vt(e)||h(e,400)&&/no successful RBE app build/i.test(e.body)}),...a&&{signedDownloadUrl:a}}},async getActiveRbeBuilds(){return K(await p.fetch(`${t}/rbe/builds/active`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe/builds/active`)},async getRecentRbeBuilds(){return K(await p.fetch(`${t}/rbe/builds/recent`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe/builds/recent`)},waitForRbeBuildEnd(e,r){return new Promise((i,a)=>{if(r?.signal?.aborted){a(Error(`waiting for build ${e} was aborted`));return}let o=!1,s=()=>{d.close(),r?.signal?.removeEventListener(`abort`,u)},c=e=>{o||(o=!0,s(),i(e))},l=e=>{o||(o=!0,s(),a(e))},u=()=>l(Error(`waiting for build ${e} was aborted`)),d=re({url:`${t}/exec/${e}/events`,fetch:te(p.fetch,t=>l(Error(`build event stream for ${e} is unreachable: ${t instanceof Error?t.message:t}`))),headers:{Authorization:`Bearer ${n}`},onMessage:t=>{if(t.event!==`end`)return;let n;try{n=JSON.parse(t.data)}catch(t){l(Error(`invalid build end event for ${e}: ${t}`));return}c(n)},onDisconnect:()=>{l(Error(`build event stream for ${e} ended without a terminal event (the build may have finished and its live stream been removed)`))}});r?.signal?.addEventListener(`abort`,u,{once:!0})})}}}};function Dt(e){let t=e.endsWith(`/`)?e.slice(0,-1):e,n=t.split(`/`);return n[n.length-1]===`local.properties`||n.length===1&&(t===`.gradle`||t===`.kotlin`||t===`build`)}var Ot=class extends W{listBuildLogs(e,t){return this._client.get(U`/v1/gradle_instances/${e}/build_logs`,t)}async createClient(e){let t,n;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,n=e.instance.status.token}else t=e.apiUrl,n=e.token;let r=dt(`[GradleInstance]`,e.logLevel??`info`),i=this._client;return{async sync(e,i){let{cacheKey:a,basisCacheDir:o}=lt(e,i?.basisCacheDir),s=i?.ignore,c={apiUrl:t,token:n,udid:a,install:!1,ignoreFn:await b(e,{basisCacheDir:o,log:r,xcodeDefaults:!1,nestedGitignore:!0,additional:s?e=>Dt(e)||s(e):Dt,...i?.include?{include:i.include}:{}}),basisCacheDir:o,watch:!1,launchMode:`ForegroundIfRunning`,log:r,syncSymlinks:!0},l=await ee(e,c),u={};return l.bytesSent!==void 0&&(u.bytesSent=l.bytesSent),u},gradlebuild(e){let a={command:`gradlebuild`,...e?.tasks?.length&&{tasks:e.tasks},...e?.projectPath&&{projectPath:e.projectPath},...e?.reactNative&&{reactNative:e.reactNative},...e?.signing&&{signing:e.signing},...e?.webhook&&{webhook:e.webhook},...e?.playstore&&{playstore:e.playstore}};if(e?.upload&&`assetName`in e.upload){let o=G(i.assets,e.upload.assetName,e.upload.ttl).then(e=>(a.signedUploadUrl=e.signedUploadUrl,a.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},a));return f(o,{apiUrl:t,token:n,log:r})}return e?.upload&&`signedUploadUrl`in e.upload&&(a.signedUploadUrl=e.upload.signedUploadUrl),f(a,{apiUrl:t,token:n,log:r})}}}};W.prototype.listBuildLogs=Ot.prototype.listBuildLogs,W.prototype.createClient=Ot.prototype.createClient;const Y=e=>{if(globalThis.process!==void 0)return globalThis.process.env?.[e]?.trim()||void 0;if(globalThis.Deno!==void 0)return globalThis.Deno.env?.get?.(e)?.trim()||void 0};var X,Z,Q,kt,$=class{constructor({baseURL:e=Y(`LIMRUN_BASE_URL`),apiKey:t=Y(`LIM_API_KEY`)??null,...n}={}){X.add(this),Q.set(this,void 0),this.androidInstances=new et(this),this.assets=new Xe(this),this.iosInstances=new Qe(this),this.xcodeInstances=new Et(this),this.gradleInstances=new W(this),this.analytics=new He(this),this.scopedTokens=new qe(this);let r={apiKey:t,...n,baseURL:e||`https://api.limrun.com`};this.baseURL=r.baseURL,this.timeout=r.timeout??Z.DEFAULT_TIMEOUT,this.logger=r.logger??console;let i=`warn`;this.logLevel=i,this.logLevel=O(r.logLevel,`ClientOptions.logLevel`,this)??O(Y(`LIMRUN_LOG`),`process.env['LIMRUN_LOG']`,this)??i,this.fetchOptions=r.fetchOptions,this.maxRetries=r.maxRetries??2,this.fetch=r.fetch??Te(),S(this,Q,ke,`f`);let a=Y(`LIMRUN_CUSTOM_HEADERS`);if(a){let e={};for(let t of a.split(`
|
|
3
|
+
`)){let n=t.indexOf(`:`);n>=0&&(e[t.substring(0,n).trim()]=t.substring(n+1).trim())}r.defaultHeaders={...e,...r.defaultHeaders}}this._options=r,this.apiKey=t}withOptions(e){return new this.constructor({...this._options,baseURL:this.baseURL,maxRetries:this.maxRetries,timeout:this.timeout,logger:this.logger,logLevel:this.logLevel,fetch:this.fetch,fetchOptions:this.fetchOptions,apiKey:this.apiKey,...e})}defaultQuery(){return this._options.defaultQuery}validateHeaders({values:e,nulls:t}){if(!(this.apiKey&&e.get(`authorization`))&&!t.has(`authorization`))throw Error(`Could not resolve authentication method. Expected the apiKey to be set. Or for the "Authorization" headers to be explicitly omitted`)}async authHeaders(e){if(this.apiKey!=null)return H([{Authorization:`Bearer ${this.apiKey}`}])}stringifyQuery(e){return Ae(e)}getUserAgent(){return`${this.constructor.name}/JS ${T}`}defaultIdempotencyKey(){return`stainless-node-retry-${ue()}`}makeStatusError(e,t,r,i){return n.generate(e,t,r,i)}buildURL(e,t,n){let r=!C(this,X,`m`,kt).call(this)&&n||this.baseURL,i=fe(e)?new URL(e):new URL(r+(r.endsWith(`/`)&&e.startsWith(`/`)?e.slice(1):e)),a=this.defaultQuery(),o=Object.fromEntries(i.searchParams);return(!he(a)||!he(o))&&(t={...o,...a,...t}),typeof t==`object`&&t&&!Array.isArray(t)&&(i.search=this.stringifyQuery(t)),i.toString()}async prepareOptions(e){}async prepareRequest(e,{url:t,options:n}){}get(e,t){return this.methodRequest(`get`,e,t)}post(e,t){return this.methodRequest(`post`,e,t)}patch(e,t){return this.methodRequest(`patch`,e,t)}put(e,t){return this.methodRequest(`put`,e,t)}delete(e,t){return this.methodRequest(`delete`,e,t)}methodRequest(e,t,n){return this.request(Promise.resolve(n).then(n=>({method:e,path:t,...n})))}request(e,t=null){return new I(this,this.makeRequest(e,t,void 0))}async makeRequest(e,t,n){let r=await e,i=r.maxRetries??this.maxRetries;t??=i,await this.prepareOptions(r);let{req:o,url:s,timeout:c}=await this.buildRequest(r,{retryCount:i-t});await this.prepareRequest(o,{url:s,options:r});let d=`log_`+(Math.random()*(1<<24)|0).toString(16).padStart(6,`0`),f=n===void 0?``:`, retryOf: ${n}`,p=Date.now();if(M(this).debug(`[${d}] sending request`,N({retryOfRequestLogID:n,method:r.method,url:s,options:r,headers:o.headers})),r.signal?.aborted)throw new y;let m=new AbortController,h=await this.fetchWithTimeout(s,o,c,m).catch(l),g=Date.now();if(h instanceof globalThis.Error){let e=`retrying, ${t} attempts remaining`;if(r.signal?.aborted)throw new y;let i=a(h)||/timed? ?out/i.test(String(h)+(`cause`in h?String(h.cause):``));if(t)return M(this).info(`[${d}] connection ${i?`timed out`:`failed`} - ${e}`),M(this).debug(`[${d}] connection ${i?`timed out`:`failed`} (${e})`,N({retryOfRequestLogID:n,url:s,durationMs:g-p,message:h.message})),this.retryRequest(r,t,n??d);throw M(this).info(`[${d}] connection ${i?`timed out`:`failed`} - error; no more retries left`),M(this).debug(`[${d}] connection ${i?`timed out`:`failed`} (error; no more retries left)`,N({retryOfRequestLogID:n,url:s,durationMs:g-p,message:h.message})),i?new u:new ne({cause:h})}let _=`[${d}${f}] ${o.method} ${s} ${h.ok?`succeeded`:`failed`} with status ${h.status} in ${g-p}ms`;if(!h.ok){let e=await this.shouldRetry(h);if(t&&e){let e=`retrying, ${t} attempts remaining`;return await Oe(h.body),M(this).info(`${_} - ${e}`),M(this).debug(`[${d}] response error (${e})`,N({retryOfRequestLogID:n,url:h.url,status:h.status,headers:h.headers,durationMs:g-p})),this.retryRequest(r,t,n??d,h.headers)}let i=e?`error; no more retries left`:`error; not retryable`;M(this).info(`${_} - ${i}`);let a=await h.text().catch(e=>l(e).message),o=ve(a),s=o?void 0:a;throw M(this).debug(`[${d}] response error (${i})`,N({retryOfRequestLogID:n,url:h.url,status:h.status,headers:h.headers,message:s,durationMs:Date.now()-p})),this.makeStatusError(h.status,o,s,h.headers)}return M(this).info(_),M(this).debug(`[${d}] response start`,N({retryOfRequestLogID:n,url:h.url,status:h.status,headers:h.headers,durationMs:g-p})),{response:h,options:r,controller:m,requestLogID:d,retryOfRequestLogID:n,startTime:p}}getAPIList(e,t,n){return this.requestAPIList(t,n&&`then`in n?n.then(t=>({method:`get`,path:e,...t})):{method:`get`,path:e,...n})}requestAPIList(e,t){let n=this.makeRequest(t,null,void 0);return new Ne(this,n,e)}async fetchWithTimeout(e,t,n,r){let{signal:i,method:a,...o}=t||{},s=this._makeAbort(r);i&&i.addEventListener(`abort`,s,{once:!0});let c=setTimeout(s,n),l=globalThis.ReadableStream&&o.body instanceof globalThis.ReadableStream||typeof o.body==`object`&&o.body!==null&&Symbol.asyncIterator in o.body,u={signal:r.signal,...l?{duplex:`half`}:{},method:`GET`,...o};a&&(u.method=a.toUpperCase());try{return await this.fetch.call(void 0,e,u)}finally{clearTimeout(c)}}async shouldRetry(e){let t=e.headers.get(`x-should-retry`);return t===`true`?!0:t===`false`?!1:e.status===408||e.status===409||e.status===429||e.status>=500}async retryRequest(e,t,n,r){let i,a=r?.get(`retry-after-ms`);if(a){let e=parseFloat(a);Number.isNaN(e)||(i=e)}let o=r?.get(`retry-after`);if(o&&!i){let e=parseFloat(o);i=Number.isNaN(e)?Date.parse(o)-Date.now():e*1e3}if(i===void 0){let n=e.maxRetries??this.maxRetries;i=this.calculateDefaultRetryTimeoutMillis(t,n)}return await ie(i),this.makeRequest(e,t-1,n)}calculateDefaultRetryTimeoutMillis(e,t){let n=t-e;return Math.min(.5*2**n,8)*(1-Math.random()*.25)*1e3}async buildRequest(e,{retryCount:t=0}={}){let n={...e},{method:r,path:i,query:a,defaultBaseURL:o}=n,s=this.buildURL(i,a,o);`timeout`in n&&_e(`timeout`,n.timeout),n.timeout=n.timeout??this.timeout;let{bodyHeaders:c,body:l}=this.buildBody({options:n});return{req:{method:r,headers:await this.buildHeaders({options:e,method:r,bodyHeaders:c,retryCount:t}),...n.signal&&{signal:n.signal},...globalThis.ReadableStream&&l instanceof globalThis.ReadableStream&&{duplex:`half`},...l&&{body:l},...this.fetchOptions??{},...n.fetchOptions??{}},url:s,timeout:n.timeout}}async buildHeaders({options:e,method:t,bodyHeaders:n,retryCount:r}){let i={};this.idempotencyHeader&&t!==`get`&&(e.idempotencyKey||=this.defaultIdempotencyKey(),i[this.idempotencyHeader]=e.idempotencyKey);let a=H([i,{Accept:`application/json`,"User-Agent":this.getUserAgent(),"X-Stainless-Retry-Count":String(r),...e.timeout?{"X-Stainless-Timeout":String(Math.trunc(e.timeout/1e3))}:{},...we()},await this.authHeaders(e),this._options.defaultHeaders,n,e.headers]);return this.validateHeaders(a),a.values}_makeAbort(e){return()=>e.abort()}buildBody({options:e}){let{body:t,headers:n}=e;if(!t)return t==null&&`body`in e?C(this,Q,`f`).call(this,{body:t,headers:H([n])}):{bodyHeaders:void 0,body:void 0};let r=H([n]);return ArrayBuffer.isView(t)||t instanceof ArrayBuffer||t instanceof DataView||typeof t==`string`&&r.values.has(`content-type`)||globalThis.Blob&&t instanceof globalThis.Blob||t instanceof FormData||t instanceof URLSearchParams||globalThis.ReadableStream&&t instanceof globalThis.ReadableStream?{bodyHeaders:void 0,body:t}:typeof t==`object`&&(Symbol.asyncIterator in t||Symbol.iterator in t&&`next`in t&&typeof t.next==`function`)?{bodyHeaders:void 0,body:De(t)}:typeof t==`object`&&r.values.get(`content-type`)===`application/x-www-form-urlencoded`?{bodyHeaders:{"content-type":`application/x-www-form-urlencoded`},body:this.stringifyQuery(t)}:C(this,Q,`f`).call(this,{body:t,headers:r})}};Z=$,Q=new WeakMap,X=new WeakSet,kt=function(){return this.baseURL!==`https://api.limrun.com`},$.Limrun=Z,$.DEFAULT_TIMEOUT=3e5,$.LimrunError=v,$.APIError=n,$.APIConnectionError=ne,$.APIConnectionTimeoutError=u,$.APIUserAbortError=y,$.NotFoundError=t,$.ConflictError=r,$.RateLimitError=o,$.BadRequestError=i,$.AuthenticationError=d,$.InternalServerError=c,$.PermissionDeniedError=_,$.UnprocessableEntityError=s,$.toFile=Be,$.AndroidInstances=et,$.Assets=Xe,$.IosInstances=Qe,$.XcodeInstances=Et,$.GradleInstances=W,$.Analytics=He,$.ScopedTokens=qe,process.platform;const At=`agent-device-cli`;function jt(e){return{apiKey:e.apiKey,defaultHeaders:{"x-agent-device-client":At,"x-agent-device-version":e.clientVersion}}}function Mt(t,n,r=`This daemon drives an existing Limrun instance with its own token. Set LIMRUN_API_KEY, or ask the instance owner to do this.`){if(t)return t;throw new e(`UNSUPPORTED_OPERATION`,`${n} requires a Limrun API key.`,{hint:r})}export{$ as i,jt as n,Mt as r,At as t};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as
|
|
1
|
+
import { B as SnapshotViewportSize, D as IosTargetActivation, E as AppleApplicationState, K as DaemonError, L as SnapshotQualityVerdict, M as SnapshotCommandOptionFields, N as SnapshotKeyboardBandFact, P as SnapshotNode, S as DeviceTarget, T as PublicPlatform, V as SnapshotVisibility, Y as NormalizedError, _ as SessionIsolationMode, a as DaemonRequest, f as LeaseBackend, g as ResponseLevel, i as DaemonLockPolicy, m as NetworkIncludeMode, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as SessionRuntimeHints, w as PlatformSelector, x as DeviceKind, y as AppleOS, z as SnapshotUnchanged } from "./sdk-contracts.js";
|
|
2
2
|
import { n as GesturePointerCount, s as AppsFilter } from "./gesture-plan-types.js";
|
|
3
3
|
import { A as BackMode, C as SwipePattern, D as FoldPose, E as DeviceRotation, O as FoldScreenCoordinateSpace, S as ScrollInputDirection, T as TransformGestureParams, _ as TextSizeCategory, c as SnapshotDiagnosticsSummary, d as MOBILE_PERMISSION_TARGETS, f as PermissionAction, i as AndroidSnapshotBackendMetadata, k as SetFoldPoseInput, l as SessionSurface, o as FindLocator, p as PermissionMode, r as CloudProviderSessionResult, s as ScreenshotResultData, t as AgentArtifactsResult, u as MACOS_PERMISSION_TARGETS, v as TvRemoteButton, w as SwipePreset, x as ScrollDirection, y as ScrollCommandResult } from "./cloud-artifacts.js";
|
|
4
|
-
import { _ as
|
|
4
|
+
import { _ as PressCommandResponseData, f as ClickCommandResponseData, g as LongPressCommandResponseData, h as HoverCommandResponseData, m as FindCommandResponseData, p as FillCommandResponseData, v as SettleObservation, y as ClickButton } from "./sdk-selectors.js";
|
|
5
5
|
import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
|
|
6
6
|
import { t as BatchRunResult } from "./sdk-batch-runner.js";
|
|
7
7
|
//#region packages/contracts/src/json.d.ts
|
|
@@ -31,6 +31,13 @@ type LaunchConfirmation = 'accepted';
|
|
|
31
31
|
//#region packages/contracts/src/client-connection.d.ts
|
|
32
32
|
type AgentDeviceDaemonTransportContext = {
|
|
33
33
|
authToken?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Cancels this one in-flight request. A built-in transport that sees an abort destroys the
|
|
36
|
+
* request's connection, which makes the daemon mark the request canceled; the promise rejects
|
|
37
|
+
* with the typed canceled-request error. A custom transport that ignores the signal keeps its
|
|
38
|
+
* own cancellation contract, and the client still rejects the caller's promise on abort.
|
|
39
|
+
*/
|
|
40
|
+
signal?: AbortSignal;
|
|
34
41
|
};
|
|
35
42
|
type AgentDeviceDaemonTransport = (req: Omit<DaemonRequest, 'token'>, context?: AgentDeviceDaemonTransportContext) => Promise<DaemonResponse>;
|
|
36
43
|
type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProfileFields & {
|
|
@@ -50,7 +57,22 @@ type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProf
|
|
|
50
57
|
iosXctestDerivedDataPath?: string;
|
|
51
58
|
iosXctestEnvDir?: string;
|
|
52
59
|
};
|
|
53
|
-
type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerAppiumVersion' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'
|
|
60
|
+
type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerAppiumVersion' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'> & {
|
|
61
|
+
/**
|
|
62
|
+
* Cancels this one call. Already aborted: the call rejects without sending anything
|
|
63
|
+
* (`details.dispatched: 'no'`). Aborted in flight: the request's connection closes, the daemon
|
|
64
|
+
* marks the request canceled, and the promise rejects with the typed canceled-request error
|
|
65
|
+
* (`details.reason: 'request_canceled'`). An abort is never a timeout: no runner sweep, no
|
|
66
|
+
* daemon reset.
|
|
67
|
+
*
|
|
68
|
+
* The guarantee covers the daemon request, and the built-in transports enforce it; a custom
|
|
69
|
+
* transport receives the signal on its context and may implement cancellation differently. Two
|
|
70
|
+
* phases run outside it: a response-artifact download started after the response begins is not
|
|
71
|
+
* canceled, and a canceled one-shot replay still runs the existing cleanup that may tear down a
|
|
72
|
+
* daemon this client started.
|
|
73
|
+
*/
|
|
74
|
+
signal?: AbortSignal;
|
|
75
|
+
};
|
|
54
76
|
type AgentDeviceIdentifiers = {
|
|
55
77
|
session?: string;
|
|
56
78
|
deviceId?: string;
|
|
@@ -85,6 +107,10 @@ type AgentDeviceDevice = {
|
|
|
85
107
|
* Apple devices; `platform` still carries the leaf (`ios`/`macos`).
|
|
86
108
|
*/
|
|
87
109
|
appleOs?: AppleOS;
|
|
110
|
+
/** Hardware model, for example `iPhone 17 Pro` or `Pixel 9`, when discovery reports it. */
|
|
111
|
+
model?: string;
|
|
112
|
+
/** OS version, for example `26.1` or `16`, when discovery reports it. */
|
|
113
|
+
osVersion?: string;
|
|
88
114
|
identifiers: AgentDeviceIdentifiers;
|
|
89
115
|
/**
|
|
90
116
|
* Present when a host-local device claim currently blocks foreign use of
|
|
@@ -379,6 +405,19 @@ type CaptureSnapshotResult = {
|
|
|
379
405
|
* the producer measured no band and the tap guard derived one from the tree.
|
|
380
406
|
*/
|
|
381
407
|
keyboard?: SnapshotKeyboardBandFact;
|
|
408
|
+
/**
|
|
409
|
+
* The box the node rects are measured in, as the producer measured it (#3182). Same coordinate
|
|
410
|
+
* space and orientation as the rects beside it, so a consumer scales and clips against the screen
|
|
411
|
+
* it is being shown instead of inferring it from the largest rect on screen.
|
|
412
|
+
*
|
|
413
|
+
* Which surface it names is the producer's answer, not always the physical panel: the app window
|
|
414
|
+
* for iOS (so iPad Split View and a foldable panel do not inflate it), the screen the bounds were
|
|
415
|
+
* measured on for Android and Apple TV. Absent means the producer measured no box — a desktop
|
|
416
|
+
* capture whose rects are absolute in window space, a backend that reads a tree without reading a
|
|
417
|
+
* screen, or a raw projection nothing validated a box against — and never a zero. This is the full
|
|
418
|
+
* screen size only; content-safe gesture bounds stay with #1821.
|
|
419
|
+
*/
|
|
420
|
+
viewport?: SnapshotViewportSize;
|
|
382
421
|
/**
|
|
383
422
|
* Screenshot captured automatically when the semantic snapshot was sparse.
|
|
384
423
|
* Remote clients receive a materialized local path through the daemon artifact channel.
|
|
@@ -574,6 +613,8 @@ type Lease = {
|
|
|
574
613
|
leaseProvider?: string;
|
|
575
614
|
deviceKey?: string;
|
|
576
615
|
clientId?: string;
|
|
616
|
+
/** Present when the daemon keeps this lease through session `close`; an older daemon omits it. */
|
|
617
|
+
retainOnClose?: true;
|
|
577
618
|
createdAt?: number;
|
|
578
619
|
heartbeatAt?: number;
|
|
579
620
|
expiresAt?: number;
|
|
@@ -589,6 +630,12 @@ type LeaseAllocateOptions = LeaseOptions & {
|
|
|
589
630
|
provider?: string;
|
|
590
631
|
deviceKey?: string;
|
|
591
632
|
clientId?: string;
|
|
633
|
+
/**
|
|
634
|
+
* Keeps the lease through session `close`; it then ends only through `leases.release`, expiry, or
|
|
635
|
+
* daemon shutdown. Asking for it on a lease the same client already holds for the run turns it on
|
|
636
|
+
* for that lease; the returned lease's `retainOnClose` says whether the daemon honored it.
|
|
637
|
+
*/
|
|
638
|
+
retainOnClose?: boolean;
|
|
592
639
|
};
|
|
593
640
|
type LeaseScopedOptions = LeaseOptions & {
|
|
594
641
|
tenant?: string;
|
|
@@ -724,6 +771,12 @@ type ReplayRunOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOption
|
|
|
724
771
|
saveScript?: boolean | string;
|
|
725
772
|
/** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
|
|
726
773
|
force?: boolean;
|
|
774
|
+
/**
|
|
775
|
+
* Activate the headless Android test IME for the sessions this replay opens
|
|
776
|
+
* (default on for emulators; opt-in on real devices). `false` keeps the real
|
|
777
|
+
* keyboard even on emulators.
|
|
778
|
+
*/
|
|
779
|
+
testIme?: boolean;
|
|
727
780
|
};
|
|
728
781
|
type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
729
782
|
paths: string[];
|
|
@@ -742,6 +795,12 @@ type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptio
|
|
|
742
795
|
reportJunit?: string;
|
|
743
796
|
shardAll?: number;
|
|
744
797
|
shardSplit?: number;
|
|
798
|
+
/**
|
|
799
|
+
* Activate the headless Android test IME for the sessions each suite attempt
|
|
800
|
+
* opens (default on for emulators; opt-in on real devices). `false` keeps the
|
|
801
|
+
* real keyboard even on emulators.
|
|
802
|
+
*/
|
|
803
|
+
testIme?: boolean;
|
|
745
804
|
};
|
|
746
805
|
type BatchStep = {
|
|
747
806
|
command: string;
|
|
@@ -844,13 +903,30 @@ type SettingsUpdateOptions = (DeviceCommandBaseOptions & {
|
|
|
844
903
|
setting: 'reset-keychain';
|
|
845
904
|
state: 'clear';
|
|
846
905
|
}) | (DeviceCommandBaseOptions & {
|
|
847
|
-
setting: 'wifi' | 'airplane'
|
|
906
|
+
setting: 'wifi' | 'airplane';
|
|
848
907
|
state: 'on' | 'off';
|
|
849
|
-
}) |
|
|
908
|
+
}) |
|
|
909
|
+
/**
|
|
910
|
+
* On Apple simulators `on`/`off` grants or revokes the app's location permission, so this leg
|
|
911
|
+
* takes the same explicit `app` as `permission` and defaults to the session app. On Android the
|
|
912
|
+
* toggle writes the global `location_mode` and consumes no app, so naming one there is refused
|
|
913
|
+
* rather than dropped; `settingsAppScope` is the declaration.
|
|
914
|
+
*/
|
|
915
|
+
(DeviceCommandBaseOptions & {
|
|
916
|
+
setting: 'location';
|
|
917
|
+
state: 'on' | 'off';
|
|
918
|
+
app?: string;
|
|
919
|
+
}) |
|
|
920
|
+
/**
|
|
921
|
+
* `set` moves the device's own location for every target, so naming an app here is a contradiction
|
|
922
|
+
* the daemon refuses with `setting_app_not_consumed` rather than a value it silently drops.
|
|
923
|
+
*/
|
|
924
|
+
(DeviceCommandBaseOptions & {
|
|
850
925
|
setting: 'location';
|
|
851
926
|
state: 'set';
|
|
852
927
|
latitude: number;
|
|
853
928
|
longitude: number;
|
|
929
|
+
app?: string;
|
|
854
930
|
}) | (DeviceCommandBaseOptions & {
|
|
855
931
|
setting: 'animations';
|
|
856
932
|
state: 'on' | 'off';
|
|
@@ -877,6 +953,13 @@ type SettingsUpdateOptions = (DeviceCommandBaseOptions & {
|
|
|
877
953
|
state: PermissionAction;
|
|
878
954
|
permission: PermissionTarget;
|
|
879
955
|
mode?: PermissionMode;
|
|
956
|
+
/**
|
|
957
|
+
* The app the permission changes, by bundle id or package name. Without it the app bound to
|
|
958
|
+
* the session is used; with it no app has to be running or open, because `simctl privacy` and
|
|
959
|
+
* Android's `pm` need only the id. macOS permissions are host-level TCC grants, so naming an
|
|
960
|
+
* app there is refused rather than dropped.
|
|
961
|
+
*/
|
|
962
|
+
app?: string;
|
|
880
963
|
});
|
|
881
964
|
//#endregion
|
|
882
965
|
//#region packages/contracts/src/alert-contract.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{n as t,r as n}from"./adb.js";const r=`This Android build ships no shell implementation for the clipboard service, so adb cannot read or write the clipboard on it. Verify a copy flow by pasting into a focused field and reading that field back.`;function i(e){return n(e.stderr)?`no-shell-command`:e.exitCode===0?`executed`:t(e.stdout,e.stderr)?`no-shell-command`:`call-failed`}function a(e){return e===`executed`?`supported`:e===`no-shell-command`?`unsupported`:`probe-failed`}function o(e){return a(i(e))}function s(t){return new e(`UNSUPPORTED_OPERATION`,`Android shell clipboard ${t} is not supported on this device.`,{reason:`android_clipboard_shell_command_unavailable`,hint:r})}export{r as ANDROID_CLIPBOARD_SHELL_COMMAND_UNAVAILABLE_HINT,s as androidClipboardShellCommandUnavailableError,o as androidClipboardShellSupportForResult,i as classifyAndroidClipboardShellResponse};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { L as SnapshotQualityVerdict, P as SnapshotNode, R as SnapshotState, T as PublicPlatform, j as ScreenshotOverlayRef, n as DaemonArtifactType } from "./sdk-contracts.js";
|
|
2
|
-
import {
|
|
1
|
+
import { B as SnapshotViewportSize, L as SnapshotQualityVerdict, P as SnapshotNode, R as SnapshotState, T as PublicPlatform, j as ScreenshotOverlayRef, n as DaemonArtifactType } from "./sdk-contracts.js";
|
|
2
|
+
import { v as SettleObservation } from "./sdk-selectors.js";
|
|
3
3
|
//#region packages/contracts/src/back-mode.d.ts
|
|
4
4
|
declare const BACK_MODES: readonly ['in-app', 'system'];
|
|
5
5
|
type BackMode = (typeof BACK_MODES)[number];
|
|
@@ -277,6 +277,11 @@ type BackendSnapshotResult = {
|
|
|
277
277
|
appName?: string;
|
|
278
278
|
appBundleId?: string;
|
|
279
279
|
snapshotDiagnostics?: SnapshotDiagnosticsSummary;
|
|
280
|
+
/**
|
|
281
|
+
* The box the node rects are measured in, as the producer measured it (#3182). Absent means the
|
|
282
|
+
* producer measured no box; see {@link SnapshotViewportSize} for what each producer measures.
|
|
283
|
+
*/
|
|
284
|
+
viewport?: SnapshotViewportSize;
|
|
280
285
|
analysis?: {
|
|
281
286
|
rawNodeCount: number;
|
|
282
287
|
maxDepth: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{A as e}from"./owner-identity.js";import"./file.js";import{a as t,r as n,s as r,t as i}from"./code-signature.js";import a from"node:crypto";import o from"node:fs";import s from"node:os";import c from"node:path";function l(e,a){let o=t(a),s=t(e),c=v(s,o),l=i(o,s),d=u(c,o,l);if(d)return n(d.files);let p;try{p=r(s,o)}catch{return`unknown`}return f(p.files,l)&&_(c,p),n(p.files)}function u(e,t,n){let r=p(e);if(!(!r||!f(r.files,n))){for(let[e,n,i]of r.files){let r=d(c.resolve(t,e));if(!r?.isFile()||r.size!==n||Math.trunc(r.mtimeMs)!==i)return}for(let e of r.absentPaths)if(d(c.resolve(t,e))?.isFile())return;return r}}function d(e){try{return o.statSync(e)}catch{return}}function f(e,t){return e.some(([e])=>e===t)}function p(e){let t=m(e);if(!t)return;let n=[];for(let e of t.files){let t=g(e);if(!t)return;n.push(t)}if(t.absent.every(e=>typeof e==`string`))return{files:n,absentPaths:t.absent}}function m(e){let t=h(e);if(t===void 0)return;let n;try{n=JSON.parse(t)}catch{return}if(!n||typeof n!=`object`)return;let r=n;if(r.version===2&&!(!Array.isArray(r.files)||!Array.isArray(r.absent)))return{files:r.files,absent:r.absent}}function h(e){let t;try{t=o.openSync(e,`r`)}catch{return}try{let e=process.getuid?.();return e!==void 0&&o.fstatSync(t).uid!==e?void 0:o.readFileSync(t,`utf8`)}catch{return}finally{o.closeSync(t)}}function g(e){if(!Array.isArray(e)||e.length!==3)return;let[t,n,r]=e;if(typeof t==`string`&&typeof n==`number`&&typeof r==`number`)return[t,n,r]}function _(t,n){let r={version:2,files:[...n.files],absent:[...n.absentPaths]};try{o.mkdirSync(c.dirname(t),{recursive:!0,mode:448}),e({destination:t,contents:JSON.stringify(r),mode:384})}catch{}}function v(e,t){let n=a.createHash(`sha1`).update(`${t} ${e}`).digest(`hex`),r=`agent-device-code-signature-${process.getuid?.()??`user`}`;return c.join(s.tmpdir(),r,`${n}.json`)}export{l as resolveCachedDaemonCodeSignature};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,s as t}from"./version.js";import n from"node:
|
|
1
|
+
import{r as e,s as t}from"./version.js";import n from"node:crypto";import r from"node:fs";import i from"node:path";const a=/(['"])(\.\.?\/[^'"]*)\1/g,o=/(['"])(@[^'"/\s]+\/[^'"\s]+)\1/g,s=[`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`];function c(){let e=process.argv[1];return e?u(e):`unknown`}function l(n=e()){return t(n)?`checkout`:`installed`}function u(t,n=e()){try{return g(d(t,n).files)}catch{return`unknown`}}function d(e,t){let n=h(t),i=[h(e)],a=new Set,o=[],s=new Set,c={root:n,packages:new Map,absentPaths:s,stamp:e=>{if(a.has(e))return!1;a.add(e);let t=r.statSync(e);if(!t.isFile())return!1;let i=m(n,e);return o.push([i,t.size,Math.trunc(t.mtimeMs)]),!0},follow:e=>{for(let t of e.missedCandidates)s.add(m(n,t));e.filePath&&i.push(e.filePath)}};for(;i.length>0;){let e=i.pop();if(e===void 0||a.has(e)||!c.stamp(e))continue;let t=r.readFileSync(e,`utf8`);for(let n of _(t))c.follow(w(e,n));f(t,c)}return{files:o,absentPaths:[...s]}}function f(e,t){for(let n of v(e)){let{name:e,subpath:r}=y(n),i=p(e,t);if(!i)continue;let a=S(i.manifest,r);a!==void 0&&t.follow(w(i.manifestPath,a))}}function p(e,t){let n=t.packages.get(e);if(n!==void 0)return n;let r=b(t.root,e,t.absentPaths);return t.packages.set(e,r),r&&t.stamp(r.manifestPath),r}function m(e,t){let n=i.resolve(t);return i.relative(i.resolve(e),n)||n}function h(e){try{return r.realpathSync.native(e)}catch{return i.resolve(e)}}function g(e){let t=e.map(([e,t,n])=>`${e}:${t}:${n}`).sort().join(`|`),r=n.createHash(`sha1`).update(t).digest(`hex`);return`graph:${e.length}:${r}`}function _(e){let t=new Set;a.lastIndex=0;let n=null;for(;(n=a.exec(e))!==null;)t.add(n[2]);return[...t]}function v(e){let t=new Set;o.lastIndex=0;let n=null;for(;(n=o.exec(e))!==null;)t.add(n[2]);return[...t]}function y(e){let t=e.split(`/`),n=t.slice(2).join(`/`);return{name:t.slice(0,2).join(`/`),subpath:n?`./${n}`:`.`}}function b(e,t,n){let a=i.join(e,`node_modules`,t,`package.json`);if(!E(a))return n.add(m(e,a)),null;let o=h(a);if(x(e,o))return null;try{return{manifestPath:o,manifest:JSON.parse(r.readFileSync(o,`utf8`))}}catch{return null}}function x(e,t){let n=i.relative(i.join(e,`node_modules`),t);return n!==``&&!n.startsWith(`..`)&&!i.isAbsolute(n)}function S(e,t){if(!e||typeof e!=`object`)return;let n=e.exports;if(!n||typeof n!=`object`)return;let r=n[t],i=typeof r==`string`?r:C(r);return typeof i==`string`&&i.startsWith(`.`)?i:void 0}function C(e){if(!(!e||typeof e!=`object`))return e.default}function w(e,t){let n=i.resolve(i.dirname(e),t),r=[];for(let e of T(n)){if(E(e))return{filePath:e,missedCandidates:r};r.push(e)}return{filePath:null,missedCandidates:r}}function*T(e){yield e;for(let t of s)yield`${e}${t}`;for(let t of s)yield i.join(e,`index${t}`)}function E(e){try{return r.statSync(e).isFile()}catch{return!1}}export{h as a,l as i,u as n,c as o,g as r,d as s,m as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{S as t,T as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={plugins:{text:{summary:`Manage installed provider plugins`,description:`Install, list, update, or remove npm provider plugins in AGENT_DEVICE_HOME (default ~/.agent-device). Changes take effect after restarting the local daemon. Use --json for structured results.`},usageOverride:`plugins list|add <package[@version]>|update <package>|remove <package>`,listUsageOverride:`plugins`,positionalArgs:[`list|add|update|remove`,`package?`],supportedFlags:[]},cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
|
|
2
2
|
|
|
3
3
|
Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
|
|
4
4
|
|
|
@@ -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{J as e,P as t,X as n,Z as r,i}from"./sdk-contracts.js";import{g as a,v as o}from"./sdk-batch-runner.js";import{a as s,n as c,t as l}from"./sdk-device.js";import{C as u,T as d,c as f,f as ee,m as p}from"./sdk-batch.js";import{A as m,D as h,F as te,I as g,M as _,N as v,O as y,R as b,_ as ne,d as re,f as ie,g as ae,h as oe,j as x,k as S,l as se,m as ce,s as le,u as ue,x as de,y as fe,z as pe}from"./registry.js";import{n as me}from"./success-text.js";import{t as he}from"./output-common.js";import{i as ge,n as C,r as _e,t 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{i as k,r as A,t as j}from"./cli-config.js";import{n as M}from"./result-serialization.js";const N=_({field:v(),artifactType:v(),path:v(),localPath:v(),fileName:v()},[`field`]),P={record:{type:`object`,oneOf:[_({recording:y(`started`),outPath:v(),sessionStateDir:v(),recordingBackend:v(),recordingScope:v(),recordOnlySession:h(),activeSessionApp:m(),showTouches:h()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),_({recording:y(`stopped`),outPath:v(),telemetryPath:v(),artifacts:{type:`array`,items:N},recordingBackend:v(),recordingScope:v(),recordOnlySession:h(),activeSessionApp:m(),durationMs:x(),capturedDurationMs:x(),recorder:S(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:S(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:h(),warning:v(),overlayWarning:v(),chunks:{type:`array`,items:m()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[_({trace:y(`started`),outPath:v()},[`trace`,`outPath`]),_({trace:y(`stopped`),outPath:v(),artifacts:{type:`array`,items:N}},[`trace`,`outPath`,`artifacts`])]}},be=_({settled:h(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:x(),captures:x(),quietMs:x(),timeoutMs:x(),refsGeneration:x(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:_({ref:v(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:ne,diff:_({summary:_({additions:x(),removals:x(),unchanged:x()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:_({kind:S([`added`,`removed`]),text:v(),ref:v(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:h(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:_({ref:v(`Plain ref body (e12) minted from the stored settled tree.`),role:v(),label:v()},[`ref`,`role`])},tailTruncated:h(`Present (true) when tail candidates exceeded the response cap.`),hint:v()},[`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:_({direction:S([`up`,`down`,`left`,`right`]),edge:S([`top`,`bottom`]),until:v(`Until scrolls only: the selector the passes stopped on.`),passes:x(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:x(),pixels:x(),durationMs:x(),message:v(),keyboardAvoided:h(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:x(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:S([`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`]),...de,...fe,...ie,...ce,...oe,...re,...ue,...ae,...P,...se,...le}),Ce={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:l},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:b({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(t){return e(t)}function B(e){let t=[`Error (${e.code}): ${e.message}`];if(e.cause){let n=e.cause.code?`${e.cause.code} `:``;t.push(`Cause: ${n}${e.cause.message}`)}e.hint&&t.push(`Hint: ${e.hint}`);for(let n of me(e.details))t.push(`Warning: ${he(n)}`);t.push(...O(r(e.details))),e.supportedOn&&t.push(`Supported on: ${e.supportedOn}`);let n=D(e.details);return n&&t.push(n),t.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)&&k(t,e)&&(i[t]=a);return A(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,r){let i=r?.refsGeneration;typeof i==`number`&&U(e,t,n(r),i)}const V=new Set([`snapshot`,`find`]),Me=new Set(ee.map(e=>e.name).filter(C).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=a(n?.divergence),i=a(r?.screen);if(i?.state!==`available`)return;let o=i.refsGeneration;if(typeof o!=`number`)return;let s=[];He(i.refs,s),U(e,t,s,o)}function He(e,t){if(Array.isArray(e))for(let n of e){let e=a(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=a(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:b({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:b({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},qe=Object.fromEntries(_e().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...g,...Te,...Ke,...qe}}function Je(){return ge().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,te(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(e={}){let n=Ae();return{execute:async(r,i)=>{if(!C(r))throw new t(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=w(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new t(`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(e,l.client);try{let t=await(e.runCommand??Ze)(f,r,d);return n.mergeCommandResult(r,t,l.client.stateDir,u.session),{isError:!1,structuredContent:await ke(r,t),content:[{type:`text`,text:await at({name:r,input:u,result:t,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(e){let n=e.stateDir,r=e.includeCost,i=e.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new t(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new t(`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(e){if(e===void 0)return;let n=i.find(t=>t===e);if(n===void 0)throw new t(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function tt(e){if(e===void 0)return`optimized`;if(e!==`optimized`&&e!==`json`)throw new t(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return e}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`?pe(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(o(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],s=f(t[i]);if(s===void 0||!o(a))return;let c=Y(s,w(s),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=d(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=u(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};
|