agent-device 0.20.6 → 0.20.7
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 +3 -3
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.apk → agent-device-android-ime-helper-0.20.7.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.manifest.json → agent-device-android-ime-helper-0.20.7.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.apk → agent-device-android-snapshot-helper-0.20.7.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.manifest.json → agent-device-android-snapshot-helper-0.20.7.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +67 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +339 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +31 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +29 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +7 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +100 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +57 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +18 -3
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-lifecycle2.js +2 -0
- package/dist/src/app-log-files.js +1 -0
- package/dist/src/app-log-reconnect.js +1 -0
- package/dist/src/app-log-runtime.js +4 -0
- package/dist/src/app-resolution.js +2 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -0
- package/dist/src/auth.js +2 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-grammar.js +1 -0
- package/dist/src/cli-help.js +199 -259
- package/dist/src/cli-output.js +1 -0
- package/dist/src/cli-runner.js +1 -2
- package/dist/src/cli.js +6 -16
- package/dist/src/client-metro.js +1 -1
- package/dist/src/cloud-artifacts.d.ts +2 -137
- package/dist/src/command-schema.js +3 -3
- package/dist/src/connection-runtime.js +1 -0
- package/dist/src/connection.js +5 -0
- package/dist/src/context.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -0
- package/dist/src/daemon.js +2 -0
- package/dist/src/debug-symbols.js +3 -3
- package/dist/src/device-claim-inspection.js +1 -0
- package/dist/src/device-input-state.js +2 -2
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +2 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/harmonyos.js +1 -0
- package/dist/src/helper.js +1 -1
- package/dist/src/host-process.js +2 -2
- package/dist/src/ime-lifecycle.js +7 -7
- package/dist/src/index.d.ts +43 -12
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/input-actions3.js +1 -0
- package/dist/src/install-artifact.js +1 -5
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +8 -15
- package/dist/src/inventory.js +5 -0
- package/dist/src/inventory2.js +1 -0
- package/dist/src/inventory3.js +2 -0
- package/dist/src/inventory4.js +1 -0
- package/dist/src/inventory5.js +1 -0
- package/dist/src/inventory6.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -0
- package/dist/src/limrun.d.ts +10 -125
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/owner-identity.js +1 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
- package/dist/src/platform-runtime-app-log-process.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -0
- package/dist/src/platform-runtime-network-web-transport.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +5 -0
- package/dist/src/platform-runtime-toolchain-host.js +1 -0
- package/dist/src/platform-runtime.js +1 -0
- package/dist/src/prepare-kind.js +15 -0
- package/dist/src/process-entry.js +1 -0
- package/dist/src/process-lock.js +1 -1
- package/dist/src/provider-webdriver.js +1 -0
- package/dist/src/provider.js +1 -0
- package/dist/src/proxy.js +2 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/registry.js +24 -24
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +3 -0
- package/dist/src/reporting.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/runtime2.js +4 -0
- package/dist/src/runtime3.js +3 -0
- package/dist/src/runtime4.js +1 -0
- package/dist/src/runtime5.js +1 -0
- package/dist/src/runtime6.js +1 -0
- package/dist/src/runtime7.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -0
- package/dist/src/sdk-android-adb.js +2 -2
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +31 -5
- package/dist/src/sdk-contracts.js +1 -1
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +280 -4
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +10 -9
- package/dist/src/shared.js +2 -0
- package/dist/src/shell-quote.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -0
- package/dist/src/snapshot-session.js +1 -0
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +2 -0
- package/dist/src/src3.js +1 -0
- package/dist/src/text-surface.js +1 -1
- package/dist/src/timing-safe-equal.js +1 -0
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +36 -20
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +6 -31
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +0 -1
- package/dist/src/app-log-request-scope.js +0 -1
- package/dist/src/devices.js +0 -1
- package/dist/src/devices2.js +0 -1
- package/dist/src/devices3.js +0 -1
- package/dist/src/devices4.js +0 -1
- package/dist/src/provider-limrun-runtime.js +0 -1
- package/dist/src/register-builtins.js +0 -1
- package/dist/src/screenshot-geometry.js +0 -1
- package/dist/src/viewport-dimension.js +0 -15
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{f as t,
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{f as t,r as n,u as r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>] [--clean]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect local advisory device ownership without daemon side effects`,description:`Inspect advisory host-local device ownership claims without starting or contacting a daemon. --stale only inspects proven-stale claims; it does not reclaim claims or clean platform resources.`},usageOverride:`device status [--platform <platform>] [--udid <udid>] [--serial <serial>] [--stale]`,listUsageOverride:`device status`,positionalArgs:[`status`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...t,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
|
|
2
2
|
|
|
3
3
|
Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ Use the /agent-device base path when connecting through cloudflared, ngrok, or a
|
|
|
9
9
|
Examples:
|
|
10
10
|
agent-device proxy --port 4310
|
|
11
11
|
cloudflared tunnel --url http://127.0.0.1:4310
|
|
12
|
-
agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`},usageOverride:`proxy [--host <host>] [--port <port>] [--daemon-auth-token <token>] [--state-dir <path>]`,listUsageOverride:`proxy`,allowedFlags:[`proxyHost`,`proxyPort`,`daemonAuthToken`,`stateDir`]},"react-devtools":{text:{summary:`Inspect components, hooks, and render profiles`,description:`Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis`},usageOverride:`react-devtools [...args]`,listUsageOverride:`react-devtools`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:
|
|
12
|
+
agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`},usageOverride:`proxy [--host <host>] [--port <port>] [--daemon-auth-token <token>] [--state-dir <path>]`,listUsageOverride:`proxy`,allowedFlags:[`proxyHost`,`proxyPort`,`daemonAuthToken`,`stateDir`]},"react-devtools":{text:{summary:`Inspect components, hooks, and render profiles`,description:`Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis`},usageOverride:`react-devtools [...args]`,listUsageOverride:`react-devtools`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},web:{text:{summary:`Manage web automation backend`,description:`Install and inspect the managed web automation backend used by --platform web.
|
|
13
13
|
|
|
14
14
|
First-run flow:
|
|
15
15
|
agent-device web setup
|
|
@@ -19,4 +19,4 @@ First-run flow:
|
|
|
19
19
|
|
|
20
20
|
Runtime web commands do not install the backend implicitly. If the managed backend is missing, run agent-device web setup. The backend is resolved only from the managed install in the effective agent-device state dir.
|
|
21
21
|
|
|
22
|
-
Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`},usageOverride:`web setup | web doctor`,listUsageOverride:`web setup|doctor`,positionalArgs:[`setup|doctor`],supportedFlags:[`stateDir`]}},o=
|
|
22
|
+
Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`},usageOverride:`web setup | web doctor`,listUsageOverride:`web setup|doctor`,positionalArgs:[`setup|doctor`],supportedFlags:[`stateDir`]}},o=n();function s(e){return Object.hasOwn(a,e)?a[e]:void 0}function c(e){return Object.hasOwn(o,e)?o[e]:void 0}const l=new Map(i().map(e=>[e.name,{supportedFlags:r}]));function u(e){if(e)return p(e)}function d(e){let t=p(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function f(t,n,r){let i=u(t);if(!t||!i||i.allowsExtraPositionals)return;let a=i.positionalArgs?.length??0;if(!(n.length<=a))throw new e(`INVALID_ARGS`,`${r?`${r} ${t}`:t} accepts at most ${a} positional argument(s), received ${n.length}: ${n.join(` `)}`)}function p(e){let t=s(e);if(t)return t;let n=l.get(e),r=c(e);if(!(!n||!r))return{...n,...r}}function m(e,t){let n=u(e);if(!n?.defaults)return!1;let r=!1;for(let[e,i]of Object.entries(n.defaults))t[e]===void 0&&(t[e]=i,r=!0);return r}export{u as i,f as n,d as r,m as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{_ as t,a as n,b as r,c as i}from"./sdk-device.js";import{Tn as a,Xt as o,Yt as s,t as c,wn as l,xn as u}from"./prepare-kind.js";import{_ as d}from"./screenshot-result.js";import{t as f}from"./sdk-remote-config.js";import{A as p,x as m}from"./sdk-android-adb.js";import{v as h}from"./url.js";import{a as g,i as _}from"./client-metro.js";import{n as ee}from"./metro2.js";import{n as te,r as v,t as ne}from"./remote-config2.js";import{a as y,i as b}from"./src3.js";import x from"node:path";import S from"node:crypto";import C from"node:fs";const w={slug:`react-devtools-companion`,runArg:h,displayName:`React DevTools companion`};async function T(e){return await _({...e,definition:w,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function E(e){return await g({...e,definition:w})}function D(e){return e===`android-instance`||e===`ios-instance`}function re(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ie(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function O(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ie(e)}function ae(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function oe(e){let t=e?.metroPublicBaseUrl?.trim();return t?ae(t):null}function se(t,n={}){if(!O(t)||!n.flags?.metroProxyBaseUrl||!D(n.flags.leaseBackend))return t;let r=oe(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function ce(e,t={}){return(await m(`npm`,re(se(e,t)),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function k(e){let t=P(e);if(!C.existsSync(t))return null;let n;try{n=JSON.parse(C.readFileSync(t,`utf8`))}catch(t){return z(e,t),null}return me(n)?n:(z(e),null)}function A(e){let t=P({stateDir:e.stateDir,session:e.state.session});C.mkdirSync(x.dirname(t),{recursive:!0}),R(t,e.state),R(F(e.stateDir),{session:e.state.session})}function j(e){return{baseUrl:pe(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function M(e){C.rmSync(P(e),{force:!0});let t=F(e.stateDir);L(e.stateDir)===e.session&&C.rmSync(t,{force:!0})}function le(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=k(t)??(t.allowActiveFallback?I({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&N(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let o=fe(i,t),s=u(i);return{runtime:i.runtime,connection:a(s),flags:{...o,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??o.daemonBaseUrl,daemonAuthToken:o.daemonAuthToken,daemonTransport:i.daemon?.transport??o.daemonTransport,daemonServerMode:i.daemon?.serverMode??o.daemonServerMode,...l(s),sessionIsolation:`tenant`,session:i.session,platform:i.platform??o.platform,target:i.target??o.target}}}function ue(e){return a(u(e))}function N(t){try{return S.createHash(`sha256`).update(C.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function P(e){return x.join(e.stateDir,`remote-connections`,`${B(e.session)}.json`)}function F(e){return x.join(e,`remote-connections`,`.active-session.json`)}function I(e){let t=L(e.stateDir);return t?k({stateDir:e.stateDir,session:t}):null}function L(e){let t=F(e);if(C.existsSync(t))try{let e=JSON.parse(C.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function de(e){if(e)return S.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function fe(e,t){try{return v({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function R(e,t){let n=`${e}.${process.pid}.${S.randomUUID()}.tmp`;try{C.writeFileSync(n,`${JSON.stringify(t,null,2)}\n`,{encoding:`utf8`,mode:384}),C.renameSync(n,e)}catch(e){throw C.rmSync(n,{force:!0}),e}}function pe(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of[...t.searchParams.keys()])/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function z(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),M(e)}function B(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${S.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function me(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&he(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ge(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&_e(t.daemon)}function he(e,t){return t.every(t=>typeof e[t]==`string`)}function ge(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function _e(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:ve(e)}function ve(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const ye=f.map(e=>e.key);function V(e){let t={};for(let n of ye){let r=e[n];r!==void 0&&(t[n]=r)}return t}function be(e){return e.remoteConfig?{...V(v({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function xe(e){return e===`cloud`||e===`proxy`||H(e)}function H(e){return e===`limrun`||y(e)}function Se(){return[`cloud`,`proxy`,b.browserStack,b.awsDeviceFarm,`limrun`].join(`, `)}function U(e){return!H(e)}function Ce(e){return e===`proxy`?`proxy`:H(e)?`direct-device-provider`:`remote-provider`}function W(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function we(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const G=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),K=new Set([`open`]),Te=new Set([o.open,o.install,o.reinstall,s.installSource]);async function Ee(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=d(r.stateDir).baseDir,o=v({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...V(o.profile),...r,remoteConfig:o.resolvedPath},c=k({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??Ye(s,o.resolvedPath,o.profile),u={...s,session:l.session},f=Je(l.runtime,u.platform)??t.runtime,p=l,m=!c,h,g=Pe(p);if(g.shouldAllocate(n)){let e=await je({command:n,client:i,state:l,nextState:p,nextFlags:u,policy:g});p=e.state,m||=e.changed,h=e.acquiredLeaseForCleanup}let _=await De({command:n,flags:u,client:i,state:l,nextState:p,runtime:f,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return p=_.state,f=_.runtime,m||=_.changed,await Ae({changed:m,stateDir:a,state:p,client:i,acquiredLeaseForCleanup:h,preparedMetroCleanupOnFailure:_.preparedMetroCleanupOnFailure,metroCleanupToStop:_.metroCleanupToStop}),{flags:{...u,session:p.session,leaseId:p.leaseId,leaseBackend:p.leaseBackend,platform:p.platform??u.platform,target:p.target??u.target},runtime:f,connection:ue(p)}}async function De(t){let{command:n,flags:r,state:i,client:a}=t,o=Oe(t.nextState,r),s=t.runtime;if(!Ke(n,r,t.batchSteps,t.positionals)||!Z(r)||!ke(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Re(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!qe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function Oe(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function ke(e,t,n){return e===!0||!t||!Q(t,n)}async function Ae(e){if(e.changed)try{A({stateDir:e.stateDir,state:e.state})}catch(t){throw await q(e.preparedMetroCleanupOnFailure),await We(e.client,e.state,e.acquiredLeaseForCleanup),t}await q(e.metroCleanupToStop)}async function je(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??X(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&$(i,c.device);let l=s.leaseBackend??o??Ge(i,t);tt(r,i,l);let u=await Xe(n,s,l,a,i),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Me(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Ne(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Me(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Ne(e,t,n,r){return{...e,leaseId:t.leaseId,leaseBackend:n,leaseProvider:t.leaseProvider??e.leaseProvider,clientId:t.clientId??e.clientId,deviceKey:t.deviceKey??e.deviceKey,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Pe(e){return e.leaseProvider===`proxy`?Ie:y(e.leaseProvider)?Le:Fe}const Fe={shouldAllocate:e=>!G.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ie={shouldAllocate:e=>e!==`devices`&&!G.has(e),ttlMs:()=>3e5,resolveLeaseState:Ze},Le={shouldAllocate:e=>!G.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Re(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:c(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:t.metroNoReuseExisting?!1:void 0,installDependenciesIfNeeded:t.metroNoInstallDeps?!1:void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function q(e){if(e)try{await ee(e)}catch{}}async function ze(e){try{await E({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function J(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}function Be(e){let t=Ve(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ve(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&He(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function He(e,t){let n=j({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ue(e,t,n){if(!t.leaseId)return;let r=Be({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Y(t,`no credential known to belong to that endpoint was available`);try{await J(e,t,r.daemonAuthToken);return}catch{return Y(t,`the release request failed`)}}function Y(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function We(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function X(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`}function Ge(t,n){let r=X(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}function Ke(e,t,n,r=[]){return e===`cdp`?O(r)&&!!t.metroPublicBaseUrl:K.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return K.has(t)&&e.runtime===void 0})}function Z(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Q(e,t){return!e.platform||!t||t!==`ios`&&t!==`android`?!0:e.platform===t}function qe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Je(e,t){if(e)return Q(e,t)?e:void 0}function Ye(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&U(r.leaseProvider))throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:N(n),daemon:j(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??X(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function Xe(e,t,n,r,i){if(t.leaseId&&t.leaseBackend===n){let i=await nt(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...W(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function Ze(t){if(!Te.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await Qe(t.client,t.flags),r=$e(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??et(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function $(e,t){if(e.platform=t.platform,e.target=t.target??e.target,i(t)){e.udid=t.id;return}t.platform===`android`&&(e.serial=t.id)}async function Qe(e,t){return await r((await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist})).map(e=>({...n(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $e(e){return`${t(e)}:${e.target??`mobile`}:${e.id}`}function et(e){if(i(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`}function tt(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function nt(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){if(rt(e))return;throw e}}function rt(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{A as C,E as D,T as E,le as S,D as T,de as _,X as a,k as b,W as c,Ce as d,U as f,j as g,be as h,J as i,we as l,V as m,Ee as n,q as o,xe as p,Ue as r,ze as s,Z as t,Se as u,N as v,ce as w,M as x,I as y};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{_ as e,v as t}from"./sdk-contracts.js";import{n}from"./version.js";import{_ as r}from"./screenshot-result.js";import{n as i}from"./shell-quote.js";import{r as a}from"./remote-config2.js";import{n as o}from"./src.js";import{i as s,n as c,r as l}from"./src3.js";import{t as u}from"./provider-webdriver.js";import{C as ee,_ as d,a as f,b as p,c as m,d as h,f as g,g as te,i as ne,l as _,m as v,o as y,p as b,r as re,s as x,t as ie,u as ae,v as oe,x as S,y as se}from"./connection-runtime.js";import{o as ce,r as le}from"./auth-session.js";import{t as C}from"./shared.js";import w from"node:path";import T from"node:crypto";import E from"node:fs";const ue=new Set([`daemonAuthToken`,`metroBearerToken`]);function de(e){let t=O(pe(e.profile)),n=w.join(e.stateDir,`remote-connections`,`generated`);E.mkdirSync(n,{recursive:!0,mode:448});let r=w.join(n,`${he(e.provider)}-${me(t)}.json`);E.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{E.chmodSync(r,384)}catch{}return r}function fe(n){try{return a(n)}catch(r){let i=t(r);throw new e(`COMMAND_FAILED`,`${n.provider} connection profile returned invalid remote config.`,{generatedConfigPath:n.configPath,cause:i.message},i)}}function D(e){let t=fe({configPath:de({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:ge(e.provider)});return{flags:{...v(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function pe(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!ue.has(e)))}function me(e){return T.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function O(e){return Array.isArray(e)?e.map(O):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,O(t)])):e}function he(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function ge(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function k(...e){return T.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function _e(e){let t=await le({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await ve({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=k(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return D({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function ve(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return ye(await ce(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function ye(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=t.connection;if(!n||typeof n!=`object`)throw new e(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return be(n.remoteConfigProfile);throw new e(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function be(t){if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(t).length===0)throw new e(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return t}function A(e){let t=M(e.provider)(e),n=k(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??f(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,..._(e.flags)};return D({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const j=[{provider:s.browserStack,buildProfileFields:N},{provider:s.awsDeviceFarm,buildProfileFields:Se}];function M(t){let n=j.find(e=>e.provider===t)?.buildProfileFields;if(n)return n;throw new e(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${t}".`)}function N(e){return I(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),I(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:P(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:F(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:F(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:xe(F(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...m(e.flags)}}function xe(t,n){if(t.startsWith(`bs://`)||/^https?:\/\//i.test(t))return t;let r=w.resolve(n,t);try{if(E.statSync(r).isFile())return r}catch{}throw new e(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function Se(e){let{env:t,flags:n}=e;l(n,s.awsDeviceFarm);let r=P(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=L(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:L(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:R(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:R(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??c(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function P(t,n){if(t===`android`||t===`ios`)return t;throw new e(`INVALID_ARGS`,n)}function F(t,n){if(t)return t;throw new e(`INVALID_ARGS`,n)}function I(t,n,r){let i=t?.[n];if(i)return i;throw new e(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function L(e,t,n,r){return F(R(e,t,n),r)}function R(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Ce(t){let n=t.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new e(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=we({flags:t.flags});return D({stateDir:t.stateDir,provider:`limrun`,profile:r,cwd:t.cwd,env:n,flags:t.flags})}function we(e){let t=e.flags,n=Te(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,..._(t)}}function Te(t){if(t.platform!==`android`&&t.platform!==`ios`)throw new e(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(t.device!==void 0)throw new e(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=f(t),r=t.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new e(`INVALID_ARGS`,`connect limrun --platform ${t.platform} requires --lease-backend ${r}.`);return r}function Ee(t){let n=t.flags.daemonBaseUrl??t.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new e(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=k(t.stateDir,n,t.flags.session),i={daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`,daemonServerMode:t.flags.daemonServerMode,tenant:t.flags.tenant??`proxy`,sessionIsolation:t.flags.sessionIsolation??`tenant`,runId:t.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:t.flags.leaseBackend??f(t.flags),platform:t.flags.platform,target:t.flags.target,device:t.flags.device,udid:t.flags.udid,serial:t.flags.serial,iosSimulatorDeviceSet:t.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:t.flags.androidDeviceAllowlist,session:t.flags.session,..._(t.flags)};return D({stateDir:t.stateDir,provider:`proxy`,profile:i,cwd:t.cwd,env:t.env,flags:t.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:t.flags.daemonTransport??`http`}})}const z={cloud:{resolve:_e,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Ee,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>A({provider:`browserstack`,...e}),verify:ke},"aws-device-farm":{resolve:e=>A({provider:`aws-device-farm`,...e}),verify:Ae},limrun:{resolve:Ce,verify:je}};async function De(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=a({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...v(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...b(i)?{provider:i}:{}}}let r=e.provider??(Me(e.flags)?`proxy`:`cloud`);return{...await z[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function Oe(e){let t=e.env??process.env;return e.provider?await z[e.provider].verify({flags:e.flags,env:t}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function ke(e){let{flags:t,env:n}=e;return await u.verifyConnection({provider:`browserstack`,username:B(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:B(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:V(t.platform,`BrowserStack`),deviceName:B(t.device,`BrowserStack profile missed device.`),osVersion:B(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:B(t.providerApp,`BrowserStack profile missed app.`)})}async function Ae(e){let{flags:t}=e;return await u.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 je(e){return await o({apiKey:B(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:n(),platform:V(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function Me(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function B(t,n){if(t!==void 0)return t;throw new e(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function V(t,n){if(t===`android`||t===`ios`)return t;throw new e(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function Ne(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session??Pe();return{session:i,previous:n.session?p({stateDir:t,session:i}):null,remoteConfigHash:oe(r),daemon:te(n)}}function Pe(){return`adc-${T.randomBytes(16).toString(`hex`)}`}function H(e,t){if(e.leaseId)return;let n=h(e.leaseProvider);if(n===`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===`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 r=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.`+r}}function Fe(e,t){return{...t,preparationMessage:H(e,t)?.message??`No live device session has been created.`,...W(e,t)}}function Ie(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(Be(n.device)),n.app&&o.push(Ve(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:d(t.daemon?.baseUrl),liveSession:Le(t),...Re(r,a),metro:t.metro?{prepared:!0,projectRoot:t.metro.projectRoot}:{prepared:!1},...ze({leasePreparation:a,runtimePreparation:n,previousLeaseNotice:i}),connectedAt:t.connectedAt,updatedAt:t.updatedAt}}function Le(e){return{status:e.leaseId?`created`:`not-created`,...e.leaseId?{leaseId:e.leaseId}:{}}}function Re(e,t){return e?{verification:{status:G(e),service:e.service,message:e.verificationMessage,...e.project?{project:e.project}:{}},...e.device?{device:e.device}:{},...e.app?{app:e.app}:{},nextSteps:e.nextSteps??t?.nextSteps??[],...e.notes?{notes:e.notes}:{}}:{}}function ze(e){let{leasePreparation:t,runtimePreparation:n,previousLeaseNotice:r}=e;return{...t?{leasePreparation:t}:{},...n?{runtimePreparation:n}:{},...r?{previousLeaseNotice:r}:{}}}function Be(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 Ve(e,t){return t.status===`missing`?`App: ${Xe(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=He(e,t);return{...n,nextSteps:K(e,n.nextSteps)}}function He(e,t){let n=h(e.leaseProvider);if(n===`proxy`)return{nextSteps:[`agent-device devices`,`agent-device open ${J(e.platform)} --relaunch`]};if(!t&&n===`direct-device-provider`)return{nextSteps:Ye()};let r=t?.app?.status===`missing`;return{nextSteps:Ue(t)?Je(e):[...Ge(t),...qe(e).nextSteps],...We(t)?{notes:Ke(e,!r)}:{}}}function Ue(e){return e?.app?.status===`missing`&&e.device?.status===`deferred`}function We(e){return e?.provider===`browserstack`||e?.provider===`aws-device-farm`}function Ge(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 Ke(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 qe(e){return{nextSteps:[`agent-device open ${J(e.platform)} --relaunch`]}}function Je(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 Ye(){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 ${i(e.session)}`}function J(e){return e===`ios`?`<bundle-id>`:`<package-id>`}function Xe(e){return e.leaseProvider===`aws-device-farm`?`not attached`:e.leaseProvider===`limrun`?`not installed yet`:`not available`}const Ze=async({positionals:e,flags:t,client:n})=>{let i=r(t.stateDir).baseDir,a=ft(e);Qe(a,t);let o=await De({provider:a,flags:t,stateDir:i}),s=o.flags,c=Y(o.remoteConfigPath),l=$e(s,c),u=Ne({stateDir:i,flags:s,remoteConfigPath:o.remoteConfigPath});et(u.previous,{flags:s,session:u.session,remoteConfigPath:o.remoteConfigPath,remoteConfigHash:u.remoteConfigHash,desiredLeaseBackend:f(s),connection:c,daemon:u.daemon});let d=await Oe({provider:o.provider,flags:s,env:process.env}),p=tt({flags:s,scope:l,connectionMetadata:c,context:u,remoteConfigPath:o.remoteConfigPath});ee({stateDir:i,state:p});let m=await at(n,i,s,u.previous,p.daemon?.baseUrl),h=_t(s,p),g=Fe(p,d);return C(s,U({state:p,runtimePreparation:h,readiness:g,previousLeaseNotice:m}),()=>Ie({state:p,runtimePreparation:h,readiness:g,previousLeaseNotice:m})),!0};function Qe(t,n){if(!(!t||!n.remoteConfig))throw new e(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function $e(t,n){if(!t.tenant)throw new e(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&g(n?.leaseProvider))throw new e(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:t.tenant,runId:t.runId}}function et(t,n){if(!(!t||pt(t,n))&&!n.flags.force)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:n.session,remoteConfig:t.remoteConfigPath})}function tt(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=it(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=nt(t,o,r),l=rt(t,o,s);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function nt(e,t,n){return{leaseId:t?.leaseId,leaseBackend:t?.leaseBackend??f(e),leaseProvider:n?.leaseProvider??t?.leaseProvider,clientId:n?.clientId??t?.clientId,deviceKey:t?.deviceKey??n?.deviceKey}}function rt(e,t,n){return{platform:e.platform??t?.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function it(e,t){return!!(t&&!e.force)}async function at(e,t,n,r,i){if(!(!r||!n.force))return await y(r.metro),await x({stateDir:t,state:r}),await re(e,r,{nextDaemonBaseUrl:i,ambientDaemonAuthToken:n.daemonAuthToken,cwd:process.cwd(),env:process.env})}function Y(e){let t=a({configPath:e,cwd:process.cwd(),env:process.env}).profile,n={leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey};return Object.values(n).some(e=>e!==void 0)?n:void 0}const ot=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=X(e);if(!i)return 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 y(i.metro),await x({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let n=await ne(t,i,e.daemonAuthToken);s=n.released,o??=n.provider}catch{}return S({stateDir:r,session:a}),C(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>ct(a,o)),!0},st=async({positionals:t,flags:n})=>{if(t[0]!==`status`)throw new e(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=X(n);if(!i)return Z(n,r),!0;let a=H(i),o=vt(i);return C(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 ct(e,t){return[`Disconnected remote session "${e}".`,...lt(t),...dt(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
5
|
+
`)}function lt(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=ut(e);return t?[t]:[]})}function ut(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 dt(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function ft(t){let n=t[0];if(n!==void 0){if(t.length>1)throw new e(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(b(n))return n;throw new e(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${ae()}.`)}}function X(e){let t=e.session??`default`,n=r(e.stateDir).baseDir;return{session:t,stateDir:n,state:p({stateDir:n,session:t})??(e.session?null:se({stateDir:n}))}}function Z(e,t){C(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function pt(e,t){return mt(e,t)&&ht(e,t)&>(e.daemon,t.daemon)}function mt(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 ht(e,t){return[[e.leaseBackend,t.desiredLeaseBackend],[e.platform,t.flags.platform],[e.target,t.flags.target],[e.leaseProvider,t.connection?.leaseProvider],[e.clientId,t.connection?.clientId]].every(([e,t])=>t===void 0||e===t)}function gt(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function _t(e,t){if(!t.runtime&&!(!ie(e)&&!$(t.remoteConfigPath)))return Q(t)}function vt(e){if(!(e.runtime||!$(e.remoteConfigPath)))return Q(e)}function Q(e){let t=q(e,`agent-device metro prepare --remote-config ${i(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{Ze as connectCommand,st as connectionCommand,ot as disconnectCommand};
|
package/dist/src/context.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{A as t,At as n,Mt as r,O as i,S as a,ct as o,d as s,it as c,j as l,k as u,lt as d}from"./screenshot-geometry.js";import{a as f,h as p,s as m}from"./sdk-batch-runner.js";import{_ as ee,c as h,f as te,h as g,o as _,p as ne,s as v,v as y}from"./sdk-device.js";import{Ht as re,Vt as b,ct as ie,fn as x,lt as ae,pn as S,st as C,t as oe,ut as se}from"./viewport-dimension.js";import{M as ce}from"./screenshot-result.js";import{_ as le,a as ue}from"./device.js";import{f as de}from"./runtime.js";import{I as fe,N as pe,j as w}from"./sdk-android-adb.js";import{t as me}from"./timeouts.js";import{a as he,o as ge}from"./boot-diagnostics.js";import{i as _e}from"./lease-context.js";import{i as T,n as ve,r as E,t as D}from"./register-builtins.js";import ye from"node:path";import{AsyncLocalStorage as O}from"node:async_hooks";import be,{promises as k}from"node:fs";let xe=[];const A=new O;async function Se(e,t){return await A.run([...e],t)}function Ce(e,t){for(let n of M()){if(!n.ownsDevice(e))continue;let r=n.getInteractor(e,t);if(r)return r}}function j(e){return M().some(t=>t.ownsDevice(e))}async function we(e,t,n,r){for(let i of M()){if(!i.ownsDevice(e))continue;if(!i.installApp)throw I(i,e,`install`);let a=await i.installApp?.(e,t,n,r);if(a)return a;throw I(i,e,`install`)}}async function Te(e,t,n){for(let r of M()){if(!r.ownsDevice(e))continue;if(!r.installInstallablePath)throw I(r,e,`install_from_source`);let i=await r.installInstallablePath?.(e,t,n);if(i)return i;throw I(r,e,`install_from_source`)}}async function Ee(e){for(let t of M()){if(!F(t,e.provider))continue;let n=await t.configurePortReverse?.(e);if(n)return n}}function M(){return A.getStore()??xe}function De(e,t={}){let n=e.map(e=>e.provider);return{providerRuntimeIds:n,providerRuntimeRequiredIds:Ae([...n,...t.providerRuntimeRequiredIds??[]]),leaseLifecycleProvider:je(e),recoverableProviderIds:e.filter(e=>e.recoverExpiredLease!==void 0).map(e=>e.provider),recoverExpiredLease:ke(e),cloudArtifactProvider:Me(e),deviceInventoryProvider:Ne(e),appleRunnerProvider:Oe(e),providerDeviceRuntimeScope:async t=>await Se(e,t)}}function Oe(e){if(e.some(N))return t=>{for(let n of e){if(!N(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerProvider(t.device);if(e)return e}}}function N(e){return`getAppleRunnerProvider`in e&&typeof e.getAppleRunnerProvider==`function`}function ke(t){if(t.some(e=>e.recoverExpiredLease!==void 0))return async n=>{let r=t.find(e=>F(e,n.leaseProvider));if(!r?.recoverExpiredLease)throw new e(`UNSUPPORTED_OPERATION`,`Provider ${n.leaseProvider??`unknown`} cannot recover an expired lease.`,{provider:n.leaseProvider,leaseId:n.leaseId});await r.recoverExpiredLease(n)}}function Ae(e){return[...new Set(e)]}function je(e){if(e.length!==0)return{allocate:async(t,n)=>await P(e,`allocate`,t,n),heartbeat:async(t,n)=>await P(e,`heartbeat`,t,n),release:async(t,n)=>await P(e,`release`,t,n)}}function Me(e){if(e.length!==0)return{listCloudArtifacts:async t=>await Pe(e,t)}}function Ne(e){if(e.length!==0)return async t=>{for(let n of e){if(!F(n,t.leaseProvider))continue;let e=await n.deviceInventoryProvider(t);if(e)return e}return null}}async function Pe(e,t){for(let n of e){if(!F(n,t.provider))continue;let e=await n.cloudArtifacts?.listCloudArtifacts?.(t);if(e)return e}}async function P(e,t,n,r){for(let i of e){if(!F(i,n.leaseProvider))continue;let e=i.leaseLifecycle[t],a=e?await e(n,r):void 0;if(a)return a}}function F(e,t){return e.provider===t}function I(t,n,r){throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime ${t.provider} does not support ${r} for this device.`,{provider:t.provider,deviceId:n.id,platform:g(n)})}const L=new O,R=new O;async function z(t,n,r){let i=await Fe(t,n,r);if(i)return i;let a=await Ie(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&Re(n,a)){let{findBootableIosSimulator:e}=await import(`./devices2.js`),t=await e({simulatorSetPath:r.simulatorSetPath,target:n.target});if(t)return t}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function Fe(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||V(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>ne(e,n)&&v(e)&&e.kind===`simulator`&&e.booted===!0);if(a.length<2)return;let{findIosSimulatorInstalledApp:o}=await import(`./apps.js`).then(e=>e.t),s=(await Promise.all(a.map(async e=>await o(e,i)?e:void 0))).filter(e=>e!==void 0);if(s.length===1)return s[0];throw s.length===0?new e(`APP_NOT_INSTALLED`,`No booted iOS simulator has ${i} installed`,{appTarget:i,...B(a),hint:`Install the app on a booted simulator, or pass --udid to select the intended device explicitly.`}):new e(`AMBIGUOUS_MATCH`,`Multiple booted iOS simulators have ${i} installed`,{appTarget:i,...B(s),hint:`Pass --udid to select the intended simulator explicitly.`})}function B(e){return{devices:e.map(e=>({id:e.id,name:e.name}))}}async function Ie(e,t,n){try{return await y(e,t,n)}catch(e){if(Le(e,t))return;throw e}}function Le(t,n){return!V(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function Re(e,t){return!V(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function V(e){return!!(e.udid||e.serial||e.deviceName)}async function ze(e,t={}){let n=Be(e),{iosSimulatorSetPath:r,...i}=n,a=Ye(n,t),o={simulatorSetPath:r,allowStoppedAndroidAvdPlaceholders:t.allowStoppedAndroidAvdPlaceholders},s={platform:n.platform,target:e.target,cacheHit:!1};return await fe(`resolve_target_device`,async()=>{let e=Je(a);if(e)return s.cacheHit=!0,e;let c=await Ge(n);if(c)return qe(i)?H(a,await z(c,i,{simulatorSetPath:r,allowLocalSimulatorFallback:n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):H(a,await y(c,i,o));let l=await T(n);return qe(i)?H(a,await z(l,i,{simulatorSetPath:r,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):H(a,await y(l,i,o))},s)}function Be(t){let n=t.platform;if(t.target&&!n)throw new e(`INVALID_ARGS`,`Device target selector requires --platform. Use --platform ios|macos|android|vega|linux|apple with --target mobile|tv|desktop.`);let r=ee({simulatorSetPath:ge(t.iosSimulatorDeviceSet),platform:n,target:t.target}),i=he(t.androidDeviceAllowlist);return{platform:n,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial,leaseId:t.leaseId,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId,iosSimulatorSetPath:r,androidSerialAllowlist:i?Array.from(i).sort():void 0}}async function Ve(e){return L.getStore()?await e():await L.run(new Map,e)}async function He(e,t){return e?await R.run(e,t):await t()}async function Ue(e,t){return await He(e,async()=>await Ve(t))}async function We(e){return await Ge(e)??await T(e)}async function Ge(e){let t=R.getStore();if(!t)return null;let n=await t(e);return n==null?null:n.map(e=>({...e}))}function Ke(e){return _(e.platform)}function qe(e){return Ke(e)}function Je(e){let t=L.getStore()?.get(e);if(t)return{...t}}function H(e,t){return L.getStore()?.set(e,{...t}),t}function Ye(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}D();const Xe={device:!0},Ze=[`open`,`close`],Qe=[`record`],$e=[`audio`,`find`,`get`,`is`,`network`,`screenshot`,`snapshot`,`wait`],et=[`click`,`fill`,`focus`,`press`,`scroll`,`type`],tt=[`viewport`],nt=new Set([...Ze,...Qe,...$e,...et,...tt]),U=rt(f(p));function rt(e){let t={};for(let[n,r]of Object.entries(e))t[n]=nt.has(n)?{...r,web:Xe}:r;for(let t of nt)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function it(e,t){let n=U[e];if(!n)return!0;let r=E(t.platform);if(!r)return!1;let i=n[r.capability.bucket];if(!i)return!1;let a=r.capability.supportsByDefault?.[e];return a&&!a(t)?!1:i[t.kind??`unknown`]===!0}function at(e,t){return E(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function ot(){return Object.keys(U).sort()}function st(e){let t=U[e];if(!t)return[];let n=[`apple`,`android`,`vega`,`linux`,`web`],r=[];for(let e of n){let n=t[e];n&&Object.values(n).some(e=>e===!0)&&r.push(e)}return r}function ct(e,t){if(e.intent===`drag`){lt(e,t);return}if(t.platform===`web`||t.appleOs===`watchos`)throw G(e,W(e,t));if(ut(e)){dt(e,t);return}if(t.appleOs===`visionos`)throw G(e,W(e,t));if(e.intent===`fling`&&`direction`in e&&t.platform===`linux`)throw G(e,`gesture fling is not supported on Linux`)}function lt(e,t){let n=t.platform===`android`&&t.target!==`tv`,r=t.platform===`apple`&&(t.appleOs===`ios`||t.appleOs===`ipados`||t.appleOs===void 0&&t.target!==`desktop`&&t.target!==`tv`);if(!(n||r))throw G(e,W(e,t),`Target-authored drag requires an adapter that preserves source hold, timed movement, and destination hold; it is supported on Android touch devices and iOS/iPadOS.`)}function ut(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function dt(e,t){if(t.platform===`android`){if(t.target!==`tv`)return;throw G(e,`gesture ${e.intent} is not supported on Android TV`,`Android TV has no touch input — this gesture is supported on Android phones, tablets, and the iOS simulator only.`)}if(t.platform!==`apple`)throw G(e,W(e,t));le(t,e.intent)}function W(e,t){return`gesture ${e.intent} is not supported on ${t.appleOs??t.platform}`}function G(t,n,r){return new e(`UNSUPPORTED_OPERATION`,n,{gesture:t.intent,...r?{hint:r}:{}})}const ft=`No active session. Run open first.`;function pt(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function mt(){return pt(`SESSION_NOT_FOUND`,ft)}function ht(e,t,n){if(it(e,t))return null;let r=n?.hint?at(e,t):void 0;return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:n?.message??`${e} is not supported on this device`,...r?{hint:r}:{}}}}const gt=/^[A-Za-z0-9_.:-]{1,64}$/,_t=8*1024,vt=4*1024;function yt(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!gt.test(n))throw new e(`INVALID_ARGS`,`Invalid trigger-app-event event name: ${n}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});if(t.length>2)throw new e(`INVALID_ARGS`,`trigger-app-event accepts at most two arguments: <event> [payloadJson]`);return{eventName:n,payload:xt(r,n)}}function bt(t,n,r){let i=g(t),a=St(t);if(!a)throw new e(`UNSUPPORTED_OPERATION`,`No app event URL template configured for ${i}.`,{hint:`Set AGENT_DEVICE_${i.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):``,s=a.replaceAll(`{event}`,encodeURIComponent(n)).replaceAll(`{payload}`,encodeURIComponent(o)).replaceAll(`{platform}`,encodeURIComponent(i));if(s.length>vt)throw new e(`INVALID_ARGS`,`trigger-app-event URL exceeds maximum supported length`,{hint:`Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.`,length:s.length,maxLength:vt});return s}function xt(t,n){if(t)try{let r=JSON.parse(t);if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,`utf8`)>_t)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${_t} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function St(e){return((v(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:h(e)?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE)?.trim()||void 0}const Ct=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function wt(e,t){return _(e.platform)&&t>1}function Tt(e,t,n=2e4){if(e.length===0)return[];let r=t>0?t:e.length,i=[],a=[],o=0;for(let t of e){let e=(t.durationMs??0)+(t.pauseMs??0)+250,s=a.length>0&&o+e>n,c=a.length>=r;(s||c)&&(i.push(a),a=[],o=0),a.push(t),o+=e}return a.length>0&&i.push(a),i}function Et(e,t){if(t<=0)return[0,0];let[n,r]=Ct[e%Ct.length];return[n*t,r*t]}async function Dt(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await me(t)}async function Ot(e,t){let{x:n,y:r}=K(t,`longpress requires x y [durationMs]`,{hint:`Direct platform longpress requires coordinates. In an open daemon session, use agent-device longpress @ref|selector [durationMs]; otherwise run snapshot -i, use the target rect center as x y, then retry longpress x y durationMs.`}),i=t[2]?Number(t[2]):void 0;return await e.longPress(n,r,i),{x:n,y:r,durationMs:i,...x(`Long pressed (${n}, ${r})`)}}async function kt(e,t){let{x:n,y:r}=K(t,`focus requires x y`);return await e.focus(n,r),{x:n,y:r,...x(`Focused (${n}, ${r})`)}}async function At(t,n,r){let i=tn(n);if(i)throw new e(`INVALID_ARGS`,`type does not accept a target ref like "${i}"`,{hint:`Use fill ${i} "text" to target that field, or press ${i} then type "text" to append.`});let a=n.join(` `);if(!a)throw new e(`INVALID_ARGS`,`type requires text`);let o=C(r?.delayMs??0,`delay-ms`,0,1e4),s=(await t.type(a,o))?.textEntryRoute;return{...s===void 0?{}:{textEntryRoute:s},text:a,delayMs:o,...x(Y(`Typed`,a))}}async function jt(t,n,r){if(r?.directElementSelector)return await Mt(t,r.directElementSelector,n,r);let i=Number(n[0]),a=Number(n[1]),o=n.slice(2).join(` `);if(Number.isNaN(i)||Number.isNaN(a)||!o)throw new e(`INVALID_ARGS`,`fill requires x y text`);let s=C(r?.delayMs??0,`delay-ms`,0,1e4);return{x:i,y:a,text:o,delayMs:s,...(await t.fill(i,a,o,s,{allowNonHittableCoordinateFallback:r?.allowNonHittableCoordinateFallback===!0}))?.maestroNonHittableCoordinateFallbackUsed===!0?{maestroNonHittableCoordinateFallbackUsed:!0}:{},...x(Y(`Filled`,o))}}async function Mt(t,n,r,i){if(!t.fillElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector fill is not supported`);let a=r.join(` `);if(!a)throw new e(`INVALID_ARGS`,`fill requires text`);let o=C(i.delayMs??0,`delay-ms`,0,1e4),s=await t.fillElementSelector(n,a,o);return{selector:n.raw,text:a,delayMs:o,...s??{},...x(Y(`Filled`,a))}}async function Nt(e,t,n,r){if(r?.directElementSelector&&v(e))return await Pt(t,r.directElementSelector);let{x:i,y:a}=K(n,`press requires x y`);if(h(e)&&r?.surface&&r.surface!==`app`)return await Ft(i,a,r);let o=d(r);if(o!==`primary`)return await It(e,i,a,o,r);let s=zt(r);return Bt(s),wt(e,s.count)?await Ht(e,i,a,s,r):await Gt(t,i,a,s)}async function Pt(t,n){if(!t.tapElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector tap is not supported`);let r=await t.tapElementSelector(n),i=r?.maestroNonHittableCoordinateFallbackUsed===!0;return{selector:n.raw,...r??{},...x(i?l:`Tapped ${n.raw}`)}}function K(t,n,r){let i=Number(t[0]),a=Number(t[1]);if(Number.isNaN(i)||Number.isNaN(a))throw new e(`INVALID_ARGS`,n,r);return{x:i,y:a}}async function Ft(t,n,r){let i=d(r);if(i!==`primary`)throw new e(`UNSUPPORTED_OPERATION`,`${i} click is not supported on macOS ${r.surface} sessions.`);let{runMacOsPressAction:a}=await import(`./helper.js`).then(e=>e.t);return await a(t,n,{bundleId:r.appBundleId,surface:r.surface}),{x:t,y:n,...x(J({x:t,y:n}))}}async function It(e,t,n,r,i){if(Lt(e,r,i),e.platform===`linux`)return await Rt(t,n,r);let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},Kt(i)),{x:t,y:n,button:r,...x(J({x:t,y:n,button:r}))}}function Lt(e,t,n){let r=o({commandLabel:`click`,platform:g(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function Rt(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions2.js`);await n(e,t)}return{x:e,y:t,button:n,...x(J({x:e,y:t,button:n}))}}function zt(e){return{count:q(e?.count,1,`count`,1,200),intervalMs:q(e?.intervalMs,0,`interval-ms`,0,1e4),holdMs:q(e?.holdMs,0,`hold-ms`,0,1e4),jitterPx:q(e?.jitterPx,0,`jitter-px`,0,100),doubleTap:!!e?.doubleTap}}function q(e,t,n,r,i){return C(e===void 0?t:e,n,r,i)}function Bt({doubleTap:t,holdMs:n,jitterPx:r}){if(t&&n>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with hold-ms`);if(t&&r>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with jitter-px`)}async function Vt(e,t,n){let{runAppleRunnerCommand:r}=await import(`./runner-client.js`).then(e=>e.o),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=Tt(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),Kt(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Wt(e,f)}u+=s.completedSteps,d.push(...s.results),f+=t.length}return{...c??{},completedSteps:u,sequenceResults:d,...l?.gestureEndUptimeMs===void 0?{}:{gestureEndUptimeMs:l.gestureEndUptimeMs}}}async function Ht(e,t,n,r,i){let a=await Vt(e,Ut(e,t,n,r),i);return{x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,timingMode:`runner-sequence`,...a,...x(J({x:t,y:n}))}}function Ut(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&v(e)&&!te(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=Et(o,r.jitterPx),l=o===r.count-1;return{kind:i,x:t+s,y:n+c,...a?{synthesized:!0}:{},...r.holdMs>0?{durationMs:r.holdMs}:{},...!l&&r.intervalMs>0?{pauseMs:r.intervalMs}:{}}})}function Wt(t,n){if(n===0||!(t instanceof e)||!t.details)return t;let r=t.details.failedStepIndex;if(typeof r!=`number`)return t;let i=t.details.completedSteps;return new e(t.code,t.message,{...t.details,failedStepIndex:r+n,chunkStepIndex:r,...typeof i==`number`?{completedSteps:n+i}:{}},t.cause)}async function Gt(e,t,n,r){let i;return await Dt(r.count,r.intervalMs,async a=>{let[o,s]=Et(a,r.jitterPx),c=t+o,l=n+s;if(r.doubleTap){let t=await e.doubleTap(c,l);i??=t??void 0;return}if(r.holdMs>0){let t=await e.longPress(c,l,r.holdMs);i??=t??void 0}else{let t=await e.tap(c,l);i??=t??void 0}}),S({x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,...i},J({x:t,y:n}))}function Kt(e){return{verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,requestId:e?.requestId,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir}}async function qt(t,n,r){let i=n[0],a=n[1]?Number(n[1]):void 0,o=r?.pixels,s=r?.durationMs;if(!i)throw new e(`INVALID_ARGS`,`scroll requires direction`);Jt(a,o,s);let c=$t(i),l={amount:a,pixels:o,durationMs:s},{interactionResult:u,completedPasses:d}=await Xt(t,r,c,l);return S(Zt(c,l,d,u),ae(c.direction,c.edge,d,a,o))}function Jt(e,n,r){Yt(e),t(r),i({amount:e,pixels:n})}function Yt(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Xt(e,t,n,r){if(n.edge){let i=n.edge,a=await se({edge:i,captureState:async n=>await Qt(e,t,i,n),scroll:async()=>await e.scroll(n.direction,r)});return{interactionResult:a.result??{},completedPasses:a.passes}}return{interactionResult:await e.scroll(n.direction,r)??{},completedPasses:1}}function Zt(e,t,n,r){let i=u(r);return{direction:e.direction,...e.edge?{edge:e.edge,passes:n}:{},...t.amount===void 0?{}:{amount:t.amount},...t.pixels===void 0?{}:{pixels:t.pixels},...i===void 0?{}:{durationMs:i},...r}}async function Qt(t,n,r,i){if(typeof t.snapshot!=`function`)throw new e(`UNSUPPORTED_OPERATION`,`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let a=t.snapshot;return await ie({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function $t(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:c(e)}}async function en(e,t,n){let{x:r,y:i}=K(t,`read requires x y`);if(e.platform===`android`){let{readAndroidTextAtPoint:t}=await import(`./input-actions.js`).then(e=>e.s);return{action:`read`,text:await t(e,r,i)??``}}if(e.platform===`linux`){let{readLinuxTextAtPoint:e}=await import(`./snapshot.js`).then(e=>e.n);return{action:`read`,text:await e(r,i,n?.surface)}}if(h(e)&&n?.surface&&n.surface!==`app`){let{runMacOsReadTextAction:e}=await import(`./helper.js`).then(e=>e.t);return{action:`read`,text:(await e(r,i,{bundleId:n.appBundleId,surface:n.surface})).text}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(e,{command:`readText`,x:r,y:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId,iosXctestrunFile:n?.iosXctestrunFile,iosXctestDerivedDataPath:n?.iosXctestDerivedDataPath,iosXctestEnvDir:n?.iosXctestEnvDir});return{action:`read`,text:typeof o.text==`string`?o.text:typeof o.message==`string`?o.message:``}}function tn(e){return de(e[0])}function J(e){return e.button&&e.button!==`primary`?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function Y(e,t){return`${e} ${Array.from(t).length} chars`}function nn(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)}function X(t,n){let r=n?.subject??`Payload`,i=t.trim();if(!i)throw new e(`INVALID_ARGS`,`${r} cannot be empty`);let a=n?.expandPath?n.expandPath(i,n.cwd):i;try{if(!be.statSync(a).isFile())throw new e(`INVALID_ARGS`,`${r} path is not a file: ${a}`);return{kind:`file`,path:a}}catch(t){if(t instanceof e)throw t;let n=t.code;if(n===`EACCES`||n===`EPERM`)throw new e(`INVALID_ARGS`,`${r} file is not readable: ${a}`);if(n&&n!==`ENOENT`)throw new e(`COMMAND_FAILED`,`Unable to read ${r} file: ${a}`,{cause:String(t)})}if(nn(i))return{kind:`inline`,text:i};throw new e(`INVALID_ARGS`,`${r} file not found: ${a}`)}async function rn(t){let n=X(t,{subject:`Push payload`}),r=n.kind===`inline`?n.text:await an(n.path);try{let t=JSON.parse(r);if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`push payload must be a JSON object`);return t}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid push payload JSON: ${t}`)}}async function an(t){try{return await k.readFile(t,`utf8`)}catch(n){let r=n.code;throw r===`ENOENT`?new e(`INVALID_ARGS`,`Push payload file not found: ${t}`):r===`EISDIR`?new e(`INVALID_ARGS`,`Push payload path is not a file: ${t}`):r===`EACCES`||r===`EPERM`?new e(`INVALID_ARGS`,`Push payload file is not readable: ${t}`):new e(`COMMAND_FAILED`,`Unable to read push payload file: ${t}`,{cause:String(n)})}}D();async function Z(t,n){if(j(t)){let r=Ce(t,n);if(r)return r;throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime does not have an active interactor for this device.`,{deviceId:t.id,platform:g(t)})}return await ve(t.platform).createInteractor(t,n)}async function on(e,t,n,r,i){let a=Q(i),o=await Z(e,a);return w({level:`debug`,phase:`platform_command_prepare`,data:{command:t,platform:e.platform,kind:e.kind}}),await fe(`platform_command`,async()=>await un(e,o,t,n,r,i,a),{command:t,platform:e.platform})}async function sn(t,n,r){let i=await Z(t,Q(r));if(!i.performGesture)throw new e(`UNSUPPORTED_OPERATION`,`Gesture execution is unavailable`);return await i.performGesture(n)}async function cn(e,t){return await(await Z(e,Q(t))).gestureViewport?.()}function Q(e){return{requestId:e?.requestId,signal:e?.signal,appBundleId:e?.appBundleId,verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir,runnerLeaseContext:e?.runnerLeaseContext}}const ln={open:({device:e,interactor:t,positionals:n,context:r})=>dn(e,t,n,r),close:async({device:e,interactor:t,positionals:n})=>{let r=n[0];return r?(await t.close(r),{app:r,...x(`Closed: ${r}`)}):(e.platform===`web`&&await t.close(``),{closed:`session`,...x(`Closed session`)})},press:({device:e,interactor:t,positionals:n,context:r})=>Nt(e,t,n,r),longpress:({interactor:e,positionals:t})=>Ot(e,t),focus:({interactor:e,positionals:t})=>kt(e,t),type:({interactor:e,positionals:t,context:n})=>At(e,t,n),fill:({interactor:e,positionals:t,context:n})=>jt(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>qt(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>fn(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>pn(e,t,n,r),viewport:({interactor:e,positionals:t})=>mn(e,t),back:async({interactor:e,context:t})=>(await e.back(t?.backMode),{action:`back`,mode:t?.backMode??`in-app`,...x(`Back`)}),home:async({interactor:e})=>(await e.home(),{action:`home`,...x(`Home`)}),orientation:async({interactor:e,positionals:t})=>{let n=ue(t[0]),r=(await e.setOrientation(n))?.orientation??n;return{action:`orientation`,orientation:r,...x(`Rotated to ${r}`)}},"app-switcher":async({interactor:e})=>(await e.appSwitcher(),{action:`app-switcher`,...x(`Opened app switcher`)}),clipboard:({interactor:e,positionals:t})=>hn(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>_n(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>gn(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>xn(e,t,n,r),push:({device:e,positionals:t,context:n})=>Sn(e,t,n),snapshot:({interactor:e,context:t})=>Cn(e,t),read:({device:e,positionals:t,context:n})=>en(e,t,n)};async function un(t,n,r,i,a,o,s){let c=Object.hasOwn(ln,r)?ln[r]:void 0;if(!c)throw new e(`INVALID_ARGS`,`Unknown command: ${r}`);return await c({device:t,interactor:n,positionals:i,outPath:a,context:o,runnerCtx:s})}async function dn(t,n,r,i){let a=r[0],o=r[1],s=i?.launchConsole,c=i?.launchArgs;if(r.length>2)throw new e(`INVALID_ARGS`,`open accepts at most two arguments: <app|url> [url]`);if(!a){if(s)throw new e(`INVALID_ARGS`,`--launch-console requires an app target`);if(c&&c.length>0)throw new e(`INVALID_ARGS`,`--launch-args requires an app target`);return await n.openDevice(),{app:null,...x(`Opened device`)}}if(s&&(!v(t)||t.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,re);if(t.platform===`linux`&&c&&c.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on Linux.`);if(o!==void 0){if(m(a))throw new e(`INVALID_ARGS`,`open <app> <url> requires an app target as the first argument`);if(!m(o))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(s)throw new e(`INVALID_ARGS`,b);return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchArgs:c,terminateRunningApp:i?.terminateRunningApp,url:o}),{app:a,url:o,...x(`Opened: ${a}`)}}if(s&&m(a))throw new e(`INVALID_ARGS`,b);if(i?.clearAppState){if(m(a))throw new e(`INVALID_ARGS`,`Clearing app state requires an app target, not a deep link.`);await n.setSetting(`clear-app-state`,`clear`,a)}return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchConsole:s,launchArgs:c,terminateRunningApp:i?.terminateRunningApp}),{app:a,...s?{launchConsole:s}:{},...x(`Opened: ${a}`)}}async function fn(e,t,n,r){let{eventName:i,payload:a}=yt(n),o=bt(e,i,a);return await t.open(o,{appBundleId:r?.appBundleId}),{event:i,eventUrl:o,transport:`deep-link`,...x(`Triggered app event: ${i}`)}}async function pn(e,t,n,i){let a=t[0]??n??`./screenshot-${Date.now()}.png`;await k.mkdir(ye.dirname(a),{recursive:!0});let o=r(i);return await e.screenshot(a,{appBundleId:i?.appBundleId,pixelDensity:o.pixelDensity,fullscreen:o.fullscreen,normalizeStatusBar:o.normalizeStatusBar,stabilize:o.stabilize,surface:i?.surface,skipIosSimulatorBootCheck:i?.skipIosSimulatorBootCheck,captureBackend:i?.screenshotCaptureBackend}),{path:a,...x(`Saved screenshot: ${a}`)}}async function mn(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=oe(n[0],`width`),i=oe(n[1],`height`);if(!t.setViewport)throw new e(`UNSUPPORTED_OPERATION`,`viewport is not supported by this backend`);return await t.setViewport(r,i),{width:r,height:i,...x(`Viewport set: ${r}x${i}`)}}async function hn(t,n){let r=(n[0]??``).toLowerCase();if(r!==`read`&&r!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write`);if(r===`read`){if(n.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments`);return{action:r,text:await t.readClipboard()}}if(n.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text (use "" to clear clipboard)`);let i=n.slice(1).join(` `);return await t.writeClipboard(i),{action:r,textLength:Array.from(i).length,...x(`Clipboard updated`)}}async function gn(t,n,r,i){if(t.target!==`tv`)throw new e(`UNSUPPORTED_OPERATION`,`tv-remote is supported only on TV targets`,{hint:`Select an Android TV, tvOS, or Vega OS target with --target tv.`});if(r.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button`);let o=a(r[0]),s=i?.durationMs===void 0?void 0:C(i.durationMs,`durationMs`,0,1e4);return await n.tvRemote(o,s),{action:`tv-remote`,button:o,...s===void 0?{}:{durationMs:s},...x(`Pressed TV remote ${o}`)}}async function _n(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!ce(a))throw new e(`INVALID_ARGS`,`keyboard requires a subcommand: status, get, dismiss, enter, or return`);if(n.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one subcommand argument`);if(t.platform===`android`)return await vn(t,a);if(v(t))return await yn(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android and iOS`)}async function vn(e,t){if(t===`enter`||t===`return`){let{pressAndroidEnter:t}=await import(`./input-actions.js`).then(e=>e.s);return await t(e),{platform:`android`,action:`enter`,...x(`Keyboard enter pressed`)}}if(t===`dismiss`){let{dismissAndroidKeyboard:t}=await import(`./device-input-state.js`).then(e=>e.t),n=await t(e);return{platform:`android`,action:`dismiss`,attempts:n.attempts,wasVisible:n.wasVisible,dismissed:n.dismissed,visible:n.visible,inputType:n.inputType,type:n.type,inputMethodPackage:n.inputMethodPackage,focusedPackage:n.focusedPackage,focusedResourceId:n.focusedResourceId,inputOwner:n.inputOwner}}let{getAndroidKeyboardState:n}=await import(`./device-input-state.js`).then(e=>e.t),r=await n(e);return{platform:`android`,action:`status`,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}async function yn(t,n,r,i){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is currently supported only on Android; use keyboard dismiss or enter on iOS`);if(n===`enter`||n===`return`){let{runAppleRunnerCommand:e}=await import(`./runner-client.js`).then(e=>e.o),n=await e(t,{command:`keyboardReturn`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`enter`,visible:n.visible,wasVisible:n.wasVisible,...x(`Keyboard enter pressed`)}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(t,{command:`keyboardDismiss`,appBundleId:r?.appBundleId},i),s=typeof o.keyboardDismissMechanism==`string`?o.keyboardDismissMechanism:void 0;return{platform:`ios`,action:`dismiss`,wasVisible:o.wasVisible,dismissed:o.dismissed,visible:o.visible,mechanism:s,...x(bn(o.dismissed===!0,s))}}function bn(e,t){return e?t===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`:`Keyboard already hidden`}async function xn(t,n,r,i){let[a,o,c,l]=r;if(!a||!o&&a!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(a===`clear-app-state`){let r=(o===`clear`?c:o)??i?.appBundleId;if(!r)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);w({level:`debug`,phase:`settings_apply`,data:{setting:a,state:`clear`,appBundleId:r,platform:t.platform}});let s=await n.setSetting(a,`clear`,r);return s&&typeof s==`object`?S({setting:a,state:`clear`,...s},$(s)??`Cleared user data for ${r}`):{setting:a,state:`clear`,...x(`Cleared user data for ${r}`)}}if(!o)throw new e(`INVALID_ARGS`,`settings requires setting state`);let u=a===`location`&&o===`set`,d=(a===`permission`||u?r[4]:r[2])??i?.appBundleId,f=a===`permission`?{permissionTarget:c,permissionMode:l}:u?{latitude:s(c,`latitude`),longitude:s(l,`longitude`)}:void 0;w({level:`debug`,phase:`settings_apply`,data:u?{setting:a,state:o,latitude:c,longitude:l,platform:t.platform}:a===`permission`?{setting:a,state:o,permissionTarget:c,permissionMode:l,platform:t.platform}:{setting:a,state:o,appBundleId:d,platform:t.platform}});let p=await n.setSetting(a,o,d,f);return p&&typeof p==`object`?S({setting:a,state:o,...p},$(p)??`Updated setting: ${a}`):{setting:a,state:o,...x(`Updated setting: ${a}`)}}async function Sn(t,n,r){let i=n[0]?.trim(),a=n[1]?.trim();if(!i||!a)throw new e(`INVALID_ARGS`,`push requires <bundle|package> <payload.json|inline-json>`);let o=await rn(a);if(v(t)){let{pushIosNotification:e}=await import(`./apps.js`).then(e=>e.t);return await e(t,i,o),{platform:`ios`,bundleId:i,...x(`Pushed notification to ${i}`)}}let{pushAndroidNotification:s}=await import(`./notifications.js`),c=await s(t,i,o);return{platform:`android`,package:i,action:c.action,extrasCount:c.extrasCount,...x(`Pushed notification to ${i}`)}}async function Cn(e,t){let n=t??{};return await e.snapshot({appBundleId:n.appBundleId,signal:n.signal,interactiveOnly:n.snapshotInteractiveOnly,preferredBackend:n.snapshotPreferredBackend,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw,includeRects:n.snapshotIncludeRects,includeHiddenContentHints:n.snapshotIncludeHiddenContentHints,surface:n.surface})}function $(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}function wn(e,t,r,i,a,o){return{requestId:a??pe().requestId,appBundleId:r,runnerLeaseContext:_e({meta:o}),activity:t?.activity,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,clearAppState:t?.clearAppState,verbose:t?.verbose,logPath:e,traceLogPath:i,iosXctestrunFile:t?.iosXctestrunFile,iosXctestDerivedDataPath:t?.iosXctestDerivedDataPath,iosXctestEnvDir:t?.iosXctestEnvDir,screenshotCaptureBackend:t?.maestro?.screenshotCaptureBackend,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotPreferredBackend:t?.snapshotPreferredBackend,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,snapshotIncludeHiddenContentHints:t?.snapshotIncludeHiddenContentHints,...n(t),count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,durationMs:t?.durationMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:d(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}export{j as S,Ue as _,X as a,we as b,mt as c,ot as d,ct as f,ze as g,We as h,cn as i,ht as l,Be as m,on as n,ft as o,st as p,sn as r,pt as s,wn as t,it as u,Ee as v,Te as x,De as y};
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{A as t,Ft as n,M as r,N as i,Nt as a,P as o,dt as s,ft as c,j as l,p as u,st as d,w as f}from"./version.js";import{G as ee,V as te,a as ne,h as re,s as p}from"./sdk-batch-runner.js";import{_ as m,b as ie,c as h,h as ae,l as g,m as _,s as v,x as oe,y as se}from"./sdk-device.js";import{Gt as ce,Kt as le,Xt as y,_n as b,dt as ue,ft as de,gn as x,n as fe,pt as pe,ut as S}from"./prepare-kind.js";import{A as me}from"./screenshot-result.js";import{a as he}from"./device.js";import{f as ge}from"./runtime.js";import{A as C,F as _e,M as ve}from"./sdk-android-adb.js";import{t as ye}from"./timeouts.js";import{F as be}from"./runner-disposal.js";import{i as xe}from"./lease-context.js";import{B as Se,V as Ce}from"./physical-device-control.js";import we from"node:path";import{AsyncLocalStorage as w}from"node:async_hooks";import Te,{promises as T}from"node:fs";let Ee=[];const E=new w;async function De(e,t){return await E.run([...e],t)}function Oe(e,t){for(let n of O()){if(!n.ownsDevice(e))continue;let r=n.getInteractor(e,t);if(r)return r}}function D(e){return O().some(t=>t.ownsDevice(e))}async function ke(e,t,n,r){for(let i of O()){if(!i.ownsDevice(e))continue;if(!i.installApp)throw j(i,e,`install`);let a=await i.installApp?.(e,t,n,r);if(a)return a;throw j(i,e,`install`)}}async function Ae(e,t,n){for(let r of O()){if(!r.ownsDevice(e))continue;if(!r.installInstallablePath)throw j(r,e,`install_from_source`);let i=await r.installInstallablePath?.(e,t,n);if(i)return i;throw j(r,e,`install_from_source`)}}async function je(e){for(let t of O()){if(!A(t,e.provider))continue;let n=await t.configurePortReverse?.(e);if(n)return n}}function O(){return E.getStore()??Ee}function Me(e,t={}){Be(e);let n=e.map(e=>e.provider);return{providerRuntimeIds:n,providerRuntimeRequiredIds:Ie([...n,...t.providerRuntimeRequiredIds??[]]),leaseLifecycleProvider:Le(e),recoverableProviderIds:e.filter(e=>e.recoverExpiredLease!==void 0).map(e=>e.provider),recoverExpiredLease:Fe(e),cloudArtifactProvider:Re(e),deviceInventorySource:ze(e),appleRunnerProvider:Ne(e),providerDeviceRuntimeScope:async t=>await De(e,t)}}function Ne(e){if(e.some(Pe))return t=>{for(let n of e){if(!Pe(n)||!n.ownsDevice(t.device))continue;let e=n.getAppleRunnerProvider(t.device);if(e)return e}}}function Pe(e){return`getAppleRunnerProvider`in e&&typeof e.getAppleRunnerProvider==`function`}function Fe(t){if(t.some(e=>e.recoverExpiredLease!==void 0))return async n=>{let r=t.find(e=>A(e,n.leaseProvider));if(!r?.recoverExpiredLease)throw new e(`UNSUPPORTED_OPERATION`,`Provider ${n.leaseProvider??`unknown`} cannot recover an expired lease.`,{provider:n.leaseProvider,leaseId:n.leaseId});await r.recoverExpiredLease(n)}}function Ie(e){return[...new Set(e)]}function Le(e){if(e.length!==0)return{allocate:async(t,n)=>await k(e,`allocate`,t,n),heartbeat:async(t,n)=>await k(e,`heartbeat`,t,n),release:async(t,n)=>await k(e,`release`,t,n)}}function Re(e){if(e.length!==0)return{listCloudArtifacts:async t=>await Ve(e,t)}}function ze(e){if(e.length!==0)return{discover:async(t,n)=>{n.throwIfAborted();for(let r of e){if(!A(r,t.leaseProvider))continue;let e=await r.deviceInventoryProvider(t,n);if(n.throwIfAborted(),e!=null)return{kind:`inventory`,devices:e}}return{kind:`declined`}}}}function Be(e){let t=new Set;for(let n of e){if(t.has(n.provider))throw TypeError(`Duplicate provider device runtime: ${n.provider}`);t.add(n.provider)}}async function Ve(e,t){for(let n of e){if(!A(n,t.provider))continue;let e=await n.cloudArtifacts?.listCloudArtifacts?.(t);if(e)return e}}async function k(e,t,n,r){for(let i of e){if(!A(i,n.leaseProvider))continue;let e=i.leaseLifecycle[t],a=e?await e(n,r):void 0;if(a)return a}}function A(e,t){return e.provider===t}function j(t,n,r){throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime ${t.provider} does not support ${r} for this device.`,{provider:t.provider,deviceId:n.id,platform:m(n)})}const He=`device_inventory_context_unavailable`,Ue=new w;async function We(e,t){return await Ue.run(e,t)}async function Ge(e){return await Je(`providerFirst`,e)}async function Ke(e){let t=Ye(),n=await t.providerFirst.discoverWithSource(e,t.requestScope);return{devices:n.devices.map(e=>({...e})),source:n.source}}async function qe(e){return await Je(`localOnly`,e)}async function Je(e,t){let n=Ye();return(await n[e].discover(t,n.requestScope)).map(e=>({...e}))}function Ye(){let t=Ue.getStore();if(!t)throw new e(`COMMAND_FAILED`,`Device inventory gateway is unavailable outside request execution`,{reason:He});return t}function Xe(t){return be(t)||t instanceof e&&t.code===`COMMAND_FAILED`&&t.details?.reason===He?!0:t instanceof Error&&t.name===`AbortError`}const M=new w;async function Ze(t,n,r){let i=await Qe(t,n,r);if(i)return i;let a=await et(t,n,r);if(r.allowLocalSimulatorFallback!==!1&&nt(n,a)){let e;try{[e]=await qe({platform:n.platform??`ios`,target:n.target,iosSimulatorSetPath:r.simulatorSetPath,kind:`simulator`})}catch(e){if(Xe(e))throw e}if(e)return e}if(a)return a;throw new e(`DEVICE_NOT_FOUND`,`No devices found`,{selector:n})}async function Qe(t,n,r){let i=r.appleSimulatorAppTarget?.trim();if(!i||N(n)||r.allowLocalSimulatorFallback===!1)return;let a=t.filter(e=>ae(e,n)&&h(e)&&e.kind===`simulator`&&e.booted===!0);if(a.length<2)return;let{findIosSimulatorInstalledApp:o}=await import(`./apps.js`).then(e=>e.t),s=(await Promise.all(a.map(async e=>await o(e,i)?e:void 0))).filter(e=>e!==void 0);if(s.length===1)return s[0];throw s.length===0?new e(`APP_NOT_INSTALLED`,`No booted iOS simulator has ${i} installed`,{appTarget:i,...$e(a),hint:`Install the app on a booted simulator, or pass --udid to select the intended device explicitly.`}):new e(`AMBIGUOUS_MATCH`,`Multiple booted iOS simulators have ${i} installed`,{appTarget:i,...$e(s),hint:`Pass --udid to select the intended simulator explicitly.`})}function $e(e){return{devices:e.map(e=>({id:e.id,name:e.name}))}}async function et(e,t,n){try{return await ie(e,t,n)}catch(e){if(tt(e,t))return;throw e}}function tt(t,n){return!N(n)&&t instanceof e&&t.code===`DEVICE_NOT_FOUND`}function nt(e,t){return!N(e)&&(!e.platform||e.platform===`apple`||e.platform===`ios`)&&e.target!==`desktop`&&(!t||t.kind===`device`)}function N(e){return!!(e.udid||e.serial||e.deviceName)}async function rt(e,t={}){let n=it(e),{iosSimulatorSetPath:r,...i}=n,a=ut(n,t),o={simulatorSetPath:r,allowStoppedAndroidAvdPlaceholders:t.allowStoppedAndroidAvdPlaceholders},s={platform:n.platform,target:e.target,cacheHit:!1};return await _e(`resolve_target_device`,async()=>{let e=ct(a);if(e)return s.cacheHit=!0,e;let c=await Ke(n),l=[...c.devices];return st(i)?lt(a,await Ze(l,i,{simulatorSetPath:r,allowLocalSimulatorFallback:c.source===`local`||n.leaseProvider===void 0,appleSimulatorAppTarget:t.appleSimulatorAppTarget})):lt(a,await ie(l,i,o))},s)}function it(t){let n=t.platform;if(t.target&&!n)throw new e(`INVALID_ARGS`,`Device target selector requires --platform. Use --platform ios|macos|android|vega|linux|apple with --target mobile|tv|desktop.`);let r=se({simulatorSetPath:Ce(t.iosSimulatorDeviceSet),platform:n,target:t.target}),i=Se(t.androidDeviceAllowlist);return{platform:n,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial,leaseId:t.leaseId,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId,iosSimulatorSetPath:r,androidSerialAllowlist:i?Array.from(i).sort():void 0}}async function at(e){return M.getStore()?await e():await M.run(new Map,e)}function ot(e){return v(e.platform)}function st(e){return ot(e)}function ct(e){let t=M.getStore()?.get(e);if(t)return{...t}}function lt(e,t){return M.getStore()?.set(e,{...t}),t}function ut(e,t){let{appleSimulatorAppTarget:n,...r}=t;return JSON.stringify({request:e,options:r})}const P=new Map;function dt(e){for(let t of e.platforms){if(P.has(t))throw Error(`PlatformPlugin already registered for platform "${t}"`);P.set(t,e)}}function ft(t){let n=P.get(t);if(!n)throw new e(`UNSUPPORTED_PLATFORM`,`Unsupported platform: ${t}`);return n}function F(e){return P.get(e)}const I={appAndDeviceLifecycle:!0,keyboard:!0,orientation:!0,physicalDeviceSurfaces:!1},pt={ios:I,ipados:I,visionos:{appAndDeviceLifecycle:!0,keyboard:!0,orientation:!0,physicalDeviceSurfaces:!1},tvos:{appAndDeviceLifecycle:!0,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!1},macos:{appAndDeviceLifecycle:!1,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!0},watchos:{appAndDeviceLifecycle:!1,keyboard:!1,orientation:!1,physicalDeviceSurfaces:!1}};function L(e){return v(e.platform)?pt[oe(e)]:void 0}const R=e=>{let t=L(e);return t?t.appAndDeviceLifecycle:!0},z=e=>e.platform!==`apple`||e.kind!==`device`||e.iosPhysicalDeviceBackend!==`xctest`,B=e=>R(e)&&z(e),mt=e=>{let t=L(e);return t?t.keyboard:e.platform===`android`},ht=e=>{let t=L(e);return t?t.orientation:e.platform===`android`},V=e=>{let t=L(e);return t&&t.physicalDeviceSurfaces||e.kind===`simulator`},gt=e=>e.platform===`android`||e.platform===`apple`&&oe(e)===`ios`||V(e),_t=e=>e.platform===`android`?e.target===`tv`:_(e),vt={[y.boot]:R,[y.apps]:z,[y.install]:B,[y.reinstall]:B,[y.installFromSource]:B,[y.perf]:z,[y.record]:z,[y.push]:R,[y.home]:R,[y.appSwitcher]:R,[y.clipboard]:e=>e.platform===`android`||e.platform===`linux`||V(e),[y.keyboard]:mt,[y.orientation]:ht,[y.tvRemote]:_t,[y.alert]:gt,[y.settings]:e=>e.platform===`android`||V(e),[y.audio]:te},yt={[y.apps]:H,[y.install]:H,[y.reinstall]:H,[y.installFromSource]:H,[y.perf]:H,[y.record]:H,[y.viewport]:e=>e.platform===`apple`?`viewport resizes web targets only (--platform web). Apple screen geometry is fixed by the selected simulator or device type — open a different simulator to test another screen size.`:void 0,[y.tvRemote]:e=>e.platform===`android`?e.target===`tv`?void 0:`tv-remote is supported only on Android TV targets.`:L(e)?_(e)?void 0:`tv-remote is supported only on tvOS devices.`:void 0};function H(e){if(!z(e))return`This command requires a CoreDevice-backed physical iOS device. The selected XCTest backend supports open, close, interactions, snapshots, and screenshots.`}const bt={id:`apple`,platforms:[`apple`],familySelector:`apple`,capability:{bucket:`apple`,supportsByDefault:vt,unsupportedHintByDefault:yt},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`apple`},recording:{resolveBackendTag:e=>g(e)?`macos`:e.kind===`device`?`ios-device`:`ios-simulator`},providers:{platformGatedResolvers:[`appleRunnerProvider`,`appleToolProvider`]},createInteractor:async(e,t)=>{let{createAppleInteractor:n}=await import(`./interactor.js`);return n(e,t)}},xt=[y.open,y.close,y.back,y.home,y.tvRemote],St=e=>e.target===`tv`,Ct=e=>e.kind===`emulator`&&St(e),wt={id:`vega`,platforms:[`vega`],capability:{bucket:`vega`,supportsByDefault:Object.fromEntries(xt.map(e=>[e,St])),unsupportedHintByDefault:Object.fromEntries(xt.map(e=>[e,t=>Ct(t)?void 0:`${e} currently supports only Vega Virtual Devices.`]))},providers:{platformGatedResolvers:[`vegaToolProvider`]},createInteractor:async(e,t)=>{let{createVegaInteractor:n}=await import(`./interactor2.js`);return n(e,t)}},Tt=[bt,{id:`android`,platforms:[`android`],capability:{bucket:`android`,supportsByDefault:{[y.audio]:te,[y.tvRemote]:e=>e.target===`tv`},unsupportedHintByDefault:{[y.tvRemote]:e=>e.target===`tv`?void 0:`tv-remote is supported only on Android TV targets.`}},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`android`},recording:{resolveBackendTag:()=>`android`},providers:{platformGatedResolvers:[`androidAdbProvider`]},createInteractor:async(e,t)=>{let{createAndroidInteractor:n}=await import(`./android.js`).then(e=>e.t);return n(e,void 0,t)}},{id:`harmonyos`,platforms:[`harmonyos`],capability:{bucket:`harmonyos`},perf:{supportsMetrics:()=>!0,metricsSamplerTag:()=>`harmonyos`},recording:{resolveBackendTag:e=>e.kind===`device`?`harmonyos`:`unsupported`},createInteractor:async(e,t)=>{let{createHarmonyInteractor:n}=await import(`./harmonyos.js`);return n(e,t)}},wt,{id:`linux`,platforms:[`linux`],capability:{bucket:`linux`},providers:{platformGatedResolvers:[`linuxToolProvider`]},createInteractor:async()=>{let{createLinuxInteractor:e}=await import(`./linux.js`);return e()}},{id:`web`,platforms:[`web`],capability:{bucket:`web`},recording:{resolveBackendTag:()=>`web`},providers:{platformGatedResolvers:[`webProvider`]},createInteractor:async()=>{let{createWebInteractor:e}=await import(`./web.js`);return e()}}];let Et=!1;function U(){if(!Et){for(let e of Tt)dt(e);Et=!0}}U();const Dt={device:!0},Ot={emulator:!0,device:!0},kt={device:!0},At=new Set(`open.perf.close.back.apps.appstate.app-switcher.click.fill.find.focus.get.home.gesture.install.keyboard.is.longpress.press.reinstall.screenshot.scroll.settings.snapshot.swipe.type.wait`.split(`.`)),jt=[`open`,`close`],Mt=[`record`],Nt=[`audio`,`find`,`get`,`is`,`screenshot`,`snapshot`,`wait`],Pt=[`click`,`fill`,`focus`,`press`,`scroll`,`type`],Ft=[`viewport`],It=new Set([...jt,...Mt,...Nt,...Pt,...Ft]),Lt=Rt(ne(re));function Rt(e){let t={};for(let[n,r]of Object.entries(e))t[n]=At.has(n)?{...r,harmonyos:Ot}:n===`record`?{...r,harmonyos:kt}:r;return zt(t)}function zt(e){let t={};for(let[n,r]of Object.entries(e))t[n]=It.has(n)?{...r,web:Dt}:r;for(let t of It)if(!(t in e))throw Error(`Web command "${t}" missing from capability matrix`);return t}function Bt(e,t){let n=Lt[e];if(!n)return!0;let r=F(t.platform);if(!r)return!1;let i=n[r.capability.bucket];if(!i)return!1;let a=r.capability.supportsByDefault?.[e];return a&&!a(t)?!1:i[t.kind??`unknown`]===!0}function Vt(e,t){return F(t.platform)?.capability.unsupportedHintByDefault?.[e]?.(t)}function Ht(){return re.filter(e=>`capability`in e&&e.capability!==void 0||e.platformExecution.kind===`device-runtime`).map(e=>e.name).sort()}function Ut(e){let t=Lt[e];if(!t)return[];let n=[`apple`,`android`,`harmonyos`,`vega`,`linux`,`web`],r=[];for(let e of n){let n=t[e];n&&Object.values(n).some(e=>e===!0)&&r.push(e)}return r}function Wt(e,t){if(e.intent===`drag`){Gt(e,t);return}if(t.platform===`web`||t.appleOs===`watchos`)throw G(e,W(e,t));if(qt(e)){Jt(e,t);return}if(t.appleOs===`visionos`)throw G(e,W(e,t));if(e.intent===`fling`&&`direction`in e&&t.platform===`linux`)throw G(e,`gesture fling is not supported on Linux`)}function Gt(e,t){if(!Kt(t))throw G(e,W(e,t),`Target-authored drag requires an adapter that preserves source hold, timed movement, and destination hold; it is supported on Android touch devices and iOS/iPadOS.`)}function Kt(e){return e.platform===`android`?e.target!==`tv`:e.platform===`apple`?e.appleOs===void 0?e.target!==`desktop`&&e.target!==`tv`:e.appleOs===`ios`||e.appleOs===`ipados`:!1}function qt(e){return e.intent===`pan`?(`pointerCount`in e?e.pointerCount:1)===2:e.intent===`pinch`||e.intent===`rotate`||e.intent===`transform`}function Jt(e,t){if(t.platform===`android`){if(t.target!==`tv`)return;throw G(e,`gesture ${e.intent} is not supported on Android TV`,`Android TV has no touch input — this gesture is supported on Android phones, tablets, and the iOS simulator only.`)}if(t.platform!==`apple`)throw G(e,W(e,t));ee(t,e.intent)}function W(e,t){return`gesture ${e.intent} is not supported on ${t.appleOs??t.platform}`}function G(t,n,r){return new e(`UNSUPPORTED_OPERATION`,n,{gesture:t.intent,...r?{hint:r}:{}})}const Yt=`No active session. Run open first.`;function Xt(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function Zt(){return Xt(`SESSION_NOT_FOUND`,Yt)}function Qt(e,t,n){if(Bt(e,t))return null;let r=n?.hint?Vt(e,t):void 0;return{ok:!1,error:{code:`UNSUPPORTED_OPERATION`,message:n?.message??`${e} is not supported on this device`,...r?{hint:r}:{}}}}const $t=/^[A-Za-z0-9_.:-]{1,64}$/,en=8*1024,tn=4*1024;function nn(t){let n=t[0]?.trim(),r=t[1]?.trim();if(!n)throw new e(`INVALID_ARGS`,`trigger-app-event requires <event> [payloadJson]`);if(!$t.test(n))throw new e(`INVALID_ARGS`,`Invalid trigger-app-event event name: ${n}`,{hint:`Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash.`});if(t.length>2)throw new e(`INVALID_ARGS`,`trigger-app-event accepts at most two arguments: <event> [payloadJson]`);return{eventName:n,payload:an(r,n)}}function rn(t,n,r){let i=m(t),a=on(t);if(!a)throw new e(`UNSUPPORTED_OPERATION`,`No app event URL template configured for ${i}.`,{hint:`Set AGENT_DEVICE_${i.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):``,s=a.replaceAll(`{event}`,encodeURIComponent(n)).replaceAll(`{payload}`,encodeURIComponent(o)).replaceAll(`{platform}`,encodeURIComponent(i));if(s.length>tn)throw new e(`INVALID_ARGS`,`trigger-app-event URL exceeds maximum supported length`,{hint:`Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.`,length:s.length,maxLength:tn});return s}function an(t,n){if(t)try{let r=JSON.parse(t);if(!r||typeof r!=`object`||Array.isArray(r))throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,`utf8`)>en)throw new e(`INVALID_ARGS`,`trigger-app-event payload for "${n}" exceeds ${en} bytes`);return r}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid trigger-app-event payload JSON: ${t}`)}}function on(e){return((h(e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:g(e)?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE)?.trim()||void 0}function sn(e){let t=e?e.textEntryReadiness:void 0,n=fn(t)?{textEntryReadiness:t}:{},r=cn(e);return r?{...n,...r}:n}function cn(e){if(!ln(e))return null;let t=un(e.target);return t?{verification:`unconfirmed`,requested:e.requested,before:e.before,after:e.after,target:t}:null}function ln(e){return!!(e&&e.verification===`unconfirmed`&&typeof e.requested==`string`&&K(e.before)&&K(e.after))}function un(e){if(!mn(e)||!dn(e))return null;let t=pn(e.rect);return t?{resourceId:e.resourceId,className:e.className,packageName:e.packageName,rect:t}:null}function dn(e){return K(e.resourceId)&&K(e.className)&&K(e.packageName)}function fn(e){return typeof e==`string`&&i.includes(e)}function K(e){return e===null||typeof e==`string`}function pn(e){return!mn(e)||![e.x,e.y,e.width,e.height].every(e=>typeof e==`number`)?null:e}function mn(e){return!!e&&typeof e==`object`}const q=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function hn(e,t){return v(e.platform)&&t>1}function gn(e,t,n=2e4){if(e.length===0)return[];let r=t>0?t:e.length,i=[],a=[],o=0;for(let t of e){let e=(t.durationMs??0)+(t.pauseMs??0)+250,s=a.length>0&&o+e>n,c=a.length>=r;(s||c)&&(i.push(a),a=[],o=0),a.push(t),o+=e}return a.length>0&&i.push(a),i}function _n(e,t){if(t<=0)return[0,0];let[n,r]=q[e%q.length];return[n*t,r*t]}async function vn(e,t,n){for(let r=0;r<e;r+=1)await n(r),r<e-1&&t>0&&await ye(t)}async function yn(e,t){let{x:n,y:r}=J(t,`longpress requires x y [durationMs]`,{hint:`Direct platform longpress requires coordinates. In an open daemon session, use agent-device longpress @ref|selector [durationMs]; otherwise run snapshot -i, use the target rect center as x y, then retry longpress x y durationMs.`}),i=t[2]?Number(t[2]):void 0;return await e.longPress(n,r,i),{x:n,y:r,durationMs:i,...x(`Long pressed (${n}, ${r})`)}}async function bn(e,t){let{x:n,y:r}=J(t,`focus requires x y`);return await e.focus(n,r),{x:n,y:r,...x(`Focused (${n}, ${r})`)}}async function xn(t,n,r){let i=Kn(n);if(i)throw new e(`INVALID_ARGS`,`type does not accept a target ref like "${i}"`,{hint:`Use fill ${i} "text" to target that field, or press ${i} then type "text" to append.`});let a=n.join(` `);if(!a)throw new e(`INVALID_ARGS`,`type requires text`);let o=S(r?.delayMs??0,`delay-ms`,0,1e4),s=(await t.type(a,o))?.textEntryRoute;return{...s===void 0?{}:{textEntryRoute:s},text:a,delayMs:o,...x(Z(`Typed`,a))}}async function Sn(t,n,r){if(r?.directElementSelector)return await Cn(t,r.directElementSelector,n,r);let i=Number(n[0]),a=Number(n[1]),o=n.slice(2).join(` `);if(Number.isNaN(i)||Number.isNaN(a)||!o)throw new e(`INVALID_ARGS`,`fill requires x y text`);let s=S(r?.delayMs??0,`delay-ms`,0,1e4),c=await t.fill(i,a,o,s,{allowNonHittableCoordinateFallback:r?.allowNonHittableCoordinateFallback===!0});return{x:i,y:a,text:o,delayMs:s,...c?.maestroNonHittableCoordinateFallbackUsed===!0?{maestroNonHittableCoordinateFallbackUsed:!0}:{},...sn(c),...x(Z(`Filled`,o))}}async function Cn(t,n,r,i){if(!t.fillElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector fill is not supported`);let a=r.join(` `);if(!a)throw new e(`INVALID_ARGS`,`fill requires text`);let o=S(i.delayMs??0,`delay-ms`,0,1e4),s=await t.fillElementSelector(n,a,o);return{selector:n.raw,text:a,delayMs:o,...s??{},...x(Z(`Filled`,a))}}async function wn(e,t,n,r){if(r?.directElementSelector&&h(e))return await Tn(t,r.directElementSelector);let{x:i,y:a}=J(n,`press requires x y`);if(g(e)&&r?.surface&&r.surface!==`app`)return await En(i,a,r);let o=c(r);if(o!==`primary`)return await Dn(e,i,a,o,r);let s=An(r);return jn(s),hn(e,s.count)?await Nn(e,i,a,s,r):await In(t,i,a,s)}async function Tn(t,n){if(!t.tapElementSelector)throw new e(`UNSUPPORTED_OPERATION`,`direct element selector tap is not supported`);let r=await t.tapElementSelector(n),i=r?.maestroNonHittableCoordinateFallbackUsed===!0;return{selector:n.raw,...r??{},...x(i?o:`Tapped ${n.raw}`)}}function J(t,n,r){let i=Number(t[0]),a=Number(t[1]);if(Number.isNaN(i)||Number.isNaN(a))throw new e(`INVALID_ARGS`,n,r);return{x:i,y:a}}async function En(t,n,r){let i=c(r);if(i!==`primary`)throw new e(`UNSUPPORTED_OPERATION`,`${i} click is not supported on macOS ${r.surface} sessions.`);let{runMacOsPressAction:a}=await import(`./helper.js`).then(e=>e.t);return await a(t,n,{bundleId:r.appBundleId,surface:r.surface}),{x:t,y:n,...x(X({x:t,y:n}))}}async function Dn(e,t,n,r,i){if(On(e,r,i),e.platform===`linux`)return await kn(t,n,r);let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o);return await a(e,{command:`mouseClick`,x:t,y:n,button:r,appBundleId:i?.appBundleId},Ln(i)),{x:t,y:n,button:r,...x(X({x:t,y:n,button:r}))}}function On(e,t,n){let r=s({commandLabel:`click`,platform:m(e),button:t,count:n?.count,intervalMs:n?.intervalMs,holdMs:n?.holdMs,jitterPx:n?.jitterPx,doubleTap:n?.doubleTap});if(r)throw r}async function kn(e,t,n){if(n===`secondary`){let{rightClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}else{let{middleClickLinux:n}=await import(`./input-actions3.js`);await n(e,t)}return{x:e,y:t,button:n,...x(X({x:e,y:t,button:n}))}}function An(e){return{count:Y(e?.count,1,`count`,1,200),intervalMs:Y(e?.intervalMs,0,`interval-ms`,0,1e4),holdMs:Y(e?.holdMs,0,`hold-ms`,0,1e4),jitterPx:Y(e?.jitterPx,0,`jitter-px`,0,100),doubleTap:!!e?.doubleTap}}function Y(e,t,n,r,i){return S(e===void 0?t:e,n,r,i)}function jn({doubleTap:t,holdMs:n,jitterPx:r}){if(t&&n>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with hold-ms`);if(t&&r>0)throw new e(`INVALID_ARGS`,`double-tap cannot be combined with jitter-px`)}async function Mn(e,t,n){let{runAppleRunnerCommand:r}=await import(`./runner-client.js`).then(e=>e.o),{MAX_RUNNER_SEQUENCE_STEPS:i,buildRunnerSequenceCommand:a,parseRunnerSequenceResult:o}=await import(`./runner-sequence.js`).then(e=>e.r),s=gn(t,i),c,l,u=0,d=[],f=0;for(let t of s){let i=await r(e,a(t,n?.appBundleId),Ln(n));c??=i,l=i;let s;try{s=o(i)}catch(e){throw Fn(e,f)}u+=s.completedSteps,d.push(...s.results),f+=t.length}return{...c??{},completedSteps:u,sequenceResults:d,...l?.gestureEndUptimeMs===void 0?{}:{gestureEndUptimeMs:l.gestureEndUptimeMs}}}async function Nn(e,t,n,r,i){let a=await Mn(e,Pn(e,t,n,r),i);return{x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,timingMode:`runner-sequence`,...a,...x(X({x:t,y:n}))}}function Pn(e,t,n,r){let i=r.doubleTap?`doubleTap`:r.holdMs>0?`longPress`:`tap`,a=i===`tap`&&h(e)&&!_(e);return Array.from({length:r.count},(e,o)=>{let[s,c]=_n(o,r.jitterPx),l=o===r.count-1;return{kind:i,x:t+s,y:n+c,...a?{synthesized:!0}:{},...r.holdMs>0?{durationMs:r.holdMs}:{},...!l&&r.intervalMs>0?{pauseMs:r.intervalMs}:{}}})}function Fn(t,n){if(n===0||!(t instanceof e)||!t.details)return t;let r=t.details.failedStepIndex;if(typeof r!=`number`)return t;let i=t.details.completedSteps;return new e(t.code,t.message,{...t.details,failedStepIndex:r+n,chunkStepIndex:r,...typeof i==`number`?{completedSteps:n+i}:{}},t.cause)}async function In(e,t,n,r){let i;return await vn(r.count,r.intervalMs,async a=>{let[o,s]=_n(a,r.jitterPx),c=t+o,l=n+s;if(r.doubleTap){let t=await e.doubleTap(c,l);i??=t??void 0;return}if(r.holdMs>0){let t=await e.longPress(c,l,r.holdMs);i??=t??void 0}else{let t=await e.tap(c,l);i??=t??void 0}}),b({x:t,y:n,count:r.count,intervalMs:r.intervalMs,holdMs:r.holdMs,jitterPx:r.jitterPx,doubleTap:r.doubleTap,...i},X({x:t,y:n}))}function Ln(e){return{verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,requestId:e?.requestId,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir}}async function Rn(t,n,r){let i=n[0],a=n[1]?Number(n[1]):void 0,o=r?.pixels,s=r?.durationMs;if(!i)throw new e(`INVALID_ARGS`,`scroll requires direction`);zn(a,o,s);let c=Wn(i),l={amount:a,pixels:o,durationMs:s},{interactionResult:u,completedPasses:d}=await Vn(t,r,c,l);return b(Hn(c,l,d,u),de(c.direction,c.edge,d,a,o))}function zn(e,n,i){Bn(e),r(i),t({amount:e,pixels:n})}function Bn(t){if(t!==void 0&&!Number.isFinite(t))throw new e(`INVALID_ARGS`,`scroll amount must be a number`)}async function Vn(e,t,n,r){if(n.edge){let i=n.edge,a=await pe({edge:i,captureState:async n=>await Un(e,t,i,n),scroll:async()=>await e.scroll(n.direction,r)});return{interactionResult:a.result??{},completedPasses:a.passes}}return{interactionResult:await e.scroll(n.direction,r)??{},completedPasses:1}}function Hn(e,t,n,r){let i=l(r);return{direction:e.direction,...e.edge?{edge:e.edge,passes:n}:{},...t.amount===void 0?{}:{amount:t.amount},...t.pixels===void 0?{}:{pixels:t.pixels},...i===void 0?{}:{durationMs:i},...r}}async function Un(t,n,r,i){if(typeof t.snapshot!=`function`)throw new e(`UNSUPPORTED_OPERATION`,`scroll ${r} requires snapshot support to verify hidden content before scrolling`);let a=t.snapshot;return await ue({edge:r,scope:i,captureNodes:async e=>(await a({appBundleId:n?.appBundleId,scope:e})).nodes??[]})}function Wn(e){return e===`bottom`?{direction:`down`,edge:`bottom`}:e===`top`?{direction:`up`,edge:`top`}:{direction:d(e)}}async function Gn(e,t,n){let{x:r,y:i}=J(t,`read requires x y`);if(e.platform===`android`){let{readAndroidTextAtPoint:t}=await import(`./input-actions.js`).then(e=>e.s);return{action:`read`,text:await t(e,r,i)??``}}if(e.platform===`linux`){let{readLinuxTextAtPoint:e}=await import(`./snapshot.js`).then(e=>e.n);return{action:`read`,text:await e(r,i,n?.surface)}}if(g(e)&&n?.surface&&n.surface!==`app`){let{runMacOsReadTextAction:e}=await import(`./helper.js`).then(e=>e.t);return{action:`read`,text:(await e(r,i,{bundleId:n.appBundleId,surface:n.surface})).text}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(e,{command:`readText`,x:r,y:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId,iosXctestrunFile:n?.iosXctestrunFile,iosXctestDerivedDataPath:n?.iosXctestDerivedDataPath,iosXctestEnvDir:n?.iosXctestEnvDir});return{action:`read`,text:typeof o.text==`string`?o.text:typeof o.message==`string`?o.message:``}}function Kn(e){return ge(e[0])}function X(e){return e.button&&e.button!==`primary`?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function Z(e,t){return`${e} ${Array.from(t).length} chars`}function qn(e){let t=e.trim();return t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)}function Jn(t,n){let r=n?.subject??`Payload`,i=t.trim();if(!i)throw new e(`INVALID_ARGS`,`${r} cannot be empty`);let a=n?.expandPath?n.expandPath(i,n.cwd):i;try{if(!Te.statSync(a).isFile())throw new e(`INVALID_ARGS`,`${r} path is not a file: ${a}`);return{kind:`file`,path:a}}catch(t){if(t instanceof e)throw t;let n=t.code;if(n===`EACCES`||n===`EPERM`)throw new e(`INVALID_ARGS`,`${r} file is not readable: ${a}`);if(n&&n!==`ENOENT`)throw new e(`COMMAND_FAILED`,`Unable to read ${r} file: ${a}`,{cause:String(t)})}if(qn(i))return{kind:`inline`,text:i};throw new e(`INVALID_ARGS`,`${r} file not found: ${a}`)}async function Yn(t){let n=Jn(t,{subject:`Push payload`}),r=n.kind===`inline`?n.text:await Xn(n.path);try{let t=JSON.parse(r);if(!t||typeof t!=`object`||Array.isArray(t))throw new e(`INVALID_ARGS`,`push payload must be a JSON object`);return t}catch(n){throw n instanceof e?n:new e(`INVALID_ARGS`,`Invalid push payload JSON: ${t}`)}}async function Xn(t){try{return await T.readFile(t,`utf8`)}catch(n){let r=n.code;throw r===`ENOENT`?new e(`INVALID_ARGS`,`Push payload file not found: ${t}`):r===`EISDIR`?new e(`INVALID_ARGS`,`Push payload path is not a file: ${t}`):r===`EACCES`||r===`EPERM`?new e(`INVALID_ARGS`,`Push payload file is not readable: ${t}`):new e(`COMMAND_FAILED`,`Unable to read push payload file: ${t}`,{cause:String(n)})}}U();async function Q(t,n){if(D(t)){let r=Oe(t,n);if(r)return r;throw new e(`UNSUPPORTED_OPERATION`,`Provider device runtime does not have an active interactor for this device.`,{deviceId:t.id,platform:m(t)})}return await ft(t.platform).createInteractor(t,n)}async function Zn(e,t,n,r,i){let a=$(i),o=await Q(e,a);return C({level:`debug`,phase:`platform_command_prepare`,data:{command:t,platform:e.platform,kind:e.kind}}),await _e(`platform_command`,async()=>await tr(e,o,t,n,r,i,a),{command:t,platform:e.platform})}async function Qn(t,n,r){let i=await Q(t,$(r));if(!i.performGesture)throw new e(`UNSUPPORTED_OPERATION`,`Gesture execution is unavailable`);return await i.performGesture(n)}async function $n(e,t){return await(await Q(e,$(t))).gestureViewport?.()}function $(e){return{requestId:e?.requestId,signal:e?.signal,appBundleId:e?.appBundleId,verbose:e?.verbose,logPath:e?.logPath,traceLogPath:e?.traceLogPath,iosXctestrunFile:e?.iosXctestrunFile,iosXctestDerivedDataPath:e?.iosXctestDerivedDataPath,iosXctestEnvDir:e?.iosXctestEnvDir,runnerLeaseContext:e?.runnerLeaseContext}}const er={open:({device:e,interactor:t,positionals:n,context:r})=>nr(e,t,n,r),close:async({device:e,interactor:t,positionals:n})=>{let r=n[0];return r?(await t.close(r),{app:r,...x(`Closed: ${r}`)}):(e.platform===`web`&&await t.close(``),{closed:`session`,...x(`Closed session`)})},press:({device:e,interactor:t,positionals:n,context:r})=>wn(e,t,n,r),longpress:({interactor:e,positionals:t})=>yn(e,t),focus:({interactor:e,positionals:t})=>bn(e,t),type:({interactor:e,positionals:t,context:n})=>xn(e,t,n),fill:({interactor:e,positionals:t,context:n})=>Sn(e,t,n),scroll:({interactor:e,positionals:t,context:n})=>Rn(e,t,n),"trigger-app-event":({device:e,interactor:t,positionals:n,context:r})=>rr(e,t,n,r),screenshot:({interactor:e,positionals:t,outPath:n,context:r})=>ir(e,t,n,r),viewport:({interactor:e,positionals:t})=>ar(e,t),back:async({interactor:e,context:t})=>(await e.back(t?.backMode),{action:`back`,mode:t?.backMode??`in-app`,...x(`Back`)}),home:async({interactor:e})=>(await e.home(),{action:`home`,...x(`Home`)}),orientation:async({interactor:e,positionals:t})=>{let n=he(t[0]),r=(await e.setOrientation(n))?.orientation??n;return{action:`orientation`,orientation:r,...x(`Rotated to ${r}`)}},"app-switcher":async({interactor:e})=>(await e.appSwitcher(),{action:`app-switcher`,...x(`Opened app switcher`)}),clipboard:({interactor:e,positionals:t})=>or(e,t),keyboard:({device:e,positionals:t,context:n,runnerCtx:r})=>cr(e,t,n,r),"tv-remote":({device:e,interactor:t,positionals:n,context:r})=>sr(e,t,n,r),settings:({device:e,interactor:t,positionals:n,context:r})=>pr(e,t,n,r),push:({device:e,positionals:t,context:n})=>vr(e,t,n),snapshot:({interactor:e,context:t})=>yr(e,t),read:({device:e,positionals:t,context:n})=>Gn(e,t,n)};async function tr(t,n,r,i,a,o,s){let c=Object.hasOwn(er,r)?er[r]:void 0;if(!c)throw new e(`INVALID_ARGS`,`Unknown command: ${r}`);return await c({device:t,interactor:n,positionals:i,outPath:a,context:o,runnerCtx:s})}async function nr(t,n,r,i){let a=r[0],o=r[1],s=i?.launchConsole,c=i?.launchArgs;if(r.length>2)throw new e(`INVALID_ARGS`,`open accepts at most two arguments: <app|url> [url]`);if(!a){if(s)throw new e(`INVALID_ARGS`,`--launch-console requires an app target`);if(c&&c.length>0)throw new e(`INVALID_ARGS`,`--launch-args requires an app target`);return await n.openDevice(),{app:null,...x(`Opened device`)}}if(s&&(!h(t)||t.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,le);if(t.platform===`linux`&&c&&c.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on Linux.`);if(o!==void 0){if(p(a))throw new e(`INVALID_ARGS`,`open <app> <url> requires an app target as the first argument`);if(!p(o))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(s)throw new e(`INVALID_ARGS`,ce);return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchArgs:c,terminateRunningApp:i?.terminateRunningApp,url:o}),{app:a,url:o,...x(`Opened: ${a}`)}}if(s&&p(a))throw new e(`INVALID_ARGS`,ce);if(i?.clearAppState){if(p(a))throw new e(`INVALID_ARGS`,`Clearing app state requires an app target, not a deep link.`);await n.setSetting(`clear-app-state`,`clear`,a)}return await n.open(a,{activity:i?.activity,appBundleId:i?.appBundleId,launchConsole:s,launchArgs:c,terminateRunningApp:i?.terminateRunningApp}),{app:a,...s?{launchConsole:s}:{},...x(`Opened: ${a}`)}}async function rr(e,t,n,r){let{eventName:i,payload:a}=nn(n),o=rn(e,i,a);return await t.open(o,{appBundleId:r?.appBundleId}),{event:i,eventUrl:o,transport:`deep-link`,...x(`Triggered app event: ${i}`)}}async function ir(e,t,r,i){let a=t[0]??r??`./screenshot-${Date.now()}.png`;await T.mkdir(we.dirname(a),{recursive:!0});let o=n(i);return await e.screenshot(a,{appBundleId:i?.appBundleId,pixelDensity:o.pixelDensity,fullscreen:o.fullscreen,normalizeStatusBar:o.normalizeStatusBar,stabilize:o.stabilize,surface:i?.surface,skipIosSimulatorBootCheck:i?.skipIosSimulatorBootCheck,captureBackend:i?.screenshotCaptureBackend}),{path:a,...x(`Saved screenshot: ${a}`)}}async function ar(t,n){if(n.length!==2)throw new e(`INVALID_ARGS`,`viewport requires exactly two arguments: <width> <height>`);let r=fe(n[0],`width`),i=fe(n[1],`height`);if(!t.setViewport)throw new e(`UNSUPPORTED_OPERATION`,`viewport is not supported by this backend`);return await t.setViewport(r,i),{width:r,height:i,...x(`Viewport set: ${r}x${i}`)}}async function or(t,n){let r=(n[0]??``).toLowerCase();if(r!==`read`&&r!==`write`)throw new e(`INVALID_ARGS`,`clipboard requires a subcommand: read or write`);if(r===`read`){if(n.length!==1)throw new e(`INVALID_ARGS`,`clipboard read does not accept additional arguments`);return{action:r,text:await t.readClipboard()}}if(n.length<2)throw new e(`INVALID_ARGS`,`clipboard write requires text (use "" to clear clipboard)`);let i=n.slice(1).join(` `);return await t.writeClipboard(i),{action:r,textLength:Array.from(i).length,...x(`Clipboard updated`)}}async function sr(t,n,r,i){if(t.target!==`tv`)throw new e(`UNSUPPORTED_OPERATION`,`tv-remote is supported only on TV targets`,{hint:`Select an Android TV, tvOS, or Vega OS target with --target tv.`});if(r.length!==1)throw new e(`INVALID_ARGS`,`tv-remote requires exactly one button`);let a=f(r[0]),o=i?.durationMs===void 0?void 0:S(i.durationMs,`durationMs`,0,1e4);return await n.tvRemote(a,o),{action:`tv-remote`,button:a,...o===void 0?{}:{durationMs:o},...x(`Pressed TV remote ${a}`)}}async function cr(t,n,r,i){let a=(n[0]??`status`).toLowerCase();if(!me(a))throw new e(`INVALID_ARGS`,`keyboard requires a subcommand: status, get, dismiss, enter, or return`);if(n.length>1)throw new e(`INVALID_ARGS`,`keyboard accepts at most one subcommand argument`);if(t.platform===`android`)return await ur(t,a);if(t.platform===`harmonyos`)return await lr(t,a);if(h(t))return await dr(t,a,r,i);throw new e(`UNSUPPORTED_OPERATION`,`keyboard is supported only on Android, HarmonyOS, and iOS`)}async function lr(t,n){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is not available through the public HarmonyOS HDC API; use keyboard dismiss or enter`);let{pressHarmonyKeyboardKey:r}=await import(`./input-actions2.js`);return await r(t,n===`dismiss`?`Back`:`Enter`),{platform:`harmonyos`,action:n===`dismiss`?`dismiss`:`enter`,...x(n===`dismiss`?`Keyboard dismissed`:`Keyboard enter pressed`)}}async function ur(e,t){if(t===`enter`||t===`return`){let{pressAndroidEnter:t}=await import(`./input-actions.js`).then(e=>e.s);return await t(e),{platform:`android`,action:`enter`,...x(`Keyboard enter pressed`)}}if(t===`dismiss`){let{dismissAndroidKeyboard:t}=await import(`./device-input-state.js`).then(e=>e.t),n=await t(e);return{platform:`android`,action:`dismiss`,attempts:n.attempts,wasVisible:n.wasVisible,dismissed:n.dismissed,visible:n.visible,inputType:n.inputType,type:n.type,inputMethodPackage:n.inputMethodPackage,focusedPackage:n.focusedPackage,focusedResourceId:n.focusedResourceId,inputOwner:n.inputOwner}}let{getAndroidKeyboardState:n}=await import(`./device-input-state.js`).then(e=>e.t),r=await n(e);return{platform:`android`,action:`status`,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}async function dr(t,n,r,i){if(n!==`dismiss`&&n!==`enter`&&n!==`return`)throw new e(`UNSUPPORTED_OPERATION`,`keyboard status/get is currently supported only on Android; use keyboard dismiss or enter on iOS`);if(n===`enter`||n===`return`){let{runAppleRunnerCommand:e}=await import(`./runner-client.js`).then(e=>e.o),n=await e(t,{command:`keyboardReturn`,appBundleId:r?.appBundleId},i);return{platform:`ios`,action:`enter`,visible:n.visible,wasVisible:n.wasVisible,...x(`Keyboard enter pressed`)}}let{runAppleRunnerCommand:a}=await import(`./runner-client.js`).then(e=>e.o),o=await a(t,{command:`keyboardDismiss`,appBundleId:r?.appBundleId},i),s=typeof o.keyboardDismissMechanism==`string`?o.keyboardDismissMechanism:void 0;return{platform:`ios`,action:`dismiss`,wasVisible:o.wasVisible,dismissed:o.dismissed,visible:o.visible,mechanism:s,...x(fr(o.dismissed===!0,s))}}function fr(e,t){return e?t===`dismissKey`?`Keyboard dismissed via its dismiss key`:`Keyboard dismissed`:`Keyboard already hidden`}async function pr(t,n,r,i){let[a,o,s,c]=r;if(!a||!o&&a!==`clear-app-state`)throw new e(`INVALID_ARGS`,`settings requires setting state`);if(a===`clear-app-state`)return await mr(t,n,o,s,i);if(!o)throw new e(`INVALID_ARGS`,`settings requires setting state`);return await hr(t,n,a,o,s,c,r,i)}async function mr(t,n,r,i,a){let o=(r===`clear`?i:r)??a?.appBundleId;if(!o)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);C({level:`debug`,phase:`settings_apply`,data:{setting:`clear-app-state`,state:`clear`,appBundleId:o,platform:t.platform}});let s=await n.setSetting(`clear-app-state`,`clear`,o);return s&&typeof s==`object`?b({setting:`clear-app-state`,state:`clear`,...s},br(s)??`Cleared user data for ${o}`):{setting:`clear-app-state`,state:`clear`,...x(`Cleared user data for ${o}`)}}async function hr(e,t,n,r,i,a,o,s){let c=n===`location`&&r===`set`,l=(n===`permission`||c?o[4]:o[2])??s?.appBundleId;C({level:`debug`,phase:`settings_apply`,data:_r(e,n,r,i,a,l,c)});let u=await t.setSetting(n,r,l,gr(n,i,a,c));return u&&typeof u==`object`?b({setting:n,state:r,...u},br(u)??`Updated setting: ${n}`):{setting:n,state:r,...x(`Updated setting: ${n}`)}}function gr(e,t,n,r){if(e===`permission`)return{permissionTarget:t,permissionMode:n};if(r)return{latitude:u(t,`latitude`),longitude:u(n,`longitude`)}}function _r(e,t,n,r,i,a,o){return o?{setting:t,state:n,latitude:r,longitude:i,platform:e.platform}:t===`permission`?{setting:t,state:n,permissionTarget:r,permissionMode:i,platform:e.platform}:{setting:t,state:n,appBundleId:a,platform:e.platform}}async function vr(t,n,r){let i=n[0]?.trim(),a=n[1]?.trim();if(!i||!a)throw new e(`INVALID_ARGS`,`push requires <bundle|package> <payload.json|inline-json>`);let o=await Yn(a);if(h(t)){let{pushIosNotification:e}=await import(`./apps.js`).then(e=>e.t);return await e(t,i,o),{platform:`ios`,bundleId:i,...x(`Pushed notification to ${i}`)}}let{pushAndroidNotification:s}=await import(`./notifications.js`),c=await s(t,i,o);return{platform:`android`,package:i,action:c.action,extrasCount:c.extrasCount,...x(`Pushed notification to ${i}`)}}async function yr(e,t){let n=t??{};return await e.snapshot({appBundleId:n.appBundleId,signal:n.signal,interactiveOnly:n.snapshotInteractiveOnly,preferredBackend:n.snapshotPreferredBackend,depth:n.snapshotDepth,scope:n.snapshotScope,raw:n.snapshotRaw,customActions:n.snapshotCustomActions,includeRects:n.snapshotIncludeRects,includeHiddenContentHints:n.snapshotIncludeHiddenContentHints,surface:n.surface})}function br(e){return typeof e.message==`string`&&e.message.length>0?e.message:void 0}function xr(e,t,n,r,i,o){return{requestId:i??ve().requestId,appBundleId:n,runnerLeaseContext:xe({meta:o}),activity:t?.activity,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,clearAppState:t?.clearAppState,verbose:t?.verbose,logPath:e,traceLogPath:r,iosXctestrunFile:t?.iosXctestrunFile,iosXctestDerivedDataPath:t?.iosXctestDerivedDataPath,iosXctestEnvDir:t?.iosXctestEnvDir,screenshotCaptureBackend:t?.maestro?.screenshotCaptureBackend,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotPreferredBackend:t?.snapshotPreferredBackend,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,snapshotCustomActions:t?.snapshotCustomActions,snapshotIncludeHiddenContentHints:t?.snapshotIncludeHiddenContentHints,...a(t),count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,durationMs:t?.durationMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:c(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}export{je as C,D,Ae as E,We as S,ke as T,rt as _,Jn as a,qe as b,Zt as c,Ht as d,Wt as f,it as g,F as h,$n as i,Qt as l,U as m,Zn as n,Yt as o,Ut as p,Qn as r,Xt as s,xr as t,Bt as u,at as v,Me as w,Xe as x,Ge as y};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"node:path";import t from"node:fs";function n(e,n){let r={providerReleases:{released:n.released.map(o),pending:n.pending.map(o)}},i=a(e),s=`${i}.${process.pid}.${Date.now()}.tmp`;try{t.writeFileSync(s,`${JSON.stringify(r)}\n`,{mode:384}),t.renameSync(s,i),t.chmodSync(i,384)}catch{try{t.rmSync(s,{force:!0})}catch{}}}function r(e){try{let n=JSON.parse(t.readFileSync(a(e),`utf8`));return s(n)?n:null}catch{return null}}function i(e){try{t.rmSync(a(e),{force:!0})}catch{}}function a(t){return e.join(t,`daemon-shutdown.json`)}function o(e){return{leaseId:e.leaseId,...e.leaseProvider?{provider:e.leaseProvider}:{}}}function s(e){if(!e||typeof e!=`object`)return!1;let t=e.providerReleases;if(!t||typeof t!=`object`)return!1;let n=t;return Array.isArray(n.released)&&Array.isArray(n.pending)&&n.released.every(c)&&n.pending.every(c)}function c(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.leaseId==`string`&&t.leaseId.trim().length>0&&(t.provider===void 0||typeof t.provider==`string`)}export{r as n,n as r,i as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{_ as t,d as n,p as r}from"./screenshot-result.js";import{t as i}from"./timeouts.js";import{d as a,n as o}from"./host-process.js";import{n as s}from"./daemon-shutdown-report.js";import{t as c}from"./shared.js";import l from"node:fs";async function u(t){let r=p(t.paths.infoPath);if(!r)return g();if(!r.processStartTime){if(!o(r.pid))return g();throw new e(`COMMAND_FAILED`,`Refusing to stop a daemon without a verified process start-time identity.`,{pid:r.pid})}if(!n(r.pid,r.processStartTime)){if(!o(r.pid))return g();throw new e(`COMMAND_FAILED`,`Refusing to stop a daemon whose PID or start-time identity could not be verified.`,{pid:r.pid,processStartTime:r.processStartTime})}if(!d(r.pid,`SIGTERM`))return g();if(await a(r.pid,t.graceTimeoutMs??1e4))return await h(t.paths,1e3),{stopped:!0,mode:`graceful`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]};if(n(r.pid,r.processStartTime)&&d(r.pid,`SIGKILL`),!await a(r.pid,t.killTimeoutMs??2e3))throw new e(`COMMAND_FAILED`,`Daemon did not exit after SIGKILL.`,{pid:r.pid});return{stopped:!0,mode:`forced`,cleanupConfidence:`unknown`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`unknown`,released:[],pending:null},warnings:[`The daemon was force-killed before provider lease state could be finalized. Provider allocations may remain active.`]}}function d(t,n){if(r(t,n))return!0;if(!o(t))return!1;throw new e(`COMMAND_FAILED`,`Daemon could not be signaled with ${n}.`,{pid:t,signal:n})}function f(e){let t=p(e);return t?.processStartTime?{pid:t.pid,processStartTime:t.processStartTime}:null}function p(e){try{let t=JSON.parse(l.readFileSync(e,`utf8`)),n=t.pid;return typeof n!=`number`||!Number.isInteger(n)||n<=0?null:{pid:n,...m(t.processStartTime)?{processStartTime:t.processStartTime}:{}}}catch{return null}}function m(e){return typeof e==`string`&&e.trim().length>0}async function h(e,t){let n=Date.now();for(;Date.now()-n<t;){if(!l.existsSync(e.infoPath)&&!l.existsSync(e.lockPath))return;await i(25)}}function g(){return{stopped:!1,mode:`not-running`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]}}const _=async({positionals:n,flags:r})=>{if(n[0]!==`stop`||n.length!==1)throw new e(`INVALID_ARGS`,`daemon accepts only: stop`);let i=t(r.stateDir),a=f(i.infoPath),o=await u({paths:i}),l=v(o,o.mode===`graceful`?s(i.baseDir):null),d=r.clean===!0&&a!==null&&l.stopped;if(d){let[{cleanupRunnerLeasesForOwner:e},{runnerLeaseCleanupAdapter:t}]=await Promise.all([import(`./runner-lease.js`).then(e=>e.c),import(`./runner-disposal.js`).then(e=>e.s)]);await e({pid:a.pid,startTime:a.processStartTime},t)}let p={...l,clean:d};return c(r,p,()=>y(p)),!0};function v(e,t){return e.mode!==`graceful`||t?t?{...e,providerReleases:{status:`completed`,...t.providerReleases}}:e:{...e,cleanupConfidence:`unknown`,providerReleases:{status:`unknown`,released:[],pending:null},warnings:[...e.warnings,`The graceful shutdown report is unavailable, so provider cleanup state is unknown. Provider allocations may remain active.`]}}function y(e){return[e.stopped?`Daemon stopped (${e.mode}).`:`No running daemon found.`,e.clean?`Retained runner cleanup completed.`:null,...e.warnings].filter(e=>!!e).join(`
|
|
2
|
+
`)}export{_ as daemonCommand};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{Wn as t}from"./sdk-batch-runner.js";import{_ as n,m as r}from"./sdk-android-adb.js";import i from"node:path";import a from"node:fs/promises";const o=/^[0-9a-fA-F-]{32,36}$/;function s(e){if(!(!e||!o.test(e)))return e.replaceAll(`-`,``).toUpperCase()}function c(e,t){return`${e.uuid}:${l(t)}`}function l(e){return`0x${e.toString(16)}`}function u(e){return typeof e==`string`&&e.length>0?e:void 0}function d(...e){for(let t of e){let e=u(t);if(e)return e}}function f(e){let t=e.filter(e=>!!e);return t.length>0?t.join(` `):void 0}function p(e){try{let n=JSON.parse(e);return t(n)?n:null}catch{return null}}function m(e){if(typeof e==`number`&&Number.isSafeInteger(e))return e;if(typeof e==`string`){let t=e.startsWith(`0x`)?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function h(e,t,n){if(!Object.hasOwn(e,t))return;let r=m(e[t]);if(r!==void 0)return r;v(n,t)}function g(e,t,n){if(!Object.hasOwn(e,t))return;let r=_(e[t]);if(r!==void 0)return r;v(n,t)}function _(e){if(typeof e==`bigint`)return e;if(typeof e==`number`&&Number.isSafeInteger(e)||typeof e==`string`&&/^(?:0x[0-9a-fA-F]+|\d+)$/.test(e))return BigInt(e)}function v(t,n){throw new e(`INVALID_ARGS`,`Invalid ${t} numeric field: ${n}`,{hint:`Crash artifact numeric fields must be integer numbers or integer numeric strings.`})}function y(e){return e.length===1?e[0]:void 0}function b(e){return[...new Set(e)]}function x(e){let t=e.match(/^(.*) \+ (\d+)$/);return t?{symbol:t[1],location:Number(t[2])}:{symbol:e}}const S=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;function ee(e){return te(e)??w(e)}function te(e){let t=ne(e);if(!t)return null;let n=(Array.isArray(t.payload.usedImages)?t.payload.usedImages:[]).flatMap((e,t)=>C(e,t));if(n.length===0)return null;let r=re(Array.isArray(t.payload.threads)?t.payload.threads:[],n);return{format:`ips`,images:n,addresses:r.map(({frame:e,...t})=>t),document:t,frameMatches:r,write:e=>oe(t,r,e)}}function ne(e){let t=p(e);if(t)return{payload:t};let n=e.indexOf(`
|
|
2
2
|
`);if(n===-1)return null;let r=e.slice(0,n),i=p(e.slice(n+1));return i?{header:r,payload:i}:null}function re(e,t){let n=new Map(t.map(e=>[e.index,e]));return e.flatMap((e,t)=>ie(e).flatMap((e,r)=>ae(e,n,t,r)))}function ie(e){return!t(e)||!Array.isArray(e.frames)?[]:e.frames.filter(t)}function ae(e,t,n,r){let i=h(e,`imageIndex`,`IPS frame`),a=g(e,`imageOffset`,`IPS frame`);if(i===void 0||a===void 0)return[];let o=t.get(i);return o?[{frame:e,frameIndex:r,threadIndex:n,image:o,address:o.base+a}]:[]}function oe(e,t,n){for(let e of t){let t=n.get(c(e.image,e.address))?.text;t&&se(e.frame,t)}e.payload.agentDeviceSymbolication={tool:`agent-device debug symbols`,symbolicatedFrames:[...n.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}\n`;return e.header?`${e.header}\n${r}`:r}function se(e,t){let n=x(t);e.symbol=n.symbol,n.location!==void 0&&(e.symbolLocation=n.location)}function C(e,n){if(!t(e))return[];let r=s(u(e.uuid)),a=g(e,`base`,`IPS usedImages`);if(!r||a===void 0)return[];let o=u(e.path);return[{index:n,name:u(e.name)??(o?i.basename(o):`image-${n}`),uuid:r,arch:u(e.arch),base:a,path:o}]}function w(e){let t=e.split(`
|
|
3
3
|
`),n=T(t);if(n.length===0)return null;let r=O(t,n);return{format:`text`,images:n,addresses:r,lines:t,frameMatches:r,write(e){let n=new Map(r.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let i=n.get(r);if(!i)return t;let a=e.get(c(i.image,i.address))?.text;return!a||t.includes(a)?t:`${t} // ${a}`}).join(`
|
|
4
|
-
`)}}}function T(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=E(r);e&&t.push(e)}return t}function E(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=s(t[4]);if(!n)return null;let r=D(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function D(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&S.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let a=i.basename(t);return{name:e.startsWith(a)?a:e}}function O(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=k(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function k(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=A(t,r,i);return a?{image:a,address:i}:null}function A(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>j(e,n))??y(r)}function j(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const M=1e4;async function N(e){return e.dsym&&e.searchPath?[H(e.cwd,e.dsym),...await P(H(e.cwd,e.searchPath))]:e.dsym?[H(e.cwd,e.dsym)]:e.searchPath?await P(H(e.cwd,e.searchPath)):[]}async function P(t){let n=[],r=0;async function o(s){if(n.length>=200)return;if(r+=1,r>M)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:M,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await F(s,t)).isDirectory()){s===t&&I(t);return}if(s.endsWith(`.dSYM`)){n.push(s);return}let c=await a.readdir(s,{withFileTypes:!0});for(let e of c)e.isDirectory()&&await o(i.join(s,e.name))}return await o(t),n}async function F(t,n){try{return await a.stat(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function I(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function L(t,n){let r=(await Promise.all(b(t).map(e=>R(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function R(e,t){return await z(e),B(e,
|
|
5
|
-
`).flatMap(t=>{let n=t.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=s(n?.[1]);return n&&r?[{dsymPath:e,uuid:r,arch:n[2],binaryPath:n[3].trim()}]:[]})}function V(t,n,r){let i=new Map;for(let e of t){let t=n.find(t=>t.uuid===e.uuid&&(e.arch===void 0||t.arch===void 0||t.arch===e.arch));t&&i.set(e.uuid,{image:e,dsym:t})}if(i.size>0)return i;let a=b(t.map(e=>e.uuid)),o=b(n.map(e=>e.uuid));throw new e(`COMMAND_FAILED`,r?`dSYM UUID does not match any Apple image in the crash artifact.`:`No matching dSYM UUID found under search path.`,{artifactUuidCount:a.length,artifactUuidSample:a.slice(0,5),dsymUuidCount:o.length,dsymUuidSample:o.slice(0,5),hint:`Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path.`})}function H(e,t){return i.resolve(e,t)}function U(e,t){return e.format===`ips`?W(e.document,e.frameMatches,t):ve(e.lines,e.frameMatches,t)}function W(e,t,n){let r=me(e.payload),i={format:`ips`,...G(e),crashedThread:r,topFrames:_e(t,r,n),findings:[]};return{...i,findings:Y(i)}}function G(e){let t=e.payload,n=pe(e.header);return{appName:K(t,n),bundleId:ce(t,n),version:le(t,n),incident:ue(t,n),timestamp:de(t,n),exceptionType:fe(t.exception),exceptionCodes:he(t.exception),terminationReason:ge(t.termination)}}function K(e,t){return d(e.procName,t?.app_name,t?.name)}function ce(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleIdentifier,n?.bundleID)}function le(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleShortVersionString,n?.app_version)}function ue(e,t){return d(e.incident,t?.incident_id)}function de(e,t){return d(e.captureTime,t?.timestamp)}function fe(e){return t(e)?u(e.type):void 0}function pe(e){return e?p(e):null}function me(e){let n=m(e.faultingThread);if(n!==void 0)return n;let r=(Array.isArray(e.threads)?e.threads:[]).findIndex(e=>t(e)&&e.triggered===!0);return r===-1?void 0:r}function he(e){return t(e)?d(e.codes,e.rawCodes):void 0}function ge(e){if(t(e))return f([u(e.namespace),u(e.code),u(e.reason)])}function _e(e,t,n){return e.filter(e=>t===void 0||e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function ve(e,t,n){let r=be(e),i={format:`text`,appName:ye(e),bundleId:q(e,`Identifier`),version:q(e,`Version`),incident:q(e,`Incident Identifier`),timestamp:q(e,`Date/Time`),exceptionType:q(e,`Exception Type`),exceptionCodes:q(e,`Exception Codes`),terminationReason:q(e,`Termination Reason`),crashedThread:r,topFrames:xe(t,r,n),findings:[]};return{...i,findings:Y(i)}}function ye(e){return q(e,`Process`)?.replace(/\s+\[\d+\]$/,``)}function q(e,t){let n=`${t}:`,r=e.find(e=>e.trimStart().startsWith(n));return r&&r.slice(r.indexOf(`:`)+1).trim()||void 0}function be(e){let t=q(e,`Triggered by Thread`),n=t?Number.parseInt(t,10):NaN;if(Number.isSafeInteger(n))return n;for(let t of e){let e=t.match(/^Thread\s+(\d+)\s+Crashed:/);if(e)return Number(e[1])}}function xe(e,t,n){return t===void 0?[]:e.filter(e=>e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function J(e,t,n,r){return{index:e,image:t.name,address:l(n),symbol:r.get(c(t,n))?.text}}function Y(e){return[Se(e),e.exceptionType?`Exception: ${e.exceptionType}`:void 0,e.terminationReason?`Termination: ${e.terminationReason}`:void 0].filter(e=>!!e).slice(0,3)}function Se(e){let t=e.topFrames.find(e=>e.symbol);return t?`Start with ${t.symbol} in ${t.image}; it is the first symbolicated frame captured on the crashed thread.`:e.topFrames.length>0?`No symbolicated frame was found on the crashed thread; verify matching dSYMs for the top images.`:void 0}async function Ce(e,t,n){let r=new Map;for(let i of we(e,t).values())for(let e of await Te(n,i))r.set(c(e.image,e.address),e);return r}function we(e,t){let n=new Map;for(let r of e){let e=t.get(r.image.uuid);if(!e)continue;let i=`${r.image.uuid}:${e.dsym.binaryPath}`,a=n.get(i)??{...e,addresses:[]};a.addresses.push(r.address),n.set(i,a)}return n}async function Te(e,t){let i=b(t.addresses.map(l)),a=
|
|
4
|
+
`)}}}function T(e){let t=[],n=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(n===-1)return t;for(let r of e.slice(n+1)){let e=E(r);e&&t.push(e)}return t}function E(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let n=s(t[4]);if(!n)return null;let r=D(t[3].trim(),t[5].trim());return{name:r.name,arch:r.arch,uuid:n,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}function D(e,t){let n=e.split(/\s+/),r=n.at(-1);if(r&&S.test(r))return{name:n.slice(0,-1).join(` `).trim(),arch:r};let a=i.basename(t);return{name:e.startsWith(a)?a:e}}function O(e,t){let n=[],r;for(let[i,a]of e.entries()){let e=a.match(/^Thread\s+(\d+)\s+Crashed:/);e?r=Number(e[1]):(a.trim().length===0||/^Thread\s+\d+/.test(a))&&(r=void 0);let o=k(a,t),s=a.match(/^\s*(\d+)/);o&&s&&n.push({...o,frameIndex:Number(s[1]),lineIndex:i,threadIndex:r})}return n}function k(e,t){let n=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!n)return null;let r=n[1].trim(),i=BigInt(n[2]),a=A(t,r,i);return a?{image:a,address:i}:null}function A(e,t,n){let r=e.filter(e=>e.name===t);return r.find(e=>j(e,n))??y(r)}function j(e,t){return e.end!==void 0&&e.base<=t&&t<=e.end}const M=1e4;async function N(e){return e.dsym&&e.searchPath?[H(e.cwd,e.dsym),...await P(H(e.cwd,e.searchPath))]:e.dsym?[H(e.cwd,e.dsym)]:e.searchPath?await P(H(e.cwd,e.searchPath)):[]}async function P(t){let n=[],r=0;async function o(s){if(n.length>=200)return;if(r+=1,r>M)throw new e(`COMMAND_FAILED`,`debug symbols search-path scan exceeded bounds.`,{searchPath:t,maxEntries:M,hint:`Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory.`});if(!(await F(s,t)).isDirectory()){s===t&&I(t);return}if(s.endsWith(`.dSYM`)){n.push(s);return}let c=await a.readdir(s,{withFileTypes:!0});for(let e of c)e.isDirectory()&&await o(i.join(s,e.name))}return await o(t),n}async function F(t,n){try{return await a.stat(t)}catch{throw new e(`INVALID_ARGS`,`debug symbols search path does not exist: ${n}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}}function I(t){throw new e(`INVALID_ARGS`,`debug symbols search path is not a directory: ${t}`,{hint:`Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly.`})}async function L(t,n){let r=(await Promise.all(b(t).map(e=>R(e,n)))).flat();if(r.length===0)throw new e(`COMMAND_FAILED`,`No UUIDs found in dSYM bundle.`,{hint:`Verify the path points to a built .dSYM bundle with DWARF contents.`});return r}async function R(e,t){return await z(e),B(e,r(await n(t,[`--uuid`,e],{timeoutMs:15e3,allowFailure:!0}),`Failed to inspect dSYM UUIDs: ${e}`,{hint:`Verify the dSYM bundle is valid and readable.`}).stdout)}async function z(t){if(!((await a.stat(t).catch(()=>null))?.isDirectory()&&t.endsWith(`.dSYM`)))throw new e(`INVALID_ARGS`,`Not a .dSYM bundle: ${t}`,{hint:`Pass the .dSYM bundle path, not the DWARF executable inside it.`})}function B(e,t){return t.split(`
|
|
5
|
+
`).flatMap(t=>{let n=t.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=s(n?.[1]);return n&&r?[{dsymPath:e,uuid:r,arch:n[2],binaryPath:n[3].trim()}]:[]})}function V(t,n,r){let i=new Map;for(let e of t){let t=n.find(t=>t.uuid===e.uuid&&(e.arch===void 0||t.arch===void 0||t.arch===e.arch));t&&i.set(e.uuid,{image:e,dsym:t})}if(i.size>0)return i;let a=b(t.map(e=>e.uuid)),o=b(n.map(e=>e.uuid));throw new e(`COMMAND_FAILED`,r?`dSYM UUID does not match any Apple image in the crash artifact.`:`No matching dSYM UUID found under search path.`,{artifactUuidCount:a.length,artifactUuidSample:a.slice(0,5),dsymUuidCount:o.length,dsymUuidSample:o.slice(0,5),hint:`Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path.`})}function H(e,t){return i.resolve(e,t)}function U(e,t){return e.format===`ips`?W(e.document,e.frameMatches,t):ve(e.lines,e.frameMatches,t)}function W(e,t,n){let r=me(e.payload),i={format:`ips`,...G(e),crashedThread:r,topFrames:_e(t,r,n),findings:[]};return{...i,findings:Y(i)}}function G(e){let t=e.payload,n=pe(e.header);return{appName:K(t,n),bundleId:ce(t,n),version:le(t,n),incident:ue(t,n),timestamp:de(t,n),exceptionType:fe(t.exception),exceptionCodes:he(t.exception),terminationReason:ge(t.termination)}}function K(e,t){return d(e.procName,t?.app_name,t?.name)}function ce(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleIdentifier,n?.bundleID)}function le(e,n){return d((t(e.bundleInfo)?e.bundleInfo:void 0)?.CFBundleShortVersionString,n?.app_version)}function ue(e,t){return d(e.incident,t?.incident_id)}function de(e,t){return d(e.captureTime,t?.timestamp)}function fe(e){return t(e)?u(e.type):void 0}function pe(e){return e?p(e):null}function me(e){let n=m(e.faultingThread);if(n!==void 0)return n;let r=(Array.isArray(e.threads)?e.threads:[]).findIndex(e=>t(e)&&e.triggered===!0);return r===-1?void 0:r}function he(e){return t(e)?d(e.codes,e.rawCodes):void 0}function ge(e){if(t(e))return f([u(e.namespace),u(e.code),u(e.reason)])}function _e(e,t,n){return e.filter(e=>t===void 0||e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function ve(e,t,n){let r=be(e),i={format:`text`,appName:ye(e),bundleId:q(e,`Identifier`),version:q(e,`Version`),incident:q(e,`Incident Identifier`),timestamp:q(e,`Date/Time`),exceptionType:q(e,`Exception Type`),exceptionCodes:q(e,`Exception Codes`),terminationReason:q(e,`Termination Reason`),crashedThread:r,topFrames:xe(t,r,n),findings:[]};return{...i,findings:Y(i)}}function ye(e){return q(e,`Process`)?.replace(/\s+\[\d+\]$/,``)}function q(e,t){let n=`${t}:`,r=e.find(e=>e.trimStart().startsWith(n));return r&&r.slice(r.indexOf(`:`)+1).trim()||void 0}function be(e){let t=q(e,`Triggered by Thread`),n=t?Number.parseInt(t,10):NaN;if(Number.isSafeInteger(n))return n;for(let t of e){let e=t.match(/^Thread\s+(\d+)\s+Crashed:/);if(e)return Number(e[1])}}function xe(e,t,n){return t===void 0?[]:e.filter(e=>e.threadIndex===t).slice(0,5).map(e=>J(e.frameIndex,e.image,e.address,n))}function J(e,t,n,r){return{index:e,image:t.name,address:l(n),symbol:r.get(c(t,n))?.text}}function Y(e){return[Se(e),e.exceptionType?`Exception: ${e.exceptionType}`:void 0,e.terminationReason?`Termination: ${e.terminationReason}`:void 0].filter(e=>!!e).slice(0,3)}function Se(e){let t=e.topFrames.find(e=>e.symbol);return t?`Start with ${t.symbol} in ${t.image}; it is the first symbolicated frame captured on the crashed thread.`:e.topFrames.length>0?`No symbolicated frame was found on the crashed thread; verify matching dSYMs for the top images.`:void 0}async function Ce(e,t,n){let r=new Map;for(let i of we(e,t).values())for(let e of await Te(n,i))r.set(c(e.image,e.address),e);return r}function we(e,t){let n=new Map;for(let r of e){let e=t.get(r.image.uuid);if(!e)continue;let i=`${r.image.uuid}:${e.dsym.binaryPath}`,a=n.get(i)??{...e,addresses:[]};a.addresses.push(r.address),n.set(i,a)}return n}async function Te(e,t){let i=b(t.addresses.map(l)),a=r(await n(e,Ee(t,i),{timeoutMs:3e4,allowFailure:!0}),`atos failed while symbolicating crash frames.`,{hint:`Verify the crash artifact and dSYM were produced from the same build and architecture.`});return De(t.image,i,a.stdout)}function Ee(e,t){return[`-arch`,e.image.arch??e.dsym.arch??`arm64`,`-o`,e.dsym.binaryPath,`-l`,l(e.image.base),...t]}function De(e,t,n){let r=Oe(n);return t.map((t,n)=>{let i=r[n]?.trim();return{image:e,address:BigInt(t),text:ke(i,t)?i:void 0}})}function Oe(e){let t=e.split(/\r?\n/);return t.at(-1)===``&&t.pop(),t}function ke(e,t){if(!e)return!1;let n=e.trim().toLowerCase();return!n||n===`??`||n===t.toLowerCase()?!1:!n.startsWith(`0x`)}async function Ae(){return{dwarfdump:await X(`dwarfdump`),atos:await X(`atos`)}}async function X(t){try{let e=await n(`xcrun`,[`--find`,t],{timeoutMs:5e3,allowFailure:!0}),r=e.stdout.trim();if(e.exitCode===0&&r.length>0)return r}catch{}throw new e(`TOOL_MISSING`,`Apple symbolication tool not found: ${t}`,{hint:`Install Xcode Command Line Tools and verify xcrun --find dwarfdump and xcrun --find atos succeed.`})}const Z=64*1024*1024;async function je(t){if(t.action!==void 0&&t.action!==`symbols`)throw new e(`INVALID_ARGS`,`debug supports only the symbols workflow.`,{hint:`Use debug symbols --artifact <crash.ips|crash.log> --dsym <App.dSYM> or --search-path <dir> --out <path>.`});let n=t.cwd??process.cwd(),r=$(n,t.artifact),o=$(n,t.out??Pe(r)),s=ee(await Me(r,`crash artifact`));s||Q();let c=await N({cwd:n,dsym:t.dsym,searchPath:t.searchPath});if(c.length===0)throw new e(`INVALID_ARGS`,`debug symbols requires --dsym or --search-path.`,{hint:`Pass a matching .dSYM bundle directly, or pass --search-path <dir> so agent-device can match crash image UUIDs to local dSYMs.`});let l=await Ae(),u=await L(c,l.dwarfdump),d=V(s.images,u,!!t.dsym),f=await Ce(s.addresses,d,l.atos),p=s.write(f);await a.mkdir(i.dirname(o),{recursive:!0}),await a.writeFile(o,p,`utf8`);let m=[...d.values()].map(({image:e,dsym:t})=>({name:e.name,uuid:e.uuid,arch:e.arch??t.arch,dsymPath:t.dsymPath,binaryPath:t.binaryPath})),h=[...f.values()].filter(e=>e.text).length,g=s.images.length-m.length,_=g>0?[`${g} Apple image${g===1?``:`s`} had no matching dSYM and were left unchanged.`]:void 0;return{kind:`debugSymbols`,platform:`apple`,artifactPath:r,outPath:o,crash:U(s,f),matchedImages:m,symbolicatedFrames:h,skippedImages:g,warnings:_,message:`Symbolicated ${h} frame${h===1?``:`s`} -> ${o}`}}function Q(){throw new e(`UNSUPPORTED_OPERATION`,`debug symbols currently supports Apple crash artifacts with Binary Images or IPS usedImages.`,{hint:`For Android Java/R8 crashes, use retrace with mapping.txt. For Android native crashes, use ndk-stack or addr2line with unstripped .so symbols. Capture the crash with logs, then symbolicate externally until Android support is added.`})}async function Me(t,n){await Ne(t,n);try{return await a.readFile(t,`utf8`)}catch(r){let i=r instanceof Error?r.message:String(r);throw new e(`INVALID_ARGS`,`Failed to read ${n}: ${t}`,{message:i})}}async function Ne(t,n){try{let r=await a.stat(t);if(r.size<=Z)return;throw new e(`INVALID_ARGS`,`${n} is too large: ${t}`,{actualBytes:r.size,maxBytes:Z,hint:`Pass a bounded Apple .ips/.crash artifact. For very large logs, first narrow the log to the crash report, or use logs grep/tail for lead-up context.`})}catch(r){if(r instanceof e)throw r;let i=r instanceof Error?r.message:String(r);throw new e(`INVALID_ARGS`,`Failed to read ${n}: ${t}`,{message:i})}}function $(e,t){return i.resolve(e,t)}function Pe(e){let t=i.extname(e);return`${t?e.slice(0,-t.length):e}-symbolicated${t||`.log`}`}export{je as symbolicateCrashArtifact};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,g as t}from"./sdk-device.js";import{t as n}from"./owner-identity.js";import r from"node:path";import i from"node:crypto";import a from"node:fs";import o from"node:os";function s(){let e=process.env.AGENT_DEVICE_CLAIMS_DIR?.trim();return e?r.resolve(e):r.join(o.homedir(),`.agent-device`,`device-claims`)}function c(e){let t=i.createHash(`sha256`).update(e).digest(`hex`);return r.join(s(),`${t}.json`)}function l(e){let t=s(),n=u(t);return`claims`in n?n.claims:n.entries.filter(e=>e.isFile()&&e.name.endsWith(`.json`)).map(e=>h(r.join(t,e.name))).filter(e=>e!==null).filter(t=>d(t.claim,e))}function u(e){try{return{entries:a.readdirSync(e,{withFileTypes:!0})}}catch(t){let n=t.code;return n===`ENOENT`||n===`ENOTDIR`?{claims:[]}:{claims:[{fileName:r.basename(e),classification:`unknown`,error:String(t)}]}}}function d(e,t){return e?[f(e,t.udid??t.serial),p(e,t.device),m(e,t.platform)].every(Boolean):!0}function f(e,t){return!t||e.device.id===t}function p(e,t){return!t||e.device.name===t||e.device.id===t}function m(n,r){return t({...e(n.device.platform),appleOs:n.device.appleOs},r)}function h(e){let t=r.basename(e);try{return g(t,a.readFileSync(e,`utf8`))}catch(e){let n=e.code;return n===`ENOENT`||n===`ENOTDIR`?null:{fileName:t,classification:`unknown`,error:String(e)}}}function g(e,t){try{let r=_(JSON.parse(t));return r?{fileName:e,deviceKey:r.deviceKey,claim:r,classification:n({owner:{pid:r.ownerPid,startTime:r.ownerStartTime},stateDir:r.stateDir})}:{fileName:e,classification:`inconsistent`}}catch(t){return{fileName:e,classification:`inconsistent`,error:String(t)}}}function _(e){if(!v(e))return null;let t=e;return y(t)?t:null}function v(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function y(e){return e.schemaVersion===1&&b(e.device)&&[e.deviceKey,e.session,e.workspace,e.stateDir,e.ownerToken].every(x)&&S(e.ownerPid)&&C(e.createdAtMs)&&C(e.updatedAtMs)}function b(e){if(!v(e))return!1;let t=e;return[t.id,t.name,t.platform,t.kind].every(x)}function x(e){return typeof e==`string`&&e.length>0}function S(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function C(e){return typeof e==`number`&&Number.isFinite(e)}export{s as i,l as n,c as r,h as t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{
|
|
2
|
-
`).replace(/\n$/,``),n=t.match(/^clipboard text:\s*(.*)$/i);return n?n[1]??``:t.trim().toLowerCase()===`null`?``:t}export{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{Z as n,et as r,nt as i,tt as a}from"./sdk-batch-runner.js";import{A as o,n as s,o as c}from"./sdk-android-adb.js";import{n as l}from"./shell-quote.js";import{t as u}from"./timeouts.js";import{i as d}from"./install-artifact.js";var f=e({dismissAndroidKeyboard:()=>y,dismissAndroidKeyboardWithAdb:()=>b,getAndroidKeyboardState:()=>_,getAndroidKeyboardStatusWithAdb:()=>v,readAndroidClipboardText:()=>j,readAndroidClipboardWithAdb:()=>M,writeAndroidClipboardText:()=>N,writeAndroidClipboardWithAdb:()=>P});const p=[`mInputShown`,`mIsInputViewShown`,`isInputViewShown`,`mDecorViewVisible`,`mWindowVisible`,`mInShowWindow`],m=new Map([[2,`number`],[3,`phone`],[4,`datetime`]]),h=new Set([32,208]),g=new Set([128,224,144]);async function _(e){return await v(c(e))}async function v(e){let t=await e([`shell`,`dumpsys`,`input_method`],{allowFailure:!0});if(t.exitCode!==0)throw s(`Failed to query Android keyboard state`,t);return x(t.stdout)}async function y(e){return await b(c(e))}async function b(e){let n=await v(e),r=n,i=0;for(;r.visible&&i<2;)await e([`shell`,`input`,`keyevent`,`111`]),i+=1,await u(120),r=await v(e);if(n.visible&&r.visible)throw new t(`UNSUPPORTED_OPERATION`,`Android keyboard dismiss is unavailable for the current IME without back navigation.`,{attempts:i,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner});return{attempts:i,wasVisible:n.visible,dismissed:n.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type,inputMethodPackage:r.inputMethodPackage,focusedPackage:r.focusedPackage,focusedResourceId:r.focusedResourceId,inputOwner:r.inputOwner}}function x(e){let t=E(e)??S(e),r=C(e),a=w(e,/\bpackageName=([A-Za-z0-9_.]+)\b/g),o=w(e,/\b(?:resourceId|resource-id)=([^\s,}]+)/g),s=i(e),c=n(a,o,s);return T(a,o,s),{visible:t??!1,inputType:r,type:r?A(r):void 0,inputMethodPackage:s,focusedPackage:a,focusedResourceId:o,inputOwner:c}}function S(e){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/)?.[1];if(!t)return null;let n=Number.parseInt(t,16);return Number.isNaN(n)?null:(n&1)!=0}function C(e){let t=w(e,/\binputType=0x([0-9a-fA-F]+)\b/gi);return t?`0x${t.toLowerCase()}`:void 0}function w(e,t){let n;for(let r of e.matchAll(t))n=r[1];return n}function T(e,t,n){n||!r(e)&&!a(t)||o({level:`warn`,phase:`android_input_ownership_fallback`,data:{focusedPackage:e,focusedResourceId:t}})}function E(e){return O(D(e,p))}function D(e,t){let n=new Map,r=RegExp(`\\b(${t.join(`|`)})=([a-zA-Z]+)\\b`,`g`);for(let t of e.matchAll(r)){let e=t[1],r=t[2]?.toLowerCase();!e||r!==`true`&&r!==`false`||n.set(e,r===`true`)}return n}function O(e){if(e.size===0)return null;let t=k(e,[`mWindowVisible`,`mDecorViewVisible`,`mInShowWindow`]);if(t!==void 0)return t;let n=e.get(`mInputShown`);return n===void 0?k(e,[`mIsInputViewShown`,`isInputViewShown`])??null:n}function k(e,t){for(let n of t){let t=e.get(n);if(t!==void 0)return t}}function A(e){let t=Number.parseInt(e.replace(/^0x/i,``),16);if(Number.isNaN(t))return`unknown`;let n=t&15,r=m.get(n);if(r)return r;if(n!==1)return`unknown`;let i=t&4080;return h.has(i)?`email`:g.has(i)?`password`:`text`}async function j(e){return await M(c(e))}async function M(e){return I(await F(e,[`shell`,`cmd`,`clipboard`,`get`,`text`],`read`))}async function N(e,t){await P(c(e),t)}async function P(e,t){await F(e,[`shell`,`cmd`,`clipboard`,`set`,`text`,l(t)],`write`)}async function F(e,n,r){let i=await e(n,{allowFailure:!0});if(d(i.stdout,i.stderr))throw new t(`UNSUPPORTED_OPERATION`,`Android shell clipboard ${r} is not supported on this device.`);if(i.exitCode!==0)throw s(`Failed to ${r} Android clipboard text`,i);return i.stdout}function I(e){let t=e.replace(/\r\n/g,`
|
|
2
|
+
`).replace(/\n$/,``),n=t.match(/^clipboard text:\s*(.*)$/i);return n?n[1]??``:t.trim().toLowerCase()===`null`?``:t}export{j as a,P as c,v as i,b as n,M as o,_ as r,N as s,f as t};
|
package/dist/src/device.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{c as t,
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{c as t,g as n,l as r}from"./sdk-device.js";const i=`user-installed`;function a(e){return e??`user-installed`}function o(t){if(t===void 0)throw new e(`INVALID_ARGS`,`appsFilter must be resolved before executing the apps command`);return t}const s=[`android`,`harmonyos`,`apple`,`vega`,`linux`];function c(e){let{booted:t,kind:n,...r}=e;return r}const l={platform:`web`,id:`agent-browser-chrome`,name:`Agent Browser Chrome`,kind:`device`,target:`desktop`,booted:!0};function u(e){let t=f();for(let n of e){let e=p(n);t[e].available+=1,n.booted===!0&&(t[e].booted+=1)}return t}function d(e,t){return e.filter(e=>n(e,t.platform)&&(t.target===void 0||(e.target??`mobile`)===t.target)&&(t.kind===void 0||e.kind===t.kind)&&(t.booted===void 0||e.booted===t.booted))}function f(){return{android:{available:0,booted:0},harmonyos:{available:0,booted:0},apple:{available:0,booted:0},vega:{available:0,booted:0},linux:{available:0,booted:0},web:{available:0,booted:0}}}function p(e){return t(e)||r(e)?`apple`:e.platform}const m=[`portrait`,`portrait-upside-down`,`landscape-left`,`landscape-right`],h={portrait:0,"landscape-left":1,"portrait-upside-down":2,"landscape-right":3};function g(e){return h[e]*90}function _(e){return h[e]%2==0?`PORTRAIT`:`LANDSCAPE`}function v(t){if(t===void 0)throw new e(`INVALID_ARGS`,`orientation requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.`);switch(t?.trim().toLowerCase()){case`portrait`:return`portrait`;case`portrait-upside-down`:case`upside-down`:return`portrait-upside-down`;case`landscape-left`:case`left`:return`landscape-left`;case`landscape-right`:case`right`:return`landscape-right`;default:throw new e(`INVALID_ARGS`,`Invalid rotation: ${t}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}export{v as a,u as c,i as d,o as f,g as i,d as l,h as n,s as o,a as p,_ as r,l as s,m as t,c as u};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{n as t}from"./shell-quote.js";import{n}from"./device-claim-inspection.js";import{t as r}from"./shared.js";const i=async({positionals:t,flags:i})=>{if(t[0]!==`status`||t.length!==1)throw new e(`INVALID_ARGS`,`device accepts only: status`);let c=n({platform:i.platform,device:i.device,udid:i.udid,serial:i.serial}),l=c.filter(a),u=(i.stale?l:c.filter(e=>!a(e))).map(o);return r(i,{claims:u,...i.stale?{}:{hiddenStaleClaims:l.length}},()=>s(u,{staleOnly:i.stale===!0,hiddenStaleClaims:l.length,staleCommand:d(i)})),!0};function a(e){return e.classification===`owner-process-dead`||e.classification===`owner-state-dir-gone`}function o(e){let t=e.claim;return{...e.deviceKey?{deviceKey:e.deviceKey}:{},...t?{}:{fileName:e.fileName},classification:e.classification,...t?{device:t.device,owner:{session:t.session,workspace:t.workspace,stateDir:t.stateDir,pid:t.ownerPid,startTime:t.ownerStartTime}}:{},...e.error?{error:e.error}:{}}}function s(e,t){let n=e.map(c);if(n.length===0){if(t.staleOnly)return`No stale local advisory device claims found.`;if(t.hiddenStaleClaims===0)return`No local advisory device claims found.`}return[...n.length===0?[`No live local advisory device claims found.`]:n,!t.staleOnly&&t.hiddenStaleClaims>0?`${t.hiddenStaleClaims} stale ${t.hiddenStaleClaims===1?`claim`:`claims`} hidden; inspect with: ${t.staleCommand}`:null].filter(e=>!!e).join(`
|
|
2
|
+
`)}function c(e){return`${l(e)}: ${e.classification}${u(e.owner)}`}function l(e){let t=e.device;return t?`${t.platform??`unknown`} ${t.name??t.id??`claim`}`:String(e.deviceKey??e.fileName??`claim`)}function u(e){if(!e||typeof e!=`object`)return``;let t=e;return` session=${t.session} workspace=${t.workspace}`}function d(e){return[`agent-device device status`,...[e.platform?`--platform ${t(e.platform)}`:null,e.device?`--device ${t(e.device)}`:null,e.udid?`--udid ${t(e.udid)}`:null,e.serial?`--serial ${t(e.serial)}`:null].filter(e=>!!e),`--stale`].join(` `)}export{i as deviceCommand};
|
package/dist/src/find.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{u as e}from"./sdk-contracts.js";import{Dn as t,cn as n,fn as r,ht as i,ln as a,pt as o,sn as s}from"./sdk-batch-runner.js";import{Ct as c,G as l,W as u,gn as d,hn as f,q as p,z as m}from"./prepare-kind.js";import"./screenshot-result.js";import{c as h,n as g,s as _,t as v}from"./context.js";import{D as y,Xt as b,on as x}from"./internal/daemon.js";import{o as S,s as C,t as w}from"./selector-runtime.js";function T(e){return e.kind===`ambiguous`?e.matchedNodes:e.kind===`resolved`?[e.resolution.node]:[]}function E(e){if(e.ambiguity!==`reject-candidates`)throw Error(`find's resolution policy must reject candidates, got "${e.ambiguity}"`)}async function D(e){let{req:t,sessionName:n,logPath:i,sessionStore:o,invoke:c}=e,l=t.command;if(l!==`find`)return null;let u=s(t.positionals??[],t.flags);if(!u.ok)return _(u.code,u.message);let{locator:d,query:f,action:p,value:g}=u.parsed;if(t.flags?.record&&!a(p))return _(`INVALID_ARGS`,`find ${p} is a mutating action and is always recorded; --record only applies to a read-only find (exists, wait, list, get text, get attrs).`);let v=await w({req:t,sessionName:n,logPath:i,sessionStore:o});if(v)return v;let y=o.get(n);if(!y)return h();let b=y.device,x=r(d,f),S=k({device:b,session:y,req:t,logPath:i,locator:d,query:f,sessionStore:o,sessionName:n}),T={req:t,sessionName:n,logPath:i,sessionStore:o,invoke:c,session:y,device:b,command:l,locator:d,query:f,publicFlags:Y(t.flags)},E=await S();if(m(E.snapshotQuality))return A(E.snapshotQuality);let{nodes:D}=E,M=j({nodes:D,locator:d,query:f,selectorExpression:x,flags:t.flags,platform:b.platform});if(!M.ok)return C(M.response,E);let N=M.node,P=R(D,N),F=await O(T,{node:N,resolvedNode:P,ref:`@${P.ref}`,nodes:D,actionFlags:{...t.flags??{},noRecord:!0}},p,g);return F&&C(F,E)}async function O(e,t,n,r){let i={click:()=>H(e,t),fill:()=>U(e,t,r),focus:()=>W(e,t),type:()=>G(e,t,r)}[n];return i?await i():null}function k(e){let{device:t,session:n,req:r,logPath:i,locator:a,query:o}=e,{sessionStore:s,sessionName:c}=e,l=S({device:t,session:n,sessionStore:s,sessionName:c,req:r,logPath:i});return async()=>{let{snapshot:e}=await l.capture({flags:{...r.flags,snapshotInteractiveOnly:!0},recovery:{legacyIosSparse:{query:o,shouldScope:Z(a)},sparseVerdictQueryScope:{query:o,shouldScope:Z(a)}}});return{nodes:e.nodes,snapshotQuality:e.snapshotQuality,systemSurfaceOnly:e.systemSurfaceOnly}}}function A(e){return _(`COMMAND_FAILED`,`find could not read the current accessibility tree`,{reason:e.reason,hint:`The snapshot quality verdict is sparse. Use screenshot as visual truth, navigate with coordinates if needed, then retry find after reaching a readable screen.`})}function j(e){let{nodes:t,locator:r,query:a,selectorExpression:s,flags:c,platform:l}=e,u=t.filter(e=>!z(e,t[0])),d=i.findAct,f;if(f=s?T(o(u,s,d,{platform:l})):n(u,r,a,{requireRect:d.requireRect}).matches,f=N(f,t),f.length>1){E(d);let e=M(f,c);if(!e)return{ok:!1,response:X(f,r,a)};f=e}let p=f[0]??null;return p?{ok:!0,node:p}:{ok:!1,response:_(`COMMAND_FAILED`,`find did not match any element`)}}function M(e,t){return t?.findFirst?[e[0]]:t?.findLast?[e[e.length-1]]:null}function N(t,n){let r=n[0]?.rect;if(!r)return t;let i=t.filter(t=>{if(!t.rect)return!1;let n=e(t.rect);return n.x>=r.x&&n.x<=r.x+r.width&&n.y>=r.y&&n.y<=r.y+r.height});return P(i.length>0?i:t,n)}function P(e,t){return e.length<2?e:e.map((e,n)=>({node:e,index:n,score:F(e,t)})).sort((e,t)=>t.score===e.score?L(e.node)-L(t.node)||e.index-t.index:t.score-e.score).map(e=>e.node)}function F(e,t){let n=l(t,e);if(n.reason===`covered`)return 0;let r=I(n,t[0]);return r>0?r:e.hittable&&e.rect&&!z(e,t[0])?3:+!!e.rect}function I(e,t){return e.node.rect?e.reason===`semantic-target`||e.reason===`same-rect-descendant`?4:e.reason===`hittable-ancestor`&&!z(e.node,t)?2:0:0}function L(e){return e.rect?e.rect.width*e.rect.height:1/0}function R(e,t){let n=u(e,t);return z(n,e[0])&&t.rect?t:n}function z(e,n){return!n?.rect||!e.rect||!t(e)?!1:B(e.rect,n.rect)}function B(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function V(e){return{ref:e.ref,node:e.resolvedNode,nodes:e.nodes}}async function H(t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,locator:l,query:u,publicFlags:p}=t,m=await s({token:r.token,session:i,command:`click`,positionals:[n.ref],flags:n.actionFlags,internal:{findResolvedTarget:V(n)}});if(!m.ok)return m;let h=n.resolvedNode.rect?e(n.resolvedNode.rect):n.node.rect?e(n.node.rect):null,g={ref:n.ref,locator:l,query:u};h&&(g.x=h.x,g.y=h.y);let _=f(m.data)??`Tapped ${n.ref}${h?` (${h.x}, ${h.y})`:``}`;return Object.assign(g,d(_)),y(a,o,r,c,{ref:n.ref,action:`click`,locator:l,query:u},{flags:p}),{ok:!0,data:g}}async function U(e,t,n){let{req:r,sessionName:i,sessionStore:a,session:o,invoke:s,command:c,publicFlags:l}=e;if(!n)return _(`INVALID_ARGS`,`find fill requires text`);let u=await s({token:r.token,session:i,command:`fill`,positionals:[t.ref,n],flags:t.actionFlags,internal:{findResolvedTarget:V(t)}});return u.ok&&y(a,o,r,c,{ref:t.ref,action:`fill`},{flags:l}),u}async function W(e,t){let n=await K(e,t);return n.ok&&J(e,t,`focus`),n}async function G(e,t,n){let{req:r,device:i,logPath:a,session:o}=e;if(!n)return _(`INVALID_ARGS`,`find type requires text`);let s=await K(e,t);if(!s.ok)return s;b(o);let c=await g(i,`type`,[n],r.flags?.out,{...v(a,r.flags,o.appBundleId,o.trace?.outPath)});return J(e,t,`type`),{ok:!0,data:c??{ref:t.ref}}}async function K(t,n){let{req:r,device:i,logPath:a,session:o}=t,s=q(n,`be focused`);if(s)return s;let c=n.resolvedNode.rect?e(n.resolvedNode.rect):null;return c?(b(o),{ok:!0,data:await g(i,`focus`,[String(c.x),String(c.y)],r.flags?.out,{...v(a,r.flags,o.appBundleId,o.trace?.outPath)})??{ref:n.ref}}):_(`COMMAND_FAILED`,`matched element has no bounds`)}function q(e,t){let n=[e.resolvedNode,e.node].find(p);return n?_(`COMMAND_FAILED`,`Matched element ${e.ref} is covered by another visible element and cannot ${t} safely`,{ref:`@${n.ref}`,interactionBlocked:n.interactionBlocked,hint:`Use a different visible target, scroll it clear of the overlay, or inspect with snapshot/screenshot before retrying.`}):null}function J(e,t,n){let{req:r,sessionStore:i,session:a,command:o,publicFlags:s}=e;y(i,a,r,o,{ref:t.ref,action:n},{flags:s})}function Y(e){return{...x(e)??{}}}function X(e,t,n){let r={matches:e.length,candidates:e.slice(0,5).map(e=>c(e,0,!1))};return _(`AMBIGUOUS_MATCH`,`find matched ${e.length} elements for ${t} "${n}". Use a more specific locator or selector.`,{locator:t,query:n,...r})}function Z(e){return e!==`role`}export{X as buildAmbiguousMatchError,D as handleFindCommands};
|
package/dist/src/finders.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{dn as e}from"./sdk-batch-runner.js";import{t}from"./sdk-finders.js";export{t as findBestMatchesByLocator,e as parseFindArgs};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as e}from"./sdk-batch-runner.js";import{
|
|
1
|
+
import{g as e}from"./sdk-batch-runner.js";import{Ut as t}from"./internal/daemon.js";import{S as n,b as r}from"./selector-runtime.js";import{t as i}from"./interaction-runtime.js";import{t as a}from"./interaction-snapshot.js";function o(t){if(!e(t.command))return{};let i=n(t.command,t.flags);if(i)return{response:i};let a=r(t.flags);if(!a)return{};let o=t.session.snapshot?.nodes??[];return{observe:async()=>await s(t,a,o)}}async function s(e,n,r){let i=c(e);if(!i)return;let a=await i.interactions.settleObservation({...n,baselineNodes:r,session:e.sessionName,requestId:e.req.meta?.requestId}),o=t(e.session,a);return o===void 0?a:{...a,refsGeneration:o}}function c(e){try{return i({req:e.req,sessionName:e.sessionName,logPath:e.logPath,sessionStore:e.sessionStore,contextFromFlags:e.contextFromFlags,captureSnapshotForSession:a})}catch{return}}export{o as planGenericSettleObservation};
|
package/dist/src/generic.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{a as e}from"./sdk-contracts.js";import{hn as t}from"./prepare-kind.js";import{t as n}from"./shared.js";import{n as r}from"./cli-runner.js";async function i({command:t,positionals:i,flags:s,client:c,debug:l,replayTestReporterRuntime:u}){let{result:d,cliOutput:f}=await r({client:c,command:t,positionals:i,flags:s});if(e(s.responseLevel))return n(s,d,()=>JSON.stringify(d,null,2)),!0;if(f)o(s,f);else{let e=await a(t,s,d,{debug:l,replayTestReporterRuntime:u});e!==0&&process.exit(e)}return!0}function a(e,r,i,a={}){return e===`test`?import(`./reporting.js`).then(({renderReplayTestResponse:e})=>e({suite:i,debug:a.debug,verbose:r.verbose,json:r.json,reporter:r.reporter,reportJunit:r.reportJunit,reporterRuntime:a.replayTestReporterRuntime})):(n(r,i,()=>t(i)),0)}function o(e,t){!e.json&&t.stderr&&process.stderr.write(t.stderr),n(e,e.json?t.jsonData??t.data:t.data,()=>t.text)}export{i as runGenericClientBackedCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{F as t}from"./sdk-android-adb.js";import{E as n}from"./internal/daemon.js";import{i as r,n as i}from"./app-lifecycle2.js";import{appSwitcherHarmony as a,backHarmony as o,doubleClickHarmony as s,fillHarmony as c,homeHarmony as l,longPressHarmony as u,n as d,performHarmonyGesture as f,pressHarmony as p,scrollHarmony as m,setHarmonyOrientation as h,t as g,typeHarmony as _}from"./input-actions2.js";import{randomUUID as v}from"node:crypto";import{promises as y}from"node:fs";async function b(t,r){let i=`/data/local/tmp/agent-device-screen-${v()}.jpeg`;try{await n(t,[`shell`,`snapshot_display`,`-f`,i],{timeoutMs:15e3}),await n(t,[`file`,`recv`,i,r],{timeoutMs:15e3});let a=await y.readFile(r);if(a.length<3||a[0]!==255||a[1]!==216||a[2]!==255)throw new e(`COMMAND_FAILED`,`HarmonyOS screenshot is not a JPEG file`)}finally{await n(t,[`shell`,`rm`,`-f`,i],{allowFailure:!0}).catch(()=>{})}}async function x(t,r,i,a){if(r!==`clear-app-state`)throw new e(`UNSUPPORTED_OPERATION`,`HarmonyOS setting "${r}" is not supported`,{hint:`HarmonyOS currently supports settings clear-app-state for an app bundle only.`});if(i!==`clear`)throw new e(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!a)throw new e(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);return await n(t,[`shell`,`aa`,`force-stop`,a],{timeoutMs:15e3}),await n(t,[`shell`,`bm`,`clean`,`-n`,a,`-d`,`-c`],{timeoutMs:15e3}),{bundleId:a,forceStopped:!0,clearedData:!0,clearedCache:!0}}function S(n,v){let y=t=>async()=>{throw new e(`UNSUPPORTED_OPERATION`,`${t} is not supported on HarmonyOS`)};return{open:(e,t)=>r(n,e,{activity:t?.activity}),openDevice:()=>l(n),close:e=>i(n,e),tap:(e,t)=>p(n,e,t),doubleTap:(e,t)=>s(n,e,t),longPress:(e,t,r)=>u(n,e,t,r),focus:(e,t)=>p(n,e,t),type:(e,t)=>_(n,e,t),fill:(e,t,r,i)=>c(n,e,t,r,i),scroll:(e,t)=>m(n,e,t),performGesture:e=>f(n,e),gestureViewport:()=>g(n),screenshot:e=>b(n,e),snapshot:async e=>({...await t(`snapshot_capture`,async()=>await d(n,e),{backend:`harmonyos-arkui`}),backend:`harmonyos-arkui`}),back:()=>o(n),home:()=>l(n),setOrientation:e=>h(n,e),appSwitcher:()=>a(n),tvRemote:y(`tv-remote`),readClipboard:y(`clipboard`),writeClipboard:y(`clipboard`),setSetting:(e,t,r)=>x(n,e,t,r)}}export{S as createHarmonyInteractor};
|