agent-device 0.21.8 → 0.21.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.8.apk → agent-device-android-ime-helper-0.21.9.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.9.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.8.manifest.json → agent-device-android-ime-helper-0.21.9.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.8.apk → agent-device-android-snapshot-helper-0.21.9.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.9.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.8.manifest.json → agent-device-android-snapshot-helper-0.21.9.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubWindowInventory.swift +65 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +45 -140
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubSidebar.swift +57 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubWindowDiscovery.swift +108 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubWindowInventoryTests.swift +65 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +175 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +10 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +42 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +45 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +39 -734
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +20 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +63 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +13 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +5 -562
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +566 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +594 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +35 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +160 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +3 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-frames.swift +203 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +5 -0
- package/dist/src/absence-observation-errors.js +1 -1
- package/dist/src/adapter.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-device-client.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/artifact-paths.js +1 -0
- package/dist/src/back-mode.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +8 -7
- package/dist/src/cli.js +4 -4
- package/dist/src/client-types.d.ts +23 -5
- package/dist/src/command-tools.js +3 -3
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/fold-runtime.js +1 -0
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-catalog.js +1 -1
- package/dist/src/interactor.js +4 -4
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/inventory2.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +17 -17
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/mp4-duration.js +1 -0
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +2 -2
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +2 -2
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-encode.js +1 -0
- package/dist/src/png-size.js +1 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording-export-quality.js +1 -1
- package/dist/src/recording-scope.js +1 -0
- package/dist/src/recording.js +3 -0
- package/dist/src/registry.js +35 -35
- package/dist/src/replay.js +2 -2
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-contract.js +1 -1
- package/dist/src/runner-dev-tools-security.js +1 -1
- package/dist/src/runner-device-readiness.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-presentation.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/runtime10.js +2 -1
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -0
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +7 -5
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-selectors.d.ts +44 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/semantic-index.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session2.js +3 -3
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/stop-sequence.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/video.js +2 -2
- package/package.json +1 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +0 -1
package/dist/src/cli-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{D as e}from"./sdk-contracts.js";import{t}from"./capture.js";import{
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{t}from"./capture.js";import{i as n}from"./catalog.js";import{a as r,r as i}from"./back-mode.js";import{a,s as o}from"./sdk-remote-config.js";import{f as s,s as c}from"./registry.js";import{n as l,t as u}from"./path-resolution.js";import"./file.js";import{n as d}from"./command-schema.js";import f from"node:path";import p from"node:fs";const m=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),h=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),g=S(),_=new Map(g.map(e=>[e.key,e]));function v(e){return _.get(e)}function y(e){return g.filter(t=>t.configurable&&t.supportsCommand(e))}function b(e,t){return v(e)?.supportsCommand(t)??!1}function x(e,t,n,r){return o(T(e),t,n,r)}function S(){let e=new Map;for(let t of i()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of s)t.set(e,new Set([`*`]));for(let e of n()){let n=d(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:!m.has(e),env:{names:h.has(e)?[]:[a(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>C(e.key,t.key))}function C(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function w(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function T(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=w(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 E(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}function D(e){let t=e.env??process.env;return E(E({},M(k(e.cwd,e.cliFlags.config,t))),I(t,e.command))}const O=r();function k(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:j(r,e,n),required:!0,source:`explicit`}]:[{path:A(n),required:!1,source:`user`},{path:f.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function A(e){return f.join(u(`~`,{env:e}),`.agent-device`,`config.json`)}function j(e,t,n){return l(e,{cwd:t,env:n})}function M(e){let t={};for(let n of e)E(t,N(n));return t}function N(t){let{path:n,required:r}=t;if(!p.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=p.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 P(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function P(n,r){let i={};for(let[a,o]of Object.entries(n)){let n=a,s=v(n);if(!s)throw a===t.flagKey?new e(`INVALID_ARGS`,`Config key "${a}" 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 "${a}" in ${r.label}.`);if(!s.configurable)throw new e(`INVALID_ARGS`,`Config key "${a}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!O.has(n))throw new e(`INVALID_ARGS`,`Config key "${a}" 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=c(o,r.label);continue}i[n]=x(s,o,r.label,a)}return i}const F=new Set([`screenshot`,`record`]);function I(n,r){let i=n[t.envVar];if(r!==null&&F.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 y(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]=x(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{E as n,b as r,D as t};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
2
|
-
`)}function m(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function h(e){return
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{_r as t}from"./sdk-batch.js";import{i as n}from"./catalog.js";import{r}from"./back-mode.js";import{d as i,f as a,v as o}from"./registry.js";import{r as s}from"./version.js";import{n as c,r as l}from"./command-schema.js";import{n as u}from"./cli-command-aliases.js";const d=[`Flows: launchApp (with clearState, permissions, and Apple-only launch arguments; permissions apply after state clearing but before launch, and a launchApp without permissions touches nothing — there is no silent all: allow default); setPermissions (mid-flow permission grants, denials, and resets; all resolves in the backend — one simctl call on iOS, the declared permissions on Android — with specific entries overriding after it); runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText on the focused element, eraseText, openLink, hideKeyboard, basic pressKey, and back; selector targets poll until available and support recursive index, childOf, above, below, leftOf, rightOf, containsChild, containsDescendants, points, and optional; outer command labels are metadata, not target selectors.`,'Assertions and navigation: assertVisible, assertNotVisible, assertTrue (literal values and ${VAR} lookups only; "", "false", "0", "null", and "undefined" are falsy, everything else is truthy), extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, clearState, and stopApp.',`Scripts: ordered runScript file/env scripts with http.post, json, and output variables; evalScript inline expressions run flow-scoped JavaScript and write output.* leaves for later steps.`],f=[`Permissions: every entry is one settings permission call, applied in order with all first; the step stops at the first entry the selected platform refuses, earlier entries stay applied, and the error names what landed. Android’s only allow level is while-in-use, so location: inuse and location: never mean allow and deny there, while location: always and photos: limited are Apple-only and fail. On iOS, which service a runtime changes is simctl privacy’s own verdict: current runtimes refuse a targeted notifications change and leave notifications untouched under all.`,`Runtime: iOS and Android only; launchApp.clearState and standalone clearState support Android and iOS simulators, launch arguments are Apple-only, and other standalone device utility/state commands are unsupported.`,"Expressions: evalScript is the only command whose payload is evaluated as JavaScript (flow env and prior output leaves are string-typed); with that exception, fields stay literal or ${VAR} lookup-only — assertTrue supports literals and bare lookups, repeat.while is unsupported, and other expression-shaped payloads fail loud.",`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 and evalScript execute flow scripts in-process via node:vm, which is not a security sandbox; runScript may make http.post network requests and its output keys cannot contain a dot. evalScript is refused outright for a flow accepted over the daemon’s remote HTTP surface, since that context can escape to the host.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function p(){return[`Supported subset:`,...d.map(e=>` - ${e}`),``,`Boundaries:`,...f.map(e=>` - ${e}`)].join(`
|
|
2
|
+
`)}function m(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function h(e){return r().filter(t=>t.key===e)}function g(e){if(!e.usageHidden)return e.usageLabel??e.names[0]}function _(e){return(e??[]).flatMap(e=>h(e).map(g).filter(e=>e!==void 0).map(e=>`[${e}]`))}function v(e,t){return[t.usageOverride??[e,...(t.positionalArgs??[]).map(m)].join(` `),..._(t.usageFlags??t.allowedFlags)].join(` `)}function y(){return`agent-device <command> [args] [--json]
|
|
3
3
|
|
|
4
4
|
Automates iOS, Android, macOS, TV, and web apps for AI agents.
|
|
5
|
-
All ${
|
|
5
|
+
All ${n().length} commands: agent-device help commands
|
|
6
6
|
|
|
7
7
|
Start:
|
|
8
8
|
When starting a task with a known app, first run:
|
|
@@ -213,6 +213,7 @@ Batch:
|
|
|
213
213
|
|
|
214
214
|
Recording:
|
|
215
215
|
record start/stop. Default scope is app (needs an active open session); use --scope device/system for whole-screen capture spanning multiple apps/home/settings. --quality medium|high on Android and Apple targets. stop burns touch overlays into the video by default; --hide-touches skips that for the fastest raw recording, and is recommended for gesture-heavy iOS simulator proof videos since overlay timing depends on a stable runner session. Android adb screenrecord has a 180s limit, so long Android recordings return as multiple MP4 chunks while the daemon stays alive; after a daemon restart, record stop recovers only manifest-owned chunks. record stop is safe to repeat: if its request window ended while the daemon was still exporting, running it again in that session returns the completed recording instead of starting a second one.
|
|
216
|
+
record contact-sheet <video.mp4> [--out <sheet.png>] reads an exported MP4 back and writes one PNG holding the frames where the screen visibly changed, each labeled with its elapsed time. It is how you read a recording you cannot play, and it needs no session or device; the frames come out of that file, so the sheet cannot describe a screen the video does not contain. The sample grid is bounded and spread over the whole clip, so it reports coverage, not a review: a flash that opens and closes between two sample times is not in it. Needs a macOS host and an MP4 (a WebM recording is refused).
|
|
216
217
|
Tracing: trace start ./trace.log, trace stop ./trace.log (path is positional, not --path).`},gestures:{summary:`Full multi-touch gesture shapes and platform quirks`,body:`agent-device help gestures
|
|
217
218
|
|
|
218
219
|
Full command shapes and platform quirks for touch/pointer gestures beyond scroll/swipe. Read this when a task needs multi-touch, a repeated gesture series, or exact per-platform verification.
|
|
@@ -681,12 +682,12 @@ A foldable Apple device (iPhone Duo) carries two integrated panels, which Apple
|
|
|
681
682
|
|
|
682
683
|
Screens are handled for you:
|
|
683
684
|
Each iOS simulator capture resolves the CoreDevice display table, captures the lit panel explicitly, and normalizes density with that panel's own point scale. Do not add a screen flag to the normal loop; there is none, because the lit panel is always the only capturable one: the dark panel yields an all-black PNG.
|
|
684
|
-
The two panels are different sizes
|
|
685
|
+
The two panels are different sizes (iPhone Duo: 466x678 points closed on the outer panel, 669x951 open on the inner). A pose change therefore invalidates every ref and coordinate. Re-snapshot after any pose change and never carry coordinates or refs across one.
|
|
685
686
|
Check which panel is lit before trusting a geometry claim: agent-device screenshot reports its point size, and 466x678 versus 669x951 says which panel you captured.
|
|
686
687
|
|
|
687
688
|
Changing the pose:
|
|
688
689
|
agent-device fold closed | half-open | open
|
|
689
|
-
fold presses the pose control in the Xcode Device Hub window for this simulator (Closed, Book, Open) and then reads the hinge angle back from CoreDevice until it agrees: closed is 0 degrees, open is 180, and half-open is any angle between them (Device Hub's Book preset, 130 degrees on iOS 27.1)
|
|
690
|
+
fold presses the pose control in the Xcode Device Hub window for this simulator (Closed, Book, Open) and then reads the hinge angle back from CoreDevice until it agrees: closed is 0 degrees, open is 180, and half-open is any angle between them (Device Hub's Book preset, 130 degrees on iOS 27.1). An angle in that interval only proves the category, so half-open is reported once two consecutive readings both fall inside it and agree within 0.5 degrees. The response reports the verified pose, the hinge angle, and the panel the device now lights with its native panel point size, marked coordinateSpace "native-panel". That point size is the panel's own geometry, not the next snapshot's viewport, so it cannot place a tap: the active app window can differ (a 669x951 inner panel hosts a 951x669 window). A hinge whose last reading is some other pose fails with COMMAND_FAILED and reason fold-pose-unverified, naming the angle CoreDevice still reports; a hinge seen half-open but never at rest fails with reason fold-pose-unsettled, naming the observed and previous angles. A single-panel simulator fails with UNSUPPORTED_OPERATION.
|
|
690
691
|
Expect a fold to take 10-16 seconds: each hinge read is a five-second devicectl stream, and half-open waits for the hinge to stop moving. Re-snapshot after every fold; refs and coordinates from before it are stale, and the command's message says so.
|
|
691
692
|
Requirements: an iOS simulator session on a foldable device, Xcode 27.1 or newer with Device Hub, and Accessibility permission for the host (agent-device settings permission grant accessibility --platform macos). The command launches Device Hub if needed, reopens its window when it shows none, and selects the simulator through its sidebar by UDID, so no operator step is needed. No official host API sets the pose; the app under test still reads it as UIHinge.status.
|
|
692
693
|
If a task asserts behavior for more than one pose, fold to each pose and re-snapshot, and report which poses the run covered.`},remote:{summary:`Direct proxy, cloud profiles, and remote config`,body:`agent-device help remote
|
|
@@ -979,7 +980,7 @@ Report:
|
|
|
979
980
|
|
|
980
981
|
Full command catalog. Use agent-device help <command> for exact flags and behavior.
|
|
981
982
|
|
|
982
|
-
${I(
|
|
983
|
+
${I(n().map(e=>{let t=c(e);return{name:e,schema:t,usage:D(e,t)}}))}
|
|
983
984
|
|
|
984
985
|
${N(`Device Selection (shared by device commands; help <command> lists each command's flags):`,j(i))}
|
|
985
986
|
|
|
@@ -990,7 +991,7 @@ ${F(`Configuration:`,x)}
|
|
|
990
991
|
${P(`Environment:`,S)}
|
|
991
992
|
|
|
992
993
|
${F(`Examples:`,C)}
|
|
993
|
-
`}function A(){return O()}function j(e){return
|
|
994
|
+
`}function A(){return O()}function j(e){return r().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function M(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function N(e,t){return P(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function P(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(`
|
|
994
995
|
`)}function F(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
|
|
995
996
|
`)}function I(e){return P(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function L(e){let t=B(e);if(t)return t;let n=l(e);if(!n)return null;let r=v(e,n),i=M(j(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),a=[];i.length>0&&a.push(N(`Command flags:`,i));let s=a.length>0?`\n\n${a.join(`
|
|
996
997
|
|
package/dist/src/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{D as e,H as t,L as n,O as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{n as l,r as u}from"./agent-device-client.js";import{s as d,t as f,u as p}from"./sdk-batch.js";import{n as m,r as h}from"./back-mode.js";import{i as g,r as _,t as v}from"./catalog.js";import{x as ee}from"./registry.js";import{a as y,i as b,l as te,n as ne,o as re,r as x}from"./diagnostics.js";import{f as ie}from"./exec.js";import{n as ae}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as oe}from"./version.js";import{t as se}from"./daemon-resolution.js";import{t as ce}from"./session-artifact-paths.js";import{r as le,t as ue}from"./command-schema.js";import{n as S,r as C,t as de}from"./cli-config.js";import{t as fe}from"./update-check.js";import{n as pe,r as me,t as he}from"./cli-command-aliases.js";import{exitAfterFlush as w}from"./process-exit.js";import{D as ge,E as _e,O as ve,d as ye,k as be,m as xe,n as Se,w as Ce}from"./connection-runtime.js";import{i as we}from"./auth-session.js";import T from"node:fs";import{pathToFileURL as Te}from"node:url";const E=`open <app> --relaunch`,Ee={start:{command:`open`,example:E},restart:{command:`open`,example:E},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 D(e){if(e.length<=2)return[];let t=g(),n=t.filter(t=>t.startsWith(e));return n.length>0?n.sort(O).slice(0,3):k(e,t)}function O(e,t){return e.length-t.length||e.localeCompare(t)}function k(e,t){let n=t.map(t=>({name:t,distance:Oe(e,t)})).filter(t=>t.distance<=De(e));if(n.length===0)return[];let r=Math.min(...n.map(e=>e.distance));return n.filter(e=>e.distance===r).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function De(e){return e.length<4?1:e.length<=6?2:3}function Oe(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):ke(e,t)}function ke(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 A(e){let t=e.toLowerCase(),n=Ee[t]?.example;if(n)return n;let r=D(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const Ae=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),je=new Set([`--session-locked`,`--session-lock-conflicts`]),Me={"--output":`--out`,"--path":`--out`};function Ne(e,t){let n=e.toLowerCase(),r=Me[n];if(r&&Pe(r,t))return r;let i=Fe(n,t);if(i.length!==0)return i.length===1?i[0]:`one of: ${i.join(`, `)}`}function Pe(e,t){let n=h().find(t=>t.names.includes(e));return n?C(n.key,t):!1}function Fe(e,t){let n=j(e);if(n.length<=2)return[];let r=Ie(t),i=r.filter(e=>j(e).startsWith(n));return i.length>0?i.sort(O).slice(0,3):k(n,r.map(e=>j(e))).map(e=>`--${e}`)}function Ie(e){let t=new Set;for(let n of h()){if(!C(n.key,e))continue;let r=n.names[0];r&&t.add(r)}return[...t]}function j(e){return e.replace(/^--?/,``)}function Le(e,t){let n=e.toLowerCase();if(Ae.has(n))return`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${E}.`;if(je.has(n))return`Unknown flag: ${e}. Use --session-lock reject|strip instead.`;if(n===i.cliToken)return`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`;let r=Ne(e,t);return r?`Unknown flag: ${e}. Did you mean ${r}?`:`Unknown flag: ${e}`}function M(t){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<t.length;o+=1){let l=t[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ve(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=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(ze(r,f))continue;let m=He(f,r);if(Be(r,m)){a.push(l);continue}if(!m){if(qe(r,a,l)){r?a.push(l):r=l;continue}throw new e(`INVALID_ARGS`,Le(f,r))}let h=Ge(m,f,p,t[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 Re(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Re(e,t){if(e)for(let n of he(e)?.impliedFlags??[])t[n]=!0}function ze(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Be(e,t){return e===`react-devtools`?!t||!C(t.key,e):!1}function Ve(e){return e===`cdp`}function He(e,t){let n=h().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??m(e);if(t){let e=n.find(e=>C(e.key,t));if(e)return e}return m(e)}function Ue(t,n){let r=n?.strictFlags??!0,i=[...t.warnings],a=S({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(S(a,t.flags),t.command&&!_(t.command)&&!a.help){let n=A(t.command),r=n?`Unknown command: ${t.command}. Did you mean ${n}?`:`Unknown command: ${t.command}`;throw new e(`INVALID_ARGS`,r)}let o=t.providedFlags.filter(e=>!C(e.key,t.command));if(o.length>0){let n=o.map(e=>e.token),s=Xe(t.command,n);if(r)throw new e(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let e of Object.keys(a))a[e]!==void 0&&(C(e,t.command)||delete a[e]);We(t),p(t.command,a);let s=Ye({command:t.command,positionals:t.positionals,flags:a,warnings:i});if(ue(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new e(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function We(t){if(t.command!==`back`)return;let n=t.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new e(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Ge(t,n,r,i){if(t.setValue!==void 0){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:t.setValue,consumeNext:!1}}if(t.type===`boolean`){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(t.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new e(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Ke(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new e(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(t.type===`string`)return{value:a,consumeNext:r===void 0};if(t.type===`enum`){if(!t.enumValues?.includes(a))throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof t.min==`number`&&o<t.min||typeof t.max==`number`&&o>t.max)throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:t.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return m(t)!==void 0}function Ke(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 qe(e,t,n){if(!Je(n)||!e)return!1;let r=le(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Je(e){return/^-\d+(\.\d+)?$/.test(e)}function Ye(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 Xe(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 I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function Ze(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(t){let n=me(t);if(n)throw new e(`INVALID_ARGS`,n);return pe(t)}function Qe(){return{renderedToStderr:!1}}function $e(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function et(e){return ae(e)}const tt={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,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand};async function R(e){let t={...e.flags},n=tt[e.command];return n&&await(await n())({...e,flags:t})?!0:et(e.command)?await nt({...e,command:e.command,flags:t}):!1}async function nt(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function rt(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function it(e){return e===`ios-instance`}function at(e){return e[0]===`wait`&&e.includes(`--connected`)}function ot(e,t,n){n===0||!at(e)||!it(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 z(e,t,n){return n||(e.push(t),``)}function
|
|
3
|
-
`)}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,providerAppiumVersion:t.providerAppiumVersion,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
|
|
1
|
+
import{D as e,H as t,L as n,O as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{n as l,r as u}from"./agent-device-client.js";import{s as d,t as f,u as p}from"./sdk-batch.js";import{i as m,r as h,t as g}from"./catalog.js";import{n as _,r as v}from"./back-mode.js";import{x as ee}from"./registry.js";import{a as y,i as b,l as te,n as ne,o as re,r as x}from"./diagnostics.js";import{f as ie}from"./exec.js";import{n as ae}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as oe}from"./version.js";import{t as se}from"./daemon-resolution.js";import{t as ce}from"./session-artifact-paths.js";import{r as S,t as le}from"./command-schema.js";import{n as C,r as w,t as ue}from"./cli-config.js";import{t as de}from"./update-check.js";import{n as fe,r as pe,t as me}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{D as he,E as ge,O as _e,d as ve,k as ye,m as be,n as xe,w as Se}from"./connection-runtime.js";import{i as Ce}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as we}from"node:url";const D=`open <app> --relaunch`,Te={start:{command:`open`,example:D},restart:{command:`open`,example:D},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 Ee(e){if(e.length<=2)return[];let t=m(),n=t.filter(t=>t.startsWith(e));return n.length>0?n.sort(O).slice(0,3):k(e,t)}function O(e,t){return e.length-t.length||e.localeCompare(t)}function k(e,t){let n=t.map(t=>({name:t,distance:Oe(e,t)})).filter(t=>t.distance<=De(e));if(n.length===0)return[];let r=Math.min(...n.map(e=>e.distance));return n.filter(e=>e.distance===r).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function De(e){return e.length<4?1:e.length<=6?2:3}function Oe(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):ke(e,t)}function ke(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 A(e){let t=e.toLowerCase(),n=Te[t]?.example;if(n)return n;let r=Ee(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const Ae=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),je=new Set([`--session-locked`,`--session-lock-conflicts`]),Me={"--output":`--out`,"--path":`--out`};function Ne(e,t){let n=e.toLowerCase(),r=Me[n];if(r&&Pe(r,t))return r;let i=Fe(n,t);if(i.length!==0)return i.length===1?i[0]:`one of: ${i.join(`, `)}`}function Pe(e,t){let n=v().find(t=>t.names.includes(e));return n?w(n.key,t):!1}function Fe(e,t){let n=j(e);if(n.length<=2)return[];let r=Ie(t),i=r.filter(e=>j(e).startsWith(n));return i.length>0?i.sort(O).slice(0,3):k(n,r.map(e=>j(e))).map(e=>`--${e}`)}function Ie(e){let t=new Set;for(let n of v()){if(!w(n.key,e))continue;let r=n.names[0];r&&t.add(r)}return[...t]}function j(e){return e.replace(/^--?/,``)}function Le(e,t){let n=e.toLowerCase();if(Ae.has(n))return`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${D}.`;if(je.has(n))return`Unknown flag: ${e}. Use --session-lock reject|strip instead.`;if(n===i.cliToken)return`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`;let r=Ne(e,t);return r?`Unknown flag: ${e}. Did you mean ${r}?`:`Unknown flag: ${e}`}function M(t){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<t.length;o+=1){let l=t[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ve(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=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(ze(r,f))continue;let m=He(f,r);if(Be(r,m)){a.push(l);continue}if(!m){if(qe(r,a,l)){r?a.push(l):r=l;continue}throw new e(`INVALID_ARGS`,Le(f,r))}let h=Ge(m,f,p,t[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 Re(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Re(e,t){if(e)for(let n of me(e)?.impliedFlags??[])t[n]=!0}function ze(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Be(e,t){return e===`react-devtools`?!t||!w(t.key,e):!1}function Ve(e){return e===`cdp`}function He(e,t){let n=v().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??_(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return _(e)}function Ue(t,n){let r=n?.strictFlags??!0,i=[...t.warnings],a=C({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(C(a,t.flags),t.command&&!h(t.command)&&!a.help){let n=A(t.command),r=n?`Unknown command: ${t.command}. Did you mean ${n}?`:`Unknown command: ${t.command}`;throw new e(`INVALID_ARGS`,r)}let o=t.providedFlags.filter(e=>!w(e.key,t.command));if(o.length>0){let n=o.map(e=>e.token),s=Qe(t.command,n);if(r)throw new e(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}let s=Xe(t);if(s.length>0){let n=Ze(t.command,t.positionals[0],s);if(r)throw new e(`INVALID_ARGS`,n);i.push(n);for(let e of s)delete a[e.key]}for(let e of Object.keys(a))a[e]!==void 0&&(w(e,t.command)||delete a[e]);We(t),p(t.command,a);let c=Ye({command:t.command,positionals:t.positionals,flags:a,warnings:i});if(le(c.command,c.positionals),c.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new e(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return c}function We(t){if(t.command!==`back`)return;let n=t.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new e(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Ge(t,n,r,i){if(t.setValue!==void 0){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:t.setValue,consumeNext:!1}}if(t.type===`boolean`){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(t.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new e(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Ke(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new e(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(t.type===`string`)return{value:a,consumeNext:r===void 0};if(t.type===`enum`){if(!t.enumValues?.includes(a))throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof t.min==`number`&&o<t.min||typeof t.max==`number`&&o>t.max)throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:t.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return _(t)!==void 0}function Ke(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 qe(e,t,n){if(!Je(n)||!e)return!1;let r=S(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Je(e){return/^-\d+(\.\d+)?$/.test(e)}function Ye(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 Xe(e){let t=S(e.command)?.flagsByAction,n=e.positionals[0];if(t===void 0||n===void 0||!Object.hasOwn(t,n))return[];let r=t[n];if(r===void 0)return[];let i=new Set(Object.values(t).flat());return e.providedFlags.filter(e=>i.has(e.key)&&!r.includes(e.key))}function Ze(e,t,n){return`${e} ${t} does not read ${n.map(e=>e.token).join(`, `)}. Run \`${e} ${t} --help\` for the options it reads.`}function Qe(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 I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function $e(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(t){let n=pe(t);if(n)throw new e(`INVALID_ARGS`,n);return fe(t)}function et(){return{renderedToStderr:!1}}function tt(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function nt(e){return ae(e)}const rt={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,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand,record:async()=>(await import(`./recording.js`)).recordingCommand};async function R(e){let t={...e.flags},n=rt[e.command];return n&&await(await n())({...e,flags:t})?!0:nt(e.command)?await it({...e,command:e.command,flags:t}):!1}async function it(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function at(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function ot(e){return e===`ios-instance`}function st(e){return e[0]===`wait`&&e.includes(`--connected`)}function ct(e,t,n){n===0||!st(e)||!ot(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 z(e,t,n){return n||(e.push(t),``)}function lt(t){if(!t?.metroProxyBaseUrl||!he(t.leaseBackend))return null;let n=[],r={serverBaseUrl:z(n,`metroProxyBaseUrl`,t.metroProxyBaseUrl),bearerToken:z(n,`metroBearerToken`,t.metroBearerToken),tenantId:z(n,`tenant`,t.tenant),runId:z(n,`runId`,t.runId),leaseId:z(n,`leaseId`,t.leaseId)};if(n.length>0)throw new e(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function ut(e,t,n){let{flags:r}=t,i=lt(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 ye({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await _e({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 dt(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?ve(n.leaseProvider).supportsDirectPortReverse&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function ft(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await ut(e,t,async()=>(dt(e,t)&&await t.configureDirectPortReverse?.(),(await ie(`npm`,at(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return ct(e,t.flags,i),i}const B=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,pt=`${f} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function mt(t){let n;try{n=JSON.parse(t)}catch{throw new e(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new e(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return n.map((e,t)=>ht(e,t+1))}function ht(t,n){let r=a(t,n,B),i=[`positionals`,`flags`].filter(e=>e in r);if(i.length>0){let t=i.map(e=>`"${e}"`).join(`, `);throw new e(`INVALID_ARGS`,`Batch step ${n} uses removed field(s): ${t}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:B})}ee(r,[`command`,`input`,`runtime`],`Batch step ${n}`,B);let s=o(r.runtime,n);return{command:d(r.command,n,pt),input:c(r,n,B),...s===void 0?{}:{runtime:s}}}function V(e,t={}){let n=H(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function H(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??_t(t.AGENT_DEVICE_PLATFORM),r=yt(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:gt(e.policyOverrides,t,r)}}function gt(e,t,n){let r=e?.sessionLock??vt(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function _t(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new e(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${t}. Use ios, android, or apple.`)}}function vt(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new e(`INVALID_ARGS`,`Invalid session lock mode: ${t}. Use reject or strip.`)}}function yt(e){return typeof e==`string`&&e.trim().length>0}function bt(e,t){let n=M(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=xt(n.command)?be({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=C(ue({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Ue(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function xt(e){return e!==null}g.runtime;async function St(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const U=(e,t={})=>import(`./error.js`).then(e=>e.t).then(({printHumanError:n})=>n(e,t)),W=e=>import(`./json.js`).then(({printJson:t})=>t(e)),Ct={sendToDaemon:u},wt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),Tt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function G(e,t=Ct){let n=ne(),r=oe(),i=Ft(e),a=e.includes(`--json`),o=qt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await te({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await Et(e,{version:r,jsonRequested:a,debugEnabled:i}),u=Z(s,o.providedFlags),d=await Dt(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:u});K(d.effectiveFlags);let f=null;try{if(s===`react-devtools`){await T(await Ot(d,t));return}if(s===`web`){let{runWebCommand:e}=await import(`./web.js`);await T(await e(c,{flags:d.effectiveFlags,stateDir:d.daemonPaths.baseDir}));return}if(de({command:s,currentVersion:r,stateDir:d.daemonPaths.baseDir,flags:d.effectiveFlags}),await kt(d,t),K(d.effectiveFlags),s===`cdp`){await T(await ge(c,{flags:d.effectiveFlags,runtime:d.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}f=At(d);let e=await jt(d),n=et();await Mt(d,l(q(d),{transport:Kt({command:s,flags:d.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await Nt(e,d,f)}finally{f&&f()}})}function K(e){e.daemonAuthToken&&re(e.daemonAuthToken)}async function Et(t,r){let i;try{i=bt(t,{cwd:process.cwd(),env:process.env})}catch(e){x({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let t=n(e,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return r.jsonRequested?await W({success:!1,error:t}):await U(t,{showDetails:r.debugEnabled}),T(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),T(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return await U(new e(`INVALID_ARGS`,`help accepts at most one command.`)),T(1);let t=a?i.positionals[0]:i.command;if(!t)return process.stdout.write(`${await I()}\n`),T(0);let n=await $e(t);return n?(process.stdout.write(n),T(0)):(await U(new e(`INVALID_ARGS`,It(t))),process.stdout.write(`${await I()}\n`),T(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await I()}\n`),T(1))}async function Dt(e,t){let i=new Set(e.providedFlags.map(e=>e.key));try{let n=H({policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),r=n.lockPolicy?{...e.flags}:V(e.flags,{policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),a=se(r.stateDir),o=r.session??`default`,s=zt({command:t.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?Wt(r,s.flags,i):r;return{...t,binding:n,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=r(i),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return e.flags.json?await W({success:!1,error:o}):await U(o,{showDetails:t.debugOutputEnabled}),T(1)}}async function Ot(e,n){let{daemonAuthToken:r,...i}=e.effectiveFlags;return await ft(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 St({route:`react-devtools`,command:g.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:n.sendToDaemon,transportOptions:{authToken:r}});a.ok||t(a.error)}})}async function kt(t,n){if(t.command===`batch`){if(t.positionals.length>0)throw new e(`INVALID_ARGS`,`batch does not accept positional arguments.`);t.parsedBatchSteps=Lt(t.flags)}if(Vt(t.command)&&(t.effectiveFlags=(await Ce({command:t.command,flags:t.effectiveFlags,stateDir:t.daemonPaths.baseDir,env:process.env})).flags),t.effectiveFlags.remoteConfig&&Bt(t.command)){let e=l(q(t),{transport:Q(n.sendToDaemon)}),r=await xe({command:t.command,flags:t.effectiveFlags,client:e,runtime:t.resolvedRuntime,positionals:t.positionals,batchSteps:t.parsedBatchSteps,forceRuntimePrepare:Gt(t.explicitFlagKeys)});t.effectiveFlags=r.flags,t.resolvedRuntime=r.runtime,t.connectionMetadata=r.connection}Ht({command:t.command,flags:t.effectiveFlags,runtime:t.resolvedRuntime,explicitFlagKeys:t.explicitFlagKeys,hadConnectionDefaults:!!t.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.
|
|
3
|
+
`)}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,providerAppiumVersion:t.providerAppiumVersion,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 At(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Jt(e.daemonPaths.logPath):null}async function jt(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 Mt(t,n,r,i){let{command:a,positionals:o,effectiveFlags:s}=t;if(a===`batch`){if(!t.parsedBatchSteps)throw new e(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let c=t.parsedBatchSteps.map((e,n)=>({...e,input:t.binding.lockPolicy&&t.flags.platform===void 0?{...e.input}:V(e.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await R({command:a,positionals:o,flags:{...s,batchSteps:c},client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return}else if(a===`runtime`)throw new e(`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 R({command:a,positionals:o,flags:s,client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return;throw new e(`INVALID_ARGS`,X(a))}async function Nt(e,t,i){let a=r(e),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});if(t.command===`close`&&Rt(a)){t.effectiveFlags.json&&await W({success:!0,data:{closed:`session`,source:`no-daemon`}});return}t.effectiveFlags.json?await W({success:!1,error:o}):(await U(o,{showDetails:t.debugOutputEnabled}),t.debugOutputEnabled&&Pt(t,o)),i&&i(),await T(1)}const J=64e3;function Pt(e,t){if(!e.effectiveFlags.daemonBaseUrl){Y(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&Y(`remote diagnostics`,ce(e.daemonPaths.baseDir,n))}function Y(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
|
|
4
4
|
`),r=n.slice(Math.max(0,n.length-200)).join(`
|
|
5
|
-
`);r.length>J&&(r=r.slice(r.length-J)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function
|
|
5
|
+
`);r.length>J&&(r=r.slice(r.length-J)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function Ft(e){try{let t=M(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function It(e){let t=A(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function X(e){return h(e)?(x({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function Z(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function Lt(t){let n=``;if(t.steps)n=t.steps;else if(t.stepsFile)try{n=E.readFileSync(t.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new e(`INVALID_ARGS`,`Failed to read --steps-file ${t.stepsFile}: ${r}`)}return mt(n)}function Rt(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 zt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:Se({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 Bt(e){return!Tt.has(e)}function Vt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Ht(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Ut(e.explicitFlagKeys)}function Ut(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Wt(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 Gt(e){for(let t of wt)if(e.has(t))return!0;return!1}function Kt(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:tt(e.commandProgress);return async(e,n)=>{let r={...n,onProgress:a};return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},r)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function qt(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}we(process.argv[1]??``).href===import.meta.url&&G(process.argv.slice(2)).catch(async e=>{let t=r(e);await U(n(t),{showDetails:!0}),await T(1)});function Jt(e){try{let t=E.existsSync(e)?E.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&E.existsSync(e))try{let n=E.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=E.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);E.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{E.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{G as runCli};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { E as IosTargetActivation, H as DaemonError, I as SnapshotQualityVerdict, M as SnapshotKeyboardBandFact, N as SnapshotNode, R as SnapshotUnchanged, S as DeviceTarget, T as PublicPlatform, U as NormalizedError, _ as SessionIsolationMode, a as DaemonRequest, f as LeaseBackend, g as ResponseLevel, i as DaemonLockPolicy, j as SnapshotCommandOptionFields, m as NetworkIncludeMode, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as SessionRuntimeHints, w as PlatformSelector, x as DeviceKind, y as AppleOS, z as SnapshotVisibility } from "./sdk-contracts.js";
|
|
2
2
|
import { t as AppsFilter } from "./app-inventory.js";
|
|
3
|
-
import { B as
|
|
3
|
+
import { A as GesturePointerCount, B as ClickButton, C as FoldPose, D as PermissionMode, E as PermissionAction, F as ScrollDirection, G as SessionSurface, H as FindLocator, I as ScrollInputDirection, L as SwipePattern, O as TextSizeCategory, R as SwipePreset, S as DeviceRotation, T as MOBILE_PERMISSION_TARGETS, U as ScreenshotResultData, V as AndroidSnapshotBackendMetadata, W as SnapshotDiagnosticsSummary, _ as HoverCommandResponseData, b as SettleObservation, g as FindCommandResponseData, h as FillCommandResponseData, k as BackMode, m as ClickCommandResponseData, p as ScrollCommandResult, v as LongPressCommandResponseData, w as MACOS_PERMISSION_TARGETS, x as TvRemoteButton, y as PressCommandResponseData, z as TransformGestureParams } from "./sdk-selectors.js";
|
|
4
4
|
import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
|
|
5
5
|
import { t as BatchRunResult } from "./sdk-batch-runner.js";
|
|
6
6
|
import { r as CloudProviderSessionResult, t as AgentArtifactsResult } from "./cloud-artifacts.js";
|
|
@@ -927,6 +927,15 @@ type SettingsUpdateOptions = (DeviceCommandBaseOptions & {
|
|
|
927
927
|
}) | (DeviceCommandBaseOptions & {
|
|
928
928
|
setting: 'appearance';
|
|
929
929
|
state: 'light' | 'dark' | 'toggle';
|
|
930
|
+
}) |
|
|
931
|
+
/**
|
|
932
|
+
* One member, two legs: with a `state` it applies that rung, and without one it asks the target
|
|
933
|
+
* what it currently holds. The ladder is shared across platforms; an owner that serves neither
|
|
934
|
+
* leg refuses on its own runtime fact rather than answering an empty value.
|
|
935
|
+
*/
|
|
936
|
+
(DeviceCommandBaseOptions & {
|
|
937
|
+
setting: 'text-size';
|
|
938
|
+
state?: TextSizeCategory;
|
|
930
939
|
}) | (DeviceCommandBaseOptions & {
|
|
931
940
|
setting: 'faceid' | 'touchid';
|
|
932
941
|
state: 'match' | 'nonmatch' | 'enroll' | 'unenroll';
|
|
@@ -1291,13 +1300,21 @@ type ViewportCommandResult = {
|
|
|
1291
1300
|
};
|
|
1292
1301
|
//#endregion
|
|
1293
1302
|
//#region packages/contracts/src/fold-runtime.d.ts
|
|
1303
|
+
/** Single source of truth for the discriminator the Apple owner sets and the MCP schema advertises. */
|
|
1304
|
+
declare const FOLD_SCREEN_COORDINATE_SPACE: 'native-panel';
|
|
1294
1305
|
/**
|
|
1295
|
-
* The
|
|
1296
|
-
*
|
|
1306
|
+
* The panel the device lights after the pose settled, in that panel's own native points: its pixel
|
|
1307
|
+
* size divided by its point scale, never rotated. `coordinateSpace` is always
|
|
1308
|
+
* {@link FOLD_SCREEN_COORDINATE_SPACE}, and these numbers are NOT snapshot coordinates — the active
|
|
1309
|
+
* app window can differ from the panel (iPhone Duo: a 669x951 inner panel hosts a 951x669 app
|
|
1310
|
+
* window), so they cannot place a tap. A caller that needs the app viewport must take a fresh
|
|
1311
|
+
* snapshot.
|
|
1297
1312
|
*/
|
|
1298
1313
|
type FoldScreenReport = Readonly<{
|
|
1299
1314
|
/** The CoreDevice display name of the panel the device now lights. */
|
|
1300
1315
|
display: string;
|
|
1316
|
+
/** Marks these dimensions as the panel's native points, never a snapshot's app viewport. */
|
|
1317
|
+
coordinateSpace: typeof FOLD_SCREEN_COORDINATE_SPACE;
|
|
1301
1318
|
widthPt: number;
|
|
1302
1319
|
heightPt: number;
|
|
1303
1320
|
}>;
|
|
@@ -1348,8 +1365,9 @@ type OrientationCommandResult = {
|
|
|
1348
1365
|
*
|
|
1349
1366
|
* Unlike `orientation`, there is no unconfirmed variant: the Apple owner reads the hinge angle
|
|
1350
1367
|
* back from CoreDevice after pressing the Device Hub pose control, and reports a pose only when
|
|
1351
|
-
* that reading agrees with the request. `screen` names the panel the device lights afterwards
|
|
1352
|
-
*
|
|
1368
|
+
* that reading agrees with the request. `screen` names the panel the device lights afterwards and
|
|
1369
|
+
* that panel's native point size (ADR 0025); it is the panel's geometry, not the app viewport, so a
|
|
1370
|
+
* caller must take a fresh snapshot before placing a tap.
|
|
1353
1371
|
*/
|
|
1354
1372
|
type FoldCommandResult = {
|
|
1355
1373
|
action: 'fold';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{B as e,D as t,L as n,r,z as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{i as s,t as c}from"./sdk-device.js";import{S as l,c as u,d,p as f,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{C as re,S as p,_ as m,b as ie,g as h,h as g,y as ae}from"./registry.js";import{n as oe}from"./success-text.js";import{t as se}from"./output-common.js";import"./device.js";import{r as ce,t as le}from"./device-rotation.js";import{t as ue}from"./tv-remote.js";import{i as de,n as _,r as fe,t as v}from"./command-metadata.js";import{r as pe}from"./replay-divergence.js";import{n as me,t as he}from"./cli-output.js";import{r as ge,t as _e}from"./recording-stop-observation.js";import{n as ve}from"./error.js";import{n as ye,r as be,t as xe}from"./cli-config.js";import{n as Se}from"./result-serialization.js";const y=[`simulator`,`emulator`,`device`];function b(e){return{type:`number`,...e?{description:e}:{}}}function x(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function S(e){return{type:`string`,const:e}}function C(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function w(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const T={type:`array`,items:{type:`string`}},E=w({wallClockMs:b(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:b(`Number of real runner round-trips made while serving the request.`),nodeCount:b(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),D=w({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return w({targetKind:x([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:b(`Resolved interaction x coordinate when available.`),y:b(`Resolved interaction y coordinate when available.`),referenceWidth:b(`Reference frame width for visualizing the interaction point.`),referenceHeight:b(`Reference frame height for visualizing the interaction point.`),ref:m(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:m(`Selector expression when the target was a selector.`),selectorChain:T,refLabel:m(),targetHittable:g(),hint:m(),warning:m(),message:m(),evidence:j,resolution:Ce,cost:E,maestroNonHittableCoordinateFallbackAllowed:g(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:g(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:S(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=w({diagnosticRef:m(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:m(`UTF-8 truncated to 256 bytes.`),label:m(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),Ce={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`unique`)},[`source`,`phase`,`kind`]),w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:x([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:k}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`exact`)},[`source`,`phase`,`kind`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`label-fallback`)},[`source`,`phase`,`kind`]),w({source:S(`direct-ios`),kind:S(`not-observed`)},[`source`,`kind`])]},A=w({from:m(`Surface the pre-action baseline described: a host bundle id, or app.`),to:m(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:m(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),j=w({foregroundApp:m(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:b(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:b(`Subset of nodeCount the platform reports as hittable.`),digest:m(`Order-independent digest of the post-action node multiset.`),changedFromBefore:g(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:A},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),we=w({settled:g(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:A,diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:g(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:g(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),M={platform:x(s),target:x(c),device:m(`Human-readable device name.`),id:m(`Stable device id.`),kind:x(y)},N=[`platform`,`target`,`device`,`id`,`kind`],Te=w({success:g(),exitCode:b(),stdout:m(),stderr:m(),error:h(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function P(e){return e.oneOf?{...e,oneOf:e.oneOf.map(P)}:{...e,properties:{...e.properties??{},settle:we}}}function Ee(e){let t={...e};for(let e of Object.keys(t))f(e)&&(t[e]=P(t[e]));return t}const F=O({properties:{evidence:j,button:x([`secondary`,`middle`]),count:b(`Number of press/click repetitions.`),intervalMs:b(`Delay between repeated press/click actions.`),holdMs:b(`Hold duration for each action.`),jitterPx:b(`Randomization radius in pixels.`),doubleTap:g(`Whether the command requested a double-tap action.`)}}),I={text:m(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:j},De=w({resourceId:C(`Android resource id of the exact field that changed.`),className:C(`Android class name of the exact field that changed.`),packageName:C(`Android package name that owns the exact field.`),rect:w({x:b(),y:b(),width:b(),height:b()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),Oe=Ee({press:F,click:F,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...O({properties:I,required:[`text`]}),not:w({},[`verification`])},O({properties:{...I,verification:S(`unconfirmed`),requested:m(`Literal text requested by the fill command.`),before:C(`Raw target text captured before the fill.`),after:C(`Raw target text captured after the fill.`),target:De},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:S(`longpress`)}}),hover:O({properties:{gesture:S(`hover`)}}),find:w({ref:m(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:g(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:m(`Text value returned by find get_text.`),node:h(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:h(`One listed match with its snapshot ref and node.`)},locator:m(`Locator kind used for the find action.`),query:m(`Query argument used for the find action.`),x:b(`Resolved x coordinate for mutating find actions.`),y:b(`Resolved y coordinate for mutating find actions.`),message:m(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:w({...M,booted:{type:`boolean`,const:!0}},[...N,`booted`]),shutdown:w({...M,shutdown:Te},[...N,`shutdown`]),viewport:w({width:b(),height:b(),message:m()},[`width`,`height`,`message`]),back:w({action:S(`back`),mode:x(te),message:m()},[`action`,`mode`,`message`]),home:w({action:S(`home`),message:m()},[`action`,`message`]),orientation:w({action:S(`orientation`),orientation:x(le),message:m(),confirmed:g(),warning:m()},[`action`,`orientation`,`message`]),"app-switcher":w({action:S(`app-switcher`),message:m()},[`action`,`message`]),fold:w({action:S(`fold`),pose:x(ce),hingeAngleDegrees:b(`Hinge angle CoreDevice read back after the pose settled.`),screen:w({display:m(`CoreDevice name of the panel the device now lights.`),widthPt:b(),heightPt:b()},[`display`,`widthPt`,`heightPt`]),message:m()},[`action`,`pose`,`hingeAngleDegrees`,`message`]),"action-button":w({action:S(`action-button`),message:m()},[`action`,`message`]),"tv-remote":w({action:S(`tv-remote`),button:x(ue),durationMs:b(),message:m()},[`action`,`button`,`message`]),wait:w({waitedMs:b(),kind:S(`selector`),text:m(),selector:m(),captures:b(),nodeCount:b(),hint:m(),warning:m()},[`waitedMs`]),scroll:w({direction:x([`up`,`down`,`left`,`right`]),edge:x([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:g(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`)},[`direction`]),prepare:w({action:S(`ios-runner`),platform:x(s),deviceId:m(),deviceName:m(),kind:x(y),durationMs:b(),runner:w({},[]),cache:x([`exact`,`restore-key`,`miss`,`external`]),artifact:x([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:m(),recoveryReason:m(),failureReason:m(),timing:w({totalMs:b(),additiveParts:w({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:w({connectMs:{type:`array`,items:S(`buildMs`)},healthCheckMs:{type:`array`,items:m()}},[`healthCheckMs`]),note:m()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:m()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[w({platform:S(`ios`),bundleId:m(),message:m()},[`platform`,`bundleId`,`message`]),w({platform:S(`android`),package:m(),action:m(),extrasCount:b(),message:m()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":w({event:m(),eventUrl:m(),transport:S(`deep-link`),message:m()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[w({action:S(`read`),text:m()},[`action`,`text`]),w({action:S(`write`),textLength:b(),message:m()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[w({platform:x([`ios`,`macos`]),appName:m(),appBundleId:m(),source:S(`session`),surface:x(ne),device_udid:m(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),w({platform:S(`android`),package:m(),activity:m()},[`platform`,`package`,`activity`])]},keyboard:w({platform:x([`android`,`ios`]),action:x([`status`,`dismiss`,`enter`]),visible:g(),wasVisible:g(),dismissed:g(),attempts:b(),inputType:m(),type:x([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:m(),focusedPackage:m(),focusedResourceId:m(),inputOwner:x([`app`,`ime`,`unknown`]),message:m()},[`platform`,`action`]),doctor:w({status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),kind:x([`auto`,`react-native`,`expo`,`repack`]),platform:m(),target:x(c),targetApp:m(),metro:w({host:m(),port:b()},[`host`,`port`]),checks:{type:`array`,items:w({id:m(),status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),hint:m(),command:m(),evidence:h()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:w({mode:S(`snapshot`),baselineInitialized:g(),summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m()},[`kind`,`text`])},warnings:T},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:w({replayed:b(),healed:b(),session:m(),sessionActive:g(`True iff the session is still active — the script had no terminal close.`),artifactPaths:T,snapshotDiagnostics:h(),message:m()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:w({total:b(),executed:b(),passed:b(),failed:b(),skipped:b(),notRun:b(),durationMs:b(),failures:{type:`array`,items:h()},tests:{type:`array`,items:h()},snapshotDiagnostics:h()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[w({recording:S(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),showTouches:g()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:S(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:D},recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),durationMs:b(),capturedDurationMs:b(),recorder:x(_e,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:x(ge,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:g(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:h()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:S(`started`),outPath:m()},[`trace`,`outPath`]),w({trace:S(`stopped`),outPath:m(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]}}),ke={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:y},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},L={...Oe,...ke},Ae={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:p({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},R=Object.entries(Ae),z=new Set(R.map(([e])=>e)),je=Object.fromEntries(R.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Me(){return Object.fromEntries(R.map(([e,t])=>[e,t.schema]))}function B(e){return n(e)}function V(t){let n=[`Error (${t.code}): ${t.message}`];if(t.cause){let e=t.cause.code?`${t.cause.code} `:``;n.push(`Cause: ${e}${t.cause.message}`)}t.hint&&n.push(`Hint: ${t.hint}`);for(let e of oe(t.details))n.push(`Warning: ${se(e)}`);n.push(...ve(e(t.details))),t.supportedOn&&n.push(`Supported on: ${t.supportedOn}`);let r=pe(t.details);return r&&n.push(r),n.join(`
|
|
2
|
-
`)}function
|
|
1
|
+
import{B as e,D as t,L as n,r,z as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{i as s,t as c}from"./sdk-device.js";import{S as l,c as u,d,p as f,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{C as re,S as p,_ as m,b as ie,g as h,h as g,y as ae}from"./registry.js";import{n as oe}from"./success-text.js";import{t as se}from"./output-common.js";import"./device.js";import{r as ce,t as le}from"./device-rotation.js";import{t as ue}from"./tv-remote.js";import{i as de,n as _,r as fe,t as v}from"./command-metadata.js";import{r as pe}from"./replay-divergence.js";import{n as me,t as he}from"./cli-output.js";import{r as ge,t as _e}from"./recording-stop-observation.js";import{t as ve}from"./fold-runtime.js";import{n as ye}from"./error.js";import{n as be,r as xe,t as Se}from"./cli-config.js";import{n as Ce}from"./result-serialization.js";const y=[`simulator`,`emulator`,`device`];function b(e){return{type:`number`,...e?{description:e}:{}}}function x(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function S(e){return{type:`string`,const:e}}function C(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function w(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const T={type:`array`,items:{type:`string`}},E=w({wallClockMs:b(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:b(`Number of real runner round-trips made while serving the request.`),nodeCount:b(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),D=w({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return w({targetKind:x([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:b(`Resolved interaction x coordinate when available.`),y:b(`Resolved interaction y coordinate when available.`),referenceWidth:b(`Reference frame width for visualizing the interaction point.`),referenceHeight:b(`Reference frame height for visualizing the interaction point.`),ref:m(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:m(`Selector expression when the target was a selector.`),selectorChain:T,refLabel:m(),targetHittable:g(),hint:m(),warning:m(),message:m(),evidence:j,resolution:we,cost:E,maestroNonHittableCoordinateFallbackAllowed:g(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:g(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:S(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=w({diagnosticRef:m(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:m(`UTF-8 truncated to 256 bytes.`),label:m(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),we={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`unique`)},[`source`,`phase`,`kind`]),w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:x([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:k}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`exact`)},[`source`,`phase`,`kind`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`label-fallback`)},[`source`,`phase`,`kind`]),w({source:S(`direct-ios`),kind:S(`not-observed`)},[`source`,`kind`])]},A=w({from:m(`Surface the pre-action baseline described: a host bundle id, or app.`),to:m(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:m(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),j=w({foregroundApp:m(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:b(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:b(`Subset of nodeCount the platform reports as hittable.`),digest:m(`Order-independent digest of the post-action node multiset.`),changedFromBefore:g(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:A},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),Te=w({settled:g(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:A,diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:g(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:g(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),M={platform:x(s),target:x(c),device:m(`Human-readable device name.`),id:m(`Stable device id.`),kind:x(y)},N=[`platform`,`target`,`device`,`id`,`kind`],Ee=w({success:g(),exitCode:b(),stdout:m(),stderr:m(),error:h(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function P(e){return e.oneOf?{...e,oneOf:e.oneOf.map(P)}:{...e,properties:{...e.properties??{},settle:Te}}}function De(e){let t={...e};for(let e of Object.keys(t))f(e)&&(t[e]=P(t[e]));return t}const F=O({properties:{evidence:j,button:x([`secondary`,`middle`]),count:b(`Number of press/click repetitions.`),intervalMs:b(`Delay between repeated press/click actions.`),holdMs:b(`Hold duration for each action.`),jitterPx:b(`Randomization radius in pixels.`),doubleTap:g(`Whether the command requested a double-tap action.`)}}),I={text:m(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:j},Oe=w({resourceId:C(`Android resource id of the exact field that changed.`),className:C(`Android class name of the exact field that changed.`),packageName:C(`Android package name that owns the exact field.`),rect:w({x:b(),y:b(),width:b(),height:b()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),ke=De({press:F,click:F,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...O({properties:I,required:[`text`]}),not:w({},[`verification`])},O({properties:{...I,verification:S(`unconfirmed`),requested:m(`Literal text requested by the fill command.`),before:C(`Raw target text captured before the fill.`),after:C(`Raw target text captured after the fill.`),target:Oe},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:S(`longpress`)}}),hover:O({properties:{gesture:S(`hover`)}}),find:w({ref:m(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:g(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:m(`Text value returned by find get_text.`),node:h(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:h(`One listed match with its snapshot ref and node.`)},locator:m(`Locator kind used for the find action.`),query:m(`Query argument used for the find action.`),x:b(`Resolved x coordinate for mutating find actions.`),y:b(`Resolved y coordinate for mutating find actions.`),message:m(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:w({...M,booted:{type:`boolean`,const:!0}},[...N,`booted`]),shutdown:w({...M,shutdown:Ee},[...N,`shutdown`]),viewport:w({width:b(),height:b(),message:m()},[`width`,`height`,`message`]),back:w({action:S(`back`),mode:x(te),message:m()},[`action`,`mode`,`message`]),home:w({action:S(`home`),message:m()},[`action`,`message`]),orientation:w({action:S(`orientation`),orientation:x(le),message:m(),confirmed:g(),warning:m()},[`action`,`orientation`,`message`]),"app-switcher":w({action:S(`app-switcher`),message:m()},[`action`,`message`]),fold:w({action:S(`fold`),pose:x(ce),hingeAngleDegrees:b(`Hinge angle CoreDevice read back after the pose settled.`),screen:w({display:m(`CoreDevice name of the panel the device now lights.`),coordinateSpace:S(ve),widthPt:b(`Panel width in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`),heightPt:b(`Panel height in native panel points (pixels divided by point scale), NOT snapshot coordinates; take a fresh snapshot to place a tap.`)},[`display`,`coordinateSpace`,`widthPt`,`heightPt`]),message:m()},[`action`,`pose`,`hingeAngleDegrees`,`message`]),"action-button":w({action:S(`action-button`),message:m()},[`action`,`message`]),"tv-remote":w({action:S(`tv-remote`),button:x(ue),durationMs:b(),message:m()},[`action`,`button`,`message`]),wait:w({waitedMs:b(),kind:S(`selector`),text:m(),selector:m(),captures:b(),nodeCount:b(),hint:m(),warning:m()},[`waitedMs`]),scroll:w({direction:x([`up`,`down`,`left`,`right`]),edge:x([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:g(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`)},[`direction`]),prepare:w({action:S(`ios-runner`),platform:x(s),deviceId:m(),deviceName:m(),kind:x(y),durationMs:b(),runner:w({},[]),cache:x([`exact`,`restore-key`,`miss`,`external`]),artifact:x([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:m(),recoveryReason:m(),failureReason:m(),timing:w({totalMs:b(),additiveParts:w({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:w({connectMs:{type:`array`,items:S(`buildMs`)},healthCheckMs:{type:`array`,items:m()}},[`healthCheckMs`]),note:m()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:m()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[w({platform:S(`ios`),bundleId:m(),message:m()},[`platform`,`bundleId`,`message`]),w({platform:S(`android`),package:m(),action:m(),extrasCount:b(),message:m()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":w({event:m(),eventUrl:m(),transport:S(`deep-link`),message:m()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[w({action:S(`read`),text:m()},[`action`,`text`]),w({action:S(`write`),textLength:b(),message:m()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[w({platform:x([`ios`,`macos`]),appName:m(),appBundleId:m(),source:S(`session`),surface:x(ne),device_udid:m(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),w({platform:S(`android`),package:m(),activity:m()},[`platform`,`package`,`activity`])]},keyboard:w({platform:x([`android`,`ios`]),action:x([`status`,`dismiss`,`enter`]),visible:g(),wasVisible:g(),dismissed:g(),attempts:b(),inputType:m(),type:x([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:m(),focusedPackage:m(),focusedResourceId:m(),inputOwner:x([`app`,`ime`,`unknown`]),message:m()},[`platform`,`action`]),doctor:w({status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),kind:x([`auto`,`react-native`,`expo`,`repack`]),platform:m(),target:x(c),targetApp:m(),metro:w({host:m(),port:b()},[`host`,`port`]),checks:{type:`array`,items:w({id:m(),status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),hint:m(),command:m(),evidence:h()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:w({mode:S(`snapshot`),baselineInitialized:g(),summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m()},[`kind`,`text`])},warnings:T},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:w({replayed:b(),healed:b(),session:m(),sessionActive:g(`True iff the session is still active — the script had no terminal close.`),artifactPaths:T,snapshotDiagnostics:h(),message:m()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:w({total:b(),executed:b(),passed:b(),failed:b(),skipped:b(),notRun:b(),durationMs:b(),failures:{type:`array`,items:h()},tests:{type:`array`,items:h()},snapshotDiagnostics:h()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[w({recording:S(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),showTouches:g()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:S(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:D},recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),durationMs:b(),capturedDurationMs:b(),recorder:x(_e,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:x(ge,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:g(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:h()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:S(`started`),outPath:m()},[`trace`,`outPath`]),w({trace:S(`stopped`),outPath:m(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]}}),Ae={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:y},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},L={...ke,...Ae},je={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:p({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},R=Object.entries(je),z=new Set(R.map(([e])=>e)),Me=Object.fromEntries(R.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Ne(){return Object.fromEntries(R.map(([e,t])=>[e,t.schema]))}function B(e){return n(e)}function V(t){let n=[`Error (${t.code}): ${t.message}`];if(t.cause){let e=t.cause.code?`${t.cause.code} `:``;n.push(`Cause: ${e}${t.cause.message}`)}t.hint&&n.push(`Hint: ${t.hint}`);for(let e of oe(t.details))n.push(`Warning: ${se(e)}`);n.push(...ye(e(t.details))),t.supportedOn&&n.push(`Supported on: ${t.supportedOn}`);let r=pe(t.details);return r&&n.push(r),n.join(`
|
|
2
|
+
`)}function Pe(e,t,n){let r=Se({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&xe(t,e)&&(i[t]=a);return be(i,t)}const Fe={devices:async e=>({devices:e.map(Ce)}),apps:async e=>({apps:e})};async function Ie(e,t){let n=Fe[e];return n?await n(t):t}function Le(){let e=new Map;return{pinInput:(t,n,r)=>Ze(t,n,He(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>Ue(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);Re(e,i,t),Ye(e,i,t)}}}function Re(e,t,n){let r=n?.refsGeneration;typeof r==`number`&&U(e,t,i(n),r)}const ze=new Set([`snapshot`,`find`]),Be=new Set(d.map(e=>e.name).filter(_).filter(e=>f(e))),Ve=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function He(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function Ue(e,t,n,r,i){let a=H(r,i);if(Be.has(t)){Ke(e,a,qe(n));return}ze.has(t)&&(t===`find`?Ge(e,a,n):We(e,a,n))}function We(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);U(e,t,i,r)}function Ge(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);U(e,t,i,r)}function Ke(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function qe(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),Je(i,n,r)}function Je(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Ye(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];Xe(i.refs,s),U(e,t,s,a)}function Xe(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Ze(e,t,n){return n===void 0||n.size===0?t:e===`wait`?Qe(t,n)??t:Ve.has(e)?$e(t,n)??t:t}function Qe(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function $e(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const et={config:p({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:p({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},tt=Object.fromEntries(fe().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...ie,...Me,...et,...tt}}function nt(){return de().map(e=>{let t=e.name in L?L[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:ft(e.name,ae(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(e={}){let n=Le();return{execute:async(r,i)=>{if(!_(r))throw new t(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=v(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new t(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=Pe(r,i,s),l=ot(c),u=ut(c),d=n.pinInput(r,u,l.client.stateDir),f=await it(e,l.client);try{let t=await(e.runCommand??at)(f,r,d);return n.mergeCommandResult(r,t,l.client.stateDir,u.session),{isError:!1,structuredContent:await Ie(r,t),content:[{type:`text`,text:await pt({name:r,input:u,result:t,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=B(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:V(i)}]}}const rt=K();async function it(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function at(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function ot(e){return{client:st(e),outputFormat:lt(e.mcpOutputFormat)}}function st(e){let n=e.stateDir,r=e.includeCost,i=e.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new t(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new t(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=ct(i);return o!==void 0&&(a.responseLevel=o),a}function ct(e){if(e===void 0)return;let n=r.find(t=>t===e);if(n===void 0)throw new t(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function lt(e){if(e===void 0)return`optimized`;if(e!==`optimized`&&e!==`json`)throw new t(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return e}function ut(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!z.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?re(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(a(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?dt(r,t,e,`${n}.${e}`):void 0)}}function dt(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let o=t[n],s=u(t[i]);if(s===void 0||!a(o))return;let c=Y(s,v(s),o);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function ft(e,t){let n=ee(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function Q(e,t){let n=l(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Ne()}}}async function pt(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await he({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?mt(e.name,t):$(t?.data??e.result)}function mt(e,t){let n=t.text??``;if(!me(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
|
|
3
3
|
`)?``:`
|
|
4
|
-
`}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{B as a,V as i,K as n,z as o,
|
|
4
|
+
`}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{B as a,V as i,K as n,z as o,nt as r,rt as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{D as e,c as t}from"./sdk-contracts.js";import{S as n,a as r,u as i,y as a}from"./sdk-device.js";import{c as o,i as s,s as c}from"./lease-scope.js";import{n as l,t as u}from"./catalog.js";import{t as d}from"./sdk-remote-config.js";import{t as f}from"./prepare-kind.js";import{r as p}from"./diagnostics.js";import{D as m}from"./owner-identity.js";import{f as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as g}from"./base-url.js";import{i as _,r as v}from"./client-metro-companion.js";import{n as y}from"./metro2.js";import{n as te,r as b,t as ne}from"./remote-config2.js";import{n as x,t as S}from"./providers.js";import C from"node:path";import w from"node:fs";import T from"node:crypto";const E={slug:`react-devtools-companion`,runArg:g,displayName:`React DevTools companion`};async function re(e){return await v({...e,definition:E,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function D(e){return await _({...e,definition:E})}function O(e){return e===`android-instance`||e===`ios-instance`}function ie(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ae(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ae(e)}function oe(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function se(e){let t=e?.metroPublicBaseUrl?.trim();return t?oe(t):null}function ce(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=se(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function le(e,t={}){let n=ce(e,t);return(await h(`npm`,ie(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function A(e){let t=L(e);if(!w.existsSync(t))return null;let n;try{n=JSON.parse(w.readFileSync(t,`utf8`))}catch(t){return H(e,t),null}return ge(n)?n:(H(e),null)}function j(e){let t=L({stateDir:e.stateDir,session:e.state.session});w.mkdirSync(C.dirname(t),{recursive:!0}),V(t,e.state),V(R(e.stateDir),{session:e.state.session})}function M(e){return{baseUrl:me(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function N(e){w.rmSync(L(e),{force:!0});let t=R(e.stateDir);B(e.stateDir)===e.session&&w.rmSync(t,{force:!0})}function ue(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=A(t)??(t.allowActiveFallback?z({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,t),l=s(i);return{runtime:i.runtime,connection:o(l),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...c(l),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function P(e){return o(s(e))}function F(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function de(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function I(t){try{return T.createHash(`sha256`).update(w.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function L(e){return C.join(e.stateDir,`remote-connections`,`${he(e.session)}.json`)}function R(e){return C.join(e,`remote-connections`,`.active-session.json`)}function z(e){let t=B(e.stateDir);return t?A({stateDir:e.stateDir,session:t}):null}function B(e){let t=R(e);if(w.existsSync(t))try{let e=JSON.parse(w.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function fe(e){if(e)return T.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function pe(e,t){try{return b({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function V(e,t){m({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function me(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function H(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),N(e)}function he(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${T.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function ge(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&_e(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ve(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ye(t.daemon)}function _e(e,t){return t.every(t=>typeof e[t]==`string`)}function ve(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ye(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:be(e)}function be(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const xe=d.map(e=>e.key);function U(e){let t={};for(let n of xe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Se(e){return e.remoteConfig?{...U(b({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ce(e){return e===`cloud`||e===`proxy`||W(e)}function W(e){return e===`limrun`||x(e)}function we(){return[`cloud`,`proxy`,S.browserStack,S.awsDeviceFarm,`limrun`].join(`, `)}function G(e){let t=W(e),n=x(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===S.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function K(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Te(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const q=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),J=new Set([`open`]),Ee=new Set([l.open,l.install,l.reinstall,u.installSource]);async function De(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=b({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...U(o.profile),...r,remoteConfig:o.resolvedPath},c=A({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?t.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??t.runtime,h=u,g=!c,_,v=Fe(h);if(v.shouldAllocate(n)){let e=await Me({command:n,client:i,state:u,nextState:h,nextFlags:d,initialApp:p,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=await Oe({command:n,flags:d,client:i,state:u,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=y.state,m=y.runtime,g||=y.changed,await je({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:y.preparedMetroCleanupOnFailure,metroCleanupToStop:y.metroCleanupToStop}),{flags:{...d,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??d.platform,target:h.target??d.target},runtime:m,connection:P(h)}}async function Oe(t){let{command:n,flags:r,state:i,client:a}=t,o=ke(t.nextState,r),s=t.runtime;if(!Je(n,r,t.batchSteps,t.positionals)||!$(r)||!Ae(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Be(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Xe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function ke(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ae(e,t,n){return e===!0||!t||!Ye(t,n)}async function je(e){if(e.changed)try{j({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await Ke(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Me(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&tt(i,c.device);let l=s.leaseBackend??o??qe(i,t);at(r,i,l);let u=await $e(n,s,l,a,i,e.initialApp),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Ne(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Pe(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Ne(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Pe(e,t,n,r){let i=F(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Fe(e){let t=G(e.leaseProvider);return t.leaseKind===`proxy`?Re:t.supportsDeferredAppSelection?Ie:t.usesCloudWebDriverLease?ze:Le}const Ie={shouldAllocate:e=>e!==l.apps&&!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Le={shouldAllocate:e=>!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Re={shouldAllocate:e=>e!==`devices`&&!q.has(e),ttlMs:()=>3e5,resolveLeaseState:et},ze={shouldAllocate:e=>!q.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Be(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:f(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await y(e)}catch{}}async function Ve(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function X(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...P(t)}):{released:!1}}function He(e){let t=Ue(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ue(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&We(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function We(e,t){let n=M({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ge(e,t,n){if(!t.leaseId)return;let r=He({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Z(t,`no credential known to belong to that endpoint was available`);try{await X(e,t,r.daemonAuthToken);return}catch{return Z(t,`the release request failed`)}}function Z(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Ke(e,t,n){if(n)try{let r=F(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function qe(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function Je(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:J.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return J.has(t)&&e.runtime===void 0})}function $(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Ye(e,n){return!e.platform||!n||!t(n)||e.platform===n}function Xe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ze(e,t){if(e)return Ye(e,t)?e:void 0}function Qe(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function $e(e,t,n,r,i,a){let o=P(t);if(t.leaseId&&t.leaseBackend===n){let i=await ot(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...K(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function et(t){if(!Ee.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(t.client,t.flags),r=rt(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??it(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function tt(e,t){if(e.platform=t.platform,e.target=t.target??e.target,i(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(e,t){let i=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await n(i.map(e=>({...r(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function rt(e){return`${a(e)}:${e.target??`mobile`}:${e.id}`}function it(e){if(i(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{N as C,O as D,le as E,re as O,de as S,j as T,fe as _,Q as a,z as b,K as c,G as d,Ce as f,P as g,M as h,X as i,D as k,Te as l,Se as m,De as n,Y as o,U as p,Ge as r,Ve as s,$ as t,we as u,I as v,ue as w,A as x,F as y};
|
|
1
|
+
import{D as e,c as t}from"./sdk-contracts.js";import{C as n,a as r,b as i,d as a}from"./sdk-device.js";import{c as o,i as s,s as c}from"./lease-scope.js";import{n as l,t as u}from"./catalog.js";import{t as d}from"./sdk-remote-config.js";import{t as f}from"./prepare-kind.js";import{r as p}from"./diagnostics.js";import{D as m}from"./owner-identity.js";import{f as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as g}from"./base-url.js";import{i as _,r as v}from"./client-metro-companion.js";import{n as y}from"./metro2.js";import{n as te,r as b,t as ne}from"./remote-config2.js";import{n as x,t as S}from"./providers.js";import C from"node:path";import w from"node:fs";import T from"node:crypto";const E={slug:`react-devtools-companion`,runArg:g,displayName:`React DevTools companion`};async function re(e){return await v({...e,definition:E,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function D(e){return await _({...e,definition:E})}function O(e){return e===`android-instance`||e===`ios-instance`}function ie(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ae(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ae(e)}function oe(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function se(e){let t=e?.metroPublicBaseUrl?.trim();return t?oe(t):null}function ce(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=se(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function le(e,t={}){let n=ce(e,t);return(await h(`npm`,ie(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function A(e){let t=L(e);if(!w.existsSync(t))return null;let n;try{n=JSON.parse(w.readFileSync(t,`utf8`))}catch(t){return H(e,t),null}return ge(n)?n:(H(e),null)}function j(e){let t=L({stateDir:e.stateDir,session:e.state.session});w.mkdirSync(C.dirname(t),{recursive:!0}),V(t,e.state),V(R(e.stateDir),{session:e.state.session})}function M(e){return{baseUrl:me(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function N(e){w.rmSync(L(e),{force:!0});let t=R(e.stateDir);B(e.stateDir)===e.session&&w.rmSync(t,{force:!0})}function ue(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=A(t)??(t.allowActiveFallback?z({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,t),l=s(i);return{runtime:i.runtime,connection:o(l),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...c(l),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function P(e){return o(s(e))}function F(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function de(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function I(t){try{return T.createHash(`sha256`).update(w.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function L(e){return C.join(e.stateDir,`remote-connections`,`${he(e.session)}.json`)}function R(e){return C.join(e,`remote-connections`,`.active-session.json`)}function z(e){let t=B(e.stateDir);return t?A({stateDir:e.stateDir,session:t}):null}function B(e){let t=R(e);if(w.existsSync(t))try{let e=JSON.parse(w.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function fe(e){if(e)return T.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function pe(e,t){try{return b({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function V(e,t){m({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function me(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function H(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),N(e)}function he(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${T.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function ge(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&_e(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ve(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ye(t.daemon)}function _e(e,t){return t.every(t=>typeof e[t]==`string`)}function ve(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ye(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:be(e)}function be(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const xe=d.map(e=>e.key);function U(e){let t={};for(let n of xe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Se(e){return e.remoteConfig?{...U(b({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ce(e){return e===`cloud`||e===`proxy`||W(e)}function W(e){return e===`limrun`||x(e)}function we(){return[`cloud`,`proxy`,S.browserStack,S.awsDeviceFarm,`limrun`].join(`, `)}function G(e){let t=W(e),n=x(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===S.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function K(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Te(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const q=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),J=new Set([`open`]),Ee=new Set([l.open,l.install,l.reinstall,u.installSource]);async function De(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=b({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...U(o.profile),...r,remoteConfig:o.resolvedPath},c=A({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?t.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??t.runtime,h=u,g=!c,_,v=Fe(h);if(v.shouldAllocate(n)){let e=await Me({command:n,client:i,state:u,nextState:h,nextFlags:d,initialApp:p,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=await Oe({command:n,flags:d,client:i,state:u,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=y.state,m=y.runtime,g||=y.changed,await je({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:y.preparedMetroCleanupOnFailure,metroCleanupToStop:y.metroCleanupToStop}),{flags:{...d,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??d.platform,target:h.target??d.target},runtime:m,connection:P(h)}}async function Oe(t){let{command:n,flags:r,state:i,client:a}=t,o=ke(t.nextState,r),s=t.runtime;if(!Je(n,r,t.batchSteps,t.positionals)||!$(r)||!Ae(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Be(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Xe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function ke(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ae(e,t,n){return e===!0||!t||!Ye(t,n)}async function je(e){if(e.changed)try{j({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await Ke(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Me(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&tt(i,c.device);let l=s.leaseBackend??o??qe(i,t);at(r,i,l);let u=await $e(n,s,l,a,i,e.initialApp),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Ne(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Pe(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Ne(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Pe(e,t,n,r){let i=F(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Fe(e){let t=G(e.leaseProvider);return t.leaseKind===`proxy`?Re:t.supportsDeferredAppSelection?Ie:t.usesCloudWebDriverLease?ze:Le}const Ie={shouldAllocate:e=>e!==l.apps&&!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Le={shouldAllocate:e=>!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Re={shouldAllocate:e=>e!==`devices`&&!q.has(e),ttlMs:()=>3e5,resolveLeaseState:et},ze={shouldAllocate:e=>!q.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Be(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:f(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await y(e)}catch{}}async function Ve(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function X(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...P(t)}):{released:!1}}function He(e){let t=Ue(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ue(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&We(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function We(e,t){let n=M({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ge(e,t,n){if(!t.leaseId)return;let r=He({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Z(t,`no credential known to belong to that endpoint was available`);try{await X(e,t,r.daemonAuthToken);return}catch{return Z(t,`the release request failed`)}}function Z(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Ke(e,t,n){if(n)try{let r=F(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function qe(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function Je(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:J.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return J.has(t)&&e.runtime===void 0})}function $(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Ye(e,n){return!e.platform||!n||!t(n)||e.platform===n}function Xe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ze(e,t){if(e)return Ye(e,t)?e:void 0}function Qe(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function $e(e,t,n,r,i,a){let o=P(t);if(t.leaseId&&t.leaseBackend===n){let i=await ot(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...K(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function et(t){if(!Ee.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(t.client,t.flags),r=rt(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??it(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function tt(e,t){if(e.platform=t.platform,e.target=t.target??e.target,a(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(e,t){let i=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await n(i.map(e=>({...r(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function rt(e){return`${i(e)}:${e.target??`mobile`}:${e.id}`}function it(e){if(a(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{N as C,O as D,le as E,re as O,de as S,j as T,fe as _,Q as a,z as b,K as c,G as d,Ce as f,P as g,M as h,X as i,D as k,Te as l,Se as m,De as n,Y as o,U as p,Ge as r,Ve as s,$ as t,we as u,I as v,ue as w,A as x,F as y};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,
|
|
1
|
+
import{a as e,h as t,y as n}from"./sdk-device.js";import{Xt as r}from"./sdk-batch.js";import{n as i,v as a}from"./owner-identity.js";import"./process.js";import{t as o}from"./daemon-registration.js";import{r as s}from"./durable-resource.js";import"./src7.js";import c from"node:path";import l from"node:fs";import u from"node:crypto";import d from"node:os";function f(e){return p(`family`in e?e.family:e.platform,e.appleOs,e.id)}function p(e,t,n){return`local:${e}:${t??`none`}:${n}`}function m(){let e=process.env.AGENT_DEVICE_CLAIMS_DIR?.trim();return e?c.resolve(e):c.join(d.homedir(),`.agent-device`,`device-claims`)}function h(e){let t=u.createHash(`sha256`).update(e).digest(`hex`);return c.join(m(),`${t}.json`)}function g(e){return{deviceKey:e.deviceKey,ownerToken:e.ownerToken,ownerPid:e.ownerPid,ownerStartTime:e.ownerStartTime}}function _(e){return e.schemaVersion===3}function v(e){return r(e.allocator.instanceId)}function y(e){return D(e)?e.schemaVersion===3?S(e):e.schemaVersion===2?O(e):e.schemaVersion===1?k(e):null:null}function b(e){return D(e)&&e.schemaVersion===3}const x=[`ownerPid`,`ownerStartTime`,`ownerToken`,`session`,`workspace`,`abandonedAtMs`];function S(e){if(e.kind!==`allocator`||C(e))return null;let t=w(e);return t&&{schemaVersion:3,kind:`allocator`,...t}}function C(e){return x.some(t=>e[t]!==void 0)}function w(e){if(!D(e.device)||!P(e.device.name))return null;let t=e.device.name,n=s(e.device),r=F(e.deviceKey),i=F(e.stateDir),a=T(e.allocator),o=N(e);return!n||!r||!i||!a||!o||r!==f(n)?null:{deviceKey:r,device:{...n,name:t},stateDir:i,allocator:a,createdAtMs:o.createdAtMs,updatedAtMs:o.updatedAtMs}}function T(e){if(!D(e))return null;let t=E(e.instanceId),n=E(e.identityIncarnationId);return t&&n?{instanceId:t,identityIncarnationId:n}:null}function E(e){return P(e)&&e===e.trim()?e:null}function D(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function O(e){if(!D(e.device)||!P(e.device.name))return null;let t=s(e.device);return t?A(e,t,e.device.name):null}function k(n){if(!D(n.device))return null;let r=n.device,i=r.name;if(!P(i)||!t(r.platform))return null;let a=e(r.platform),o=s({id:r.id,family:a.platform,kind:r.kind,target:r.target,...r.appleOs===void 0?a.platform===`apple`?{appleOs:r.platform===`macos`?`macos`:`ios`}:{}:{appleOs:r.appleOs},...r.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:r.iosPhysicalDeviceBackend}});return o?A(n,o,i):null}function A(e,t,n){let r=j(e),i=M(e),a=N(e);return!r||!i||!a||r.deviceKey!==f(t)?null:{schemaVersion:2,...r,device:{...t,name:n},...i,...a}}function j(e){let t=F(e.deviceKey),n=F(e.session),r=F(e.workspace),i=F(e.stateDir);return!t||!n||!r||!i?null:{deviceKey:t,session:n,workspace:r,stateDir:i}}function M(e){let{ownerPid:t,ownerStartTime:n}=e,r=F(e.ownerToken);return!I(t)||!r||n!==null&&!P(n)?null:{ownerPid:t,ownerStartTime:n,ownerToken:r}}function N(e){let{createdAtMs:t,updatedAtMs:n,abandonedAtMs:r}=e;return!L(t)||!L(n)||r!==void 0&&!L(r)?null:{createdAtMs:t,updatedAtMs:n,...L(r)?{abandonedAtMs:r}:{}}}function P(e){return typeof e==`string`&&e.length>0}function F(e){return P(e)?e:null}function I(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function L(e){return typeof e==`number`&&Number.isFinite(e)}function R(e){let t=m(),n=z(t);if(`claims`in n)return n.claims;let r=n.entries.filter(e=>e.isFile()&&e.name.endsWith(`.json`)).map(e=>K(c.join(t,e.name))).filter(e=>e!==null).filter(t=>B(t.claim??t.allocatorClaim,e)),i=a(r.flatMap(e=>e.claim?[e.claim.ownerPid]:[]));return r.map(e=>e.claim?J(e,i.get(e.claim.ownerPid)??null):e)}function z(e){try{return{entries:l.readdirSync(e,{withFileTypes:!0})}}catch(t){let n=t.code;return n===`ENOENT`||n===`ENOTDIR`?{claims:[]}:{claims:[{fileName:c.basename(e),classification:`unknown`,error:String(t)}]}}}function B(e,t){return!e||[V(e,t.udid??t.serial),H(e,t.device),U(e,t.platform)].every(Boolean)}function V(e,t){return!t||e.device.id===t}function H(e,t){return!t||e.device.name===t||e.device.id===t}function U(e,t){return n({platform:e.device.family,appleOs:e.device.appleOs},t)}function W(e){let t=K(e);return t?.claim?J(t,a([t.claim.ownerPid]).get(t.claim.ownerPid)??null):t}function G(e){let t=K(e);return t?.allocatorClaim||t?.classification===`allocator-inconsistent`?t:null}function K(e){let t=c.basename(e);try{return q(t,l.readFileSync(e,`utf8`))}catch(e){let n=e.code;return n===`ENOENT`||n===`ENOTDIR`?null:{fileName:t,classification:`unknown`,error:String(e)}}}function q(e,t){try{let n=JSON.parse(t),r=y(n);return r?_(r)?{fileName:e,deviceKey:r.deviceKey,allocatorClaim:r,classification:`allocator-held`}:{fileName:e,deviceKey:r.deviceKey,claim:r,classification:`unknown`}:{fileName:e,classification:b(n)?`allocator-inconsistent`:`inconsistent`}}catch(t){return{fileName:e,classification:`inconsistent`,error:String(t)}}}function J(e,t){let n=e.claim;if(!n)return e;let r={pid:n.ownerPid,startTime:n.ownerStartTime},a=i({owner:r,stateDir:n.stateDir},t),s=a===`live`&&o({...r,stateDir:n.stateDir});return{...e,classification:s?`owner-daemon-superseded`:a}}function Y(e){switch(e){case`owner-process-dead`:case`owner-process-reused`:case`owner-state-dir-gone`:case`owner-daemon-superseded`:return!0;case`live`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}function X(e){switch(e){case`owner-process-dead`:case`owner-daemon-superseded`:return!0;case`live`:case`owner-process-reused`:case`owner-state-dir-gone`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}export{G as a,f as c,R as i,h as l,Y as n,v as o,W as r,g as s,X as t,m as u};
|