agent-device 0.21.22 → 0.21.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.22.apk → agent-device-android-ime-helper-0.21.24.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.24.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.22.manifest.json → agent-device-android-ime-helper-0.21.24.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.24.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.22.manifest.json → agent-device-android-snapshot-helper-0.21.24.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/SnapshotTraversal.swift +12 -6
- package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/RectResponseTests.swift +21 -0
- package/apple/snapshot-bridge/README.md +9 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +56 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +14 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +29 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +34 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +19 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +3 -3
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-browser-provider.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/alert.js +1 -1
- package/dist/src/android-adb.d.ts +3 -2
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/app-backend.js +1 -1
- package/dist/src/app-inventory.d.ts +4 -0
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state-runtime.d.ts +15 -0
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/aws-device-farm-connection.js +1 -0
- package/dist/src/back-mode.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/browserstack-connection.js +1 -0
- package/dist/src/browserstack-device-features.js +1 -0
- package/dist/src/browserstack.js +1 -0
- package/dist/src/cache.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +35 -19
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +3 -4
- package/dist/src/client-companion-tunnel.js +1 -0
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-options.js +3 -3
- package/dist/src/client-types.d.ts +7 -5
- package/dist/src/cloud-artifacts.d.ts +9 -2
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/command-metadata.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-verification.js +1 -0
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/daemon-client-lease-beat.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-client-transport.js +1 -1
- package/dist/src/daemon-http.js +1 -1
- package/dist/src/daemon-policy-file.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.d.ts +2 -15
- package/dist/src/device-readiness-runtime.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +3 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/device3.js +1 -1
- package/dist/src/dispatch-resolve.js +3 -3
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/format.js +2 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan-types.d.ts +2 -5
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/human-control.js +1 -1
- package/dist/src/ime-rebind.js +1 -0
- package/dist/src/ime-settings-record.js +1 -0
- package/dist/src/ime-state.js +1 -0
- package/dist/src/index.d.ts +3 -3
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/instance-client.js +1 -1
- 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.js +5 -5
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/ios-client.js +4 -4
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- 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-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +4 -555
- package/dist/src/load.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/log-stream.js +33 -0
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/manifest.js +1 -0
- package/dist/src/mechanics.js +16 -16
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/node-http.js +1 -0
- package/dist/src/observation.js +1 -2
- package/dist/src/overlay.js +3 -3
- package/dist/src/owner-identity.js +3 -3
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf-target.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plugin.js +1 -0
- package/dist/src/plugins/webdriver.d.ts +111 -0
- package/dist/src/plugins/webdriver.js +1 -0
- package/dist/src/plugins.d.ts +2 -1
- package/dist/src/plugins2.js +1 -1
- package/dist/src/process-exit.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/provider-credential-fingerprint.js +1 -1
- package/dist/src/provider-device-admission.js +1 -1
- package/dist/src/provider-device-runtime.d.ts +556 -0
- package/dist/src/provider-policy.js +1 -0
- package/dist/src/provider-profile-fields.js +1 -1
- package/dist/src/provider-webdriver.js +1 -2
- package/dist/src/providers.js +1 -1
- package/dist/src/proxy.js +2 -2
- package/dist/src/react-devtools.js +2 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording.js +1 -1
- package/dist/src/registry.js +24 -24
- package/dist/src/remote-bridge.js +1 -0
- package/dist/src/remote-config-core.js +1 -0
- package/dist/src/remote-config.js +1 -1
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/remote-connection-state.js +1 -0
- package/dist/src/replay.js +2 -2
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.js +1 -1
- package/dist/src/retry2.js +1 -0
- package/dist/src/runner-artifact-manifest.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -3
- package/dist/src/runner-cache-retention.js +1 -0
- package/dist/src/runner-cache-trim.js +1 -0
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-device-set.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-error-classification.js +1 -1
- package/dist/src/runner-exchange.js +1 -1
- package/dist/src/runner-lease.js +1 -0
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-session-types.js +1 -1
- package/dist/src/runner-start-budget.js +1 -1
- package/dist/src/runner-toolchain-probe.js +2 -0
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime-deployment.js +1 -0
- package/dist/src/runtime.js +1 -1
- package/dist/src/runtime10.js +1 -2
- package/dist/src/runtime11.js +2 -0
- package/dist/src/runtime2.js +2 -5
- package/dist/src/runtime3.js +5 -1
- package/dist/src/runtime4.js +1 -5
- package/dist/src/runtime5.js +5 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -1
- package/dist/src/screenshot3.js +2 -2
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +25 -33
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-remote-config.d.ts +4 -0
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-pipeline-policy.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator-state.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -1
- package/dist/src/snapshot-desktop-projection.js +1 -1
- package/dist/src/snapshot-private-evidence.js +1 -0
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +1 -1
- package/dist/src/src4.js +1 -1
- package/dist/src/src5.js +1 -1
- package/dist/src/src6.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +20 -20
- package/dist/src/store.js +1 -1
- package/dist/src/target-evidence.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime2.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/video.js +1 -1
- package/package.json +24 -16
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.22.apk.sha256 +0 -1
- 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 +0 -1
- package/dist/src/capabilities.js +0 -1
- package/dist/src/compatibility-policy.js +0 -1
- package/dist/src/daemon-artifacts.js +0 -1
- package/dist/src/device-claim-rule.js +0 -1
- package/dist/src/human-control-contract.js +0 -1
- package/dist/src/prepare-kind.js +0 -1
- package/dist/src/provider-device-runtimes.js +0 -1
- package/dist/src/screen-recording-admission-ledger.js +0 -1
- package/dist/src/screenshot-runtime.js +0 -1
- package/dist/src/session-routing.js +0 -1
- package/dist/src/session-runtime-admission.js +0 -1
- package/dist/src/session-stream.js +0 -27
- package/dist/src/timeouts.js +0 -1
- package/dist/src/touch-reference-frame.js +0 -1
- package/dist/src/vars.js +0 -2
- package/dist/src/viewport.js +0 -1
package/dist/src/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{F as e,P as t}from"./sdk-contracts.js";import{a as n}from"./version.js";import{t as r}from"./daemon-resolution.js";import{r as i}from"./remote-config2.js";import{s as a}from"./device-shell.js";import{t as o}from"./device2.js";import{n as s}from"./src.js";import{a as c,i as l,n as u,r as d,t as f}from"./provider-webdriver.js";import{n as p,o as m}from"./providers.js";import{i as h,n as g,t as ee}from"./provider-limrun-credentials.js";import{n as _}from"./provider-profile-fields.js";import{C as te,E as ne,O as re,S as ie,T as ae,_ as oe,a as se,b as ce,c as v,d as le,f as y,g as ue,i as de,l as fe,m as b,n as pe,o as x,p as S,s as C,t as me,u as w,v as he,w as T,x as ge,y as _e}from"./connection-runtime.js";import{o as ve,r as ye}from"./auth-session.js";import{t as E}from"./shared.js";import D from"node:crypto";import O from"node:fs";import k from"node:path";const be=new Set([`daemonAuthToken`,`metroBearerToken`]);function xe(e){let t=M(j(e.profile)),n=k.join(e.stateDir,`remote-connections`,`generated`);O.mkdirSync(n,{recursive:!0,mode:448});let r=k.join(n,`${we(e.provider)}-${Ce(t)}.json`);O.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{O.chmodSync(r,384)}catch{}return r}function Se(n){try{return i(n)}catch(r){let i=e(r);throw new t(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function A(e){let t=Se({configPath:xe({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Te(e.provider)});return{flags:{...b(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function j(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!be.has(e)))}function Ce(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function M(e){return Array.isArray(e)?e.map(M):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,M(t)])):e}function we(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Te(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function N(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function Ee(e){let t=await ye({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await De({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=N(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return A({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function De(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return Oe(await ve(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function Oe(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return ke(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function ke(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function P(e){let t=je(e.provider);_(e.flags,u[e.provider]);let n=t(e),r=N(e.provider,e.stateDir,e.flags.session,n.device),i={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${r}`,leaseProvider:e.provider,clientId:r,leaseBackend:e.flags.leaseBackend??x(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...n,...w(e.flags)};return A({stateDir:e.stateDir,provider:e.provider,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,...n.providerApp?{extraFlags:{providerApp:n.providerApp}}:{}})}const Ae=[{provider:p.browserStack,buildProfileFields:Me},{provider:p.awsDeviceFarm,buildProfileFields:Pe}];function je(e){let n=Ae.find(t=>t.provider===e)?.buildProfileFields;if(n)return n;throw new t(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Me(e){return d(e.env??{},`connect browserstack`),{platform:F(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:I(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:I(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Ne(I(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...fe(e.flags)}}function Ne(e,n){if(/^https?:\/\//i.test(e))return e;let r=c(e);if(r!==void 0)return r;let i=k.resolve(n,e);try{if(O.statSync(i).isFile())return i}catch{}throw new t(`INVALID_ARGS`,`BrowserStack app file not found: ${i}`)}function Pe(e){let{env:t,flags:n}=e,r=F(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=L(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:L(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:R(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:R(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??l(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function F(e,n){if(e===`android`||e===`ios`)return e;throw new t(`INVALID_ARGS`,n)}function I(e,n){if(e)return e;throw new t(`INVALID_ARGS`,n)}function L(e,t,n,r){return I(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Fe(e){let n=e.env??process.env,r=Ie({flags:e.flags}),i=h(n),a=g(r.leaseBackend)??`android`;if(!i?.apiKey&&!i?.instances?.[a])throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY, or ${ee(a).join(`, `)} for an existing instance.`,{hint:`Set the credentials in the environment before running agent-device connect limrun.`});return A({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Ie(e){let t=e.flags,n=Le(t);return{stateDir:r(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...w(t)}}function Le(e){if(_(e,o),e.platform!==`android`&&e.platform!==`ios`)throw new t(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(e.device!==void 0)throw new t(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=x(e),r=e.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new t(`INVALID_ARGS`,`connect limrun --platform ${e.platform} requires --lease-backend ${r}.`);return r}function Re(e){let n=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new t(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=N(e.stateDir,n,e.flags.session),i={daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??x(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...w(e.flags)};return A({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const z={cloud:{resolve:Ee,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Re,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>P({provider:`browserstack`,...e}),verify:Ve},"aws-device-farm":{resolve:e=>P({provider:`aws-device-farm`,...e}),verify:He},limrun:{resolve:Fe,verify:Ue}};async function ze(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=i({configPath:e.flags.remoteConfig,cwd:t,env:n}),a=r.profile.leaseProvider;return{flags:{...b(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...S(a)?{provider:a}:{}}}let r=e.provider??(We(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Be(e){return e.provider?await z[e.provider].verify({flags:e.flags,env:process.env}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function Ve(e){let{flags:t,env:n}=e,r=m(n);return await f.verifyConnection({provider:`browserstack`,username:B(r.username,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(r.accessKey,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:V(t.platform,`BrowserStack`),deviceName:B(t.device,`BrowserStack profile missed device.`),osVersion:B(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:B(t.providerApp,`BrowserStack profile missed app.`)})}async function He(e){let{flags:t}=e;return await f.verifyConnection({provider:`aws-device-farm`,platform:V(t.platform,`AWS Device Farm`),projectArn:B(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:B(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function Ue(e){return await s({...h(e.env),clientVersion:n(),platform:V(e.flags.platform,`Limrun`)})}function We(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function B(e,n){if(e!==void 0)return e;throw new t(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(e,n){if(e===`android`||e===`ios`)return e;throw new t(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function Ge(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??Ke();return{session:i,previous:n.session?T({stateDir:t,session:i}):null,remoteConfigHash:ce(r),daemon:ue(n)}}function Ke(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=y(e.leaseProvider),r=n.leaseKind;if(r===`proxy`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`};if(n.supportsDeferredAppSelection)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.`};if(r===`direct-device-provider`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`};let i=e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``;return{status:`deferred`,nextSteps:K(e,[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`]),message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+i}}function qe(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Je(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
-
`)}let a=G(n),o=[`${a===`verified`?`Connected`:`Configured`} successfully with ${n.service}.`,`${a===`verified`?`Verified`:`Status`}: ${n.verificationMessage}`];return n.project&&o.push(`Project: ${n.project.name??n.project.reference} — verified`),n.device&&o.push(
|
|
3
|
-
`)}function U(e){let{state:t,runtimePreparation:n,readiness:r,previousLeaseNotice:i}=e,a=H(t,r);return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:
|
|
4
|
-
`)),!0};function
|
|
5
|
-
`)}function
|
|
1
|
+
import{F as e,P as t,d as n}from"./sdk-contracts.js";import{a as r}from"./version.js";import{t as i}from"./daemon-resolution.js";import{r as a}from"./remote-config-core.js";import"./remote-config2.js";import{s as o}from"./device-shell.js";import{t as s}from"./device2.js";import{n as c}from"./src.js";import{n as l}from"./provider-webdriver.js";import{i as u,n as d,t as f}from"./provider-limrun-credentials.js";import{n as p,r as m}from"./provider-profile-fields.js";import{a as h,c as ee,d as te,f as ne,g,h as re,i as ie,l as ae,n as oe,o as se,r as ce,s as le,u as _}from"./remote-connection-state.js";import{o as v,r as y}from"./auth-session.js";import{t as b}from"./shared.js";import{n as x,r as S,t as ue}from"./provider-policy.js";import{connectionPlatformConflict as de,hasDeferredMetroConfig as fe,releasePreviousLease as pe,releaseRemoteConnectionLease as me,resolveRequestedLeaseBackend as C,stopMetroCleanup as w,stopReactDevtoolsCleanup as T,t as E}from"./connection-runtime.js";import{n as he}from"./load.js";import D from"node:crypto";import O from"node:fs";import k from"node:path";const ge=new Set([`daemonAuthToken`,`metroBearerToken`]);function A(e){let t=F(N(e.profile)),n=k.join(e.stateDir,`remote-connections`,`generated`);O.mkdirSync(n,{recursive:!0,mode:448});let r=k.join(n,`${I(e.provider)}-${P(t)}.json`);O.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{O.chmodSync(r,384)}catch{}return r}function j(n){try{return a(n)}catch(r){let i=e(r);throw new t(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function M(e){let t=j({configPath:A({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:L(e.provider)});return{flags:{...g(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function N(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!ge.has(e)))}function P(e){return D.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function F(e){return Array.isArray(e)?e.map(F):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,F(t)])):e}function I(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function L(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function R(...e){return D.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function _e(e){let t=await y({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await ve({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=R(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return M({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function ve(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return ye(await v(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function ye(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return be(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function be(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function xe(e){let n=e.env??process.env,r=Se({flags:e.flags}),i=u(n),a=d(r.leaseBackend)??`android`;if(!i?.apiKey&&!i?.instances?.[a])throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY, or ${f(a).join(`, `)} for an existing instance.`,{hint:`Set the credentials in the environment before running agent-device connect limrun.`});return M({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Se(e){let t=e.flags,n=Ce(t);return{stateDir:i(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...E(t)}}function Ce(e){if(p(e,s),e.platform!==`android`&&e.platform!==`ios`)throw new t(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(e.device!==void 0)throw new t(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=C(e),r=e.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new t(`INVALID_ARGS`,`connect limrun --platform ${e.platform} requires --lease-backend ${r}.`);return r}function we(e){let n=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new t(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=R(e.stateDir,n,e.flags.session),i={daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??C(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...E(e.flags)};return M({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const z={cloud:{resolve:_e,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:we,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},limrun:{resolve:xe,verify:Oe}};function B(e){return Object.hasOwn(z,e)?z[e]:void 0}async function V(e,t,n){let r=l(e,t);return r?await n(r):await he(e,t,n)}async function Te(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=a({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...g(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...S(i,n)?{provider:i}:{}}}let r=e.provider??(ke(e.flags)?`proxy`:`cloud`),i={flags:e.flags,stateDir:e.stateDir,cwd:t,env:n},o=B(r);return{...o?await o.resolve(i):await V(r,n,async e=>await Ee(r,e,i)),provider:r}}async function Ee(e,r,i){let a=await r.resolve(i);if(a.profile.leaseProvider!==e)throw new t(`INVALID_ARGS`,`Provider connection profile must select its declared provider: ${e}`);let o=R(e,i.stateDir,i.flags.session,a.profile.device);return M({...i,...a,provider:e,profile:{tenant:i.flags.tenant??e,sessionIsolation:i.flags.sessionIsolation??`tenant`,runId:i.flags.runId??`${e}-${o}`,clientId:o,target:i.flags.target??`mobile`,session:i.flags.session,stateDir:i.stateDir,leaseBackend:i.flags.leaseBackend??n(a.profile.platform),...E(i.flags),...a.profile}})}async function De(e){if(!e.provider)return{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`};let t={flags:e.flags,env:process.env},n=B(e.provider);return n?await n.verify(t):await V(e.provider,t.env,async e=>await e.verify(t))}async function Oe(e){return await c({...u(e.env),clientVersion:r(),platform:m(e.flags.platform,`Limrun`)})}function ke(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function Ae(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??je();return{session:i,previous:n.session?_({stateDir:t,session:i}):null,remoteConfigHash:se(r),daemon:oe(n)}}function je(){return`adc-${D.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=x(e.leaseProvider),r=n.leaseKind;if(r===`proxy`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`};if(n.supportsDeferredAppSelection)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.`};if(r===`direct-device-provider`)return{status:`deferred`,nextSteps:W(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`};let i=e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``;return{status:`deferred`,nextSteps:K(e,[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`]),message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+i}}function Me(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Ne(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=H(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
2
|
+
`)}let a=G(n),o=[`${a===`verified`?`Connected`:`Configured`} successfully with ${n.service}.`,`${a===`verified`?`Verified`:`Status`}: ${n.verificationMessage}`];return n.project&&o.push(`Project: ${n.project.name??n.project.reference} — verified`),n.device&&o.push(Le(n.device)),n.app&&o.push(Re(t,n.app)),o.push(n.preparationMessage),o.push(`Next:`),o.push(...n.nextSteps.map(e=>` ${e}`)),o.push(...n.notes??[]),r&&o.push(r.message),i&&o.push(i.message),o.join(`
|
|
3
|
+
`)}function U(e){let{state:t,runtimePreparation:n,readiness:r,previousLeaseNotice:i}=e,a=H(t,r);return{connected:!0,session:t.session,tenant:t.tenant,runId:t.runId,leaseAllocated:!!t.leaseId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,platform:t.platform,target:t.target,remoteConfig:t.remoteConfigPath,remoteConfigHash:t.remoteConfigHash,daemonBaseUrlFingerprint:h(t.daemon?.baseUrl),liveSession:Pe(t),...Fe(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...Ie({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function Pe(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Fe(e,t){return e?{verification:{status:G(e),service:e.service,message:e.verificationMessage,...e.project?{project:e.project}:{}},...e.device?{device:e.device}:{},...e.app?{app:e.app}:{},nextSteps:e.nextSteps??t?.nextSteps??[],...e.notes?{notes:e.notes}:{}}:{}}function Ie(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function Le(e){let t=`osVersion`in e?e.osVersion:void 0,n=[e.platform,t].filter(Boolean).join(` `),r=n?` (${n})`:``;return e.status===`deferred`?`Device: ${e.name??`Provider-selected device`} — allocated on first device command`:`Device: ${e.name??e.reference??`Configured device`}${r} — verified`}function Re(e,t){return t.status===`missing`?`App: ${qe(e)} — ${t.message??`Install or attach an app before open.`}`:`App: ${t.name??t.reference??`configured app`} — ${t.status===`verified`?`verified`:t.message??`configured`}`}function W(e,t){let n=ze(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function ze(e,t){let n=x(e.leaseProvider).leaseKind;if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${J(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:Ke()};if(x(t?.provider).supportsDeferredAppSelection)return{nextSteps:[`agent-device apps`,`agent-device open <uploaded-asset-name>`]};let r=t?.app?.status===`missing`;return{nextSteps:Be(t)?Ge(e):[...He(t),...We(e).nextSteps],...Ve(t)?{notes:Ue(e,!r)}:{}}}function Be(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function Ve(e){return x(e?.provider).supportsArtifacts}function He(e){return e?.app?.status!==`missing`||!e.project?.reference||!e.device?.reference?[]:[`agent-device connect aws-device-farm --platform ${e.device.platform} --aws-project-arn ${e.project.reference} --aws-device-arn ${e.device.reference} --aws-app-arn <arn> --force`]}function Ue(e,t){return[...t?[`Use the installed package or bundle identifier in open, not the app artifact name.`]:[],`After close, run ${q(e,`agent-device artifacts --json`)} for provider video and logs.`]}function We(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function Ge(e){let t=J(e.platform);return[`agent-device install ${t} <app-path-or-url>`,`agent-device open ${t} --relaunch`]}function G(e){return`status`in e?e.status:`verified`}function Ke(){return[`agent-device open <package-or-bundle-id> --relaunch`,`agent-device snapshot -i`,`agent-device close`,`agent-device artifacts --json`]}function K(e,t){return t.map(t=>q(e,t))}function q(e,t){return`${t} --session ${o(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function qe(e){let t=x(e.leaseProvider);return t.requiresAppAttachment?`not attached`:t.supportsDeferredAppSelection?`not installed yet`:`not available`}const Je=async({positionals:e,flags:t,client:n})=>{let r=i(t.stateDir).baseDir,a=ut(e);Ye(a,t);let o=await Te({provider:a,flags:t,stateDir:r}),s=o.flags,c=it(o.remoteConfigPath),l=Xe(s,c),u=Ae({stateDir:r,flags:s,remoteConfigPath:o.remoteConfigPath});Ze(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:C(s),connection:c,daemon:u.daemon});let d=await De(o),f=Qe({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});re({stateDir:r,state:f});let p=await rt(n,r,s,u.previous,f),m=gt(s,f),h=Me(f,d);return await b(s,U({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p}),()=>Ne({state:f,runtimePreparation:m,readiness:h,previousLeaseNotice:p})),!0};function Ye(e,n){if(!(!e||!n.remoteConfig))throw new t(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function Xe(e,n){if(!e.tenant)throw new t(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&x(n?.leaseProvider).requiresRemoteDaemon)throw new t(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:e.tenant,runId:e.runId}}function Ze(e,n){if(!(!e||dt(e,n))&&!n.flags.force)throw new t(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:n.session,remoteConfig:e.remoteConfigPath})}function Qe(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=nt(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=$e(t,o,r),l=tt(t,o,s,c,i.session);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function $e(e,t,n){let r=le(n??{},t??{}),i=t?.leaseBackend??C(e);return i===`macos-app`?et(e,t,r):{leaseId:t?.leaseId,leaseBackend:i,...r,deviceKey:t?.deviceKey??r.deviceKey}}function et(e,t,n){return{leaseId:e.leaseId??t?.leaseId,leaseBackend:`macos-app`,...n}}function tt(e,t,n,r,i){let a=ee({leaseBackend:r.leaseBackend,recordedPlatform:t?.platform,requestedPlatform:e.platform});if(!a.ok)throw de({session:i,leaseBackend:r.leaseBackend,boundPlatform:a.boundPlatform,requestedPlatform:a.requestedPlatform,detail:t?`bound-connection`:`requested-backend`});return{platform:a.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function nt(e,t){return!!(t&&!e.force)}async function rt(e,t,n,r,i){if(!(!r||!n.force)&&(await w(r.metro),await T({stateDir:t,state:r}),!(r.leaseId&&r.leaseId===i.leaseId)))return await pe(e,r,{nextDaemonBaseUrl:i.daemon?.baseUrl,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function it(e){let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return ce(t)}const at=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=X(e);if(!i)return await Z(e,n),!0;let a=i.session,o;if(i.leaseId||i.runtime||i.metro)try{o=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await w(i.metro),await T({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await me(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return ne({stateDir:r,session:a}),await b(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>ot(a,o)),!0},Y=async({positionals:e,flags:n})=>{if(e[0]!==`status`)throw new t(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=X(n);if(!i)return await Z(n,r),!0;let a=H(i),o=_t(i);return await b(n,U({state:i,runtimePreparation:o}),()=>[`Configured remote session "${i.session}".`,`tenant=${i.tenant} runId=${i.runId} leaseId=${i.leaseId??`pending`} backend=${i.leaseBackend??`pending`}`,`remoteConfig=${i.remoteConfigPath}`,i.runtime?`metro=prepared`:`metro=not-prepared`,a?.message,o?.message].filter(e=>!!e).join(`
|
|
4
|
+
`)),!0};function ot(e,t){return[`Disconnected remote session "${e}".`,...st(t),...lt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
+
`)}function st(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=ct(e);return t?[t]:[]})}function ct(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.message==`string`&&t.message.length!==0)return`Provider release warning${typeof t.code==`string`&&t.code.length>0?` (${t.code})`:``}: ${t.message}`}function lt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function ut(e){let n=e[0];if(n!==void 0){if(e.length>1)throw new t(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(S(n))return n;throw new t(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${ue()}.`)}}function X(e){let t=e.session??`default`,n=i(e.stateDir).baseDir;return{session:t,stateDir:n,state:_({stateDir:n,session:t})??(e.session?null:ae({stateDir:n}))}}async function Z(e,t){await b(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function dt(e,t){return ft(e,t)&&pt(e,t)&&ht(e.daemon,t.daemon)}function ft(e,t){return[[e.remoteConfigPath,t.remoteConfigPath],[e.remoteConfigHash,t.remoteConfigHash],[e.session,t.session],[e.tenant,t.flags.tenant],[e.runId,t.flags.runId]].every(([e,t])=>e===t)}function pt(e,t){return ie(e,t.flags.platform)?[[e.leaseBackend,t.desiredLeaseBackend],[e.target,t.flags.target]].every(([e,t])=>t===void 0||e===t)&&mt(e,t.flags.leaseId)&&te(e,t.connection):!1}function mt(e,t){return e.leaseBackend!==`macos-app`||t===void 0||t===e.leaseId}function ht(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function gt(e,t){if(!t.runtime&&!(!fe(e)&&!$(t.remoteConfigPath)))return Q(t)}function _t(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=q(e,`agent-device metro prepare --remote-config ${o(e.remoteConfigPath)}`);return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function $(e){try{let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}export{Je as connectCommand,Y as connectionCommand,at as disconnectCommand};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { U as centerOfRect, Z as defaultHintForCode, a as DaemonRequest, d as JsonRpcRequestEnvelope, et as normalizeError, f as LeaseBackend, o as DaemonResponse, q as DaemonError, r as DaemonInstallSource, s as DaemonResponseData, u as JsonRpcId, v as SessionRuntimeHints } from "./sdk-contracts.js";
|
|
2
2
|
export { type DaemonError, type DaemonInstallSource, type DaemonRequest, type DaemonResponse, type DaemonResponseData, type JsonRpcId, type JsonRpcRequestEnvelope, type LeaseBackend, type SessionRuntimeHints, centerOfRect, defaultHintForCode, normalizeError };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{P as e}from"./sdk-contracts.js";import{n as t,r as n}from"./diagnostics.js";import"./diagnostics2.js";import{o as r,p as i,r as a,t as o}from"./lease-scope.js";import{T as s,
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{n as t,r as n}from"./diagnostics.js";import"./diagnostics2.js";import{o as r,p as i,r as a,t as o}from"./lease-scope.js";import{T as s,sn as c}from"./sdk-batch.js";import{t as l}from"./catalog.js";import{a as u,s as d}from"./daemon-client-transport.js";const f=new Set([`LEASE_SCOPE_REQUIRED`,`LEASE_SCOPE_MISMATCH`]);function p(t){return a(t)||t instanceof e&&(f.has(t.details?.reason)||t.code===`INVALID_ARGS`)}async function m(e){let{heartbeat:t,callerSignal:r}=e;if(!t)return await e.task(new AbortController().signal);let i=new AbortController,a=new AbortController,s=o,c=h(s),l,u=!1,d=()=>{u=!0,l&&clearTimeout(l),a.abort()},f,m,v=new Promise((e,t)=>{m=t});r&&r.addEventListener(`abort`,d,{once:!0});let y=()=>{let e=e=>{u||(l&&clearTimeout(l),l=setTimeout(y,e))},r=e=>{if(f=e,u){n({level:`warn`,phase:`lease_lost_after_phase`,data:{message:e instanceof Error?e.message:String(e)}});return}i.abort(),m?.(e)},o=e=>{u||n({level:`warn`,phase:`lease_heartbeat_failed`,data:{message:e instanceof Error?e.message:String(e)}})};e(c),(async()=>{let n=s;try{let r=g(await t(n,a.signal));if(r===void 0||r===s)return;let i=h(r);s=r,c=i,e(i)}catch(e){if(p(e)){r(e);return}o(e)}})().catch(()=>void 0)};l=setTimeout(y,0),v.catch(()=>void 0);let b=await _((async()=>await Promise.race([e.task(i.signal),v]))());if(d(),r&&r.removeEventListener(`abort`,d),f!==void 0)throw f;if(!b.ok)throw b.error;return b.value}function h(e){return Math.max(1e3,Math.floor(e/3))}function g(e){let t=e?.data?.lease,n=t?.expiresAt,r=t?.heartbeatAt;if(typeof n==`number`&&typeof r==`number`)return n>r?n-r:void 0}async function _(e){try{return{ok:!0,value:await e}}catch(e){return{ok:!1,error:e}}}function v(e,t){return{command:l.leaseHeartbeat,positionals:[],session:t.session,token:t.token,meta:{...i(e),sessionIsolation:t.sessionIsolation,requestId:t.requestId}}}function y(e,n,i){if(!d(e))return;let a=r(i);if(!a.leaseId)return;let o=c(s(l.leaseHeartbeat),{positionals:[]});return async(r,s)=>await u(e,v(a,{session:i.session,sessionIsolation:i.meta?.sessionIsolation,requestId:t(),token:e.token}),n.transportPreference,n.paths,o===void 0?r:Math.min(o,r),{signal:s})}export{y as buildUploadLeaseHeartbeat,m as runProtectedLeaseWork};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{J as e,P as t}from"./sdk-contracts.js";import{r as n}from"./diagnostics.js";import"./diagnostics2.js";import{n as r}from"./catalog.js";import{m as i}from"./owner-identity.js";import{t as a}from"./timeouts.js";import{r as o}from"./file.js";import"./command.js";import{c as s,i as c,l,n as u,o as d,s as f,t as p}from"./daemon-client-transport.js";import"./process.js";import{a as m,i as ee,o as te,r as ne}from"./version.js";import{t as re}from"./ttl-memo.js";import{n as ie,r as h,t as g}from"./daemon-resolution.js";import"./retry.js";import{s as _}from"./device-shell.js";import{i as v}from"./replay-divergence.js";import{n as y}from"./daemon-registration.js";import{a as b,i as ae,n as oe,o as x,t as S}from"./daemon-registration-owner.js";import{i as se,n as ce}from"./code-signature.js";import C from"node:fs";import w from"node:path";import T from"node:net";function le(e,t,n){let r=e.data??{},i=typeof r.session==`string`?r.session:void 0,a=[...n?[`--daemon-base-url ${_(ue(n))}`]:[],...t?[`--state-dir ${_(t)}`]:[],...i?[`--session ${_(i)}`]:[]];if(a.length===0)return e;let o=`This session's daemon was kept alive because its script left the session active; pass ${a.join(` `)} on your next command to reach it.`+(n?` If authentication is required, provide or configure --daemon-auth-token.`:``),s=typeof r.message==`string`?r.message:void 0;return{...e,data:{...r,hint:o,message:s?`${s} ${o}`:o}}}function ue(e){let t=new URL(e);return t.username=``,t.password=``,t.search=``,t.hash=``,t.toString().replace(/\/+$/,``)}const E=re();function D(){let e=E.get(`local`);if(e)return e;let n=ne(),r=[w.join(n,`dist`,`src`,`internal`,`daemon.js`),w.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>C.existsSync(e))??i,o=w.join(n,te),s=r.some(e=>C.existsSync(e)),c=C.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return E.set(`local`,l),l}async function O(){let e=D(),t=se(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:ce(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function k(e,t){let n=m();if(e.version!==n)return e.version&&ee(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=A(await O(),e);return r?{kind:`replace`,reason:r}:await t.onClientTransport()?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function A(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:j(e,t):t.codeOrigin===`installed`?j(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function j(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const M=15e3,N=new T.BlockList;N.addSubnet(`127.0.0.0`,8,`ipv4`),N.addAddress(`::1`,`ipv6`),N.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function P(e,t){let n=F(e),r=I(e,t),i=L(e,r.remoteBaseUrl),a=R(e,n,r.rawBaseUrl)?oe():void 0;return{paths:a?.paths??g(n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function F(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function I(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Ae(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return je(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function L(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=h(r);if(n&&i===`socket`)throw new t(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:ie(a)}}function R(e,t,n){return Z(e.command)&&!t&&!n}async function z(e){if(e.remoteBaseUrl)return await V(e);let t=await B(e);return await pe(t.info,e.paths.baseDir),t}async function B(e){let t=await H(e);return t?{info:t,startedByClient:!1}:await ge(e)}async function V(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl},r=await p(n);if(r.reachable)return n.remoteInstanceId=r.instanceId,n.remoteUpstreamInstanceId=r.upstream?.instanceId,{info:n,startedByClient:!1};throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function H(e,t={}){let{deadline:n}=t,r=o(e.paths.lockPath);if(r.state===`unproven`)throw W(e,r);let i=s(e.paths.infoPath);if(!i||!de(r,i)||t.waitForLiveStartup&&await U(i,n))return null;let a=await k(i,{onClientTransport:()=>G(i,e.transportPreference,n),onAnyAdvertisedTransport:()=>G(i,`auto`,n)});if(a.kind===`reuse`)return i;if(a.kind===`refuseNewer`)throw me(i,a,e.paths.baseDir);return J(n)<5e3?null:(he(i,a.reason,e.paths.baseDir),await fe(i,e.paths),null)}async function U(e,t){return i(e.pid)&&!await u(e,`auto`,J(t))}function de(e,t){return e.state===`absent`||y(e,{pid:t.pid,startTime:t.processStartTime??null})}function W(e,n){return new t(`COMMAND_FAILED`,`Daemon registration ownership could not be verified.`,{reason:`daemon_registration_unproven`,inspection:n,stateDir:e.paths.baseDir,hint:l(d(e.paths),e.paths)})}async function fe(e,n){let r=await x({paths:n,observed:{pid:e.pid,startTime:e.processStartTime??null},mode:`graceful`});if(r.status===`retained`)throw new t(`COMMAND_FAILED`,`Daemon replacement could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:r,hint:r.error?.hint??l(d(n),n)})}async function G(e,t,r){if(await K(e,t,r))return!0;for(let o=1;o<=3;o+=1){if(!i(e.pid)||r!==void 0&&Date.now()>=r)return!1;if(await a(Math.min(200,J(r))),await K(e,t,r))return n({level:`warn`,phase:`daemon_probe_recovered`,data:{pid:e.pid,retry:o}}),!0}return!1}async function pe(e,n){if(!process.env.AGENT_DEVICE_DAEMON_POLICY?.trim())return;let{loadDaemonPolicy:r}=await import(`./daemon-policy-file.js`).then(e=>e.t),i=r(process.env)?.digest;if(i!==e.policyDigest)throw new t(`COMMAND_FAILED`,`The running daemon does not enforce the daemon policy named by AGENT_DEVICE_DAEMON_POLICY.`,{reason:`DAEMON_POLICY_MISMATCH`,expectedPolicyDigest:i,daemonPolicyDigest:e.policyDigest??null,hint:`Stop the running daemon (agent-device daemon stop --state-dir ${_(n)}), then retry so a daemon starts with this policy.`})}async function K(e,t,n){try{return await u(e,t,J(n))}catch(e){if(c(e))return!1;throw e}}function me(e,n,r){let{daemonVersion:i,clientVersion:a}=n;return new t(`COMMAND_FAILED`,`Daemon (pid ${e.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:e.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${_(r)}`})}function he(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function ge(e){let n=Date.now()+M,r=[],i,o=0;for(;o<2&&Date.now()<n;){o+=1;let t=await _e(e,n);if(`daemon`in t)return t.daemon;if(i=t,t.cleanup&&r.push(t.cleanup),!t.retry)break;await a(Math.min(150,Math.max(0,n-Date.now())))}let{startError:s,startupError:c,daemonProcess:u}=i??{},f=d(e.paths),p=ke(e.paths.logPath);throw new t(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:M,startupAttempts:o,cleanupResults:r,startError:s,startupError:c,daemonProcess:u,...p?{daemonLogTail:p}:{},metadataState:f,hint:l(f,e.paths)})}async function _e(t,n){let r;try{r=$(t)}catch(e){return await ve(t,e)}let i=await Ce(n,t,r);if(i.kind===`ready`)return{daemon:i.daemon};if(i.kind===`retry`)return{retry:!0};if(i.kind===`unproven`){let t=e(i.error);return{retry:!1,startError:t.message,startupError:t,daemonProcess:{pid:r.pid}}}let{cleanup:a,joined:s}=await q(t,r,n),c=Y(o(t.paths.lockPath));return{cleanup:a,retry:s&&i.kind===`early_exit`&&c,startError:i.kind===`early_exit`?Oe(i.exit):void 0,daemonProcess:i.kind===`early_exit`?i.exit:{pid:r.pid}}}async function ve(t,n){let r=t.ownedStateDir?await x({paths:t.paths,observed:null,mode:`graceful`,ownedStateDir:t.ownedStateDir,lockTimeoutMs:0}):await b({paths:t.paths,observed:null,lockTimeoutMs:0});return{cleanup:r,startError:e(n).message,retry:!t.ownedStateDir&&r.status!==`retained`}}async function q(e,t,n){return{cleanup:await x({paths:e.paths,observed:t.readIdentity(),mode:`graceful`,ownedStateDir:e.ownedStateDir,termTimeoutMs:Math.min(3e3,J(n)),killTimeoutMs:1e3,lockTimeoutMs:0}),joined:await ye(t)}}async function ye(e){let t;try{return await Promise.race([e.exited.then(()=>!0),new Promise(e=>{t=setTimeout(()=>e(!1),1e3)})])}finally{clearTimeout(t)}}function J(e){return e===void 0?1/0:Math.max(0,e-Date.now())}function Y(e){return e.state===`absent`||e.state===`held`&&(e.liveness===`owner-process-dead`||e.liveness===`owner-process-reused`)}async function be(r,i,a,o){if(!Z(r.command)||!i.startedByClient&&!a.ownedStateDir||f(i.info)||X(o)||Q(r,o))return o;let s=await x({paths:a.paths,observed:{pid:i.info.pid,startTime:i.info.processStartTime??null},mode:`graceful`,ownedStateDir:a.ownedStateDir});return n({level:s.status===`retained`?`warn`:`info`,phase:`daemon_replay_cleanup`,data:{pid:i.info.pid,...s}}),s.status!==`absent`&&s.repairCommitFailure?xe(o,s.repairCommitFailure,s.status===`retained`?s.error:void 0):s.status===`retained`&&o?.ok?{ok:!1,error:e(new t(`COMMAND_FAILED`,`Replay completed, but daemon cleanup could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:s,stateDir:a.paths.baseDir,hint:s.error?.hint??`State and diagnostics were retained at ${a.paths.baseDir}. Resolve the reported cleanup failure before retrying.`}))}:o}function xe(n,r,i){if(n&&!n.ok)return n;let{sessionName:a,tombstone:o}=r,s=o.sourcePath?`re-run: replay ${o.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,c=`The repair transaction for session "${a}" completed, but committing its healed script failed at teardown: ${o.commitFailure.message}. ${s}.`;return{ok:!1,error:e(new t(`REPAIR_COMMIT_FAILED`,c,i?{cleanupFailure:i}:void 0))}}function X(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:v(e.error.details?.divergence)?.repairSessionHeld===!0}function Se(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Z(e){return e===r.replay||e===r.test}function Q(e,t){return e.command!==r.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}async function Ce(e,t,n){let r;for(n.exited.then(e=>{r=e});Date.now()<e;){if(r){let n=we(r);if(n===`unproven`)return{kind:`unproven`,error:W(t)};if(n===`failed`)return{kind:`early_exit`,exit:r};let i=await Te(t,e);if(i)return i}else{let i=await Ee(t,n,e);if(i&&!r)return{kind:`ready`,daemon:{info:i,startedByClient:!0}}}await a(Math.min(100,J(e)))}return{kind:`timeout`}}function we(e){if(e.error||e.signal)return`failed`;switch(e.exitCode){case S.busy:return`busy`;case S.unproven:return`unproven`;default:return`failed`}}async function Te(e,n){let r;try{r=await H(e,{deadline:n,waitForLiveStartup:!0})}catch(e){if(e instanceof t&&e.details?.reason===`daemon_registration_unproven`)return{kind:`unproven`,error:e};throw e}if(Date.now()>=n)return null;if(r)return{kind:`ready`,daemon:{info:r,startedByClient:!1}};let i=o(e.paths.lockPath);return i.state===`unproven`?{kind:`unproven`,error:W(e,i)}:Y(i)?{kind:`retry`}:null}async function Ee(r,i,a){let o=s(r.paths.infoPath);if(!o||!De(o,i))return null;try{return await u(o,r.transportPreference,J(a))&&Date.now()<a?o:null}catch(o){let{cleanup:s,joined:c}=await q(r,i,a);throw n({level:`warn`,phase:`daemon_startup_observation_failed`,data:{stateDir:r.paths.baseDir,cleanup:s,joined:c,error:e(o)}}),o instanceof t&&(o.details={...o.details,stateDir:r.paths.baseDir,cleanupResults:[s],startupJoined:c}),o}}function De(e,t){let n=t.readIdentity();return e.pid===n.pid&&n.startTime!==null&&e.processStartTime===n.startTime}function $(e){let t=D();return ae({paths:e.paths,serverMode:e.serverMode,ownedStateDir:e.ownedStateDir,args:t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath]})}function Oe(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function ke(e){try{if(!C.existsSync(e))return;let t=C.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=C.openSync(e,`r`);try{let e=Buffer.alloc(n);C.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{C.closeSync(r)}}catch{return}}function Ae(e){if(!e)return;let n;try{n=new URL(e)}catch(n){throw new t(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new t(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return n.toString().replace(/\/+$/,``)}function je(e,n){if(!e)return;let r=new URL(e).hostname;if(!Me(r)&&!(typeof n==`string`&&n.trim().length>0))throw new t(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function Me(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:T.isIPv4(t)?N.check(t,`ipv4`):T.isIPv6(t)?N.check(t,`ipv6`):!1}function Ne(e,t,n){return e.ok?Q(t,e)?le(e,n.ownedStateDir?n.paths.baseDir:void 0,n.remoteBaseUrl):e:n.ownedStateDir&&X(e)?Se(e,n.paths.baseDir):e}export{Ne as attachSessionAddressHints,be as cleanupDaemonAfterRequest,z as ensureDaemon,P as resolveClientSettings};
|
|
1
|
+
import{J as e,P as t}from"./sdk-contracts.js";import{r as n}from"./diagnostics.js";import"./diagnostics2.js";import{n as r}from"./catalog.js";import{m as i}from"./owner-identity.js";import{i as a}from"./retry.js";import{r as o}from"./file.js";import"./command.js";import{c as s,i as c,l,n as u,o as d,s as f,t as p}from"./daemon-client-transport.js";import"./process.js";import{a as m,i as ee,o as te,r as ne}from"./version.js";import{t as re}from"./ttl-memo.js";import{n as ie,r as h,t as g}from"./daemon-resolution.js";import"./retry2.js";import{s as _}from"./device-shell.js";import{i as v}from"./replay-divergence.js";import{n as y}from"./daemon-registration.js";import{a as b,i as ae,n as oe,o as x,t as S}from"./daemon-registration-owner.js";import{i as se,n as ce}from"./code-signature.js";import C from"node:fs";import w from"node:path";import T from"node:net";function le(e,t,n){let r=e.data??{},i=typeof r.session==`string`?r.session:void 0,a=[...n?[`--daemon-base-url ${_(ue(n))}`]:[],...t?[`--state-dir ${_(t)}`]:[],...i?[`--session ${_(i)}`]:[]];if(a.length===0)return e;let o=`This session's daemon was kept alive because its script left the session active; pass ${a.join(` `)} on your next command to reach it.`+(n?` If authentication is required, provide or configure --daemon-auth-token.`:``),s=typeof r.message==`string`?r.message:void 0;return{...e,data:{...r,hint:o,message:s?`${s} ${o}`:o}}}function ue(e){let t=new URL(e);return t.username=``,t.password=``,t.search=``,t.hash=``,t.toString().replace(/\/+$/,``)}const E=re();function D(){let e=E.get(`local`);if(e)return e;let n=ne(),r=[w.join(n,`dist`,`src`,`internal`,`daemon.js`),w.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>C.existsSync(e))??i,o=w.join(n,te),s=r.some(e=>C.existsSync(e)),c=C.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return E.set(`local`,l),l}async function O(){let e=D(),t=se(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:ce(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function k(e,t){let n=m();if(e.version!==n)return e.version&&ee(e.version,n)&&await t.onAnyAdvertisedTransport()?{kind:`refuseNewer`,daemonVersion:e.version,clientVersion:n}:{kind:`replace`,reason:`version mismatch (client v${n})`};let r=A(await O(),e);return r?{kind:`replace`,reason:r}:await t.onClientTransport()?{kind:`reuse`}:{kind:`replace`,reason:`unreachable`}}function A(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:j(e,t):t.codeOrigin===`installed`?j(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function j(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const M=15e3,N=new T.BlockList;N.addSubnet(`127.0.0.0`,8,`ipv4`),N.addAddress(`::1`,`ipv6`),N.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function P(e,t){let n=F(e),r=I(e,t),i=L(e,r.remoteBaseUrl),a=R(e,n,r.rawBaseUrl)?oe():void 0;return{paths:a?.paths??g(n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function F(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function I(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Ae(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return je(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function L(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=h(r);if(n&&i===`socket`)throw new t(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:ie(a)}}function R(e,t,n){return Z(e.command)&&!t&&!n}async function z(e){if(e.remoteBaseUrl)return await V(e);let t=await B(e);return await pe(t.info,e.paths.baseDir),t}async function B(e){let t=await H(e);return t?{info:t,startedByClient:!1}:await ge(e)}async function V(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl},r=await p(n);if(r.reachable)return n.remoteInstanceId=r.instanceId,n.remoteUpstreamInstanceId=r.upstream?.instanceId,{info:n,startedByClient:!1};throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function H(e,t={}){let{deadline:n}=t,r=o(e.paths.lockPath);if(r.state===`unproven`)throw W(e,r);let i=s(e.paths.infoPath);if(!i||!de(r,i)||t.waitForLiveStartup&&await U(i,n))return null;let a=await k(i,{onClientTransport:()=>G(i,e.transportPreference,n),onAnyAdvertisedTransport:()=>G(i,`auto`,n)});if(a.kind===`reuse`)return i;if(a.kind===`refuseNewer`)throw me(i,a,e.paths.baseDir);return J(n)<5e3?null:(he(i,a.reason,e.paths.baseDir),await fe(i,e.paths),null)}async function U(e,t){return i(e.pid)&&!await u(e,`auto`,J(t))}function de(e,t){return e.state===`absent`||y(e,{pid:t.pid,startTime:t.processStartTime??null})}function W(e,n){return new t(`COMMAND_FAILED`,`Daemon registration ownership could not be verified.`,{reason:`daemon_registration_unproven`,inspection:n,stateDir:e.paths.baseDir,hint:l(d(e.paths),e.paths)})}async function fe(e,n){let r=await x({paths:n,observed:{pid:e.pid,startTime:e.processStartTime??null},mode:`graceful`});if(r.status===`retained`)throw new t(`COMMAND_FAILED`,`Daemon replacement could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:r,hint:r.error?.hint??l(d(n),n)})}async function G(e,t,r){if(await K(e,t,r))return!0;for(let o=1;o<=3;o+=1){if(!i(e.pid)||r!==void 0&&Date.now()>=r)return!1;if(await a(Math.min(200,J(r))),await K(e,t,r))return n({level:`warn`,phase:`daemon_probe_recovered`,data:{pid:e.pid,retry:o}}),!0}return!1}async function pe(e,n){if(!process.env.AGENT_DEVICE_DAEMON_POLICY?.trim())return;let{loadDaemonPolicy:r}=await import(`./daemon-policy-file.js`).then(e=>e.t),i=r(process.env)?.digest;if(i!==e.policyDigest)throw new t(`COMMAND_FAILED`,`The running daemon does not enforce the daemon policy named by AGENT_DEVICE_DAEMON_POLICY.`,{reason:`DAEMON_POLICY_MISMATCH`,expectedPolicyDigest:i,daemonPolicyDigest:e.policyDigest??null,hint:`Stop the running daemon (agent-device daemon stop --state-dir ${_(n)}), then retry so a daemon starts with this policy.`})}async function K(e,t,n){try{return await u(e,t,J(n))}catch(e){if(c(e))return!1;throw e}}function me(e,n,r){let{daemonVersion:i,clientVersion:a}=n;return new t(`COMMAND_FAILED`,`Daemon (pid ${e.pid}, v${i}) is newer than this client (v${a}); refusing to replace it.`,{daemonPid:e.pid,daemonVersion:i,clientVersion:a,hint:`Use the agent-device v${i} CLI that started it, or stop it deliberately: agent-device daemon stop --state-dir ${_(r)}`})}function he(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function ge(e){let n=Date.now()+M,r=[],i,o=0;for(;o<2&&Date.now()<n;){o+=1;let t=await _e(e,n);if(`daemon`in t)return t.daemon;if(i=t,t.cleanup&&r.push(t.cleanup),!t.retry)break;await a(Math.min(150,Math.max(0,n-Date.now())))}let{startError:s,startupError:c,daemonProcess:u}=i??{},f=d(e.paths),p=ke(e.paths.logPath);throw new t(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:M,startupAttempts:o,cleanupResults:r,startError:s,startupError:c,daemonProcess:u,...p?{daemonLogTail:p}:{},metadataState:f,hint:l(f,e.paths)})}async function _e(t,n){let r;try{r=$(t)}catch(e){return await ve(t,e)}let i=await Ce(n,t,r);if(i.kind===`ready`)return{daemon:i.daemon};if(i.kind===`retry`)return{retry:!0};if(i.kind===`unproven`){let t=e(i.error);return{retry:!1,startError:t.message,startupError:t,daemonProcess:{pid:r.pid}}}let{cleanup:a,joined:s}=await q(t,r,n),c=Y(o(t.paths.lockPath));return{cleanup:a,retry:s&&i.kind===`early_exit`&&c,startError:i.kind===`early_exit`?Oe(i.exit):void 0,daemonProcess:i.kind===`early_exit`?i.exit:{pid:r.pid}}}async function ve(t,n){let r=t.ownedStateDir?await x({paths:t.paths,observed:null,mode:`graceful`,ownedStateDir:t.ownedStateDir,lockTimeoutMs:0}):await b({paths:t.paths,observed:null,lockTimeoutMs:0});return{cleanup:r,startError:e(n).message,retry:!t.ownedStateDir&&r.status!==`retained`}}async function q(e,t,n){return{cleanup:await x({paths:e.paths,observed:t.readIdentity(),mode:`graceful`,ownedStateDir:e.ownedStateDir,termTimeoutMs:Math.min(3e3,J(n)),killTimeoutMs:1e3,lockTimeoutMs:0}),joined:await ye(t)}}async function ye(e){let t;try{return await Promise.race([e.exited.then(()=>!0),new Promise(e=>{t=setTimeout(()=>e(!1),1e3)})])}finally{clearTimeout(t)}}function J(e){return e===void 0?1/0:Math.max(0,e-Date.now())}function Y(e){return e.state===`absent`||e.state===`held`&&(e.liveness===`owner-process-dead`||e.liveness===`owner-process-reused`)}async function be(r,i,a,o){if(!Z(r.command)||!i.startedByClient&&!a.ownedStateDir||f(i.info)||X(o)||Q(r,o))return o;let s=await x({paths:a.paths,observed:{pid:i.info.pid,startTime:i.info.processStartTime??null},mode:`graceful`,ownedStateDir:a.ownedStateDir});return n({level:s.status===`retained`?`warn`:`info`,phase:`daemon_replay_cleanup`,data:{pid:i.info.pid,...s}}),s.status!==`absent`&&s.repairCommitFailure?xe(o,s.repairCommitFailure,s.status===`retained`?s.error:void 0):s.status===`retained`&&o?.ok?{ok:!1,error:e(new t(`COMMAND_FAILED`,`Replay completed, but daemon cleanup could not be confirmed.`,{reason:`daemon_retirement_unconfirmed`,retirement:s,stateDir:a.paths.baseDir,hint:s.error?.hint??`State and diagnostics were retained at ${a.paths.baseDir}. Resolve the reported cleanup failure before retrying.`}))}:o}function xe(n,r,i){if(n&&!n.ok)return n;let{sessionName:a,tombstone:o}=r,s=o.sourcePath?`re-run: replay ${o.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,c=`The repair transaction for session "${a}" completed, but committing its healed script failed at teardown: ${o.commitFailure.message}. ${s}.`;return{ok:!1,error:e(new t(`REPAIR_COMMIT_FAILED`,c,i?{cleanupFailure:i}:void 0))}}function X(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:v(e.error.details?.divergence)?.repairSessionHeld===!0}function Se(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Z(e){return e===r.replay||e===r.test}function Q(e,t){return e.command!==r.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}async function Ce(e,t,n){let r;for(n.exited.then(e=>{r=e});Date.now()<e;){if(r){let n=we(r);if(n===`unproven`)return{kind:`unproven`,error:W(t)};if(n===`failed`)return{kind:`early_exit`,exit:r};let i=await Te(t,e);if(i)return i}else{let i=await Ee(t,n,e);if(i&&!r)return{kind:`ready`,daemon:{info:i,startedByClient:!0}}}await a(Math.min(100,J(e)))}return{kind:`timeout`}}function we(e){if(e.error||e.signal)return`failed`;switch(e.exitCode){case S.busy:return`busy`;case S.unproven:return`unproven`;default:return`failed`}}async function Te(e,n){let r;try{r=await H(e,{deadline:n,waitForLiveStartup:!0})}catch(e){if(e instanceof t&&e.details?.reason===`daemon_registration_unproven`)return{kind:`unproven`,error:e};throw e}if(Date.now()>=n)return null;if(r)return{kind:`ready`,daemon:{info:r,startedByClient:!1}};let i=o(e.paths.lockPath);return i.state===`unproven`?{kind:`unproven`,error:W(e,i)}:Y(i)?{kind:`retry`}:null}async function Ee(r,i,a){let o=s(r.paths.infoPath);if(!o||!De(o,i))return null;try{return await u(o,r.transportPreference,J(a))&&Date.now()<a?o:null}catch(o){let{cleanup:s,joined:c}=await q(r,i,a);throw n({level:`warn`,phase:`daemon_startup_observation_failed`,data:{stateDir:r.paths.baseDir,cleanup:s,joined:c,error:e(o)}}),o instanceof t&&(o.details={...o.details,stateDir:r.paths.baseDir,cleanupResults:[s],startupJoined:c}),o}}function De(e,t){let n=t.readIdentity();return e.pid===n.pid&&n.startTime!==null&&e.processStartTime===n.startTime}function $(e){let t=D();return ae({paths:e.paths,serverMode:e.serverMode,ownedStateDir:e.ownedStateDir,args:t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath]})}function Oe(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function ke(e){try{if(!C.existsSync(e))return;let t=C.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=C.openSync(e,`r`);try{let e=Buffer.alloc(n);C.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{C.closeSync(r)}}catch{return}}function Ae(e){if(!e)return;let n;try{n=new URL(e)}catch(n){throw new t(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new t(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return n.toString().replace(/\/+$/,``)}function je(e,n){if(!e)return;let r=new URL(e).hostname;if(!Me(r)&&!(typeof n==`string`&&n.trim().length>0))throw new t(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function Me(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:T.isIPv4(t)?N.check(t,`ipv4`):T.isIPv6(t)?N.check(t,`ipv6`):!1}function Ne(e,t,n){return e.ok?Q(t,e)?le(e,n.ownedStateDir?n.paths.baseDir:void 0,n.remoteBaseUrl):e:n.ownedStateDir&&X(e)?Se(e,n.paths.baseDir):e}export{Ne as attachSessionAddressHints,be as cleanupDaemonAfterRequest,z as ensureDaemon,P as resolveClientSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{I as e,P as t,Y as n,at as r,rt as i}from"./sdk-contracts.js";import{n as a,r as o}from"./diagnostics.js";import"./diagnostics2.js";import{d as s,m as c,o as l}from"./lease-scope.js";import{T as u}from"./sdk-batch.js";import{n as d}from"./catalog.js";import{r as f}from"./owner-identity.js";import{d as p,f as m,l as h,n as g,s as _}from"./daemon-http.js";import{n as v}from"./daemon-artifacts.js";import{i as ee,n as y,t as b}from"./transport.js";import{n as x,o as te,t as ne}from"./request-progress-protocol.js";import{t as re}from"./session-artifact-paths.js";import"./process.js";import{a as ie}from"./version.js";import{t as ae}from"./daemon-resolution.js";import S from"node:fs";import oe from"node:path";import C from"node:net";function w(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function T(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(w(e.req,n,r))}if(ne(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return x(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(w(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function se(e,t){return te(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function ce(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=T({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=b(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(w(n,e)))})}function le(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=T({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=b(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(w(r,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},e instanceof Error?e:void 0)))})}const E=1e4,D=8388608;function ue(e,t){return m(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function de(e){let{logPath:t,...n}=e;return n}async function fe(e,t){let n=de(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return O(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=re(t.stateDir,r),a=await pe({endpoint:t.endpoint,ref:r,destinationPath:e});return a?O(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return O(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function O(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function pe(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(ue(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await y(i.protocol);return await S.promises.mkdir(oe.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}S.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...h(t.token),...p(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=S.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>D&&(s.destroy(),n.destroy(),o(`record exceeds ${D} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${E}ms`),s.destroy()},E);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function k(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=me(e);if(n.error){he(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new t(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}ve(r,i,n.result,o,s)}catch(n){s(new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},n instanceof Error?n:void 0))}}function me(e){return JSON.parse(e)}async function he(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=ge(e);if(!n.baseUrl){a(A(s,o));return}a(A(await fe(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function ge(e){let t=e.data??{},r=_e(t.cause);return{code:i(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:r,details:typeof t.details==`object`&&t.details?t.details:void 0,hint:typeof t.hint==`string`?t.hint:void 0,diagnosticId:typeof t.diagnosticId==`string`?t.diagnosticId:void 0,logPath:typeof t.logPath==`string`?t.logPath:void 0,diagnosticsRecord:n(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function _e(e){return r(e)}function A(e,n){return new t(i(e.code,`COMMAND_FAILED`),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,logPathUnavailable:e.logPathUnavailable,diagnosticsRecord:e.diagnosticsRecord,retriable:e.retriable,supportedOn:e.supportedOn,requestId:n},e.cause)}async function ve(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await v(e,t,n):n)}catch(e){i(e)}}function ye(e,t){let n=e.meta?.requestId??a();return be(e.command)?{jsonrpc:`2.0`,id:n,method:xe(e.command),params:{...Se(e,e.command,t),...e.command===`lease_allocate`?c(e.flags):{},...e.command===`lease_allocate`&&e.meta?.providerCredentialFingerprint?{providerCredentialFingerprint:e.meta.providerCredentialFingerprint}:{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function be(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function xe(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Se(e,t,n){return s(l(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}async function Ce(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:s,command:c,platform:l,session:u,action:d}=e,f=!i&&we(c)?await(await import(`./daemon-client-liveness-probe.js`)).probeDaemonResponsive(n,{session:u}):void 0,p=f===!1,m;if(p){let{stopAndRetireDaemon:e}=await import(`./daemon-registration-owner.js`).then(e=>e.r);m=await e({paths:r,observed:{pid:n.pid,startTime:n.processStartTime??null},mode:`force`})}let h=m?.status===`retired`,g=m?.status===`retained`&&m.termination?.status!==`exited`;return o({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:s,command:c,daemonPidReset:h?n.pid:void 0,daemonPidForceKilled:h?Oe(m):void 0,daemonRetirement:m,daemonPreservedAfterTimeout:g||!i&&!p,daemonLivenessProbeAnswered:f,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:s,reason:`daemon_transport_timeout`,...m?{retirement:m,stateDir:r.baseDir}:{},hint:m?.status===`retained`?`The daemon could not be safely retired. State was retained at ${r.baseDir}. ${m.error?.hint??`Retry with --debug and inspect daemon diagnostics before retrying.`}`:De({remote:i,resetDaemon:h,command:c,applePlatformDeclared:Ee(l),session:u,action:d})})}function we(e){return u(e).onTimeout===`reset-daemon`}const Te=new Set([`apple`,`ios`,`macos`]);function Ee(e){return e!==void 0&&Te.has(e)}function De(e){let{remote:t,resetDaemon:n,command:r,applePlatformDeclared:i,session:a,action:o}=e;if(!n&&r===d.record&&o===`stop`)return`The ${t?`remote `:``}daemon may still be exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(n)return`Retry with --debug and check daemon diagnostics logs. The daemon did not answer the liveness probe and was reset after the timeout.`;let s=i&&r===d.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled; the daemon was kept alive so the session can still be closed or inspected.${s}`}function Oe(e){if(!e||e.status===`absent`)return!1;let t=e.termination;return t?.status===`exited`&&t.mode===`forced`}function ke(e){let t=Ie(e);if(!t||typeof t!=`object`)return null;let n=t,r=Ae(n);if(!r)return null;let i=je(n);return i?{token:r,...i,transport:Ne(n.transport),pid:f(n.pid)?n.pid:0,version:j(n.version),codeOrigin:Me(n.codeOrigin),codeSignature:j(n.codeSignature),processStartTime:j(n.processStartTime),policyDigest:j(n.policyDigest)}:null}function Ae(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function je(e){let t=M(e.port),n=M(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Me(e){return e===`installed`||e===`checkout`?e:void 0}function Ne(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function j(e){return typeof e==`string`?e:void 0}function M(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function Pe(e){return{hasInfo:S.existsSync(e.infoPath),hasLock:S.existsSync(e.lockPath)}}function N(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Fe(e,t=ae(process.env.AGENT_DEVICE_STATE_DIR)){let n=[e.hasInfo?t.infoPath:null,e.hasLock?t.lockPath:null].filter(Boolean).join(` and `);return`Daemon startup did not establish a reachable owner. ${n?`State was retained at ${n}. `:``}Retry with --debug and inspect daemon diagnostics. Before upgrading, stop all older clients and daemons with their original CLI and prevent them from returning to this state directory. Unverified lock state requires confirming every user stopped before manual recovery; deleting metadata alone is not a safe reset.`}function Ie(e){if(!S.existsSync(e))return null;try{return JSON.parse(S.readFileSync(e,`utf8`))}catch{return null}}function P(t,n,r){return e({requestId:r,dispatched:n},t.reason)}function F(e,t){if(e?.aborted)throw P(e,`no`,t)}const Le={refuseIfAborted:()=>{},guard:async e=>await e()};function Re(e){let{signal:t,requestId:n}=e;return t?{refuseIfAborted(){if(t.aborted)throw P(t,`no`,n)},guard:async e=>{if(t.aborted)throw P(t,`no`,n);return await new Promise((r,i)=>{let a=()=>i(P(t,`unknown`,n));t.addEventListener(`abort`,a,{once:!0}),e().then(e=>{t.removeEventListener(`abort`,a),r(e)},e=>{t.removeEventListener(`abort`,a),i(e)})})}}:Le}const I=3e3,L=`daemon_endpoint_unavailable`;function ze(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&e.details?.reason===L}function R(e){return new t(`COMMAND_FAILED`,e===`http`?`Daemon HTTP endpoint is unavailable`:`Daemon socket endpoint is unavailable`,{reason:L,transport:e})}async function Be(e,t,n){let r=Date.now()+(n??1/0),i=q(e,t),a=Y(e,t,i);return await z(e,i,(r-Date.now())/(a?2:1))?Date.now()<r:a?await z(e,a,r-Date.now())&&Date.now()<r:!1}async function z(e,t,n){return t===`http`?await He(e,n):await Ve(e.port,n)}function Ve(e,t=500){return!e||t<=0?Promise.resolve(!1):new Promise(n=>{let r=!1,i=C.createConnection({host:`127.0.0.1`,port:e},()=>{a(!0)}),a=e=>{r||(r=!0,i.destroy(),n(e))};i.setTimeout(Math.min(500,Math.ceil(t))),i.on(`timeout`,()=>{a(!1)}),i.on(`error`,()=>{a(!1)})})}function He(e,t){return V(e,t).then(e=>e.reachable)}async function B(e,n,r){let i=await V(e,n,r);if(!e.baseUrl||!i.reachable)return i;let a=[i,i.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(a)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:ie(),remoteVersion:a.version,remoteService:a.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:a.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return i}function Ue(e){return e.baseUrl?m(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null}async function V(e,t,n){let r=Ue(e);if(!r)return{reachable:!1};let i=new URL(r),a=Math.min(e.baseUrl?I:500,t??1/0);if(a<=0)return{reachable:!1,timedOut:!0};let o=performance.now()+a,s=AbortSignal.timeout(Math.ceil(a)),c=n?AbortSignal.any([s,n]):s,l=await Promise.race([y(i.protocol),new Promise(e=>{c.addEventListener(`abort`,()=>e(null),{once:!0})})]),u=()=>We(s,o);return!l||H(c,o)?u():await new Promise(t=>{let n=e.baseUrl?h(e.token):{},r=l.request({protocol:i.protocol,host:i.hostname,port:i.port,path:i.pathname+i.search,method:`GET`,timeout:a,signal:c,headers:n},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t(H(s,o)?{reachable:!1,timedOut:!0}:{reachable:r<500,statusCode:r,...Ge(n)})}),e.on(`error`,()=>t(u())),e.on(`aborted`,()=>t(u()))});r.on(`timeout`,()=>{r.destroy(),t({reachable:!1,timedOut:!0})}),r.on(`error`,()=>{t(u())}),r.end()})}function We(e,t){return H(e,t)?{reachable:!1,timedOut:!0}:{reachable:!1}}function H(e,t){return e.aborted||performance.now()>=t}function Ge(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?U(t.upstream):void 0;return{...U(t),...n?{upstream:n}:{}}}catch{return{}}}function U(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0,...typeof e.instanceId==`string`?{instanceId:e.instanceId}:{},...typeof e.hostArch==`string`?{hostArch:e.hostArch}:{}}}async function Ke(e,n,r,i,a,o={}){try{return await qe(e,n,r,i,a,o)}catch(r){if(!(r instanceof t)||r.details?.reason!==`daemon_transport_timeout`)throw r;let a=r.details.timeoutMs;throw typeof a==`number`?await Ce({info:e,statePaths:i,...$e(n,N(e),a)}):r}}async function qe(e,t,n,r,i,a={}){let o=q(e,n),s=typeof i==`number`?performance.now()+i:void 0;F(a.signal,t.meta?.requestId);try{return await K(e,t,r,i,o,a)}catch(c){if(e.baseUrl&&Ye(c))return await Je(e,t,r,i,s,o,a);G(c)&&$(e);let l=Y(e,n,o);if(!l||!Xe(c,o))throw c;return await K(e,t,r,i,l,a)}}async function Je(e,n,r,i,a,o,s){$(e);let c=W(n,i,a),l=await B(e,c,s.signal);F(s.signal,n.meta?.requestId);let u=W(n,i,a,l.timedOut?c:void 0);if(!l.reachable)throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.baseUrl});e.remoteInstanceId=l.instanceId,e.remoteUpstreamInstanceId=l.upstream?.instanceId,it(e,l);try{return await K(e,n,r,u,o,s)}catch(t){throw G(t)&&$(e),t}}function W(e,t,n,r){if(n===void 0||t===void 0)return;let i=n-performance.now();if(i>0&&(r===void 0||r>I))return i;throw Z(t,e.meta?.requestId)}function Ye(e){return e instanceof t&&e.details?.reason===`remote_instance_mismatch`}function G(e){return e instanceof t&&(e.details?.reason===`daemon_transport_failure`||e.details?.reason===`daemon_transport_timeout`||e.details?.reason===`daemon_response_read_failure`)}async function K(e,t,n,r,i,a){return i===`http`?await nt(e,t,n,r,a):await Qe(e,t,r,a)}function q(e,n){if(e.baseUrl){if(n===`socket`)throw new t(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(n===`http`||n===`socket`)return Ze(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>J(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function J(e,t){return t===`http`?!!e.httpPort:!!e.port}function Y(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return J(e,r)?r:null}function Xe(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function Ze(e,t){if(J(e,t))return t;throw R(t)}function X(e,n,r,i={}){return o({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:e instanceof Error?e.message:String(e)}}),new t(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,reason:`daemon_transport_failure`,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},e instanceof Error?e:void 0)}async function Qe(e,t,n,r){let i=e.port;if(!i)throw R(`socket`);let a=r.signal;return F(a,t.meta?.requestId),new Promise((e,o)=>{let s=!1,c=!1,l=C.createConnection({host:`127.0.0.1`,port:i},()=>{if(a?.aborted){c=!0,d(a);return}s=!0,l.write(`${JSON.stringify(t)}\n`)}),u=typeof n==`number`?setTimeout(()=>{c||(c=!0,p(),o(Z(n,t.meta?.requestId)),l.destroy())},n):void 0,d=e=>{p(),u&&clearTimeout(u),l.destroy(),o(P(e,s?`unknown`:`no`,t.meta?.requestId))},f=()=>{c||(c=!0,d(a))},p=()=>{a&&a.removeEventListener(`abort`,f)};a&&a.addEventListener(`abort`,f,{once:!0}),ce(l,{req:t,onProgress:r.onProgress,isSettled:()=>c,clearTimeout:()=>{u&&clearTimeout(u)},resolve:t=>{c=!0,p(),e(t)},reject:e=>{c=!0,p(),o(e)}}),l.on(`error`,e=>{c||(c=!0,u&&clearTimeout(u),p(),o(X(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:s})))})})}function Z(e,n){return new t(`COMMAND_FAILED`,`Daemon request timed out`,{reason:`daemon_transport_timeout`,timeoutMs:e,requestId:n})}function $e(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}function et(e){return{...e.remoteInstanceId?{[g]:e.remoteInstanceId}:{},...e.remoteUpstreamInstanceId?{[_]:e.remoteUpstreamInstanceId}:{}}}function tt(e,t){return e===409&&t[`x-agent-device-instance-mismatch`]===`true`}async function nt(e,n,r,i,a){let o=e.baseUrl?new URL(m(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw R(`http`);let s=JSON.stringify(ye(n,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&(Object.assign(c,h(e.token)),Object.assign(c,et(e)));let l=await y(o.protocol),u=a.signal;return F(u,n.meta?.requestId),await new Promise((d,f)=>{let p=!1,m=!1,h=()=>{u&&u.removeEventListener(`abort`,x)},g=e=>{p||(p=!0,h(),d(e))},_=e=>{p||(p=!0,h(),f(e))},v=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(tt(i.statusCode,i.headers??{})){i.resume(),b&&clearTimeout(b),_(new t(`COMMAND_FAILED`,`Remote daemon instance changed`,{reason:`remote_instance_mismatch`,daemonBaseUrl:e.baseUrl}));return}if(se(n,i.headers?.[`content-type`])){le(i,{req:n,onProgress:a.onProgress,reject:_,clearTimeout:()=>{b&&clearTimeout(b)},handleResponseBody:t=>{k(t,{info:e,req:n,stateDir:r.baseDir,resolve:g,reject:_})}});return}ee(i).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId,reason:`daemon_response_read_failure`},e instanceof Error?e:void 0)}).then(t=>{b&&clearTimeout(b),k(t,{info:e,req:n,stateDir:r.baseDir,resolve:g,reject:_})}).catch(e=>{b&&clearTimeout(b),_(e)})}),y=N(e),b=typeof i==`number`?setTimeout(()=>{_(Z(i,n.meta?.requestId)),v.destroy()},i):void 0,x=()=>{p||(b&&clearTimeout(b),_(P(u,m?`unknown`:`no`,n.meta?.requestId)),v.destroy())};u&&u.addEventListener(`abort`,x,{once:!0}),v.on(`error`,e=>{b&&clearTimeout(b),!p&&_(X(e,n.meta?.requestId,y))}),v.write(s),v.end(),m=!0})}let Q;function rt(e,t){return e.baseUrl===t.baseUrl&&e.token===t.token&&e.pid===t.pid}function it(e,t){!t.instanceId||t.upstream&&!t.upstream.instanceId||(Q={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:Promise.resolve(t)})}function $(e){Q&&rt(Q,e)&&(Q=void 0)}async function at(e){if(Q&&rt(Q,e))return await Q.health;let t={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:B(e)};Q=t;try{let e=await t.health;return(!e.reachable||!e.instanceId||e.upstream&&!e.upstream.instanceId)&&Q===t&&(Q=void 0),e}catch(e){throw Q===t&&(Q=void 0),e}}export{Ke as a,ke as c,ze as i,Fe as l,Be as n,Pe as o,Re as r,N as s,at as t};
|
|
1
|
+
import{I as e,P as t,Y as n,at as r,rt as i}from"./sdk-contracts.js";import{n as a,r as o}from"./diagnostics.js";import"./diagnostics2.js";import{d as s,m as c,o as l}from"./lease-scope.js";import{T as u}from"./sdk-batch.js";import{n as d}from"./catalog.js";import{r as f}from"./owner-identity.js";import{l as p}from"./exec.js";import{d as m,f as h,h as g,l as _,m as v,n as y,s as ee}from"./daemon-http.js";import{r as b,t as x}from"./output-path.js";import"./command.js";import{i as te,n as S,t as C}from"./transport.js";import{n as ne,o as re,t as ie}from"./request-progress-protocol.js";import{t as ae}from"./session-artifact-paths.js";import"./process.js";import{a as oe}from"./version.js";import{t as se}from"./daemon-resolution.js";import{createHash as ce,randomUUID as le}from"node:crypto";import w from"node:fs";import ue from"node:os";import T from"node:path";import{Transform as de,Writable as fe}from"node:stream";import{pipeline as pe}from"node:stream/promises";import me from"node:net";async function he(e,t){let n=w.statSync(e),r=T.basename(e),i=n.isDirectory(),a=ve(t)??_e(e,n),o=[];try{let t=i?await ge(e,o):e,n=w.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await ye(t),sizeBytes:n.size,cleanup:()=>E(o)}}catch(e){throw E(o),e}}async function ge(e,t){let n=w.mkdtempSync(T.join(ue.tmpdir(),`agent-device-upload-${le()}-`));t.push(n);let r=T.join(n,`${T.basename(e)}.tar.gz`);return await p(`tar`,[`czf`,r,`-C`,T.dirname(e),T.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function _e(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function ve(e){return e===`ios`||e===`android`?e:void 0}function E(e){for(let t of e)w.rmSync(t,{recursive:!0,force:!0})}async function ye(e){let n=ce(`sha256`),r=new fe({write(e,t,r){n.update(e),r()}});return await pe(w.createReadStream(e),r).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),n.digest(`hex`)}function be(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Ce(i),c=Math.min(i,r+s);return new de({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function xe(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Se(e)}\n`)}}function Se(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${O(e.totalBytes)}) via ${D(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${O(e.transferredBytes)} of ${O(e.totalBytes)}`;case`progress`:return`Uploaded ${O(e.transferredBytes)} of ${O(e.totalBytes)} (${we(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${D(e.to)} upload`}}function Ce(e){return Math.max(8388608,Math.ceil(e*.05))}function D(e){return e===`direct`?`direct`:`legacy`}function we(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function O(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const k=3e5,A=`uploadStreamRetryable`;async function j(e){return await M({...e,url:e.url,redirectCount:0,startOffset:0})}function Te(e){return e instanceof t&&e.details?.[A]===!0}async function M(e){let n=await S(e.url.protocol),r=w.statSync(e.payloadPath).size,i=De(e.headers,e.startOffset,r);return Ee(e.progress,e.startOffset,r),await new Promise((a,o)=>{let s=!1,c=n.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i,...e.signal?{signal:e.signal}:{}},n=>{s=!0,te(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Oe(s)){if(e.redirectCount>=5){o(new t(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let n=new URL(c,e.url);M({...e,url:n,redirectCount:e.redirectCount+1}).then(a,o);return}let u=ke(s)?Ae(n.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new t(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}M({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:n.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new t(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:k,...e.timeoutHint?{hint:e.timeoutHint}:{},...N(e)}))},k);c.on(`error`,n=>{if(!s){if(clearTimeout(l),e.signal?.aborted){o(e.signal.reason);return}o(new t(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...N(e)},n))}}),c.on(`close`,()=>clearTimeout(l)),pe(w.createReadStream(e.payloadPath,{start:e.startOffset}),be({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??T.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:r,onProgress:e.progress?.onProgress}),c).catch(e=>{if(s)return;c.destroy();let n=e instanceof Error?e:Error(String(e));o(new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function N(e){return e.retryable===!0?{[A]:!0}:{}}function Ee(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function De(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Oe(e){return[301,302,303,307,308].includes(e)}function ke(e){return e===308}function Ae(e,t){let n=je(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=P(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function je(e){let t=P(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function P(e){return Array.isArray(e)?e[0]:e}const F=3e4;async function I(e){let t=await he(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=le();try{let i=await R({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r,signal:e.signal});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Me({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress,signal:e.signal})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await L({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})):await L({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress,signal:e.signal})}finally{t.cleanup()}}async function Me(e){let t=async t=>(await Re(e.artifact,t,e.onProgress,e.signal),await ze({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId,signal:e.signal}));try{return await t(e.preflight)}catch(n){if(e.signal?.aborted)throw n;return Pe(n)?await Ne(e,t):void 0}}async function Ne(e,t){let n=await R({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId,signal:e.signal});if(n?.kind===`cache-hit`)return n.uploadId;if(n?.kind===`direct-upload`)try{return await t(n)}catch{return}}function Pe(e){return e instanceof t?Te(e):!0}async function L(e){let{normalizedBase:n,token:r,artifact:i}=e,a=new URL(`upload`,n),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,_(r));let s=await j({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,signal:e.signal,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new t(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof t?e:new t(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function R(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,_(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:Fe(e.signal,F),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(t=>{if(e.signal?.aborted)throw t});if(r?.ok)return Ie(await r.json().catch(()=>void 0))}function Fe(e,t){let n=AbortSignal.timeout(t);return e?AbortSignal.any([e,n]):n}function Ie(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Le(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Le(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Re(e,n,r,i){let a=await j({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,signal:i,progress:{stage:`direct`,fileName:e.fileName,onProgress:r}});if(a.statusCode<200||a.statusCode>=300)throw new t(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function ze(e){let n=new URL(`upload/finalize`,e.normalizedBase),r={"content-type":`application/json`};Object.assign(r,_(e.token));let i=await fetch(n,{method:`POST`,headers:r,signal:Fe(e.signal,F),body:JSON.stringify({uploadId:e.uploadId})}).catch(n=>{throw e.signal?.aborted?n:new t(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},n)});if(!i.ok)throw new t(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new t(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Be(e,t,n){let r=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,a=e.meta?.installSource,o={},s,c=xe();if(!at(t))return Ke({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o});Ve(e),i=Ue(e,r,i,o);let l=await qe(e,t,c,n);return l&&(a=l.installSource,s=l.uploadedArtifactId??s),e.command!==`install`&&e.command!==`reinstall`||(s=await He(e,t,r,c,n)??s),Ke({positionals:r,flags:i,installSource:a,uploadedArtifactId:s,clientArtifactPaths:o})}function Ve(e){if(e.flags?.saveScript!==void 0)throw new t(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:e.command})}async function He(e,t,n,r,i){let a=n.length===1?0:1,o=n[a];if(o===void 0)return;if(o.startsWith(`remote:`)){n[a]=o.slice(7);return}let s=Ge(o,e.meta?.cwd);if(s)return await I({localPath:s,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r,signal:i})}function Ue(e,t,n,r){let i=Je(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=We(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function We(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function Ge(e,t){let n=T.isAbsolute(e)?e:T.resolve(t??process.cwd(),e);return w.existsSync(n)?n:void 0}function Ke(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function qe(e,t,n,r){let i=e.meta?.installSource;if(e.command!==`install_source`||!i||i.kind!==`path`)return null;let a=i.path.trim();if(!a)return{installSource:i};if(a.startsWith(`remote:`))return{installSource:{...i,path:a.slice(7)}};let o=T.isAbsolute(a)?a:T.resolve(e.meta?.cwd??process.cwd(),a);if(!w.existsSync(o))return{installSource:{...i,path:o}};let s=await I({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n,signal:r});return{installSource:{...i,path:o},uploadedArtifactId:s}}function Je(e,t){if(e.command===`screenshot`){let n=$e(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:g(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:g(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!Ze(e)&&e.flags?.platform===void 0)return null;let t=Xe(e),n=Qe($e(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:g(`recording`,T.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:Ye(e),flagKey:`artifactsDir`,flagPath:v(`test-artifacts`)}:null}function Ye(e){let t=e.flags?.artifactsDir;return et(z(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function Xe(e){return b(e.flags?.platform)}function Ze(e){return z(e.positionals?.[1])||z(e.flags?.out)}function Qe(e,t){return t.flags?.platform===`web`?x(e,Xe(t)):e}function $e(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return et(z(i)?i:a,e.meta?.cwd)}function et(e,t){return T.isAbsolute(e)?e:T.resolve(t??process.cwd(),e)}function z(e){return typeof e==`string`&&e.trim().length>0}async function tt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=nt(n,t),o=await rt({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta,isDirectory:n.artifactType===`test-artifacts`});i[n.field]=o,a.push({...n,localPath:o})}return i.artifacts=a,{ok:!0,data:i}}function nt(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return T.resolve(t.meta?.cwd??process.cwd(),r)}async function rt(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(it(e.baseUrl,e.artifactId)),token:e.token,artifactId:e.artifactId,destinationPath:e.destinationPath,requestScope:e.requestScope,...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs},...e.isDirectory===void 0?{}:{isDirectory:e.isDirectory}})}function it(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function at(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function B(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function ot(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(B(e.req,n,r))}if(ie(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return ne(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(B(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function st(e,t){return re(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function ct(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=ot({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=C(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(B(n,e)))})}function lt(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=ot({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=C(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(B(r,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},e instanceof Error?e:void 0)))})}const ut=1e4,V=8388608;function dt(e,t){return h(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function ft(e){let{logPath:t,...n}=e;return n}async function pt(e,t){let n=ft(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return H(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=ae(t.stateDir,r),a=await mt({endpoint:t.endpoint,ref:r,destinationPath:e});return a?H(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return H(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function H(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function mt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(dt(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await S(i.protocol);return await w.promises.mkdir(T.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}w.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{..._(t.token),...m(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=w.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>V&&(s.destroy(),n.destroy(),o(`record exceeds ${V} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${ut}ms`),s.destroy()},ut);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function ht(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=gt(e);if(n.error){_t(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new t(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}xt(r,i,n.result,o,s)}catch(n){s(new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},n instanceof Error?n:void 0))}}function gt(e){return JSON.parse(e)}async function _t(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=vt(e);if(!n.baseUrl){a(bt(s,o));return}a(bt(await pt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function vt(e){let t=e.data??{},r=yt(t.cause);return{code:i(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:r,details:typeof t.details==`object`&&t.details?t.details:void 0,hint:typeof t.hint==`string`?t.hint:void 0,diagnosticId:typeof t.diagnosticId==`string`?t.diagnosticId:void 0,logPath:typeof t.logPath==`string`?t.logPath:void 0,diagnosticsRecord:n(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function yt(e){return r(e)}function bt(e,n){return new t(i(e.code,`COMMAND_FAILED`),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,logPathUnavailable:e.logPathUnavailable,diagnosticsRecord:e.diagnosticsRecord,retriable:e.retriable,supportedOn:e.supportedOn,requestId:n},e.cause)}async function xt(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await tt(e,t,n):n)}catch(e){i(e)}}function St(e,t){let n=e.meta?.requestId??a();return Ct(e.command)?{jsonrpc:`2.0`,id:n,method:wt(e.command),params:{...Tt(e,e.command,t),...e.command===`lease_allocate`?c(e.flags):{},...e.command===`lease_allocate`&&e.meta?.providerCredentialFingerprint?{providerCredentialFingerprint:e.meta.providerCredentialFingerprint}:{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Ct(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function wt(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Tt(e,t,n){return s(l(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}async function Et(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:s,command:c,platform:l,session:u,action:d}=e,f=!i&&Dt(c)?await(await import(`./daemon-client-liveness-probe.js`)).probeDaemonResponsive(n,{session:u}):void 0,p=f===!1,m;if(p){let{stopAndRetireDaemon:e}=await import(`./daemon-registration-owner.js`).then(e=>e.r);m=await e({paths:r,observed:{pid:n.pid,startTime:n.processStartTime??null},mode:`force`})}let h=m?.status===`retired`,g=m?.status===`retained`&&m.termination?.status!==`exited`;return o({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:s,command:c,daemonPidReset:h?n.pid:void 0,daemonPidForceKilled:h?jt(m):void 0,daemonRetirement:m,daemonPreservedAfterTimeout:g||!i&&!p,daemonLivenessProbeAnswered:f,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:s,reason:`daemon_transport_timeout`,...m?{retirement:m,stateDir:r.baseDir}:{},hint:m?.status===`retained`?`The daemon could not be safely retired. State was retained at ${r.baseDir}. ${m.error?.hint??`Retry with --debug and inspect daemon diagnostics before retrying.`}`:At({remote:i,resetDaemon:h,command:c,applePlatformDeclared:kt(l),session:u,action:d})})}function Dt(e){return u(e).onTimeout===`reset-daemon`}const Ot=new Set([`apple`,`ios`,`macos`]);function kt(e){return e!==void 0&&Ot.has(e)}function At(e){let{remote:t,resetDaemon:n,command:r,applePlatformDeclared:i,session:a,action:o}=e;if(!n&&r===d.record&&o===`stop`)return`The ${t?`remote `:``}daemon may still be exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(n)return`Retry with --debug and check daemon diagnostics logs. The daemon did not answer the liveness probe and was reset after the timeout.`;let s=i&&r===d.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled; the daemon was kept alive so the session can still be closed or inspected.${s}`}function jt(e){if(!e||e.status===`absent`)return!1;let t=e.termination;return t?.status===`exited`&&t.mode===`forced`}function Mt(e){let t=Bt(e);if(!t||typeof t!=`object`)return null;let n=t,r=Nt(n);if(!r)return null;let i=Pt(n);return i?{token:r,...i,transport:It(n.transport),pid:f(n.pid)?n.pid:0,version:U(n.version),codeOrigin:Ft(n.codeOrigin),codeSignature:U(n.codeSignature),processStartTime:U(n.processStartTime),policyDigest:U(n.policyDigest)}:null}function Nt(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function Pt(e){let t=Lt(e.port),n=Lt(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Ft(e){return e===`installed`||e===`checkout`?e:void 0}function It(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function U(e){return typeof e==`string`?e:void 0}function Lt(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function Rt(e){return{hasInfo:w.existsSync(e.infoPath),hasLock:w.existsSync(e.lockPath)}}function W(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function zt(e,t=se(process.env.AGENT_DEVICE_STATE_DIR)){let n=[e.hasInfo?t.infoPath:null,e.hasLock?t.lockPath:null].filter(Boolean).join(` and `);return`Daemon startup did not establish a reachable owner. ${n?`State was retained at ${n}. `:``}Retry with --debug and inspect daemon diagnostics. Before upgrading, stop all older clients and daemons with their original CLI and prevent them from returning to this state directory. Unverified lock state requires confirming every user stopped before manual recovery; deleting metadata alone is not a safe reset.`}function Bt(e){if(!w.existsSync(e))return null;try{return JSON.parse(w.readFileSync(e,`utf8`))}catch{return null}}function G(t,n,r){return e({requestId:r,dispatched:n},t.reason)}function K(e,t){if(e?.aborted)throw G(e,`no`,t)}const Vt={refuseIfAborted:()=>{},guard:async e=>await e()};function Ht(e){let{signal:t,requestId:n}=e;return t?{refuseIfAborted(){if(t.aborted)throw G(t,`no`,n)},guard:async e=>{if(t.aborted)throw G(t,`no`,n);return await new Promise((r,i)=>{let a=()=>i(G(t,`unknown`,n));t.addEventListener(`abort`,a,{once:!0}),e().then(e=>{t.removeEventListener(`abort`,a),r(e)},e=>{t.removeEventListener(`abort`,a),i(e)})})}}:Vt}const Ut=3e3,Wt=`daemon_endpoint_unavailable`;function Gt(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&e.details?.reason===Wt}function q(e){return new t(`COMMAND_FAILED`,e===`http`?`Daemon HTTP endpoint is unavailable`:`Daemon socket endpoint is unavailable`,{reason:Wt,transport:e})}async function Kt(e,t,n){let r=Date.now()+(n??1/0),i=un(e,t),a=dn(e,t,i);return await qt(e,i,(r-Date.now())/(a?2:1))?Date.now()<r:a?await qt(e,a,r-Date.now())&&Date.now()<r:!1}async function qt(e,t,n){return t===`http`?await Yt(e,n):await Jt(e.port,n)}function Jt(e,t=500){return!e||t<=0?Promise.resolve(!1):new Promise(n=>{let r=!1,i=me.createConnection({host:`127.0.0.1`,port:e},()=>{a(!0)}),a=e=>{r||(r=!0,i.destroy(),n(e))};i.setTimeout(Math.min(500,Math.ceil(t))),i.on(`timeout`,()=>{a(!1)}),i.on(`error`,()=>{a(!1)})})}function Yt(e,t){return $t(e,t).then(e=>e.reachable)}async function Xt(e,n,r){let i=await $t(e,n,r);if(!e.baseUrl||!i.reachable)return i;let a=[i,i.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(a)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:oe(),remoteVersion:a.version,remoteService:a.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:a.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return i}function Zt(e){return Qt(e,`health`)}function Qt(e,t){return e.baseUrl?h(e.baseUrl,t):e.httpPort?`http://127.0.0.1:${e.httpPort}/${t}`:null}async function $t(e,t,n){let r=Zt(e);if(!r)return{reachable:!1};let i=new URL(r),a=Math.min(e.baseUrl?Ut:500,t??1/0);if(a<=0)return{reachable:!1,timedOut:!0};let o=performance.now()+a,s=AbortSignal.timeout(Math.ceil(a)),c=n?AbortSignal.any([s,n]):s,l=await Promise.race([S(i.protocol),new Promise(e=>{c.addEventListener(`abort`,()=>e(null),{once:!0})})]),u=()=>en(s,o);return!l||J(c,o)?u():await new Promise(t=>{let n=e.baseUrl?_(e.token):{},r=l.request({protocol:i.protocol,host:i.hostname,port:i.port,path:i.pathname+i.search,method:`GET`,timeout:a,signal:c,headers:n},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t(J(s,o)?{reachable:!1,timedOut:!0}:{reachable:r<500,statusCode:r,...tn(n)})}),e.on(`error`,()=>t(u())),e.on(`aborted`,()=>t(u()))});r.on(`timeout`,()=>{r.destroy(),t({reachable:!1,timedOut:!0})}),r.on(`error`,()=>{t(u())}),r.end()})}function en(e,t){return J(e,t)?{reachable:!1,timedOut:!0}:{reachable:!1}}function J(e,t){return e.aborted||performance.now()>=t}function tn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?nn(t.upstream):void 0;return{...nn(t),...n?{upstream:n}:{}}}catch{return{}}}function nn(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0,...typeof e.instanceId==`string`?{instanceId:e.instanceId}:{},...typeof e.hostArch==`string`?{hostArch:e.hostArch}:{}}}async function rn(e,n,r,i,a,o={}){try{return await an(e,n,r,i,a,o)}catch(r){if(!(r instanceof t)||r.details?.reason!==`daemon_transport_timeout`)throw r;let a=r.details.timeoutMs;throw typeof a==`number`?await Et({info:e,statePaths:i,...gn(n,W(e),a)}):r}}async function an(e,t,n,r,i,a={}){let o=un(e,n),s=typeof i==`number`?performance.now()+i:void 0;K(a.signal,t.meta?.requestId);try{return await Y(e,t,r,i,o,a)}catch(c){if(e.baseUrl&&cn(c))return await on(e,t,r,i,s,o,a);ln(c)&&$(e);let l=dn(e,n,o);if(!l||!fn(c,o))throw c;return await Y(e,t,r,i,l,a)}}async function on(e,n,r,i,a,o,s){$(e);let c=sn(n,i,a),l=await Xt(e,c,s.signal);K(s.signal,n.meta?.requestId);let u=sn(n,i,a,l.timedOut?c:void 0);if(!l.reachable)throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.baseUrl});e.remoteInstanceId=l.instanceId,e.remoteUpstreamInstanceId=l.upstream?.instanceId,xn(e,l);try{return await Y(e,n,r,u,o,s)}catch(t){throw ln(t)&&$(e),t}}function sn(e,t,n,r){if(n===void 0||t===void 0)return;let i=n-performance.now();if(i>0&&(r===void 0||r>Ut))return i;throw Z(t,e.meta?.requestId)}function cn(e){return e instanceof t&&e.details?.reason===`remote_instance_mismatch`}function ln(e){return e instanceof t&&(e.details?.reason===`daemon_transport_failure`||e.details?.reason===`daemon_transport_timeout`||e.details?.reason===`daemon_response_read_failure`)}async function Y(e,t,n,r,i,a){return i===`http`?await yn(e,t,n,r,a):await hn(e,t,r,a)}function un(e,n){if(e.baseUrl){if(n===`socket`)throw new t(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(n===`http`||n===`socket`)return pn(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>X(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function X(e,t){return t===`http`?!!e.httpPort:!!e.port}function dn(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return X(e,r)?r:null}function fn(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function pn(e,t){if(X(e,t))return t;throw q(t)}function mn(e,n,r,i={}){return o({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:e instanceof Error?e.message:String(e)}}),new t(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,reason:`daemon_transport_failure`,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},e instanceof Error?e:void 0)}async function hn(e,t,n,r){let i=e.port;if(!i)throw q(`socket`);let a=r.signal;return K(a,t.meta?.requestId),new Promise((e,o)=>{let s=!1,c=!1,l=me.createConnection({host:`127.0.0.1`,port:i},()=>{if(a?.aborted){c=!0,d(a);return}s=!0,l.write(`${JSON.stringify(t)}\n`)}),u=typeof n==`number`?setTimeout(()=>{c||(c=!0,p(),o(Z(n,t.meta?.requestId)),l.destroy())},n):void 0,d=e=>{p(),u&&clearTimeout(u),l.destroy(),o(G(e,s?`unknown`:`no`,t.meta?.requestId))},f=()=>{c||(c=!0,d(a))},p=()=>{a&&a.removeEventListener(`abort`,f)};a&&a.addEventListener(`abort`,f,{once:!0}),ct(l,{req:t,onProgress:r.onProgress,isSettled:()=>c,clearTimeout:()=>{u&&clearTimeout(u)},resolve:t=>{c=!0,p(),e(t)},reject:e=>{c=!0,p(),o(e)}}),l.on(`error`,e=>{c||(c=!0,u&&clearTimeout(u),p(),o(mn(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:s})))})})}function Z(e,n){return new t(`COMMAND_FAILED`,`Daemon request timed out`,{reason:`daemon_transport_timeout`,timeoutMs:e,requestId:n})}function gn(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}function _n(e){return{...e.remoteInstanceId?{[y]:e.remoteInstanceId}:{},...e.remoteUpstreamInstanceId?{[ee]:e.remoteUpstreamInstanceId}:{}}}function vn(e,t){return e===409&&t[`x-agent-device-instance-mismatch`]===`true`}async function yn(e,n,r,i,a){let o=Qt(e,`rpc`);if(!o)throw q(`http`);let s=new URL(o),c=JSON.stringify(St(n,{includeTokenParam:!e.baseUrl})),l={"content-type":`application/json`,"content-length":Buffer.byteLength(c)};e.baseUrl&&(Object.assign(l,_(e.token)),Object.assign(l,_n(e)));let u=await S(s.protocol),d=a.signal;return K(d,n.meta?.requestId),await new Promise((o,f)=>{let p=!1,m=!1,h=()=>{d&&d.removeEventListener(`abort`,x)},g=e=>{p||(p=!0,h(),o(e))},_=e=>{p||(p=!0,h(),f(e))},v=t=>{ht(t,{info:e,req:n,stateDir:r.baseDir,resolve:g,reject:_})},y=u.request({protocol:s.protocol,host:s.hostname,port:s.port,method:`POST`,path:s.pathname+s.search,headers:l},r=>{if(vn(r.statusCode,r.headers??{})){r.resume(),b&&clearTimeout(b),_(new t(`COMMAND_FAILED`,`Remote daemon instance changed`,{reason:`remote_instance_mismatch`,daemonBaseUrl:e.baseUrl}));return}if(st(n,r.headers?.[`content-type`])){lt(r,{req:n,onProgress:a.onProgress,reject:_,clearTimeout:()=>{b&&clearTimeout(b)},handleResponseBody:v});return}te(r).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId,reason:`daemon_response_read_failure`},e instanceof Error?e:void 0)}).then(e=>{b&&clearTimeout(b),v(e)}).catch(e=>{b&&clearTimeout(b),_(e)})}),ee=W(e),b=typeof i==`number`?setTimeout(()=>{_(Z(i,n.meta?.requestId)),y.destroy()},i):void 0,x=()=>{p||(b&&clearTimeout(b),_(G(d,m?`unknown`:`no`,n.meta?.requestId)),y.destroy())};d&&d.addEventListener(`abort`,x,{once:!0}),y.on(`error`,e=>{b&&clearTimeout(b),!p&&_(mn(e,n.meta?.requestId,ee))}),y.write(c),y.end(),m=!0})}let Q;function bn(e,t){return e.baseUrl===t.baseUrl&&e.token===t.token&&e.pid===t.pid}function xn(e,t){!t.instanceId||t.upstream&&!t.upstream.instanceId||(Q={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:Promise.resolve(t)})}function $(e){Q&&bn(Q,e)&&(Q=void 0)}async function Sn(e){if(Q&&bn(Q,e))return await Q.health;let t={baseUrl:e.baseUrl??``,token:e.token,pid:e.pid,health:Xt(e)};Q=t;try{let e=await t.health;return(!e.reachable||!e.instanceId||e.upstream&&!e.upstream.instanceId)&&Q===t&&(Q=void 0),e}catch(e){throw Q===t&&(Q=void 0),e}}export{rn as a,Mt as c,Gt as i,zt as l,Kt as n,Rt as o,Ht as r,W as s,Sn as t,Be as u};
|
package/dist/src/daemon-http.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
import e from"node:path";const t=`/agent-device`,n=`x-agent-device-tenant`,r=`x-agent-device-network-access`,i=`public-only`;function a(e){return o(e,t)}function o(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(t.replace(/^\/+/,``),n).toString()}function s(e){let t=e?.trim();return t?{authorization:`Bearer ${t}`,"x-agent-device-token":t}:{}}function c(e){let t=e?.trim();return t?{[n]:t}:{}}const l=`x-agent-device-instance`,u=`x-agent-device-upstream-instance`,d=`x-agent-device-instance-mismatch`;function f(e,t,n){return{jsonrpc:`2.0`,id:e,error:{code:-32001,message:t,data:n}}}function p(e,t,n={}){return{ok:!0,service:e,version:t,rpcProtocolVersion:2,...n.instanceId===void 0?{}:{instanceId:n.instanceId},...n.hostArch===void 0?{}:{hostArch:n.hostArch},...n.leaseBackends===void 0?{}:{leaseBackends:n.leaseBackends},...n.upstream===void 0?{}:{upstream:n.upstream}}}const m=`/tmp`;function h(t,n){return e.posix.join(m,`${y(t)}${v(n)}`)}function g(t){return e.posix.join(m,y(t))}function _(t,n,r){let i=v(r),a=e.posix.basename(t,i);return t===e.posix.join(m,`${a}${i}`)&&a.startsWith(`agent-device-${n}-`)&&/^\d+-[a-z0-9]+$/.test(a.slice(`agent-device-${n}-`.length))}function v(e){return e.startsWith(`.`)?e:`.${e}`}function y(e){return`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}export{i as a,p as c,c as d,o as f,_ as g,h,r as i,s as l,g as m,l as n,n as o,f as p,d as r,u as s,t,a as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{P as
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{H as t,P as n}from"./sdk-contracts.js";import{f as r}from"./sdk-batch.js";import i from"node:crypto";import a from"node:fs";import o from"node:path";var s=e({DAEMON_POLICY_ENV:()=>c,loadDaemonPolicy:()=>_,parseDaemonPolicy:()=>v,resolveDaemonPolicyCommandName:()=>h});const c=`AGENT_DEVICE_DAEMON_POLICY`,l=[`device-shutdown`],u=r,d=new Set(u.filter(e=>e.catalog.group===`internal`&&e.daemon!==void 0&&e.platformExecution.kind===`none`).map(e=>e.name)),f=new Map(u.flatMap(e=>{let{group:t,servesPublicCommand:n}=e.catalog;return t===`public`?[[e.name,e.name]]:t!==`internal`||d.has(e.name)?[]:[[e.name,n??e.name]]})),p=new Set(f.values()),m=new Set(u.filter(e=>e.catalog.group===`local-cli`).map(e=>e.name));function h(e){if(!d.has(e))return f.get(e)??e}const g=new Set([`version`,`devices`,`commands`,`capabilities`,`leases`]);function _(e=process.env){let n=e[c]?.trim();if(!n)return;let r=o.resolve(n),i;try{i=JSON.parse(a.readFileSync(r,`utf8`))}catch(e){throw E(r,`cannot read policy JSON: ${t(e)}`)}return v(i,r)}function v(e,t){let n=C(e,`policy`,t);for(let e of Object.keys(n))if(!g.has(e))throw E(t,`unknown key "${e}"`);if(n.version!==1)throw E(t,`"version" must be 1`);let r=n.devices===void 0?void 0:y(n.devices,t),a=n.commands===void 0?void 0:b(n.commands,t),o=n.capabilities===void 0?new Set:x(n.capabilities,t),s=n.leases===void 0?void 0:S(n.leases,t),c=JSON.stringify({devices:r?[...r].sort():null,commands:a?{mode:a.mode,names:[...a.names].sort()}:null,capabilities:[...o].sort(),...s?{leases:{require:s}}:{}});return Object.freeze({sourcePath:t,digest:i.createHash(`sha256`).update(c).digest(`hex`),deviceIds:r,commands:a,deniedCapabilities:o,...s?{requiredLeaseBackend:s}:{}})}function y(e,t){let n=C(e,`devices`,t);T(n,[`allow`],`devices`,t);let r=w(n.allow,`devices.allow`,t);if(r.length===0)throw E(t,`"devices.allow" must not be empty`);return new Set(r.map((e,n)=>{let r=`devices.allow[${n}]`,i=C(e,r,t);T(i,[`udid`,`serial`],r,t);let a=[i.udid,i.serial].filter(e=>e!==void 0);if(a.length!==1||typeof a[0]!=`string`||!a[0].trim())throw E(t,`"${r}" must name exactly one "udid" or "serial"`);return a[0].trim()}))}function b(e,t){let n=C(e,`commands`,t);if(T(n,[`allow`,`deny`],`commands`,t),n.allow===void 0==(n.deny===void 0))throw E(t,`"commands" must set exactly one of "allow" or "deny"`);let r=n.allow===void 0?`deny`:`allow`,i=`commands.${r}`,a=w(n[r],i,t).map(e=>{if(typeof e==`string`&&m.has(e))throw E(t,`"${i}" names ${JSON.stringify(e)}, which runs in the client; name the daemon command it sends, such as "runtime"`);if(typeof e!=`string`||!p.has(e))throw E(t,`"${i}" names unknown command ${JSON.stringify(e)}`);return e});return Object.freeze({mode:r,names:new Set(a)})}function x(e,t){let n=C(e,`capabilities`,t);T(n,[`deny`],`capabilities`,t);let r=l;return new Set(w(n.deny,`capabilities.deny`,t).map(e=>{if(typeof e!=`string`||!r.includes(e))throw E(t,`"capabilities.deny" names unknown capability ${JSON.stringify(e)}`);return e}))}function S(e,t){let n=C(e,`leases`,t);if(T(n,[`require`],`leases`,t),n.require!==`macos-app`)throw E(t,`"leases.require" must be macos-app`);return n.require}function C(e,t,n){if(typeof e==`object`&&e&&!Array.isArray(e))return e;throw E(n,`"${t}" must be an object`)}function w(e,t,n){if(Array.isArray(e))return e;throw E(n,`"${t}" must be an array`)}function T(e,t,n,r){for(let i of Object.keys(e))if(!t.includes(i))throw E(r,`unknown key "${n}.${i}"`)}function E(e,t){return new n(`INVALID_ARGS`,`Invalid daemon policy ${e}: ${t}`,{policyPath:e,hint:`Fix the file named by ${c}, then start the daemon again.`})}export{_ as n,h as r,s as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{J as t,P as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{J as t,P as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{S as o,j as s,m as c,o as l,r as u,w as d,x as f}from"./owner-identity.js";import{f as p}from"./exec.js";import{i as m}from"./retry.js";import{i as h,n as g,r as _}from"./file.js";import"./command.js";import"./process.js";import{t as v}from"./daemon-resolution.js";import"./retry2.js";import{n as y}from"./session-repair-tombstone.js";import{i as b,n as x,r as S}from"./daemon-registration.js";import{r as C,t as w}from"./daemon-shutdown-report.js";import T from"node:fs";import E from"node:os";import D from"node:path";async function O(e,t){let{logPath:n,command:a=`daemon`,debug:o=!0}=e;return await i({command:a,session:`daemon`,logPath:n,debug:o},async()=>{try{return await t()}finally{r({force:!0})}})}const k=[/\/dist\/src\/daemon\.js($|[\s"'])/,/\/dist\/src\/internal\/daemon\.js($|[\s"'])/,/\/src\/daemon\.ts($|[\s"'])/];function A(e){let t=e.toLowerCase().replaceAll(`\\`,`/`);return k.some(e=>e.test(t))}function ee(e,t){if(!t||!c(e))return!1;let n=d(e);if(!n||n!==t)return!1;let r=o(e);return r?A(r):!1}function te(e,t){try{return process.kill(e,t),!0}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return!1;throw e}}async function j(e,t){if(!u(e.pid))return{exited:!1,elapsedMs:0};let n=Date.now(),r=n+t.timeoutMs,i=t.pollMs??100,a=()=>{if(!c(e.pid))return!0;let t=f([e.pid]).get(e.pid);return!!(t?.state.startsWith(`Z`)||t?.startTime&&t.startTime!==e.startTime)},o=a();for(;!o&&Date.now()<r;)await m(Math.min(i,Math.max(0,r-Date.now()))),o=a();return{exited:o,elapsedMs:Date.now()-n}}async function M(e,t){if(!u(e.pid))return{status:`retained`,reason:`identity-unverified`};if(!e.startTime?.trim())return c(e.pid)?{status:`retained`,reason:`missing-start-time`}:{status:`not-running`};let n={pid:e.pid,startTime:e.startTime};if((await j(n,{timeoutMs:0})).exited)return{status:`exited`,identity:n,mode:`already-exited`};let r;if(t.mode===`graceful`){let e=await N(n,{signal:`SIGTERM`,timeoutMs:t.termTimeoutMs});if(e.status!==`survived`)return e;r=`SIGTERM`}let i=await N(n,{signal:`SIGKILL`,timeoutMs:t.killTimeoutMs,previousSignal:r});return i.status===`survived`?{status:`retained`,reason:`exit-timeout`}:i}async function N(e,t){let n=ee(e.pid,e.startTime),r=n&&te(e.pid,t.signal),i=r?t.signal===`SIGTERM`?`graceful`:`forced`:t.previousSignal?`graceful`:`already-exited`;return(await j(e,{timeoutMs:i===`already-exited`?0:t.timeoutMs})).exited?{status:`exited`,identity:e,mode:i}:r?{status:`survived`}:{status:`retained`,signal:t.signal,reason:n?`signal-failed`:`identity-unverified`}}var P=e({DAEMON_STARTUP_EXIT_CODES:()=>F,createOwnedReplayStateDir:()=>U,launchDaemonProcess:()=>W,recoverAbandonedDaemonRegistration:()=>X,stopAndRetireDaemon:()=>q,tryAcquireDaemonRegistration:()=>I});const F=Object.freeze({busy:75,unproven:78});async function I(e){let t={...e},n=l(),r=h({lockDirPath:t.lockPath,owner:{...n,acquiredAtMs:Date.now()},description:`daemon registration`});if(r.status!==`acquired`)return r;let{acquisition:i}=r;try{i.assertHeld(),T.rmSync(C(t.baseDir),{force:!0})}catch(e){await R(i,e,t.logPath)}return{status:`acquired`,owner:Object.freeze({publish({socketPort:e,httpPort:r,...a}){i.assertHeld(),B(t.logPath);let o=e&&r?`dual`:r?`http`:`socket`;i.assertHeld(),s({destination:t.infoPath,contents:JSON.stringify({...a,port:e,httpPort:r,transport:o,pid:n.pid,processStartTime:n.startTime??void 0,stateDir:t.baseDir},null,2),mode:384})},async finish(e){let r;try{e&&z(t.baseDir,e,i),r=L(t.infoPath,n,i)}catch(e){return await R(i,e,t.logPath)}return await i.release(),r}})}}function L(e,t,n){n.assertHeld();let r=b(e,t);if(r.state!==`match`)return r;n.assertHeld();try{T.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)throw e}return{state:`removed`}}async function R(e,t,n){try{await e.release()}catch(e){await Q(n,`daemon_registration_release_failed`,e)}throw t}function z(e,t,n){let r=C(e),i=`${JSON.stringify(w(t))}\n`;n.assertHeld();try{s({destination:r,contents:i,mode:384})}catch{return}}function B(e){if(process.platform===`win32`){V(e);return}let t=T.openSync(e,`a`,384);try{T.ftruncateSync(t,0)}finally{T.closeSync(t)}}function V(e){let t;try{t=T.openSync(e,`r+`,384)}catch(n){if(n.code!==`ENOENT`)throw n;T.closeSync(T.openSync(e,`a`,384)),t=T.openSync(e,`r+`,384)}try{T.ftruncateSync(t,0)}finally{T.closeSync(t)}}const H=new WeakMap;function U(){let e=Object.freeze(v(T.mkdtempSync(D.join(E.tmpdir(),`agent-device-replay-daemon-`)))),t=Object.freeze({paths:e});return H.set(t,{paths:e,startups:[],sealed:!1}),t}function W(e){let t=e.ownedStateDir&&K(e.ownedStateDir,e.paths);if(t?.sealed)throw new n(`COMMAND_FAILED`,`Replay daemon startup admission is closed.`,{reason:`daemon_startup_admission_closed`});T.mkdirSync(e.paths.baseDir,{recursive:!0});let r=T.openSync(e.paths.logPath,`a`);try{let n=p(process.execPath,e.args,{env:{...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode},stdio:[`ignore`,r,r]}),i={...e.paths},a={launch:Object.freeze({...n,get startTime(){return a.startTime},readIdentity(){return G(i,a),{pid:n.pid,startTime:a.startTime??null}}}),joined:!1};return t&&t.startups.push(a),n.exited.then(()=>{a.joined=!0}),a.startTime=d(n.pid)??void 0,a.launch}finally{T.closeSync(r)}}function G(e,t){if(t.startTime||t.joined)return;let n=S(e.infoPath);if(n?.pid!==t.launch.pid||!n.startTime)return;let r=_(e.lockPath);x(r,n)&&(t.startTime=n.startTime)}function K(e,t){let r=H.get(e);if(!r||Object.entries(r.paths).some(([e,n])=>t[e]!==n))throw new n(`COMMAND_FAILED`,`Private replay directory ownership could not be verified.`,{reason:`daemon_private_state_unowned`});return r}async function q(e){let n,r=e.observed;try{if(e.ownedStateDir&&(n=K(e.ownedStateDir,e.paths),n.sealed=!0,r=J(n,r),n.retirement))return await n.retirement}catch(r){return await $(n,e.startupJoinTimeoutMs??1e3),{status:`retained`,reason:`ownership-unproven`,removedInfo:!1,error:t(r)}}let i=Z({...e,observed:r},t=>M(t,{mode:e.mode,termTimeoutMs:e.termTimeoutMs??3e3,killTimeoutMs:e.killTimeoutMs??1e3}),n,e.startupJoinTimeoutMs??1e3);n&&(n.retirement=i);let a=await i;return n&&(a.status===`absent`||!a.removedStateDir)&&(n.retirement=void 0),a}function J(e,t){if(!t){if(e.startups.length===0)return null;throw Y()}let n=e.startups.find(({launch:e})=>e.pid===t.pid);if(!n)throw Y();let{launch:r}=n,i=t.startTime?t:r.readIdentity();if(r.startTime&&r.startTime===i.startTime)return i;throw Y()}function Y(){return new n(`COMMAND_FAILED`,`The observed daemon is not an owned startup lifetime.`,{reason:`daemon_private_startup_unowned`})}async function X(e){return await Z(e,async e=>{if(!e.startTime?.trim())return{status:`retained`,reason:`missing-start-time`};let t={pid:e.pid,startTime:e.startTime};return(await j(t,{timeoutMs:0})).exited?{status:`exited`,identity:t,mode:`already-exited`}:{status:`retained`,reason:`identity-unverified`}})}async function Z(e,n,r,i=1e3){let a={...e.paths},o=e.observed&&{...e.observed},s,c;if(o)try{s=await n(o)}catch(e){c=t(e)}let l=await $(r,i);return c?{status:`retained`,reason:`stop-failed`,removedInfo:!1,error:c}:s&&s.status!==`exited`?{status:`retained`,reason:`exit-unconfirmed`,termination:s,removedInfo:!1}:l?await ne({...e,paths:a},s,r):{status:`retained`,reason:`startup-unconfirmed`,termination:s,removedInfo:!1}}async function ne(e,n,r){let i=e.paths,a;try{a=await g({lockDirPath:i.lockPath,owner:{...l(),acquiredAtMs:Date.now()},description:`daemon registration retirement`,timeoutMs:e.lockTimeoutMs??1e3})}catch(e){let r=t(e);return{status:`retained`,reason:r.details?.reason===`process_lock_timeout`?`lock-busy`:`retirement-unconfirmed`,termination:n,removedInfo:!1,error:r}}let o={status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1};try{o=ie(L(i.infoPath,n?.identity??null,a),n),o=ae(r,a,o)}catch(e){o={status:`retained`,reason:`retirement-unconfirmed`,termination:n,removedInfo:o.removedInfo,error:t(e)}}return await re(a,o,i.logPath)}async function re(e,n,r){try{await e.release()}catch(e){let i=n.status===`retained`?n.error:void 0;i&&await Q(r,`daemon_retirement_release_failed`,e),n={...n,status:`retained`,reason:`retirement-unconfirmed`,error:i??t(e)}}return n}function ie(e,t){return t&&(e.state===`removed`||e.state===`absent`)?{status:`retired`,termination:t,removedInfo:e.state===`removed`}:e.state===`absent`?{status:`absent`,removedInfo:!1}:{status:`retained`,termination:t,removedInfo:!1,reason:e.state===`replaced`?`registration-replaced`:e.state===`unreadable`?`metadata-unreadable`:`ownership-unproven`}}async function Q(e,n,r){await O({logPath:e},()=>{a({level:`warn`,phase:n,data:{error:t(r)}})})}async function $(e,t){if(!e||e.startups.every(e=>e.joined))return!0;let n;try{return await Promise.race([Promise.all(e.startups.map(({launch:e})=>e.exited)).then(()=>!0),new Promise(e=>{n=setTimeout(()=>e(!1),t)})])}finally{n&&clearTimeout(n)}}function ae(e,n,r){if(!e||r.status!==`retired`&&(r.status!==`absent`||e.startups.length!==0))return r;try{n.assertHeld();let t=y(e.paths.sessionsDir);return t?r.status===`retired`?{...r,removedStateDir:!1,repairCommitFailure:t}:{status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1,removedStateDir:!1,repairCommitFailure:t}:(n.assertHeld(),T.rmSync(e.paths.baseDir,{recursive:!0,force:!0}),{...r,removedStateDir:!0})}catch(e){return{...r,status:`retained`,reason:`retirement-unconfirmed`,removedStateDir:!1,error:t(e)}}}export{X as a,O as c,W as i,U as n,q as o,P as r,I as s,F as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{v as e}from"./sdk-batch-runner.js";import{o as t,w as n,y as r}from"./sdk-device.js";import{Zt as i}from"./sdk-batch.js";import{n as a,x as o}from"./owner-identity.js";import"./process.js";import{t as s}from"./daemon-registration.js";import{r as c}from"./durable-resource.js";import"./src7.js";import l from"node:crypto";import u from"node:fs";import d from"node:os";import f from"node:path";function p(e){return m(`family`in e?e.family:e.platform,e.appleOs,e.id)}function m(e,t,n){return`local:${e}:${t??`none`}:${n}`}function h(){let e=process.env.AGENT_DEVICE_CLAIMS_DIR?.trim();return e?f.resolve(e):f.join(d.homedir(),`.agent-device`,`device-claims`)}function g(e){let t=l.createHash(`sha256`).update(e).digest(`hex`);return f.join(h(),`${t}.json`)}function _(e){return{deviceKey:e.deviceKey,ownerToken:e.ownerToken,ownerPid:e.ownerPid,ownerStartTime:e.ownerStartTime}}function v(e){return e.schemaVersion===3}function y(e){return i(e.allocator.instanceId)}function b(t){return e(t)?t.schemaVersion===3?C(t):t.schemaVersion===2?O(t):t.schemaVersion===1?k(t):null:null}function x(t){return e(t)&&t.schemaVersion===3}const S=[`ownerPid`,`ownerStartTime`,`ownerToken`,`session`,`workspace`,`abandonedAtMs`];function C(e){if(e.kind!==`allocator`||w(e))return null;let t=T(e);return t&&{schemaVersion:3,kind:`allocator`,...t}}function w(e){return S.some(t=>e[t]!==void 0)}function T(t){if(!e(t.device)||!P(t.device.name))return null;let n=t.device.name,r=c(t.device),i=F(t.deviceKey),a=F(t.stateDir),o=E(t.allocator),s=N(t);return!r||!i||!a||!o||!s||i!==p(r)?null:{deviceKey:i,device:{...r,name:n},stateDir:a,allocator:o,createdAtMs:s.createdAtMs,updatedAtMs:s.updatedAtMs}}function E(t){if(!e(t))return null;let n=D(t.instanceId),r=D(t.identityIncarnationId);return n&&r?{instanceId:n,identityIncarnationId:r}:null}function D(e){return P(e)&&e===e.trim()?e:null}function O(t){if(!e(t.device)||!P(t.device.name))return null;let n=c(t.device);return n?A(t,n,t.device.name):null}function k(n){if(!e(n.device))return null;let i=n.device,a=i.name;if(!P(a)||!r(i.platform))return null;let o=t(i.platform),s=c({id:i.id,family:o.platform,kind:i.kind,target:i.target,...i.appleOs===void 0?o.platform===`apple`?{appleOs:i.platform===`macos`?`macos`:`ios`}:{}:{appleOs:i.appleOs},...i.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:i.iosPhysicalDeviceBackend}});return s?A(n,s,a):null}function A(e,t,n){let r=j(e),i=M(e),a=N(e);return!r||!i||!a||r.deviceKey!==p(t)?null:{schemaVersion:2,...r,device:{...t,name:n},...i,...a}}function j(e){let t=F(e.deviceKey),n=F(e.session),r=F(e.workspace),i=F(e.stateDir);return!t||!n||!r||!i?null:{deviceKey:t,session:n,workspace:r,stateDir:i}}function M(e){let{ownerPid:t,ownerStartTime:n}=e,r=F(e.ownerToken);return!I(t)||!r||n!==null&&!P(n)?null:{ownerPid:t,ownerStartTime:n,ownerToken:r}}function N(e){let{createdAtMs:t,updatedAtMs:n,abandonedAtMs:r}=e;return!L(t)||!L(n)||r!==void 0&&!L(r)?null:{createdAtMs:t,updatedAtMs:n,...L(r)?{abandonedAtMs:r}:{}}}function P(e){return typeof e==`string`&&e.length>0}function F(e){return P(e)?e:null}function I(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function L(e){return typeof e==`number`&&Number.isFinite(e)}function R(e){let t=h(),n=z(t);if(`claims`in n)return n.claims;let r=n.entries.filter(e=>e.isFile()&&e.name.endsWith(`.json`)).map(e=>K(f.join(t,e.name))).filter(e=>e!==null).filter(t=>B(t.claim??t.allocatorClaim,e)),i=o(r.flatMap(e=>e.claim?[e.claim.ownerPid]:[]));return r.map(e=>e.claim?J(e,i.get(e.claim.ownerPid)??null):e)}function z(e){try{return{entries:u.readdirSync(e,{withFileTypes:!0})}}catch(t){let n=t.code;return n===`ENOENT`||n===`ENOTDIR`?{claims:[]}:{claims:[{fileName:f.basename(e),classification:`unknown`,error:String(t)}]}}}function B(e,t){return!e||[V(e,t.udid??t.serial),H(e,t.device),U(e,t.platform)].every(Boolean)}function V(e,t){return!t||e.device.id===t}function H(e,t){return!t||e.device.name===t||e.device.id===t}function U(e,t){return n({platform:e.device.family,appleOs:e.device.appleOs},t)}function W(e){let t=K(e);return t?.claim?J(t,o([t.claim.ownerPid]).get(t.claim.ownerPid)??null):t}function G(e){let t=K(e);return t?.allocatorClaim||t?.classification===`allocator-inconsistent`?t:null}function K(e){let t=f.basename(e);try{return q(t,u.readFileSync(e,`utf8`))}catch(e){let n=e.code;return n===`ENOENT`||n===`ENOTDIR`?null:{fileName:t,classification:`unknown`,error:String(e)}}}function q(e,t){try{let n=JSON.parse(t),r=b(n);return r?v(r)?{fileName:e,deviceKey:r.deviceKey,allocatorClaim:r,classification:`allocator-held`}:{fileName:e,deviceKey:r.deviceKey,claim:r,classification:`unknown`}:{fileName:e,classification:x(n)?`allocator-inconsistent`:`inconsistent`}}catch(t){return{fileName:e,classification:`inconsistent`,error:String(t)}}}function J(e,t){let n=e.claim;if(!n)return e;let r={pid:n.ownerPid,startTime:n.ownerStartTime},i=a({owner:r,stateDir:n.stateDir},t),o=i===`live`&&s({...r,stateDir:n.stateDir});return{...e,classification:o?`owner-daemon-superseded`:i}}function Y(e){switch(e){case`owner-process-dead`:case`owner-process-reused`:case`owner-state-dir-gone`:case`owner-daemon-superseded`:return!0;case`live`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}function X(e){switch(e){case`owner-process-dead`:case`owner-daemon-superseded`:return!0;case`live`:case`owner-process-reused`:case`owner-state-dir-gone`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}export{G as a,p as c,R as i,g as l,Y as n,y as o,W as r,_ as s,X as t,h as u};
|
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { j as Rect } from "./sdk-contracts.js";
|
|
2
2
|
import { a as PointerTrajectorySample, i as PointerTrajectory, o as SinglePointerGesturePlan, r as MultiTouchGesturePlan } from "./gesture-plan-types.js";
|
|
3
3
|
import { Readable, Stream, Writable } from "node:stream";
|
|
4
|
-
//#region packages/contracts/src/app-state-runtime.d.ts
|
|
5
|
-
/** Neutral foreground identity returned by a selected platform/provider runtime. */
|
|
6
|
-
type AppStateRuntimeResult = Readonly<{
|
|
7
|
-
package?: string;
|
|
8
|
-
activity?: string;
|
|
9
|
-
/**
|
|
10
|
-
* Apple: how the app named by the input is running, as a live runner reads it. It says nothing
|
|
11
|
-
* about which app is frontmost; a session app in a background state has left the foreground.
|
|
12
|
-
* Absent when no runner session is live to ask, so the read never starts one.
|
|
13
|
-
*/
|
|
14
|
-
applicationState?: AppleApplicationState;
|
|
15
|
-
}>;
|
|
16
|
-
//#endregion
|
|
17
4
|
//#region packages/platform-android/src/helper-artifacts.d.ts
|
|
18
5
|
type AndroidImeHelperManifest = {
|
|
19
6
|
name: 'android-ime-helper';
|
|
@@ -224,4 +211,4 @@ declare function dismissAndroidKeyboardWithAdb(adb: AndroidAdbExecutor): Promise
|
|
|
224
211
|
declare function readAndroidClipboardWithAdb(adb: AndroidAdbExecutor): Promise<string>;
|
|
225
212
|
declare function writeAndroidClipboardWithAdb(adb: AndroidAdbExecutor, text: string): Promise<void>;
|
|
226
213
|
//#endregion
|
|
227
|
-
export { readAndroidClipboardWithAdb as a, AndroidAdbExecutor as c, AndroidAdbProvider as d, AndroidPortReverseEndpoint as f, getAndroidKeyboardStatusWithAdb as i, AndroidAdbExecutorOptions as l,
|
|
214
|
+
export { readAndroidClipboardWithAdb as a, AndroidAdbExecutor as c, AndroidAdbProvider as d, AndroidPortReverseEndpoint as f, getAndroidKeyboardStatusWithAdb as i, AndroidAdbExecutorOptions as l, AndroidKeyboardState as n, writeAndroidClipboardWithAdb as o, AndroidPortReverseProvider as p, dismissAndroidKeyboardWithAdb as r, AndroidInputOwner as s, AndroidKeyboardDismissResult as t, AndroidAdbExecutorResult as u };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v as e}from"./sdk-batch-runner.js";import{
|
|
1
|
+
import{v as e}from"./sdk-batch-runner.js";import{g as t,h as n}from"./sdk-device.js";import{r}from"./recording-export-quality.js";import{n as i}from"./recording-scope.js";import{i as a,n as o}from"./recording-stop-observation.js";import{t as s}from"./screen-recording-completion.js";import{t as c}from"./artifact-paths.js";async function l(e,t){try{return await e()}catch{if(t?.aborted)throw t.reason;return!1}}function u(e){return e.exitCode===0}function d(e){return process.platform===`darwin`&&(t(e)||n(e)&&e.kind===`simulator`||e.platform===`android`&&e.kind===`emulator`)}const f=[`scope`,`showTouches`,`recordOnlySession`,`activeSessionApp`,`exportQuality`,`fps`];function p(e){return i(e.scope)&&typeof e.showTouches==`boolean`&&typeof e.recordOnlySession==`boolean`&&(e.exportQuality===void 0||r(e.exportQuality))&&m(e.fps)&&h(e.activeSessionApp)}function m(e){return e===void 0||typeof e==`number`&&Number.isInteger(e)&&e>0}function h(t){return t===void 0?!0:!e(t)||!g(t.bundleId)?!1:t.name===void 0||g(t.name)}function g(e){return typeof e==`string`&&e.length>0}function _(e){return e.exportPath===void 0?e.observation===void 0||e.observation.recorder===`unconfirmed`:!1}const v=`stopObservation`,y=`stoppedAtMs`,b=`stopRecorderWarning`,x=`collectedPath`,S=`exportPath`,C=`stopFinalization`,w=Symbol(`unreadable`),T={telemetryPath:M(),warning:M(),overlayWarning:M(),nativePathDisposition:{encode:e=>e,read:e=>e===void 0?void 0:a(e)?e:w},chunks:{encode:e=>e.map(N),read:e=>e===void 0?void 0:P(e)??w},capturedDurationMs:{encode:e=>e,read:e=>e===void 0?void 0:I(e)?e:w}};function E(e){return{...e.observation===void 0?{}:{[v]:O(e.observation)},...e.stoppedAtMs===void 0?{}:{[y]:e.stoppedAtMs},...e.recorderWarning===void 0?{}:{[b]:e.recorderWarning},...e.collectedPath===void 0?{}:{[x]:e.collectedPath},...e.exportPath===void 0?{}:{[S]:e.exportPath},...e.finalization===void 0?{}:{[C]:k(e.finalization)}}}function D(e){let t=e?.[v],n=e?.[y],r=L(e?.[b]),i=L(e?.[x]),a=L(e?.[S]),s=A(e?.[C]);return{...o(t)?{observation:t}:{},...I(n)?{stoppedAtMs:n}:{},...r===void 0?{}:{recorderWarning:r},...i===void 0?{}:{collectedPath:i},...a===void 0?{}:{exportPath:a},...s===void 0?{}:{finalization:s}}}function O(e){return e.recorder===`confirmed`?{recorder:e.recorder}:{recorder:e.recorder,why:e.why}}function k(e){let t={};for(let n of j()){let r=e[n];r!==void 0&&(t[n]=T[n].encode(r))}return t}function A(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e,n={};for(let e of j()){let r=T[e].read(t[e]);if(r===w)return;r!==void 0&&(n[e]=r)}return Object.keys(n).length===0?void 0:n}function j(){return Object.keys(T)}function M(){return{encode:e=>e,read:L}}function N(e){return{index:e.index,path:e.path,...e.clientOutPath===void 0?{}:{clientOutPath:e.clientOutPath}}}function P(e){if(!Array.isArray(e))return;let t=e.map(F);return t.every(e=>e!==void 0)?t:void 0}function F(e){if(typeof e!=`object`||!e)return;let{index:t,path:n,clientOutPath:r}=e,i=L(n),a=L(r);if(!(!Number.isInteger(t)||t<1||i===void 0)&&(r===void 0||a!==void 0))return{index:t,path:i,...a===void 0?{}:{clientOutPath:a}}}function I(e){return typeof e==`number`&&Number.isFinite(e)&&e>=0}function L(e){return typeof e==`string`&&e.length>0?e:void 0}async function R(e){let{steps:t,snapshot:n,progress:r,now:i=Date.now}=e,a=D(r?.learned),o=a.observation,l=a.recorderWarning,u=a.stoppedAtMs;if(_(a)){u=i();let e=await t.stop();o=e.observation,l=e.warning,r?.record(E({observation:o,stoppedAtMs:u,recorderWarning:e.warning}))}if(o===void 0)throw Error(`record stop reached collection without an observation of its recorder and a committed export`);let d=a.collectedPath??c(n.outPath);a.collectedPath===void 0&&(await t.collect(d),r?.record(E({collectedPath:d})));let f=a.finalization??await t.finalize({collectedPath:d,exportPath:n.outPath,stoppedAtMs:u??i()});r?.record(E({exportPath:n.outPath,finalization:f})),await t.discard(d);let{nativePathDisposition:p,warning:m,...h}=f,g=[m,l].filter(e=>e!==void 0&&e.length>0);return s(n,{...h,...g.length===0?{}:{warning:g.join(` `)}},{stopObservation:o,...p===void 0?{}:{nativePathDisposition:p}})}const z=`boot_timeout`;export{p as a,l as c,f as i,R as n,d as o,D as r,u as s,z as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{P as t}from"./sdk-contracts.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{P as t}from"./sdk-contracts.js";import{C as n,b as r,h as i,k as a,u as o}from"./sdk-device.js";var s=e({markSelectionBootOccurred:()=>u,resolveExistingSessionDeviceSelection:()=>l,resolveInventoryDeviceSelection:()=>c});async function c(e){let{devices:t,selector:r,source:i}=e,s=o(r);if(i===`provider`&&!s)return p(t,r);if(i===`local`&&!s){let n=await m(t,r,e.appleSimulatorAppTarget);if(n)return n}let c=t.filter(e=>n(e,r,{includeExplicitSelectors:s}));try{return d(await a([...t],r),c,{explicitSelector:s,source:i})}catch(e){throw h(e,c)}}function l(e){return{device:e,reason:`existing-session`,source:`session`,candidateCount:1,bootOccurred:!1}}function u(e){if(!e||e.source!==`local`)return e;let{device:t}=e;return t.booted!==!0&&(t.kind===`simulator`||t.kind===`emulator`)?{...e,bootOccurred:!0}:e}function d(e,t,n){return{device:e,reason:n.explicitSelector?`explicit-selector`:n.source===`provider`?`single-provider-device`:f(e,t),source:n.source,candidateCount:t.length,bootOccurred:!1}}function f(e,t){return e.booted===!0&&t.filter(e=>e.booted===!0).length===1?`single-booted-local`:!e.booted&&t.length===1?`single-bootable-local`:`preferred-local`}async function p(e,r){let i=e.filter(e=>n(e,r)),o=i[0];if(o!==void 0&&i.length===1)return d(o,i,{explicitSelector:!1,source:`provider`});try{await a([...e],r)}catch(e){throw h(e,i)}throw new t(`AMBIGUOUS_MATCH`,`Multiple provider devices match this request.`,{...g(i),matches:i.length,hint:`Select the leased provider device explicitly with --device, --udid, or --serial.`,retrySelectors:_(i)})}async function m(e,r,a){let o=a?.trim();if(!o)return;let{readInstalledAppProbe:s}=await import(`./device-inventory-context.js`).then(e=>e.t),c=s();if(!c)return;let l=e.filter(e=>n(e,r)&&i(e)&&e.kind===`simulator`&&e.booted===!0);if(l.length<2)return;let u=(await Promise.all(l.map(async e=>await c(e,o)?e:void 0))).filter(e=>e!==void 0),d=u[0];if(d!==void 0&&u.length===1)return{device:d,reason:`single-app-installed-local`,source:`local`,candidateCount:1,bootOccurred:!1};throw u.length===0?new t(`APP_NOT_INSTALLED`,`No booted iOS simulator has ${o} installed`,{appTarget:o,...g(l),hint:`Install the app on a booted simulator, or pass --udid to select the intended device explicitly.`,retrySelectors:_(l)}):new t(`AMBIGUOUS_MATCH`,`Multiple booted iOS simulators have ${o} installed`,{appTarget:o,...g(u),hint:`Pass --udid to select the intended simulator explicitly.`,retrySelectors:_(u)})}function h(e,n){return!(e instanceof t)||e.code!==`AMBIGUOUS_MATCH`?e:new t(e.code,e.message,{...e.details??{},...g(n),retrySelectors:_(n)},e)}function g(e){return{devices:e.slice(0,10).map(e=>({id:e.id,name:e.name}))}}function _(e){return e.slice(0,10).flatMap(e=>[{flag:r(e.platform)?`--serial`:`--udid`,value:e.id},{flag:`--device`,value:e.name}])}export{u as n,l as r,s as t};
|