agent-device 0.19.0 → 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.2.apk +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.2.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.19.0.manifest.json → agent-device-android-multitouch-helper-0.19.2.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.19.0.apk → agent-device-android-snapshot-helper-0.19.2.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.2.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.19.0.manifest.json → agent-device-android-snapshot-helper-0.19.2.manifest.json} +6 -6
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +24 -7
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +506 -119
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +153 -48
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +172 -0
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +76 -5
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +60 -52
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +159 -56
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +142 -0
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -14
- package/dist/src/android-adb.d.ts +1 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +6 -0
- package/dist/src/android.js +1 -1
- package/dist/src/app-lifecycle.js +3 -3
- package/dist/src/apple-runner-options.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/cli-help.js +149 -37
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +11 -11
- package/dist/src/client.js +2 -2
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/device-input-state.js +2 -2
- package/dist/src/devices2.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/index.d.ts +224 -20
- package/dist/src/input-actions.js +3 -3
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +17 -15
- package/dist/src/lease.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/metro.d.ts +0 -1
- package/dist/src/notifications.js +1 -1
- package/dist/src/points.js +1 -1
- package/dist/src/project-runtime.js +1 -1
- package/dist/src/providers.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace-recording.js +2 -2
- package/dist/src/record-trace.js +1 -1
- package/dist/src/registry.js +24 -23
- package/dist/src/reporting.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/sdk-android-adb.d.ts +2 -2
- package/dist/src/sdk-batch-runner.d.ts +0 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-finders.d.ts +1 -2
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.d.ts +0 -1
- package/dist/src/sdk-remote-config.d.ts +1 -2
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +0 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/selectors2.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session.js +10 -10
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-diagnostics.js +2 -2
- package/dist/src/snapshot-helper.js +4 -4
- package/dist/src/snapshot-quality.js +1 -1
- package/dist/src/snapshot2.js +2 -2
- package/dist/src/tv-remote.js +14 -0
- package/dist/src/version.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +5 -4
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +8 -7
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.0.apk +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.0.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.0.apk.sha256 +0 -1
- package/dist/src/device-rotation.js +0 -14
- package/dist/src/logcat.js +0 -6
package/dist/src/cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{B as e,C as t,F as n,I as r,a as i,b as a,p as o,u as s}from"./sdk-contracts.js";import{A as c,E as l,I as u,M as d,N as f,O as p,S as m,j as h,v as g}from"./sdk-android-adb.js";import{C as _,D as v,E as y,T as b,_ as x,w as S}from"./sdk-batch.js";import{a as C,c as w,i as T,l as ee,n as te,o as ne,r as re,s as ie}from"./client.js";import{E as ae,S as E,s as oe}from"./snapshot-diagnostics.js";import{n as se}from"./version.js";import{n as D,t as ce}from"./path-resolution.js";import{Fn as le,Ln as O,Nn as ue,Pn as de,Rn as k,Tn as fe,wn as pe,xn as me,zn as he}from"./device-rotation.js";import{c as ge,g as _e,h as A,p as ve}from"./registry.js";import{a as ye,l as j}from"./sdk-batch-runner.js";import{v as be}from"./url.js";import{i as xe,r as Se}from"./client-metro-companion.js";import"./selectors2.js";import{n as Ce}from"./command-metadata.js";import{n as we}from"./metro2.js";import{n as M,r as Te,t as N}from"./providers.js";import{n as Ee,r as De,t as Oe}from"./command-schema.js";import{t as ke}from"./update-check.js";import{i as Ae,n as je,r as Me,t as Ne}from"./sdk-remote-config.js";import{i as P,r as Pe,t as Fe}from"./cli-runner.js";import{_ as Ie,t as Le,v as Re,y as ze}from"./points.js";import F,{randomBytes as Be,randomUUID as Ve}from"node:crypto";import I from"node:fs";import L from"node:path";import He from"node:http";import{pipeline as Ue}from"node:stream/promises";import{Readable as We}from"node:stream";import{pathToFileURL as Ge}from"node:url";function R(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const Ke=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),qe=new Set([`appsFilter`,`iosSimulatorDeviceSet`,`sessionLocked`,`sessionLockConflicts`]),Je=$e(),Ye=new Map(Je.map(e=>[e.key,e]));function Xe(e){return Ye.get(e)}function Ze(e){return Je.filter(t=>t.config.enabled&&t.supportsCommand(e))}function z(e,t){return Xe(e)?.supportsCommand(t)??!1}function Qe(e,t,n,r){return p(tt(e),t,n,r)}function $e(){let e=new Map;for(let t of _e()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ve)t.set(e,new Set([`*`]));for(let e of v()){let n=Ee(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,config:{enabled:!Ke.has(e),key:e},env:{names:qe.has(e)?[]:[l(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>e.key.localeCompare(t.key))}function et(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function tt(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=et(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 nt(e){let t={json:!1,help:!1,version:!1},r=null,i=[],a=[],o=[],s=!0;for(let a=0;a<e.length;a+=1){let c=e[a];if(s&&c===`--`){s=!1;continue}if(!s){r?i.push(c):r=V(c);continue}if(at(r)){i.push(c);continue}let l=c.startsWith(`--`),u=c.startsWith(`-`)&&c.length>1;if(!l&&!u){r?i.push(c):r=V(c);continue}let[d,f]=l?lt(c):[c,void 0];if(rt(r,d))continue;let p=ot(d,r);if(it(r,p)){i.push(c);continue}if(!p){if(mt(r,i,c)){r?i.push(c):r=c;continue}throw new n(`INVALID_ARGS`,`Unknown flag: ${d}`)}let m=ut(p,d,f,e[a+1]);m.consumeNext&&(a+=1);let h=t[p.key];if(p.multiple){let e=Array.isArray(h)?[...h,m.value]:h===void 0?[m.value]:[h,m.value];t[p.key]=e}else t[p.key]=m.value;o.push({key:p.key,token:d})}return{command:r,positionals:i,flags:t,warnings:a,providedFlags:o}}function rt(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function it(e,t){return e===`react-devtools`?t?!z(t.key,e):!0:!1}function at(e){return e===`cdp`}function ot(e,t){let n=_e().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??A(e);if(t){let e=n.find(e=>z(e.key,t));if(e)return e}return A(e)}function st(e,t){let r=t?.strictFlags??!0,i=[...e.warnings],a=R({json:!1,help:!1,version:!1},t?.defaultFlags??{});if(R(a,e.flags),e.command&&!y(e.command)&&!a.help){let t=vt(e.command);throw new n(`INVALID_ARGS`,t?`Unknown command: ${e.command}. Did you mean ${t}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!z(t.key,e.command));if(o.length>0){let t=o.map(e=>e.token),s=yt(e.command,t);if(r)throw new n(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(z(t,e.command)||delete a[t]);if(ct(e),Oe(e.command,a),e.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new n(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return gt({command:e.command,positionals:e.positionals,flags:a,warnings:i})}function ct(e){if(e.command!==`back`)return;let t=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(t.map(e=>e.token)).size<=1))throw new n(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function lt(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function ut(e,t,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new n(`INVALID_ARGS`,`Flag ${t} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||ft(i)?{value:!0,consumeNext:!1}:pt(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&ft(a))throw new n(`INVALID_ARGS`,`Flag ${t} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new n(`INVALID_ARGS`,`Invalid ${dt(t)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new n(`INVALID_ARGS`,`Invalid ${dt(t)}: ${a}`);return{value:Math.floor(o),consumeNext:r===void 0}}function dt(e){return e.replace(/^-+/,``)}function ft(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?lt(e):[e,void 0];return A(t)!==void 0}function pt(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 mt(e,t,n){if(!ht(n)||!e)return!1;let r=De(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function ht(e){return/^-\d+(\.\d+)?$/.test(e)}function gt(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}const _t={tap:`press or click`};function vt(e){return _t[e]}function yt(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 B(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function bt(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(V(e))}function V(e){return e===`long-press`?`longpress`:e===`metrics`?`perf`:e===`tap`?`press`:e}const xt={slug:`react-devtools-companion`,runArg:be,displayName:`React DevTools companion`};async function St(e){return await Se({...e,definition:xt,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 Ct(e){return await xe({...e,definition:xt})}function wt(e){let t=e.env??process.env,r=Dt(e);if(!I.existsSync(r))throw new n(`INVALID_ARGS`,`Remote config file not found: ${r}`);let i;try{i=I.readFileSync(r,`utf8`)}catch(e){throw new n(`INVALID_ARGS`,`Failed to read remote config file: ${r}`,{cause:e instanceof Error?e.message:String(e)})}let a;try{a=JSON.parse(i)}catch(e){throw new n(`INVALID_ARGS`,`Invalid JSON in remote config file: ${r}`,{cause:e instanceof Error?e.message:String(e)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new n(`INVALID_ARGS`,`Remote config file must contain a JSON object: ${r}`);let o={},s=a,c=L.dirname(r);for(let[e,i]of Object.entries(s)){let a=Ae(e);if(!a)throw new n(`INVALID_ARGS`,`Unsupported remote config key "${e}" in remote config file ${r}.`);let s=p(a,i,`remote config file ${r}`,e);o[a.key]=typeof s==`string`&&`path`in a&&a.path?D(s,{cwd:c,env:t}):s}return{resolvedPath:r,profile:o}}function Tt(e=process.env){let t={};for(let n of je){let r=Me(n.key).map(t=>({name:t,value:e[t]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);r&&(t[n.key]=p(n,r.value,`environment variable ${r.name}`,r.name))}return t}function Et(...e){let t={};for(let n of e)if(n)for(let e of je){let r=n[e.key];r!==void 0&&(t[e.key]=r)}return t}function Dt(e){let t=e.env??process.env;return D(e.configPath,{cwd:e.cwd,env:t})}function H(e){let t=wt(e);return{resolvedPath:t.resolvedPath,profile:Et(Tt(e.env),t.profile)}}function Ot(e){return e===`android-instance`||e===`ios-instance`}function kt(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function At(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function jt(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!At(e)}function Mt(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 Nt(e){let t=e?.metroPublicBaseUrl?.trim();return t?Mt(t):null}function Pt(e,t={}){if(!jt(e)||!t.flags?.metroProxyBaseUrl||!Ot(t.flags.leaseBackend))return e;let r=Nt(t.flags);if(!r)throw new n(`INVALID_ARGS`,`cdp remote bridge target discovery requires a Metro public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro CDP endpoint without bridge proxy authentication.`});return[...e,`--url`,r]}async function Ft(e,t={}){return(await m(`npm`,kt(Pt(e,t)),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function U(e){let t=Vt(e);if(!I.existsSync(t))return null;let n;try{n=JSON.parse(I.readFileSync(t,`utf8`))}catch(t){return Yt(e,t),null}return Zt(n)?n:(Yt(e),null)}function It(e){let t=Vt({stateDir:e.stateDir,session:e.state.session});I.mkdirSync(L.dirname(t),{recursive:!0}),qt(t,e.state),qt(Ht(e.stateDir),{session:e.state.session})}function Lt(e){return{baseUrl:Jt(e.daemonBaseUrl),authToken:e.daemonAuthToken,transport:e.daemonTransport,serverMode:e.daemonServerMode}}function Rt(e){I.rmSync(Vt(e),{force:!0});let t=Ht(e.stateDir);Wt(e.stateDir)===e.session&&I.rmSync(t,{force:!0})}function zt(e){let t=e.validateRemoteConfigHash??!0,r=e.remoteConfig?Dt({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,i=U(e)??(e.allowActiveFallback?Ut({stateDir:e.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(t&&W(i.remoteConfigPath)!==i.remoteConfigHash)throw new n(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=Kt(i,e),o=me(i);return{runtime:i.runtime,connection:fe(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:i.daemon?.authToken??a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...pe(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function Bt(e){return fe(me(e))}function W(e){try{return F.createHash(`sha256`).update(I.readFileSync(e)).digest(`hex`)}catch(t){throw new n(`INVALID_ARGS`,`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function Vt(e){return L.join(e.stateDir,`remote-connections`,`${Xt(e.session)}.json`)}function Ht(e){return L.join(e,`remote-connections`,`.active-session.json`)}function Ut(e){let t=Wt(e.stateDir);return t?U({stateDir:e.stateDir,session:t}):null}function Wt(e){let t=Ht(e);if(I.existsSync(t))try{let e=JSON.parse(I.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function Gt(e){if(e)return F.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function Kt(e,t){try{return H({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function qt(e,t){I.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:`utf8`,mode:384}),I.chmodSync(e,384)}function Jt(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of[...t.searchParams.keys()])/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function Yt(e,t){h({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),Rt(e)}function Xt(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${F.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Zt(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&Qt(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&$t(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&en(t.daemon)}function Qt(e,t){return t.every(t=>typeof e[t]==`string`)}function $t(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function en(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:tn(e)}function tn(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 nn=Ne.map(e=>e.key);function rn(e){let t={};for(let n of nn){let r=e[n];r!==void 0&&(t[n]=r)}return t}function an(e){return e.remoteConfig?{...rn(H({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function on(e){return e===`cloud`||e===`proxy`||M(e)}function sn(e){return M(e)}function cn(){return[`cloud`,`proxy`,N.browserStack,N.awsDeviceFarm].join(`, `)}function ln(e){return!sn(e)}function un(e){return e===`proxy`?`proxy`:sn(e)?`direct-device-provider`:`remote-provider`}const dn=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),fn=new Set([`open`]),pn=new Set([S.open,S.install,S.reinstall,_.installSource]);async function mn(e){let{command:t,flags:r,client:i}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=E(r.stateDir).baseDir,o=H({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...rn(o.profile),...r,remoteConfig:o.resolvedPath},c=U({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new n(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??Rn(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=Ln(l.runtime,u.platform)??e.runtime,f=l,p=!c,m,h=Sn(f);if(h.shouldAllocate(t)){let e=await yn({command:t,client:i,state:l,nextState:f,nextFlags:u,policy:h});f=e.state,p||=e.changed,m=e.acquiredLeaseForCleanup}let g=await hn({command:t,flags:u,client:i,state:l,nextState:f,runtime:d,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return f=g.state,d=g.runtime,p||=g.changed,await vn({changed:p,stateDir:a,state:f,client:i,acquiredLeaseForCleanup:m,preparedMetroCleanupOnFailure:g.preparedMetroCleanupOnFailure,metroCleanupToStop:g.metroCleanupToStop}),{flags:{...u,session:f.session,leaseId:f.leaseId,leaseBackend:f.leaseBackend,platform:f.platform??u.platform,target:f.target??u.target},runtime:d,connection:Bt(f)}}async function hn(e){let{command:t,flags:r,state:i,client:a}=e,o=gn(e.nextState,r),s=e.runtime;if(!Mn(t,r,e.batchSteps,e.positionals)||!Nn(r)||!_n(e.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new n(`INVALID_ARGS`,`${t} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await En(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!In(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?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function gn(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function _n(e,t,n){return e===!0||!t||!Pn(t,n)}async function vn(e){if(e.changed)try{It({stateDir:e.stateDir,state:e.state})}catch(t){throw await G(e.preparedMetroCleanupOnFailure),await An(e.client,e.state,e.acquiredLeaseForCleanup),t}await G(e.metroCleanupToStop)}async function yn(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??K(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&Vn(i,c.device);let l=s.leaseBackend??o??jn(i,t);Gn(r,i,l);let u=await zn(n,s,l,a,i),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,bn(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:xn(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function bn(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function xn(e,t,n,r){return{...e,leaseId:t.leaseId,leaseBackend:n,leaseProvider:t.leaseProvider??e.leaseProvider,clientId:t.clientId??e.clientId,deviceKey:t.deviceKey??e.deviceKey,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Sn(e){return e.leaseProvider===`proxy`?wn:M(e.leaseProvider)?Tn:Cn}const Cn={shouldAllocate:e=>!dn.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},wn={shouldAllocate:e=>e!==`devices`&&!dn.has(e),ttlMs:()=>3e5,resolveLeaseState:Bn},Tn={shouldAllocate:e=>!dn.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function En(e,t,r,i,a){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if(e.platform!==`ios`&&e.platform!==`android`)throw new n(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new n(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:Fn(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:a,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:e.metroNoReuseExisting?!1:void 0,installDependenciesIfNeeded:e.metroNoInstallDeps?!1:void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:e.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function G(e){if(e)try{await we(e)}catch{}}async function Dn(e){try{await Ct({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function On(e,t){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:t.daemon?.authToken,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}async function kn(e,t){if(t.leaseId)try{await On(e,t)}catch{}}async function An(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function K(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`}function jn(e,t){let r=K(e);if(r)return r;throw new n(`INVALID_ARGS`,`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}function Mn(e,t,n,r=[]){return e===`cdp`?jt(r)&&!!t.metroPublicBaseUrl:fn.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return fn.has(t)&&e.runtime===void 0})}function Nn(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Pn(e,t){return!e.platform||!t||t!==`ios`&&t!==`android`?!0:e.platform===t}function Fn(e){if(e!==void 0){if(e===`auto`||e===`react-native`||e===`expo`)return e;throw new n(`INVALID_ARGS`,`metro prepare --kind must be auto, react-native, or expo`)}}function In(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ln(e,t){if(e)return Pn(e,t)?e:void 0}function Rn(e,t,r={}){if(!e.tenant)throw new n(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new n(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&ln(r.leaseProvider))throw new n(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:e.session??`default`,remoteConfigPath:t,remoteConfigHash:W(t),daemon:Lt(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??K(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.target,connectedAt:i,updatedAt:i}}async function zn(e,t,n,r,i){if(t.leaseId&&t.leaseBackend===n){let i=await Kn(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function Bn(e){if(!pn.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new n(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let t=await Hn(e.client,e.flags),r=Un(t);return{state:{...e.state,deviceKey:r,leaseBackend:e.state.leaseBackend??e.leaseBackend??Wn(t),platform:e.state.platform??t.platform,target:e.state.target??t.target,updatedAt:new Date().toISOString()},device:t}}function Vn(e,t){if(e.platform=t.platform,e.target=t.target??e.target,o(t)){e.udid=t.id;return}t.platform===`android`&&(e.serial=t.id)}async function Hn(e,n){return await t((await e.devices.list({platform:n.platform,target:n.target,device:n.device,udid:n.udid,serial:n.serial,iosSimulatorDeviceSet:n.iosSimulatorDeviceSet,androidDeviceAllowlist:n.androidDeviceAllowlist})).map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:n.platform,target:n.target,deviceName:n.device,udid:n.udid,serial:n.serial})}function Un(e){return`${a(e)}:${e.target??`mobile`}:${e.id}`}function Wn(e){if(o(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`}function Gn(e,t,r){if(e.leaseBackend&&e.leaseBackend!==r)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:e.session,leaseBackend:e.leaseBackend});if(e.platform&&t.platform&&e.platform!==t.platform)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:e.session,platform:e.platform});if(e.target&&t.target&&e.target!==t.target)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:e.session,target:e.target})}async function Kn(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){if(qn(e))return;throw e}}function qn(e){return!(e instanceof n)||e.code!==`UNAUTHORIZED`?!1:e.details?.reason===`LEASE_NOT_FOUND`||e.details?.reason===`LEASE_EXPIRED`||e.details?.reason===`LEASE_REVOKED`}async function Jn(e,t){let r=await e.text(),i={};if(r.trim().length>0)try{i=JSON.parse(r)}catch(r){throw new n(`COMMAND_FAILED`,t.invalidJsonMessage,{status:e.status},r instanceof Error?r:void 0)}if(!e.ok)throw new n(`UNAUTHORIZED`,t.rejectedMessage,{status:e.status,response:i});return i}const Yn=1e3;async function Xn(e){return await Zn({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:e.command===`connect`&&!e.flags.noLogin,env:e.env})}async function Zn(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:`none`};if(J(e.flags.daemonAuthToken))return{flags:e.flags,source:`flag`};if(J(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:`env`};if(!mr(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:`none`};let r=await ar({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:`cli-session`};if(!e.allowInteractiveLogin)throw e.flags.noLogin?new n(`UNAUTHORIZED`,`Remote daemon authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`}):pr(e.command,t);let i=await $n({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:i.accessToken},source:`login`}}async function Qn(e){let t=e.env??e.io?.env??process.env;if(J(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:q(t)};if(J(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:q(t)};let r=await ar({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(e.flags.noLogin)throw new n(`UNAUTHORIZED`,`Cloud connection profile authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`});let i=await $n({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:`agent-device connect`});return{accessToken:i.accessToken,cloudBaseUrl:i.session.cloudBaseUrl}}async function $n(e){let t=e.env??e.io?.env??process.env,r=ur(t,e.io);if(r===`non-interactive`)throw pr(e.commandLabel??`agent-device connect`,t);let i=q(t),a=await cr({baseUrl:i,pathName:`/api/control-plane/device-auth/start`,body:{client:`agent-device`,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});lr(a);let o=a.verificationUriComplete??a.verificationUri,s=r===`local-browser`?a.verificationUri:hr(a.verificationUri,a.userCode);r===`local-browser`?(_r(e.io,`Opening ${a.verificationUri}...\n`),await gr(o,e.io)):_r(e.io,`Open this URL on your machine:\n${s}\n\nWaiting for approval for 10 minutes...\n`);let c=await sr({cloudBaseUrl:i,deviceCode:a.deviceCode,expiresIn:a.expiresIn,interval:a.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),l=c.cliSession?.refreshCredential??c.cliSession?.refreshToken;if(!J(c.accessToken)||!J(l))throw new n(`UNAUTHORIZED`,`Device authorization did not return CLI credentials.`);let u=new Date(e.io?.now?.()??Date.now()).toISOString(),d={version:1,id:c.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:i,workspaceId:c.cliSession?.workspaceId,accountId:c.cliSession?.accountId,name:c.cliSession?.name,refreshCredential:l,createdAt:u,expiresAt:c.cliSession?.expiresAt};return tr({stateDir:e.stateDir,session:d}),{accessToken:c.accessToken,expiresAt:c.expiresAt,session:d}}function er(e){let t=rr(e.stateDir);if(!I.existsSync(t))return null;try{let e=JSON.parse(I.readFileSync(t,`utf8`));return e.version!==1||!J(e.id)||!J(e.cloudBaseUrl)||!J(e.refreshCredential)||!J(e.createdAt)?null:e}catch{return null}}function tr(e){let t=rr(e.stateDir);I.mkdirSync(L.dirname(t),{recursive:!0,mode:448}),I.writeFileSync(t,`${JSON.stringify(e.session,null,2)}\n`,{mode:384});try{I.chmodSync(t,384)}catch{}}function nr(e){let t=rr(e.stateDir);return I.existsSync(t)?(I.rmSync(t,{force:!0}),!0):!1}function rr(e){return L.join(e,`auth`,`cli-session.json`)}function ir(e){let t=er({stateDir:e.stateDir});return t?{authenticated:!0,source:`cli-session`,sessionId:t.id,cloudBaseUrl:t.cloudBaseUrl,workspaceId:t.workspaceId,accountId:t.accountId,name:t.name,createdAt:t.createdAt,expiresAt:t.expiresAt,expired:vr(t.expiresAt,e.now)}:{authenticated:!1,source:`none`}}async function ar(e){let t=er({stateDir:e.stateDir});return!t||vr(t.expiresAt,e.io?.now)?null:{accessToken:(await or({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:q(e.env,t.cloudBaseUrl)}}async function or(e){let t=await cr({baseUrl:q(e.env,e.session.cloudBaseUrl),pathName:`/api/control-plane/cli-session/refresh`,body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(J(t.accessToken))return{accessToken:t.accessToken,expiresAt:t.expiresAt};throw t.status===`revoked`||t.error===`revoked`?new n(`UNAUTHORIZED`,`Stored cloud CLI session was revoked.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:t.status,error:t.error}):new n(`UNAUTHORIZED`,`Failed to refresh CLI session.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:t.status,error:t.error})}async function sr(e){let t=e.now??Date.now,r=Math.min((e.expiresIn??600)*1e3,6e5),i=t()+r,a=Math.max(Yn,(e.interval??5e3/1e3)*1e3);for(;t()<i;){let t=await cr({baseUrl:e.cloudBaseUrl,pathName:`/api/control-plane/device-auth/poll`,body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if(t.status===`approved`||J(t.accessToken))return t;if(t.status===`slow_down`||t.error===`slow_down`)a+=Yn;else if(t.status!==`authorization_pending`&&t.error!==`authorization_pending`)throw new n(`UNAUTHORIZED`,`Device authorization was not approved.`,{status:t.status,error:t.error});await yr(a)}throw new n(`TIMEOUT`,`Device authorization expired before approval.`)}async function cr(e){let t=await(e.fetchImpl??fetch)(new URL(e.pathName,e.baseUrl),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await Jn(t,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud auth endpoint rejected the request.`})}function lr(e){if(!J(e.deviceCode)||!J(e.userCode)||!J(e.verificationUri))throw new n(`COMMAND_FAILED`,`Cloud auth start returned an unusable response.`)}function ur(e,t){let n=t?.stdinIsTTY??process.stdin.isTTY,r=t?.stdoutIsTTY??process.stdout.isTTY;return dr(e)||!n||!r?`non-interactive`:fr(e)?`device-code`:`local-browser`}function dr(e){return e.CI===`true`||e.GITHUB_ACTIONS===`true`||e.BUILDKITE===`true`}function fr(e){return!!(e.SSH_TTY||e.SSH_CONNECTION||e.CODESPACES===`true`||e.GITPOD_WORKSPACE_ID||e.REMOTE_CONTAINERS===`true`)}function pr(e,t){let r=q(t);return new n(`UNAUTHORIZED`,`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL(`/api-keys`,r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function q(e,t){let r=e.AGENT_DEVICE_CLOUD_BASE_URL??t??`https://cloud.agent-device.dev`;try{return new URL(r).toString().replace(/\/+$/,``)}catch(e){throw new n(`INVALID_ARGS`,`Invalid AGENT_DEVICE_CLOUD_BASE_URL.`,{cloudBaseUrl:r},e instanceof Error?e:void 0)}}function mr(e,t){if(t.AGENT_DEVICE_CLOUD_AUTH===`1`||t.AGENT_DEVICE_CLOUD_AUTH===`true`||J(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return t===`agent-device.dev`||t.endsWith(`.agent-device.dev`)}catch{return!1}}function hr(e,t){let n=new URL(e);return n.searchParams.set(`user_code`,t),n.toString()}async function gr(e,t){if(t?.openBrowser){await t.openBrowser(e);return}let n=process.platform;try{n===`darwin`?await g(`open`,[e],{allowFailure:!0,timeoutMs:5e3}):n===`win32`?await g(`cmd`,[`/c`,`start`,``,e],{allowFailure:!0,timeoutMs:5e3}):await g(`xdg-open`,[e],{allowFailure:!0,timeoutMs:5e3})}catch{_r(t,`Open this URL on your machine:\n${e}\n`)}}function _r(e,t){(e?.stderr??process.stderr).write(t)}function vr(e,t){if(!e)return!1;let n=Date.parse(e);return Number.isFinite(n)?n<=(t?.()??Date.now()):!0}function J(e){return typeof e==`string`&&e.trim().length>0}async function yr(e){await new Promise(t=>setTimeout(t,e))}const br=new Set([`daemonAuthToken`,`metroBearerToken`]);function xr(e){let t=Er(wr(e.profile)),n=L.join(e.stateDir,`remote-connections`,`generated`);I.mkdirSync(n,{recursive:!0,mode:448});let r=L.join(n,`${Dr(e.provider)}-${Tr(t)}.json`);I.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{I.chmodSync(r,384)}catch{}return r}function Sr(e){try{return H(e)}catch(t){let i=r(t);throw new n(`COMMAND_FAILED`,`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:i.message},i)}}function Cr(e){let t=Sr({configPath:xr({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Or(e.provider)});return{flags:{...rn(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function wr(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!br.has(e)))}function Tr(e){return F.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function Er(e){return Array.isArray(e)?e.map(Er):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Er(t)])):e}function Dr(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Or(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}async function kr(e){let t=await Qn({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await Ar({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=Nr({stateDir:e.stateDir,cloudBaseUrl:t.cloudBaseUrl,daemonBaseUrl:typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,session:e.flags.session});return Cr({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function Ar(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return jr(await Jn(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function jr(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let t=e.connection;if(!t||typeof t!=`object`)throw new n(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(t.remoteConfigProfile!==void 0)return Mr(t.remoteConfigProfile);throw new n(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Mr(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new n(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function Nr(e){return F.createHash(`sha256`).update(`${e.stateDir}\0${e.cloudBaseUrl}\0${e.daemonBaseUrl}\0${e.session??``}`).digest(`hex`).slice(0,16)}function Pr(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}}function Fr(e){let t=Lr(e.provider)(e),n=Wr(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??K(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...Pr(e.flags)};return Cr({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const Ir=[{provider:N.browserStack,buildProfileFields:Rr},{provider:N.awsDeviceFarm,buildProfileFields:zr}];function Lr(e){let t=Ir.find(t=>t.provider===e)?.buildProfileFields;if(t)return t;throw new n(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Rr(e){return Vr(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),Vr(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:Br(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:Y(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:Y(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Y(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName}}function zr(e){let{env:t,flags:n}=e;return{platform:Br(n.platform,`connect aws-device-farm requires --platform ios|android.`),device:n.device,awsProjectArn:Hr(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`),awsDeviceArn:Hr(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:Ur(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:Ur(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`]),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function Br(e,t){if(e===`android`||e===`ios`)return e;throw new n(`INVALID_ARGS`,t)}function Y(e,t){if(e)return e;throw new n(`INVALID_ARGS`,t)}function Vr(e,t,r){let i=e?.[t];if(i)return i;throw new n(`INVALID_ARGS`,`${r} requires ${t} in the environment.`)}function Hr(e,t,n,r){return Y(Ur(e,t,n),r)}function Ur(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Wr(e,t,n,r){return F.createHash(`sha256`).update(`${e}\0${t}\0${n??``}\0${r??``}`).digest(`hex`).slice(0,16)}function Gr(e){let t=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!t)throw new n(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=Kr(e.stateDir,t,e.flags.session),i={daemonBaseUrl:t,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??K(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...Pr(e.flags)};return Cr({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:t,daemonTransport:e.flags.daemonTransport??`http`}})}function Kr(e,t,n){return F.createHash(`sha256`).update(`${e}\0${t}\0${n??``}`).digest(`hex`).slice(0,16)}const qr=async({positionals:e,flags:t,client:n})=>{let r=E(t.stateDir).baseDir,i=pi(e);Yr(i,t);let a=await Jr({provider:i,flags:t,stateDir:r}),o=a.flags,s=ai(a.remoteConfigPath),c=Xr(o,s),l=Zr({stateDir:r,flags:o,remoteConfigPath:a.remoteConfigPath});Qr(l.previous,{flags:o,session:l.session,remoteConfigPath:a.remoteConfigPath,remoteConfigHash:l.remoteConfigHash,desiredLeaseBackend:K(o),connection:s,daemon:l.daemon});let u=$r({flags:o,scope:c,connectionMetadata:s,context:l,remoteConfigPath:a.remoteConfigPath});It({stateDir:r,state:u}),await ri(n,r,o,l.previous);let d=Ti(u),f=Ci(o,u);return P(o,Oi(u,f),()=>[`Connected remote session "${l.session}" tenant "${c.tenant}" run "${c.runId}" ${u.leaseId?`lease ${u.leaseId}`:`lease pending`}`,d?.message,f?.message].filter(e=>!!e).join(`
|
|
2
|
-
`)),!0};async function
|
|
3
|
-
`)),!0};function
|
|
4
|
-
`)}function
|
|
5
|
-
`):`Not authenticated.`}const
|
|
6
|
-
`)}function X(e,t,n){return n?ue(e,t,{validateStream:!1}):e}function _a(){return new Promise(()=>{})}const va=new Set([`id`,`text`,`label`]),ya=new Set([`enabled`,`selected`]);function ba(e){let t=Re(e);return xa(t.actions,{actionLines:t.actionLines,metadata:ze(e)})}function xa(e,t={}){let r={config:Sa(t.metadata),warnings:[],unsupported:[]},i=[];for(let[n,a]of e.entries()){let e=t.actionLines?.[n]??n+1,o=wa(a);switch(o.kind){case`commands`:i.push(...o.commands),to(r,o.warnings,a,e);break;case`config`:$a(r,o.appId,a,e),i.push(...o.commands),to(r,o.warnings,a,e);break;case`unsupported`:r.unsupported.push({line:e,action:Z(a),message:o.message});break}}if(r.unsupported.length>0)throw new n(`INVALID_ARGS`,`Cannot export replay to Maestro YAML: unsupported .ad action ${io(r.unsupported)}.`,{unsupported:r.unsupported});return{yaml:ro(r.config,i),warnings:r.warnings}}function Sa(e){return e?.env&&Object.keys(e.env).length>0?{env:e.env}:{}}const Ca={open:Ta,click:Oa,press:Oa,longpress:ka,fill:Na,type:Pa,keyboard:Fa,back:()=>({kind:`commands`,commands:[`back`]}),wait:Ia,find:La,screenshot:Ra,scroll:za,swipe:Ba};function wa(e){return Ca[e.command]?.(e)??{kind:`unsupported`,message:`${e.command} has no Maestro equivalent`}}function Ta(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`open requires an app id or URL`};if(ao(t))return{kind:`commands`,commands:[{openLink:t}]};let r=Ea(e,t);return n&&ao(n)?{kind:`config`,appId:t,commands:[r,{openLink:n}]}:n?{kind:`unsupported`,message:`open with a non-URL second argument is unsupported`}:{kind:`config`,appId:t,commands:[r]}}function Ea(e,t){let n=Da(e);return n?{launchApp:{appId:t,...n}}:`launchApp`}function Da(e){let t=e.flags?.launchArgs,n={};return e.flags?.relaunch===!0&&(n.stopApp=!0),e.flags?.clearAppState===!0&&(n.clearState=!0),Array.isArray(t)&&t.length>0&&(n.launchArguments=t),Object.keys(n).length>0?n:void 0}function Oa(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`${e.command} requires a target`};let r=Wa(t,n);if(!r)return{kind:`unsupported`,message:`tap target is not Maestro-compatible`};let i=Ya(e);return i.ok?e.flags?.doubleTap===!0?{kind:`commands`,commands:[{doubleTapOn:r}],warnings:Ma(e,`doubleTapOn`)}:typeof e.flags?.holdMs==`number`?{kind:`commands`,commands:[{longPressOn:r}],warnings:[ja(e.flags.holdMs),...Ma(e,`longPressOn`)]}:{kind:`commands`,commands:[Qa(r,i.options)]}:{kind:`unsupported`,message:i.message}}function ka(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`longpress requires a target`};let r=Wa(t,n);return r?{kind:`commands`,commands:[{longPressOn:r}],warnings:Aa(e).map(ja)}:{kind:`unsupported`,message:`longpress target is not Maestro-compatible`}}function Aa(e){let[t,n,r]=e.positionals,i=Q(t)&&Q(n)?r:n;return i&&Q(i)?[Number(i)]:[]}function ja(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function Ma(e,t){let n=[];return typeof e.flags?.count==`number`&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function Na(e){let[t,n]=e.positionals;if(!t||n===void 0)return{kind:`unsupported`,message:`fill requires a target and text`};let r=Wa(t);return r?{kind:`commands`,commands:[{tapOn:r},{inputText:n}],warnings:[`fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents`]}:{kind:`unsupported`,message:`fill target is not Maestro-compatible`}}function Pa(e){let[t]=e.positionals;if(t===void 0)return{kind:`unsupported`,message:`type requires text`};let n=eo(t);return n===null?{kind:`commands`,commands:[{inputText:t}]}:{kind:`commands`,commands:[{eraseText:n}]}}function Fa(e){let[t]=e.positionals;return t===`dismiss`?{kind:`commands`,commands:[`hideKeyboard`]}:t===`enter`||t===`return`?{kind:`commands`,commands:[{pressKey:`Enter`}]}:{kind:`unsupported`,message:`keyboard ${t??``}`.trim()}}function Ia(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`wait requires a target or duration`};if(Q(t))return{kind:`commands`,commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:[`wait <ms> exports as waitForAnimationToEnd and may return before the full duration`]};if(t===`text`&&n)return{kind:`commands`,commands:[{extendedWaitUntil:{visible:n,timeout:no(e,17e3)}}]};let r=Ga(t);return r?{kind:`commands`,commands:[{extendedWaitUntil:{visible:r,timeout:no(e,17e3)}}]}:{kind:`unsupported`,message:`wait selector is not Maestro-compatible`}}function La(e){let[t,n,r]=e.positionals;return t!==`text`||!n||!r?{kind:`unsupported`,message:`only find text <query> exists|missing exports to Maestro`}:r===`exists`?{kind:`commands`,commands:[{assertVisible:n}]}:r===`missing`||r===`not-exists`?{kind:`commands`,commands:[{assertNotVisible:n}]}:{kind:`unsupported`,message:`find text assertion "${r}" is unsupported`}}function Ra(e){let[t]=e.positionals;return t?{kind:`commands`,commands:[{takeScreenshot:t}]}:{kind:`unsupported`,message:`screenshot requires an output path`}}function za(e){let[t]=e.positionals;return!t||t===`down`?{kind:`commands`,commands:[`scroll`]}:{kind:`unsupported`,message:`scroll ${t} is not exported yet`}}function Ba(e){let t=Va(e);if(!t)return{kind:`unsupported`,message:`only coordinate swipe exports to Maestro`};let n=Ha(e);if(n===null)return{kind:`unsupported`,message:`swipe count must be a positive integer`};let r=Ua(e);return r?{kind:`unsupported`,message:r}:{kind:`commands`,commands:Array.from({length:n},()=>({swipe:t}))}}function Va(e){let[t,n,r,i,a]=e.positionals;if(!(!Q(t)||!Q(n)||!Q(r)||!Q(i)))return{start:Le(t,n),end:Le(r,i),...a&&Q(a)?{duration:Number(a)}:{}}}function Ha(e){let t=e.flags?.count??1;return Number.isInteger(t)&&t>=1?t:null}function Ua(e){if(e.flags?.pauseMs!==void 0)return`swipe --pause-ms has no Maestro equivalent`;if(e.flags?.pattern&&e.flags.pattern!==`one-way`)return`swipe ping-pong pattern has no Maestro equivalent`}function Wa(e,t){return Q(e)&&Q(t)?{point:Le(e,t)}:e.startsWith(`@`)?null:Ga(e)}function Ga(e){let t;try{t=x(e)}catch{return e.includes(`=`)||e.includes(`||`)?null:e}let n=Ka(t.selectors);return n===null?t.selectors.length===1?qa(t.selectors[0]):null:n}function Ka(e){if(e.length<=1)return null;let t=e.flatMap(e=>e.terms.length===1&&va.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||t.length===0)return null;let n=t[0];return typeof n==`string`&&t.every(e=>e===n)?n:null}function qa(e){let t={};for(let n of e.terms)if(!Ja(t,n))return null;return Object.keys(t).length>0?t:null}function Ja(e,t){return va.has(t.key)?typeof t.value!=`string`||e.id||e.text||e.label?!1:(e[t.key]=t.value,!0):ya.has(t.key)&&typeof t.value==`boolean`?(e[t.key]=t.value,!0):!1}function Ya(e){let t=Za(e);return t?{ok:!1,message:t}:{ok:!0,options:Xa(e)}}function Xa(e){let t={};return typeof e.flags?.count==`number`&&e.flags.count>1&&(t.repeat=e.flags.count),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&(t.delay=e.flags.intervalMs),t}function Za(e){if(e.flags?.jitterPx!==void 0)return`tap --jitter-px has no Maestro equivalent`;if(e.flags?.clickButton&&e.flags.clickButton!==`primary`)return`tap --button ${e.flags.clickButton} has no Maestro equivalent`}function Qa(e,t){return Object.keys(t).length===0?{tapOn:e}:typeof e==`string`?{tapOn:{text:e,...t}}:e&&typeof e==`object`&&!Array.isArray(e)?{tapOn:{...e,...t}}:{tapOn:e}}function $a(e,t,n,r){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:r,action:Z(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})}function eo(e){return e.length===0||![...e].every(e=>e===`\b`)?null:e.length}function to(e,t,n,r){for(let i of t??[])e.warnings.push({line:r,action:Z(n),message:i})}function no(e,t){let n=e.positionals.at(-1);return n&&Q(n)?Number(n):t}function ro(e,t){return Ie(Object.keys(e).length>0?[e,t]:[t])}function io(e){return e.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join(`; `)}function Z(e){return[e.command,...e.positionals??[]].join(` `).trim()}function ao(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function Q(e){return e!==void 0&&Number.isFinite(Number(e))}const oo=async e=>{let{positionals:t}=e;return t[0]===`export`?await co(e):so(e)};function so({positionals:e,flags:t}){if(e.length>1)throw new n(`INVALID_ARGS`,`replay accepts exactly one input path: replay <path>`);if(t.replayExportFormat!==void 0||t.out!==void 0)throw new n(`INVALID_ARGS`,`replay --format/--out are only supported with replay export.`);return!1}async function co({positionals:e,flags:t}){lo(e,t);let r=e[1];if(!r)throw new n(`INVALID_ARGS`,`replay export requires an input path.`);let i=D(r),a=ba(I.readFileSync(i,`utf8`)),o=typeof t.out==`string`?D(t.out):void 0;o&&(I.mkdirSync(L.dirname(o),{recursive:!0}),I.writeFileSync(o,a.yaml));for(let e of a.warnings)process.stderr.write(`Warning: line ${e.line}: ${e.message}\n`);return P(t,{format:t.replayExportFormat??`maestro`,sourcePath:i,...o?{path:o}:{yaml:a.yaml},warnings:a.warnings},()=>o??a.yaml),!0}function lo(e,t){if(e.length>2)throw new n(`INVALID_ARGS`,`replay export accepts exactly one input path: replay export <file.ad>`);if(t.replayUpdate)throw new n(`INVALID_ARGS`,`replay export does not support --update.`);if(t.replayMaestro)throw new n(`INVALID_ARGS`,`replay export reads .ad files; omit --maestro.`);if(t.replayEnv?.length)throw new n(`INVALID_ARGS`,`replay export does not evaluate --env substitutions.`);let r=t.replayExportFormat??`maestro`;if(r!==`maestro`)throw new n(`INVALID_ARGS`,`Unsupported replay export format: ${r}`)}const uo=async({positionals:e,flags:t,client:n})=>{let r=await Fe({client:n,command:`screenshot`,positionals:e,flags:t});return i(t.responseLevel)?(P(t,r,()=>JSON.stringify(r,null,2)),!0):(P(t,{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}},()=>r.overlayRefs?`Annotated ${r.overlayRefs.length} refs onto ${r.path}`:r.path),!0)},fo=async({positionals:e,flags:t,client:r})=>{if(e[0]===`snapshot`){let n=await Fe({client:r,command:`diff`,positionals:e,flags:t});return P(t,n,()=>le(n)),!0}if(e[0]!==`screenshot`)return!1;let i=t.baseline;if(!i||typeof i!=`string`)throw new n(`INVALID_ARGS`,`diff screenshot requires --baseline <path>`);let a=D(i),o=typeof t.out==`string`?D(t.out):void 0,s=e[1];if(e.length>2)throw new n(`INVALID_ARGS`,`diff screenshot accepts at most one current screenshot path`);let[{createAgentDevice:c,localCommandPolicy:l},{createLocalArtifactAdapter:u}]=await Promise.all([import(`./runtime.js`).then(e=>e.r),import(`./sdk-io.js`).then(e=>e.n)]),d=await c({backend:po(r,t),artifacts:u(),sessions:{get:e=>({name:e}),set:()=>{}},policy:l()}).capture.diffScreenshot({session:t.session,baseline:{kind:`path`,path:a},current:s?{kind:`path`,path:D(s)}:{kind:`live`},...o?{out:{kind:`path`,path:o}}:{},threshold:ho(t.threshold),overlayRefs:t.overlayRefs,normalizeStatusBar:t.screenshotNormalizeStatusBar,surface:t.surface});return P(t,d,()=>de(d)),!0};function po(e,t){return{platform:mo(t),captureScreenshot:async(t,n,r)=>{let i=await e.capture.screenshot({path:n,session:t.session,overlayRefs:r?.overlayRefs,fullscreen:r?.fullscreen,normalizeStatusBar:r?.normalizeStatusBar,stabilize:r?.stabilize,surface:r?.surface});return{path:i.path,...i.overlayRefs?{overlayRefs:i.overlayRefs}:{}}}}}function mo(e){switch(e.platform){case`android`:case`linux`:case`macos`:return e.platform;default:return`ios`}}function ho(e){if(!(e==null||e===``))return Number(e)}const go={connect:qr,disconnect:oi,connection:si,auth:ki,proxy:ua,replay:oo,screenshot:uo,diff:fo};async function _o(e){let t={...e.flags},n=go[e.command];return n&&await n({...e,flags:t})?!0:b(e.command)?await vo({...e,command:e.command,flags:t}):!1}async function vo(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function yo(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function bo(e){return e===`ios-instance`}function xo(e){return e[0]===`wait`&&e.includes(`--connected`)}function So(e,t,n){n===0||!xo(e)||!bo(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(`
|
|
7
|
-
`))}function $(e,t,n){return n||(e.push(t),``)}function
|
|
8
|
-
`)}function
|
|
9
|
-
`),n}function
|
|
10
|
-
`),m===`cdp`){let t=await
|
|
1
|
+
import{B as e,C as t,F as n,I as r,a as i,b as a,p as o,u as s}from"./sdk-contracts.js";import{A as c,E as l,I as u,M as d,N as f,O as p,S as m,j as h,v as g}from"./sdk-android-adb.js";import{C as _}from"./sdk-batch.js";import{$n as v,Gn as y,Hn as b,Kn as x,Mn as S,Nn as C,Qn as w,Un as T,Vn as E,Zn as D,er as ee,kn as te,qn as ne}from"./tv-remote.js";import{a as re,c as ie,i as ae,l as oe,n as se,o as ce,r as le,s as ue}from"./client.js";import{C as O,D as de,c as fe,o as pe}from"./snapshot-diagnostics.js";import{n as me}from"./version.js";import{n as k,t as he}from"./path-resolution.js";import{_ as A,h as ge,l as _e,u as ve,v as ye}from"./registry.js";import{a as be,l as xe}from"./sdk-batch-runner.js";import{v as Se}from"./url.js";import{i as Ce,r as we}from"./client-metro-companion.js";import"./selectors2.js";import{n as Te}from"./command-metadata.js";import{n as Ee}from"./metro2.js";import{n as De,r as Oe,t as j}from"./providers.js";import{n as ke,r as Ae,t as je}from"./command-schema.js";import{t as Me}from"./update-check.js";import{i as Ne,n as Pe,r as Fe,t as Ie}from"./sdk-remote-config.js";import{i as M,r as Le,t as Re}from"./cli-runner.js";import{_ as ze,t as N,v as Be,y as Ve}from"./points.js";import P,{randomBytes as He,randomUUID as Ue}from"node:crypto";import F from"node:fs";import I from"node:path";import We from"node:http";import{pipeline as Ge}from"node:stream/promises";import{Readable as Ke}from"node:stream";import{pathToFileURL as qe}from"node:url";function L(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const Je=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),Ye=new Set([`appsFilter`,`iosSimulatorDeviceSet`,`sessionLocked`,`sessionLockConflicts`]),Xe=tt(),Ze=new Map(Xe.map(e=>[e.key,e]));function Qe(e){return Ze.get(e)}function $e(e){return Xe.filter(t=>t.config.enabled&&t.supportsCommand(e))}function R(e,t){return Qe(e)?.supportsCommand(t)??!1}function et(e,t,n,r){return p(rt(e),t,n,r)}function tt(){let e=new Map;for(let t of ye()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ge)t.set(e,new Set([`*`]));for(let e of ee()){let n=ke(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,config:{enabled:!Je.has(e),key:e},env:{names:Ye.has(e)?[]:[l(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>e.key.localeCompare(t.key))}function nt(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function rt(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=nt(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}const z=`open <app> --relaunch`,it={start:{command:`open`,example:z},restart:{command:`open`,example:z},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`}};function at(e){if(e.length<=2)return[];let t=ee(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=ot(e),i=t.map(t=>({name:t,distance:st(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function ot(e){return e.length<4?1:e.length<=6?2:3}function st(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):ct(e,t)}function ct(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 lt(e){let t=e.toLowerCase(),n=it[t]?.example;if(n)return n;let r=at(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const ut=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]);function dt(e){return ut.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${z}.`:`Unknown flag: ${e}`}function ft(e){let t={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=V(l));continue}if(gt(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=V(l));continue}let[f,p]=u?bt(l):[l,void 0];if(mt(r,f))continue;let m=_t(f,r);if(ht(r,m)){a.push(l);continue}if(!m){if(Tt(r,a,l)){r?a.push(l):r=l;continue}throw new n(`INVALID_ARGS`,dt(f))}let h=xt(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=t[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];t[m.key]=e}else t[m.key]=h.value;s.push({key:m.key,token:f})}return pt(i,t),{command:r,positionals:a,flags:t,warnings:o,providedFlags:s}}function pt(e,t){e?.toLowerCase()===`relaunch`&&(t.relaunch=!0)}function mt(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function ht(e,t){return e===`react-devtools`?t?!R(t.key,e):!0:!1}function gt(e){return e===`cdp`}function _t(e,t){let n=ye().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??A(e);if(t){let e=n.find(e=>R(e.key,t));if(e)return e}return A(e)}function vt(e,t){let r=t?.strictFlags??!0,i=[...e.warnings],a=L({json:!1,help:!1,version:!1},t?.defaultFlags??{});if(L(a,e.flags),e.command&&!v(e.command)&&!a.help){let t=lt(e.command);throw new n(`INVALID_ARGS`,t?`Unknown command: ${e.command}. Did you mean ${t}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!R(t.key,e.command));if(o.length>0){let t=o.map(e=>e.token),s=Ot(e.command,t);if(r)throw new n(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(R(t,e.command)||delete a[t]);if(yt(e),je(e.command,a),e.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new n(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return Dt({command:e.command,positionals:e.positionals,flags:a,warnings:i})}function yt(e){if(e.command!==`back`)return;let t=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(t.map(e=>e.token)).size<=1))throw new n(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function bt(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function xt(e,t,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new n(`INVALID_ARGS`,`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new n(`INVALID_ARGS`,`Flag ${t} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||Ct(i)?{value:!0,consumeNext:!1}:wt(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&Ct(a))throw new n(`INVALID_ARGS`,`Flag ${t} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new n(`INVALID_ARGS`,`Invalid ${St(t)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new n(`INVALID_ARGS`,`Invalid ${St(t)}: ${a}`);return{value:Math.floor(o),consumeNext:r===void 0}}function St(e){return e.replace(/^-+/,``)}function Ct(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?bt(e):[e,void 0];return A(t)!==void 0}function wt(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 Tt(e,t,n){if(!Et(n)||!e)return!1;let r=Ae(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function Et(e){return/^-\d+(\.\d+)?$/.test(e)}function Dt(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 Ot(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 B(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function kt(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(V(e))}function V(e){let t=e.toLowerCase();return t===`long-press`?`longpress`:t===`metrics`?`perf`:t===`tap`?`press`:t===`launch`||t===`relaunch`?`open`:e}const At={slug:`react-devtools-companion`,runArg:Se,displayName:`React DevTools companion`};async function jt(e){return await we({...e,definition:At,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 Mt(e){return await Ce({...e,definition:At})}function Nt(e){let t=e.env??process.env,r=It(e);if(!F.existsSync(r))throw new n(`INVALID_ARGS`,`Remote config file not found: ${r}`);let i;try{i=F.readFileSync(r,`utf8`)}catch(e){throw new n(`INVALID_ARGS`,`Failed to read remote config file: ${r}`,{cause:e instanceof Error?e.message:String(e)})}let a;try{a=JSON.parse(i)}catch(e){throw new n(`INVALID_ARGS`,`Invalid JSON in remote config file: ${r}`,{cause:e instanceof Error?e.message:String(e)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new n(`INVALID_ARGS`,`Remote config file must contain a JSON object: ${r}`);let o={},s=a,c=I.dirname(r);for(let[e,i]of Object.entries(s)){let a=Ne(e);if(!a)throw new n(`INVALID_ARGS`,`Unsupported remote config key "${e}" in remote config file ${r}.`);let s=p(a,i,`remote config file ${r}`,e);o[a.key]=typeof s==`string`&&`path`in a&&a.path?k(s,{cwd:c,env:t}):s}return{resolvedPath:r,profile:o}}function Pt(e=process.env){let t={};for(let n of Pe){let r=Fe(n.key).map(t=>({name:t,value:e[t]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);r&&(t[n.key]=p(n,r.value,`environment variable ${r.name}`,r.name))}return t}function Ft(...e){let t={};for(let n of e)if(n)for(let e of Pe){let r=n[e.key];r!==void 0&&(t[e.key]=r)}return t}function It(e){let t=e.env??process.env;return k(e.configPath,{cwd:e.cwd,env:t})}function H(e){let t=Nt(e);return{resolvedPath:t.resolvedPath,profile:Ft(Pt(e.env),t.profile)}}function Lt(e){return e===`android-instance`||e===`ios-instance`}function Rt(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function zt(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function Bt(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!zt(e)}function Vt(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 Ht(e){let t=e?.metroPublicBaseUrl?.trim();return t?Vt(t):null}function Ut(e,t={}){if(!Bt(e)||!t.flags?.metroProxyBaseUrl||!Lt(t.flags.leaseBackend))return e;let r=Ht(t.flags);if(!r)throw new n(`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[...e,`--url`,r]}async function Wt(e,t={}){return(await m(`npm`,Rt(Ut(e,t)),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function U(e){let t=Xt(e);if(!F.existsSync(t))return null;let n;try{n=JSON.parse(F.readFileSync(t,`utf8`))}catch(t){return an(e,t),null}return sn(n)?n:(an(e),null)}function Gt(e){let t=Xt({stateDir:e.stateDir,session:e.state.session});F.mkdirSync(I.dirname(t),{recursive:!0}),nn(t,e.state),nn(Zt(e.stateDir),{session:e.state.session})}function Kt(e){return{baseUrl:rn(e.daemonBaseUrl),authToken:e.daemonAuthToken,transport:e.daemonTransport,serverMode:e.daemonServerMode}}function qt(e){F.rmSync(Xt(e),{force:!0});let t=Zt(e.stateDir);$t(e.stateDir)===e.session&&F.rmSync(t,{force:!0})}function Jt(e){let t=e.validateRemoteConfigHash??!0,r=e.remoteConfig?It({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,i=U(e)??(e.allowActiveFallback?Qt({stateDir:e.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(t&&W(i.remoteConfigPath)!==i.remoteConfigHash)throw new n(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=tn(i,e),o=te(i);return{runtime:i.runtime,connection:C(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:i.daemon?.authToken??a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...S(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function Yt(e){return C(te(e))}function W(e){try{return P.createHash(`sha256`).update(F.readFileSync(e)).digest(`hex`)}catch(t){throw new n(`INVALID_ARGS`,`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function Xt(e){return I.join(e.stateDir,`remote-connections`,`${on(e.session)}.json`)}function Zt(e){return I.join(e,`remote-connections`,`.active-session.json`)}function Qt(e){let t=$t(e.stateDir);return t?U({stateDir:e.stateDir,session:t}):null}function $t(e){let t=Zt(e);if(F.existsSync(t))try{let e=JSON.parse(F.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function en(e){if(e)return P.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function tn(e,t){try{return H({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function nn(e,t){F.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:`utf8`,mode:384}),F.chmodSync(e,384)}function rn(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of[...t.searchParams.keys()])/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function an(e,t){h({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),qt(e)}function on(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${P.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function sn(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&cn(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ln(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&un(t.daemon)}function cn(e,t){return t.every(t=>typeof e[t]==`string`)}function ln(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function un(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:dn(e)}function dn(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 fn=Ie.map(e=>e.key);function pn(e){let t={};for(let n of fn){let r=e[n];r!==void 0&&(t[n]=r)}return t}function mn(e){return e.remoteConfig?{...pn(H({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function hn(e){return e===`cloud`||e===`proxy`||De(e)}function gn(e){return De(e)}function _n(){return[`cloud`,`proxy`,j.browserStack,j.awsDeviceFarm].join(`, `)}function vn(e){return!gn(e)}function yn(e){return e===`proxy`?`proxy`:gn(e)?`direct-device-provider`:`remote-provider`}const G=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),bn=new Set([`open`]),xn=new Set([w.open,w.install,w.reinstall,D.installSource]);async function Sn(e){let{command:t,flags:r,client:i}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=O(r.stateDir).baseDir,o=H({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...pn(o.profile),...r,remoteConfig:o.resolvedPath},c=U({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new n(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??Gn(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=Wn(l.runtime,u.platform)??e.runtime,f=l,p=!c,m,h=An(f);if(h.shouldAllocate(t)){let e=await Dn({command:t,client:i,state:l,nextState:f,nextFlags:u,policy:h});f=e.state,p||=e.changed,m=e.acquiredLeaseForCleanup}let g=await Cn({command:t,flags:u,client:i,state:l,nextState:f,runtime:d,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return f=g.state,d=g.runtime,p||=g.changed,await En({changed:p,stateDir:a,state:f,client:i,acquiredLeaseForCleanup:m,preparedMetroCleanupOnFailure:g.preparedMetroCleanupOnFailure,metroCleanupToStop:g.metroCleanupToStop}),{flags:{...u,session:f.session,leaseId:f.leaseId,leaseBackend:f.leaseBackend,platform:f.platform??u.platform,target:f.target??u.target},runtime:d,connection:Yt(f)}}async function Cn(e){let{command:t,flags:r,state:i,client:a}=e,o=wn(e.nextState,r),s=e.runtime;if(!Bn(t,r,e.batchSteps,e.positionals)||!Vn(r)||!Tn(e.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new n(`INVALID_ARGS`,`${t} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Pn(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Un(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?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function wn(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Tn(e,t,n){return e===!0||!t||!Hn(t,n)}async function En(e){if(e.changed)try{Gt({stateDir:e.stateDir,state:e.state})}catch(t){throw await K(e.preparedMetroCleanupOnFailure),await Rn(e.client,e.state,e.acquiredLeaseForCleanup),t}await K(e.metroCleanupToStop)}async function Dn(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&&Jn(i,c.device);let l=s.leaseBackend??o??zn(i,t);Qn(r,i,l);let u=await Kn(n,s,l,a,i),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,On(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:kn(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function On(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function kn(e,t,n,r){return{...e,leaseId:t.leaseId,leaseBackend:n,leaseProvider:t.leaseProvider??e.leaseProvider,clientId:t.clientId??e.clientId,deviceKey:t.deviceKey??e.deviceKey,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function An(e){return e.leaseProvider===`proxy`?Mn:De(e.leaseProvider)?Nn:jn}const jn={shouldAllocate:e=>!G.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Mn={shouldAllocate:e=>e!==`devices`&&!G.has(e),ttlMs:()=>3e5,resolveLeaseState:qn},Nn={shouldAllocate:e=>!G.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Pn(e,t,r,i,a){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if(e.platform!==`ios`&&e.platform!==`android`)throw new n(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new n(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:_e(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:a,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:e.metroNoReuseExisting?!1:void 0,installDependenciesIfNeeded:e.metroNoInstallDeps?!1:void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:e.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function K(e){if(e)try{await Ee(e)}catch{}}async function Fn(e){try{await Mt({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function In(e,t){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:t.daemon?.authToken,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}async function Ln(e,t){if(t.leaseId)try{await In(e,t)}catch{}}async function Rn(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`}function zn(e,t){let r=q(e);if(r)return r;throw new n(`INVALID_ARGS`,`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}function Bn(e,t,n,r=[]){return e===`cdp`?Bt(r)&&!!t.metroPublicBaseUrl:bn.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return bn.has(t)&&e.runtime===void 0})}function Vn(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Hn(e,t){return!e.platform||!t||t!==`ios`&&t!==`android`?!0:e.platform===t}function Un(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Wn(e,t){if(e)return Hn(e,t)?e:void 0}function Gn(e,t,r={}){if(!e.tenant)throw new n(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new n(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&vn(r.leaseProvider))throw new n(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:e.session??`default`,remoteConfigPath:t,remoteConfigHash:W(t),daemon:Kt(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??q(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.target,connectedAt:i,updatedAt:i}}async function Kn(e,t,n,r,i){if(t.leaseId&&t.leaseBackend===n){let i=await $n(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function qn(e){if(!xn.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new n(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let t=await Yn(e.client,e.flags),r=Xn(t);return{state:{...e.state,deviceKey:r,leaseBackend:e.state.leaseBackend??e.leaseBackend??Zn(t),platform:e.state.platform??t.platform,target:e.state.target??t.target,updatedAt:new Date().toISOString()},device:t}}function Jn(e,t){if(e.platform=t.platform,e.target=t.target??e.target,o(t)){e.udid=t.id;return}t.platform===`android`&&(e.serial=t.id)}async function Yn(e,n){return await t((await e.devices.list({platform:n.platform,target:n.target,device:n.device,udid:n.udid,serial:n.serial,iosSimulatorDeviceSet:n.iosSimulatorDeviceSet,androidDeviceAllowlist:n.androidDeviceAllowlist})).map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:n.platform,target:n.target,deviceName:n.device,udid:n.udid,serial:n.serial})}function Xn(e){return`${a(e)}:${e.target??`mobile`}:${e.id}`}function Zn(e){if(o(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`}function Qn(e,t,r){if(e.leaseBackend&&e.leaseBackend!==r)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:e.session,leaseBackend:e.leaseBackend});if(e.platform&&t.platform&&e.platform!==t.platform)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:e.session,platform:e.platform});if(e.target&&t.target&&e.target!==t.target)throw new n(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:e.session,target:e.target})}async function $n(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){if(er(e))return;throw e}}function er(e){return!(e instanceof n)||e.code!==`UNAUTHORIZED`?!1:e.details?.reason===`LEASE_NOT_FOUND`||e.details?.reason===`LEASE_EXPIRED`||e.details?.reason===`LEASE_REVOKED`}function tr(e){return Te(e)}async function nr(e,t){let r=await e.text(),i={};if(r.trim().length>0)try{i=JSON.parse(r)}catch(r){throw new n(`COMMAND_FAILED`,t.invalidJsonMessage,{status:e.status},r instanceof Error?r:void 0)}if(!e.ok)throw new n(`UNAUTHORIZED`,t.rejectedMessage,{status:e.status,response:i});return i}const rr=1e3;async function ir(e){return await ar({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:e.command===`connect`&&!e.flags.noLogin,env:e.env})}async function ar(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:`none`};if(Y(e.flags.daemonAuthToken))return{flags:e.flags,source:`flag`};if(Y(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:`env`};if(!Sr(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:`none`};let r=await pr({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:`cli-session`};if(!e.allowInteractiveLogin)throw e.flags.noLogin?new n(`UNAUTHORIZED`,`Remote daemon authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`}):xr(e.command,t);let i=await sr({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:i.accessToken},source:`login`}}async function or(e){let t=e.env??e.io?.env??process.env;if(Y(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:J(t)};if(Y(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:J(t)};let r=await pr({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(e.flags.noLogin)throw new n(`UNAUTHORIZED`,`Cloud connection profile authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`});let i=await sr({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:`agent-device connect`});return{accessToken:i.accessToken,cloudBaseUrl:i.session.cloudBaseUrl}}async function sr(e){let t=e.env??e.io?.env??process.env,r=vr(t,e.io);if(r===`non-interactive`)throw xr(e.commandLabel??`agent-device connect`,t);let i=J(t),a=await gr({baseUrl:i,pathName:`/api/control-plane/device-auth/start`,body:{client:`agent-device`,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});_r(a);let o=a.verificationUriComplete??a.verificationUri,s=r===`local-browser`?a.verificationUri:Cr(a.verificationUri,a.userCode);r===`local-browser`?(Tr(e.io,`Opening ${a.verificationUri}...\n`),await wr(o,e.io)):Tr(e.io,`Open this URL on your machine:\n${s}\n\nWaiting for approval for 10 minutes...\n`);let c=await hr({cloudBaseUrl:i,deviceCode:a.deviceCode,expiresIn:a.expiresIn,interval:a.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),l=c.cliSession?.refreshCredential??c.cliSession?.refreshToken;if(!Y(c.accessToken)||!Y(l))throw new n(`UNAUTHORIZED`,`Device authorization did not return CLI credentials.`);let u=new Date(e.io?.now?.()??Date.now()).toISOString(),d={version:1,id:c.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:i,workspaceId:c.cliSession?.workspaceId,accountId:c.cliSession?.accountId,name:c.cliSession?.name,refreshCredential:l,createdAt:u,expiresAt:c.cliSession?.expiresAt};return lr({stateDir:e.stateDir,session:d}),{accessToken:c.accessToken,expiresAt:c.expiresAt,session:d}}function cr(e){let t=dr(e.stateDir);if(!F.existsSync(t))return null;try{let e=JSON.parse(F.readFileSync(t,`utf8`));return e.version!==1||!Y(e.id)||!Y(e.cloudBaseUrl)||!Y(e.refreshCredential)||!Y(e.createdAt)?null:e}catch{return null}}function lr(e){let t=dr(e.stateDir);F.mkdirSync(I.dirname(t),{recursive:!0,mode:448}),F.writeFileSync(t,`${JSON.stringify(e.session,null,2)}\n`,{mode:384});try{F.chmodSync(t,384)}catch{}}function ur(e){let t=dr(e.stateDir);return F.existsSync(t)?(F.rmSync(t,{force:!0}),!0):!1}function dr(e){return I.join(e,`auth`,`cli-session.json`)}function fr(e){let t=cr({stateDir:e.stateDir});return t?{authenticated:!0,source:`cli-session`,sessionId:t.id,cloudBaseUrl:t.cloudBaseUrl,workspaceId:t.workspaceId,accountId:t.accountId,name:t.name,createdAt:t.createdAt,expiresAt:t.expiresAt,expired:Er(t.expiresAt,e.now)}:{authenticated:!1,source:`none`}}async function pr(e){let t=cr({stateDir:e.stateDir});return!t||Er(t.expiresAt,e.io?.now)?null:{accessToken:(await mr({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:J(e.env,t.cloudBaseUrl)}}async function mr(e){let t=await gr({baseUrl:J(e.env,e.session.cloudBaseUrl),pathName:`/api/control-plane/cli-session/refresh`,body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(Y(t.accessToken))return{accessToken:t.accessToken,expiresAt:t.expiresAt};throw t.status===`revoked`||t.error===`revoked`?new n(`UNAUTHORIZED`,`Stored cloud CLI session was revoked.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:t.status,error:t.error}):new n(`UNAUTHORIZED`,`Failed to refresh CLI session.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:t.status,error:t.error})}async function hr(e){let t=e.now??Date.now,r=Math.min((e.expiresIn??600)*1e3,6e5),i=t()+r,a=Math.max(rr,(e.interval??5e3/1e3)*1e3);for(;t()<i;){let t=await gr({baseUrl:e.cloudBaseUrl,pathName:`/api/control-plane/device-auth/poll`,body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if(t.status===`approved`||Y(t.accessToken))return t;if(t.status===`slow_down`||t.error===`slow_down`)a+=rr;else if(t.status!==`authorization_pending`&&t.error!==`authorization_pending`)throw new n(`UNAUTHORIZED`,`Device authorization was not approved.`,{status:t.status,error:t.error});await Dr(a)}throw new n(`TIMEOUT`,`Device authorization expired before approval.`)}async function gr(e){let t=await(e.fetchImpl??fetch)(new URL(e.pathName,e.baseUrl),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await nr(t,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud auth endpoint rejected the request.`})}function _r(e){if(!Y(e.deviceCode)||!Y(e.userCode)||!Y(e.verificationUri))throw new n(`COMMAND_FAILED`,`Cloud auth start returned an unusable response.`)}function vr(e,t){let n=t?.stdinIsTTY??process.stdin.isTTY,r=t?.stdoutIsTTY??process.stdout.isTTY;return yr(e)||!n||!r?`non-interactive`:br(e)?`device-code`:`local-browser`}function yr(e){return e.CI===`true`||e.GITHUB_ACTIONS===`true`||e.BUILDKITE===`true`}function br(e){return!!(e.SSH_TTY||e.SSH_CONNECTION||e.CODESPACES===`true`||e.GITPOD_WORKSPACE_ID||e.REMOTE_CONTAINERS===`true`)}function xr(e,t){let r=J(t);return new n(`UNAUTHORIZED`,`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL(`/api-keys`,r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function J(e,t){let r=e.AGENT_DEVICE_CLOUD_BASE_URL??t??`https://cloud.agent-device.dev`;try{return new URL(r).toString().replace(/\/+$/,``)}catch(e){throw new n(`INVALID_ARGS`,`Invalid AGENT_DEVICE_CLOUD_BASE_URL.`,{cloudBaseUrl:r},e instanceof Error?e:void 0)}}function Sr(e,t){if(t.AGENT_DEVICE_CLOUD_AUTH===`1`||t.AGENT_DEVICE_CLOUD_AUTH===`true`||Y(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return t===`agent-device.dev`||t.endsWith(`.agent-device.dev`)}catch{return!1}}function Cr(e,t){let n=new URL(e);return n.searchParams.set(`user_code`,t),n.toString()}async function wr(e,t){if(t?.openBrowser){await t.openBrowser(e);return}let n=process.platform;try{n===`darwin`?await g(`open`,[e],{allowFailure:!0,timeoutMs:5e3}):n===`win32`?await g(`cmd`,[`/c`,`start`,``,e],{allowFailure:!0,timeoutMs:5e3}):await g(`xdg-open`,[e],{allowFailure:!0,timeoutMs:5e3})}catch{Tr(t,`Open this URL on your machine:\n${e}\n`)}}function Tr(e,t){(e?.stderr??process.stderr).write(t)}function Er(e,t){if(!e)return!1;let n=Date.parse(e);return Number.isFinite(n)?n<=(t?.()??Date.now()):!0}function Y(e){return typeof e==`string`&&e.trim().length>0}async function Dr(e){await new Promise(t=>setTimeout(t,e))}const Or=new Set([`daemonAuthToken`,`metroBearerToken`]);function kr(e){let t=Pr(Mr(e.profile)),n=I.join(e.stateDir,`remote-connections`,`generated`);F.mkdirSync(n,{recursive:!0,mode:448});let r=I.join(n,`${Fr(e.provider)}-${Nr(t)}.json`);F.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{F.chmodSync(r,384)}catch{}return r}function Ar(e){try{return H(e)}catch(t){let i=r(t);throw new n(`COMMAND_FAILED`,`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:i.message},i)}}function jr(e){let t=Ar({configPath:kr({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Ir(e.provider)});return{flags:{...pn(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function Mr(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!Or.has(e)))}function Nr(e){return P.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function Pr(e){return Array.isArray(e)?e.map(Pr):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Pr(t)])):e}function Fr(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Ir(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}async function Lr(e){let t=await or({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await Rr({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=Vr({stateDir:e.stateDir,cloudBaseUrl:t.cloudBaseUrl,daemonBaseUrl:typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,session:e.flags.session});return jr({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function Rr(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return zr(await nr(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function zr(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let t=e.connection;if(!t||typeof t!=`object`)throw new n(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(t.remoteConfigProfile!==void 0)return Br(t.remoteConfigProfile);throw new n(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Br(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new n(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new n(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function Vr(e){return P.createHash(`sha256`).update(`${e.stateDir}\0${e.cloudBaseUrl}\0${e.daemonBaseUrl}\0${e.session??``}`).digest(`hex`).slice(0,16)}function Hr(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}}function Ur(e){let t=Gr(e.provider)(e),n=Qr(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??q(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...Hr(e.flags)};return jr({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const Wr=[{provider:j.browserStack,buildProfileFields:Kr},{provider:j.awsDeviceFarm,buildProfileFields:qr}];function Gr(e){let t=Wr.find(t=>t.provider===e)?.buildProfileFields;if(t)return t;throw new n(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Kr(e){return Yr(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),Yr(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:Jr(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:X(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:X(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:X(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName}}function qr(e){let{env:t,flags:n}=e;return{platform:Jr(n.platform,`connect aws-device-farm requires --platform ios|android.`),device:n.device,awsProjectArn:Xr(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`),awsDeviceArn:Xr(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:Zr(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:Zr(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`]),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function Jr(e,t){if(e===`android`||e===`ios`)return e;throw new n(`INVALID_ARGS`,t)}function X(e,t){if(e)return e;throw new n(`INVALID_ARGS`,t)}function Yr(e,t,r){let i=e?.[t];if(i)return i;throw new n(`INVALID_ARGS`,`${r} requires ${t} in the environment.`)}function Xr(e,t,n,r){return X(Zr(e,t,n),r)}function Zr(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function Qr(e,t,n,r){return P.createHash(`sha256`).update(`${e}\0${t}\0${n??``}\0${r??``}`).digest(`hex`).slice(0,16)}function $r(e){let t=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!t)throw new n(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=ei(e.stateDir,t,e.flags.session),i={daemonBaseUrl:t,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??q(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...Hr(e.flags)};return jr({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:t,daemonTransport:e.flags.daemonTransport??`http`}})}function ei(e,t,n){return P.createHash(`sha256`).update(`${e}\0${t}\0${n??``}`).digest(`hex`).slice(0,16)}const ti=async({positionals:e,flags:t,client:n})=>{let r=O(t.stateDir).baseDir,i=xi(e);ri(i,t);let a=await ni({provider:i,flags:t,stateDir:r}),o=a.flags,s=pi(a.remoteConfigPath),c=ii(o,s),l=ai({stateDir:r,flags:o,remoteConfigPath:a.remoteConfigPath});oi(l.previous,{flags:o,session:l.session,remoteConfigPath:a.remoteConfigPath,remoteConfigHash:l.remoteConfigHash,desiredLeaseBackend:q(o),connection:s,daemon:l.daemon});let u=si({flags:o,scope:c,connectionMetadata:s,context:l,remoteConfigPath:a.remoteConfigPath});Gt({stateDir:r,state:u}),await di(n,r,o,l.previous);let d=Ni(u),f=ji(o,u);return M(o,Ii(u,f),()=>[`Connected remote session "${l.session}" tenant "${c.tenant}" run "${c.runId}" ${u.leaseId?`lease ${u.leaseId}`:`lease pending`}`,d?.message,f?.message].filter(e=>!!e).join(`
|
|
2
|
+
`)),!0};async function ni(e){let{provider:t,flags:n,stateDir:r}=e;return n.remoteConfig?fi(n):gn(t)?Ur({provider:t,flags:n,stateDir:r,cwd:process.cwd(),env:process.env}):t===`proxy`||!t&&Si(n)?$r({flags:n,stateDir:r,cwd:process.cwd(),env:process.env}):await Lr({flags:n,stateDir:r,cwd:process.cwd(),env:process.env})}function ri(e,t){if(!(!e||!t.remoteConfig))throw new n(`INVALID_ARGS`,`connect provider positional and --remote-config are mutually exclusive.`)}function ii(e,t){if(!e.tenant)throw new n(`INVALID_ARGS`,`connect requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new n(`INVALID_ARGS`,`connect requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&vn(t?.leaseProvider))throw new n(`INVALID_ARGS`,`connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);return{tenant:e.tenant,runId:e.runId}}function ai(e){let{stateDir:t,flags:n,remoteConfigPath:r}=e,i=n.session?null:Qt({stateDir:t}),a=n.session??i?.session??gi(t);return{session:a,previous:i?.session===a?i:U({stateDir:t,session:a}),remoteConfigHash:W(r),daemon:Ai(n)}}function oi(e,t){if(!(!e||Ei(e,t))&&!t.flags.force)throw new n(`INVALID_ARGS`,`A different remote connection is already active for this session. Re-run connect with --force to replace it.`,{session:t.session,remoteConfig:e.remoteConfigPath})}function si(e){let{flags:t,scope:n,connectionMetadata:r,context:i,remoteConfigPath:a}=e,o=ui(t,i.previous)?i.previous:null,s=new Date().toISOString(),c=ci(t,o,r),l=li(t,o,s);return{version:1,session:i.session,remoteConfigPath:a,remoteConfigHash:i.remoteConfigHash,daemon:i.daemon,tenant:n.tenant,runId:n.runId,...c,...l,updatedAt:s}}function ci(e,t,n){return{leaseId:t?.leaseId,leaseBackend:t?.leaseBackend??q(e),leaseProvider:n?.leaseProvider??t?.leaseProvider,clientId:n?.clientId??t?.clientId,deviceKey:t?.deviceKey??n?.deviceKey}}function li(e,t,n){return{platform:e.platform??t?.platform,target:e.target??t?.target,runtime:t?.runtime,metro:t?.metro,connectedAt:t?.connectedAt??n}}function ui(e,t){return!!(t&&!e.force)}async function di(e,t,n,r){!r||!n.force||(await K(r.metro),await Fn({stateDir:t,state:r}),await Ln(e,r))}function fi(e){if(!e.remoteConfig)throw new n(`INVALID_ARGS`,`connect requires --remote-config <path>.`);return{flags:e,remoteConfigPath:H({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env}).resolvedPath}}function pi(e){let t=H({configPath:e,cwd:process.cwd(),env:process.env}).profile,n={leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey};return Object.values(n).some(e=>e!==void 0)?n:void 0}const mi=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:i}=wi(e);if(!i)return Ti(e,n),!0;let a=i.session,o;try{o=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await K(i.metro),await Fn({stateDir:r,state:i});let s=!1;if(i.leaseId)try{let e=await In(t,i);s=e.released,o??=e.provider}catch{}return qt({stateDir:r,session:a}),M(e,{connected:!1,session:a,released:s,...o?{provider:o}:{}},()=>_i(a,o)),!0},hi=async({positionals:e,flags:t})=>{if(e[0]!==`status`)throw new n(`INVALID_ARGS`,`connection accepts only: status`);let{session:r,state:i}=wi(t);if(!i)return Ti(t,r),!0;let a=Ni(i),o=Mi(i);return M(t,Ii(i,o),()=>[`Connected remote session "${i.session}".`,`tenant=${i.tenant} runId=${i.runId} leaseId=${i.leaseId??`pending`} backend=${i.leaseBackend??`pending`}`,`remoteConfig=${i.remoteConfigPath}`,i.runtime?`metro=prepared`:`metro=not-prepared`,a?.message,o?.message].filter(e=>!!e).join(`
|
|
3
|
+
`)),!0};function gi(e){for(let t=0;t<8;t+=1){let t=`adc-${P.randomBytes(3).toString(`hex`)}`;if(!U({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${P.randomBytes(2).toString(`hex`)}`}function _i(e,t){return[`Disconnected remote session "${e}".`,...vi(t),...bi(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
4
|
+
`)}function vi(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=yi(e);return t?[t]:[]})}function yi(e){if(!e||typeof e!=`object`)return;let t=e;if(!(typeof t.message!=`string`||t.message.length===0))return`Provider release warning${typeof t.code==`string`&&t.code.length>0?` (${t.code})`:``}: ${t.message}`}function bi(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function xi(e){let t=e[0];if(t!==void 0){if(e.length>1)throw new n(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(hn(t))return t;throw new n(`INVALID_ARGS`,`Unknown connect provider: ${t}. Supported providers: ${_n()}.`)}}function Si(e){return!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend?!1:Ci(e.daemonBaseUrl)}function Ci(e){try{return new URL(e).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function wi(e){let t=e.session??`default`,n=O(e.stateDir).baseDir;return{session:t,stateDir:n,state:U({stateDir:n,session:t})??(e.session?null:Qt({stateDir:n}))}}function Ti(e,t){M(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function Ei(e,t){return Di(e,t)&&Oi(e,t)&&ki(e.daemon,t.daemon)}function Di(e,t){return[[e.remoteConfigPath,t.remoteConfigPath],[e.remoteConfigHash,t.remoteConfigHash],[e.session,t.session],[e.tenant,t.flags.tenant],[e.runId,t.flags.runId]].every(([e,t])=>e===t)}function Oi(e,t){return[[e.leaseBackend,t.desiredLeaseBackend],[e.platform,t.flags.platform],[e.target,t.flags.target],[e.leaseProvider,t.connection?.leaseProvider],[e.clientId,t.connection?.clientId]].every(([e,t])=>t===void 0||e===t)}function ki(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function Ai(e){return Kt(e)}function ji(e,t){if(!t.runtime&&!(!Vn(e)&&!Fi(t.remoteConfigPath)))return Pi(t.remoteConfigPath)}function Mi(e){if(!(e.runtime||!Fi(e.remoteConfigPath)))return Pi(e.remoteConfigPath)}function Ni(e){if(e.leaseId)return;let t=yn(e.leaseProvider);return t===`proxy`?{status:`deferred`,nextSteps:[`agent-device open <app-id> --relaunch`,`agent-device devices`],message:`Proxy lease allocation is pending; run open when ready to allocate or refresh the device lease. Devices can inspect inventory but do not allocate a proxy lease.`}:t===`direct-device-provider`?{status:`deferred`,nextSteps:[`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device artifacts --json`,`agent-device close`],message:`Hosted ${e.leaseProvider} lease allocation is pending; run open when ready to create the provider session. After close, run "agent-device artifacts --json" to fetch provider video/log links when available.`}:{status:`deferred`,nextSteps:[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`],message:`Lease allocation is pending; run install-from-source, open, snapshot, or devices when ready to allocate or refresh the lease.`+(e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``)}}function Pi(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function Fi(e){try{let t=H({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function Ii(e,t){let n=Ni(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:en(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...n?{leasePreparation:n}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}const Li=async({positionals:e,flags:t})=>{let r=e[0]??`status`,i=O(t.stateDir).baseDir;if(r===`status`){let e=fr({stateDir:i});return M(t,e,()=>Ri(e)),!0}if(r===`login`){let e=await sr({stateDir:i,flags:t,commandLabel:`agent-device auth login`});return M(t,{authenticated:!0,source:`cli-session`,sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>`Authenticated with cloud CLI session.`),!0}if(r===`logout`){let e=ur({stateDir:i});return M(t,{authenticated:!1,removed:e},()=>e?`Removed stored cloud CLI session.`:`No stored cloud CLI session.`),!0}throw new n(`INVALID_ARGS`,`auth accepts only: status, login, logout`)};function Ri(e){return e.authenticated?[`Authenticated with cloud CLI session.`,`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?`status=expired`:null].filter(e=>!!e).join(`
|
|
5
|
+
`):`Not authenticated.`}const zi=`${ce}/`,Bi=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`],Vi=[`content-type`,`content-disposition`,`x-request-id`];function Hi(e){let t=ea(e);return We.createServer((e,n)=>{Ui(e,n,t).catch(e=>{_a(n,e)})})}async function Ui(e,t,n){let r=ra(e.url??`/`);if(e.method===`GET`&&r===`/health`){await Wi(t,n);return}if(!ia(r,e.method)){t.statusCode=404,t.end(`Not found`);return}let i;if(r===`/rpc`&&(i=(await de(e,n.maxRpcBodyBytes,`Proxy request body is too large.`)).toString(`utf8`)),!ua(e,n.clientToken,i)){ga(t,r,ma(i));return}await Ki({req:e,res:t,route:r,options:n,rpcBody:i})}async function Wi(e,t){let n=await Gi(t);e.statusCode=200,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify(fe(`agent-device-proxy`,{upstream:n})))}async function Gi(e){let t=new URL(oe(e.upstreamBaseUrl,`health`)),n=await e.fetchImpl(t,{method:`GET`,headers:ca({headers:{}},e.upstreamToken,`/health`),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function Ki(e){let{req:t,res:n,route:r,options:i,rpcBody:a}=e,o=sa(i.upstreamBaseUrl,r,t.url??`/`),s=t.method??`GET`,c=ca(t,i.upstreamToken,r),l=la(t,r,a,i.upstreamToken);await qi({req:t,res:n,route:r,response:await i.fetchImpl(o,{method:s,headers:c,signal:AbortSignal.timeout(i.upstreamTimeoutMs),...l?{body:l,duplex:`half`}:{}}),clientToken:i.clientToken})}async function qi(e){let{req:t,res:n,route:r,response:i,clientToken:a}=e;if(n.statusCode=i.status,Ji(i,n),Yi(t,n),oa(r)){await Xi({req:t,res:n,response:i,clientToken:a});return}await $i(i,n)}function Ji(e,t){for(let n of Vi){let r=e.headers.get(n);r&&t.setHeader(n,r)}}function Yi(e,t){t.hasHeader(`x-request-id`)||t.setHeader(`x-request-id`,ha(e))}async function Xi(e){let{req:t,res:n,response:r,clientToken:i}=e,a=await r.text();n.setHeader(`content-type`,r.headers.get(`content-type`)??`application/json`),n.end(Zi(a,t,i))}function Zi(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let i=r;if(!i.upload||typeof i.upload.url!=`string`)return e;let a=Qi(i.upload.url,t);if(!a)return e;let o=i.upload.headers&&typeof i.upload.headers==`object`?{...i.upload.headers}:{};return Object.assign(o,ue(n)),JSON.stringify({...r,upload:{...i.upload,url:a,headers:o}})}function Qi(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=typeof t.headers.host==`string`?t.headers.host:``;if(!r)return null;let i=new URL(t.url??`/`,`http://127.0.0.1`).pathname,a=i.lastIndexOf(`/upload/preflight`),o=a>=0?i.slice(0,a):``,s=t.headers[`x-forwarded-proto`],c=Array.isArray(s)?s[0]:s,l=new URL(`${c||`http`}://${r}`);return l.pathname=`${o}${n.pathname}`,l.search=n.search,l.toString()}async function $i(e,t){if(!e.body){t.end();return}await Ge(Ke.fromWeb(e.body),t)}function ea(e){return{upstreamBaseUrl:ta(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:na(e.upstreamToken,`upstreamToken`),clientToken:na(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,fetchImpl:e.fetchImpl??fetch}}function ta(e,t){try{let t=new URL(e);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`unsupported protocol`);return t.toString().replace(/\/+$/,``)}catch(r){throw new n(`INVALID_ARGS`,`Invalid ${t}`,{[t]:e},r)}}function na(e,t){let r=e.trim();if(!r)throw new n(`INVALID_ARGS`,`Proxy ${t} is required.`);return r}function ra(e){let t=new URL(e,`http://127.0.0.1`).pathname;return t===`/agent-device`?`/`:t.startsWith(zi)?`/${t.slice(zi.length)}`:t}function ia(e,t){return e===`/rpc`?t===`POST`:aa(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)?t===`GET`:!1}function aa(e,t){return e===`/upload`||oa(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function oa(e){return e===`/upload/preflight`}function sa(e,t,n){let r=new URL(oe(e,t)),i=n.indexOf(`?`);return i>=0&&(r.search=n.slice(i)),r}function ca(e,t,n){let r=new Headers;for(let t of Bi){let n=e.headers[t];typeof n==`string`&&n.trim()&&r.set(t,n)}n===`/rpc`&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);for(let[e,n]of Object.entries(ue(t)))r.set(e,n);return r}function la(e,t,n,r){if(!(e.method===`GET`||e.method===`HEAD`))return t===`/rpc`?fa(n??``,r):e}function ua(e,t,n){let r=da(e,n);return r.length>0&&Oe(r,t)}function da(e,t){let n=typeof e.headers.authorization==`string`?e.headers.authorization:``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers[`x-agent-device-token`];if(typeof r==`string`)return r;if(t){let e=pa(t);if(e)return e}return``}function fa(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function pa(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function ma(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function ha(e){let t=e.headers[`x-request-id`];return typeof t==`string`&&t.trim()?t.trim().slice(0,128):Ue()}function ga(t,r,i){if(t.statusCode=401,t.setHeader(`content-type`,`application/json`),r===`/rpc`){t.end(JSON.stringify({jsonrpc:`2.0`,id:i,error:{code:-32001,message:`Invalid proxy token`,data:e(new n(`UNAUTHORIZED`,`Invalid proxy token`))}}));return}t.end(JSON.stringify({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`}))}function _a(t,n){if(t.headersSent){t.destroy(n instanceof Error?n:void 0);return}let r=e(n);t.statusCode=r.code===`INVALID_ARGS`?400:500,t.setHeader(`content-type`,`application/json`),t.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}const va=async({positionals:e,flags:t})=>{if(e.length>0)throw new n(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await ya(t);return M(t,r,()=>wa(r)),await Ta(),!0};async function ya(e){let t=re({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:e.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await ae(t),i=ba(r.info.httpPort),a=xa(e),o=Hi({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:a});await Sa(o,e.proxyHost?.trim()||`127.0.0.1`,e.proxyPort??0);let s=o.address();if(!s||typeof s==`string`)throw new n(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let c=`http://${Ca(s.address)}:${s.port}`;return{proxyBaseUrl:c,agentDeviceBaseUrl:ie(c),token:a,upstreamBaseUrl:i,stateDir:t.paths.baseDir}}function ba(e){if(!e)throw new n(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${e}`}function xa(e){return e.daemonAuthToken?.trim()||He(32).toString(`hex`)}function Sa(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function Ca(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function wa(e,t={}){let n=t.useColor??ne(),r=Z(`✓`,`green`,n),i=Z(e.proxyBaseUrl,`cyan`,n),a=Z(`<tunnel URL>`,`cyan`,n),o=Z(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
|
|
6
|
+
`)}function Z(e,t,n){return n?E(e,t,{validateStream:!1}):e}function Ta(){return new Promise(()=>{})}const Ea=new Set([`id`,`text`,`label`]),Da=new Set([`enabled`,`selected`]);function Oa(e){let t=Be(e);return ka(t.actions,{actionLines:t.actionLines,metadata:Ve(e)})}function ka(e,t={}){let r={config:Aa(t.metadata),warnings:[],unsupported:[]},i=[];for(let[n,a]of e.entries()){let e=t.actionLines?.[n]??n+1,o=Ma(a);switch(o.kind){case`commands`:i.push(...o.commands),lo(r,o.warnings,a,e);break;case`config`:so(r,o.appId,a,e),i.push(...o.commands),lo(r,o.warnings,a,e);break;case`unsupported`:r.unsupported.push({line:e,action:mo(a),message:o.message});break}}if(r.unsupported.length>0)throw new n(`INVALID_ARGS`,`Cannot export replay to Maestro YAML: unsupported .ad action ${po(r.unsupported)}.`,{unsupported:r.unsupported});return{yaml:fo(r.config,i),warnings:r.warnings}}function Aa(e){return e?.env&&Object.keys(e.env).length>0?{env:e.env}:{}}const ja={open:Na,click:Ia,press:Ia,longpress:La,fill:Va,type:Ha,keyboard:Ua,back:()=>({kind:`commands`,commands:[`back`]}),wait:Wa,find:Ga,screenshot:Ka,scroll:qa,swipe:Ja};function Ma(e){return ja[e.command]?.(e)??{kind:`unsupported`,message:`${e.command} has no Maestro equivalent`}}function Na(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`open requires an app id or URL`};if(ho(t))return{kind:`commands`,commands:[{openLink:t}]};let r=Pa(e,t);return n&&ho(n)?{kind:`config`,appId:t,commands:[r,{openLink:n}]}:n?{kind:`unsupported`,message:`open with a non-URL second argument is unsupported`}:{kind:`config`,appId:t,commands:[r]}}function Pa(e,t){let n=Fa(e);return n?{launchApp:{appId:t,...n}}:`launchApp`}function Fa(e){let t=e.flags?.launchArgs,n={};return e.flags?.relaunch===!0&&(n.stopApp=!0),e.flags?.clearAppState===!0&&(n.clearState=!0),Array.isArray(t)&&t.length>0&&(n.launchArguments=t),Object.keys(n).length>0?n:void 0}function Ia(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`${e.command} requires a target`};let r=Qa(t,n);if(!r)return{kind:`unsupported`,message:`tap target is not Maestro-compatible`};let i=ro(e);return i.ok?e.flags?.doubleTap===!0?{kind:`commands`,commands:[{doubleTapOn:r}],warnings:Ba(e,`doubleTapOn`)}:typeof e.flags?.holdMs==`number`?{kind:`commands`,commands:[{longPressOn:r}],warnings:[za(e.flags.holdMs),...Ba(e,`longPressOn`)]}:{kind:`commands`,commands:[oo(r,i.options)]}:{kind:`unsupported`,message:i.message}}function La(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`longpress requires a target`};let r=Qa(t,n);return r?{kind:`commands`,commands:[{longPressOn:r}],warnings:Ra(e).map(za)}:{kind:`unsupported`,message:`longpress target is not Maestro-compatible`}}function Ra(e){let[t,n,r]=e.positionals,i=Q(t)&&Q(n)?r:n;return i&&Q(i)?[Number(i)]:[]}function za(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function Ba(e,t){let n=[];return typeof e.flags?.count==`number`&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function Va(e){let[t,n]=e.positionals;if(!t||n===void 0)return{kind:`unsupported`,message:`fill requires a target and text`};let r=Qa(t);return r?{kind:`commands`,commands:[{tapOn:r},{inputText:n}],warnings:[`fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents`]}:{kind:`unsupported`,message:`fill target is not Maestro-compatible`}}function Ha(e){let[t]=e.positionals;if(t===void 0)return{kind:`unsupported`,message:`type requires text`};let n=co(t);return n===null?{kind:`commands`,commands:[{inputText:t}]}:{kind:`commands`,commands:[{eraseText:n}]}}function Ua(e){let[t]=e.positionals;return t===`dismiss`?{kind:`commands`,commands:[`hideKeyboard`]}:t===`enter`||t===`return`?{kind:`commands`,commands:[{pressKey:`Enter`}]}:{kind:`unsupported`,message:`keyboard ${t??``}`.trim()}}function Wa(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`wait requires a target or duration`};if(Q(t))return{kind:`commands`,commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:[`wait <ms> exports as waitForAnimationToEnd and may return before the full duration`]};if(t===`text`&&n)return{kind:`commands`,commands:[{extendedWaitUntil:{visible:n,timeout:uo(e,17e3)}}]};let r=$a(t);return r?{kind:`commands`,commands:[{extendedWaitUntil:{visible:r,timeout:uo(e,17e3)}}]}:{kind:`unsupported`,message:`wait selector is not Maestro-compatible`}}function Ga(e){let[t,n,r]=e.positionals;return t!==`text`||!n||!r?{kind:`unsupported`,message:`only find text <query> exists|missing exports to Maestro`}:r===`exists`?{kind:`commands`,commands:[{assertVisible:n}]}:r===`missing`||r===`not-exists`?{kind:`commands`,commands:[{assertNotVisible:n}]}:{kind:`unsupported`,message:`find text assertion "${r}" is unsupported`}}function Ka(e){let[t]=e.positionals;return t?{kind:`commands`,commands:[{takeScreenshot:t}]}:{kind:`unsupported`,message:`screenshot requires an output path`}}function qa(e){let[t]=e.positionals;return!t||t===`down`?{kind:`commands`,commands:[`scroll`]}:{kind:`unsupported`,message:`scroll ${t} is not exported yet`}}function Ja(e){let t=Ya(e);if(!t)return{kind:`unsupported`,message:`only coordinate swipe exports to Maestro`};let n=Xa(e);if(n===null)return{kind:`unsupported`,message:`swipe count must be a positive integer`};let r=Za(e);return r?{kind:`unsupported`,message:r}:{kind:`commands`,commands:Array.from({length:n},()=>({swipe:t}))}}function Ya(e){let[t,n,r,i,a]=e.positionals;if(!(!Q(t)||!Q(n)||!Q(r)||!Q(i)))return{start:N(t,n),end:N(r,i),...a&&Q(a)?{duration:Number(a)}:{}}}function Xa(e){let t=e.flags?.count??1;return Number.isInteger(t)&&t>=1?t:null}function Za(e){if(e.flags?.pauseMs!==void 0)return`swipe --pause-ms has no Maestro equivalent`;if(e.flags?.pattern&&e.flags.pattern!==`one-way`)return`swipe ping-pong pattern has no Maestro equivalent`}function Qa(e,t){return Q(e)&&Q(t)?{point:N(e,t)}:e.startsWith(`@`)?null:$a(e)}function $a(e){let t;try{t=_(e)}catch{return e.includes(`=`)||e.includes(`||`)?null:e}let n=eo(t.selectors);return n===null?t.selectors.length===1?to(t.selectors[0]):null:n}function eo(e){if(e.length<=1)return null;let t=e.flatMap(e=>e.terms.length===1&&Ea.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||t.length===0)return null;let n=t[0];return typeof n==`string`&&t.every(e=>e===n)?n:null}function to(e){let t={};for(let n of e.terms)if(!no(t,n))return null;return Object.keys(t).length>0?t:null}function no(e,t){return Ea.has(t.key)?typeof t.value!=`string`||e.id||e.text||e.label?!1:(e[t.key]=t.value,!0):Da.has(t.key)&&typeof t.value==`boolean`?(e[t.key]=t.value,!0):!1}function ro(e){let t=ao(e);return t?{ok:!1,message:t}:{ok:!0,options:io(e)}}function io(e){let t={};return typeof e.flags?.count==`number`&&e.flags.count>1&&(t.repeat=e.flags.count),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&(t.delay=e.flags.intervalMs),t}function ao(e){if(e.flags?.jitterPx!==void 0)return`tap --jitter-px has no Maestro equivalent`;if(e.flags?.clickButton&&e.flags.clickButton!==`primary`)return`tap --button ${e.flags.clickButton} has no Maestro equivalent`}function oo(e,t){return Object.keys(t).length===0?{tapOn:e}:typeof e==`string`?{tapOn:{text:e,...t}}:e&&typeof e==`object`&&!Array.isArray(e)?{tapOn:{...e,...t}}:{tapOn:e}}function so(e,t,n,r){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:r,action:mo(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})}function co(e){return e.length===0||![...e].every(e=>e===`\b`)?null:e.length}function lo(e,t,n,r){for(let i of t??[])e.warnings.push({line:r,action:mo(n),message:i})}function uo(e,t){let n=e.positionals.at(-1);return n&&Q(n)?Number(n):t}function fo(e,t){return ze(Object.keys(e).length>0?[e,t]:[t])}function po(e){return e.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join(`; `)}function mo(e){return[e.command,...e.positionals??[]].join(` `).trim()}function ho(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function Q(e){return e!==void 0&&Number.isFinite(Number(e))}const go=async e=>{let{positionals:t}=e;return t[0]===`export`?await vo(e):_o(e)};function _o({positionals:e,flags:t}){if(e.length>1)throw new n(`INVALID_ARGS`,`replay accepts exactly one input path: replay <path>`);if(t.replayExportFormat!==void 0||t.out!==void 0)throw new n(`INVALID_ARGS`,`replay --format/--out are only supported with replay export.`);return!1}async function vo({positionals:e,flags:t}){yo(e,t);let r=e[1];if(!r)throw new n(`INVALID_ARGS`,`replay export requires an input path.`);let i=k(r),a=Oa(F.readFileSync(i,`utf8`)),o=typeof t.out==`string`?k(t.out):void 0;o&&(F.mkdirSync(I.dirname(o),{recursive:!0}),F.writeFileSync(o,a.yaml));for(let e of a.warnings)process.stderr.write(`Warning: line ${e.line}: ${e.message}\n`);return M(t,{format:t.replayExportFormat??`maestro`,sourcePath:i,...o?{path:o}:{yaml:a.yaml},warnings:a.warnings},()=>o??a.yaml),!0}function yo(e,t){if(e.length>2)throw new n(`INVALID_ARGS`,`replay export accepts exactly one input path: replay export <file.ad>`);if(t.replayUpdate)throw new n(`INVALID_ARGS`,`replay export does not support --update.`);if(t.replayMaestro)throw new n(`INVALID_ARGS`,`replay export reads .ad files; omit --maestro.`);if(t.replayEnv?.length)throw new n(`INVALID_ARGS`,`replay export does not evaluate --env substitutions.`);let r=t.replayExportFormat??`maestro`;if(r!==`maestro`)throw new n(`INVALID_ARGS`,`Unsupported replay export format: ${r}`)}const bo=async({positionals:e,flags:t,client:n})=>{let r=await Re({client:n,command:`screenshot`,positionals:e,flags:t});return i(t.responseLevel)?(M(t,r,()=>JSON.stringify(r,null,2)),!0):(M(t,pe(r),()=>r.overlayRefs?`Annotated ${r.overlayRefs.length} refs onto ${r.path}`:Co(r)),!0)},xo=async({positionals:e,flags:t,client:r})=>{if(e[0]===`snapshot`){let n=await Re({client:r,command:`diff`,positionals:e,flags:t});return M(t,n,()=>T(n)),!0}if(e[0]!==`screenshot`)return!1;let i=t.baseline;if(!i||typeof i!=`string`)throw new n(`INVALID_ARGS`,`diff screenshot requires --baseline <path>`);let a=k(i),o=typeof t.out==`string`?k(t.out):void 0,s=e[1];if(e.length>2)throw new n(`INVALID_ARGS`,`diff screenshot accepts at most one current screenshot path`);let[{createAgentDevice:c,localCommandPolicy:l},{createLocalArtifactAdapter:u}]=await Promise.all([import(`./runtime.js`).then(e=>e.r),import(`./sdk-io.js`).then(e=>e.n)]),d=await c({backend:So(r,t),artifacts:u(),sessions:{get:e=>({name:e}),set:()=>{}},policy:l()}).capture.diffScreenshot({session:t.session,baseline:{kind:`path`,path:a},current:s?{kind:`path`,path:k(s)}:{kind:`live`},...o?{out:{kind:`path`,path:o}}:{},threshold:To(t.threshold),overlayRefs:t.overlayRefs,normalizeStatusBar:t.screenshotNormalizeStatusBar,surface:t.surface});return M(t,d,()=>b(d)),!0};function So(e,t){return{platform:wo(t),captureScreenshot:async(t,n,r)=>pe(await e.capture.screenshot({path:n,session:t.session,overlayRefs:r?.overlayRefs,pixelDensity:r?.pixelDensity,fullscreen:r?.fullscreen,normalizeStatusBar:r?.normalizeStatusBar,stabilize:r?.stabilize,surface:r?.surface}))}}function Co(e){if(typeof e.width!=`number`||typeof e.height!=`number`)return e.path;let t=typeof e.pixelDensity==`number`?` @${e.pixelDensity}x`:``;return`${e.path} (${e.width}x${e.height}${t})`}function wo(e){switch(e.platform){case`android`:case`linux`:case`macos`:return e.platform;default:return`ios`}}function To(e){if(!(e==null||e===``))return Number(e)}const Eo={connect:ti,disconnect:mi,connection:hi,auth:Li,proxy:va,replay:go,screenshot:bo,diff:xo};async function Do(e){let t={...e.flags},n=Eo[e.command];return n&&await n({...e,flags:t})?!0:tr(e.command)?await Oo({...e,command:e.command,flags:t}):!1}async function Oo(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function ko(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function Ao(e){return e===`ios-instance`}function jo(e){return e[0]===`wait`&&e.includes(`--connected`)}function Mo(e,t,n){n===0||!jo(e)||!Ao(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(`
|
|
7
|
+
`))}function $(e,t,n){return n||(e.push(t),``)}function No(e){if(!e?.metroProxyBaseUrl||!Lt(e.leaseBackend))return null;let t=[],r={serverBaseUrl:$(t,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:$(t,`metroBearerToken`,e.metroBearerToken),tenantId:$(t,`tenant`,e.tenant),runId:$(t,`runId`,e.runId),leaseId:$(t,`leaseId`,e.leaseId)};if(t.length>0)throw new n(`INVALID_ARGS`,`react-devtools remote bridge requires ${t.join(`, `)}.`,{missing:t});return r}async function Po(e,t,n){let{flags:r}=t,i=No(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 Mt({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await jt({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()}async function Fo(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await Po(e,t,async()=>(await m(`npm`,ko(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);return Mo(e,t.flags,i),i}async function Io(e,t){switch(e[0]){case`setup`:{Lo(t.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),n=await e({stateDir:t.stateDir});return Ro(t.flags.json,n),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),n=await e({stateDir:t.stateDir});return zo(t.flags.json,n.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,n),n.exitCode}default:throw new n(`INVALID_ARGS`,`web requires setup or doctor`)}}function Lo(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
|
|
8
|
+
`)}function Ro(e,t){if(e){x({success:!0,data:{status:Bo(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function zo(e,t,n){if(e){x({success:!0,data:Vo(n)});return}process.stdout.write(`${t}\n`)}function Bo(e){let{socketDir:t,...n}=e;return n}function Vo(e){let t=e.status;return Ho(t)?{...e,status:Bo(t)}:e}function Ho(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function Uo(e){let t;try{t=JSON.parse(e)}catch{throw new n(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(t)||t.length===0)throw new n(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return Wo(t)}function Wo(e){let t=!1,n=e.map((e,n)=>{if(Ko(e))return qo(e,n+1);let r=Jo(e,n+1);return t=!0,Go(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
|
|
9
|
+
`),n}function Go(e){let t=Le(e.command,e.positionals??[],$o(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function Ko(e){return xe(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function qo(e,t){let n=be(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function Jo(e,t){if(!xe(e))throw new n(`INVALID_ARGS`,`Invalid batch step ${t}.`);Xo(e,t);let r=Yo(e.command,t),i=Zo(e.positionals,t),a=Qo(e.flags,t),o=be(e.runtime,t);return{command:r,...i===void 0?{}:{positionals:i},...a===void 0?{}:{flags:a},...o===void 0?{}:{runtime:o}}}function Yo(e,t){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new n(`INVALID_ARGS`,`Batch step ${t} requires command.`);if(Te(r))return r;throw new n(`INVALID_ARGS`,`Batch step ${t} command is not available through command batch: ${String(e)}`)}function Xo(e,t){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new n(`INVALID_ARGS`,`Batch step ${t} has unknown legacy field(s): ${r.join(`, `)}.`)}function Zo(e,t){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new n(`INVALID_ARGS`,`Batch step ${t} positionals must contain only strings.`);return e}}function Qo(e,t){if(e!==void 0){if(!xe(e))throw new n(`INVALID_ARGS`,`Batch step ${t} flags must be an object.`);return e}}function $o(e){return{json:!1,help:!1,version:!1,...e}}function es(e,t={}){let n=ts(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function ts(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??rs(t.AGENT_DEVICE_PLATFORM),r=as(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:ns(e.policyOverrides,t,r)}}function ns(e,t,n){let r=e?.sessionLock??e?.sessionLockConflicts??is(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(e?.sessionLocked===!0||n)return`reject`}function rs(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`ios`||t===`android`||t===`apple`)return t;throw new n(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function is(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t){if(t===`reject`||t===`strip`)return t;throw new n(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function as(e){return typeof e==`string`&&e.trim().length>0}function os(e){let t=e.env??process.env;return L(L({},us(ss(e.cwd,e.cliFlags.config,t))),ps(t,e.command))}function ss(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:ls(r,e,n),required:!0}]:[{path:cs(n),required:!1},{path:I.resolve(e,`agent-device.json`),required:!1}]}function cs(e){return I.join(he(`~`,{env:e}),`.agent-device`,`config.json`)}function ls(e,t,n){return k(e,{cwd:t,env:n})}function us(e){let t={};for(let n of e)L(t,ds(n.path,n.required));return t}function ds(e,t){if(!F.existsSync(e)){if(t)throw new n(`INVALID_ARGS`,`Config file not found: ${e}`);return{}}let r;try{r=F.readFileSync(e,`utf8`)}catch(t){throw new n(`INVALID_ARGS`,`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}let i;try{i=JSON.parse(r)}catch(t){throw new n(`INVALID_ARGS`,`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!i||typeof i!=`object`||Array.isArray(i))throw new n(`INVALID_ARGS`,`Config file must contain a JSON object: ${e}`);return fs(i,`config file ${e}`)}function fs(e,t){let r={};for(let[i,a]of Object.entries(e)){if(i===`installSource`){r.installSource=ve(a,t);continue}let e=i,o=Qe(e);if(!o)throw new n(`INVALID_ARGS`,`Unknown config key "${i}" in ${t}.`);if(!o.config.enabled)throw new n(`INVALID_ARGS`,`Unsupported config key "${i}" in ${t}.`);r[e]=et(o,a,t,i)}return r}function ps(e,t){let n={};for(let r of $e(t)){if(r.key===`installSource`)continue;let t=r.env.names.map(t=>({name:t,value:e[t]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(n[r.key]=et(r,t.value,`environment variable ${t.name}`,t.name))}return n}function ms(e,t){let n=ft(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=hs(n.command)?mn({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=L(os({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...vt(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function hs(e){return e!==null}const gs={sendToDaemon:le},_s=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),vs=new Set([`connect`,`connection`,`close`,`disconnect`,`metro`,`proxy`,`session`]);async function ys(t,i=gs){let a=c(),o=me(),s=bs(t),l=t.includes(`--json`);await u({session:Is(t)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:a,command:t[0],debug:s},async()=>{let c;try{c=ms(t,{cwd:process.cwd(),env:process.env})}catch(t){h({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:f().diagnosticId,logPath:d({force:!0})??void 0});l?x({success:!1,error:n}):y(n,{showDetails:s}),process.exit(1);return}for(let e of c.warnings)process.stderr.write(`Warning: ${e}\n`);c.flags.version&&(process.stdout.write(`${o}\n`),process.exit(0));let u=c.command===`help`,p=c.flags.help;if(u||p){u&&c.positionals.length>1&&(y(new n(`INVALID_ARGS`,`help accepts at most one command.`)),process.exit(1));let e=u?c.positionals[0]:c.command;e||(process.stdout.write(`${await B()}\n`),process.exit(0));let t=await kt(e);t&&(process.stdout.write(t),process.exit(0)),y(new n(`INVALID_ARGS`,xs(e))),process.stdout.write(`${await B()}\n`),process.exit(1)}c.command||(process.stdout.write(`${await B()}\n`),process.exit(1));let{command:m,positionals:g}=c,_=Cs(m,c.providedFlags),v,b,S,C,w,T,E=new Set(c.providedFlags.map(e=>e.key));try{v=ts({policyOverrides:c.flags,configuredPlatform:c.flags.platform,configuredSession:c.flags.session}),b=v.lockPolicy?{...c.flags}:es(c.flags,{policyOverrides:c.flags,configuredPlatform:c.flags.platform,configuredSession:c.flags.session}),S=O(b.stateDir),C=b.session??`default`,w=Es({command:m,explicitFlagKeys:E,stateDir:S.baseDir,session:C,remoteConfig:b.remoteConfig,hasResolvedSession:b.session!==void 0}),T=w?js(b,w.flags,E):b}catch(t){let n=e(r(t),{diagnosticId:f().diagnosticId,logPath:d({force:!0})??void 0});c.flags.json?x({success:!1,error:n}):y(n,{showDetails:_}),process.exit(1);return}let D=null;try{if(m===`react-devtools`){let e=await Fo(g,{flags:T,stateDir:S.baseDir,session:T.session??C,cwd:process.cwd(),env:process.env});process.exit(e);return}if(m===`web`){let e=await Io(g,{flags:T,stateDir:S.baseDir});process.exit(e);return}Me({command:m,currentVersion:o,stateDir:S.baseDir,flags:T});let e=w?.runtime,t=w?.connection,r=(e,t,n)=>({session:e.session,requestId:a,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:e.providerApp,providerOsVersion:e.providerOsVersion,providerProject:e.providerProject,providerBuild:e.providerBuild,providerSessionName:e.providerSessionName,awsProjectArn:e.awsProjectArn,awsDeviceArn:e.awsDeviceArn,awsAppArn:e.awsAppArn,awsRegion:e.awsRegion,awsInteractionMode:e.awsInteractionMode,runtime:t,lockPolicy:v.lockPolicy,lockPlatform:v.defaultPlatform,cwd:process.cwd(),debug:_,cost:e.cost,responseLevel:e.responseLevel}),s;if(m===`batch`){if(g.length>0)throw new n(`INVALID_ARGS`,`batch does not accept positional arguments.`);s=ws(b)}if(Os(m)&&(T=(await ir({command:m,flags:T,stateDir:S.baseDir,env:process.env})).flags),T.remoteConfig&&Ds(m)){let n=se(r(T,e,t),{transport:Ps(i.sendToDaemon)}),a=await Sn({command:m,flags:T,client:n,runtime:e,positionals:g,batchSteps:s,forceRuntimePrepare:Ms(E)});T=a.flags,e=a.runtime,t=a.connection}if(ks({command:m,flags:T,runtime:e,explicitFlagKeys:E,hadConnectionDefaults:!!w})&&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.
|
|
10
|
+
`),m===`cdp`){let t=await Wt(g,{flags:T,runtime:e,cwd:process.cwd(),env:process.env});process.exit(t);return}let c=T.daemonBaseUrl;D=_&&!T.json&&!c?Ls(S.logPath):null;let l=m===`test`?await import(`./reporting.js`).then(({createReplayTestReporterRuntime:e})=>e({debug:_,verbose:T.verbose,json:T.json,reporter:T.reporter,reportJunit:T.reportJunit})):void 0,u=se(r(T,e,t),{transport:Ns({command:m,flags:T,replayTestReporterRuntime:l,transport:i.sendToDaemon})});if(m===`batch`){if(!s)throw new n(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let e=s.map((e,t)=>({...e,input:v.lockPolicy&&b.platform===void 0?{...e.input}:es(e.input,{policyOverrides:T,configuredPlatform:T.platform,configuredSession:T.session,inheritedPlatform:T.platform})}));if(await Do({command:m,positionals:g,flags:{...T,batchSteps:e},client:u,debug:_,replayTestReporterRuntime:l}))return}else if(m===`runtime`)throw new n(`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 Do({command:m,positionals:g,flags:T,client:u,debug:_,replayTestReporterRuntime:l}))return;throw new n(`INVALID_ARGS`,Ss(m))}catch(t){let n=r(t),i=e(n,{diagnosticId:f().diagnosticId,logPath:d({force:!0})??void 0});if(m===`close`&&Ts(n)){T.json&&x({success:!0,data:{closed:`session`,source:`no-daemon`}});return}if(T.json)x({success:!1,error:i});else if(y(i,{showDetails:_}),_)try{let e=S.logPath;if(F.existsSync(e)){let t=F.readFileSync(e,`utf8`).split(`
|
|
11
11
|
`),n=t.slice(Math.max(0,t.length-200)).join(`
|
|
12
|
-
`);n.trim().length>0&&process.stderr.write(`\n[daemon log]\n${n}\n`)}}catch{}
|
|
12
|
+
`);n.trim().length>0&&process.stderr.write(`\n[daemon log]\n${n}\n`)}}catch{}D&&D(),process.exit(1)}finally{D&&D()}})}function bs(e){try{let t=ft(e);return Cs(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function xs(e){let t=lt(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Ss(e){return v(e)?(h({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function Cs(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function ws(e){let t=``;if(e.steps)t=e.steps;else if(e.stepsFile)try{t=F.readFileSync(e.stepsFile,`utf8`)}catch(t){let r=t instanceof Error?t.message:String(t);throw new n(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return Uo(t)}function Ts(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 Es(e){return e.command===`connect`||e.command===`connection`||e.command===`proxy`?null:Jt({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 Ds(e){return!vs.has(e)}function Os(e){return e!==`auth`&&e!==`connection`&&e!==`proxy`}function ks(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:As(e.explicitFlagKeys)}function As(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function js(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 Ms(e){for(let t of _s)if(e.has(t))return!0;return!1}function Ns(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;return n.json?Ps(i):async e=>await Fs(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},t===`test`&&r?{onProgress:r.onProgress}:void 0)}function Ps(e){return async t=>await Fs(e,t)}async function Fs(e,t,n){return await e(t,n)}function Is(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}qe(process.argv[1]??``).href===import.meta.url&&ys(process.argv.slice(2)).catch(t=>{y(e(r(t)),{showDetails:!0}),process.exit(1)});function Ls(e){try{let t=F.existsSync(e)?F.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&F.existsSync(e))try{let n=F.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=F.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);F.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{F.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{ys as runCli};
|