agent-device 0.20.8 → 0.20.10
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 +94 -31
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +13 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +10 -117
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +103 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +108 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +179 -73
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +61 -0
- package/dist/src/ai-sdk.js +1 -0
- package/dist/src/android-adb.d.ts +6 -6
- 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 +6 -7
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +2 -0
- package/dist/src/appearance.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/artifacts.d.ts +1 -1
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/bounds.js +1 -0
- package/dist/src/byte-limit-stream.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +42 -30
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +7 -7
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +1582 -0
- package/dist/src/command-catalog.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -0
- package/dist/src/config.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols.js +3 -3
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device-ready.js +1 -1
- package/dist/src/device2.js +2 -2
- package/dist/src/dispatch.js +1 -1
- package/dist/src/entities.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper-package-install.js +1 -0
- package/dist/src/helper.js +2 -2
- package/dist/src/host-process.js +1 -1
- package/dist/src/ime-lifecycle.js +2 -9
- package/dist/src/ime-recovery-marker.js +1 -0
- package/dist/src/index.d.ts +2 -1569
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact.js +1 -1
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -0
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -0
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -0
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +4 -7
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/keyed-lock.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 -1
- package/dist/src/limrun.d.ts +13 -3
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -0
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -0
- package/dist/src/observability.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf.js +4 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -1
- package/dist/src/project-runtime.js +1 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -0
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-export-quality.js +1 -0
- package/dist/src/registry.js +29 -26
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +5 -5
- package/dist/src/rolldown-runtime.js +1 -0
- package/dist/src/runner-client.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime-transport.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -3
- package/dist/src/runtime3.js +1 -3
- package/dist/src/runtime4.js +3 -1
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -0
- package/dist/src/runtime9.js +1 -0
- package/dist/src/scoped-provider.js +1 -0
- package/dist/src/screenshot-density.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/script-source-bundle.js +16 -0
- package/dist/src/sdk-android-adb.d.ts +44 -26
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +125 -88
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +107 -95
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/sdk.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +10 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +1 -30
- package/dist/src/session2.js +27 -0
- package/dist/src/setting-state.js +1 -1
- package/dist/src/shared.js +1 -1
- package/dist/src/simctl.js +1 -0
- package/dist/src/simulator-state.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -0
- package/dist/src/snapshot-session.js +1 -1
- package/dist/src/snapshot.js +8 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -2
- package/dist/src/src3.js +2 -1
- package/dist/src/src4.js +1 -0
- package/dist/src/string-enum.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/verdict.js +1 -0
- package/dist/src/verified-file.js +1 -0
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +27 -10
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +0 -1
- package/dist/src/interaction-touch-reference-frame.js +0 -1
- package/dist/src/notifications.js +0 -1
- package/dist/src/platform-runtime-toolchain-host.js +0 -1
- package/dist/src/prepare-kind.js +0 -15
- package/dist/src/selector-vocabulary.js +0 -1
- package/dist/src/text-surface.js +0 -1
package/dist/src/auth-session.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{_ as t}from"./sdk-android-adb.js";import n from"node:path";import r from"node:fs";async function i(t,n){let r=await t.text(),i={};if(r.trim().length>0)try{i=JSON.parse(r)}catch(r){throw new e(`COMMAND_FAILED`,n.invalidJsonMessage,{status:t.status},r instanceof Error?r:void 0)}if(!t.ok)throw new e(`UNAUTHORIZED`,n.rejectedMessage,{status:t.status,response:i});return i}const a=1e3;async function o(e){return await s({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:e.command===`connect`&&!e.flags.noLogin,env:e.env})}async function s(t){let n=t.env??t.io?.env??process.env;if(!t.flags.daemonBaseUrl)return{flags:t.flags,source:`none`};if(A(t.flags.daemonAuthToken))return{flags:t.flags,source:`flag`};if(A(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:t.flags,source:`env`};if(!T(t.flags.daemonBaseUrl,n))return{flags:t.flags,source:`none`};let r=await h({stateDir:t.stateDir,flags:t.flags,env:n,io:t.io});if(r)return{flags:{...t.flags,daemonAuthToken:r.accessToken},source:`cli-session`};if(!t.allowInteractiveLogin)throw t.flags.noLogin?new e(`UNAUTHORIZED`,`Remote daemon authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`}):C(t.command,n);let i=await l({stateDir:t.stateDir,flags:t.flags,env:n,io:t.io});return{flags:{...t.flags,daemonAuthToken:i.accessToken},source:`login`}}async function c(t){let n=t.env??t.io?.env??process.env;if(A(t.flags.daemonAuthToken))return{accessToken:t.flags.daemonAuthToken,cloudBaseUrl:w(n)};if(A(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:n.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:w(n)};let r=await h({stateDir:t.stateDir,flags:t.flags,env:n,io:t.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(t.flags.noLogin)throw new e(`UNAUTHORIZED`,`Cloud connection profile authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`});let i=await l({stateDir:t.stateDir,flags:t.flags,env:n,io:t.io,commandLabel:`agent-device connect`});return{accessToken:i.accessToken,cloudBaseUrl:i.session.cloudBaseUrl}}async function l(t){let n=t.env??t.io?.env??process.env,r=b(n,t.io);if(r===`non-interactive`)throw C(t.commandLabel??`agent-device connect`,n);let i=w(n),a=await v({baseUrl:i,pathName:`/api/control-plane/device-auth/start`,body:{client:`agent-device`,tenant:t.flags.tenant,runId:t.flags.runId,daemonBaseUrl:t.flags.daemonBaseUrl,session:t.flags.session},fetchImpl:t.io?.fetch});y(a);let o=a.verificationUriComplete??a.verificationUri,s=r===`local-browser`?a.verificationUri:E(a.verificationUri,a.userCode);r===`local-browser`?(O(t.io,`Opening ${a.verificationUri}...\n`),await D(o,t.io)):O(t.io,`Open this URL on your machine:\n${s}\n\nWaiting for approval for 10 minutes...\n`);let c=await _({cloudBaseUrl:i,deviceCode:a.deviceCode,expiresIn:a.expiresIn,interval:a.interval,fetchImpl:t.io?.fetch,now:t.io?.now}),l=c.cliSession?.refreshCredential??c.cliSession?.refreshToken;if(!A(c.accessToken)||!A(l))throw new e(`UNAUTHORIZED`,`Device authorization did not return CLI credentials.`);let u=new Date(t.io?.now?.()??Date.now()).toISOString(),f={version:1,id:c.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:i,workspaceId:c.cliSession?.workspaceId,accountId:c.cliSession?.accountId,name:c.cliSession?.name,refreshCredential:l,createdAt:u,expiresAt:c.cliSession?.expiresAt};return d({stateDir:t.stateDir,session:f}),{accessToken:c.accessToken,expiresAt:c.expiresAt,session:f}}function u(e){let t=p(e.stateDir);if(!r.existsSync(t))return null;try{let e=JSON.parse(r.readFileSync(t,`utf8`));return e.version!==1||!A(e.id)||!A(e.cloudBaseUrl)||!A(e.refreshCredential)||!A(e.createdAt)?null:e}catch{return null}}function d(e){let t=p(e.stateDir);r.mkdirSync(n.dirname(t),{recursive:!0,mode:448}),r.writeFileSync(t,`${JSON.stringify(e.session,null,2)}\n`,{mode:384});try{r.chmodSync(t,384)}catch{}}function f(e){let t=p(e.stateDir);return r.existsSync(t)?(r.rmSync(t,{force:!0}),!0):!1}function p(e){return n.join(e,`auth`,`cli-session.json`)}function m(e){let t=u({stateDir:e.stateDir});return t?{authenticated:!0,source:`cli-session`,sessionId:t.id,cloudBaseUrl:t.cloudBaseUrl,workspaceId:t.workspaceId,accountId:t.accountId,name:t.name,createdAt:t.createdAt,expiresAt:t.expiresAt,expired:k(t.expiresAt,e.now)}:{authenticated:!1,source:`none`}}async function h(e){let t=u({stateDir:e.stateDir});return!t||k(t.expiresAt,e.io?.now)?null:{accessToken:(await g({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:w(e.env,t.cloudBaseUrl)}}async function g(t){let n=await v({baseUrl:w(t.env,t.session.cloudBaseUrl),pathName:`/api/control-plane/cli-session/refresh`,body:{refreshCredential:t.session.refreshCredential,tenant:t.flags.tenant,runId:t.flags.runId,daemonBaseUrl:t.flags.daemonBaseUrl,session:t.flags.session},fetchImpl:t.io?.fetch});if(A(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};throw n.status===`revoked`||n.error===`revoked`?new e(`UNAUTHORIZED`,`Stored cloud CLI session was revoked.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error}):new e(`UNAUTHORIZED`,`Failed to refresh CLI session.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error})}async function _(t){let n=t.now??Date.now,r=Math.min((t.expiresIn??600)*1e3,6e5),i=n()+r,o=Math.max(a,(t.interval??5e3/1e3)*1e3);for(;n()<i;){let n=await v({baseUrl:t.cloudBaseUrl,pathName:`/api/control-plane/device-auth/poll`,body:{deviceCode:t.deviceCode},fetchImpl:t.fetchImpl});if(n.status===`approved`||A(n.accessToken))return n;if(n.status===`slow_down`||n.error===`slow_down`)o+=a;else if(n.status!==`authorization_pending`&&n.error!==`authorization_pending`)throw new e(`UNAUTHORIZED`,`Device authorization was not approved.`,{status:n.status,error:n.error});await j(o)}throw new e(`TIMEOUT`,`Device authorization expired before approval.`)}async function v(e){let t=await(e.fetchImpl??fetch)(new URL(e.pathName,e.baseUrl),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await i(t,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud auth endpoint rejected the request.`})}function y(t){if(!A(t.deviceCode)||!A(t.userCode)||!A(t.verificationUri))throw new e(`COMMAND_FAILED`,`Cloud auth start returned an unusable response.`)}function b(e,t){let n=t?.stdinIsTTY??process.stdin.isTTY,r=t?.stdoutIsTTY??process.stdout.isTTY;return x(e)||!n||!r?`non-interactive`:S(e)?`device-code`:`local-browser`}function x(e){return e.CI===`true`||e.GITHUB_ACTIONS===`true`||e.BUILDKITE===`true`}function S(e){return!!(e.SSH_TTY||e.SSH_CONNECTION||e.CODESPACES===`true`||e.GITPOD_WORKSPACE_ID||e.REMOTE_CONTAINERS===`true`)}function C(t,n){let r=w(n);return new e(`UNAUTHORIZED`,`${t} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL(`/api-keys`,r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function w(t,n){let r=t.AGENT_DEVICE_CLOUD_BASE_URL??n??`https://cloud.agent-device.dev`;try{return new URL(r).toString().replace(/\/+$/,``)}catch(t){throw new e(`INVALID_ARGS`,`Invalid AGENT_DEVICE_CLOUD_BASE_URL.`,{cloudBaseUrl:r},t instanceof Error?t:void 0)}}function T(e,t){if(t.AGENT_DEVICE_CLOUD_AUTH===`1`||t.AGENT_DEVICE_CLOUD_AUTH===`true`||A(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return t===`agent-device.dev`||t.endsWith(`.agent-device.dev`)}catch{return!1}}function E(e,t){let n=new URL(e);return n.searchParams.set(`user_code`,t),n.toString()}async function D(e,n){if(n?.openBrowser){await n.openBrowser(e);return}let r=process.platform;try{r===`darwin`?await t(`open`,[e],{allowFailure:!0,timeoutMs:5e3}):r===`win32`?await t(`cmd`,[`/c`,`start`,``,e],{allowFailure:!0,timeoutMs:5e3}):await t(`xdg-open`,[e],{allowFailure:!0,timeoutMs:5e3})}catch{O(n,`Open this URL on your machine:\n${e}\n`)}}function O(e,t){(e?.stderr??process.stderr).write(t)}function k(e,t){if(!e)return!1;let n=Date.parse(e);return Number.isFinite(n)?n<=(t?.()??Date.now()):!0}function A(e){return typeof e==`string`&&e.trim().length>0}async function j(e){await new Promise(t=>setTimeout(t,e))}export{m as a,o as i,f as n,i as o,c as r,l as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={interactiveOnly:`snapshotInteractiveOnly`,scope:`snapshotScope`,depth:`snapshotDepth`,raw:`snapshotRaw`,customActions:`snapshotCustomActions`,includeHiddenContentHints:`snapshotIncludeHiddenContentHints`,preferredBackend:`snapshotPreferredBackend`};function t(t){return t?Object.fromEntries(Object.entries(e).flatMap(([e,n])=>{let r=t[e];return r===void 0?[]:[[n,r]]})):{}}export{t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as
|
|
2
|
-
`).toLowerCase();return r===`ios`&&d.includes(`0xe8008012`)?`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:r===`ios`&&(d.includes(`provisioning profile`)||d.includes(`embedded profile`))?`BOOT_COMMAND_FAILED`:r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t,v as n,y as r}from"./sdk-contracts.js";import{A as i}from"./sdk-android-adb.js";var a=e({Deadline:()=>c,isEnvTruthy:()=>o,retryWithPolicy:()=>l});function o(e){return[`1`,`true`,`yes`,`on`].includes((e??``).trim().toLowerCase())}const s={maxAttempts:3,baseDelayMs:200,maxDelayMs:2e3,jitter:.2};var c=class e{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(t,n=Date.now()){return new e(n,t)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return this.remainingMs(e)<=0}};async function l(e,n={},i={}){let a={maxAttempts:n.maxAttempts??s.maxAttempts,baseDelayMs:n.baseDelayMs??s.baseDelayMs,maxDelayMs:n.maxDelayMs??s.maxDelayMs,jitter:n.jitter??s.jitter,shouldRetry:n.shouldRetry},o;for(let t=1;t<=a.maxAttempts;t+=1){if(i.signal?.aborted)throw r();if(i.deadline?.isExpired()&&t>1)break;try{let n=await e({attempt:t,maxAttempts:a.maxAttempts,deadline:i.deadline});return i.onEvent?.({phase:i.phase,event:`succeeded`,attempt:t,maxAttempts:a.maxAttempts,elapsedMs:i.deadline?.elapsedMs(),remainingMs:i.deadline?.remainingMs()}),f({phase:i.phase,event:`succeeded`,attempt:t,maxAttempts:a.maxAttempts,elapsedMs:i.deadline?.elapsedMs(),remainingMs:i.deadline?.remainingMs()}),n}catch(e){o=e;let n=i.classifyReason?.(e),r={phase:i.phase,event:`attempt_failed`,attempt:t,maxAttempts:a.maxAttempts,elapsedMs:i.deadline?.elapsedMs(),remainingMs:i.deadline?.remainingMs(),reason:n};if(i.onEvent?.(r),f(r),t>=a.maxAttempts||a.shouldRetry&&!a.shouldRetry(e,t))break;let s=u(a.baseDelayMs,a.maxDelayMs,a.jitter,t),c=i.deadline?Math.min(s,i.deadline.remainingMs()):s;if(c<=0)break;let l={phase:i.phase,event:`retry_scheduled`,attempt:t,maxAttempts:a.maxAttempts,delayMs:c,elapsedMs:i.deadline?.elapsedMs(),remainingMs:i.deadline?.remainingMs(),reason:n};i.onEvent?.(l),f(l),await d(c,i.signal)}}let c={phase:i.phase,event:`exhausted`,attempt:a.maxAttempts,maxAttempts:a.maxAttempts,elapsedMs:i.deadline?.elapsedMs(),remainingMs:i.deadline?.remainingMs(),reason:i.classifyReason?.(o)};throw i.onEvent?.(c),f(c),o||new t(`COMMAND_FAILED`,`retry failed`)}function u(e,t,n,r){let i=Math.min(t,e*2**(r-1)),a=i*n;return Math.max(0,i+(Math.random()*2-1)*a)}function d(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=!1,i=()=>{r||(r=!0,t&&t.removeEventListener(`abort`,o),n())},a=setTimeout(i,e);function o(){clearTimeout(a),i()}t&&t.addEventListener(`abort`,o,{once:!0})})}function f(e){i({level:e.event===`attempt_failed`||e.event===`exhausted`?`warn`:`debug`,phase:`retry`,data:{...e}})}const p=new Set([`IOS_BOOT_TIMEOUT`,`IOS_RUNNER_CONNECT_TIMEOUT`,`IOS_TOOL_MISSING`,`ANDROID_BOOT_TIMEOUT`,`ADB_TRANSPORT_UNAVAILABLE`,`CI_RESOURCE_STARVATION_SUSPECTED`]);function m(e){return p.has(e.toUpperCase())}function h(e){let t=e.error?n(e.error):null,r=e.context?.platform,i=e.context?.phase;if(t?.code===`TOOL_MISSING`)return r===`android`?`ADB_TRANSPORT_UNAVAILABLE`:`IOS_TOOL_MISSING`;let a=t?.details??{},o=typeof a.message==`string`?a.message:void 0,s=typeof a.stdout==`string`?a.stdout:void 0,c=typeof a.stderr==`string`?a.stderr:void 0,l=a.boot&&typeof a.boot==`object`?a.boot:null,u=a.bootstatus&&typeof a.bootstatus==`object`?a.bootstatus:null,d=[e.message,t?.message,e.stdout,e.stderr,o,s,c,typeof l?.stdout==`string`?l.stdout:void 0,typeof l?.stderr==`string`?l.stderr:void 0,typeof u?.stdout==`string`?u.stdout:void 0,typeof u?.stderr==`string`?u.stderr:void 0].filter(Boolean).join(`
|
|
2
|
+
`).toLowerCase();return r===`ios`&&d.includes(`0xe8008012`)?`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:r===`ios`&&(d.includes(`provisioning profile`)||d.includes(`embedded profile`))?`BOOT_COMMAND_FAILED`:r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:t?.code===`COMMAND_FAILED`||d.length>0?`BOOT_COMMAND_FAILED`:`UNKNOWN`}function g(e){switch(e){case`IOS_BOOT_TIMEOUT`:return`Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.`;case`IOS_RUNNER_CONNECT_TIMEOUT`:return`Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.`;case`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:return`The XCTest runner cannot be installed on this device: its provisioning profile does not cover it. Register the device with the signing team (Xcode > Settings > Accounts, or add its UDID to the provisioning profile) and retry. Retrying without that will keep failing.`;case`ANDROID_BOOT_TIMEOUT`:return`Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.`;case`ADB_TRANSPORT_UNAVAILABLE`:return`Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.`;case`CI_RESOURCE_STARVATION_SUSPECTED`:return`CI machine may be resource constrained; reduce parallel jobs or use a larger runner.`;case`IOS_TOOL_MISSING`:return`Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.`;case`BOOT_COMMAND_FAILED`:return`Inspect command stderr/stdout for the failing boot phase and retry after environment validation.`;default:return`Retry once and inspect verbose logs for the failing phase.`}}export{o as a,c as i,h as n,l as o,m as r,a as s,g as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let n=Number(t[1]),r=Number(t[2]),i=Number(t[3]),a=Number(t[4]);return{x:n,y:r,width:Math.max(0,i-n),height:Math.max(0,a-r)}}export{e as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import t from"node:path";import{createReadStream as n,createWriteStream as r,promises as i}from"node:fs";import{pipeline as a}from"node:stream/promises";import{Transform as o}from"node:stream";import{createGunzip as s}from"node:zlib";import*as c from"tar-stream";import*as l from"yauzl";const u=2*1024*1024*1024;var d=class{maxBytes;maxEntries;maxDepth;#e=0;#t=0;constructor(e={}){this.maxBytes=v(e.maxBytes??4294967296,`maxBytes`),this.maxEntries=v(e.maxEntries??1e5,`maxEntries`),this.maxDepth=v(e.maxDepth??3,`maxDepth`)}get bytes(){return this.#e}get entries(){return this.#t}preflightArchive(e){let t=v(e.depth,`depth`),n=v(e.entryCount,`entryCount`),r=v(e.declaredBytes,`declaredBytes`);if(t<1||t>this.maxDepth)throw _(`ARCHIVE_NESTING_LIMIT`,`Archive nesting depth exceeds the limit`);if(n>this.maxEntries-this.#t)throw _(`ARCHIVE_ENTRY_LIMIT`,`Archive contains too many entries`);if(r>this.maxBytes-this.#e)throw _(`ARCHIVE_EXPANDED_BYTES_LIMIT`,`Archive expands beyond the byte limit`);return new f(e=>this.#n(e),()=>this.#r(),e.entryCount,e.declaredBytes)}#n(e){let t=v(e,`bytes`);if(t>this.maxBytes-this.#e)throw _(`ARCHIVE_EXPANDED_BYTES_LIMIT`,`Archive expands beyond the byte limit`);this.#e+=t}#r(){if(this.#t>=this.maxEntries)throw _(`ARCHIVE_ENTRY_LIMIT`,`Archive contains too many entries`);this.#t+=1}},f=class{#e;#t;#n;#r;#i=0;#a=0;constructor(e,t,n,r){this.#e=e,this.#t=t,this.#n=n,this.#r=r}chargeBytes(e){let t=v(e,`bytes`);if(t>this.#r-this.#a)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);this.#e(t),this.#a+=t}commitEntry(){if(this.#i>=this.#n)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);this.#t(),this.#i+=1}finish(){if(this.#i!==this.#n||this.#a!==this.#r)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`)}};function p(e,t,n){return e.preflightArchive({depth:t,entryCount:n.length,declaredBytes:n.reduce((e,t)=>e+t.size,0)})}function m(e,t){return e.name===t.name&&e.kind===t.kind&&e.size===t.size&&e.mode===t.mode}function h(e){if(!e||e.includes(`\0`)||e.includes(`\\`)||t.posix.isAbsolute(e)||/^[a-zA-Z]:/.test(e)||e.startsWith(`//`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive contains an unsafe entry path`);let n=t.posix.normalize(e).replace(/^(\.\/)+/,``).replace(/\/$/,``);if(!n||n===`.`||n===`..`||n.startsWith(`../`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive contains an unsafe entry path`);return n}function g(e,n){let r=h(n),i=t.resolve(e),a=t.resolve(i,...r.split(`/`));if(!a.startsWith(`${i}${t.sep}`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive entry escapes the extraction root`);return a}function _(t,n,r){return new e(`INVALID_ARGS`,n,{reason:t},r)}function v(e,t){if(!Number.isSafeInteger(e)||e<0)throw RangeError(`${t} must be a non-negative safe integer`);return e}async function y(e){e.signal?.throwIfAborted();let t=e.budget??new d,n=e.depth??1,r=await b(e,t,n);await e.validateManifest?.(r);let i=p(t,n,r),a=c.extract(),o=x(e.archivePath,e.gzip,a,e.signal);try{for await(let t of a){e.signal?.throwIfAborted();let n=w(t.header);if(!n){await E(t);continue}let a=r.shift();if(!a||!m(a,n))throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);await T(t,a,e.outputRoot,i),i.commitEntry()}await o}catch(e){throw a.destroy(),await o.catch(()=>{}),e}if(r.length!==0)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);i.finish()}async function b(e,t,n){let r=[],i=0,a=c.extract(),o=x(e.archivePath,e.gzip,a,e.signal);try{for await(let o of a){e.signal?.throwIfAborted();let a=w(o.header);if(!a){await E(o);continue}i+=a.size,t.preflightArchive({depth:n,entryCount:r.length+1,declaredBytes:i}),r.push(a),await E(o)}await o}catch(e){throw a.destroy(),await o.catch(()=>{}),e}return r}function x(e,t,r,i){return t?a(n(e),s(),r,{signal:i}):a(n(e),r,{signal:i})}function S(e){if(e===`directory`)return`directory`;if(e===`file`||e===`contiguous-file`||e==null)return`file`;throw e===`link`||e===`symlink`?_(`ARCHIVE_UNSAFE_ENTRY`,`Uploaded app bundle archive cannot contain symlinks or hard links`):_(`ARCHIVE_UNSAFE_ENTRY`,`Archive contains a link or special entry`)}function C(e,t){return(e??(t===`directory`?493:420))&511}function w(e){if(D(e.name,e.type))return;let t=h(e.name),n=S(e.type),r=n===`directory`?0:e.size??0;if(!Number.isSafeInteger(r)||r<0)throw _(`ARCHIVE_INVALID_ENTRY`,`Archive entry has an invalid size`);return{name:t,kind:n,size:r,mode:C(e.mode,n)}}async function T(e,n,o,s){let c=g(o,n.name);if(n.kind===`directory`){await i.mkdir(c,{recursive:!0,mode:n.mode}),await E(e);return}await i.mkdir(t.dirname(c),{recursive:!0}),await a(e,async function*(e){for await(let t of e)s.chargeBytes(Buffer.byteLength(t)),yield t},r(c,{flags:`wx`,mode:n.mode}))}async function E(e){for await(let t of e);}function D(e,t){return t===`directory`&&(e===`.`||e===`./`||e===``)}async function O(e){e.signal?.throwIfAborted();let n=e.budget??new d,o=e.depth??1,s=[],c=0;await k(e.archivePath,e.signal,e=>{n.preflightArchive({depth:o,entryCount:s.length+1,declaredBytes:c});let t=M(e);c+=t.size,n.preflightArchive({depth:o,entryCount:s.length+1,declaredBytes:c}),s.push(t)}),await e.validateManifest?.(s);let l=p(n,o,s),u=await k(e.archivePath,e.signal,(e,t)=>{t>=s.length&&F()});u.length!==s.length&&F();let f=await A(e.archivePath);try{for(let n=0;n<u.length;n+=1){e.signal?.throwIfAborted();let o=u[n],c=s[n];(!o||!c||!m(M(o),c))&&F();let d=g(e.outputRoot,c.name);c.kind===`directory`?await i.mkdir(d,{recursive:!0,mode:c.mode}):(await i.mkdir(t.dirname(d),{recursive:!0}),await a(await j(f,o),async function*(e){for await(let t of e)l.chargeBytes(Buffer.byteLength(t)),yield t},r(d,{flags:`wx`,mode:c.mode}),{signal:e.signal})),l.commitEntry()}l.finish()}finally{f.close()}}async function k(e,t,n){let r=await A(e);return await new Promise((e,i)=>{let a=[],o=()=>{r.off(`entry`,s),r.off(`end`,c),r.off(`error`,l),t?.removeEventListener(`abort`,u)},s=e=>{try{n?.(e,a.length),a.push(e),r.readEntry()}catch(e){o(),i(e)}},c=()=>{o(),e(a)},l=e=>{o(),i(e)},u=()=>{o(),r.close(),i(t?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r.on(`entry`,s),r.once(`end`,c),r.once(`error`,l),t?.addEventListener(`abort`,u,{once:!0}),t?.aborted)return u();r.readEntry()}).finally(()=>r.close())}function A(e){return new Promise((t,n)=>{l.open(e,{lazyEntries:!0,autoClose:!1,validateEntrySizes:!0,strictFileNames:!0},(e,r)=>e?n(e):t(r))})}function j(e,t){return new Promise((n,r)=>{e.openReadStream(t,(e,t)=>e?r(e):n(t))})}function M(e){N(e);let t=h(e.fileName),n=e.externalFileAttributes>>>16&65535,r=P(e.fileName,n),i=r?493:420;return{name:t,kind:r?`directory`:`file`,size:r?0:e.uncompressedSize,mode:n&511||i}}function N(e){if(e.isEncrypted())throw _(`ARCHIVE_UNSAFE_ENTRY`,`Encrypted archive entries are not supported`);let t=e.externalFileAttributes>>>16&61440;if(t!==0&&t!==16384&&t!==32768)throw _(`ARCHIVE_UNSAFE_ENTRY`,`Archive contains a link or special entry`)}function P(e,t){return e.endsWith(`/`)||(t&61440)==16384}function F(){throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`)}async function I(e){e.signal?.throwIfAborted();let n=t.resolve(e.archivePath),r=t.resolve(e.outputRoot);if(n===r||n.startsWith(`${r}${t.sep}`))throw RangeError(`archivePath must be outside outputRoot`);await i.mkdir(r,{recursive:!1});try{e.type===`zip`?await O({...e,archivePath:n,outputRoot:r}):await y({...e,archivePath:n,outputRoot:r,gzip:e.type===`tgz`})}catch(e){throw await i.rm(r,{recursive:!0,force:!0}),e}}function L(e){let t=e.toLowerCase();if(t.endsWith(`.tar.gz`)||t.endsWith(`.tgz`))return`tgz`;if(t.endsWith(`.tar`))return`tar`;if(t.endsWith(`.zip`)||t.endsWith(`.ipa`))return`zip`}function R(e){if(!Number.isSafeInteger(e.maxBytes)||e.maxBytes<0)throw RangeError(`maxBytes must be a non-negative safe integer`);let t=0,n=new o({transform(n,r,i){let a=t+n.byteLength;if(!Number.isSafeInteger(a)||a>e.maxBytes){i(e.createLimitError());return}t=a,i(null,n)}});return Object.defineProperty(n,"bytesSeen",{enumerable:!0,get:()=>t}),n}export{u as a,d as i,L as n,I as r,R as t};
|
package/dist/src/cli-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{_ as t}from"./location-coordinates.js";import{i as n}from"./command-catalog.js";import{S as r,d as i,l as a}from"./registry.js";import{n as o,t as s}from"./path-resolution.js";import{D as c,T as l}from"./sdk-android-adb.js";import{r as u}from"./command-schema.js";import d from"node:path";import f from"node:fs";const p=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),m=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),h=x(),g=new Map(h.map(e=>[e.key,e]));function _(e){return g.get(e)}function v(e){return h.filter(t=>t.configurable&&t.supportsCommand(e))}function y(e,t){return _(e)?.supportsCommand(t)??!1}function b(e,t,n,r){return c(w(e),t,n,r)}function x(){let e=new Map;for(let t of r()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of i)t.set(e,new Set([`*`]));for(let e of n()){let n=u(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!p.has(e),env:{names:m.has(e)?[]:[l(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>S(e.key,t.key))}function S(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function C(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function w(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=C(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}function T(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}function E(e){let t=e.env??process.env;return T(T({},j(O(e.cwd,e.cliFlags.config,t))),F(t,e.command))}const D=new Set(`json.platform.target.device.udid.serial.session.sessionLock.activity.launchArgs.launchUrl.remote.deviceHub.testIme.appsFilter.clean.force.stale.relaunch.shutdown.surface.headless.restart.noRecord.record.recordAs.snapshotInteractiveOnly.snapshotDiff.snapshotDepth.snapshotScope.snapshotRaw.snapshotCustomActions.snapshotForceFull.screenshotPixelDensity.screenshotFullscreen.screenshotScale.screenshotNoStabilize.screenshotNormalizeStatusBar.overlayRefs.networkInclude.baseline.threshold.count.pointerCount.fps.quality.hideTouches.recordingScope.intervalMs.delayMs.durationMs.holdMs.jitterPx.pixels.doubleTap.verify.settle.settleQuietMs.clickButton.backMode.pauseMs.pattern.kind.perfTemplate.responseLevel.verbose.cost.timeoutMs.retries.failFast.recordVideo.replayUpdate.replayMaestro.replayFrom.replayPlanDigest.replayKeepSession.findFirst.findLast.batchOnError.batchMaxSteps.retainPaths.retentionMs.shardAll.shardSplit.noLogin`.split(`.`));function O(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:A(r,e,n),required:!0,source:`explicit`}]:[{path:k(n),required:!1,source:`user`},{path:d.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function k(e){return d.join(s(`~`,{env:e}),`.agent-device`,`config.json`)}function A(e,t,n){return o(e,{cwd:t,env:n})}function j(e){let t={};for(let n of e)T(t,M(n));return t}function M(t){let{path:n,required:r}=t;if(!f.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=f.readFileSync(n,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}let a;try{a=JSON.parse(i)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${n}`);return N(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function N(n,r){let i={};for(let[o,s]of Object.entries(n)){let n=o,c=_(n);if(!c)throw o===t.flagKey?new e(`INVALID_ARGS`,`Config key "${o}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${o}" in ${r.label}.`);if(!c.configurable)throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!D.has(n))throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(n===`installSource`){i.installSource=a(s,r.label);continue}i[n]=b(c,s,r.label,o)}return i}const P=new Set([`screenshot`,`record`]);function F(n,r){let i=n[t.envVar];if(r!==null&&P.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of v(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=b(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{T as n,y as r,E as t};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{n as e}from"./
|
|
2
|
-
`)}function
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{rr as t}from"./sdk-batch-runner.js";import{i as n}from"./command-catalog.js";import{S as r,d as i,m as a}from"./registry.js";import{n as o}from"./version.js";import{i as s,r as c}from"./command-schema.js";const l=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText, eraseText, openLink, hideKeyboard, basic pressKey, and back; targets support index, childOf, label, points, and optional.`,`Assertions and navigation: assertVisible, assertNotVisible, extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, and stopApp.`,`Scripts: ordered runScript file/env scripts with http.post, json, and output variables.`],u=[`Runtime: iOS and Android only; launchApp.clearState supports Android and iOS simulators, launch arguments are Apple-only, and standalone device utility/state commands are unsupported.`,`Expressions: when.true supports boolean literals and maestro.platform comparisons; repeat.while, evalScript, and broader JavaScript expressions are unsupported.`,`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Failure diagnostics: resolved targets and runFlow paths are rendered, while inputText payloads remain hidden; do not place secrets in diagnostic identifiers.`,`Trust: runScript executes trusted scripts, may make http.post network requests, and is not a security sandbox; output keys cannot contain a dot.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function d(){return[`Supported subset:`,...l.map(e=>` - ${e}`),``,`Boundaries:`,...u.map(e=>` - ${e}`)].join(`
|
|
2
|
+
`)}function f(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function p(e){return r().filter(t=>t.key===e)}function m(e,t){if(t.usageOverride)return t.usageOverride;let n=(t.positionalArgs??[]).map(f),r=(t.allowedFlags??[]).flatMap(e=>p(e).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`);return[e,...n,...r].join(` `)}function h(){return`agent-device <command> [args] [--json]
|
|
3
3
|
|
|
4
4
|
Automates iOS, Android, macOS, TV, and web apps for AI agents.
|
|
5
5
|
All ${n().length} commands: agent-device help commands
|
|
@@ -14,6 +14,7 @@ Start:
|
|
|
14
14
|
|
|
15
15
|
Loop:
|
|
16
16
|
press|click|fill|longpress <target> ... --settle
|
|
17
|
+
hover <target> --settle (web only; reveals hover-gated UI)
|
|
17
18
|
scroll <direction|top|bottom> [amount] --settle; back --settle
|
|
18
19
|
acts, waits for quiet, and prints the UI diff. Continue from that diff.
|
|
19
20
|
Run snapshot -i only when the diff lacks the next target or did not settle.
|
|
@@ -30,7 +31,7 @@ Targets:
|
|
|
30
31
|
Then screenshot, press <x> <y>, and re-snapshot on the changed screen.
|
|
31
32
|
|
|
32
33
|
Rules:
|
|
33
|
-
--settle is only for press/click/fill/longpress/scroll/back; never open,
|
|
34
|
+
--settle is only for press/click/fill/longpress/hover/scroll/back; never open,
|
|
34
35
|
snapshot, or close. type never accepts --settle.
|
|
35
36
|
fill <target> <text> --settle replaces; type <text> appends after focus.
|
|
36
37
|
Late network/debounce result: wait text "Expected", not snapshot polling.
|
|
@@ -48,14 +49,14 @@ Guides (agent-device help <topic>):
|
|
|
48
49
|
manual-qa / dogfood / validate / debugging / scripting / gestures
|
|
49
50
|
react-native / react-devtools / cdp / tv / web / macos / remote
|
|
50
51
|
physical-device / ios-system-ui / maestro
|
|
51
|
-
`}const
|
|
52
|
+
`}var g=e({buildCommandUsageText:()=>N,buildUsageText:()=>E,helpTopicIds:()=>P});const _=[`Default config files: ~/.agent-device/config.json, ./agent-device.json (project-safe defaults only).`,`Use --config <path> or AGENT_DEVICE_CONFIG for explicit connection/provider defaults; project config cannot select endpoints or credentials.`],v=[{label:`AGENT_DEVICE_SESSION`,description:`Explicit session name`},{label:`AGENT_DEVICE_PLATFORM`,description:`Default platform binding`},{label:`AGENT_DEVICE_SCREENSHOT_SCALE`,description:`Default screenshot scale factor`},{label:`AGENT_DEVICE_SESSION_LOCK`,description:`Bound-session conflict mode`},{label:`AGENT_DEVICE_DAEMON_BASE_URL`,description:`Connect to remote daemon`},{label:`AGENT_DEVICE_DAEMON_AUTH_TOKEN`,description:`Remote daemon service/API token`},{label:`AGENT_DEVICE_CLOUD_BASE_URL`,description:`Bridge/control-plane API origin for cloud auth and /api-keys`}],y=[`agent-device open Settings --platform ios`,`agent-device open https://example.com --platform web`,`agent-device snapshot -i`,`agent-device fill @e3 "test@example.com"`,`agent-device replay ./session.ad`,`agent-device test ./suite --platform android`],b=`Wait failure contract:
|
|
52
53
|
Read the verdict from error.details.reason in --json, not the message text.
|
|
53
54
|
wait_target_absent: a readable capture ran and found no match.
|
|
54
55
|
wait_capture_stalled: no readable capture finished before the deadline -- retriable.
|
|
55
56
|
wait_deadline_exceeded: a later capture used the remaining budget after an earlier readable one.
|
|
56
57
|
wait_landmark_identity_mismatch: a replay destination guard found the selector but not the recorded identity.
|
|
57
58
|
wait_stable_timeout: wait stable never saw a stable UI -- not an absence verdict.
|
|
58
|
-
`,
|
|
59
|
+
`,x={commands:{summary:`Full command catalog, global flags, configuration, and environment`,body:`agent-device help commands`},"manual-qa":{summary:`Follow manual test scripts with exact interactions and verification`,body:`agent-device help manual-qa
|
|
59
60
|
|
|
60
61
|
Use this when asked to follow a manual QA script, test case, checklist, acceptance flow, or user-provided instructions.
|
|
61
62
|
|
|
@@ -95,11 +96,11 @@ Recovery:
|
|
|
95
96
|
Sparse or recovered accessibility snapshot: use screenshot as visual truth, leave the bad screen if needed, then retry snapshot -i.
|
|
96
97
|
Non-hittable success hint: verify with the settled diff or snapshot; retarget by a better ref/selector if the UI did not change.
|
|
97
98
|
|
|
98
|
-
${
|
|
99
|
+
${b}`},maestro:{summary:`Supported Maestro YAML commands, grammar, and runtime boundaries`,body:`agent-device help maestro
|
|
99
100
|
|
|
100
101
|
Run Maestro compatibility flows with replay <flow.yaml> --maestro or test <path> --maestro. Bind an iOS or Android target with --platform or an existing session.
|
|
101
102
|
|
|
102
|
-
${
|
|
103
|
+
${d()}
|
|
103
104
|
|
|
104
105
|
Unsupported syntax fails loudly rather than being skipped. Architecture, performance tradeoffs, and declared conformance divergences: https://github.com/callstack/agent-device/blob/main/docs/adr/0015-direct-maestro-engine.md
|
|
105
106
|
Focused compatibility request: https://github.com/callstack/agent-device/issues/new`},workflow:{summary:`Normal agent-device bootstrap, exploration, and validation loop`,body:`agent-device help workflow
|
|
@@ -144,7 +145,7 @@ Session ordering:
|
|
|
144
145
|
Stateful commands (open/press/fill/type/scroll/back/alert/replay/batch/close) run serially within one session. Parallelize only read-only commands, or separate sessions/devices.
|
|
145
146
|
|
|
146
147
|
Read-only and waits:
|
|
147
|
-
${
|
|
148
|
+
${b}
|
|
148
149
|
snapshot/get/is/find answer read-only questions; snapshot -i only when refs are needed. --settle confirms local UI quieted; for results that arrive later (network/debounce), follow with wait text "Expected result" or wait <selector> instead of polling.
|
|
149
150
|
wait stable [quietMs] [timeoutMs] (defaults 500/10000) is the fallback for open/relaunch/navigation, or an intentionally-unsettled mutation -- not after a --settle whose diff already shows the change. Ambiguous find: add --first or --last.
|
|
150
151
|
|
|
@@ -179,6 +180,9 @@ Escalate:
|
|
|
179
180
|
|
|
180
181
|
Use this for reusable .ad script authoring (save-script), scripted destination guards, secret-safe fills, batch multi-step JSON, replay divergence/repair, and evidence recording.
|
|
181
182
|
|
|
183
|
+
Script paths are the caller's:
|
|
184
|
+
replay <path> and test <path-or-glob> resolve and read on the machine running the command, then send the script content (Maestro runFlow includes too) with the request. The same flows therefore run against a local daemon and against a remote one (AGENT_DEVICE_DAEMON_BASE_URL) with no copy step, and a missing script fails immediately, naming the path you typed. --save-script writes on the DAEMON host and is rejected against a remote daemon.
|
|
185
|
+
|
|
182
186
|
Reusable open-to-destination scripts:
|
|
183
187
|
Arm recording on the first open, perform the full journey, verify the destination with a selector-targeted wait, then publish without closing:
|
|
184
188
|
agent-device open com.example.app --relaunch --save-script=screen-x.ad
|
|
@@ -259,7 +263,7 @@ Vega OS:
|
|
|
259
263
|
vega virtual-device stop
|
|
260
264
|
Use a component ID from the app package or Vega SDK tooling; agent-device app inventory is not yet supported.
|
|
261
265
|
Use --serial VirtualDevice for explicit VVD selection.
|
|
262
|
-
|
|
266
|
+
The VVD is never booted implicitly; start it with vega virtual-device start.
|
|
263
267
|
Snapshot, screenshot, selectors, install, touch/text/gesture, logs, and performance commands remain unsupported until their Vega backends are implemented.
|
|
264
268
|
|
|
265
269
|
Buttons:
|
|
@@ -356,6 +360,7 @@ Diagnostics and traces:
|
|
|
356
360
|
Open output includes Session state; JSON also includes runnerLogPath and requestLogPath.
|
|
357
361
|
For open timing under --debug, run open --debug --json and inspect requestLogPath for the open_timing event.
|
|
358
362
|
Session requests/<request-id>.ndjson holds daemon request diagnostics; session runner.log holds Apple runner/xcodebuild output.
|
|
363
|
+
Against a remote daemon the Diagnostics Log path is always local: the failing request's record is fetched to <state-dir>/remote-diagnostics/, and if it cannot be fetched the line reads "unavailable" with the reason instead of a daemon-host path.
|
|
359
364
|
daemon.log is global daemon lifecycle evidence, not the primary per-run log.
|
|
360
365
|
Use trace for low-level session diagnostics around one repro:
|
|
361
366
|
agent-device trace start ./traces/diagnostics.trace
|
|
@@ -368,7 +373,7 @@ Diagnostics and traces:
|
|
|
368
373
|
agent-device perf cpu profile report --kind xctrace --out ./artifacts/app-profile.json
|
|
369
374
|
agent-device perf trace start --kind xctrace --template "Animation Hitches" --out ./artifacts/hitches.trace
|
|
370
375
|
agent-device perf trace stop --kind xctrace --out ./artifacts/hitches.trace
|
|
371
|
-
perf xctrace
|
|
376
|
+
perf xctrace keeps the .trace artifact on disk; CPU report returns a bounded weighted top-function summary. Do not dump .trace contents into context.
|
|
372
377
|
For Android native CPU/trace evidence, use perf artifacts instead of raw adb/simpleperf/perfetto output:
|
|
373
378
|
agent-device perf cpu profile start --kind simpleperf --out /tmp/cpu.perf.data
|
|
374
379
|
agent-device perf cpu profile stop --kind simpleperf
|
|
@@ -376,6 +381,10 @@ Diagnostics and traces:
|
|
|
376
381
|
agent-device perf trace start --kind perfetto --out /tmp/app.perfetto-trace
|
|
377
382
|
agent-device perf trace stop --kind perfetto
|
|
378
383
|
Treat native perf output as the agent evidence: for example, state=stopped, outPath=/tmp/app.perfetto-trace, sizeBytes=5392410, method=adb-shell-perfetto. The 5.3 MB raw trace stays in the artifact.
|
|
384
|
+
CPU reports return at most ten top functions in structured data and print five in default CLI output.
|
|
385
|
+
Prefer explicit perf frames, perf memory, perf cpu, or perf trace forms. Bare perf, perf sample, perf metrics, and metrics are deprecated compatibility forms until the next major release.
|
|
386
|
+
On Android, those deprecated aggregate forms retain the released dumpsys cpuinfo point sample for compatibility; new profiling workflows should use perf cpu profile.
|
|
387
|
+
Startup duration belongs to the open command's startup result; read it there instead of using aggregate perf.
|
|
379
388
|
|
|
380
389
|
Memory diagnostics:
|
|
381
390
|
Use perf memory when the symptom is leak/growth/OOM suspicion and you need agent-readable evidence.
|
|
@@ -386,7 +395,7 @@ Memory diagnostics:
|
|
|
386
395
|
{"metrics":{"memory":{"available":true,"totalPssKb":562958,"totalRssKb":570304,"topConsumers":[{"name":"Dalvik Heap","pssKb":213456}]}}}
|
|
387
396
|
Example default snapshot output:
|
|
388
397
|
Memory artifact (android-hprof): /tmp/app.hprof (42MB)
|
|
389
|
-
Prefer perf memory sample over raw dumpsys/leaks output for first-pass agent diagnosis: it keeps arrays bounded
|
|
398
|
+
Prefer perf memory sample over raw dumpsys/leaks output for first-pass agent diagnosis: it keeps arrays bounded and returns only relevant memory evidence.
|
|
390
399
|
Prefer perf memory snapshot over printing heap/memgraph data: snapshots return path, size, kind, method, and support metadata while the large artifact stays on disk for external inspection.
|
|
391
400
|
Unsupported platforms return artifact.available=false with reason/hint; do not pretend a heap or memgraph was captured.
|
|
392
401
|
|
|
@@ -464,7 +473,7 @@ Example:
|
|
|
464
473
|
agent-device react-devtools profile report @c5
|
|
465
474
|
agent-device network dump --include headers
|
|
466
475
|
|
|
467
|
-
Use snapshot, screenshot, logs, network, and perf
|
|
476
|
+
Use snapshot, screenshot, logs, network, perf frames, and perf memory for device/app runtime evidence. Use react-devtools when component internals or React rendering behavior matters.`},cdp:{summary:`React Native CDP targets, JS heap snapshots, and leak triage`,body:`agent-device help cdp
|
|
468
477
|
|
|
469
478
|
Use this when a React Native or Expo app exposes a CDP target through Metro and
|
|
470
479
|
the task needs JavaScript heap growth checks, heap snapshot diffs, allocation
|
|
@@ -570,7 +579,7 @@ Overlays and busy RN UIs:
|
|
|
570
579
|
React DevTools routing:
|
|
571
580
|
Keep the agent-device react-devtools prefix on every React DevTools command.
|
|
572
581
|
Use help react-devtools for status/wait, component trees, props/state/hooks, profile windows, slow renders, rerenders, and remote bridge rules.
|
|
573
|
-
If React DevTools cannot connect, report status and continue with logs, network, perf
|
|
582
|
+
If React DevTools cannot connect, report status and continue with logs, network, perf frames, perf memory, screenshot, and trace evidence instead of blocking the whole flow.
|
|
574
583
|
|
|
575
584
|
CDP memory routing:
|
|
576
585
|
Keep the agent-device cdp prefix on every CDP command.
|
|
@@ -587,7 +596,7 @@ Slow-flow investigation:
|
|
|
587
596
|
If the task says to open the app, include the open command even when it also describes the current screen.
|
|
588
597
|
Use help react-devtools for the narrow React profile window. Profiling plans need both status and wait --connected before profile start.
|
|
589
598
|
Check status before wait/profile. Do not substitute react-devtools start for status; start launches the helper, while status reports connection state.
|
|
590
|
-
Use help debugging for logs clear --restart, logs mark, network dump --include headers, perf
|
|
599
|
+
Use help debugging for logs clear --restart, logs mark, network dump --include headers, perf frames, perf memory, native profiles, traces, and runtime failure evidence.
|
|
591
600
|
For 15-20s async work, use wait with the exact expected text or selector instead of repeated snapshots.
|
|
592
601
|
Report React render offenders separately from network/backend waits and device frame/CPU/memory findings.`},"physical-device":{summary:`Connected phone/tablet setup and iOS signing prerequisites`,body:`agent-device help physical-device
|
|
593
602
|
|
|
@@ -770,6 +779,7 @@ Open and inspect:
|
|
|
770
779
|
agent-device snapshot -i --platform macos
|
|
771
780
|
|
|
772
781
|
Surfaces:
|
|
782
|
+
--surface is an open flag; the session keeps it, so later commands do not repeat it.
|
|
773
783
|
--surface app normal app session
|
|
774
784
|
--surface frontmost-app inspect whichever app is frontmost
|
|
775
785
|
--surface desktop desktop-wide surface
|
|
@@ -777,7 +787,7 @@ Surfaces:
|
|
|
777
787
|
|
|
778
788
|
Menu bar app example:
|
|
779
789
|
agent-device open "Agent Device Tester Menu" --platform macos --surface menubar
|
|
780
|
-
agent-device snapshot -i --platform macos
|
|
790
|
+
agent-device snapshot -i --platform macos
|
|
781
791
|
|
|
782
792
|
Context menu example:
|
|
783
793
|
agent-device click @e66 --button secondary --platform macos
|
|
@@ -793,7 +803,7 @@ Rules:
|
|
|
793
803
|
Use --platform web only for the minimal browser command loop exposed through agent-device.
|
|
794
804
|
|
|
795
805
|
Dependency:
|
|
796
|
-
|
|
806
|
+
Browser mechanics come from a managed, pinned agent-browser backend. agent-device owns command/session/replay integration, selectors/refs at the command surface, and artifact routing; agent-browser owns browser launch, page control, screenshots, and browser-specific behavior.
|
|
797
807
|
Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow. Use agent-browser directly for standalone web automation.
|
|
798
808
|
Before first use, set up and verify the managed backend:
|
|
799
809
|
agent-device web setup
|
|
@@ -813,6 +823,7 @@ First-slice loop:
|
|
|
813
823
|
agent-device is visible 'label="Welcome"' --platform web
|
|
814
824
|
agent-device find text "Welcome" exists --platform web
|
|
815
825
|
agent-device click @e12 --platform web
|
|
826
|
+
agent-device hover @e14 --settle --platform web
|
|
816
827
|
agent-device fill @e13 "qa@example.com" --platform web
|
|
817
828
|
agent-device wait text "Welcome" 3000 --platform web
|
|
818
829
|
agent-device record start ./artifacts/web-flow.webm --platform web
|
|
@@ -825,7 +836,8 @@ First-slice loop:
|
|
|
825
836
|
agent-device close --platform web
|
|
826
837
|
|
|
827
838
|
Supported in agent-device web sessions:
|
|
828
|
-
open <url>, snapshot -i, get text/attrs, is visible/exists/text, find text/selector, click/press @ref or selector, fill/type @ref or selector, wait text/selector, network dump, audio probe, screenshot, record start/stop with WebM output, close, and replay scripts made from those commands.
|
|
839
|
+
open <url>, snapshot -i, get text/attrs, is visible/exists/text, find text/selector, click/press @ref or selector, hover @ref or selector, fill/type @ref or selector, wait text/selector, network dump, audio probe, screenshot, record start/stop with WebM output, close, and replay scripts made from those commands.
|
|
840
|
+
hover moves the pointer without pressing so hover-gated UI (row toolbars, menus) appears; use --settle to read what it revealed, then act on the fresh refs. hover @ref hovers the browser element handle directly; pair --settle with a selector or coordinates (web refs carry no geometry, as with click @ref --settle). Web only: touch platforms have no hover state, so hover-gated flows there need a different entry point.
|
|
829
841
|
|
|
830
842
|
Out of scope for agent-device web support:
|
|
831
843
|
Browser runtime debugging, tabs/windows/devtools control, network routing/interception/HAR, storage/cookie management, arbitrary page scripting, downloads/uploads, multi-page orchestration, and agent-browser-specific diagnostics. Use agent-browser directly for those browser-specific workflows.
|
|
@@ -890,7 +902,7 @@ Rules:
|
|
|
890
902
|
scroll takes direction then amount and does not support a selector or --settle: agent-device scroll down 3.
|
|
891
903
|
Keep commands in the report reproducible; use selectors or refs from fresh snapshots, not guessed coordinates.
|
|
892
904
|
Prefer refs for exploration and selectors for deterministic replay.
|
|
893
|
-
Use logs, network, screenshot --overlay-refs, trace, perf
|
|
905
|
+
Use logs, network, screenshot --overlay-refs, trace, perf frames, perf memory, native profiles, or react-devtools only when they add evidence to a specific issue.
|
|
894
906
|
Never delete screenshots, videos, traces, or report artifacts during a session.
|
|
895
907
|
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`},validate:{summary:`Engineering self-validation with device evidence and cleanup`,body:`agent-device help validate
|
|
896
908
|
|
|
@@ -921,36 +933,36 @@ Evidence:
|
|
|
921
933
|
Visual claim: screenshot, optionally screenshot --overlay-refs when target mapping matters.
|
|
922
934
|
Runtime/logging claim: logs clear --restart, logs mark, reproduce, logs path.
|
|
923
935
|
Network claim: network dump --include headers when headers are relevant.
|
|
924
|
-
Performance claim: perf
|
|
936
|
+
Performance claim: perf frames, perf memory sample, native profile reports, or trace artifacts with bounded output.
|
|
925
937
|
Replay/regression claim: replay or test through the public command path.
|
|
926
938
|
|
|
927
939
|
Report:
|
|
928
940
|
Summarize what changed, exact validation commands, pass/fail observations, artifact paths, and residual risk.
|
|
929
|
-
If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function
|
|
941
|
+
If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function S(e,t,n){let r=n.endsWith(`?`),i=r?n.slice(0,-1):n,a=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i),o=a||t.usageOverride!==void 0&&t.usageOverride.startsWith(`${e} ${i}`);return r?a?`[${i}]`:o?i:`[${i}]`:o?i:`<${i}>`}function C(e,t){return t.listUsageOverride?t.listUsageOverride:[e,...(t.positionalArgs??[]).map(n=>S(e,t,n))].join(` `)}function w(){return h()}function T(){return`agent-device help commands
|
|
930
942
|
|
|
931
943
|
Full command catalog. Use agent-device help <command> for exact flags and behavior.
|
|
932
944
|
|
|
933
|
-
${
|
|
945
|
+
${M(n().map(e=>{let t=c(e);return{name:e,schema:t,usage:C(e,t)}}))}
|
|
934
946
|
|
|
935
|
-
${
|
|
947
|
+
${k(`Global Flags:`,D(i))}
|
|
936
948
|
|
|
937
|
-
${
|
|
949
|
+
${j(`Configuration:`,_)}
|
|
938
950
|
|
|
939
|
-
${
|
|
951
|
+
${A(`Environment:`,v)}
|
|
940
952
|
|
|
941
|
-
${
|
|
942
|
-
`}function
|
|
943
|
-
`)}function
|
|
944
|
-
`)}function
|
|
953
|
+
${j(`Examples:`,y)}
|
|
954
|
+
`}function E(){return w()}function D(e){return r().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function O(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function k(e,t){return A(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function A(e,t){if(t.length===0)return`${e}\n (none)`;let n=Math.max(...t.map(e=>Math.min(e.label.length,26)))+2,r=[e];for(let e of t){let t=e.label.length<=26?e.label.padEnd(n):`${e.label} `;r.push(` ${t}${e.description}`)}return r.join(`
|
|
955
|
+
`)}function j(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
|
|
956
|
+
`)}function M(e){return A(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function N(e){let t=F(e);if(t)return t;let n=s(e);if(!n)return null;let r=m(e,n),i=O(D(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),o=[];i.length>0&&o.push(k(`Command flags:`,i));let c=o.length>0?`\n\n${o.join(`
|
|
945
957
|
|
|
946
958
|
`)}`:``;return`Usage:
|
|
947
959
|
agent-device ${r}
|
|
948
960
|
|
|
949
961
|
${a(n.text)}${c}
|
|
950
|
-
`}function
|
|
962
|
+
`}function P(){return Object.keys(x)}function F(e){let t=x[e];return t?`${I(e,e===`commands`?T():t.body)}
|
|
951
963
|
|
|
952
964
|
Related:
|
|
953
965
|
agent-device help <command> command-specific flags
|
|
954
966
|
agent-device help manual-qa routine QA loop
|
|
955
967
|
agent-device help workflow full automation reference
|
|
956
|
-
`:null}function
|
|
968
|
+
`:null}function I(e,t){let n=`agent-device help ${e}`;return t.startsWith(n)?`agent-device ${o()} — ${e}${t.slice(n.length)}`:t}export{P as i,E as n,g as r,N as t};
|
package/dist/src/cli-runner.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./cli-
|
|
1
|
+
import{t as e}from"./cli-output.js";import{t}from"./cli-grammar.js";import{n}from"./command-surface.js";async function r(e){return(await i(e)).result}async function i(r){let i=t(r.command,r.positionals,r.flags),a=await n(r.client,r.command,i);return{result:a,cliOutput:e({name:r.command,input:i,result:a})}}export{i as n,r as t};
|
package/dist/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`))}function
|
|
3
|
-
`)}function
|
|
4
|
-
`),n}function
|
|
5
|
-
`)}function
|
|
6
|
-
`),n
|
|
7
|
-
`);
|
|
1
|
+
import{E as e,_ as t,k as n,v as r}from"./sdk-contracts.js";import{_ as i}from"./location-coordinates.js";import{Lr as a,l as o}from"./sdk-batch-runner.js";import{St as s,xt as c}from"./script-source-bundle.js";import{n as l,r as u}from"./agent-device-client.js";import{C as d,_ as f}from"./screenshot-result.js";import{i as p,r as m,t as h}from"./command-catalog.js";import{S as g,x as _}from"./registry.js";import{n as v}from"./command-metadata.js";import{A as y,I as ee,M as b,N as x,j as S,k as te,x as ne}from"./sdk-android-adb.js";import{n as re}from"./version.js";import{i as ie,n as C,t as ae}from"./command-schema.js";import{n as w,r as T,t as oe}from"./cli-config.js";import{n as se,t as ce}from"./internal/bin.js";import{t as le}from"./update-check.js";import{exitAfterFlush as E}from"./process-exit.js";import{D as ue,E as de,S as fe,T as pe,h as me,n as he,w as ge}from"./connection-runtime.js";import{t as _e}from"./cli-grammar.js";import{i as ve}from"./auth-session.js";import D from"node:fs";import{pathToFileURL as ye}from"node:url";const O=`open <app> --relaunch`,be={start:{command:`open`,example:O},restart:{command:`open`,example:O},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function k(e){if(e.length<=2)return[];let t=p(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=A(e),i=t.map(t=>({name:t,distance:j(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function A(e){return e.length<4?1:e.length<=6?2:3}function j(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):M(e,t)}function M(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function N(e){let t=e.toLowerCase(),n=be[t]?.example;if(n)return n;let r=k(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const xe=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),Se=new Set([`--session-locked`,`--session-lock-conflicts`]);function Ce(e){return xe.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:Se.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===i.cliToken?`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`:`Unknown flag: ${e}`}function P(e){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=z(l));continue}if(De(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=z(l));continue}let[f,p]=u?F(l):[l,void 0];if(Te(r,f))continue;let m=Oe(f,r);if(Ee(r,m)){a.push(l);continue}if(!m){if(Ne(r,a,l)){r?a.push(l):r=l;continue}throw new t(`INVALID_ARGS`,Ce(f))}let h=je(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return we(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function we(e,t){if(e)for(let n of ce(e)?.impliedFlags??[])t[n]=!0}function Te(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Ee(e,t){return e===`react-devtools`?t?!T(t.key,e):!0:!1}function De(e){return e===`cdp`}function Oe(e,t){let n=g().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??_(e);if(t){let e=n.find(e=>T(e.key,t));if(e)return e}return _(e)}function ke(e,n){let r=n?.strictFlags??!0,i=[...e.warnings],a=w({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(w(a,e.flags),e.command&&!m(e.command)&&!a.help){let n=N(e.command);throw new t(`INVALID_ARGS`,n?`Unknown command: ${e.command}. Did you mean ${n}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!T(t.key,e.command));if(o.length>0){let n=o.map(e=>e.token),s=Ie(e.command,n);if(r)throw new t(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(T(t,e.command)||delete a[t]);Ae(e),ae(e.command,a);let s=Fe({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(C(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new t(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Ae(e){if(e.command!==`back`)return;let n=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new t(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function F(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function je(e,n,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new t(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||L(i)?{value:!0,consumeNext:!1}:Me(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&L(a))throw new t(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new t(`INVALID_ARGS`,`Invalid ${I(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new t(`INVALID_ARGS`,`Invalid ${I(n)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function I(e){return e.replace(/^-+/,``)}function L(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?F(e):[e,void 0];return _(t)!==void 0}function Me(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function Ne(e,t,n){if(!Pe(n)||!e)return!1;let r=ie(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function Pe(e){return/^-\d+(\.\d+)?$/.test(e)}function Fe(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function Ie(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function R(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.r);return e()}async function Le(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.r);return t(z(e))}function z(e){if(e.toLowerCase()===`rotate`)throw new t(`INVALID_ARGS`,`rotate was renamed to orientation; for the two-finger gesture use: gesture rotate`);return se(e)}function Re(e){return v(e)}const ze={connect:async()=>(await import(`./connection.js`)).connectCommand,disconnect:async()=>(await import(`./connection.js`)).disconnectCommand,connection:async()=>(await import(`./connection.js`)).connectionCommand,auth:async()=>(await import(`./auth.js`)).authCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device2.js`)).deviceCommand,proxy:async()=>(await import(`./proxy.js`)).proxyCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot.js`)).diffCommand};async function B(e){let t={...e.flags},n=ze[e.command];return n&&await(await n())({...e,flags:t})?!0:Re(e.command)?await Be({...e,command:e.command,flags:t}):!1}async function Be(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function Ve(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function He(e){return e===`ios-instance`}function Ue(e){return e[0]===`wait`&&e.includes(`--connected`)}function We(e,t,n){n===0||!Ue(e)||!He(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.",``].join(`
|
|
2
|
+
`))}function V(e,t,n){return n||(e.push(t),``)}function Ge(e){if(!e?.metroProxyBaseUrl||!pe(e.leaseBackend))return null;let n=[],r={serverBaseUrl:V(n,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:V(n,`metroBearerToken`,e.metroBearerToken),tenantId:V(n,`tenant`,e.tenant),runId:V(n,`runId`,e.runId),leaseId:V(n,`leaseId`,e.leaseId)};if(n.length>0)throw new t(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function Ke(e,t,n){let{flags:r}=t,i=Ge(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await ue({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await de({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function qe(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?n.leaseProvider===`limrun`&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function Je(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await Ke(e,t,async()=>(qe(e,t)&&await t.configureDirectPortReverse?.(),(await ne(`npm`,Ve(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return We(e,t.flags,i),i}async function Ye(e,n){switch(e[0]){case`setup`:{Xe(n.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Ze(n.flags.json,t),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Qe(n.flags.json,t.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,t),t.exitCode}default:throw new t(`INVALID_ARGS`,`web requires setup or doctor`)}}function Xe(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
|
|
3
|
+
`)}function Ze(e,t){if(e){s({success:!0,data:{status:H(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function Qe(e,t,n){if(e){s({success:!0,data:$e(n)});return}process.stdout.write(`${t}\n`)}function H(e){let{socketDir:t,...n}=e;return n}function $e(e){let t=e.status;return et(t)?{...e,status:H(t)}:e}function et(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function tt(e){let n;try{n=JSON.parse(e)}catch{throw new t(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new t(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return nt(n)}function nt(e){let t=!1,n=e.map((e,n)=>{if(it(e))return at(e,n+1);let r=ot(e,n+1);return t=!0,rt(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
|
|
4
|
+
`),n}function rt(e){let t=_e(e.command,e.positionals??[],dt(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function it(e){return a(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function at(e,t){let n=o(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function ot(e,n){if(!a(e))throw new t(`INVALID_ARGS`,`Invalid batch step ${n}.`);ct(e,n);let r=st(e.command,n),i=lt(e.positionals,n);C(r,i??[],`Batch step ${n}`);let s=ut(e.flags,n),c=o(e.runtime,n);return{command:r,...i===void 0?{}:{positionals:i},...s===void 0?{}:{flags:s},...c===void 0?{}:{runtime:c}}}function st(e,n){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new t(`INVALID_ARGS`,`Batch step ${n} requires command.`);if(v(r))return r;throw new t(`INVALID_ARGS`,`Batch step ${n} command is not available through command batch: ${String(e)}`)}function ct(e,n){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new t(`INVALID_ARGS`,`Batch step ${n} has unknown legacy field(s): ${r.join(`, `)}.`)}function lt(e,n){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new t(`INVALID_ARGS`,`Batch step ${n} positionals must contain only strings.`);return e}}function ut(e,n){if(e!==void 0){if(!a(e))throw new t(`INVALID_ARGS`,`Batch step ${n} flags must be an object.`);return e}}function dt(e){return{json:!1,help:!1,version:!1,...e}}function U(e,t={}){let n=W(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function W(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??pt(t.AGENT_DEVICE_PLATFORM),r=ht(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:ft(e.policyOverrides,t,r)}}function ft(e,t,n){let r=e?.sessionLock??mt(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function pt(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function mt(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new t(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function ht(e){return typeof e==`string`&&e.trim().length>0}function gt(e,t){let n=P(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=_t(n.command)?me({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=w(oe({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...ke(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function _t(e){return e!==null}h.runtime;async function vt(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const yt={sendToDaemon:u},bt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),xt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`]);async function G(e,t=yt){let n=te(),r=re(),i=jt(e),a=e.includes(`--json`);await ee({session:Ut(e)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await St(e,{version:r,jsonRequested:a,debugEnabled:i}),u=X(s,o.providedFlags),d=await Ct(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:u});K(d.effectiveFlags);let f=null;try{if(s===`react-devtools`){await E(await wt(d,t));return}if(s===`web`){await E(await Ye(c,{flags:d.effectiveFlags,stateDir:d.daemonPaths.baseDir}));return}if(le({command:s,currentVersion:r,stateDir:d.daemonPaths.baseDir,flags:d.effectiveFlags}),await Tt(d,t),K(d.effectiveFlags),s===`cdp`){await E(await ge(c,{flags:d.effectiveFlags,runtime:d.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}f=Et(d);let e=await Dt(d);await Ot(d,l(q(d),{transport:Ht({command:s,flags:d.effectiveFlags,replayTestReporterRuntime:e,transport:t.sendToDaemon})}),e)}catch(e){await kt(e,d,f)}finally{f&&f()}})}function K(e){e.daemonAuthToken&&x(e.daemonAuthToken)}async function St(n,r){let i;try{i=gt(n,{cwd:process.cwd(),env:process.env})}catch(t){y({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:b().diagnosticId,logPath:S({force:!0})?.path});return r.jsonRequested?s({success:!1,error:n}):c(n,{showDetails:r.debugEnabled}),E(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),E(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return c(new t(`INVALID_ARGS`,`help accepts at most one command.`)),E(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await R()}\n`),E(0);let n=await Le(e);return n?(process.stdout.write(n),E(0)):(c(new t(`INVALID_ARGS`,Mt(e))),process.stdout.write(`${await R()}\n`),E(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await R()}\n`),E(1))}async function Ct(t,n){let i=new Set(t.providedFlags.map(e=>e.key));try{let e=W({policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),r=e.lockPolicy?{...t.flags}:U(t.flags,{policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),a=f(r.stateDir),o=r.session??`default`,s=Z({command:n.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?Bt(r,s.flags,i):r;return{...n,binding:e,flags:r,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(r(i),{diagnosticId:b().diagnosticId,logPath:S({force:!0})?.path});return t.flags.json?s({success:!1,error:a}):c(a,{showDetails:n.debugOutputEnabled}),E(1)}}async function wt(e,t){let{daemonAuthToken:r,...i}=e.effectiveFlags;return await Je(e.positionals,{flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await vt({route:`react-devtools`,command:h.runtime,request:{positionals:[`port-reverse`],flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},transport:t.sendToDaemon,transportOptions:{authToken:r}});a.ok||n(a.error)}})}async function Tt(e,n){if(e.command===`batch`){if(e.positionals.length>0)throw new t(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=Pt(e.flags)}if(Lt(e.command)&&(e.effectiveFlags=(await ve({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&It(e.command)){let t=l(q(e),{transport:Q(n.sendToDaemon)}),r=await he({command:e.command,flags:e.effectiveFlags,client:t,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Vt(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Rt({command:e.command,flags:e.effectiveFlags,runtime:e.resolvedRuntime,explicitFlagKeys:e.explicitFlagKeys,hadConnectionDefaults:!!e.connectionDefaults})&&process.stderr.write(`Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.
|
|
5
|
+
`)}function q(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function Et(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Wt(e.daemonPaths.logPath):null}async function Dt(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function Ot(e,n,r){let{command:i,positionals:a,effectiveFlags:o}=e;if(i===`batch`){if(!e.parsedBatchSteps)throw new t(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let s=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:U(t.input,{policyOverrides:o,configuredPlatform:o.platform,configuredSession:o.session,inheritedPlatform:o.platform})}));if(await B({command:i,positionals:a,flags:{...o,batchSteps:s},client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return}else if(i===`runtime`)throw new t(`INVALID_ARGS`,`runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.`);else if(await B({command:i,positionals:a,flags:o,client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return;throw new t(`INVALID_ARGS`,Nt(i))}async function kt(t,n,i){let a=r(t),o=e(a,{diagnosticId:b().diagnosticId,logPath:S({force:!0})?.path});if(n.command===`close`&&Ft(a)){n.effectiveFlags.json&&s({success:!0,data:{closed:`session`,source:`no-daemon`}});return}n.effectiveFlags.json?s({success:!1,error:o}):(c(o,{showDetails:n.debugOutputEnabled}),n.debugOutputEnabled&&At(n,o)),i&&i(),await E(1)}const J=64e3;function At(e,t){if(!e.effectiveFlags.daemonBaseUrl){Y(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&Y(`remote diagnostics`,d(e.daemonPaths.baseDir,n))}function Y(e,t){try{if(D.existsSync(t)){let n=D.readFileSync(t,`utf8`).split(`
|
|
6
|
+
`),r=n.slice(Math.max(0,n.length-200)).join(`
|
|
7
|
+
`);r.length>J&&(r=r.slice(r.length-J)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function jt(e){try{let t=P(e);return X(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function Mt(e){let t=N(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Nt(e){return m(e)?(y({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function X(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function Pt(e){let n=``;if(e.steps)n=e.steps;else if(e.stepsFile)try{n=D.readFileSync(e.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new t(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return tt(n)}function Ft(e){return e.code===`COMMAND_FAILED`?e.details?.kind===`daemon_startup_failed`?!0:e.message.toLowerCase().includes(`failed to start daemon`)?typeof e.details?.infoPath==`string`||typeof e.details?.lockPath==`string`:!1:!1}function Z(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:fe({stateDir:e.stateDir,session:e.session,remoteConfig:e.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!e.explicitFlagKeys.has(`session`)&&(!e.remoteConfig||e.command===`disconnect`||!e.hasResolvedSession),validateRemoteConfigHash:e.command!==`disconnect`})}function It(e){return!xt.has(e)}function Lt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Rt(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:zt(e.explicitFlagKeys)}function zt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Bt(e,t,n){let r={...e};for(let[e,i]of Object.entries(t))i!==void 0&&(n.has(e)||(r[e]=i));return r}function Vt(e){for(let t of bt)if(e.has(t))return!0;return!1}function Ht(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;return n.json?Q(i):async(e,n)=>{let a=t===`test`&&r?{...n,onProgress:r.onProgress}:n;return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},a)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Ut(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`--session=`)){let e=n.slice(10).trim();return e.length>0?e:null}if(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}ye(process.argv[1]??``).href===import.meta.url&&G(process.argv.slice(2)).catch(async t=>{c(e(r(t)),{showDetails:!0}),await E(1)});function Wt(e){try{let t=D.existsSync(e)?D.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&D.existsSync(e))try{let n=D.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=D.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);D.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{D.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{G as runCli};
|