agent-device 0.17.6 → 0.17.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.6.apk → agent-device-android-multitouch-helper-0.17.7.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.7.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.6.manifest.json → agent-device-android-multitouch-helper-0.17.7.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.6.apk → agent-device-android-snapshot-helper-0.17.7.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.7.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.6.manifest.json → agent-device-android-snapshot-helper-0.17.7.manifest.json} +6 -6
- package/dist/src/2133.js +1 -1
- package/dist/src/2948.js +1 -1
- package/dist/src/368.js +1 -0
- package/dist/src/4291.js +1 -2
- package/dist/src/4428.js +3 -3
- package/dist/src/4723.js +1 -1
- package/dist/src/5910.js +2 -0
- package/dist/src/6311.js +18 -18
- package/dist/src/7244.js +1 -1
- package/dist/src/9581.js +11 -1
- package/dist/src/9722.js +36 -36
- package/dist/src/9873.js +1 -1
- package/dist/src/android-adb.d.ts +1 -1
- package/dist/src/batch.d.ts +1 -1
- package/dist/src/cli-help.js +126 -27
- package/dist/src/cli-output.js +4 -4
- package/dist/src/cli.js +13 -12
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/index.d.ts +7 -4
- package/dist/src/interaction.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/provider.js +1 -0
- package/dist/src/record-trace-recording.js +3 -3
- package/dist/src/remote-config.d.ts +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +2 -2
- package/dist/src/session.js +8 -8
- package/dist/src/snapshot.js +1 -1
- package/dist/src/web.js +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +6 -6
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +1 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +9 -5
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +0 -2
- package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +44 -8
- package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +59 -16
- package/ios-runner/RUNNER_PROTOCOL.md +1 -1
- package/package.json +5 -2
- package/server.json +2 -2
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.6.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.6.apk.sha256 +0 -1
- package/dist/src/5299.js +0 -1
package/dist/src/cli.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import{pathToFileURL as e}from"node:url";import t from"node:fs";import n from"node:crypto";import o from"node:path";import{resolveRemoteConfigProfile as r,resolveRemoteConfigPath as s,REMOTE_CONFIG_FIELD_SPECS as a,parseSourceValue as i,buildPrimaryEnvVarName as l}from"./4723.js";import{isClientBackedCliCommandName as c,listCliCommandNames as d}from"./2133.js";import{getCliCommandSchema as u,applyCommandDefaults as f,getCommandSchema as m}from"./9581.js";import{asAppError as p,normalizeError as g,AppError as h}from"./733.js";import{buildCommandUsageText as w,buildUsageText as v}from"./cli-help.js";import{ensureCompanionTunnel as y,stopCompanionTunnel as I}from"./8275.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as A}from"./4069.js";import{createRequestId as _,withDiagnosticsScope as S,getDiagnosticsMeta as k,flushDiagnosticsToSessionFile as D,emitDiagnostic as C}from"./432.js";import{resolveDaemonPaths as N}from"./2892.js";import{stopMetroTunnel as b}from"./metro.js";import{runCmdStreaming as R,runCmd as U}from"./8875.js";import{formatSnapshotDiffText as E,formatScreenshotDiffText as P,printHumanError as L,printJson as
|
|
2
|
-
`,{encoding:"utf8",mode:384}),t.chmodSync(e,384)}function eG(e,t){C({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),eT(e)}let ej=a.map(e=>e.key);function eK(e){let t={};for(let n of ej){let o=e[n];void 0!==o&&(t[n]=o)}return t}let eF=new Set(["connect","connection","close","disconnect","metro","session"]),eH=new Set(["open"]);async function eq(e){let t,n,{command:o,flags:s,client:a}=e;if(!s.remoteConfig)return{flags:s,runtime:e.runtime};let i=N(s.stateDir).baseDir,l=r({configPath:s.remoteConfig,cwd:process.cwd(),env:process.env}),c={...eK(l.profile),...s,remoteConfig:l.resolvedPath},d=eE({stateDir:i,session:c.session??"default"});if(d&&d.remoteConfigPath!==l.resolvedPath)throw new h("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:d.session,activeRemoteConfig:d.remoteConfigPath,requestedRemoteConfig:l.resolvedPath});let u=d??function(e,t){if(!e.tenant)throw new h("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new h("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new h("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let n=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:ex(t),daemon:eL(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??eY(e),platform:e.platform,target:e.target,connectedAt:n,updatedAt:n}}(c,l.resolvedPath),f={...c,session:u.session},m=function(e,t){if(e)return eQ(e,t)?e:void 0}(u.runtime,f.platform)??e.runtime,p=u,g=!d;if(w=o,!eF.has(w)){let e=u.leaseBackend??function(e,t){let n=eY(e);if(n)return n;throw new h("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(s,o);var w,v,y,I,A,_=u,S=s,k=e;if(_.leaseBackend&&_.leaseBackend!==k)throw new h("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:_.session,leaseBackend:_.leaseBackend});if(_.platform&&S.platform&&_.platform!==S.platform)throw new h("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:_.session,platform:_.platform});if(_.target&&S.target&&_.target!==S.target)throw new h("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:_.session,target:_.target});let t=await e0(a,p,e);f.leaseId=t.leaseId,f.leaseBackend=e,f.platform=p.platform??f.platform,f.target=p.target??f.target,(p.leaseId!==t.leaseId||p.leaseBackend!==e)&&(p={...p,leaseId:t.leaseId,leaseBackend:e,platform:p.platform??s.platform,target:p.target??s.target,updatedAt:new Date().toISOString()},g=!0)}if(v=o,y=e.batchSteps,(eH.has(v)||"batch"===v&&y&&y.some(e=>{let t=e.command.trim().toLowerCase();return eH.has(t)&&void 0===e.runtime}))&&eX(f)&&(!p.leaseId&&f.leaseId&&(p={...p,leaseId:f.leaseId,leaseBackend:f.leaseBackend}),e.forceRuntimePrepare||!m||!eQ(m,f.platform))){if(!p.leaseId)throw new h("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await eW(f,a,u.remoteConfigPath,u.session,{tenantId:u.tenant,runId:u.runId,leaseId:p.leaseId});m=e.runtime;let r=(I=p.metro,A=e.cleanup,I?.projectRoot!==A?.projectRoot||I?.profileKey!==A?.profileKey||I?.consumerKey!==A?.consumerKey);t=r?p.metro:void 0,n=r?e.cleanup:void 0,p={...p,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},g=!0}if(g)try{eP({stateDir:i,state:p})}catch(e){throw await eJ(n),e}return await eJ(t),{flags:{...f,session:p.session,leaseId:p.leaseId,leaseBackend:p.leaseBackend,platform:p.platform??f.platform,target:p.target??f.target},runtime:m}}async function eW(e,t,n,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new h("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new h("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let s=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:function(e){if(void 0!==e){if("auto"===e||"react-native"===e||"expo"===e)return e;throw new h("INVALID_ARGS","metro prepare --kind must be auto, react-native, or expo")}}(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:n,companionConsumerKey:o,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?s.iosRuntime:s.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:s.projectRoot,profileKey:n,consumerKey:o}:void 0}}async function eJ(e){if(e)try{await b(e)}catch{}}async function ez(e){try{await eU({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function eZ(e,t){if(t.leaseId)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,daemonBaseUrl:t.daemon?.baseUrl,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode})}catch{}}function eY(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function eX(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function eQ(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function e0(e,t,n){if(t.leaseId&&t.leaseBackend===n){let o=await e1(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n})}async function e1(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend})}catch(e){var o;if((o=e)instanceof h&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}async function e3(e,t){let n=await e.text(),o={};if(n.trim().length>0)try{o=JSON.parse(n)}catch(n){throw new h("COMMAND_FAILED",t.invalidJsonMessage,{status:e.status},n instanceof Error?n:void 0)}if(!e.ok)throw new h("UNAUTHORIZED",t.rejectedMessage,{status:e.status,response:o});return o}async function e8(e){return await e2({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function e2(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tl(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tl(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||tl(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let n=await e7({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{flags:{...e.flags,daemonAuthToken:n.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new h("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw to(e.command,t)}let o=await e9({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function e4(e){let t=e.env??e.io?.env??process.env;if(tl(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:tr(t)};if(tl(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:tr(t)};let n=await e7({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{accessToken:n.accessToken,cloudBaseUrl:n.cloudBaseUrl};if(e.flags.noLogin)throw new h("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let o=await e9({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:o.accessToken,cloudBaseUrl:o.session.cloudBaseUrl}}async function e9(e){let n,r,s,a=e.env??e.io?.env??process.env,i=(d=a,u=e.io,n=u?.stdinIsTTY??process.stdin.isTTY,r=u?.stdoutIsTTY??process.stdout.isTTY,"true"!==(f=d).CI&&"true"!==f.GITHUB_ACTIONS&&"true"!==f.BUILDKITE&&n&&r?(m=d).SSH_TTY||m.SSH_CONNECTION||"true"===m.CODESPACES||m.GITPOD_WORKSPACE_ID||"true"===m.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===i)throw to(e.commandLabel??"agent-device connect",a);let l=tr(a),c=await tn({baseUrl:l,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});var d,u,f,m,p,g,w=c;if(!tl(w.deviceCode)||!tl(w.userCode)||!tl(w.verificationUri))throw new h("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=c.verificationUriComplete??c.verificationUri,y="local-browser"===i?c.verificationUri:(p=c.verificationUri,g=c.userCode,(s=new URL(p)).searchParams.set("user_code",g),s.toString());"local-browser"===i?(ta(e.io,`Opening ${c.verificationUri}...
|
|
3
|
-
`),await
|
|
1
|
+
import{pathToFileURL as e}from"node:url";import t from"node:fs";import n from"node:crypto";import o from"node:path";import{resolveRemoteConfigProfile as r,resolveRemoteConfigPath as s,REMOTE_CONFIG_FIELD_SPECS as a,parseSourceValue as i,buildPrimaryEnvVarName as l}from"./4723.js";import{isClientBackedCliCommandName as c,listCliCommandNames as d}from"./2133.js";import{getCliCommandSchema as u,applyCommandDefaults as f,getCommandSchema as m}from"./9581.js";import{asAppError as p,normalizeError as g,AppError as h}from"./733.js";import{buildCommandUsageText as w,buildUsageText as v}from"./cli-help.js";import{ensureCompanionTunnel as y,stopCompanionTunnel as I}from"./8275.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as A}from"./4069.js";import{createRequestId as _,withDiagnosticsScope as S,getDiagnosticsMeta as k,flushDiagnosticsToSessionFile as D,emitDiagnostic as C}from"./432.js";import{resolveDaemonPaths as N}from"./2892.js";import{stopMetroTunnel as b}from"./metro.js";import{runCmdStreaming as R,runCmd as U}from"./8875.js";import{formatSnapshotDiffText as E,formatScreenshotDiffText as P,printHumanError as L,printJson as x}from"./6311.js";import{parseSelectorChain as T}from"./9836.js";import{stringifyMaestroYamlDocuments as M,parseReplayScriptDetailed as B,formatMaestroPoint as O,readReplayScriptMetadata as $}from"./4428.js";import{resolveUserPath as V,expandUserHomePath as G}from"./9612.js";import{interactionCliReaders as j,observabilityCliReaders as K,parseInstallSourceConfig as F,getFlagDefinition as H,gestureCliReaders as q,reactNativeCliReaders as W,getFlagDefinitions as J,captureCliReaders as z,GLOBAL_FLAG_KEYS as Z,replayCliReaders as Y,batchCliReaders as X,appCliReaders as Q,selectorCliReaders as ee,recordingCliReaders as et,systemCliReaders as en,perfCliReaders as eo}from"./9873.js";import{isCommandName as er,metroCliReaders as es,debuggingCliReaders as ea}from"./2948.js";import{formatCliOutput as ei}from"./cli-output.js";import{runCommand as el}from"./command-surface.js";import{createLocalArtifactAdapter as ec}from"./314.js";import{setupManagedAgentBrowser as ed,localCommandPolicy as eu,doctorManagedAgentBrowser as ef,createAgentDevice as em}from"./368.js";import{readVersion as ep}from"./7244.js";import{createAgentDeviceClient as eg,sendToDaemon as eh}from"./9919.js";import{maybeRunUpgradeNotifier as ew}from"./5448.js";function ev(e,t){for(let[n,o]of Object.entries(t))void 0!==o&&(e[n]=o);return e}let ey=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),eI=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),eA=function(){let e=new Map;for(let t of J()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of Z)t.set(e,new Set(["*"]));for(let e of d()){let n=u(e);for(let o of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(o);n&&n.has("*")||(n?n.add(e):t.set(o,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,config:{enabled:!ey.has(e),key:e},env:{names:eI.has(e)?[]:[l(e)]},supportsCommand(n){let o=t.get(e);return!!o&&(!!o.has("*")||!!n&&o.has(n))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),e_=new Map(eA.map(e=>[e.key,e]));function eS(e,t){return e_.get(e)?.supportsCommand(t)??!1}function ek(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let n=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===n.type){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...n,setValue:void 0,enumValues:t}}return n}function eD(e){let t={json:!1,help:!1,version:!1},n=null,o=[],r=[],s=!0;for(let c=0;c<e.length;c+=1){var a,i,l;let d=e[c];if(s&&"--"===d){s=!1;continue}if(!s){n?o.push(d):n=eR(d);continue}let u=d.startsWith("--"),f=d.startsWith("-")&&d.length>1;if(!u&&!f){n?o.push(d):n=eR(d);continue}let[p,g]=u?eC(d):[d,void 0];if(a=n,"-c"===p&&("snapshot"===a||"diff"===a))continue;let w=H(p);if(i=n,l=w,"react-devtools"===i&&(!l||!eS(l.key,i))){o.push(d);continue}if(!w){if(function(e,t,n){var o;if(o=n,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=m(e);if(!r||r.allowsExtraPositionals)return!0;let s=r.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(n,o,d)){n?o.push(d):n=d;continue}throw new h("INVALID_ARGS",`Unknown flag: ${p}`)}let v=function(e,t,n,o){if(void 0!==e.setValue){if(void 0!==n)throw new h("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new h("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new h("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===o||eb(o)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(o)?{value:!0,consumeNext:!1}:{value:o,consumeNext:!0}}let r=n??o;if(void 0===r||void 0===n&&eb(r))throw new h("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new h("INVALID_ARGS",`Invalid ${eN(t)}: ${r}`);return{value:r,consumeNext:void 0===n}}let s=Number(r);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new h("INVALID_ARGS",`Invalid ${eN(t)}: ${r}`);return{value:Math.floor(s),consumeNext:void 0===n}}(w,p,g,e[c+1]);v.consumeNext&&(c+=1);let y=t[w.key];if(w.multiple){let e=Array.isArray(y)?[...y,v.value]:void 0===y?[v.value]:[y,v.value];t[w.key]=e}else t[w.key]=v.value;r.push({key:w.key,token:p})}return{command:n,positionals:o,flags:t,warnings:[],providedFlags:r}}function eC(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eN(e){return e.replace(/^-+/,"")}function eb(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?eC(e):[e,void 0];return void 0!==H(t)}function eR(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}let eU={slug:"react-devtools-companion",runArg:A,displayName:"React DevTools companion"};async function eE(e){return await y({...e,definition:eU,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 eP(e){return await I({...e,definition:eU})}function eL(e){var n;let o,r=eO(e);if(!t.existsSync(r))return null;try{o=JSON.parse(t.readFileSync(r,"utf8"))}catch(t){return eK(e,t),null}return!(!(n=o)||"object"!=typeof n||Array.isArray(n))&&1===n.version&&"string"==typeof n.session&&"string"==typeof n.remoteConfigPath&&"string"==typeof n.remoteConfigHash&&(void 0===n.daemon||"object"==typeof n.daemon&&null!==n.daemon&&!Array.isArray(n.daemon))&&"string"==typeof n.tenant&&"string"==typeof n.runId&&(void 0===n.leaseId||"string"==typeof n.leaseId)&&(void 0===n.leaseBackend||"string"==typeof n.leaseBackend)&&"string"==typeof n.connectedAt&&"string"==typeof n.updatedAt?o:(eK(e),null)}function ex(e){let n=eO({stateDir:e.stateDir,session:e.state.session});t.mkdirSync(o.dirname(n),{recursive:!0}),ej(n,e.state),ej(e$(e.stateDir),{session:e.state.session})}function eT(e){return{baseUrl:function(e){if(!e)return;let t=new URL(e);for(let e of(t.username="",t.password="",[...t.searchParams.keys()]))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,"")}(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function eM(e){t.rmSync(eO(e),{force:!0});let n=e$(e.stateDir);eG(e.stateDir)===e.session&&t.rmSync(n,{force:!0})}function eB(e){try{return n.createHash("sha256").update(t.readFileSync(e)).digest("hex")}catch(t){throw new h("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function eO(e){return o.join(e.stateDir,"remote-connections",`${function(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,"_");if(!t)return"default";if(t===e)return t;let o=n.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${o}`}(e.session)}.json`)}function e$(e){return o.join(e,"remote-connections",".active-session.json")}function eV(e){let t=eG(e.stateDir);return t?eL({stateDir:e.stateDir,session:t}):null}function eG(e){let n=e$(e);if(t.existsSync(n))try{let e=JSON.parse(t.readFileSync(n,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function ej(e,n){t.writeFileSync(e,`${JSON.stringify(n,null,2)}
|
|
2
|
+
`,{encoding:"utf8",mode:384}),t.chmodSync(e,384)}function eK(e,t){C({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),eM(e)}let eF=a.map(e=>e.key);function eH(e){let t={};for(let n of eF){let o=e[n];void 0!==o&&(t[n]=o)}return t}let eq=new Set(["connect","connection","close","disconnect","metro","session"]),eW=new Set(["open"]);async function eJ(e){let t,n,{command:o,flags:s,client:a}=e;if(!s.remoteConfig)return{flags:s,runtime:e.runtime};let i=N(s.stateDir).baseDir,l=r({configPath:s.remoteConfig,cwd:process.cwd(),env:process.env}),c={...eH(l.profile),...s,remoteConfig:l.resolvedPath},d=eL({stateDir:i,session:c.session??"default"});if(d&&d.remoteConfigPath!==l.resolvedPath)throw new h("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:d.session,activeRemoteConfig:d.remoteConfigPath,requestedRemoteConfig:l.resolvedPath});let u=d??function(e,t){if(!e.tenant)throw new h("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new h("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new h("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let n=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:eB(t),daemon:eT(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??eQ(e),platform:e.platform,target:e.target,connectedAt:n,updatedAt:n}}(c,l.resolvedPath),f={...c,session:u.session},m=function(e,t){if(e)return e1(e,t)?e:void 0}(u.runtime,f.platform)??e.runtime,p=u,g=!d;if(w=o,!eq.has(w)){let e=u.leaseBackend??function(e,t){let n=eQ(e);if(n)return n;throw new h("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(s,o);var w,v,y,I,A,_=u,S=s,k=e;if(_.leaseBackend&&_.leaseBackend!==k)throw new h("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:_.session,leaseBackend:_.leaseBackend});if(_.platform&&S.platform&&_.platform!==S.platform)throw new h("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:_.session,platform:_.platform});if(_.target&&S.target&&_.target!==S.target)throw new h("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:_.session,target:_.target});let t=await e3(a,p,e);f.leaseId=t.leaseId,f.leaseBackend=e,f.platform=p.platform??f.platform,f.target=p.target??f.target,(p.leaseId!==t.leaseId||p.leaseBackend!==e)&&(p={...p,leaseId:t.leaseId,leaseBackend:e,platform:p.platform??s.platform,target:p.target??s.target,updatedAt:new Date().toISOString()},g=!0)}if(v=o,y=e.batchSteps,(eW.has(v)||"batch"===v&&y&&y.some(e=>{let t=e.command.trim().toLowerCase();return eW.has(t)&&void 0===e.runtime}))&&e0(f)&&(!p.leaseId&&f.leaseId&&(p={...p,leaseId:f.leaseId,leaseBackend:f.leaseBackend}),e.forceRuntimePrepare||!m||!e1(m,f.platform))){if(!p.leaseId)throw new h("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await ez(f,a,u.remoteConfigPath,u.session,{tenantId:u.tenant,runId:u.runId,leaseId:p.leaseId});m=e.runtime;let r=(I=p.metro,A=e.cleanup,I?.projectRoot!==A?.projectRoot||I?.profileKey!==A?.profileKey||I?.consumerKey!==A?.consumerKey);t=r?p.metro:void 0,n=r?e.cleanup:void 0,p={...p,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},g=!0}if(g)try{ex({stateDir:i,state:p})}catch(e){throw await eZ(n),e}return await eZ(t),{flags:{...f,session:p.session,leaseId:p.leaseId,leaseBackend:p.leaseBackend,platform:p.platform??f.platform,target:p.target??f.target},runtime:m}}async function ez(e,t,n,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new h("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new h("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let s=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:function(e){if(void 0!==e){if("auto"===e||"react-native"===e||"expo"===e)return e;throw new h("INVALID_ARGS","metro prepare --kind must be auto, react-native, or expo")}}(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:n,companionConsumerKey:o,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?s.iosRuntime:s.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:s.projectRoot,profileKey:n,consumerKey:o}:void 0}}async function eZ(e){if(e)try{await b(e)}catch{}}async function eY(e){try{await eP({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function eX(e,t){if(t.leaseId)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,daemonBaseUrl:t.daemon?.baseUrl,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode})}catch{}}function eQ(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function e0(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function e1(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function e3(e,t,n){if(t.leaseId&&t.leaseBackend===n){let o=await e8(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n})}async function e8(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend})}catch(e){var o;if((o=e)instanceof h&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}async function e2(e,t){let n=await e.text(),o={};if(n.trim().length>0)try{o=JSON.parse(n)}catch(n){throw new h("COMMAND_FAILED",t.invalidJsonMessage,{status:e.status},n instanceof Error?n:void 0)}if(!e.ok)throw new h("UNAUTHORIZED",t.rejectedMessage,{status:e.status,response:o});return o}async function e4(e){return await e5({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function e5(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(td(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(td(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||td(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let n=await tt({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{flags:{...e.flags,daemonAuthToken:n.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new h("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw ts(e.command,t)}let o=await e9({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function e6(e){let t=e.env??e.io?.env??process.env;if(td(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:ta(t)};if(td(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:ta(t)};let n=await tt({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{accessToken:n.accessToken,cloudBaseUrl:n.cloudBaseUrl};if(e.flags.noLogin)throw new h("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let o=await e9({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:o.accessToken,cloudBaseUrl:o.session.cloudBaseUrl}}async function e9(e){let n,r,s,a=e.env??e.io?.env??process.env,i=(d=a,u=e.io,n=u?.stdinIsTTY??process.stdin.isTTY,r=u?.stdoutIsTTY??process.stdout.isTTY,"true"!==(f=d).CI&&"true"!==f.GITHUB_ACTIONS&&"true"!==f.BUILDKITE&&n&&r?(m=d).SSH_TTY||m.SSH_CONNECTION||"true"===m.CODESPACES||m.GITPOD_WORKSPACE_ID||"true"===m.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===i)throw ts(e.commandLabel??"agent-device connect",a);let l=ta(a),c=await tr({baseUrl:l,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});var d,u,f,m,p,g,w=c;if(!td(w.deviceCode)||!td(w.userCode)||!td(w.verificationUri))throw new h("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=c.verificationUriComplete??c.verificationUri,y="local-browser"===i?c.verificationUri:(p=c.verificationUri,g=c.userCode,(s=new URL(p)).searchParams.set("user_code",g),s.toString());"local-browser"===i?(tl(e.io,`Opening ${c.verificationUri}...
|
|
3
|
+
`),await ti(v,e.io)):tl(e.io,`Open this URL on your machine:
|
|
4
4
|
${y}
|
|
5
5
|
|
|
6
6
|
Waiting for approval for 10 minutes...
|
|
7
|
-
`);let I=await
|
|
8
|
-
`,{mode:384});try{t.chmodSync(n,384)}catch{}}({stateDir:e.stateDir,session:S}),{accessToken:I.accessToken,expiresAt:I.expiresAt,session:S}}function
|
|
7
|
+
`);let I=await to({cloudBaseUrl:l,deviceCode:c.deviceCode,expiresIn:c.expiresIn,interval:c.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),A=I.cliSession?.refreshCredential??I.cliSession?.refreshToken;if(!td(I.accessToken)||!td(A))throw new h("UNAUTHORIZED","Device authorization did not return CLI credentials.");let _=new Date(e.io?.now?.()??Date.now()).toISOString(),S={version:1,id:I.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:l,workspaceId:I.cliSession?.workspaceId,accountId:I.cliSession?.accountId,name:I.cliSession?.name,refreshCredential:A,createdAt:_,expiresAt:I.cliSession?.expiresAt};return function(e){let n=te(e.stateDir);t.mkdirSync(o.dirname(n),{recursive:!0,mode:448}),t.writeFileSync(n,`${JSON.stringify(e.session,null,2)}
|
|
8
|
+
`,{mode:384});try{t.chmodSync(n,384)}catch{}}({stateDir:e.stateDir,session:S}),{accessToken:I.accessToken,expiresAt:I.expiresAt,session:S}}function e7(e){let n=te(e.stateDir);if(!t.existsSync(n))return null;try{let e=JSON.parse(t.readFileSync(n,"utf8"));if(1!==e.version||!td(e.id)||!td(e.cloudBaseUrl)||!td(e.refreshCredential)||!td(e.createdAt))return null;return e}catch{return null}}function te(e){return o.join(e,"auth","cli-session.json")}async function tt(e){let t=e7({stateDir:e.stateDir});return!t||tc(t.expiresAt,e.io?.now)?null:{accessToken:(await tn({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:ta(e.env,t.cloudBaseUrl)}}async function tn(e){let t=ta(e.env,e.session.cloudBaseUrl),n=await tr({baseUrl:t,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(td(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};if("revoked"===n.status||"revoked"===n.error)throw new h("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error});throw new h("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error})}async function to(e){let t=e.now??Date.now,n=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+n,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tr({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||td(t.accessToken))return t;if("slow_down"===t.status||"slow_down"===t.error)r+=1e3;else if("authorization_pending"!==t.status&&"authorization_pending"!==t.error)throw new h("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tu(r)}throw new h("TIMEOUT","Device authorization expired before approval.")}async function tr(e){let t=e.fetchImpl??fetch,n=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await e2(n,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${n.status}).`,rejectedMessage:"Cloud auth endpoint rejected the request."})}function ts(e,t){let n=ta(t);return new h("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",n).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function ta(e,t){let n=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(n).toString().replace(/\/+$/,"")}catch(e){throw new h("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:n},e instanceof Error?e:void 0)}}async function ti(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let n=process.platform;try{"darwin"===n?await U("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===n?await U("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await U("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tl(t,`Open this URL on your machine:
|
|
9
9
|
${e}
|
|
10
|
-
`)}}function
|
|
11
|
-
`,{mode:384});try{t.chmodSync(i,384)}catch{}return i}({stateDir:e.stateDir,profile:a}),cwd:e.cwd,env:e.env});return{flags:{...
|
|
12
|
-
`))}let tm=async({flags:e,client:t})=>{var o,s,a,i;let l=N(e.stateDir).baseDir,c=e.remoteConfig?function(e){if(!e.remoteConfig)throw new h("INVALID_ARGS","connect requires --remote-config <path>.");let t=r({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await td({flags:e,stateDir:l,cwd:process.cwd(),env:process.env}),d=c.flags,u=d.tenant,f=d.runId;if(!u)throw new h("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!f)throw new h("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!d.daemonBaseUrl)throw new h("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let m=d.session?null:eO({stateDir:l}),p=d.session??m?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${n.randomBytes(3).toString("hex")}`;if(!eE({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${n.randomBytes(2).toString("hex")}`}(l),g=ex(c.remoteConfigPath),w=eL(d),v=m?.session===p?m:eE({stateDir:l,session:p});if(v&&(o=v,s={flags:d,session:p,remoteConfigPath:c.remoteConfigPath,remoteConfigHash:g,desiredLeaseBackend:eY(d),daemon:w},o.remoteConfigPath!==s.remoteConfigPath||o.remoteConfigHash!==s.remoteConfigHash||o.session!==s.session||o.tenant!==s.flags.tenant||o.runId!==s.flags.runId||void 0!==s.desiredLeaseBackend&&o.leaseBackend!==s.desiredLeaseBackend||void 0!==s.flags.platform&&o.platform!==s.flags.platform||void 0!==s.flags.target&&o.target!==s.flags.target||(a=o.daemon,i=s.daemon,(a?.baseUrl??void 0)!==(i?.baseUrl??void 0)||(a?.transport??void 0)!==(i?.transport??void 0)||(a?.serverMode??void 0)!==(i?.serverMode??void 0)))&&!d.force)throw new h("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:p,remoteConfig:v.remoteConfigPath});let y=new Date().toISOString(),I={version:1,session:p,remoteConfigPath:c.remoteConfigPath,remoteConfigHash:g,daemon:w,tenant:u,runId:f,leaseId:v&&!d.force?v.leaseId:void 0,leaseBackend:v&&!d.force?v.leaseBackend:eY(d),platform:d.platform??(v&&!d.force?v.platform:void 0),target:d.target??(v&&!d.force?v.target:void 0),runtime:v&&!d.force?v.runtime:void 0,metro:v&&!d.force?v.metro:void 0,connectedAt:v&&!d.force?v.connectedAt:y,updatedAt:y};eP({stateDir:l,state:I}),v&&d.force&&(await eJ(v.metro),await ez({stateDir:l,state:v}),await eZ(t,v));let A=tv(I),_=function(e,t){if(!t.runtime&&(eX(e)||tI(t.remoteConfigPath)))return ty(t.remoteConfigPath)}(d,I);return tf(d,tA(I,_),()=>[`Connected remote session "${p}" tenant "${u}" run "${f}" ${I.leaseId?`lease ${I.leaseId}`:"lease pending"}`,A?.message,_?.message].filter(e=>!!e).join("\n")),!0},tp=async({flags:e,client:t})=>{let{session:n,stateDir:o,state:r}=th(e);if(!r)return tw(e,n),!0;let s=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await eJ(r.metro),await ez({stateDir:o,state:r});let a=!1;if(r.leaseId)try{a=(await t.leases.release({tenant:r.tenant,runId:r.runId,leaseId:r.leaseId})).released}catch{}return eT({stateDir:o,session:s}),tf(e,{connected:!1,session:s,released:a},()=>`Disconnected remote session "${s}".`),!0},tg=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new h("INVALID_ARGS","connection accepts only: status");let{session:n,state:o}=th(t);if(!o)return tw(t,n),!0;let r=tv(o),s=function(e){if(!e.runtime&&tI(e.remoteConfigPath))return ty(e.remoteConfigPath)}(o);return tf(t,tA(o,s),()=>[`Connected remote session "${o.session}".`,`tenant=${o.tenant} runId=${o.runId} leaseId=${o.leaseId??"pending"} backend=${o.leaseBackend??"pending"}`,`remoteConfig=${o.remoteConfigPath}`,o.runtime?"metro=prepared":"metro=not-prepared",r?.message,s?.message].filter(e=>!!e).join("\n")),!0};function th(e){let t=e.session??"default",n=N(e.stateDir).baseDir;return{session:t,stateDir:n,state:eE({stateDir:n,session:t})??(e.session?null:eO({stateDir:n}))}}function tw(e,t){tf(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function tv(e){if(!e.leaseId)return{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."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function ty(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 tI(e){try{let t=r({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function tA(e,t){let o=tv(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return n.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...o?{leasePreparation:o}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t_=async({positionals:e,flags:n})=>{let o=e[0]??"status",r=N(n.stateDir).baseDir;if("status"===o){var s;let e,t=(e=e5({stateDir:(s={stateDir:r}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:ti(e.expiresAt,s.now)}:{authenticated:!1,source:"none"};return tf(n,t,()=>{var e;return(e=t).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("\n"):"Not authenticated."}),!0}if("login"===o){let e=await e9({stateDir:r,flags:n,commandLabel:"agent-device auth login"});return tf(n,{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("logout"===o){let e,o=(e=e6({stateDir:r}.stateDir),!!t.existsSync(e)&&(t.rmSync(e,{force:!0}),!0));return tf(n,{authenticated:!1,removed:o},()=>o?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new h("INVALID_ARGS","auth accepts only: status, login, logout")},tS=new Set(["id","text","label"]),tk=new Set(["enabled","selected"]),tD={open:function(e){var t,n,o;let r,s,a,[i,l]=e.positionals;if(!i)return{kind:"unsupported",message:"open requires an app id or URL"};if(tT(i))return{kind:"commands",commands:[{openLink:i}]};let c=(t=e,n=i,(a=(o=t,r=o.flags?.launchArgs,s={},o.flags?.relaunch===!0&&(s.stopApp=!0),o.flags?.clearAppState===!0&&(s.clearState=!0),Array.isArray(r)&&r.length>0&&(s.launchArguments=r),Object.keys(s).length>0?s:void 0))?{launchApp:{appId:n,...a}}:"launchApp");return l&&tT(l)?{kind:"config",appId:i,commands:[c,{openLink:l}]}:l?{kind:"unsupported",message:"open with a non-URL second argument is unsupported"}:{kind:"config",appId:i,commands:[c]}},click:tC,press:tC,longpress:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"longpress requires a target"};let o=tR(t,n);return o?{kind:"commands",commands:[{longPressOn:o}],warnings:(function(e){let[t,n,o]=e.positionals,r=tx(t)&&tx(n)?o:n;return r&&tx(r)?[Number(r)]:[]})(e).map(tN)}:{kind:"unsupported",message:"longpress target is not Maestro-compatible"}},fill:function(e){let[t,n]=e.positionals;if(!t||void 0===n)return{kind:"unsupported",message:"fill requires a target and text"};let o=tR(t);return o?{kind:"commands",commands:[{tapOn:o},{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"}},type:function(e){var t;let[n]=e.positionals;if(void 0===n)return{kind:"unsupported",message:"type requires text"};let o=0!==(t=n).length&&[...t].every(e=>"\b"===e)?t.length:null;return null!==o?{kind:"commands",commands:[{eraseText:o}]}:{kind:"commands",commands:[{inputText:n}]}},keyboard:function(e){let[t]=e.positionals;return"dismiss"===t?{kind:"commands",commands:["hideKeyboard"]}:"enter"===t||"return"===t?{kind:"commands",commands:[{pressKey:"Enter"}]}:{kind:"unsupported",message:`keyboard ${t??""}`.trim()}},back:()=>({kind:"commands",commands:["back"]}),wait:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"wait requires a target or duration"};if(tx(t))return{kind:"commands",commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:["wait <ms> exports as waitForAnimationToEnd and may return before the full duration"]};if("text"===t&&n)return{kind:"commands",commands:[{extendedWaitUntil:{visible:n,timeout:tP(e,17e3)}}]};let o=tU(t);return o?{kind:"commands",commands:[{extendedWaitUntil:{visible:o,timeout:tP(e,17e3)}}]}:{kind:"unsupported",message:"wait selector is not Maestro-compatible"}},find:function(e){let[t,n,o]=e.positionals;return"text"===t&&n&&o?"exists"===o?{kind:"commands",commands:[{assertVisible:n}]}:"missing"===o||"not-exists"===o?{kind:"commands",commands:[{assertNotVisible:n}]}:{kind:"unsupported",message:`find text assertion "${o}" is unsupported`}:{kind:"unsupported",message:"only find text <query> exists|missing exports to Maestro"}},screenshot:function(e){let[t]=e.positionals;return t?{kind:"commands",commands:[{takeScreenshot:t}]}:{kind:"unsupported",message:"screenshot requires an output path"}},scroll:function(e){let[t]=e.positionals;return t&&"down"!==t?{kind:"unsupported",message:`scroll ${t} is not exported yet`}:{kind:"commands",commands:["scroll"]}},swipe:function(e){var t,n;let o,r=function(e){let[t,n,o,r,s]=e.positionals;if(tx(t)&&tx(n)&&tx(o)&&tx(r))return{start:O(t,n),end:O(o,r),...s&&tx(s)?{duration:Number(s)}:{}}}(e);if(!r)return{kind:"unsupported",message:"only coordinate swipe exports to Maestro"};let s=(t=e,Number.isInteger(o=t.flags?.count??1)&&o>=1?o:null);if(null===s)return{kind:"unsupported",message:"swipe count must be a positive integer"};let a=(n=e,n.flags?.pauseMs!==void 0?"swipe --pause-ms has no Maestro equivalent":n.flags?.pattern&&"one-way"!==n.flags.pattern?"swipe ping-pong pattern has no Maestro equivalent":void 0);return a?{kind:"unsupported",message:a}:{kind:"commands",commands:Array.from({length:s},()=>({swipe:r}))}}};function tC(e){var t,n,o,r,s;let a,i,[l,c]=e.positionals;if(!l)return{kind:"unsupported",message:`${e.command} requires a target`};let d=tR(l,c);if(!d)return{kind:"unsupported",message:"tap target is not Maestro-compatible"};let u=(a=(n=t=e,n.flags?.jitterPx!==void 0?"tap --jitter-px has no Maestro equivalent":n.flags?.clickButton&&"primary"!==n.flags.clickButton?`tap --button ${n.flags.clickButton} has no Maestro equivalent`:void 0))?{ok:!1,message:a}:{ok:!0,options:(o=t,i={},"number"==typeof o.flags?.count&&o.flags.count>1&&(i.repeat=o.flags.count),"number"==typeof o.flags?.intervalMs&&o.flags.intervalMs>0&&(i.delay=o.flags.intervalMs),i)};return u.ok?e.flags?.doubleTap===!0?{kind:"commands",commands:[{doubleTapOn:d}],warnings:tb(e,"doubleTapOn")}:"number"==typeof e.flags?.holdMs?{kind:"commands",commands:[{longPressOn:d}],warnings:[tN(e.flags.holdMs),...tb(e,"longPressOn")]}:{kind:"commands",commands:[(r=d,0===Object.keys(s=u.options).length?{tapOn:r}:"string"==typeof r?{tapOn:{text:r,...s}}:r&&"object"==typeof r&&!Array.isArray(r)?{tapOn:{...r,...s}}:{tapOn:r})]}:{kind:"unsupported",message:u.message}}function tN(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function tb(e,t){let n=[];return"number"==typeof e.flags?.count&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),"number"==typeof e.flags?.intervalMs&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function tR(e,t){return tx(e)&&tx(t)?{point:O(e,t)}:e.startsWith("@")?null:tU(e)}function tU(e){let t;try{t=x(e)}catch{return e.includes("=")||e.includes("||")?null:e}let n=function(e){if(e.length<=1)return null;let t=e.flatMap(e=>1===e.terms.length&&tS.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||0===t.length)return null;let n=t[0];return"string"!=typeof n?null:t.every(e=>e===n)?n:null}(t.selectors);return null!==n?n:1!==t.selectors.length?null:function(e){let t={};for(let r of e.terms){var n,o;if(n=t,o=r,tS.has(o.key)?"string"!=typeof o.value||!!n.id||!!n.text||!!n.label||(n[o.key]=o.value,!!0):!tk.has(o.key)||"boolean"!=typeof o.value||(n[o.key]=o.value,!!0))return null}return Object.keys(t).length>0?t:null}(t.selectors[0])}function tE(e,t,n,o){for(let r of t??[])e.warnings.push({line:o,action:tL(n),message:r})}function tP(e,t){let n=e.positionals.at(-1);return n&&tx(n)?Number(n):t}function tL(e){return[e.command,...e.positionals??[]].join(" ").trim()}function tT(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function tx(e){return void 0!==e&&Number.isFinite(Number(e))}let tB=async e=>{let{positionals:t}=e;return"export"!==t[0]?function({positionals:e,flags:t}){if(e.length>1)throw new h("INVALID_ARGS","replay accepts exactly one input path: replay <path>");if(void 0!==t.replayExportFormat||void 0!==t.out)throw new h("INVALID_ARGS","replay --format/--out are only supported with replay export.");return!1}(e):await tM(e)};async function tM({positionals:e,flags:n}){let r;var s,a=e,i=n;if(a.length>2)throw new h("INVALID_ARGS","replay export accepts exactly one input path: replay export <file.ad>");if(i.replayUpdate)throw new h("INVALID_ARGS","replay export does not support --update.");if(i.replayMaestro)throw new h("INVALID_ARGS","replay export reads .ad files; omit --maestro.");if(i.replayEnv?.length)throw new h("INVALID_ARGS","replay export does not evaluate --env substitutions.");let l=i.replayExportFormat??"maestro";if("maestro"!==l)throw new h("INVALID_ARGS",`Unsupported replay export format: ${l}`);let c=e[1];if(!c)throw new h("INVALID_ARGS","replay export requires an input path.");let d=V(c),u=function(e,t={}){var n,o,r,s;let a={config:(n=t.metadata,n?.env&&Object.keys(n.env).length>0?{env:n.env}:{}),warnings:[],unsupported:[]},i=[];for(let[n,r]of e.entries()){let e=t.actionLines?.[n]??n+1,s=(o=r,tD[o.command]?.(o)??{kind:"unsupported",message:`${o.command} has no Maestro equivalent`});switch(s.kind){case"commands":i.push(...s.commands),tE(a,s.warnings,r,e);break;case"config":(function(e,t,n,o){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:o,action:tL(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})})(a,s.appId,r,e),i.push(...s.commands),tE(a,s.warnings,r,e);break;case"unsupported":a.unsupported.push({line:e,action:tL(r),message:s.message})}}if(a.unsupported.length>0)throw new h("INVALID_ARGS",`Cannot export replay to Maestro YAML: unsupported .ad action ${a.unsupported.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join("; ")}.`,{unsupported:a.unsupported});return{yaml:(r=a.config,s=i,B(Object.keys(r).length>0?[r,s]:[s])),warnings:a.warnings}}((r=M(s=t.readFileSync(d,"utf8"))).actions,{actionLines:r.actionLines,metadata:$(s)}),f="string"==typeof n.out?V(n.out):void 0;for(let e of(f&&(t.mkdirSync(o.dirname(f),{recursive:!0}),t.writeFileSync(f,u.yaml)),u.warnings))process.stderr.write(`Warning: line ${e.line}: ${e.message}
|
|
13
|
-
`);return
|
|
10
|
+
`)}}function tl(e,t){(e?.stderr??process.stderr).write(t)}function tc(e,t){if(!e)return!1;let n=Date.parse(e);return!Number.isFinite(n)||n<=(t?.()??Date.now())}function td(e){return"string"==typeof e&&e.trim().length>0}async function tu(e){await new Promise(t=>setTimeout(t,e))}async function tf(e){let s=await e6({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),a=await tm({cloudBaseUrl:s.cloudBaseUrl,accessToken:s.accessToken,fetchImpl:e.fetchImpl}),i=function(e){try{return r(e)}catch(n){let t=p(n);throw new h("COMMAND_FAILED","Cloud connection profile returned invalid remote config.",{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(e){var r;let s=function e(t){return Array.isArray(t)?t.map(e):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).filter(([,e])=>void 0!==e).sort(([e],[t])=>e.localeCompare(t)).map(([t,n])=>[t,e(n)])):t}(e.profile),a=o.join(e.stateDir,"remote-connections","generated");t.mkdirSync(a,{recursive:!0,mode:448});let i=o.join(a,`cloud-${(r=s,n.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16))}.json`);t.writeFileSync(i,`${JSON.stringify(s,null,2)}
|
|
11
|
+
`,{mode:384});try{t.chmodSync(i,384)}catch{}return i}({stateDir:e.stateDir,profile:a}),cwd:e.cwd,env:e.env});return{flags:{...eH(i.profile),...e.flags,remoteConfig:i.resolvedPath,daemonAuthToken:s.accessToken},remoteConfigPath:i.resolvedPath}}async function tm(e){let t=e.fetchImpl??fetch,n=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});var o=await e2(n,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${n.status}).`,rejectedMessage:"Cloud connection profile endpoint rejected the request."});if(!o||"object"!=typeof o||Array.isArray(o))throw new h("COMMAND_FAILED","Cloud connection profile response is invalid.");let r=o.connection;if(!r||"object"!=typeof r)throw new h("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(void 0!==r.remoteConfigProfile){var s=r.remoteConfigProfile;if(!s||"object"!=typeof s||Array.isArray(s))throw new h("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(s).length)throw new h("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return s}throw new h("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}function tp(e,t,n){var o;if(e.json)return void x({success:!0,data:t});let r=n?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
|
|
12
|
+
`))}let tg=async({flags:e,client:t})=>{var o,s,a,i;let l=N(e.stateDir).baseDir,c=e.remoteConfig?function(e){if(!e.remoteConfig)throw new h("INVALID_ARGS","connect requires --remote-config <path>.");let t=r({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tf({flags:e,stateDir:l,cwd:process.cwd(),env:process.env}),d=c.flags,u=d.tenant,f=d.runId;if(!u)throw new h("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!f)throw new h("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!d.daemonBaseUrl)throw new h("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let m=d.session?null:eV({stateDir:l}),p=d.session??m?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${n.randomBytes(3).toString("hex")}`;if(!eL({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${n.randomBytes(2).toString("hex")}`}(l),g=eB(c.remoteConfigPath),w=eT(d),v=m?.session===p?m:eL({stateDir:l,session:p});if(v&&(o=v,s={flags:d,session:p,remoteConfigPath:c.remoteConfigPath,remoteConfigHash:g,desiredLeaseBackend:eQ(d),daemon:w},o.remoteConfigPath!==s.remoteConfigPath||o.remoteConfigHash!==s.remoteConfigHash||o.session!==s.session||o.tenant!==s.flags.tenant||o.runId!==s.flags.runId||void 0!==s.desiredLeaseBackend&&o.leaseBackend!==s.desiredLeaseBackend||void 0!==s.flags.platform&&o.platform!==s.flags.platform||void 0!==s.flags.target&&o.target!==s.flags.target||(a=o.daemon,i=s.daemon,(a?.baseUrl??void 0)!==(i?.baseUrl??void 0)||(a?.transport??void 0)!==(i?.transport??void 0)||(a?.serverMode??void 0)!==(i?.serverMode??void 0)))&&!d.force)throw new h("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:p,remoteConfig:v.remoteConfigPath});let y=new Date().toISOString(),I={version:1,session:p,remoteConfigPath:c.remoteConfigPath,remoteConfigHash:g,daemon:w,tenant:u,runId:f,leaseId:v&&!d.force?v.leaseId:void 0,leaseBackend:v&&!d.force?v.leaseBackend:eQ(d),platform:d.platform??(v&&!d.force?v.platform:void 0),target:d.target??(v&&!d.force?v.target:void 0),runtime:v&&!d.force?v.runtime:void 0,metro:v&&!d.force?v.metro:void 0,connectedAt:v&&!d.force?v.connectedAt:y,updatedAt:y};ex({stateDir:l,state:I}),v&&d.force&&(await eZ(v.metro),await eY({stateDir:l,state:v}),await eX(t,v));let A=tI(I),_=function(e,t){if(!t.runtime&&(e0(e)||t_(t.remoteConfigPath)))return tA(t.remoteConfigPath)}(d,I);return tp(d,tS(I,_),()=>[`Connected remote session "${p}" tenant "${u}" run "${f}" ${I.leaseId?`lease ${I.leaseId}`:"lease pending"}`,A?.message,_?.message].filter(e=>!!e).join("\n")),!0},th=async({flags:e,client:t})=>{let{session:n,stateDir:o,state:r}=tv(e);if(!r)return ty(e,n),!0;let s=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await eZ(r.metro),await eY({stateDir:o,state:r});let a=!1;if(r.leaseId)try{a=(await t.leases.release({tenant:r.tenant,runId:r.runId,leaseId:r.leaseId})).released}catch{}return eM({stateDir:o,session:s}),tp(e,{connected:!1,session:s,released:a},()=>`Disconnected remote session "${s}".`),!0},tw=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new h("INVALID_ARGS","connection accepts only: status");let{session:n,state:o}=tv(t);if(!o)return ty(t,n),!0;let r=tI(o),s=function(e){if(!e.runtime&&t_(e.remoteConfigPath))return tA(e.remoteConfigPath)}(o);return tp(t,tS(o,s),()=>[`Connected remote session "${o.session}".`,`tenant=${o.tenant} runId=${o.runId} leaseId=${o.leaseId??"pending"} backend=${o.leaseBackend??"pending"}`,`remoteConfig=${o.remoteConfigPath}`,o.runtime?"metro=prepared":"metro=not-prepared",r?.message,s?.message].filter(e=>!!e).join("\n")),!0};function tv(e){let t=e.session??"default",n=N(e.stateDir).baseDir;return{session:t,stateDir:n,state:eL({stateDir:n,session:t})??(e.session?null:eV({stateDir:n}))}}function ty(e,t){tp(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function tI(e){if(!e.leaseId)return{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."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function tA(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 t_(e){try{let t=r({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function tS(e,t){let o=tI(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return n.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...o?{leasePreparation:o}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let tk=async({positionals:e,flags:n})=>{let o=e[0]??"status",r=N(n.stateDir).baseDir;if("status"===o){var s;let e,t=(e=e7({stateDir:(s={stateDir:r}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:tc(e.expiresAt,s.now)}:{authenticated:!1,source:"none"};return tp(n,t,()=>{var e;return(e=t).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("\n"):"Not authenticated."}),!0}if("login"===o){let e=await e9({stateDir:r,flags:n,commandLabel:"agent-device auth login"});return tp(n,{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("logout"===o){let e,o=(e=te({stateDir:r}.stateDir),!!t.existsSync(e)&&(t.rmSync(e,{force:!0}),!0));return tp(n,{authenticated:!1,removed:o},()=>o?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new h("INVALID_ARGS","auth accepts only: status, login, logout")},tD=new Set(["id","text","label"]),tC=new Set(["enabled","selected"]),tN={open:function(e){var t,n,o;let r,s,a,[i,l]=e.positionals;if(!i)return{kind:"unsupported",message:"open requires an app id or URL"};if(tM(i))return{kind:"commands",commands:[{openLink:i}]};let c=(t=e,n=i,(a=(o=t,r=o.flags?.launchArgs,s={},o.flags?.relaunch===!0&&(s.stopApp=!0),o.flags?.clearAppState===!0&&(s.clearState=!0),Array.isArray(r)&&r.length>0&&(s.launchArguments=r),Object.keys(s).length>0?s:void 0))?{launchApp:{appId:n,...a}}:"launchApp");return l&&tM(l)?{kind:"config",appId:i,commands:[c,{openLink:l}]}:l?{kind:"unsupported",message:"open with a non-URL second argument is unsupported"}:{kind:"config",appId:i,commands:[c]}},click:tb,press:tb,longpress:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"longpress requires a target"};let o=tE(t,n);return o?{kind:"commands",commands:[{longPressOn:o}],warnings:(function(e){let[t,n,o]=e.positionals,r=tB(t)&&tB(n)?o:n;return r&&tB(r)?[Number(r)]:[]})(e).map(tR)}:{kind:"unsupported",message:"longpress target is not Maestro-compatible"}},fill:function(e){let[t,n]=e.positionals;if(!t||void 0===n)return{kind:"unsupported",message:"fill requires a target and text"};let o=tE(t);return o?{kind:"commands",commands:[{tapOn:o},{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"}},type:function(e){var t;let[n]=e.positionals;if(void 0===n)return{kind:"unsupported",message:"type requires text"};let o=0!==(t=n).length&&[...t].every(e=>"\b"===e)?t.length:null;return null!==o?{kind:"commands",commands:[{eraseText:o}]}:{kind:"commands",commands:[{inputText:n}]}},keyboard:function(e){let[t]=e.positionals;return"dismiss"===t?{kind:"commands",commands:["hideKeyboard"]}:"enter"===t||"return"===t?{kind:"commands",commands:[{pressKey:"Enter"}]}:{kind:"unsupported",message:`keyboard ${t??""}`.trim()}},back:()=>({kind:"commands",commands:["back"]}),wait:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"wait requires a target or duration"};if(tB(t))return{kind:"commands",commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:["wait <ms> exports as waitForAnimationToEnd and may return before the full duration"]};if("text"===t&&n)return{kind:"commands",commands:[{extendedWaitUntil:{visible:n,timeout:tx(e,17e3)}}]};let o=tP(t);return o?{kind:"commands",commands:[{extendedWaitUntil:{visible:o,timeout:tx(e,17e3)}}]}:{kind:"unsupported",message:"wait selector is not Maestro-compatible"}},find:function(e){let[t,n,o]=e.positionals;return"text"===t&&n&&o?"exists"===o?{kind:"commands",commands:[{assertVisible:n}]}:"missing"===o||"not-exists"===o?{kind:"commands",commands:[{assertNotVisible:n}]}:{kind:"unsupported",message:`find text assertion "${o}" is unsupported`}:{kind:"unsupported",message:"only find text <query> exists|missing exports to Maestro"}},screenshot:function(e){let[t]=e.positionals;return t?{kind:"commands",commands:[{takeScreenshot:t}]}:{kind:"unsupported",message:"screenshot requires an output path"}},scroll:function(e){let[t]=e.positionals;return t&&"down"!==t?{kind:"unsupported",message:`scroll ${t} is not exported yet`}:{kind:"commands",commands:["scroll"]}},swipe:function(e){var t,n;let o,r=function(e){let[t,n,o,r,s]=e.positionals;if(tB(t)&&tB(n)&&tB(o)&&tB(r))return{start:O(t,n),end:O(o,r),...s&&tB(s)?{duration:Number(s)}:{}}}(e);if(!r)return{kind:"unsupported",message:"only coordinate swipe exports to Maestro"};let s=(t=e,Number.isInteger(o=t.flags?.count??1)&&o>=1?o:null);if(null===s)return{kind:"unsupported",message:"swipe count must be a positive integer"};let a=(n=e,n.flags?.pauseMs!==void 0?"swipe --pause-ms has no Maestro equivalent":n.flags?.pattern&&"one-way"!==n.flags.pattern?"swipe ping-pong pattern has no Maestro equivalent":void 0);return a?{kind:"unsupported",message:a}:{kind:"commands",commands:Array.from({length:s},()=>({swipe:r}))}}};function tb(e){var t,n,o,r,s;let a,i,[l,c]=e.positionals;if(!l)return{kind:"unsupported",message:`${e.command} requires a target`};let d=tE(l,c);if(!d)return{kind:"unsupported",message:"tap target is not Maestro-compatible"};let u=(a=(n=t=e,n.flags?.jitterPx!==void 0?"tap --jitter-px has no Maestro equivalent":n.flags?.clickButton&&"primary"!==n.flags.clickButton?`tap --button ${n.flags.clickButton} has no Maestro equivalent`:void 0))?{ok:!1,message:a}:{ok:!0,options:(o=t,i={},"number"==typeof o.flags?.count&&o.flags.count>1&&(i.repeat=o.flags.count),"number"==typeof o.flags?.intervalMs&&o.flags.intervalMs>0&&(i.delay=o.flags.intervalMs),i)};return u.ok?e.flags?.doubleTap===!0?{kind:"commands",commands:[{doubleTapOn:d}],warnings:tU(e,"doubleTapOn")}:"number"==typeof e.flags?.holdMs?{kind:"commands",commands:[{longPressOn:d}],warnings:[tR(e.flags.holdMs),...tU(e,"longPressOn")]}:{kind:"commands",commands:[(r=d,0===Object.keys(s=u.options).length?{tapOn:r}:"string"==typeof r?{tapOn:{text:r,...s}}:r&&"object"==typeof r&&!Array.isArray(r)?{tapOn:{...r,...s}}:{tapOn:r})]}:{kind:"unsupported",message:u.message}}function tR(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function tU(e,t){let n=[];return"number"==typeof e.flags?.count&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),"number"==typeof e.flags?.intervalMs&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function tE(e,t){return tB(e)&&tB(t)?{point:O(e,t)}:e.startsWith("@")?null:tP(e)}function tP(e){let t;try{t=T(e)}catch{return e.includes("=")||e.includes("||")?null:e}let n=function(e){if(e.length<=1)return null;let t=e.flatMap(e=>1===e.terms.length&&tD.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||0===t.length)return null;let n=t[0];return"string"!=typeof n?null:t.every(e=>e===n)?n:null}(t.selectors);return null!==n?n:1!==t.selectors.length?null:function(e){let t={};for(let r of e.terms){var n,o;if(n=t,o=r,tD.has(o.key)?"string"!=typeof o.value||!!n.id||!!n.text||!!n.label||(n[o.key]=o.value,!!0):!tC.has(o.key)||"boolean"!=typeof o.value||(n[o.key]=o.value,!!0))return null}return Object.keys(t).length>0?t:null}(t.selectors[0])}function tL(e,t,n,o){for(let r of t??[])e.warnings.push({line:o,action:tT(n),message:r})}function tx(e,t){let n=e.positionals.at(-1);return n&&tB(n)?Number(n):t}function tT(e){return[e.command,...e.positionals??[]].join(" ").trim()}function tM(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function tB(e){return void 0!==e&&Number.isFinite(Number(e))}let tO=async e=>{let{positionals:t}=e;return"export"!==t[0]?function({positionals:e,flags:t}){if(e.length>1)throw new h("INVALID_ARGS","replay accepts exactly one input path: replay <path>");if(void 0!==t.replayExportFormat||void 0!==t.out)throw new h("INVALID_ARGS","replay --format/--out are only supported with replay export.");return!1}(e):await t$(e)};async function t$({positionals:e,flags:n}){let r;var s,a=e,i=n;if(a.length>2)throw new h("INVALID_ARGS","replay export accepts exactly one input path: replay export <file.ad>");if(i.replayUpdate)throw new h("INVALID_ARGS","replay export does not support --update.");if(i.replayMaestro)throw new h("INVALID_ARGS","replay export reads .ad files; omit --maestro.");if(i.replayEnv?.length)throw new h("INVALID_ARGS","replay export does not evaluate --env substitutions.");let l=i.replayExportFormat??"maestro";if("maestro"!==l)throw new h("INVALID_ARGS",`Unsupported replay export format: ${l}`);let c=e[1];if(!c)throw new h("INVALID_ARGS","replay export requires an input path.");let d=V(c),u=function(e,t={}){var n,o,r,s;let a={config:(n=t.metadata,n?.env&&Object.keys(n.env).length>0?{env:n.env}:{}),warnings:[],unsupported:[]},i=[];for(let[n,r]of e.entries()){let e=t.actionLines?.[n]??n+1,s=(o=r,tN[o.command]?.(o)??{kind:"unsupported",message:`${o.command} has no Maestro equivalent`});switch(s.kind){case"commands":i.push(...s.commands),tL(a,s.warnings,r,e);break;case"config":(function(e,t,n,o){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:o,action:tT(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})})(a,s.appId,r,e),i.push(...s.commands),tL(a,s.warnings,r,e);break;case"unsupported":a.unsupported.push({line:e,action:tT(r),message:s.message})}}if(a.unsupported.length>0)throw new h("INVALID_ARGS",`Cannot export replay to Maestro YAML: unsupported .ad action ${a.unsupported.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join("; ")}.`,{unsupported:a.unsupported});return{yaml:(r=a.config,s=i,M(Object.keys(r).length>0?[r,s]:[s])),warnings:a.warnings}}((r=B(s=t.readFileSync(d,"utf8"))).actions,{actionLines:r.actionLines,metadata:$(s)}),f="string"==typeof n.out?V(n.out):void 0;for(let e of(f&&(t.mkdirSync(o.dirname(f),{recursive:!0}),t.writeFileSync(f,u.yaml)),u.warnings))process.stderr.write(`Warning: line ${e.line}: ${e.message}
|
|
13
|
+
`);return tp(n,{format:n.replayExportFormat??"maestro",sourcePath:d,...f?{path:f}:{yaml:u.yaml},warnings:u.warnings},()=>f??u.yaml),!0}let tV={...Q,...z,...j,...q,...ee,...K,...eo,...ea,...W,...et,...Y,...en,...es,...X};async function tG(e){return(await tj(e)).result}async function tj(e){var t,n,o;let r=(t=e.command,n=e.positionals,o=e.flags,tV[t](n,o)),s=await el(e.client,e.command,r);return{result:s,cliOutput:ei({name:e.command,input:r,result:s})}}let tK={connect:tg,disconnect:th,connection:tw,auth:tk,replay:tO,screenshot:async({positionals:e,flags:t,client:n})=>{let o=await tG({client:n,command:"screenshot",positionals:e,flags:t});return tp(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},diff:async({positionals:e,flags:t,client:n})=>{var o;if("snapshot"===e[0]){let o=await tG({client:n,command:"diff",positionals:e,flags:t});return tp(t,o,()=>E(o)),!0}if("screenshot"!==e[0])return!1;let r=t.baseline;if(!r||"string"!=typeof r)throw new h("INVALID_ARGS","diff screenshot requires --baseline <path>");let s=V(r),a="string"==typeof t.out?V(t.out):void 0,i=e[1];if(e.length>2)throw new h("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=em({backend:(o=n,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,n)=>{let r=await o.capture.screenshot({path:t,session:e.session,overlayRefs:n?.overlayRefs,fullscreen:n?.fullscreen,stabilize:n?.stabilize,surface:n?.surface});return{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}}}}),artifacts:ec(),sessions:{get:e=>({name:e}),set:()=>{}},policy:eu()}),c=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:s},current:i?{kind:"path",path:V(i)}:{kind:"live"},...a?{out:{kind:"path",path:a}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(t.threshold),overlayRefs:t.overlayRefs,surface:t.surface});return tp(t,c,()=>P(c)),!0}};async function tF(e){let t={...e.flags},n=tK[e.command];return!!(n&&await n({...e,flags:t}))||!!c(e.command)&&await tH({...e,command:e.command,flags:t})}async function tH(e){let{runGenericClientBackedCommand:t}=await import("./generic.js");return await t(e)}function tq(e,t,n){return n||(e.push(t),"")}async function tW(e,t,n){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let n=[],o={serverBaseUrl:tq(n,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:tq(n,"metroBearerToken",e.metroBearerToken),tenantId:tq(n,"tenant",e.tenant),runId:tq(n,"runId",e.runId),leaseId:tq(n,"leaseId",e.leaseId)};if(n.length>0)throw new h("INVALID_ARGS",`react-devtools remote bridge requires ${n.join(", ")}.`,{missing:n});return o}(o);if(!r)return n();let s=t.stateDir??process.cwd(),a=t.session??o?.session??"default",i=o?.remoteConfig??`${r.tenantId}:${r.runId}:${r.leaseId}`;if("stop"===e[0])try{return await n()}finally{await eP({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await eE({projectRoot:t.cwd??process.cwd(),stateDir:s,serverBaseUrl:r.serverBaseUrl,bearerToken:r.bearerToken,bridgeScope:{tenantId:r.tenantId,runId:r.runId,leaseId:r.leaseId},session:a,profileKey:i,consumerKey:a,env:t.env??process.env}),await n()}async function tJ(e,t={}){let n=t.cwd??process.cwd(),o=t.env??process.env,r=await tW(e,t,async()=>(await R("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==r&&"wait"===(s=e)[0]&&s.includes("--connected")&&"ios-instance"===a?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf 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`.\n"),r}async function tz(e,t){switch(e[0]){case"setup":{let e=await ed({stateDir:t.stateDir});return tZ(t.flags.json,"Managed web backend installed.",{status:e}),0}case"doctor":{let e=await ef({stateDir:t.stateDir});return tZ(t.flags.json,0===e.exitCode?"Web backend is healthy.":"Web backend doctor reported issues.",e),e.exitCode}default:throw new h("INVALID_ARGS","web requires setup or doctor")}}function tZ(e,t,n){e?x({success:!0,data:n}):process.stdout.write(`${t}
|
|
14
|
+
`)}function tY(e,t={}){let n=tX(t),o={...e};return n.defaultPlatform&&void 0===o.platform&&(o.platform=n.defaultPlatform),o}function tX(e){var t,n,o,r;let s,a=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new h("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(a.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??a.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(n=e.policyOverrides,o=a,r=l,(s=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new h("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(o.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||r?"reject":void 0))}}let tQ={sendToDaemon:eh},t0=new Set(["launchUrl","kind","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),t1=new Set(["connect","connection","close","disconnect","metro","session"]);async function t3(e,n=tQ){let a=_(),l=ep(),c=function(e){try{let t=eD(e);return t8(t.command??"",t.providedFlags)}catch{return e.includes("--debug")||e.includes("-v")||e.includes("--verbose")}}(e),d=e.includes("--json"),u=function(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("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await S({session:u,requestId:a,command:e[0],debug:c},async()=>{var u,m,y,I,A,_,S,b,R,U,E,P,T,M,B,O,$;let j,K,H,q,W,J,z;try{let n,s,a,l,c,d,p,g;u={cwd:process.cwd(),env:process.env},n=eD(e),s=u?.env??process.env,a=u?.cwd??process.cwd(),I=n.command,l=null!==I&&(m={remoteConfig:n.flags.remoteConfig,cwd:a,env:s}).remoteConfig?{...eH(r({configPath:m.remoteConfig,cwd:m.cwd,env:m.env}).profile),remoteConfig:m.remoteConfig}:{},p=ev((c=(y={command:n.command,cwd:a,cliFlags:n.flags,env:s}).env??process.env,d=ev({},function(e){let n={};for(let o of e)ev(n,function(e,n){let o,r;if(!t.existsSync(e)){if(n)throw new h("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{o=t.readFileSync(e,"utf8")}catch(t){throw new h("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{r=JSON.parse(o)}catch(t){throw new h("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!r||"object"!=typeof r||Array.isArray(r))throw new h("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[o,r]of Object.entries(e)){if("installSource"===o){n.installSource=F(r,t);continue}let e=e_.get(o);if(!e)throw new h("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new h("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);n[o]=i(ek(e),r,t,o)}return n}(r,`config file ${e}`)}(o.path,o.required));return n}((A=y.cwd,_=y.cliFlags.config,S=c,(g=_??S.AGENT_DEVICE_CONFIG)?[{path:(b=g,R=A,U=S,V(b,{cwd:R,env:U})),required:!0}]:[{path:(E=S,o.join(G("~",{env:E}),".agent-device","config.json")),required:!1},{path:o.resolve(A,"agent-device.json"),required:!1}]))),ev(d,function(e,t){var n,o,r;let s={};for(let a of eA.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===a.key)continue;let t=a.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(s[a.key]=(n=t.value,o=`environment variable ${t.name}`,r=t.name,i(ek(a),n,o,r)))}return s}(c,y.command))),l),j={...function(e,t){let n=t?.strictFlags??!0,o=[...e.warnings],r=ev({json:!1,help:!1,version:!1},t?.defaultFlags??{});ev(r,e.flags);let s=e.providedFlags.filter(t=>!eS(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new h("INVALID_ARGS",l);for(let e of(o.push(l),s))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eS(t,e.command)||delete r[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new h("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),f(e.command,r),"batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new h("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(n,{strictFlags:u?.strictFlags,defaultFlags:p}),providedFlags:n.providedFlags}}catch(t){C({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=g(t,{diagnosticId:k().diagnosticId,logPath:D({force:!0})??void 0});d?x({success:!1,error:e}):L(e,{showDetails:c}),process.exit(1);return}for(let e of j.warnings)process.stderr.write(`Warning: ${e}
|
|
14
15
|
`);j.flags.version&&(process.stdout.write(`${l}
|
|
15
16
|
`),process.exit(0));let Z="help"===j.command,Y=j.flags.help;if(Z||Y){Z&&j.positionals.length>1&&(L(new h("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=Z?j.positionals[0]:j.command;e||(process.stdout.write(`${v()}
|
|
16
|
-
`),process.exit(0));let t=w(
|
|
17
|
+
`),process.exit(0));let t=w(eR(e));t&&(process.stdout.write(t),process.exit(0)),L(new h("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${v()}
|
|
17
18
|
`),process.exit(1)}j.command||(process.stdout.write(`${v()}
|
|
18
|
-
`),process.exit(1));let{command:X,positionals:Q}=j,ee=
|
|
19
|
+
`),process.exit(1));let{command:X,positionals:Q}=j,ee=t8(X,j.providedFlags),et=new Set(j.providedFlags.map(e=>e.key));try{H=(K=tX({policyOverrides:j.flags,configuredPlatform:j.flags.platform,configuredSession:j.flags.session})).lockPolicy?{...j.flags}:tY(j.flags,{policyOverrides:j.flags,configuredPlatform:j.flags.platform,configuredSession:j.flags.session}),q=N(H.stateDir),W=H.session??"default",P={command:X,explicitFlagKeys:et,stateDir:q.baseDir,session:W,remoteConfig:H.remoteConfig,hasResolvedSession:void 0!==H.session},z=(J="connect"===P.command||"connection"===P.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?s({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=eL(e)??(e.allowActiveFallback?eV({stateDir:e.stateDir}):null);if(!o||n&&o.remoteConfigPath!==n)return null;if(t&&eB(o.remoteConfigPath)!==o.remoteConfigHash)throw new h("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let a=function(e,t){try{return r({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(o,e);return{runtime:o.runtime,flags:{...a,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??a.daemonBaseUrl,daemonTransport:o.daemon?.transport??a.daemonTransport,daemonServerMode:o.daemon?.serverMode??a.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??a.platform,target:o.target??a.target}}}({stateDir:P.stateDir,session:P.session,remoteConfig:P.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!P.explicitFlagKeys.has("session")&&(!P.remoteConfig||"disconnect"===P.command||!P.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==P.command}))?function(e,t,n){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(n.has(e)||(o[e]=r));return o}(H,J.flags,et):H}catch(t){let e=g(p(t),{diagnosticId:k().diagnosticId,logPath:D({force:!0})??void 0});j.flags.json?x({success:!1,error:e}):L(e,{showDetails:ee}),process.exit(1);return}let en=null;try{let e;if("react-devtools"===X){let e=await tJ(Q,{flags:z,stateDir:q.baseDir,session:z.session??W,cwd:process.cwd(),env:process.env});process.exit(e);return}if("web"===X){let e=await tz(Q,{flags:z,stateDir:q.baseDir});process.exit(e);return}ew({command:X,currentVersion:l,stateDir:q.baseDir,flags:z});let o=J?.runtime,r=(e,t)=>({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,runtime:t,lockPolicy:K.lockPolicy,lockPlatform:K.defaultPlatform,cwd:process.cwd(),debug:ee});if("batch"===X){if(Q.length>0)throw new h("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let n,o,r,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=t.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new h("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{r=JSON.parse(i)}catch{throw new h("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(r)||0===r.length)throw new h("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=r,n=!1,o=a.map((e,t)=>{var o,r,s,a,i,l;let c;if(o=e,null!==o&&"object"==typeof o&&!Array.isArray(o)&&"input"in o&&!("positionals"in o)&&!("flags"in o))return e;let d=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new h("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,o=t;let r=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(r.length>0)throw new h("INVALID_ARGS",`Batch step ${o} has unknown legacy field(s): ${r.join(", ")}.`);let s=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new h("INVALID_ARGS",`Batch step ${t} requires command.`);if(er(n))return n;throw new h("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new h("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!e||"object"!=typeof e||Array.isArray(e))throw new h("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===e.runtime?{}:{runtime:e.runtime}}}(e,t+1);return n=!0,c=(s=(r=d).command,a=r.positionals??[],l=r.flags,i={json:!1,help:!1,version:!1,...l},tV[s](a,i)),{command:r.command,input:c,...void 0===r.runtime?{}:{runtime:r.runtime}}}),n&&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.\n'),o}(H)}if(T=X,"auth"!==T&&"connection"!==T&&(z=(await e4({command:X,flags:z,stateDir:q.baseDir,env:process.env})).flags),z.remoteConfig&&(M=X,!t1.has(M))){let t=eg(r(z,o),{transport:n.sendToDaemon}),s=await eJ({command:X,flags:z,client:t,runtime:o,batchSteps:e,forceRuntimePrepare:function(e){for(let t of t0)if(e.has(t))return!0;return!1}(et)});z=s.flags,o=s.runtime}B={command:X,flags:z,runtime:o,explicitFlagKeys:et,hadConnectionDefaults:!!J},!("open"===B.command&&!B.runtime&&!B.flags.bundleUrl&&!B.flags.metroHost&&!B.flags.metroPort&&!B.flags.remoteConfig&&!B.hadConnectionDefaults&&((O=B.explicitFlagKeys).has("daemonBaseUrl")||O.has("daemonTransport")||O.has("tenant")||O.has("sessionIsolation")||O.has("runId")||O.has("leaseId")||O.has("leaseBackend")))||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.\n");let s=z.daemonBaseUrl;en=!ee||z.json||s?null:function(e){try{let n=t.existsSync(e)?t.statSync(e).size:0,o=!1,r=setInterval(()=>{if(!o&&t.existsSync(e))try{let o=t.statSync(e);if(o.size<n&&(n=0),o.size<=n)return;let r=t.openSync(e,"r");try{let e=Buffer.alloc(o.size-n);t.readSync(r,e,0,e.length,n),n=o.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{t.closeSync(r)}}catch{}},200);return()=>{o=!0,clearInterval(r)}}catch{return null}}(q.logPath);let i=eg(r(z,o),{transport:function(e){let{command:t,flags:n,transport:o}=e;return"test"!==t||n.json?o:async e=>await o({...e,meta:{...e.meta,requestProgress:"replay-test"}})}({command:X,flags:z,transport:n.sendToDaemon})});if("batch"===X){if(!e)throw new h("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:K.lockPolicy&&void 0===H.platform?{...e.input}:tY(e.input,{policyOverrides:z,configuredPlatform:z.platform,configuredSession:z.session,inheritedPlatform:z.platform})}));if(await tF({command:X,positionals:Q,flags:{...z,batchSteps:t},client:i,debug:ee}))return}else if("runtime"===X)throw new h("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 tF({command:X,positionals:Q,flags:z,client:i,debug:ee}))return;throw new h("INVALID_ARGS",`Unknown command: ${X}`)}catch(o){let e=p(o),n=g(e,{diagnosticId:k().diagnosticId,logPath:D({force:!0})??void 0});if("close"===X&&"COMMAND_FAILED"===($=e).code&&($.details?.kind==="daemon_startup_failed"||$.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof $.details?.infoPath||"string"==typeof $.details?.lockPath))){z.json&&x({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(z.json)x({success:!1,error:n});else if(L(n,{showDetails:ee}),ee)try{let e=q.logPath;if(t.existsSync(e)){let n=t.readFileSync(e,"utf8").split("\n"),o=n.slice(Math.max(0,n.length-200)).join("\n");o.trim().length>0&&process.stderr.write(`
|
|
19
20
|
[daemon log]
|
|
20
21
|
${o}
|
|
21
|
-
`)}}catch{}en&&en(),process.exit(1)}finally{en&&en()}})}function
|
|
22
|
+
`)}}catch{}en&&en(),process.exit(1)}finally{en&&en()}})}function t8(e,t){return t.some(t=>"verbose"===t.key&&("--debug"===t.token||"-v"===t.token||"test"!==e))}e(process.argv[1]??"").href===import.meta.url&&t3(process.argv.slice(2)).catch(e=>{L(g(p(e)),{showDetails:!0}),process.exit(1)});export{t3 as runCli,tj as runCliCommandWithOutput,tp as writeCommandOutput};
|
package/dist/src/contracts.d.ts
CHANGED
|
@@ -223,7 +223,7 @@ export declare function normalizeError(err: unknown, context?: {
|
|
|
223
223
|
logPath?: string;
|
|
224
224
|
}): NormalizedError;
|
|
225
225
|
|
|
226
|
-
declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "apple"];
|
|
226
|
+
declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "web", "apple"];
|
|
227
227
|
|
|
228
228
|
declare type PlatformSelector = (typeof PLATFORM_SELECTORS)[number];
|
|
229
229
|
|
package/dist/src/index.d.ts
CHANGED
|
@@ -968,9 +968,9 @@ export declare type PinchOptions = DeviceCommandBaseOptions & {
|
|
|
968
968
|
|
|
969
969
|
declare type Platform = (typeof PLATFORMS)[number];
|
|
970
970
|
|
|
971
|
-
declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "apple"];
|
|
971
|
+
declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "web", "apple"];
|
|
972
972
|
|
|
973
|
-
declare const PLATFORMS: readonly ['ios', 'macos', 'android', 'linux'];
|
|
973
|
+
declare const PLATFORMS: readonly ['ios', 'macos', 'android', 'linux', 'web'];
|
|
974
974
|
|
|
975
975
|
declare type PlatformSelector = (typeof PLATFORM_SELECTORS)[number];
|
|
976
976
|
|
|
@@ -1045,13 +1045,16 @@ declare type ReactNativeCommandOptions = DeviceCommandBaseOptions & {
|
|
|
1045
1045
|
action: 'dismiss-overlay';
|
|
1046
1046
|
};
|
|
1047
1047
|
|
|
1048
|
-
declare
|
|
1048
|
+
declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
|
|
1049
|
+
|
|
1050
|
+
declare type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
|
|
1049
1051
|
|
|
1050
1052
|
export declare type RecordOptions = AgentDeviceRequestOverrides & {
|
|
1051
1053
|
action: 'start' | 'stop';
|
|
1052
1054
|
path?: string;
|
|
1053
1055
|
fps?: number;
|
|
1054
|
-
|
|
1056
|
+
maxSize?: number;
|
|
1057
|
+
quality?: RecordingExportQuality;
|
|
1055
1058
|
hideTouches?: boolean;
|
|
1056
1059
|
};
|
|
1057
1060
|
|
package/dist/src/interaction.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__webpack_require__ as e}from"./rslib-runtime.js";import{createDaemonRuntimeSessionStore as t,setSessionSnapshot as r,dispatchCommand as a,ensureAndroidBlockingSystemDialogReady as n,isCommandSupportedOnDevice as s,errorResponse as o,recoverAndroidBlockingSystemDialog as i,getActiveAndroidSnapshotFreshness as l}from"./9722.js";import{createAgentDevice as c}from"./5299.js";import{asAppError as u,normalizeError as f,AppError as d}from"./733.js";import{dispatchGetViaRuntime as p,isAndroidEscapeError as g,createDaemonRuntimePolicy as m,assertAndroidPressStayedInApp as S,dispatchIsViaRuntime as k,isDirectIosSelectorFallbackError as y,refSnapshotFlagGuardResponse as _,readSimpleIosSelectorTarget as h}from"./selector-runtime.js";import{buttonTag as w,resolveClickButton as b,readFillTargetFromPositionals as v,getClickButtonValidationError as x,successText as N}from"./9873.js";import{interaction_snapshot_captureSnapshotForSession as F,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as R,buildTouchVisualizationResult as M,finalizeTouchInteraction as O}from"./8184.js";import{emitDiagnostic as I}from"./432.js";import{PUBLIC_COMMANDS as C}from"./2133.js";var A={};function E(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:o("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function q(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new d("SESSION_NOT_FOUND","No active session. Run open first.");return c({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0})}),tap:async(n,s)=>U(await a(r.device,"press",[String(s.x),String(s.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(n,s,o)=>U(await a(r.device,"fill",[String(s.x),String(s.y),o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),longPress:async(n,s,o)=>U(await a(r.device,"longpress",[String(s.x),String(s.y),...o?.durationMs===void 0?[]:[String(o.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,s)=>U(await a(r.device,"type",[s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),...m("interaction commands",{plural:!0}),sessions:t({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(r(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function U(e){return e&&"object"==typeof e?e:void 0}function D(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function T(e,t){let r=D(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:e.slice(1).join(" ").trim()}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:o("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function H(e){return"ref"===e.kind?{ref:K(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function K(e){return e?.startsWith("@")?e.slice(1):e}async function L(e){switch(e.req.command){case"press":return await j(e,"press");case"click":return await j(e,"click");case"longpress":return await j(e,"longpress");case"fill":return await V(e);default:return null}}async function j(e,t){let r,{req:a,sessionName:n,sessionStore:i}=e,l=i.get(n);if(!l)return o("SESSION_NOT_FOUND","No active session. Run open first.");let c="click"===t?"click":t,u="longpress"===t?"longpress":"press",f=E(l,c);if(f)return f;if(!s(u,l.device))return o("UNSUPPORTED_OPERATION",`${u} is not supported on this device`);let d=b(a.flags),p=w(d);if("longpress"!==t&&"primary"!==d){let e=x({commandLabel:c,platform:l.device.platform,button:d,count:a.flags?.count,intervalMs:a.flags?.intervalMs,holdMs:a.flags?.holdMs,jitterPx:a.flags?.jitterPx,doubleTap:a.flags?.doubleTap});if(e)return o(e.code,e.message,e.details)}let g="longpress"===t?function(e){var t,r,a;let n,s=D(e);if(s){return{ok:!0,target:{kind:"point",x:s.x,y:s.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let o=(n=(r=e).at(-1),r.length>1&&void 0!==(a=n)&&""!==a.trim()&&Number.isFinite(Number(a))?{targetPositionals:r.slice(0,-1),duration:{durationMs:Number(n)}}:{targetPositionals:r,duration:{}}),i=T(o.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...o.duration}:i}(a.positionals??[]):T(a.positionals??[],c);if(!g.ok)return g.response;if("ref"===g.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await z(e,l)}let m=function(e){var t;let{session:r,commandLabel:a,target:n,flags:s}=e;if("click"!==a||"selector"!==n.kind||(t=s,t?.count!==void 0||t?.intervalMs!==void 0||t?.holdMs!==void 0||t?.jitterPx!==void 0||t?.doubleTap!==void 0||t?.clickButton!==void 0&&"primary"!==t.clickButton))return null;let o=h({session:r,selectorExpression:n.selector});return o?{...o,...s?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:l,commandLabel:c,target:g.target,flags:a.flags});if(m){let t=await W(e,l,m);if(t)return t}let k="longpress"===t?g.durationMs:void 0;return await Y(e,{androidFreshnessBaseline:r,run:async e=>await B({runtime:e,command:t,target:g.target,sessionName:n,requestId:a.meta?.requestId,clickButton:d,flags:a.flags,durationMs:k}),afterRun:async e=>{var t;await S(l,(t=g.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async r=>{var a;let n="durationMs"in(a=r)?a.durationMs:void 0,s=await G({params:e,session:l,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:p});return{result:s,responseData:s}}})}async function B(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:s,flags:o}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:s,durationMs:e.durationMs});let i={session:n,requestId:s,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap};return"click"===r?await t.interactions.click(a,i):await t.interactions.press(a,i)}async function G(e){let{params:t,session:r,result:a,extra:n}=e,s="point"===a.kind?await R({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return M({data:a.backendResult,fallbackX:a.point.x,fallbackY:a.point.y,referenceFrame:s,extra:{...H(a),...n}})}async function W(e,t,r){return await $({params:e,session:t,selector:r,command:"press",positionals:[],extra:{selector:r.raw},fallbackPhase:"ios_direct_selector_tap_fallback"})}async function $(e){let{params:t,session:r,selector:n,command:s,positionals:o,extra:i,fallbackPhase:l}=e,c=Date.now();try{var u,d;let e,l,f=await a(r.device,s,o,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(u=f,e="number"==typeof u.x?u.x:void 0,l="number"==typeof u.y?u.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=M({data:f,fallbackX:g.x,fallbackY:g.y,referenceFrame:(d=f,"number"==typeof d.referenceWidth&&"number"==typeof d.referenceHeight?{referenceWidth:d.referenceWidth,referenceHeight:d.referenceHeight}:void 0),extra:{...i,...function(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let r="tapped via non-hittable coordinate fallback"===t.message;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:r,...r?{maestroFallbackReason:"non-hittable-coordinate"}:{}}}(n,f)}});return O({session:r,sessionStore:t.sessionStore,command:t.req.command,positionals:t.req.positionals??[],retryPositionals:J(g),flags:t.req.flags,result:m,responseData:m,actionStartedAt:c,actionFinishedAt:p})}catch(e){if(!y(e))return{ok:!1,error:f(e)};return I({level:"debug",phase:l,data:{selector:n.raw,error:e instanceof Error?e.message:String(e)}}),null}}async function V(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(n){let e=E(n,"fill");if(e)return e}if(n&&!s("fill",n.device))return o("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return o("SESSION_NOT_FOUND","No active session. Run open first.");let i=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=v(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:o("INVALID_ARGS","fill requires text after ref")}}let a=D(e);if(a){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:a.x,y:a.y},text:t}:{ok:!1,response:o("INVALID_ARGS","fill requires text after coordinates")}}let n=v(e);return"selector"!==n.kind?{ok:!1,response:o("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}:n.text.trim()?{ok:!0,target:{kind:"selector",selector:n.target.selector},text:n.text}:{ok:!1,response:o("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!i.ok)return i.response;if("ref"===i.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await z(e,n)}let l=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=h({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:i.target,flags:t.flags});if(l){let t=await X(e,n,l,i.text);if(t)return t}return await Y(e,{run:async e=>await e.interactions.fill(i.target,i.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:P(n.snapshot?.nodes??[]),r=M({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...H(e),text:i.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:K(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(a.warning=e.warning),{result:r,responseData:a}}})}async function X(e,t,r,a){return await $({params:e,session:t,selector:r,command:"fill",positionals:[a],extra:{selector:r.raw,text:a},fallbackPhase:"ios_direct_selector_fill_fallback"})}async function Y(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return o("SESSION_NOT_FOUND","No active session. Run open first.");let a=q(e),s=Date.now();try{let o=await n({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await n({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:u}=await t.buildPayloads(i);return"recovered"===o.status&&(c.warning=o.warning,u.warning=o.warning),O({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:function(e,t){if("click"===e||"press"===e)return J(t.point)}(e.req.command,i),flags:e.req.flags,result:c,responseData:u,actionStartedAt:s,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=u(t);if(g(e))throw e;return{ok:!1,error:f(t)}}}async function z(e,t){if(!l(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){I({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}function J(e){return[String(e.x),String(e.y)]}async function Q(e){let t=await L({...e,captureSnapshotForSession:F,refSnapshotFlagGuardResponse:_});if(t)return t;switch(e.req.command){case C.type:return await Z({...e,captureSnapshotForSession:F});case"get":return await p(e);case"is":return await k(e);default:return null}}async function Z(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return o("SESSION_NOT_FOUND","No active session. Run open first.");if(!s(C.type,a.device))return o("UNSUPPORTED_OPERATION","type is not supported on this device");let n=await ee(a);return n||await et(e,a)}async function ee(e){return"android"===e.device.platform&&e.recording&&"failed"===(await i({session:e})).status?o("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function et(e,t){let{req:r,sessionName:a,sessionStore:s}=e,o=(r.positionals??[]).join(" "),i=q(e),l=Date.now();try{let e=await n({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(o,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await n({session:t,command:r.command,phase:"after-command"});let u=Date.now(),f={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...N(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(f.warning=e.warning),O({session:t,sessionStore:s,command:r.command,positionals:r.positionals??[],flags:r.flags,result:f,responseData:f,actionStartedAt:l,actionFinishedAt:u})}catch(e){return{ok:!1,error:f(e)}}}e.r(A),e.d(A,{handleInteractionCommands:()=>Q});export{A as interaction_namespaceObject};
|
|
1
|
+
import{__webpack_require__ as e}from"./rslib-runtime.js";import{createDaemonRuntimeSessionStore as t,setSessionSnapshot as r,dispatchCommand as a,ensureAndroidBlockingSystemDialogReady as n,isCommandSupportedOnDevice as s,errorResponse as o,recoverAndroidBlockingSystemDialog as i,getActiveAndroidSnapshotFreshness as l}from"./9722.js";import{createAgentDevice as c}from"./368.js";import{asAppError as u,normalizeError as f,AppError as d}from"./733.js";import{dispatchGetViaRuntime as p,isAndroidEscapeError as g,createDaemonRuntimePolicy as m,assertAndroidPressStayedInApp as S,dispatchIsViaRuntime as k,isDirectIosSelectorFallbackError as y,refSnapshotFlagGuardResponse as _,readSimpleIosSelectorTarget as h}from"./selector-runtime.js";import{buttonTag as w,resolveClickButton as b,readFillTargetFromPositionals as v,getClickButtonValidationError as x,successText as N}from"./9873.js";import{interaction_snapshot_captureSnapshotForSession as F,readSnapshotNodesReferenceFrame as P,resolveDirectTouchReferenceFrameSafely as R,buildTouchVisualizationResult as M,finalizeTouchInteraction as O}from"./8184.js";import{emitDiagnostic as I}from"./432.js";import{PUBLIC_COMMANDS as C}from"./2133.js";var A={};function E(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:o("UNSUPPORTED_OPERATION",`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function q(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new d("SESSION_NOT_FOUND","No active session. Run open first.");return c({backend:function(e){let{req:t,session:r}=e;return{platform:r.device.platform,captureSnapshot:async(a,n)=>({snapshot:await e.captureSnapshotForSession(r,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:n?.interactiveOnly===!0})}),tap:async(n,s)=>U(await a(r.device,"press",[String(s.x),String(s.y)],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),fill:async(n,s,o)=>U(await a(r.device,"fill",[String(s.x),String(s.y),o],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),longPress:async(n,s,o)=>U(await a(r.device,"longpress",[String(s.x),String(s.y),...o?.durationMs===void 0?[]:[String(o.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath))),typeText:async(n,s)=>U(await a(r.device,"type",[s],t.flags?.out,e.contextFromFlags(t.flags,r.appBundleId,r.trace?.outPath)))}}({...e,session:n}),...m("interaction commands",{plural:!0}),sessions:t({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(r(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function U(e){return e&&"object"==typeof e?e:void 0}function D(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}function T(e,t){let r=D(e);if(r)return{ok:!0,target:{kind:"point",x:r.x,y:r.y}};let a=e[0]??"";if(a.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:a,fallbackLabel:e.slice(1).join(" ").trim()}};let n=e.join(" ").trim();return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:o("INVALID_ARGS",`${t} requires @ref, selector expression, or x y coordinates`)}}function H(e){return"ref"===e.kind?{ref:K(e.target?.kind==="ref"?e.target.ref:void 0),refLabel:e.refLabel,selectorChain:e.selectorChain}:"selector"===e.kind?{selector:e.target?.kind==="selector"?e.target.selector:void 0,selectorChain:e.selectorChain,refLabel:e.refLabel}:{}}function K(e){return e?.startsWith("@")?e.slice(1):e}async function L(e){switch(e.req.command){case"press":return await j(e,"press");case"click":return await j(e,"click");case"longpress":return await j(e,"longpress");case"fill":return await V(e);default:return null}}async function j(e,t){let r,{req:a,sessionName:n,sessionStore:i}=e,l=i.get(n);if(!l)return o("SESSION_NOT_FOUND","No active session. Run open first.");let c="click"===t?"click":t,u="longpress"===t?"longpress":"press",f=E(l,c);if(f)return f;if(!s(u,l.device))return o("UNSUPPORTED_OPERATION",`${u} is not supported on this device`);let d=b(a.flags),p=w(d);if("longpress"!==t&&"primary"!==d){let e=x({commandLabel:c,platform:l.device.platform,button:d,count:a.flags?.count,intervalMs:a.flags?.intervalMs,holdMs:a.flags?.holdMs,jitterPx:a.flags?.jitterPx,doubleTap:a.flags?.doubleTap});if(e)return o(e.code,e.message,e.details)}let g="longpress"===t?function(e){var t,r,a;let n,s=D(e);if(s){return{ok:!0,target:{kind:"point",x:s.x,y:s.y},...void 0===(t=e[2])?{}:{durationMs:Number(t)}}}let o=(n=(r=e).at(-1),r.length>1&&void 0!==(a=n)&&""!==a.trim()&&Number.isFinite(Number(a))?{targetPositionals:r.slice(0,-1),duration:{durationMs:Number(n)}}:{targetPositionals:r,duration:{}}),i=T(o.targetPositionals,"longpress");return i.ok?{ok:!0,target:i.target,...o.duration}:i}(a.positionals??[]):T(a.positionals??[],c);if(!g.ok)return g.response;if("ref"===g.target.kind){let n=e.refSnapshotFlagGuardResponse("longpress"===t?"longpress":"press",a.flags);if(n)return n;r=await z(e,l)}let m=function(e){var t;let{session:r,commandLabel:a,target:n,flags:s}=e;if("click"!==a||"selector"!==n.kind||(t=s,t?.count!==void 0||t?.intervalMs!==void 0||t?.holdMs!==void 0||t?.jitterPx!==void 0||t?.doubleTap!==void 0||t?.clickButton!==void 0&&"primary"!==t.clickButton))return null;let o=h({session:r,selectorExpression:n.selector});return o?{...o,...s?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:l,commandLabel:c,target:g.target,flags:a.flags});if(m){let t=await W(e,l,m);if(t)return t}let k="longpress"===t?g.durationMs:void 0;return await Y(e,{androidFreshnessBaseline:r,run:async e=>await B({runtime:e,command:t,target:g.target,sessionName:n,requestId:a.meta?.requestId,clickButton:d,flags:a.flags,durationMs:k}),afterRun:async e=>{var t;await S(l,(t=g.target,"point"===t.kind?"coordinate tap":"ref"===e.kind&&e.target?.kind==="ref"?e.target.ref:"selector"===e.kind&&e.target?.kind==="selector"?e.target.selector:"target"))},buildPayloads:async r=>{var a;let n="durationMs"in(a=r)?a.durationMs:void 0,s=await G({params:e,session:l,result:r,extra:"longpress"===t?{...void 0!==n?{durationMs:n}:{},gesture:"longpress"}:p});return{result:s,responseData:s}}})}async function B(e){let{runtime:t,command:r,target:a,sessionName:n,requestId:s,flags:o}=e;if("longpress"===r)return await t.interactions.longPress(a,{session:n,requestId:s,durationMs:e.durationMs});let i={session:n,requestId:s,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap};return"click"===r?await t.interactions.click(a,i):await t.interactions.press(a,i)}async function G(e){let{params:t,session:r,result:a,extra:n}=e,s="point"===a.kind?await R({session:r,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):P(r.snapshot?.nodes??[]);return M({data:a.backendResult,fallbackX:a.point.x,fallbackY:a.point.y,referenceFrame:s,extra:{...H(a),...n}})}async function W(e,t,r){return await $({params:e,session:t,selector:r,command:"press",positionals:[],extra:{selector:r.raw},fallbackPhase:"ios_direct_selector_tap_fallback"})}async function $(e){let{params:t,session:r,selector:n,command:s,positionals:o,extra:i,fallbackPhase:l}=e,c=Date.now();try{var u,d;let e,l,f=await a(r.device,s,o,t.req.flags?.out,{...t.contextFromFlags(t.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:n,surface:r.surface})??{},p=Date.now(),g=(u=f,e="number"==typeof u.x?u.x:void 0,l="number"==typeof u.y?u.y:void 0,void 0!==e&&void 0!==l?{x:e,y:l}:{x:0,y:0}),m=M({data:f,fallbackX:g.x,fallbackY:g.y,referenceFrame:(d=f,"number"==typeof d.referenceWidth&&"number"==typeof d.referenceHeight?{referenceWidth:d.referenceWidth,referenceHeight:d.referenceHeight}:void 0),extra:{...i,...function(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let r="tapped via non-hittable coordinate fallback"===t.message;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:r,...r?{maestroFallbackReason:"non-hittable-coordinate"}:{}}}(n,f)}});return O({session:r,sessionStore:t.sessionStore,command:t.req.command,positionals:t.req.positionals??[],retryPositionals:J(g),flags:t.req.flags,result:m,responseData:m,actionStartedAt:c,actionFinishedAt:p})}catch(e){if(!y(e))return{ok:!1,error:f(e)};return I({level:"debug",phase:l,data:{selector:n.raw,error:e instanceof Error?e.message:String(e)}}),null}}async function V(e){let{req:t,sessionName:r,sessionStore:a}=e,n=a.get(r);if(n){let e=E(n,"fill");if(e)return e}if(n&&!s("fill",n.device))return o("UNSUPPORTED_OPERATION","fill is not supported on this device");if(!n)return o("SESSION_NOT_FOUND","No active session. Run open first.");let i=function(e){let t=e[0]??"";if(t.startsWith("@")){var r;let a=v(e).text;return a?{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:(r=e).length>=3&&r[1]?.trim()||""},text:a}:{ok:!1,response:o("INVALID_ARGS","fill requires text after ref")}}let a=D(e);if(a){let t=e.slice(2).join(" ");return t?{ok:!0,target:{kind:"point",x:a.x,y:a.y},text:t}:{ok:!1,response:o("INVALID_ARGS","fill requires text after coordinates")}}let n=v(e);return"selector"!==n.kind?{ok:!1,response:o("INVALID_ARGS","fill requires x y text, @ref text, or selector text")}:n.text.trim()?{ok:!0,target:{kind:"selector",selector:n.target.selector},text:n.text}:{ok:!1,response:o("INVALID_ARGS","fill requires text after selector")}}(t.positionals??[]);if(!i.ok)return i.response;if("ref"===i.target.kind){let r=e.refSnapshotFlagGuardResponse("fill",t.flags);if(r)return r;await z(e,n)}let l=function(e){let{session:t,target:r,flags:a}=e;if("selector"!==r.kind)return null;let n=h({session:t,selectorExpression:r.selector});return n?{...n,...a?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}({session:n,target:i.target,flags:t.flags});if(l){let t=await X(e,n,l,i.text);if(t)return t}return await Y(e,{run:async e=>await e.interactions.fill(i.target,i.text,{session:r,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs}),buildPayloads:e=>{let t="point"===e.kind?void 0:P(n.snapshot?.nodes??[]),r=M({data:e.backendResult,fallbackX:e.point.x,fallbackY:e.point.y,referenceFrame:t,extra:{...H(e),text:i.text}});e.warning&&(r.warning=e.warning);let a="ref"===e.kind?{...e.backendResult??{ref:K(e.target?.kind==="ref"?e.target.ref:void 0),x:e.point.x,y:e.point.y}}:r;return e.warning&&(a.warning=e.warning),{result:r,responseData:a}}})}async function X(e,t,r,a){return await $({params:e,session:t,selector:r,command:"fill",positionals:[a],extra:{selector:r.raw,text:a},fallbackPhase:"ios_direct_selector_fill_fallback"})}async function Y(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return o("SESSION_NOT_FOUND","No active session. Run open first.");let a=q(e),s=Date.now();try{let o=await n({session:r,command:e.req.command,phase:"before-command"}),i=await t.run(a);await t.afterRun?.(i),await n({session:r,command:e.req.command,phase:"after-command"});let l=Date.now(),{result:c,responseData:u}=await t.buildPayloads(i);return"recovered"===o.status&&(c.warning=o.warning,u.warning=o.warning),O({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:function(e,t){if("click"===e||"press"===e)return J(t.point)}(e.req.command,i),flags:e.req.flags,result:c,responseData:u,actionStartedAt:s,actionFinishedAt:l,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(t){let e=u(t);if(g(e))throw e;return{ok:!1,error:f(t)}}}async function z(e,t){if(!l(t))return;let r=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:"ref-refresh"})}catch(t){I({level:"warn",phase:"android_ref_snapshot_refresh_failed",data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return r}function J(e){return[String(e.x),String(e.y)]}async function Q(e){let t=await L({...e,captureSnapshotForSession:F,refSnapshotFlagGuardResponse:_});if(t)return t;switch(e.req.command){case C.type:return await Z({...e,captureSnapshotForSession:F});case"get":return await p(e);case"is":return await k(e);default:return null}}async function Z(e){let{sessionName:t,sessionStore:r}=e,a=r.get(t);if(!a)return o("SESSION_NOT_FOUND","No active session. Run open first.");if(!s(C.type,a.device))return o("UNSUPPORTED_OPERATION","type is not supported on this device");let n=await ee(a);return n||await et(e,a)}async function ee(e){return"android"===e.device.platform&&e.recording&&"failed"===(await i({session:e})).status?o("COMMAND_FAILED","Android system dialog blocked the recording session"):null}async function et(e,t){let{req:r,sessionName:a,sessionStore:s}=e,o=(r.positionals??[]).join(" "),i=q(e),l=Date.now();try{let e=await n({session:t,command:r.command,phase:"before-command"}),c=await i.interactions.typeText(o,{session:a,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await n({session:t,command:r.command,phase:"after-command"});let u=Date.now(),f={...c.backendResult??{},text:c.text,delayMs:c.delayMs,...N(c.message??`Typed ${Array.from(c.text).length} chars`)};return"recovered"===e.status&&(f.warning=e.warning),O({session:t,sessionStore:s,command:r.command,positionals:r.positionals??[],flags:r.flags,result:f,responseData:f,actionStartedAt:l,actionFinishedAt:u})}catch(e){return{ok:!1,error:f(e)}}}e.r(A),e.d(A,{handleInteractionCommands:()=>Q});export{A as interaction_namespaceObject};
|
package/dist/src/internal/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var e,t,r,s;let n,o=process.argv.slice(2);function c(e){return"--help"===e||"-h"===e}function i(e){import("../cli.js").then(({runCli:t})=>t(e)).catch(p)}function p(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}
|
|
2
|
-
`),process.exit(1)}1===(t=e=o).length&&("--version"===(r=t[0])||"-V"===r)&&(process.stdout.write(`0.17.
|
|
2
|
+
`),process.exit(1)}1===(t=e=o).length&&("--version"===(r=t[0])||"-V"===r)&&(process.stdout.write(`0.17.7
|
|
3
3
|
`),1)||0===e.length&&(import("../cli-help.js").then(({buildUsageText:e})=>{process.stdout.write(`${e()}
|
|
4
4
|
`),process.exit(1)}).catch(p),1)||void 0!==(n=function(e){var t,r,s,n;switch(e.length){case 1:return"help"===(t=e[0])||c(t)?null:void 0;case 2:return r=e[0],s=e[1],"help"===r?s:(n=r,c(s)?n:void 0);default:return}}(s=e))&&(import("../cli-help.js").then(({buildCommandUsageText:e,buildUsageText:t})=>{var r;if(null===n)return void process.stdout.write(`${t()}
|
|
5
5
|
`);let o=e("long-press"===(r=n)?"longpress":"metrics"===r?"perf":r);o?process.stdout.write(o):i(s)}).catch(p),1)||("mcp"!==o[0]||o.includes("--help")||o.includes("-h")?i(o):import("../server.js").then(({runAgentDeviceMcpServer:e})=>e()).catch(p));export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createScopedProvider as r,createAgentBrowserWebProvider as e}from"./9722.js";let o=r(e());function t(r){return o.resolve(r)}async function n(r,e){return await o.run(r,e)}export{t as resolveWebProvider,n as withWebProvider};
|