agent-device 0.14.6 → 0.14.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.
@@ -0,0 +1 @@
1
+ cf52647a87d8724c94c1be073fdee6dd87fd509d2a45111678100c9045ff51ae agent-device-android-snapshot-helper-0.14.7.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.14.6",
4
- "releaseTag": "v0.14.6",
5
- "assetName": "agent-device-android-snapshot-helper-0.14.6.apk",
3
+ "version": "0.14.7",
4
+ "releaseTag": "v0.14.7",
5
+ "assetName": "agent-device-android-snapshot-helper-0.14.7.apk",
6
6
  "apkUrl": null,
7
- "sha256": "e9a4afcfa6fee4515b0dadacb7a92530d68ec4bb999aa0808651df5d41be78e0",
8
- "checksumName": "agent-device-android-snapshot-helper-0.14.6.apk.sha256",
7
+ "sha256": "cf52647a87d8724c94c1be073fdee6dd87fd509d2a45111678100c9045ff51ae",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.14.7.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 14006,
10
+ "versionCode": 14007,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
package/dist/src/1974.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"node:fs";import r from"node:path";import{createHash as t}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdDetached as o,runCmdSync as i}from"./9818.js";import{readProcessCommand as a,waitForProcessExit as s,resolveRuntimeTransportHints as l,isProcessAlive as u,readProcessStartTime as c}from"./8656.js";import{normalizeBaseUrl as d,ENV_COMPANION_TUNNEL_BEARER_TOKEN as m,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as p,ENV_COMPANION_TUNNEL_STATE_PATH as f,ENV_COMPANION_TUNNEL_LAUNCH_URL as h,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as g,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as y,ENV_COMPANION_TUNNEL_DEVICE_PORT as b,buildBundleUrl as S,METRO_COMPANION_RUN_ARG as w,ENV_COMPANION_TUNNEL_SESSION as P,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as v,ENV_COMPANION_TUNNEL_REGISTER_PATH as U,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as _,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as I}from"./2301.js";import{AppError as E}from"./9152.js";import{resolveUserPath as M}from"./3267.js";import{sleep as k}from"./4829.js";let N="companion-tunnel";function $(e){return t("sha256").update(e).digest("hex")}function A(e){return e?.trim()?e.trim():void 0}function R(e,t,n,o){let i=o??r.join(e,".agent-device");if(!n)return{statePath:r.join(i,`${t.slug}.json`),logPath:r.join(i,`${t.slug}.log`)};let a=$(n).slice(0,12),s=r.join(i,t.slug);return{statePath:r.join(s,`${t.slug}-${a}.json`),logPath:r.join(s,`${t.slug}-${a}.log`)}}function x(r){try{let t=JSON.parse(e.readFileSync(r,"utf8"));if(!Number.isInteger(t.pid)||0>=Number(t.pid)||"string"!=typeof t.serverBaseUrl||"string"!=typeof t.localBaseUrl||"string"!=typeof t.tokenHash||0===t.tokenHash.length)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>"string"==typeof e&&e.length>0):[];return{pid:Number(t.pid),startTime:"string"==typeof t.startTime?t.startTime:void 0,command:"string"==typeof t.command?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:A("string"==typeof t.launchUrl?t.launchUrl:void 0),registerPath:A("string"==typeof t.registerPath?t.registerPath:void 0),unregisterPath:A("string"==typeof t.unregisterPath?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:A("string"==typeof t.session?t.session:void 0),bridgeScope:function(e){if(!(!e||"object"!=typeof e||Array.isArray(e))&&"string"==typeof e.tenantId&&"string"==typeof e.runId&&"string"==typeof e.leaseId)return{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId}}(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function T(t,n){e.mkdirSync(r.dirname(t),{recursive:!0}),e.writeFileSync(t,`${JSON.stringify(n,null,2)}
2
- `,"utf8")}function j(r){try{let t=e.readdirSync(r);0===t.length&&e.rmdirSync(r)}catch{}}function C(t,n){let o=r.dirname(t.statePath),i=r.dirname(t.logPath);var a=t.statePath;try{e.unlinkSync(a)}catch{}var s=t.logPath;try{e.unlinkSync(s)}catch{}j(o),i!==o&&j(i),r.basename(o)===n.slug&&j(r.dirname(o))}function B(e,r){return e.includes(r.runArg)}function K(e){return A(e.consumerKey)??A(e.profileKey)??null}function D(e,r){return!r||e.consumers.includes(r)?e:{...e,consumers:[...e.consumers,r]}}async function H(e,r){if(!u(e.pid))return;let t=a(e.pid);if(t&&B(t,r)){try{process.kill(e.pid,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await s(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await s(e.pid,1e3)}}}async function O(t){let i=K(t),s=R(t.projectRoot,t.definition,t.profileKey,t.stateDir),l=x(s.statePath);if(l&&function(e,r){var t,n;if(!u(e.pid))return!1;if(e.startTime){let r=c(e.pid);if(!r||r!==e.startTime)return!1}let o=a(e.pid);return!!o&&!!B(o,r.definition)&&!!e.bridgeScope&&e.serverBaseUrl===d(r.serverBaseUrl)&&e.localBaseUrl===d(r.localBaseUrl)&&e.launchUrl===A(r.launchUrl)&&e.registerPath===A(r.registerPath)&&e.unregisterPath===A(r.unregisterPath)&&e.devicePort===r.devicePort&&e.session===A(r.session)&&(t=e.bridgeScope,n=r.bridgeScope,t.tenantId===n.tenantId&&t.runId===n.runId&&t.leaseId===n.leaseId)&&e.tokenHash===$(r.bearerToken)}(l,t)){let e=D(l,i);return e!==l&&T(s.statePath,e),{pid:l.pid,spawned:!1,statePath:s.statePath,logPath:s.logPath}}l&&(await H(l,t.definition),C(s,t.definition));let S=function(t,i){let s=function(t){let o=n(import.meta.url),i=r.extname(o)||".js",a=[r.join(r.dirname(o),`${N}${i}`),r.join(r.dirname(o),"internal",`${N}${i}`)].find(r=>e.existsSync(r));if(!a)throw Error(`${t.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return a}(t.definition),l=s.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(r.dirname(i),{recursive:!0});let u=e.openSync(i,"a"),S=0;try{let e;S=o(process.execPath,[...l,s,t.definition.runArg],{env:((e={...t.env??process.env})[p]=d(t.serverBaseUrl),e[m]=t.bearerToken,e[_]=d(t.localBaseUrl),e[f]=R(t.projectRoot,t.definition,t.profileKey,t.stateDir).statePath,e[y]=t.bridgeScope.tenantId,e[v]=t.bridgeScope.runId,e[g]=t.bridgeScope.leaseId,t.launchUrl?.trim()?e[h]=t.launchUrl.trim():delete e[h],t.registerPath?.trim()?e[U]=t.registerPath.trim():delete e[U],t.unregisterPath?.trim()?e[I]=t.unregisterPath.trim():delete e[I],void 0!==t.devicePort?e[b]=String(t.devicePort):delete e[b],t.session?.trim()?e[P]=t.session.trim():delete e[P],e),stdio:["ignore",u,u]})}finally{e.closeSync(u)}if(!Number.isInteger(S)||S<=0)throw Error(`Failed to start ${t.definition.displayName} process.`);return{pid:S,startTime:c(S)??void 0,command:a(S)??void 0,serverBaseUrl:d(t.serverBaseUrl),localBaseUrl:d(t.localBaseUrl),launchUrl:A(t.launchUrl),registerPath:A(t.registerPath),unregisterPath:A(t.unregisterPath),devicePort:t.devicePort,session:A(t.session),bridgeScope:t.bridgeScope,tokenHash:$(t.bearerToken),consumers:[]}}(t,s.logPath);return T(s.statePath,D(S,i)),{pid:S.pid,spawned:!0,statePath:s.statePath,logPath:s.logPath}}async function L(e){let r=K(e),t=R(e.projectRoot,e.definition,e.profileKey,e.stateDir),n=x(t.statePath);if(!n)return C(t,e.definition),{stopped:!1,statePath:t.statePath};let o=r?{...n,consumers:n.consumers.filter(e=>e!==r)}:{...n,consumers:[]};return o.consumers.length>0?(T(t.statePath,o),{stopped:!1,statePath:t.statePath}):(await H(n,e.definition),C(t,e.definition),{stopped:!0,statePath:t.statePath})}let G={slug:"metro-companion",runArg:w,displayName:"Metro companion"};async function J(e){return await O({...e,definition:G,registerPath:e.registerPath??"/api/metro/companion/register"})}async function F(e){return await L({...e,definition:G})}function V(e){return"string"==typeof e&&e.trim()?d(e.trim()):""}function q(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function W(e,r,t){return M(e,{env:r,cwd:t})}function z(r){try{return e.accessSync(r,e.constants.F_OK),!0}catch{return!1}}function X(e,r,t){if(null==e||""===e)return r;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,t):r}function Y(e,r){if(null==e||""===e)return r;let t=Number.parseInt(String(e),10);if(!Number.isInteger(t)||t<1||t>65535)throw new E("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return t}function Q(e,r){return{platform:r,bundleUrl:S(e,r)}}function Z(e,r){return{platform:r,metroHost:q(e?.metro_host),metroPort:e?.metro_port,bundleUrl:q(e?.metro_bundle_url),launchUrl:q(e?.launch_url)}}async function ee(e){await k(e)}async function er(e,r,t={}){try{let n=await fetch(e,{headers:t,signal:AbortSignal.timeout(r)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Error(`Timed out fetching ${e} after ${r}ms`);throw t}}async function et(e,r){try{let t=await er(e,r);return t.ok&&t.body.includes("packager-status:running")}catch{return!1}}async function en(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await s(e,1e3)){try{process.kill(e,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await s(e,1e3)}}}function eo(e,r){let t=Error(e);return t.retryable=r,t}function ei(e,r){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(r).includes("Metro companion is not connected"))}function ea(e){return!!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable)}async function es(e){let r;try{var t,n;r=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw eo(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw eo(r instanceof Error?r.message:String(r),!0)}let o=function(e,r,t){if(!e)return{};try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw Error("Expected a JSON object");return r}catch(i){let n=e.slice(0,200),o=i instanceof Error?i.message:String(i);throw eo(`/api/metro/bridge returned invalid JSON (${r}) from ${t}: ${o}. body=${JSON.stringify(n)}`,ei(r,e))}}(await r.text(),r.status,e.baseUrl);if(!r.ok)throw eo(`/api/metro/bridge failed (${r.status}): ${JSON.stringify(o)}`,ei(r.status,o));var i=o;let a=i.data??i;if(!a||"object"!=typeof a||Array.isArray(a))throw eo("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:a.enabled,baseUrl:a.base_url,statusUrl:a.status_url??"",bundleUrl:a.bundle_url??"",iosRuntime:Z(a.ios_runtime,"ios"),androidRuntime:Z(a.android_runtime,"android"),upstream:{bundleUrl:a.upstream.bundle_url??"",host:a.upstream.host??"",port:a.upstream.port??0,statusUrl:a.upstream.status_url??""},probe:{reachable:a.probe.reachable,statusCode:a.probe.status_code,latencyMs:a.probe.latency_ms,detail:a.probe.detail}}}catch(e){throw eo(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function el(e,r,t,n,o){let i=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return r&&i.push(`bridgeError=${r}`),t?.probe.reachable===!1&&i.push(`bridgeProbe=${t.probe.detail||`unreachable (status ${t.probe.statusCode||0})`}`),n&&n!==r&&i.push(`initialBridgeError=${n}`),o&&i.push(`metroCompanionLog=${o}`),i.join(" ")}async function eu(e,r,t){let n=Date.now()+r;for(;Date.now()<n;){let r=Math.min(t,Math.max(n-Date.now(),1));if(await et(e,r))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await ee(o)}return!1}async function ec(e){let r=Date.now()+e.startupTimeoutMs,t=null,n=null;for(;Date.now()<r;){try{let r=await es({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==r.probe.reachable)return r;t=r,n=null}catch(e){if(n=e instanceof Error?e.message:String(e),!ea(e))break}let o=Math.min(1e3,Math.max(r-Date.now(),0));o>0&&await ee(o)}throw Error(el(e.baseUrl,n,t,e.initialBridgeError,e.companionLogPath))}async function ed(t={}){let n=t.env??process.env,a=process.cwd(),s=W(t.projectRoot??a,n,a),l=function(t,n){if("auto"!==n)return n;let o=function(t){let n=r.join(t,"package.json");if(!z(n))throw new E("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(t);return"string"==typeof({...o.dependencies??{},...o.devDependencies??{}}).expo?"expo":"react-native"}(s,t.kind??"auto"),u=Y(t.metroPort??8081,8081),c=q(t.listenHost)??"0.0.0.0",d=q(t.statusHost)??"127.0.0.1",m=V(t.publicBaseUrl),p=X(t.startupTimeoutMs,18e4,3e4),f=X(t.probeTimeoutMs,1e4,1e3),h=t.reuseExisting??!0,g=t.installDependenciesIfNeeded??!0,y=t.runtimeFilePath?W(t.runtimeFilePath,n,a):null,b=W(t.logPath??r.join(s,".agent-device","metro.log"),n,a);if(!m&&!V(t.proxyBaseUrl))throw new E("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:S,proxyBaseUrl:w,proxyBearerToken:P}=function(e,r){if(e&&!r)throw new E("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&r)throw new E("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&r),proxyBaseUrl:e,proxyBearerToken:r}}(V(t.proxyBaseUrl),q(t.proxyBearerToken)??""),v=S?function(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new E("INVALID_ARGS","metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.");return e}(t.bridgeScope):null,U=g?function(t,n){if(function(r){try{return e.statSync(r).isDirectory()}catch{return!1}}(r.join(t,"node_modules")))return{installed:!1};let o=z(r.join(t,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:z(r.join(t,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return i(o.command,o.installArgs,{cwd:t,env:n}),{installed:!0,packageManager:o.command}}(s,n):{installed:!1},_=`http://${d}:${u}/status`,I=!1,M=!1,k=0;if(h&&await et(_,f))M=!0;else if(I=!0,k=function(t,n,i,a,s,l){let u="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(i)]}:{command:"npx",installArgs:["react-native","start","--host",a,"--port",String(i)]};e.mkdirSync(r.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),d=0;try{d=o(u.command,u.installArgs,{cwd:t,env:l,stdio:["ignore",c,c]})}finally{e.closeSync(c)}if(!Number.isInteger(d)||d<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:d}}(s,l,u,c,b,n).pid,!await eu(_,p,f))throw await en(k).catch(()=>{}),Error(`Metro did not become ready at ${_} within ${p}ms. Check ${b}.`);let N=m?Q(m,"ios"):{platform:"ios"},$=m?Q(m,"android"):{platform:"android"},A=null,R=null;if(v)try{A=await es({baseUrl:w,bearerToken:P,scope:v,timeoutMs:f})}catch(e){if(!ea(e))throw e;R=e instanceof Error?e.message:String(e)}if(v&&(!A||!1===A.probe.reachable)){let e;try{e=(await J({projectRoot:s,serverBaseUrl:w,bearerToken:P,bridgeScope:v,localBaseUrl:`http://${d}:${u}`,launchUrl:q(t.launchUrl),profileKey:q(t.companionProfileKey),consumerKey:q(t.companionConsumerKey),env:n})).logPath}catch(e){throw Error(el(w,e instanceof Error?e.message:String(e),A,R))}try{A=await ec({baseUrl:w,bearerToken:P,scope:v,probeTimeoutMs:f,startupTimeoutMs:p,initialBridgeError:R,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}v&&function(e,r){if(!r?.iosRuntime.bundleUrl)throw Error(el(e,"bridge descriptor is missing ios_runtime.metro_bundle_url",r))}(w,A);let x=A?.iosRuntime??N,T=A?.androidRuntime??$,j={projectRoot:s,kind:l,dependenciesInstalled:U.installed,packageManager:U.packageManager??null,started:I,reused:M,pid:k,logPath:b,statusUrl:_,runtimeFilePath:y,iosRuntime:x,androidRuntime:T,bridge:A};return y&&(e.mkdirSync(r.dirname(y),{recursive:!0}),e.writeFileSync(y,JSON.stringify(j,null,2))),j}async function em(e={}){let r=X(e.timeoutMs,1e4,1e3),t=function(e){var r;let t,n=q(e.bundleUrl)??e.runtime?.bundleUrl,o=!!q(e.bundleUrl),i=!!q(n),a=l({metroHost:q(e.metroHost)??(o?void 0:q(e.runtime?.metroHost))??(i?void 0:"localhost"),metroPort:void 0!==e.metroPort?Y(e.metroPort,8081):o?void 0:e.runtime?.metroPort??(i?void 0:8081),bundleUrl:n});if(!a)throw new E("INVALID_ARGS","Unable to resolve Metro host and port for reload.");return r=function(e){let r=q(e);if(!r)return"/reload";let t=new URL(r).pathname.replace(/\/+$/,"");return t.endsWith("/index.bundle")?`${t.slice(0,-13)}/reload`:"/reload"}(n),(t=new URL(`${a.scheme}://localhost`)).hostname=a.host,t.port=String(a.port),t.pathname=r,t.toString()}(e),n=await er(t,r);if(!n.ok)throw new E("COMMAND_FAILED",`Metro reload failed (${n.status}).`,{reloadUrl:t,status:n.status,body:n.body,hint:"Verify Metro is running and the target React Native app is connected to this Metro instance."});return{reloaded:!0,reloadUrl:t,status:n.status,body:n.body}}export{Q as buildMetroRuntimeHints,O as ensureCompanionTunnel,J as ensureMetroCompanion,ed as prepareMetroRuntime,em as reloadMetro,L as stopCompanionTunnel,F as stopMetroCompanion};
1
+ import e from"node:fs";import r from"node:path";import{createHash as t}from"node:crypto";import{fileURLToPath as n}from"node:url";import{runCmdDetached as i,runCmdSync as o}from"./9818.js";import{readProcessCommand as a,waitForProcessExit as s,resolveRuntimeTransportHints as l,isProcessAlive as u,readProcessStartTime as c}from"./8656.js";import{normalizeBaseUrl as d,ENV_COMPANION_TUNNEL_BEARER_TOKEN as m,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as p,ENV_COMPANION_TUNNEL_STATE_PATH as f,ENV_COMPANION_TUNNEL_LAUNCH_URL as h,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as g,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as y,ENV_COMPANION_TUNNEL_DEVICE_PORT as b,buildBundleUrl as S,METRO_COMPANION_RUN_ARG as w,ENV_COMPANION_TUNNEL_SESSION as P,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as v,ENV_COMPANION_TUNNEL_REGISTER_PATH as U,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as _,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as I}from"./2301.js";import{AppError as E}from"./9152.js";import{resolveUserPath as M}from"./3267.js";import{sleep as k}from"./4829.js";let N="companion-tunnel";function $(e){return t("sha256").update(e).digest("hex")}function A(e){return e?.trim()?e.trim():void 0}function R(e,t,n,i){let o=i??r.join(e,".agent-device");if(!n)return{statePath:r.join(o,`${t.slug}.json`),logPath:r.join(o,`${t.slug}.log`)};let a=$(n).slice(0,12),s=r.join(o,t.slug);return{statePath:r.join(s,`${t.slug}-${a}.json`),logPath:r.join(s,`${t.slug}-${a}.log`)}}function x(r){try{let t=JSON.parse(e.readFileSync(r,"utf8"));if(!Number.isInteger(t.pid)||0>=Number(t.pid)||"string"!=typeof t.serverBaseUrl||"string"!=typeof t.localBaseUrl||"string"!=typeof t.tokenHash||0===t.tokenHash.length)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>"string"==typeof e&&e.length>0):[];return{pid:Number(t.pid),startTime:"string"==typeof t.startTime?t.startTime:void 0,command:"string"==typeof t.command?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:A("string"==typeof t.launchUrl?t.launchUrl:void 0),registerPath:A("string"==typeof t.registerPath?t.registerPath:void 0),unregisterPath:A("string"==typeof t.unregisterPath?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:A("string"==typeof t.session?t.session:void 0),bridgeScope:function(e){if(!(!e||"object"!=typeof e||Array.isArray(e))&&"string"==typeof e.tenantId&&"string"==typeof e.runId&&"string"==typeof e.leaseId)return{tenantId:e.tenantId,runId:e.runId,leaseId:e.leaseId}}(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function T(t,n){e.mkdirSync(r.dirname(t),{recursive:!0}),e.writeFileSync(t,`${JSON.stringify(n,null,2)}
2
+ `,"utf8")}function j(r){try{let t=e.readdirSync(r);0===t.length&&e.rmdirSync(r)}catch{}}function C(t,n){let i=r.dirname(t.statePath),o=r.dirname(t.logPath);var a=t.statePath;try{e.unlinkSync(a)}catch{}var s=t.logPath;try{e.unlinkSync(s)}catch{}j(i),o!==i&&j(o),r.basename(i)===n.slug&&j(r.dirname(i))}function B(e,r){return e.includes(r.runArg)}function K(e){return A(e.consumerKey)??A(e.profileKey)??null}function D(e,r){return!r||e.consumers.includes(r)?e:{...e,consumers:[...e.consumers,r]}}async function H(e,r){if(!u(e.pid))return;let t=a(e.pid);if(t&&B(t,r)){try{process.kill(e.pid,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await s(e.pid,1e3)){try{process.kill(e.pid,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await s(e.pid,1e3)}}}async function O(t){var o;let s,l=K(t),S=R(t.projectRoot,t.definition,t.profileKey,t.stateDir),w=x(S.statePath);if(w&&function(e,r){var t,n;if(!u(e.pid))return!1;if(e.startTime){let r=c(e.pid);if(!r||r!==e.startTime)return!1}let i=a(e.pid);return!!i&&!!B(i,r.definition)&&!!e.bridgeScope&&e.serverBaseUrl===d(r.serverBaseUrl)&&e.localBaseUrl===d(r.localBaseUrl)&&e.launchUrl===A(r.launchUrl)&&e.registerPath===A(r.registerPath)&&e.unregisterPath===A(r.unregisterPath)&&e.devicePort===r.devicePort&&e.session===A(r.session)&&(t=e.bridgeScope,n=r.bridgeScope,t.tenantId===n.tenantId&&t.runId===n.runId&&t.leaseId===n.leaseId)&&e.tokenHash===$(r.bearerToken)}(w,t)){let e=D(w,l);return e!==w&&T(S.statePath,e),{pid:w.pid,spawned:!1,statePath:S.statePath,logPath:S.logPath}}w&&(await H(w,t.definition),C(S,t.definition)),o=S.statePath,e.mkdirSync(r.dirname(o),{recursive:!0}),e.closeSync(e.openSync(o,"a"));try{s=function(t,o){let s=function(t){let i=n(import.meta.url),o=r.extname(i)||".js",a=[r.join(r.dirname(i),`${N}${o}`),r.join(r.dirname(i),"internal",`${N}${o}`)].find(r=>e.existsSync(r));if(!a)throw Error(`${t.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return a}(t.definition),l=s.endsWith(".ts")?["--experimental-strip-types"]:[];e.mkdirSync(r.dirname(o),{recursive:!0});let u=e.openSync(o,"a"),S=0;try{let e;S=i(process.execPath,[...l,s,t.definition.runArg],{env:((e={...t.env??process.env})[p]=d(t.serverBaseUrl),e[m]=t.bearerToken,e[_]=d(t.localBaseUrl),e[f]=R(t.projectRoot,t.definition,t.profileKey,t.stateDir).statePath,e[y]=t.bridgeScope.tenantId,e[v]=t.bridgeScope.runId,e[g]=t.bridgeScope.leaseId,t.launchUrl?.trim()?e[h]=t.launchUrl.trim():delete e[h],t.registerPath?.trim()?e[U]=t.registerPath.trim():delete e[U],t.unregisterPath?.trim()?e[I]=t.unregisterPath.trim():delete e[I],void 0!==t.devicePort?e[b]=String(t.devicePort):delete e[b],t.session?.trim()?e[P]=t.session.trim():delete e[P],e),stdio:["ignore",u,u]})}finally{e.closeSync(u)}if(!Number.isInteger(S)||S<=0)throw Error(`Failed to start ${t.definition.displayName} process.`);return{pid:S,startTime:c(S)??void 0,command:a(S)??void 0,serverBaseUrl:d(t.serverBaseUrl),localBaseUrl:d(t.localBaseUrl),launchUrl:A(t.launchUrl),registerPath:A(t.registerPath),unregisterPath:A(t.unregisterPath),devicePort:t.devicePort,session:A(t.session),bridgeScope:t.bridgeScope,tokenHash:$(t.bearerToken),consumers:[]}}(t,S.logPath),T(S.statePath,D(s,l))}catch(e){throw s&&await H(s,t.definition).catch(()=>{}),C(S,t.definition),e}return{pid:s.pid,spawned:!0,statePath:S.statePath,logPath:S.logPath}}async function L(e){let r=K(e),t=R(e.projectRoot,e.definition,e.profileKey,e.stateDir),n=x(t.statePath);if(!n)return C(t,e.definition),{stopped:!1,statePath:t.statePath};let i=r?{...n,consumers:n.consumers.filter(e=>e!==r)}:{...n,consumers:[]};return i.consumers.length>0?(T(t.statePath,i),{stopped:!1,statePath:t.statePath}):(await H(n,e.definition),C(t,e.definition),{stopped:!0,statePath:t.statePath})}let G={slug:"metro-companion",runArg:w,displayName:"Metro companion"};async function J(e){return await O({...e,definition:G,registerPath:e.registerPath??"/api/metro/companion/register"})}async function F(e){return await L({...e,definition:G})}function V(e){return"string"==typeof e&&e.trim()?d(e.trim()):""}function q(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function W(e,r,t){return M(e,{env:r,cwd:t})}function z(r){try{return e.accessSync(r,e.constants.F_OK),!0}catch{return!1}}function X(e,r,t){if(null==e||""===e)return r;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,t):r}function Y(e,r){if(null==e||""===e)return r;let t=Number.parseInt(String(e),10);if(!Number.isInteger(t)||t<1||t>65535)throw new E("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return t}function Q(e,r){return{platform:r,bundleUrl:S(e,r)}}function Z(e,r){return{platform:r,metroHost:q(e?.metro_host),metroPort:e?.metro_port,bundleUrl:q(e?.metro_bundle_url),launchUrl:q(e?.launch_url)}}async function ee(e){await k(e)}async function er(e,r,t={}){try{let n=await fetch(e,{headers:t,signal:AbortSignal.timeout(r)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Error(`Timed out fetching ${e} after ${r}ms`);throw t}}async function et(e,r){try{let t=await er(e,r);return t.ok&&t.body.includes("packager-status:running")}catch{return!1}}async function en(e){if(Number.isInteger(e)&&!(e<=0)){try{process.kill(e,"SIGTERM")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}if(!await s(e,1e3)){try{process.kill(e,"SIGKILL")}catch(r){let e=r.code;if("ESRCH"===e||"EPERM"===e)return;throw r}await s(e,1e3)}}}function ei(e,r){let t=Error(e);return t.retryable=r,t}function eo(e,r){return!!(e>=500||408===e||425===e||429===e||JSON.stringify(r).includes("Metro companion is not connected"))}function ea(e){return!!(e&&"object"==typeof e&&"retryable"in e&&!0===e.retryable)}async function es(e){let r;try{var t,n;r=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,n=e.bearerToken,{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw ei(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0);throw ei(r instanceof Error?r.message:String(r),!0)}let i=function(e,r,t){if(!e)return{};try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw Error("Expected a JSON object");return r}catch(o){let n=e.slice(0,200),i=o instanceof Error?o.message:String(o);throw ei(`/api/metro/bridge returned invalid JSON (${r}) from ${t}: ${i}. body=${JSON.stringify(n)}`,eo(r,e))}}(await r.text(),r.status,e.baseUrl);if(!r.ok)throw ei(`/api/metro/bridge failed (${r.status}): ${JSON.stringify(i)}`,eo(r.status,i));var o=i;let a=o.data??o;if(!a||"object"!=typeof a||Array.isArray(a))throw ei("/api/metro/bridge returned malformed descriptor: Expected a JSON object.",!1);try{return{enabled:a.enabled,baseUrl:a.base_url,statusUrl:a.status_url??"",bundleUrl:a.bundle_url??"",iosRuntime:Z(a.ios_runtime,"ios"),androidRuntime:Z(a.android_runtime,"android"),upstream:{bundleUrl:a.upstream.bundle_url??"",host:a.upstream.host??"",port:a.upstream.port??0,statusUrl:a.upstream.status_url??""},probe:{reachable:a.probe.reachable,statusCode:a.probe.status_code,latencyMs:a.probe.latency_ms,detail:a.probe.detail}}}catch(e){throw ei(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function el(e,r,t,n,i){let o=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return r&&o.push(`bridgeError=${r}`),t?.probe.reachable===!1&&o.push(`bridgeProbe=${t.probe.detail||`unreachable (status ${t.probe.statusCode||0})`}`),n&&n!==r&&o.push(`initialBridgeError=${n}`),i&&o.push(`metroCompanionLog=${i}`),o.join(" ")}async function eu(e,r,t){let n=Date.now()+r;for(;Date.now()<n;){let r=Math.min(t,Math.max(n-Date.now(),1));if(await et(e,r))return!0;let i=Math.min(500,Math.max(n-Date.now(),0));i>0&&await ee(i)}return!1}async function ec(e){let r=Date.now()+e.startupTimeoutMs,t=null,n=null;for(;Date.now()<r;){try{let r=await es({baseUrl:e.baseUrl,bearerToken:e.bearerToken,scope:e.scope,runtime:e.runtime,timeoutMs:e.probeTimeoutMs});if(!1!==r.probe.reachable)return r;t=r,n=null}catch(e){if(n=e instanceof Error?e.message:String(e),!ea(e))break}let i=Math.min(1e3,Math.max(r-Date.now(),0));i>0&&await ee(i)}throw Error(el(e.baseUrl,n,t,e.initialBridgeError,e.companionLogPath))}async function ed(t={}){let n=t.env??process.env,a=process.cwd(),s=W(t.projectRoot??a,n,a),l=function(t,n){if("auto"!==n)return n;let i=function(t){let n=r.join(t,"package.json");if(!z(n))throw new E("INVALID_ARGS",`package.json not found at ${n}`);return JSON.parse(e.readFileSync(n,"utf8"))}(t);return"string"==typeof({...i.dependencies??{},...i.devDependencies??{}}).expo?"expo":"react-native"}(s,t.kind??"auto"),u=Y(t.metroPort??8081,8081),c=q(t.listenHost)??"0.0.0.0",d=q(t.statusHost)??"127.0.0.1",m=V(t.publicBaseUrl),p=X(t.startupTimeoutMs,18e4,3e4),f=X(t.probeTimeoutMs,1e4,1e3),h=t.reuseExisting??!0,g=t.installDependenciesIfNeeded??!0,y=t.runtimeFilePath?W(t.runtimeFilePath,n,a):null,b=W(t.logPath??r.join(s,".agent-device","metro.log"),n,a);if(!m&&!V(t.proxyBaseUrl))throw new E("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:S,proxyBaseUrl:w,proxyBearerToken:P}=function(e,r){if(e&&!r)throw new E("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&r)throw new E("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&r),proxyBaseUrl:e,proxyBearerToken:r}}(V(t.proxyBaseUrl),q(t.proxyBearerToken)??""),v=S?function(e){if(!e?.tenantId||!e.runId||!e.leaseId)throw new E("INVALID_ARGS","metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.");return e}(t.bridgeScope):null,U=g?function(t,n){if(function(r){try{return e.statSync(r).isDirectory()}catch{return!1}}(r.join(t,"node_modules")))return{installed:!1};let i=z(r.join(t,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:z(r.join(t,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return o(i.command,i.installArgs,{cwd:t,env:n}),{installed:!0,packageManager:i.command}}(s,n):{installed:!1},_=`http://${d}:${u}/status`,I=!1,M=!1,k=0;if(h&&await et(_,f))M=!0;else if(I=!0,k=function(t,n,o,a,s,l){let u="expo"===n?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(o)]}:{command:"npx",installArgs:["react-native","start","--host",a,"--port",String(o)]};e.mkdirSync(r.dirname(s),{recursive:!0});let c=e.openSync(s,"a"),d=0;try{d=i(u.command,u.installArgs,{cwd:t,env:l,stdio:["ignore",c,c]})}finally{e.closeSync(c)}if(!Number.isInteger(d)||d<=0)throw Error("Failed to start Metro. Expected a detached child PID.");return{pid:d}}(s,l,u,c,b,n).pid,!await eu(_,p,f))throw await en(k).catch(()=>{}),Error(`Metro did not become ready at ${_} within ${p}ms. Check ${b}.`);let N=m?Q(m,"ios"):{platform:"ios"},$=m?Q(m,"android"):{platform:"android"},A=null,R=null;if(v)try{A=await es({baseUrl:w,bearerToken:P,scope:v,timeoutMs:f})}catch(e){if(!ea(e))throw e;R=e instanceof Error?e.message:String(e)}if(v&&(!A||!1===A.probe.reachable)){let e;try{e=(await J({projectRoot:s,serverBaseUrl:w,bearerToken:P,bridgeScope:v,localBaseUrl:`http://${d}:${u}`,launchUrl:q(t.launchUrl),profileKey:q(t.companionProfileKey),consumerKey:q(t.companionConsumerKey),env:n})).logPath}catch(e){throw Error(el(w,e instanceof Error?e.message:String(e),A,R))}try{A=await ec({baseUrl:w,bearerToken:P,scope:v,probeTimeoutMs:f,startupTimeoutMs:p,initialBridgeError:R,companionLogPath:e})}catch(e){throw e instanceof Error?e:Error(String(e))}}v&&function(e,r){if(!r?.iosRuntime.bundleUrl)throw Error(el(e,"bridge descriptor is missing ios_runtime.metro_bundle_url",r))}(w,A);let x=A?.iosRuntime??N,T=A?.androidRuntime??$,j={projectRoot:s,kind:l,dependenciesInstalled:U.installed,packageManager:U.packageManager??null,started:I,reused:M,pid:k,logPath:b,statusUrl:_,runtimeFilePath:y,iosRuntime:x,androidRuntime:T,bridge:A};return y&&(e.mkdirSync(r.dirname(y),{recursive:!0}),e.writeFileSync(y,JSON.stringify(j,null,2))),j}async function em(e={}){let r=X(e.timeoutMs,1e4,1e3),t=function(e){var r;let t,n=q(e.bundleUrl)??e.runtime?.bundleUrl,i=!!q(e.bundleUrl),o=!!q(n),a=l({metroHost:q(e.metroHost)??(i?void 0:q(e.runtime?.metroHost))??(o?void 0:"localhost"),metroPort:void 0!==e.metroPort?Y(e.metroPort,8081):i?void 0:e.runtime?.metroPort??(o?void 0:8081),bundleUrl:n});if(!a)throw new E("INVALID_ARGS","Unable to resolve Metro host and port for reload.");return r=function(e){let r=q(e);if(!r)return"/reload";let t=new URL(r).pathname.replace(/\/+$/,"");return t.endsWith("/index.bundle")?`${t.slice(0,-13)}/reload`:"/reload"}(n),(t=new URL(`${a.scheme}://localhost`)).hostname=a.host,t.port=String(a.port),t.pathname=r,t.toString()}(e),n=await er(t,r);if(!n.ok)throw new E("COMMAND_FAILED",`Metro reload failed (${n.status}).`,{reloadUrl:t,status:n.status,body:n.body,hint:"Verify Metro is running and the target React Native app is connected to this Metro instance."});return{reloaded:!0,reloadUrl:t,status:n.status,body:n.body}}export{Q as buildMetroRuntimeHints,O as ensureCompanionTunnel,J as ensureMetroCompanion,ed as prepareMetroRuntime,em as reloadMetro,L as stopCompanionTunnel,F as stopMetroCompanion};
package/dist/src/9542.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import o from"node:path";import{pipeline as n}from"node:stream/promises";import i from"node:os";import{createHash as s,randomUUID as l}from"node:crypto";import{Writable as d}from"node:stream";import{toAppErrorCode as c,AppError as u}from"./9152.js";import{runCmdSync as p,runCmd as m,runCmdDetached as f}from"./9818.js";import{buildDeviceIdentifiers as h,resolveDaemonPaths as y,readVersion as w,findProjectRoot as v,resolveDaemonServerMode as g,computeDaemonCodeSignature as I,resolveDaemonTransportPreference as b,buildAppIdentifiers as A}from"./180.js";import{createRequestId as _,withDiagnosticTimer as M,emitDiagnostic as S}from"./7599.js";import{isAgentDeviceDaemonProcess as k,stopProcessForTakeover as E}from"./8656.js";import{sleep as D}from"./4829.js";import{tryParseSelectorChain as P}from"./940.js";import{reloadMetro as T,prepareMetroRuntime as N}from"./1974.js";let U="sha256";async function x(e){let t=await C(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await F({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await B(t.payloadPath,r),await j({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await L({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function C(e,t){var a,n,i;let s,l=r.statSync(e),d=o.basename(e),c=l.isDirectory(),u=("ios"===(a=t)||"android"===a?a:void 0)??(n=e,i=l,s=n.toLowerCase(),i.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),p=[];try{let t=c?await R(e,p):e,a=r.statSync(t);return{payloadPath:t,fileName:d,artifactType:c?"app-bundle":"file",platform:u,contentType:c?"application/gzip":"application/octet-stream",sha256:await z(t),sizeBytes:a.size,cleanup:()=>O(p)}}catch(e){throw O(p),e}}async function R(e,t){let a=r.mkdtempSync(o.join(i.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let n=o.join(a,`${o.basename(e)}.tar.gz`);return await m("tar",["czf",n,"-C",o.dirname(e),o.basename(e)]),n}function O(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function L(e){let{normalizedBase:t,token:a,artifact:r}=e,o=new URL("upload",t),n={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":U,"transfer-encoding":"chunked"};a&&(n.authorization=`Bearer ${a}`,n["x-agent-device-token"]=a);let i=await q({url:o,method:"POST",headers:n,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(i.body);if(!e.ok||!e.uploadId)throw new u("COMMAND_FAILED",`Upload failed: ${i.body}`);return e.uploadId}catch(e){if(e instanceof u)throw e;throw new u("COMMAND_FAILED",`Invalid upload response: ${i.body}`)}}async function F(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function B(e,t){let a=await q({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new u("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function q(e){let o="https:"===e.url.protocol?a:t;return await new Promise((t,a)=>{let i=o.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:e.headers},e=>{let a="";e.setEncoding("utf8"),e.on("data",e=>{a+=e}),e.on("end",()=>{clearTimeout(s),t({statusCode:e.statusCode??500,statusMessage:e.statusMessage,body:a})})}),s=setTimeout(()=>{i.destroy(),a(new u("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);i.on("error",t=>{clearTimeout(s),a(new u("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t))}),i.on("close",()=>clearTimeout(s)),n(r.createReadStream(e.payloadPath),i).catch(e=>{i.destroy(),a(new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e))))})})}async function j(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new u("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new u("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let o=await r.json().catch(()=>void 0);if(!o?.ok||!o.uploadId)throw new u("COMMAND_FAILED","Invalid upload finalize response");return o.uploadId}async function z(e){let t=s(U),a=new d({write(e,a,r){t.update(e),r()}});return await n(r.createReadStream(e),a).catch(e=>{throw new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),t.digest("hex")}let $=eA(),H=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS){if(!e)return 15e3;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):15e3}(),V=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_ATTEMPTS){if(!e)return 2;let t=Number(e);return Number.isFinite(t)?Math.min(5,Math.max(1,Math.floor(t))):2}(),G=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],K=new e.BlockList;async function J(t){let a=t.meta?.requestId??_(),r=!!(t.meta?.debug||t.flags?.verbose),o=function(t){let a,r=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,o=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new u("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new u("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),n=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var i=o,s=n;if(!(!i||"localhost"===(a=new URL(i).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(a)?K.check(a,"ipv4"):!!e.isIPv6(a)&&K.check(a,"ipv6")))&&("string"!=typeof s||!(s.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:i,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let l=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,d=b(l);if(o&&"socket"===d)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:o});let c=g(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===l?"dual":void 0));return{paths:y(r),transportPreference:d,serverMode:c,remoteBaseUrl:o,remoteAuthToken:n}}(t),n=function(e,t=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if("test"!==e)return eA(t)}(t.command),i=await M("daemon_startup",async()=>await Z(o),{requestId:a,session:t.session}),s=await W(t,i),l={...t,positionals:s.positionals,flags:s.flags,token:i.token,meta:{...t.meta??{},requestId:a,debug:r,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};return S({level:"info",phase:"daemon_request_prepare",data:{requestId:a,command:t.command,session:t.session}}),await M("daemon_request",async()=>await eu(i,l,o.transportPreference,n),{requestId:a,command:t.command})}async function W(e,t){let a,n=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(ev(t)){let r=function(e,t){if("screenshot"===e.command){let a=X(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:Y("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:Y("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=X(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:Y("recording",o.extname(t)||".mp4")}}return null}(e,n);r&&(void 0!==r.positionalPath&&(n[r.positionalIndex]=r.positionalPath),void 0!==r.flagPath&&((i??={}).out=r.flagPath),l[r.field]=r.localPath);let d=await Q(e,t);d&&(s=d.installSource,a=d.uploadedArtifactId??a)}if(!ev(t)||"install"!==e.command&&"reinstall"!==e.command||n.length<2)return{positionals:n,flags:i,installSource:s,uploadedArtifactId:a,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let d=n[1];if(d.startsWith("remote:"))return n[1]=d.slice(7),{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let c=o.isAbsolute(d)?d:o.resolve(e.meta?.cwd??process.cwd(),d);return r.existsSync(c)?{positionals:n,flags:i,installSource:s,uploadedArtifactId:a=await x({localPath:c,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform}),...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}:{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}}async function Q(e,t){let a=e.meta?.installSource;if("install_source"!==e.command||!a||"path"!==a.kind)return null;let n=a.path.trim();if(!n)return{installSource:a};if(n.startsWith("remote:"))return{installSource:{...a,path:n.slice(7)}};let i=o.isAbsolute(n)?n:o.resolve(e.meta?.cwd??process.cwd(),n);if(!r.existsSync(i))return{installSource:{...a,path:i}};let s=await x({localPath:i,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform});return{installSource:{...a,path:i},uploadedArtifactId:s}}function X(e,t,a,r=0){let n=e.positionals?.[r]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=n&&n.trim().length>0?n:i;return o.isAbsolute(s)?s:o.resolve(e.meta?.cwd??process.cwd(),s)}function Y(e,t){let a=t.startsWith(".")?t:`.${t}`;return o.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function Z(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await el(t,"http"))return t;throw new u("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}let a=er(e.paths.infoPath),r=w(),o=I((t=ec()).useSrc?t.srcPath:t.distPath,t.root),n=!!a&&await el(a,e.transportPreference);if(a&&a.version===r&&a.codeSignature===o&&n)return a;a&&(a.version!==r||a.codeSignature!==o||!n)&&(await ea(a),es(e.paths.infoPath)),function(e){let t=en(e);if(!t.hasLock||t.hasInfo)return;let a=eo(e.lockPath);if(!a)return es(e.lockPath);k(a.pid,a.processStartTime)||es(e.lockPath)}(e.paths);let i=0;for(let t=1;t<=V;t+=1){await ed(e);let a=await ee(H,e);if(a)return a;if(await et(e.paths)){i+=1;continue}let r=en(e.paths);if(!(t<V))break;if(!r.hasInfo&&!r.hasLock){await D(150);continue}}let s=en(e.paths);throw new u("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:H,startupAttempts:V,lockRecoveryCount:i,metadataState:s,hint:function(e,t=y(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`Detected ${t.lockPath} without ${t.infoPath}. If no agent-device daemon process is running, delete ${t.lockPath} and retry.`:e.hasLock&&e.hasInfo?`Daemon metadata may be stale. If no agent-device daemon process is running, delete ${t.infoPath} and ${t.lockPath}, then retry.`:`Daemon metadata is missing or stale. Delete ${t.infoPath} if present and retry.`}(s,e.paths)})}async function ee(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=er(t.paths.infoPath);if(e&&await el(e,t.transportPreference))return e;await D(100)}return null}async function et(e){let t=en(e);if(!t.hasLock||t.hasInfo)return!1;let a=eo(e.lockPath);return a&&k(a.pid,a.processStartTime)&&await E(a.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:a.processStartTime}),es(e.lockPath),!0}async function ea(e){await E(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function er(e){let t=ei(e);if(!t||"object"!=typeof t)return null;let a="string"==typeof t.token&&t.token.length>0?t.token:null;if(!a)return null;let r=Number.isInteger(t.port)&&Number(t.port)>0,o=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!r&&!o)return null;let n=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,d=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:a,port:r?Number(t.port):void 0,httpPort:o?Number(t.httpPort):void 0,transport:"socket"===n||"http"===n||"dual"===n?n:void 0,pid:d?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function eo(e){let t=ei(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}K.addSubnet("127.0.0.0",8,"ipv4"),K.addAddress("::1","ipv6"),K.addSubnet("::ffff:127.0.0.0",104,"ipv6");function en(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function ei(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function es(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function el(r,o){var n;return"http"===ep(r,o)?await function(e){let r=e.baseUrl?eg(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let o=new URL(r),n="https:"===o.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=n.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(r):await ((n=r.port)?new Promise(t=>{let a=e.createConnection({host:"127.0.0.1",port:n},()=>{a.destroy(),t(!0)});a.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function ed(e){let t=ec(),a=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};f(process.execPath,a,{env:r})}function ec(){let e=v(),t=[o.join(e,"dist","src","internal","daemon.js"),o.join(e,"dist","src","daemon.js")],a=t.find(e=>r.existsSync(e))??t[0],n=o.join(e,"src","daemon.ts"),i=t.some(e=>r.existsSync(e)),s=r.existsSync(n);if(!i&&!s)throw new u("COMMAND_FAILED","Daemon entry not found",{distPaths:t,srcPath:n});return{root:e,distPath:a,distPaths:t,srcPath:n,useSrc:process.execArgv.includes("--experimental-strip-types")?s:!i&&s}}async function eu(e,t,a,r){return"http"===ep(e,a)?await ew(e,t,r):await ey(e,t,r)}function ep(e,t){if(e.baseUrl){if("socket"===t)throw new u("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var a=e,r=t;if(em(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>em(e,t));if(o)return o;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function em(e,t){return"http"===t?!!e.httpPort:!!e.port}function ef(e,t,a,r,o,n){let i=o?{terminated:0}:function(){let e=0;try{for(let t of G){let a=p("pkill",["-f",t],{allowFailure:!0});0===a.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=o?{forcedKill:!1}:function(e,t){let a=!1;try{k(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{E(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{es(t.infoPath),es(t.lockPath)}return{forcedKill:a}}(e,t);return S({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:n,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:o?void 0:e.pid,daemonPidForceKilled:o?void 0:s.forcedKill,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:n,requestId:a,hint:o?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."})}function eh(e,t,a){return S({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new u("COMMAND_FAILED","Failed to communicate with daemon",{requestId:t,hint:a?"Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.":"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e instanceof Error?e:void 0)}async function ey(t,a,r){let o=t.port;if(!o)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((n,i)=>{let s=e.createConnection({host:"127.0.0.1",port:o},()=>{s.write(`${JSON.stringify(a)}
1
+ import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import o from"node:path";import{pipeline as n}from"node:stream/promises";import i from"node:os";import{createHash as s,randomUUID as l}from"node:crypto";import{Writable as d}from"node:stream";import{toAppErrorCode as c,AppError as u}from"./9152.js";import{runCmdSync as p,runCmd as m,runCmdDetached as f}from"./9818.js";import{buildDeviceIdentifiers as h,resolveDaemonPaths as y,readVersion as w,findProjectRoot as v,resolveDaemonServerMode as g,computeDaemonCodeSignature as I,resolveDaemonTransportPreference as b,buildAppIdentifiers as A}from"./180.js";import{createRequestId as _,withDiagnosticTimer as M,emitDiagnostic as S}from"./7599.js";import{isAgentDeviceDaemonProcess as k,stopProcessForTakeover as E}from"./8656.js";import{sleep as D}from"./4829.js";import{tryParseSelectorChain as P}from"./940.js";import{reloadMetro as T,prepareMetroRuntime as N}from"./1974.js";let U="sha256";async function x(e){let t=await C(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await F({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await B(t.payloadPath,r),await j({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await L({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function C(e,t){var a,n,i;let s,l=r.statSync(e),d=o.basename(e),c=l.isDirectory(),u=("ios"===(a=t)||"android"===a?a:void 0)??(n=e,i=l,s=n.toLowerCase(),i.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),p=[];try{let t=c?await R(e,p):e,a=r.statSync(t);return{payloadPath:t,fileName:d,artifactType:c?"app-bundle":"file",platform:u,contentType:c?"application/gzip":"application/octet-stream",sha256:await z(t),sizeBytes:a.size,cleanup:()=>O(p)}}catch(e){throw O(p),e}}async function R(e,t){let a=r.mkdtempSync(o.join(i.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let n=o.join(a,`${o.basename(e)}.tar.gz`);return await m("tar",["czf",n,"-C",o.dirname(e),o.basename(e)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),n}function O(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function L(e){let{normalizedBase:t,token:a,artifact:r}=e,o=new URL("upload",t),n={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":U,"transfer-encoding":"chunked"};a&&(n.authorization=`Bearer ${a}`,n["x-agent-device-token"]=a);let i=await q({url:o,method:"POST",headers:n,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(i.body);if(!e.ok||!e.uploadId)throw new u("COMMAND_FAILED",`Upload failed: ${i.body}`);return e.uploadId}catch(e){if(e instanceof u)throw e;throw new u("COMMAND_FAILED",`Invalid upload response: ${i.body}`)}}async function F(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function B(e,t){let a=await q({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new u("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function q(e){let o="https:"===e.url.protocol?a:t;return await new Promise((t,a)=>{let i=o.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:e.headers},e=>{let a="";e.setEncoding("utf8"),e.on("data",e=>{a+=e}),e.on("end",()=>{clearTimeout(s),t({statusCode:e.statusCode??500,statusMessage:e.statusMessage,body:a})})}),s=setTimeout(()=>{i.destroy(),a(new u("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);i.on("error",t=>{clearTimeout(s),a(new u("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t))}),i.on("close",()=>clearTimeout(s)),n(r.createReadStream(e.payloadPath),i).catch(e=>{i.destroy(),a(new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e))))})})}async function j(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new u("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new u("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let o=await r.json().catch(()=>void 0);if(!o?.ok||!o.uploadId)throw new u("COMMAND_FAILED","Invalid upload finalize response");return o.uploadId}async function z(e){let t=s(U),a=new d({write(e,a,r){t.update(e),r()}});return await n(r.createReadStream(e),a).catch(e=>{throw new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),t.digest("hex")}let $=eA(),H=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS){if(!e)return 15e3;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):15e3}(),V=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_ATTEMPTS){if(!e)return 2;let t=Number(e);return Number.isFinite(t)?Math.min(5,Math.max(1,Math.floor(t))):2}(),G=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],K=new e.BlockList;async function J(t){let a=t.meta?.requestId??_(),r=!!(t.meta?.debug||t.flags?.verbose),o=function(t){let a,r=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,o=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new u("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new u("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),n=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var i=o,s=n;if(!(!i||"localhost"===(a=new URL(i).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(a)?K.check(a,"ipv4"):!!e.isIPv6(a)&&K.check(a,"ipv6")))&&("string"!=typeof s||!(s.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:i,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let l=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,d=b(l);if(o&&"socket"===d)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:o});let c=g(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===l?"dual":void 0));return{paths:y(r),transportPreference:d,serverMode:c,remoteBaseUrl:o,remoteAuthToken:n}}(t),n=function(e,t=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if("test"!==e)return eA(t)}(t.command),i=await M("daemon_startup",async()=>await Z(o),{requestId:a,session:t.session}),s=await W(t,i),l={...t,positionals:s.positionals,flags:s.flags,token:i.token,meta:{...t.meta??{},requestId:a,debug:r,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};return S({level:"info",phase:"daemon_request_prepare",data:{requestId:a,command:t.command,session:t.session}}),await M("daemon_request",async()=>await eu(i,l,o.transportPreference,n),{requestId:a,command:t.command})}async function W(e,t){let a,n=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(ev(t)){let r=function(e,t){if("screenshot"===e.command){let a=Q(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:X("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:X("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=Q(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:X("recording",o.extname(t)||".mp4")}}return null}(e,n);r&&(void 0!==r.positionalPath&&(n[r.positionalIndex]=r.positionalPath),void 0!==r.flagPath&&((i??={}).out=r.flagPath),l[r.field]=r.localPath);let d=await Y(e,t);d&&(s=d.installSource,a=d.uploadedArtifactId??a)}if(!ev(t)||"install"!==e.command&&"reinstall"!==e.command||n.length<2)return{positionals:n,flags:i,installSource:s,uploadedArtifactId:a,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let d=n[1];if(d.startsWith("remote:"))return n[1]=d.slice(7),{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let c=o.isAbsolute(d)?d:o.resolve(e.meta?.cwd??process.cwd(),d);return r.existsSync(c)?{positionals:n,flags:i,installSource:s,uploadedArtifactId:a=await x({localPath:c,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform}),...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}:{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}}async function Y(e,t){let a=e.meta?.installSource;if("install_source"!==e.command||!a||"path"!==a.kind)return null;let n=a.path.trim();if(!n)return{installSource:a};if(n.startsWith("remote:"))return{installSource:{...a,path:n.slice(7)}};let i=o.isAbsolute(n)?n:o.resolve(e.meta?.cwd??process.cwd(),n);if(!r.existsSync(i))return{installSource:{...a,path:i}};let s=await x({localPath:i,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform});return{installSource:{...a,path:i},uploadedArtifactId:s}}function Q(e,t,a,r=0){let n=e.positionals?.[r]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=n&&n.trim().length>0?n:i;return o.isAbsolute(s)?s:o.resolve(e.meta?.cwd??process.cwd(),s)}function X(e,t){let a=t.startsWith(".")?t:`.${t}`;return o.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function Z(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await el(t,"http"))return t;throw new u("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}let a=er(e.paths.infoPath),r=w(),o=I((t=ec()).useSrc?t.srcPath:t.distPath,t.root),n=!!a&&await el(a,e.transportPreference);if(a&&a.version===r&&a.codeSignature===o&&n)return a;a&&(a.version!==r||a.codeSignature!==o||!n)&&(await ea(a),es(e.paths.infoPath)),function(e){let t=en(e);if(!t.hasLock||t.hasInfo)return;let a=eo(e.lockPath);if(!a)return es(e.lockPath);k(a.pid,a.processStartTime)||es(e.lockPath)}(e.paths);let i=0;for(let t=1;t<=V;t+=1){await ed(e);let a=await ee(H,e);if(a)return a;if(await et(e.paths)){i+=1;continue}let r=en(e.paths);if(!(t<V))break;if(!r.hasInfo&&!r.hasLock){await D(150);continue}}let s=en(e.paths);throw new u("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:H,startupAttempts:V,lockRecoveryCount:i,metadataState:s,hint:function(e,t=y(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`Detected ${t.lockPath} without ${t.infoPath}. If no agent-device daemon process is running, delete ${t.lockPath} and retry.`:e.hasLock&&e.hasInfo?`Daemon metadata may be stale. If no agent-device daemon process is running, delete ${t.infoPath} and ${t.lockPath}, then retry.`:`Daemon metadata is missing or stale. Delete ${t.infoPath} if present and retry.`}(s,e.paths)})}async function ee(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=er(t.paths.infoPath);if(e&&await el(e,t.transportPreference))return e;await D(100)}return null}async function et(e){let t=en(e);if(!t.hasLock||t.hasInfo)return!1;let a=eo(e.lockPath);return a&&k(a.pid,a.processStartTime)&&await E(a.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:a.processStartTime}),es(e.lockPath),!0}async function ea(e){await E(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function er(e){let t=ei(e);if(!t||"object"!=typeof t)return null;let a="string"==typeof t.token&&t.token.length>0?t.token:null;if(!a)return null;let r=Number.isInteger(t.port)&&Number(t.port)>0,o=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!r&&!o)return null;let n=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,d=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:a,port:r?Number(t.port):void 0,httpPort:o?Number(t.httpPort):void 0,transport:"socket"===n||"http"===n||"dual"===n?n:void 0,pid:d?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function eo(e){let t=ei(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}K.addSubnet("127.0.0.0",8,"ipv4"),K.addAddress("::1","ipv6"),K.addSubnet("::ffff:127.0.0.0",104,"ipv6");function en(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function ei(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function es(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function el(r,o){var n;return"http"===ep(r,o)?await function(e){let r=e.baseUrl?eg(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let o=new URL(r),n="https:"===o.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=n.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(r):await ((n=r.port)?new Promise(t=>{let a=e.createConnection({host:"127.0.0.1",port:n},()=>{a.destroy(),t(!0)});a.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function ed(e){let t=ec(),a=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};f(process.execPath,a,{env:r})}function ec(){let e=v(),t=[o.join(e,"dist","src","internal","daemon.js"),o.join(e,"dist","src","daemon.js")],a=t.find(e=>r.existsSync(e))??t[0],n=o.join(e,"src","daemon.ts"),i=t.some(e=>r.existsSync(e)),s=r.existsSync(n);if(!i&&!s)throw new u("COMMAND_FAILED","Daemon entry not found",{distPaths:t,srcPath:n});return{root:e,distPath:a,distPaths:t,srcPath:n,useSrc:process.execArgv.includes("--experimental-strip-types")?s:!i&&s}}async function eu(e,t,a,r){return"http"===ep(e,a)?await ew(e,t,r):await ey(e,t,r)}function ep(e,t){if(e.baseUrl){if("socket"===t)throw new u("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var a=e,r=t;if(em(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>em(e,t));if(o)return o;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function em(e,t){return"http"===t?!!e.httpPort:!!e.port}function ef(e,t,a,r,o,n){let i=o?{terminated:0}:function(){let e=0;try{for(let t of G){let a=p("pkill",["-f",t],{allowFailure:!0});0===a.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=o?{forcedKill:!1}:function(e,t){let a=!1;try{k(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{E(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{es(t.infoPath),es(t.lockPath)}return{forcedKill:a}}(e,t);return S({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:n,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:o?void 0:e.pid,daemonPidForceKilled:o?void 0:s.forcedKill,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:n,requestId:a,hint:o?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."})}function eh(e,t,a){return S({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new u("COMMAND_FAILED","Failed to communicate with daemon",{requestId:t,hint:a?"Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.":"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e instanceof Error?e:void 0)}async function ey(t,a,r){let o=t.port;if(!o)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((n,i)=>{let s=e.createConnection({host:"127.0.0.1",port:o},()=>{s.write(`${JSON.stringify(a)}
2
2
  `)}),l=y(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),d="number"==typeof r?setTimeout(()=>{s.destroy(),i(ef(t,l,a.meta?.requestId,a.command,!1,r))},r):void 0,c="";s.setEncoding("utf8"),s.on("data",e=>{let t=(c+=e).indexOf("\n");if(-1===t)return;let r=c.slice(0,t).trim();if(r)try{let e=JSON.parse(r);s.end(),d&&clearTimeout(d),n(e)}catch(e){d&&clearTimeout(d),i(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}}),s.on("error",e=>{d&&clearTimeout(d),i(eh(e,a.meta?.requestId,!1))})})}async function ew(e,r,o){var n,i,s;let l,d=e.baseUrl?new URL(eg(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!d)throw new u("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let p=JSON.stringify((n=r,i={includeTokenParam:!e.baseUrl},l=n.meta?.requestId??_(),"lease_allocate"!==(s=n.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:n}:{jsonrpc:"2.0",id:l,method:function(e){switch(e){case"lease_allocate":return"agent_device.lease.allocate";case"lease_heartbeat":return"agent_device.lease.heartbeat";case"lease_release":return"agent_device.lease.release"}}(n.command),params:function(e,t,a){let r={...a.includeTokenParam?{token:e.token}:{},session:e.session,tenantId:e.meta?.tenantId,runId:e.meta?.runId};switch(t){case"lease_allocate":return{...r,ttlMs:e.meta?.leaseTtlMs,backend:e.meta?.leaseBackend};case"lease_heartbeat":return{...r,leaseId:e.meta?.leaseId,ttlMs:e.meta?.leaseTtlMs};case"lease_release":return{...r,leaseId:e.meta?.leaseId}}}(n,n.command,i)})),m={"content-type":"application/json","content-length":Buffer.byteLength(p)};return e.baseUrl&&e.token&&(m.authorization=`Bearer ${e.token}`,m["x-agent-device-token"]=e.token),await new Promise((n,i)=>{let s=y(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),l=("https:"===d.protocol?a:t).request({protocol:d.protocol,host:d.hostname,port:d.port,method:"POST",path:d.pathname+d.search,headers:m},t=>{let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{h&&clearTimeout(h);try{let t=JSON.parse(a);if(t.error){let e=t.error.data??{};i(new u(c(null!=e.code?String(e.code):void 0,"COMMAND_FAILED"),String(e.message??t.error.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:r.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void i(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));if(e.baseUrl&&t.result.ok)return void eI(e,r,t.result).then(n).catch(i);n(t.result)}catch(e){h&&clearTimeout(h),i(new u("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:a},e instanceof Error?e:void 0))}})}),f=ev(e),h="number"==typeof o?setTimeout(()=>{l.destroy(),i(ef(e,s,r.meta?.requestId,r.command,f,o))},o):void 0;l.on("error",e=>{h&&clearTimeout(h),i(eh(e,r.meta?.requestId,f))}),l.write(p),l.end()})}function ev(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function eg(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function eI(e,t,a){let r=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===r.length||!e.baseUrl)return a;let n=a.data?{...a.data}:{},i=[];for(let a of r){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){i.push(a);continue}let r=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=e.fileName?.trim()||`${e.field}-${Date.now()}`;return o.resolve(t.meta?.cwd??process.cwd(),a)}(a,t);await eb({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:r,requestId:t.meta?.requestId}),n[a.field]=r,i.push({...a,localPath:r})}return n.artifacts=i,{ok:!0,data:n}}async function eb(e){var i,s;let l,d=new URL((i=e.baseUrl,s=e.artifactId,l=i.endsWith("/")?i:`${i}/`,new URL(`artifacts/${encodeURIComponent(s)}`,l).toString())),c="https:"===d.protocol?a:t;await r.promises.mkdir(o.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let o=!1,i=e.timeoutMs??$,s=n=>{if(!o){if(o=!0,clearTimeout(p),n)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(n));t()}},l=c.request({protocol:d.protocol,host:d.hostname,port:d.port,method:"GET",path:d.pathname+d.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{s(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:a}))});return}t.on("aborted",()=>{s(new u("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),n(t,r.createWriteStream(e.destinationPath)).then(()=>s(),e=>s(e instanceof Error?e:Error(String(e))))}),p=setTimeout(()=>{l.destroy(new u("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:i}))},i);l.on("error",t=>{t instanceof u?s(t):s(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:i},t instanceof Error?t:void 0))}),l.end()})}function eA(e=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if(!e)return 9e4;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):9e4}let e_={alert:"alert",appState:"appstate",appSwitcher:"app-switcher",apps:"apps",back:"back",batch:"batch",boot:"boot",click:"click",clipboard:"clipboard",devices:"devices",diff:"diff",fill:"fill",find:"find",focus:"focus",get:"get",home:"home",is:"is",keyboard:"keyboard",logs:"logs",longPress:"longpress",network:"network",perf:"perf",pinch:"pinch",press:"press",push:"push",record:"record",replay:"replay",rotate:"rotate",scroll:"scroll",screenshot:"screenshot",settings:"settings",snapshot:"snapshot",swipe:"swipe",test:"test",trace:"trace",triggerAppEvent:"trigger-app-event",type:"type",wait:"wait"};function eM(e,t,a,r){let o=a(e[t]);if(void 0===o)throw new u("COMMAND_FAILED",r,{response:e});return o}function eS(e,t){return eM(e,t,eN,`Daemon response is missing "${t}".`)}function ek(e,t){return eN(e[t])}function eE(e,t){var a;let r;return a=eN,null===(r=e[t])?null:a(r)}function eD(e,t){return eM(e,t,ex,`Daemon response has invalid "${t}".`)}function eP(e,t){return function(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}(e[t])??"mobile"}function eT(e,t){let a=e[t];if(!eO(a))return;let r="number"==typeof a.x?a.x:void 0,o="number"==typeof a.y?a.y:void 0,n="number"==typeof a.width?a.width:void 0,i="number"==typeof a.height?a.height:void 0;if(void 0!==r&&void 0!==o&&void 0!==n&&void 0!==i)return{x:r,y:o,width:n,height:i}}function eN(e){return"string"==typeof e&&e.length>0?e:void 0}function eU(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function ex(e){return"ios"===e||"macos"===e||"android"===e?e:void 0}function eC(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}function eR(e){if(!eO(e))throw new u("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:e});return e}function eO(e){return"object"==typeof e&&null!==e}function eL(e){let t={};for(let[a,r]of Object.entries(e))void 0!==r&&(t[a]=r);return t}function eF(e,t){let a=ek(e,"bundleId"),r=ek(e,"package");return{app:eS(e,"app"),appPath:eS(e,"appPath"),platform:eD(e,"platform"),appId:a??r,bundleId:a,package:r,identifiers:A({session:t,bundleId:a,packageName:r})}}function eB(e){let t=eR(e),a=eD(t,"platform"),r=eS(t,"id"),o=eS(t,"name");return{platform:a,target:eP(t,"target"),kind:eM(t,"kind",eC,'Daemon response has invalid "kind".'),id:r,name:o,booted:"boolean"==typeof t.booted?t.booted:void 0,identifiers:h(a,r,o),ios:"ios"===a?{udid:r}:void 0,android:"android"===a?{serial:r}:void 0}}function eq(e){let t=eR(e),a=eD(t,"platform"),r=eS(t,"id"),o=eS(t,"name"),n=eP(t,"target"),i=eS(t,"device"),s={session:o,...h(a,r,i)};return{name:o,createdAt:eM(t,"createdAt",eU,'Daemon response is missing numeric "createdAt".'),device:{platform:a,target:n,id:r,name:i,identifiers:s,ios:"ios"===a?{udid:r,simulatorSetPath:eE(t,"ios_simulator_device_set")}:void 0,android:"android"===a?{serial:r}:void 0},identifiers:s}}function ej(e){return e??"default"}function ez(e={},t={}){var a;let r,o=t.transport??J,n=async(t,a=[],r={})=>{var n,i;let s=(n=e,i=r,{...n,...i}),l=await o({session:ej(s.session),command:t,positionals:a,flags:eL({stateDir:s.stateDir,daemonBaseUrl:s.daemonBaseUrl,daemonAuthToken:s.daemonAuthToken,daemonTransport:s.daemonTransport,daemonServerMode:s.daemonServerMode,tenant:s.tenant,sessionIsolation:s.sessionIsolation,runId:s.runId,leaseId:s.leaseId,leaseBackend:s.leaseBackend,platform:s.platform,target:s.target,device:s.device,udid:s.udid,serial:s.serial,iosSimulatorDeviceSet:s.iosSimulatorDeviceSet,androidDeviceAllowlist:s.androidDeviceAllowlist,runtime:s.simulatorRuntimeId,boot:s.boot,reuseExisting:s.reuseExisting,surface:s.surface,activity:s.activity,relaunch:s.relaunch,shutdown:s.shutdown,saveScript:s.saveScript,noRecord:s.noRecord,backMode:s.backMode,metroHost:s.metroHost,metroPort:s.metroPort,bundleUrl:s.bundleUrl,launchUrl:s.launchUrl,snapshotInteractiveOnly:s.interactiveOnly,snapshotCompact:s.compact,snapshotDepth:s.depth,snapshotScope:s.scope,snapshotRaw:s.raw,screenshotFullscreen:s.screenshotFullscreen,screenshotMaxSize:s.screenshotMaxSize,overlayRefs:s.overlayRefs,appsFilter:s.appsFilter,out:s.out,count:s.count,fps:s.fps,quality:s.quality,hideTouches:s.hideTouches,intervalMs:s.intervalMs,delayMs:s.delayMs,holdMs:s.holdMs,jitterPx:s.jitterPx,pixels:s.pixels,doubleTap:s.doubleTap,clickButton:s.clickButton,pauseMs:s.pauseMs,pattern:s.pattern,headless:s.headless,restart:s.restart,replayUpdate:s.replayUpdate,replayEnv:s.replayEnv,replayShellEnv:s.replayShellEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit,findFirst:s.findFirst,findLast:s.findLast,networkInclude:s.networkInclude,batchOnError:s.batchOnError,batchMaxSteps:s.batchMaxSteps,batchSteps:s.batchSteps,verbose:s.debug}),runtime:s.runtime,meta:eL({requestId:s.requestId,cwd:s.cwd,debug:s.debug,lockPolicy:s.lockPolicy,lockPlatform:s.lockPlatform,tenantId:s.tenant,runId:s.runId,leaseId:s.leaseId,leaseBackend:s.leaseBackend,leaseTtlMs:s.leaseTtlMs,sessionIsolation:s.sessionIsolation,installSource:s.installSource,retainMaterializedPaths:s.retainMaterializedPaths,materializedPathRetentionMs:s.materializedPathRetentionMs,materializationId:s.materializationId})});return l.ok||function(e){throw new u(c(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(l.error),l.data??{}},i=async(e={})=>{let t=await n("session_list",[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(eq)},s=async(e,t=[],a={})=>await n(e,t,a),l=(t={})=>{var a,r;return ej((a=e,r=t,{...a,...r}).session)};return{command:(a=async e=>await n(e.command,e.positionals,e.options),r=async e=>await a(e),{wait:async e=>await r(function(e){if(1!==[void 0!==e.durationMs?"durationMs":void 0,void 0!==e.text?"text":void 0,void 0!==e.ref?"ref":void 0,void 0!==e.selector?"selector":void 0].filter(Boolean).length)throw new u("INVALID_ARGS","wait command requires exactly one of durationMs, text, ref, or selector.");if(void 0!==e.durationMs)return{command:e_.wait,positionals:[String(e.durationMs)],options:e};let t=void 0!==e.timeoutMs?[String(e.timeoutMs)]:[];if(void 0!==e.text)return{command:e_.wait,positionals:["text",e.text,...t],options:e};if(void 0!==e.ref)return{command:e_.wait,positionals:[e.ref,...t],options:e};let a=e.selector;return function(e){if(!P(e))throw new u("INVALID_ARGS",`Invalid wait selector: ${e}`)}(a),{command:e_.wait,positionals:[a,...t],options:e}}(e)),alert:async(e={})=>{var t;let a;return await r((a=(t=e).action??"get",{command:e_.alert,positionals:[a,...void 0!==t.timeoutMs?[String(t.timeoutMs)]:[]],options:t}))},appState:async(e={})=>await r({command:e_.appState,positionals:[],options:e}),back:async(e={})=>await r({command:e_.back,positionals:[],options:{...e,backMode:e.mode}}),home:async(e={})=>await r({command:e_.home,positionals:[],options:e}),rotate:async e=>await r({command:e_.rotate,positionals:[e.orientation],options:e}),appSwitcher:async(e={})=>await r({command:e_.appSwitcher,positionals:[],options:e}),keyboard:async(e={})=>await r({command:e_.keyboard,positionals:e.action?[e.action]:[],options:e}),clipboard:async e=>{var t;return await r("read"===(t=e).action?{command:e_.clipboard,positionals:["read"],options:t}:{command:e_.clipboard,positionals:["write",t.text],options:t})}}),devices:{list:async(e={})=>{let t=await n(e_.devices,[],e);return(Array.isArray(t.devices)?t.devices:[]).map(eB)},boot:async(e={})=>await s(e_.boot,[],e)},sessions:{list:async(e={})=>await i(e),close:async(e={})=>{let t=l(e),a=(await n("close",[],e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},simulators:{ensure:async e=>{let{runtime:t,...a}=e,r=await n("ensure-simulator",[],{...a,simulatorRuntimeId:t}),o=eS(r,"udid"),i=eS(r,"device");return{udid:o,device:i,runtime:eS(r,"runtime"),created:!0===r.created,booted:!0===r.booted,iosSimulatorDeviceSet:eE(r,"ios_simulator_device_set"),identifiers:{deviceId:o,deviceName:i,udid:o}}}},apps:{install:async e=>eF(await n("install",[e.app,e.appPath],e),l(e)),reinstall:async e=>eF(await n("reinstall",[e.app,e.appPath],e),l(e)),installFromSource:async e=>(function(e,t){let a=ek(e,"bundleId"),r=ek(e,"packageName"),o=a??r??ek(e,"appId"),n=ek(e,"launchTarget")??r??a??o;if(!n)throw new u("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:ek(e,"appName"),appId:o,bundleId:a,packageName:r,launchTarget:n,installablePath:ek(e,"installablePath"),archivePath:ek(e,"archivePath"),materializationId:ek(e,"materializationId"),materializationExpiresAt:ek(e,"materializationExpiresAt"),identifiers:A({session:t,bundleId:a,packageName:r,appId:o})}})(await n("install_source",[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),l(e)),list:async(e={})=>{let t=await n(e_.apps,[],e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=l(e),a=e.app?e.url?[e.app,e.url]:[e.app]:[],r=await n("open",a,e),o=function(e){let t=e.platform,a=ek(e,"id"),r=ek(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t||!a||!r)return;let o=eP(e,"target"),n=h(t,a,r);return{platform:t,target:o,id:a,name:r,identifiers:n,ios:"ios"===t?{udid:ek(e,"device_udid")??a,simulatorSetPath:eE(e,"ios_simulator_device_set")}:void 0,android:"android"===t?{serial:ek(e,"serial")??a}:void 0}}(r),i=ek(r,"appBundleId");return{session:t,appName:ek(r,"appName"),appBundleId:i,appId:i,startup:function(e){if(eO(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:ek(e,"appTarget"),appBundleId:ek(e,"appBundleId")}}(r.startup),runtime:function(e){if(!eO(e))return;let t=e.platform,a=ek(e,"metroHost"),r="number"==typeof e.metroPort?e.metroPort:void 0;return{platform:"ios"===t||"android"===t?t:void 0,metroHost:a,metroPort:r,bundleUrl:ek(e,"bundleUrl"),launchUrl:ek(e,"launchUrl")}}(r.runtime),device:o,identifiers:{session:t,deviceId:o?.id,deviceName:o?.name,udid:o?.ios?.udid,serial:o?.android?.serial,appId:i,appBundleId:i}}},close:async(e={})=>{let t=l(e),a=(await n("close",e.app?[e.app]:[],e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>{var t;return await s(e_.push,[e.app,"string"==typeof(t=e.payload)?t:JSON.stringify(t)],e)},triggerEvent:async e=>{var t;return await s(e_.triggerAppEvent,[(t=e).event,...t.payload?[JSON.stringify(t.payload)]:[]],e)}},materializations:{release:async e=>{var t;return{released:!0===(t=await n("release_materialized_paths",[],{...e,materializationId:e.materializationId})).released,materializationId:eS(t,"materializationId"),identifiers:{}}}},leases:{allocate:async e=>eK(await n("lease_allocate",[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>eK(await n("lease_heartbeat",[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await n("lease_release",[],e)).released})},metro:{prepare:async t=>await N({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath}),reload:async(t={})=>await T({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t;let a=l(e),r=await n(e_.snapshot,[],e),o=ek(r,"appBundleId"),i="object"==typeof r.visibility&&null!==r.visibility?r.visibility:void 0,s="object"==typeof r.androidSnapshot&&null!==r.androidSnapshot?r.androidSnapshot:void 0;return{nodes:Array.isArray(t=r.nodes)?t:[],truncated:!0===r.truncated,appName:ek(r,"appName"),appBundleId:o,...i?{visibility:i}:{},...s?{androidSnapshot:s}:{},warnings:Array.isArray(r.warnings)?r.warnings.filter(e=>"string"==typeof e):void 0,identifiers:{session:a,appId:o,appBundleId:o}}},screenshot:async(e={})=>{let t=l(e),a=await n(e_.screenshot,e.path?[e.path]:[],{...e,screenshotFullscreen:e.fullscreen,screenshotMaxSize:e.maxSize});return{path:eS(a,"path"),overlayRefs:function(e){let t=e.overlayRefs;if(!Array.isArray(t))return;let a=[];for(let e of t){if(!eO(e))continue;let t=ek(e,"ref"),r=eT(e,"rect"),o=eT(e,"overlayRect"),n=function(e,t){let a=e[t];if(!eO(a))return;let r="number"==typeof a.x?a.x:void 0,o="number"==typeof a.y?a.y:void 0;if(void 0!==r&&void 0!==o)return{x:r,y:o}}(e,"center");t&&r&&o&&n&&a.push({ref:t,label:ek(e,"label"),rect:r,overlayRect:o,center:n})}return a}(a),identifiers:{session:t}}},diff:async e=>await s(e_.diff,[e.kind],{...e,interactiveOnly:e.interactiveOnly,compact:e.compact,depth:e.depth,scope:e.scope,raw:e.raw})},interactions:{click:async e=>await s(e_.click,e$(e),{...e,clickButton:e.button}),press:async e=>await s(e_.press,e$(e),e),longPress:async e=>await s(e_.longPress,[String(e.x),String(e.y),...eV(e.durationMs)],e),swipe:async e=>await s(e_.swipe,[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y),...eV(e.durationMs)],e),focus:async e=>await s(e_.focus,[String(e.x),String(e.y)],e),type:async e=>await s(e_.type,[e.text],e),fill:async e=>await s(e_.fill,[...e$(e),e.text],e),scroll:async e=>await s(e_.scroll,[e.direction,...eV(e.amount)],e),pinch:async e=>await s(e_.pinch,[String(e.scale),...eV(e.x),...eV(e.y)],e),get:async e=>{var t;return await s(e_.get,[e.format,...void 0!==(t=e).ref?[t.ref,...eH(t.label)]:[t.selector]],e)},is:async e=>await s(e_.is,[e.predicate,e.selector,..."text"===e.predicate?[e.value]:[]],e),find:async e=>await s(e_.find,function(e){let t=e.locator&&"any"!==e.locator?[e.locator,e.query]:[e.query];switch(e.action){case void 0:case"click":case"focus":case"exists":return e.action?[...t,e.action]:t;case"getText":return[...t,"get","text"];case"getAttrs":return[...t,"get","attrs"];case"wait":return[...t,"wait",...eV(e.timeoutMs)];case"fill":case"type":return[...t,e.action,e.value]}}(e),{...e,findFirst:e.first,findLast:e.last})},replay:{run:async e=>await s(e_.replay,[e.path],{...e,replayUpdate:e.update,replayEnv:e.env,replayShellEnv:eG(process.env)}),test:async e=>await s(e_.test,e.paths,{...e,replayUpdate:e.update,replayEnv:e.env,replayShellEnv:eG(process.env)})},batch:{run:async e=>await s(e_.batch,[],{...e,batchSteps:e.steps,batchOnError:e.onError,batchMaxSteps:e.maxSteps})},observability:{perf:async(e={})=>await s(e_.perf,[],e),logs:async(e={})=>{var t;return await s(e_.logs,[(t=e).action??"path",...eH(t.message)],e)},network:async(e={})=>{var t;return await s(e_.network,[...(t=e).action?[t.action]:[],...eV(t.limit)],{...e,networkInclude:e.include})}},recording:{record:async e=>await s(e_.record,[e.action,...eH(e.path)],e),trace:async e=>await s(e_.trace,[e.action,...eH(e.path)],e)},settings:{update:async e=>await s(e_.settings,[e.setting,e.state,..."permission"in e?[e.permission]:[],..."mode"in e&&e.mode?[e.mode]:[]],e)}}}function e$(e){return void 0!==e.ref?[e.ref,...eH(e.label)]:void 0!==e.selector?[e.selector]:[String(e.x),String(e.y)]}function eH(e){return void 0===e?[]:[e]}function eV(e){return void 0===e?[]:[String(e)]}function eG(e){let t={};for(let[a,r]of Object.entries(e))"string"==typeof r&&a.startsWith("AD_VAR_")&&(t[a]=r);return t}function eK(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:eS(t,"leaseId"),tenantId:eS(t,"tenantId"),runId:eS(t,"runId"),backend:eS(t,"backend"),createdAt:"number"==typeof t.createdAt?t.createdAt:void 0,heartbeatAt:"number"==typeof t.heartbeatAt?t.heartbeatAt:void 0,expiresAt:"number"==typeof t.expiresAt?t.expiresAt:void 0}}export{e_ as CLIENT_COMMANDS,ez as createAgentDeviceClient,J as sendToDaemon};
@@ -1,4 +1,4 @@
1
- let e,t,s,o,r,n,a,i;import l from"node:path";import{styleText as c}from"node:util";import{pathToFileURL as d}from"node:url";import p from"node:fs";import u from"node:crypto";import{buildMobileSnapshotPresentation as m,SESSION_SURFACES as f,formatSnapshotLine as g,SETTINGS_USAGE_OVERRIDE as h,createAgentDevice as v,displayNodeLabel as y,localCommandPolicy as w,parseDeviceRotation as b,parseWaitArgs as k,buildSnapshotDisplayLines as A}from"../2007.js";import{resolveRemoteConfigProfile as I,resolveRemoteConfigPath as D,REMOTE_CONFIG_FIELD_SPECS as S,parseSourceValue as x,buildPrimaryEnvVarName as $}from"../remote-config.js";import{asAppError as L,normalizeError as N,AppError as C}from"../9152.js";import{ensureCompanionTunnel as R,stopCompanionTunnel as _}from"../1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as E}from"../2301.js";import{createRequestId as O,withDiagnosticsScope as U,getDiagnosticsMeta as P,flushDiagnosticsToSessionFile as T,emitDiagnostic as M}from"../7599.js";import{serializeOpenResult as F,serializeSnapshotResult as B,serializeSessionListEntry as j,serializeDeployResult as V,readCommandMessage as G,serializeCloseResult as q,resolveDaemonPaths as K,serializeEnsureSimulatorResult as H,serializeInstallFromSourceResult as J,serializeDevice as z,readVersion as W}from"../180.js";import{stopMetroTunnel as Y}from"../metro.js";import{runCmdStreaming as Z,runCmd as X}from"../9818.js";import{resolveUserPath as Q,expandUserHomePath as ee}from"../3267.js";import{createLocalArtifactAdapter as et}from"../io.js";import{createAgentDeviceClient as es,CLIENT_COMMANDS as eo,sendToDaemon as er}from"../9542.js";import{splitSelectorFromArgs as en}from"../940.js";import{isEnvTruthy as ea}from"../8809.js";import{parseBatchStepsJson as ei}from"../1231.js";import{maybeRunUpgradeNotifier as el}from"../113.js";function ec(e,t){for(let[s,o]of Object.entries(t))void 0!==o&&(e[s]=o);return e}let ed=["snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"],ep=["snapshotDepth","snapshotScope","snapshotRaw"],eu={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
1
+ let e,t,s,o,r,n,a,i;import l from"node:path";import{styleText as c}from"node:util";import{pathToFileURL as d}from"node:url";import p from"node:fs";import u from"node:crypto";import{buildMobileSnapshotPresentation as m,SESSION_SURFACES as f,formatSnapshotLine as g,SETTINGS_USAGE_OVERRIDE as h,createAgentDevice as v,displayNodeLabel as y,localCommandPolicy as w,parseDeviceRotation as b,parseWaitArgs as k,buildSnapshotDisplayLines as A}from"../2007.js";import{resolveRemoteConfigProfile as I,resolveRemoteConfigPath as D,REMOTE_CONFIG_FIELD_SPECS as S,parseSourceValue as x,buildPrimaryEnvVarName as $}from"../remote-config.js";import{asAppError as C,normalizeError as L,AppError as N}from"../9152.js";import{ensureCompanionTunnel as R,stopCompanionTunnel as _}from"../1974.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as E}from"../2301.js";import{createRequestId as O,withDiagnosticsScope as U,getDiagnosticsMeta as P,flushDiagnosticsToSessionFile as T,emitDiagnostic as M}from"../7599.js";import{serializeOpenResult as F,serializeSnapshotResult as B,serializeSessionListEntry as j,serializeDeployResult as V,readCommandMessage as G,serializeCloseResult as q,resolveDaemonPaths as H,serializeEnsureSimulatorResult as K,serializeInstallFromSourceResult as J,serializeDevice as z,readVersion as W}from"../180.js";import{stopMetroTunnel as Y}from"../metro.js";import{runCmdStreaming as Z,runCmd as X}from"../9818.js";import{resolveUserPath as Q,expandUserHomePath as ee}from"../3267.js";import{createLocalArtifactAdapter as et}from"../io.js";import{createAgentDeviceClient as es,CLIENT_COMMANDS as eo,sendToDaemon as er}from"../9542.js";import{splitSelectorFromArgs as en}from"../940.js";import{isEnvTruthy as ea}from"../8809.js";import{parseBatchStepsJson as ei}from"../1231.js";import{maybeRunUpgradeNotifier as el}from"../113.js";function ec(e,t){for(let[s,o]of Object.entries(t))void 0!==o&&(e[s]=o);return e}let ed=["snapshotInteractiveOnly","snapshotCompact","snapshotDepth","snapshotScope","snapshotRaw"],ep=["snapshotDepth","snapshotScope","snapshotRaw"],eu={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
2
2
 
3
3
  Version-matched operating guide for normal agent-device work.
4
4
 
@@ -102,7 +102,7 @@ Validation and evidence:
102
102
  Android animations: settings animations off/on, not animations disable/restore.
103
103
  Debug logs: logs clear --restart, logs mark, reproduce, then logs path; do not split clear/restart into separate stop/start commands.
104
104
  Network headers: network dump --include headers; do not write network log headers.
105
- Remote config: connect --remote-config ./remote-config.json, open, snapshot, disconnect.
105
+ Remote/cloud: connect to discover a cloud profile, or connect --remote-config ./remote-config.json for a local profile; then open, snapshot, disconnect.
106
106
  macOS menu bar: open ... --platform macos --surface menubar; snapshot -i --platform macos --surface menubar.
107
107
 
108
108
  React Native dev loop:
@@ -220,7 +220,8 @@ Rules:
220
220
  @c refs reset after reload/remount. After reload, wait --connected and inspect again.
221
221
  Keep the profile window narrow; unrelated navigation makes render data noisy.
222
222
  For cross-platform validation with explicit device selectors, prefer isolated --state-dir and restart react-devtools between platforms.
223
- Remote Android and iOS bridge runs normally through agent-device react-devtools; the CLI manages the needed local service tunnel. Expo support depends on the SDK's bundled React Native runtime.
223
+ Remote Android and iOS bridge runs normally through agent-device react-devtools; the CLI keeps the needed local service tunnel alive until agent-device react-devtools stop or disconnect. Expo support depends on the SDK's bundled React Native runtime.
224
+ Remote iOS apps attempt the legacy React DevTools websocket during JavaScript startup. If the app was already open before react-devtools start, run open <bundle-id> --platform ios --relaunch, then wait --connected.
224
225
 
225
226
  Example:
226
227
  agent-device react-devtools status
@@ -234,9 +235,15 @@ Example:
234
235
 
235
236
  Use snapshot, screenshot, logs, network, and perf for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},remote:{summary:"Remote config, tenant, lease, and remote host flow",body:`agent-device help remote
236
237
 
237
- Use remote config when a profile owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
238
+ Use remote config or the cloud connection profile when a profile owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
238
239
 
239
- Normal flow:
240
+ Cloud profile flow:
241
+ agent-device connect
242
+ agent-device open com.example.app
243
+ agent-device snapshot
244
+ agent-device disconnect
245
+
246
+ Local profile flow:
240
247
  agent-device connect --remote-config ./remote-config.json
241
248
  agent-device open com.example.app
242
249
  agent-device snapshot
@@ -249,11 +256,12 @@ Script flow, per-command config:
249
256
 
250
257
  Rules:
251
258
  connect and disconnect are top-level commands. Do not write agent-device remote connect or agent-device remote disconnect.
252
- Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id in ordinary remote flows.
259
+ Use connect without --remote-config when the cloud control plane owns the connection profile.
260
+ Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
253
261
  For self-contained scripts, pass the same --remote-config to every operational command, including disconnect; a preceding connect is optional but not required.
254
262
  For remote artifact installs, use install-from-source <url> or install-from-source --github-actions-artifact org/repo:artifact; do not download CI artifacts locally first.
255
263
  After connect, let the active remote connection supply runtime hints.
256
- For remote Android and iOS bridge React DevTools, run agent-device react-devtools normally. The CLI opens the needed local service tunnel for the DevTools daemon and cleans it up when the command exits.
264
+ For remote Android and iOS bridge React DevTools, run agent-device react-devtools normally. The CLI opens the needed local service tunnel for the DevTools daemon and keeps it alive until agent-device react-devtools stop or disconnect.
257
265
  Use --debug when remote connection or transport errors need diagnostic ids and remote log hints.`},macos:{summary:"macOS desktop, frontmost-app, and menu bar surfaces",body:`agent-device help macos
258
266
 
259
267
  Use macOS only when the task targets desktop apps, desktop surfaces, or menu bar extras.
@@ -355,26 +363,26 @@ ${a}
355
363
  ${i}
356
364
  `);function eA(e){return em.filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function eI(e,t){return eD(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function eD(e,t){if(0===t.length)return`${e}
357
365
  (none)`;let s=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(s)}${e.description}`);return o.join("\n")}function eS(e,t){return 0===t.length?`${e}
358
- (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let ex=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),e$={iosSimulatorDeviceSet:["IOS_SIMULATOR_DEVICE_SET"],androidDeviceAllowlist:["ANDROID_DEVICE_ALLOWLIST"],metroBearerToken:["AGENT_DEVICE_PROXY_TOKEN"]},eL=function(){let e=new Map;for(let t of em){let s=e.get(t.key);s?s.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ef)t.set(e,new Set(["*"]));for(let e of ew()){let s=ey(e);if(s)for(let o of s.allowedFlags){let s=t.get(o);s&&s.has("*")||(s?s.add(e):t.set(o,new Set([e])))}}return[...e.entries()].map(([e,s])=>({key:e,flagDefinitions:s,config:{enabled:!ex.has(e),key:e},env:{names:[$(e),...e$[e]??[]]},supportsCommand(s){let o=t.get(e);return!!o&&(!!o.has("*")||!!s&&o.has(s))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eN=new Map(eL.map(e=>[e.key,e]));function eC(e,t){return eN.get(e)?.supportsCommand(t)??!1}function eR(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let s=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===s.type){let t=e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...s,setValue:void 0,enumValues:t}}return s}function e_(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eE(e){return e.replace(/^-+/,"")}function eO(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?e_(e):[e,void 0];return void 0!==eh.get(t)}function eU(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eP(e){process.stdout.write(`${JSON.stringify(e,null,2)}
359
- `)}function eT(e,t={}){let s=e instanceof C?N(e):e;process.stderr.write(`Error (${s.code}): ${s.message}
366
+ (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}let ex=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),e$={iosSimulatorDeviceSet:["IOS_SIMULATOR_DEVICE_SET"],androidDeviceAllowlist:["ANDROID_DEVICE_ALLOWLIST"],metroBearerToken:["AGENT_DEVICE_PROXY_TOKEN"]},eC=function(){let e=new Map;for(let t of em){let s=e.get(t.key);s?s.push(t):e.set(t.key,[t])}let t=new Map;for(let e of ef)t.set(e,new Set(["*"]));for(let e of ew()){let s=ey(e);if(s)for(let o of s.allowedFlags){let s=t.get(o);s&&s.has("*")||(s?s.add(e):t.set(o,new Set([e])))}}return[...e.entries()].map(([e,s])=>({key:e,flagDefinitions:s,config:{enabled:!ex.has(e),key:e},env:{names:[$(e),...e$[e]??[]]},supportsCommand(s){let o=t.get(e);return!!o&&(!!o.has("*")||!!s&&o.has(s))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eL=new Map(eC.map(e=>[e.key,e]));function eN(e,t){return eL.get(e)?.supportsCommand(t)??!1}function eR(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let s=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===s.type){let t=e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...s,setValue:void 0,enumValues:t}}return s}function e_(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eE(e){return e.replace(/^-+/,"")}function eO(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?e_(e):[e,void 0];return void 0!==eh.get(t)}function eU(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}function eP(e){process.stdout.write(`${JSON.stringify(e,null,2)}
367
+ `)}function eT(e,t={}){let s=e instanceof N?L(e):e;process.stderr.write(`Error (${s.code}): ${s.message}
360
368
  `),s.hint&&process.stderr.write(`Hint: ${s.hint}
361
369
  `),s.diagnosticId&&process.stderr.write(`Diagnostic ID: ${s.diagnosticId}
362
370
  `),s.logPath&&process.stderr.write(`Diagnostics Log: ${s.logPath}
363
371
  `),t.showDetails&&s.details&&process.stderr.write(`${JSON.stringify(s.details,null,2)}
364
372
  `)}function eM(e){return e&&e.summaryLines.length>0?`
365
- ${e.summaryLines.join("\n")}`:""}function eF(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function eB(e){return e>0?`+${e}`:String(e)}function ej(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",s=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${s}`}function eV(e){return e.min===e.max?eB(e.min):`${eB(e.min)}..${eB(e.max)}`}function eG(e){let t=process.cwd(),s=l.relative(t,e);return""!==s&&(s.startsWith("..")||l.isAbsolute(s))?e:""===s?".":`.${l.sep}${s}`}function eq(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function eK(){let e=process.env.FORCE_COLOR;return"string"==typeof e?"0"!==e:"string"!=typeof process.env.NO_COLOR&&!!process.stdout.isTTY}function eH(e,t){return t?c("dim",e):e}function eJ(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function ez(e,t){var s;let o="scroll-area"===(s=e.type)||"list"===s||"collection"===s||"table"===s?s:null;if(!o)return[];let r=[];if(e.node.hiddenContentAbove&&"below"!==t&&r.push(`[content above ${o} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&r.push(`[content below ${o} hidden]`),0===r.length)return[];let n=" ".repeat(e.depth+1);return r.map(e=>`${n}${e}`)}let eW={slug:"react-devtools-companion",runArg:E,displayName:"React DevTools companion"};async function eY(e){return await R({...e,definition:eW,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 eZ(e){return await _({...e,definition:eW})}function eX(e){var t;let s,o=e3(e);if(!p.existsSync(o))return null;try{s=JSON.parse(p.readFileSync(o,"utf8"))}catch(t){return e7(e,t),null}return!(!(t=s)||"object"!=typeof t||Array.isArray(t))&&1===t.version&&"string"==typeof t.session&&"string"==typeof t.remoteConfigPath&&"string"==typeof t.remoteConfigHash&&(void 0===t.daemon||"object"==typeof t.daemon&&null!==t.daemon&&!Array.isArray(t.daemon))&&"string"==typeof t.tenant&&"string"==typeof t.runId&&(void 0===t.leaseId||"string"==typeof t.leaseId)&&(void 0===t.leaseBackend||"string"==typeof t.leaseBackend)&&"string"==typeof t.connectedAt&&"string"==typeof t.updatedAt?s:(e7(e),null)}function eQ(e){let t=e3({stateDir:e.stateDir,session:e.state.session});p.mkdirSync(l.dirname(t),{recursive:!0}),e6(t,e.state),e6(e5(e.stateDir),{session:e.state.session})}function e0(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 e1(e){p.rmSync(e3(e),{force:!0});let t=e5(e.stateDir);e4(e.stateDir)===e.session&&p.rmSync(t,{force:!0})}function e2(e){try{return u.createHash("sha256").update(p.readFileSync(e)).digest("hex")}catch(t){throw new C("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function e3(e){return l.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 s=u.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${s}`}(e.session)}.json`)}function e5(e){return l.join(e,"remote-connections",".active-session.json")}function e8(e){let t=e4(e.stateDir);return t?eX({stateDir:e.stateDir,session:t}):null}function e4(e){let t=e5(e);if(p.existsSync(t))try{let e=JSON.parse(p.readFileSync(t,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function e6(e,t){p.writeFileSync(e,`${JSON.stringify(t,null,2)}
366
- `,{encoding:"utf8",mode:384}),p.chmodSync(e,384)}function e7(e,t){M({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),e1(e)}let e9=S.map(e=>e.key);function te(e){let t={};for(let s of e9){let o=e[s];void 0!==o&&(t[s]=o)}return t}let tt=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]),ts=new Set(["open"]);async function to(e){let t,s,{command:o,flags:r,client:n}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=K(r.stateDir).baseDir,i=I({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),l={...te(i.profile),...r,remoteConfig:i.resolvedPath},c=eX({stateDir:a,session:l.session??"default"});if(c&&c.remoteConfigPath!==i.resolvedPath)throw new C("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:i.resolvedPath});let d=c??function(e,t){if(!e.tenant)throw new C("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new C("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new C("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let s=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:e2(t),daemon:e0(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??tl(e),platform:e.platform,target:e.target,connectedAt:s,updatedAt:s}}(l,i.resolvedPath),p={...l,session:d.session},u=function(e,t){if(e)return td(e,t)?e:void 0}(d.runtime,p.platform)??e.runtime,m=d,f=!c;if(g=o,!tt.has(g)){let e=d.leaseBackend??function(e,t){let s=tl(e);if(s)return s;throw new C("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(r,o);var g,h,v,y,w,b=d,k=r,A=e;if(b.leaseBackend&&b.leaseBackend!==A)throw new C("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:b.session,leaseBackend:b.leaseBackend});if(b.platform&&k.platform&&b.platform!==k.platform)throw new C("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:b.session,platform:b.platform});if(b.target&&k.target&&b.target!==k.target)throw new C("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:b.session,target:b.target});let t=await tp(n,m,e);p.leaseId=t.leaseId,p.leaseBackend=e,p.platform=m.platform??p.platform,p.target=m.target??p.target,(m.leaseId!==t.leaseId||m.leaseBackend!==e)&&(m={...m,leaseId:t.leaseId,leaseBackend:e,platform:m.platform??r.platform,target:m.target??r.target,updatedAt:new Date().toISOString()},f=!0)}if(h=o,v=e.batchSteps,(ts.has(h)||"batch"===h&&v&&v.some(e=>{let t=e.command.trim().toLowerCase();return ts.has(t)&&void 0===e.runtime}))&&tc(p)&&(!m.leaseId&&p.leaseId&&(m={...m,leaseId:p.leaseId,leaseBackend:p.leaseBackend}),e.forceRuntimePrepare||!u||!td(u,p.platform))){if(!m.leaseId)throw new C("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await tr(p,n,d.remoteConfigPath,d.session,{tenantId:d.tenant,runId:d.runId,leaseId:m.leaseId});u=e.runtime;let r=(y=m.metro,w=e.cleanup,y?.projectRoot!==w?.projectRoot||y?.profileKey!==w?.profileKey||y?.consumerKey!==w?.consumerKey);t=r?m.metro:void 0,s=r?e.cleanup:void 0,m={...m,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},f=!0}if(f)try{eQ({stateDir:a,state:m})}catch(e){throw await tn(s),e}return await tn(t),{flags:{...p,session:m.session,leaseId:m.leaseId,leaseBackend:m.leaseBackend,platform:m.platform??p.platform,target:m.target??p.target},runtime:u}}async function tr(e,t,s,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new C("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new C("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let n=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:e.metroKind,publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:s,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?n.iosRuntime:n.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:n.projectRoot,profileKey:s,consumerKey:o}:void 0}}async function tn(e){if(e)try{await Y(e)}catch{}}async function ta(e){try{await eZ({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function ti(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 tl(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function tc(e){return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||e.metroKind)}function td(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function tp(e,t,s){if(t.leaseId&&t.leaseBackend===s){let o=await tu(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:s});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:s})}async function tu(e,t,s){try{return await e.leases.heartbeat({tenant:s.tenant,runId:s.runId,leaseId:t,leaseBackend:s.leaseBackend})}catch(e){var o;if((o=e)instanceof C&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}function tm(e){return{platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,androidDeviceAllowlist:e.androidDeviceAllowlist}}function tf(e,t,s){var o;if(e.json)return void eP({success:!0,data:t});let r=s?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
367
- `))}function tg(e,t){tf(e,t,()=>G(t))}let th=async({positionals:e,flags:t,client:s})=>{if("list"!==(e[0]??"list"))throw new C("INVALID_ARGS","session only supports list");let o={sessions:(await s.sessions.list()).map(j)};return tf(t,o,()=>JSON.stringify(o,null,2)),!0},tv=async({flags:e,client:t})=>{let s=await t.devices.list(tm(e));return tf(e,{devices:s.map(z)},()=>s.map(ty).join("\n")),!0};function ty(e){let t=e.kind?` ${e.kind}`:"",s=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${s})${o}`}let tw=async({flags:e,client:t})=>{if(!e.device)throw new C("INVALID_ARGS","ensure-simulator requires --device <name>");let s=await t.simulators.ensure({device:e.device,runtime:e.runtime,boot:e.boot,reuseExisting:e.reuseExisting,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet});return tf(e,H(s),()=>{let e=s.created?"Created":"Reused",t=s.booted?" (booted)":"";return s.runtime?`${e}: ${s.device} ${s.udid}${t}
368
- Runtime: ${s.runtime}`:`${e}: ${s.device} ${s.udid}${t}`}),!0},tb=async({positionals:e,flags:t,client:s})=>{let o=(e[0]??"").toLowerCase();if("reload"===o){let e=await s.metro.reload({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs});return tf(t,e,()=>`Reloaded React Native apps via ${e.reloadUrl}`),!0}if("prepare"!==o)throw new C("INVALID_ARGS","metro requires a subcommand: prepare or reload");if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new C("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let r=await s.metro.prepare({projectRoot:t.metroProjectRoot,kind:t.metroKind,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:t.tenant&&t.runId&&t.leaseId?{tenantId:t.tenant,runId:t.runId,leaseId:t.leaseId}:void 0,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return tf(t,r,()=>JSON.stringify(r,null,2)),!0},tk=async({flags:e,client:t})=>{let s=await t.apps.list({...tm(e),appsFilter:e.appsFilter});return tf(e,{apps:s},()=>s.join("\n")),!0};function tA(e,t,s,o){var r;return"number"==typeof s||"string"==typeof(r=s)&&/^\d+$/.test(r.trim())?{kind:"github-actions-artifact",owner:e,repo:t,artifactId:function(e,t){let s="number"==typeof e?e:"string"==typeof e?Number(e):NaN;if(!Number.isInteger(s))throw new C("INVALID_ARGS",`${t} must be an integer.`);return s}(s,o)}:{kind:"github-actions-artifact",owner:e,repo:t,artifactName:tD(s,o)}}function tI(e,t){let s=e.indexOf("/");if(s<=0||s===e.length-1||-1!==e.indexOf("/",s+1))throw new C("INVALID_ARGS",`${t} must use owner/repo.`);let o={owner:e.slice(0,s).trim(),repo:e.slice(s+1).trim()};if(!o.owner||!o.repo)throw new C("INVALID_ARGS",`${t} must use owner/repo.`);return o}function tD(e,t){let s="string"==typeof e&&e.trim().length>0?e.trim():void 0;if(!s)throw new C("INVALID_ARGS",`${t} must be a non-empty string.`);return s}let tS=async({positionals:e,flags:t,client:s})=>{let o=V(await tL("install",e,t,s));return tg(t,o),!0},tx=async({positionals:e,flags:t,client:s})=>{let o=V(await tL("reinstall",e,t,s));return tg(t,o),!0},t$=async({positionals:e,flags:t,client:s})=>{let o=J(await tN(e,t,s));return tg(t,o),!0};async function tL(e,t,s,o){let r=t[0],n=t[1];if(!r||!n)throw new C("INVALID_ARGS",`${e} requires: ${e} <app> <path-to-app-binary>`);let a={app:r,appPath:n,...tm(s)};return"install"===e?await o.apps.install(a):await o.apps.reinstall(a)}async function tN(e,t,s){let o=function(e,t){let s=e[0]?.trim();if(e.length>1)throw new C("INVALID_ARGS","install-from-source accepts either one <url> positional or --github-actions-artifact");let o=t.githubActionsArtifact?function(e,t="--github-actions-artifact"){let s=e.indexOf(":");if(s<=0||s===e.length-1)throw new C("INVALID_ARGS",`${t} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:o,repo:r}=tI(e.slice(0,s),t);return tA(o,r,e.slice(s+1),`${t} artifact`)}(t.githubActionsArtifact):void 0,r=t.installSource;if(1!=+!!s+ +!!o+ +!!r)throw new C("INVALID_ARGS","install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource");return o||r||{kind:"url",url:s,headers:function(e){if(!e||0===e.length)return;let t={};for(let s of e){let e=s.indexOf(":");if(e<=0)throw new C("INVALID_ARGS",`Invalid --header value "${s}". Expected "name:value".`);let o=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!o)throw new C("INVALID_ARGS",`Invalid --header value "${s}". Header name cannot be empty.`);t[o]=r}return t}(t.header)}}(e,t);if("url"!==o.kind&&t.header&&t.header.length>0)throw new C("INVALID_ARGS","install-from-source --header is only supported for URL sources");return await s.apps.installFromSource({...tm(t),retainPaths:t.retainPaths,retentionMs:t.retentionMs,source:o})}let tC=async({positionals:e,flags:t,client:s})=>{let o=F(await s.apps.open({app:e[0],url:e[1],surface:t.surface,activity:t.activity,relaunch:t.relaunch,saveScript:t.saveScript,noRecord:t.noRecord,...tm(t)}));return tg(t,o),!0},tR=async({positionals:e,flags:t,client:s})=>{let o=q(e[0]?await s.apps.close({app:e[0],shutdown:t.shutdown}):await s.sessions.close({shutdown:t.shutdown}));return tg(t,o),!0};async function t_(e){return await tE({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function tE(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tH(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tH(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||tH(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 s=tP({stateDir:e.stateDir});if(s&&!tK(s.expiresAt,e.io?.now)){let o=await tM({session:s,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"cli-session"}}if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new C("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw tj(e.command,t)}let o=await tU({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function tO(e){let t=e.env??e.io?.env??process.env;if(tH(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:tV(t),source:"flag"};if(tH(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:tV(t),source:"env"};let s=tP({stateDir:e.stateDir});if(s&&!tK(s.expiresAt,e.io?.now))return{accessToken:(await tM({session:s,flags:e.flags,env:t,io:e.io})).accessToken,cloudBaseUrl:tV(t,s.cloudBaseUrl),source:"cli-session"};let o=await tU({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:o.accessToken,cloudBaseUrl:o.session.cloudBaseUrl,source:"login"}}async function tU(e){let t,s,o,r=e.env??e.io?.env??process.env,n=(c=r,d=e.io,t=d?.stdinIsTTY??process.stdin.isTTY,s=d?.stdoutIsTTY??process.stdout.isTTY,"true"!==(u=c).CI&&"true"!==u.GITHUB_ACTIONS&&"true"!==u.BUILDKITE&&t&&s?(m=c).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"===n)throw tj(e.commandLabel??"agent-device connect",r);let a=tV(r),i=await tB({baseUrl:a,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 c,d,u,m,f,g,h=i;if(!tH(h.deviceCode)||!tH(h.userCode)||!tH(h.verificationUri))throw new C("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=i.verificationUriComplete??i.verificationUri,y="local-browser"===n?i.verificationUri:(f=i.verificationUri,g=i.userCode,(o=new URL(f)).searchParams.set("user_code",g),o.toString());"local-browser"===n?(tq(e.io,`Opening ${i.verificationUri}...
369
- `),await tG(v,e.io)):tq(e.io,`Open this URL on your machine:
373
+ ${e.summaryLines.join("\n")}`:""}function eF(e){return`x=${e.x},y=${e.y},w=${e.width},h=${e.height}`}function eB(e){return e>0?`+${e}`:String(e)}function ej(e){let t=e.nearestText?` near ${JSON.stringify(e.nearestText)}`:"",s=e.regionIndex?` r${e.regionIndex}`:"";return`${e.likelyKind}${t}${s}`}function eV(e){return e.min===e.max?eB(e.min):`${eB(e.min)}..${eB(e.max)}`}function eG(e){let t=process.cwd(),s=l.relative(t,e);return""!==s&&(s.startsWith("..")||l.isAbsolute(s))?e:""===s?".":`.${l.sep}${s}`}function eq(e){return"number"==typeof e&&Number.isFinite(e)?e:0}function eH(){let e=process.env.FORCE_COLOR;return"string"==typeof e?"0"!==e:"string"!=typeof process.env.NO_COLOR&&!!process.stdout.isTTY}function eK(e,t){return t?c("dim",e):e}function eJ(e){let t=e.warnings;return Array.isArray(t)?t.filter(e=>"string"==typeof e&&e.length>0):[]}function ez(e,t){var s;let o="scroll-area"===(s=e.type)||"list"===s||"collection"===s||"table"===s?s:null;if(!o)return[];let r=[];if(e.node.hiddenContentAbove&&"below"!==t&&r.push(`[content above ${o} hidden]`),e.node.hiddenContentBelow&&"above"!==t&&r.push(`[content below ${o} hidden]`),0===r.length)return[];let n=" ".repeat(e.depth+1);return r.map(e=>`${n}${e}`)}let eW={slug:"react-devtools-companion",runArg:E,displayName:"React DevTools companion"};async function eY(e){return await R({...e,definition:eW,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 eZ(e){return await _({...e,definition:eW})}function eX(e){var t;let s,o=e3(e);if(!p.existsSync(o))return null;try{s=JSON.parse(p.readFileSync(o,"utf8"))}catch(t){return e7(e,t),null}return!(!(t=s)||"object"!=typeof t||Array.isArray(t))&&1===t.version&&"string"==typeof t.session&&"string"==typeof t.remoteConfigPath&&"string"==typeof t.remoteConfigHash&&(void 0===t.daemon||"object"==typeof t.daemon&&null!==t.daemon&&!Array.isArray(t.daemon))&&"string"==typeof t.tenant&&"string"==typeof t.runId&&(void 0===t.leaseId||"string"==typeof t.leaseId)&&(void 0===t.leaseBackend||"string"==typeof t.leaseBackend)&&"string"==typeof t.connectedAt&&"string"==typeof t.updatedAt?s:(e7(e),null)}function eQ(e){let t=e3({stateDir:e.stateDir,session:e.state.session});p.mkdirSync(l.dirname(t),{recursive:!0}),e6(t,e.state),e6(e5(e.stateDir),{session:e.state.session})}function e0(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 e1(e){p.rmSync(e3(e),{force:!0});let t=e5(e.stateDir);e4(e.stateDir)===e.session&&p.rmSync(t,{force:!0})}function e2(e){try{return u.createHash("sha256").update(p.readFileSync(e)).digest("hex")}catch(t){throw new N("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function e3(e){return l.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 s=u.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${s}`}(e.session)}.json`)}function e5(e){return l.join(e,"remote-connections",".active-session.json")}function e8(e){let t=e4(e.stateDir);return t?eX({stateDir:e.stateDir,session:t}):null}function e4(e){let t=e5(e);if(p.existsSync(t))try{let e=JSON.parse(p.readFileSync(t,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function e6(e,t){p.writeFileSync(e,`${JSON.stringify(t,null,2)}
374
+ `,{encoding:"utf8",mode:384}),p.chmodSync(e,384)}function e7(e,t){M({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),e1(e)}let e9=S.map(e=>e.key);function te(e){let t={};for(let s of e9){let o=e[s];void 0!==o&&(t[s]=o)}return t}let tt=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]),ts=new Set(["open"]);async function to(e){let t,s,{command:o,flags:r,client:n}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=H(r.stateDir).baseDir,i=I({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),l={...te(i.profile),...r,remoteConfig:i.resolvedPath},c=eX({stateDir:a,session:l.session??"default"});if(c&&c.remoteConfigPath!==i.resolvedPath)throw new N("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:i.resolvedPath});let d=c??function(e,t){if(!e.tenant)throw new N("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new N("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new N("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let s=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:e2(t),daemon:e0(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??tl(e),platform:e.platform,target:e.target,connectedAt:s,updatedAt:s}}(l,i.resolvedPath),p={...l,session:d.session},u=function(e,t){if(e)return td(e,t)?e:void 0}(d.runtime,p.platform)??e.runtime,m=d,f=!c;if(g=o,!tt.has(g)){let e=d.leaseBackend??function(e,t){let s=tl(e);if(s)return s;throw new N("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(r,o);var g,h,v,y,w,b=d,k=r,A=e;if(b.leaseBackend&&b.leaseBackend!==A)throw new N("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:b.session,leaseBackend:b.leaseBackend});if(b.platform&&k.platform&&b.platform!==k.platform)throw new N("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:b.session,platform:b.platform});if(b.target&&k.target&&b.target!==k.target)throw new N("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:b.session,target:b.target});let t=await tp(n,m,e);p.leaseId=t.leaseId,p.leaseBackend=e,p.platform=m.platform??p.platform,p.target=m.target??p.target,(m.leaseId!==t.leaseId||m.leaseBackend!==e)&&(m={...m,leaseId:t.leaseId,leaseBackend:e,platform:m.platform??r.platform,target:m.target??r.target,updatedAt:new Date().toISOString()},f=!0)}if(h=o,v=e.batchSteps,(ts.has(h)||"batch"===h&&v&&v.some(e=>{let t=e.command.trim().toLowerCase();return ts.has(t)&&void 0===e.runtime}))&&tc(p)&&(!m.leaseId&&p.leaseId&&(m={...m,leaseId:p.leaseId,leaseBackend:p.leaseBackend}),e.forceRuntimePrepare||!u||!td(u,p.platform))){if(!m.leaseId)throw new N("INVALID_ARGS",`${o} requires a resolved remote lease before Metro runtime can be prepared.`);let e=await tr(p,n,d.remoteConfigPath,d.session,{tenantId:d.tenant,runId:d.runId,leaseId:m.leaseId});u=e.runtime;let r=(y=m.metro,w=e.cleanup,y?.projectRoot!==w?.projectRoot||y?.profileKey!==w?.profileKey||y?.consumerKey!==w?.consumerKey);t=r?m.metro:void 0,s=r?e.cleanup:void 0,m={...m,runtime:e.runtime,metro:e.cleanup,updatedAt:new Date().toISOString()},f=!0}if(f)try{eQ({stateDir:a,state:m})}catch(e){throw await tn(s),e}return await tn(t),{flags:{...p,session:m.session,leaseId:m.leaseId,leaseBackend:m.leaseBackend,platform:m.platform??p.platform,target:m.target??p.target},runtime:u}}async function tr(e,t,s,o,r){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new N("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new N("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let n=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:e.metroKind,publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:r,launchUrl:e.launchUrl,companionProfileKey:s,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?n.iosRuntime:n.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:n.projectRoot,profileKey:s,consumerKey:o}:void 0}}async function tn(e){if(e)try{await Y(e)}catch{}}async function ta(e){try{await eZ({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function ti(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 tl(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function tc(e){return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||e.metroKind)}function td(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function tp(e,t,s){if(t.leaseId&&t.leaseBackend===s){let o=await tu(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:s});if(o)return o}return await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:s})}async function tu(e,t,s){try{return await e.leases.heartbeat({tenant:s.tenant,runId:s.runId,leaseId:t,leaseBackend:s.leaseBackend})}catch(e){var o;if((o=e)instanceof N&&"UNAUTHORIZED"===o.code&&(o.details?.reason==="LEASE_NOT_FOUND"||o.details?.reason==="LEASE_EXPIRED"||o.details?.reason==="LEASE_REVOKED"))return;throw e}}function tm(e){return{platform:e.platform,target:e.target,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,androidDeviceAllowlist:e.androidDeviceAllowlist}}function tf(e,t,s){var o;if(e.json)return void eP({success:!0,data:t});let r=s?.();r&&(o=r,process.stdout.write(o.endsWith("\n")?o:`${o}
375
+ `))}function tg(e,t){tf(e,t,()=>G(t))}let th=async({positionals:e,flags:t,client:s})=>{if("list"!==(e[0]??"list"))throw new N("INVALID_ARGS","session only supports list");let o={sessions:(await s.sessions.list()).map(j)};return tf(t,o,()=>JSON.stringify(o,null,2)),!0},tv=async({flags:e,client:t})=>{let s=await t.devices.list(tm(e));return tf(e,{devices:s.map(z)},()=>s.map(ty).join("\n")),!0};function ty(e){let t=e.kind?` ${e.kind}`:"",s=e.target?` target=${e.target}`:"",o="boolean"==typeof e.booted?` booted=${e.booted}`:"";return`${e.name} (${e.platform}${t}${s})${o}`}let tw=async({flags:e,client:t})=>{if(!e.device)throw new N("INVALID_ARGS","ensure-simulator requires --device <name>");let s=await t.simulators.ensure({device:e.device,runtime:e.runtime,boot:e.boot,reuseExisting:e.reuseExisting,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet});return tf(e,K(s),()=>{let e=s.created?"Created":"Reused",t=s.booted?" (booted)":"";return s.runtime?`${e}: ${s.device} ${s.udid}${t}
376
+ Runtime: ${s.runtime}`:`${e}: ${s.device} ${s.udid}${t}`}),!0},tb=async({positionals:e,flags:t,client:s})=>{let o=(e[0]??"").toLowerCase();if("reload"===o){let e=await s.metro.reload({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,timeoutMs:t.metroProbeTimeoutMs});return tf(t,e,()=>`Reloaded React Native apps via ${e.reloadUrl}`),!0}if("prepare"!==o)throw new N("INVALID_ARGS","metro requires a subcommand: prepare or reload");if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new N("INVALID_ARGS","metro prepare requires --public-base-url <url> or --proxy-base-url <url>.");let r=await s.metro.prepare({projectRoot:t.metroProjectRoot,kind:t.metroKind,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:t.tenant&&t.runId&&t.leaseId?{tenantId:t.tenant,runId:t.runId,leaseId:t.leaseId}:void 0,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return tf(t,r,()=>JSON.stringify(r,null,2)),!0},tk=async({flags:e,client:t})=>{let s=await t.apps.list({...tm(e),appsFilter:e.appsFilter});return tf(e,{apps:s},()=>s.join("\n")),!0};function tA(e,t,s,o){var r;return"number"==typeof s||"string"==typeof(r=s)&&/^\d+$/.test(r.trim())?{kind:"github-actions-artifact",owner:e,repo:t,artifactId:function(e,t){let s="number"==typeof e?e:"string"==typeof e?Number(e):NaN;if(!Number.isInteger(s))throw new N("INVALID_ARGS",`${t} must be an integer.`);return s}(s,o)}:{kind:"github-actions-artifact",owner:e,repo:t,artifactName:tD(s,o)}}function tI(e,t){let s=e.indexOf("/");if(s<=0||s===e.length-1||-1!==e.indexOf("/",s+1))throw new N("INVALID_ARGS",`${t} must use owner/repo.`);let o={owner:e.slice(0,s).trim(),repo:e.slice(s+1).trim()};if(!o.owner||!o.repo)throw new N("INVALID_ARGS",`${t} must use owner/repo.`);return o}function tD(e,t){let s="string"==typeof e&&e.trim().length>0?e.trim():void 0;if(!s)throw new N("INVALID_ARGS",`${t} must be a non-empty string.`);return s}let tS=async({positionals:e,flags:t,client:s})=>{let o=V(await tC("install",e,t,s));return tg(t,o),!0},tx=async({positionals:e,flags:t,client:s})=>{let o=V(await tC("reinstall",e,t,s));return tg(t,o),!0},t$=async({positionals:e,flags:t,client:s})=>{let o=J(await tL(e,t,s));return tg(t,o),!0};async function tC(e,t,s,o){let r=t[0],n=t[1];if(!r||!n)throw new N("INVALID_ARGS",`${e} requires: ${e} <app> <path-to-app-binary>`);let a={app:r,appPath:n,...tm(s)};return"install"===e?await o.apps.install(a):await o.apps.reinstall(a)}async function tL(e,t,s){let o=function(e,t){let s=e[0]?.trim();if(e.length>1)throw new N("INVALID_ARGS","install-from-source accepts either one <url> positional or --github-actions-artifact");let o=t.githubActionsArtifact?function(e,t="--github-actions-artifact"){let s=e.indexOf(":");if(s<=0||s===e.length-1)throw new N("INVALID_ARGS",`${t} must use owner/repo:artifact, for example thymikee/RNCLI83:6635342232`);let{owner:o,repo:r}=tI(e.slice(0,s),t);return tA(o,r,e.slice(s+1),`${t} artifact`)}(t.githubActionsArtifact):void 0,r=t.installSource;if(1!=+!!s+ +!!o+ +!!r)throw new N("INVALID_ARGS","install-from-source requires exactly one source: <url>, --github-actions-artifact, or config installSource");return o||r||{kind:"url",url:s,headers:function(e){if(!e||0===e.length)return;let t={};for(let s of e){let e=s.indexOf(":");if(e<=0)throw new N("INVALID_ARGS",`Invalid --header value "${s}". Expected "name:value".`);let o=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!o)throw new N("INVALID_ARGS",`Invalid --header value "${s}". Header name cannot be empty.`);t[o]=r}return t}(t.header)}}(e,t);if("url"!==o.kind&&t.header&&t.header.length>0)throw new N("INVALID_ARGS","install-from-source --header is only supported for URL sources");return await s.apps.installFromSource({...tm(t),retainPaths:t.retainPaths,retentionMs:t.retentionMs,source:o})}let tN=async({positionals:e,flags:t,client:s})=>{let o=F(await s.apps.open({app:e[0],url:e[1],surface:t.surface,activity:t.activity,relaunch:t.relaunch,saveScript:t.saveScript,noRecord:t.noRecord,...tm(t)}));return tg(t,o),!0},tR=async({positionals:e,flags:t,client:s})=>{let o=q(e[0]?await s.apps.close({app:e[0],shutdown:t.shutdown}):await s.sessions.close({shutdown:t.shutdown}));return tg(t,o),!0};async function t_(e){return await tE({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function tE(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tJ(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tJ(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||tJ(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 s=await tM({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(s)return{flags:{...e.flags,daemonAuthToken:s.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new N("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw tV(e.command,t)}let o=await tU({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:o.accessToken},source:"login"}}async function tO(e){let t=e.env??e.io?.env??process.env;if(tJ(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:tG(t)};if(tJ(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:tG(t)};let s=await tM({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(s)return{accessToken:s.accessToken,cloudBaseUrl:s.cloudBaseUrl};if(e.flags.noLogin)throw new N("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let o=await tU({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 tU(e){let t,s,o,r=e.env??e.io?.env??process.env,n=(c=r,d=e.io,t=d?.stdinIsTTY??process.stdin.isTTY,s=d?.stdoutIsTTY??process.stdout.isTTY,"true"!==(u=c).CI&&"true"!==u.GITHUB_ACTIONS&&"true"!==u.BUILDKITE&&t&&s?(m=c).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"===n)throw tV(e.commandLabel??"agent-device connect",r);let a=tG(r),i=await tj({baseUrl:a,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 c,d,u,m,f,g,h=i;if(!tJ(h.deviceCode)||!tJ(h.userCode)||!tJ(h.verificationUri))throw new N("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=i.verificationUriComplete??i.verificationUri,y="local-browser"===n?i.verificationUri:(f=i.verificationUri,g=i.userCode,(o=new URL(f)).searchParams.set("user_code",g),o.toString());"local-browser"===n?(tH(e.io,`Opening ${i.verificationUri}...
377
+ `),await tq(v,e.io)):tH(e.io,`Open this URL on your machine:
370
378
  ${y}
371
379
 
372
380
  Waiting for approval for 10 minutes...
373
- `);let w=await tF({cloudBaseUrl:a,deviceCode:i.deviceCode,expiresIn:i.expiresIn,interval:i.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),b=w.cliSession?.refreshCredential??w.cliSession?.refreshToken;if(!tH(w.accessToken)||!tH(b))throw new C("UNAUTHORIZED","Device authorization did not return CLI credentials.");let k=new Date(e.io?.now?.()??Date.now()).toISOString(),A={version:1,id:w.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:a,workspaceId:w.cliSession?.workspaceId,accountId:w.cliSession?.accountId,name:w.cliSession?.name,refreshCredential:b,createdAt:k,expiresAt:w.cliSession?.expiresAt};return function(e){let t=tT(e.stateDir);p.mkdirSync(l.dirname(t),{recursive:!0,mode:448}),p.writeFileSync(t,`${JSON.stringify(e.session,null,2)}
374
- `,{mode:384});try{p.chmodSync(t,384)}catch{}}({stateDir:e.stateDir,session:A}),{accessToken:w.accessToken,expiresAt:w.expiresAt,session:A}}function tP(e){let t=tT(e.stateDir);if(!p.existsSync(t))return null;try{let e=JSON.parse(p.readFileSync(t,"utf8"));if(1!==e.version||!tH(e.id)||!tH(e.cloudBaseUrl)||!tH(e.refreshCredential)||!tH(e.createdAt))return null;return e}catch{return null}}function tT(e){return l.join(e,"auth","cli-session.json")}async function tM(e){let t=tV(e.env,e.session.cloudBaseUrl),s=await tB({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(tH(s.accessToken))return{accessToken:s.accessToken,expiresAt:s.expiresAt};if("revoked"===s.status||"revoked"===s.error)throw new C("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error});throw new C("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error})}async function tF(e){let t=e.now??Date.now,s=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+s,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tB({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tH(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 C("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tJ(r)}throw new C("TIMEOUT","Device authorization expired before approval.")}async function tB(e){let t=e.fetchImpl??fetch,s=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new C("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new C("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:s.status,response:r});return r}function tj(e,t){let s=tV(t);return new C("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",s).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tV(e,t){let s=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(s).toString().replace(/\/+$/,"")}catch(e){throw new C("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:s},e instanceof Error?e:void 0)}}async function tG(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let s=process.platform;try{"darwin"===s?await X("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===s?await X("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await X("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tq(t,`Open this URL on your machine:
381
+ `);let w=await tB({cloudBaseUrl:a,deviceCode:i.deviceCode,expiresIn:i.expiresIn,interval:i.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),b=w.cliSession?.refreshCredential??w.cliSession?.refreshToken;if(!tJ(w.accessToken)||!tJ(b))throw new N("UNAUTHORIZED","Device authorization did not return CLI credentials.");let k=new Date(e.io?.now?.()??Date.now()).toISOString(),A={version:1,id:w.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:a,workspaceId:w.cliSession?.workspaceId,accountId:w.cliSession?.accountId,name:w.cliSession?.name,refreshCredential:b,createdAt:k,expiresAt:w.cliSession?.expiresAt};return function(e){let t=tT(e.stateDir);p.mkdirSync(l.dirname(t),{recursive:!0,mode:448}),p.writeFileSync(t,`${JSON.stringify(e.session,null,2)}
382
+ `,{mode:384});try{p.chmodSync(t,384)}catch{}}({stateDir:e.stateDir,session:A}),{accessToken:w.accessToken,expiresAt:w.expiresAt,session:A}}function tP(e){let t=tT(e.stateDir);if(!p.existsSync(t))return null;try{let e=JSON.parse(p.readFileSync(t,"utf8"));if(1!==e.version||!tJ(e.id)||!tJ(e.cloudBaseUrl)||!tJ(e.refreshCredential)||!tJ(e.createdAt))return null;return e}catch{return null}}function tT(e){return l.join(e,"auth","cli-session.json")}async function tM(e){let t=tP({stateDir:e.stateDir});return!t||tK(t.expiresAt,e.io?.now)?null:{accessToken:(await tF({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:tG(e.env,t.cloudBaseUrl)}}async function tF(e){let t=tG(e.env,e.session.cloudBaseUrl),s=await tj({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(tJ(s.accessToken))return{accessToken:s.accessToken,expiresAt:s.expiresAt};if("revoked"===s.status||"revoked"===s.error)throw new N("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error});throw new N("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:s.status,error:s.error})}async function tB(e){let t=e.now??Date.now,s=Math.min((e.expiresIn??600)*1e3,6e5),o=t()+s,r=Math.max(1e3,(e.interval??5)*1e3);for(;t()<o;){let t=await tj({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tJ(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 N("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tz(r)}throw new N("TIMEOUT","Device authorization expired before approval.")}async function tj(e){let t=e.fetchImpl??fetch,s=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim().length>0)try{r=JSON.parse(o)}catch(e){throw new N("COMMAND_FAILED",`Cloud auth endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new N("UNAUTHORIZED","Cloud auth endpoint rejected the request.",{status:s.status,response:r});return r}function tV(e,t){let s=tG(t);return new N("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",s).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tG(e,t){let s=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(s).toString().replace(/\/+$/,"")}catch(e){throw new N("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:s},e instanceof Error?e:void 0)}}async function tq(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let s=process.platform;try{"darwin"===s?await X("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===s?await X("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await X("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tH(t,`Open this URL on your machine:
375
383
  ${e}
376
- `)}}function tq(e,t){(e?.stderr??process.stderr).write(t)}function tK(e,t){if(!e)return!1;let s=Date.parse(e);return!Number.isFinite(s)||s<=(t?.()??Date.now())}function tH(e){return"string"==typeof e&&e.trim().length>0}async function tJ(e){await new Promise(t=>setTimeout(t,e))}async function tz(e){if(e.flags.noLogin)throw new C("INVALID_ARGS","connect without --remote-config requires cloud auth.",{hint:"Remove --no-login, pass --remote-config <path>, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let t=await tO({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),s=await tW({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),o=I({configPath:function(e){var t;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,s])=>[t,e(s)])):t}(e.profile),o=l.join(e.stateDir,"remote-connections","generated");p.mkdirSync(o,{recursive:!0,mode:448});let r=l.join(o,`cloud-${(t=s,u.createHash("sha256").update(JSON.stringify(t)).digest("hex").slice(0,16))}.json`);p.writeFileSync(r,`${JSON.stringify(s,null,2)}
377
- `,{mode:384});try{p.chmodSync(r,384)}catch{}return r}({stateDir:e.stateDir,profile:s}),cwd:e.cwd,env:e.env});return{flags:{...te(o.profile),...e.flags,remoteConfig:o.resolvedPath,daemonAuthToken:t.accessToken},remoteConfigPath:o.resolvedPath}}async function tW(e){let t=e.fetchImpl??fetch,s=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim())try{r=JSON.parse(o)}catch(e){throw new C("COMMAND_FAILED",`Cloud connection profile endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new C("UNAUTHORIZED","Cloud connection profile endpoint rejected the request.",{status:s.status,response:r});var n=r;if(!n||"object"!=typeof n||Array.isArray(n))throw new C("COMMAND_FAILED","Cloud connection profile response is invalid.");let a=n.connection;if(!a||"object"!=typeof a)throw new C("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(a.remoteConfigProfile&&"object"==typeof a.remoteConfigProfile&&!Array.isArray(a.remoteConfigProfile))return a.remoteConfigProfile;if("string"==typeof a.remoteConfig)try{let e=JSON.parse(a.remoteConfig);if(e&&"object"==typeof e&&!Array.isArray(e))return e}catch(e){throw new C("COMMAND_FAILED","Cloud connection profile returned invalid remote config JSON.",{},e instanceof Error?e:void 0)}throw new C("COMMAND_FAILED","Cloud connection profile did not include remote config.")}let tY=async({flags:e,client:t})=>{var s,o,r,n;let a=K(e.stateDir).baseDir,i=e.remoteConfig?function(e){if(!e.remoteConfig)throw new C("INVALID_ARGS","connect requires --remote-config <path>.");let t=I({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tZ(e,a),l=i.flags,c=l.tenant,d=l.runId;if(!c)throw new C("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!d)throw new C("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!l.daemonBaseUrl)throw new C("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let p=l.session?null:e8({stateDir:a}),m=l.session??p?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${u.randomBytes(3).toString("hex")}`;if(!eX({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${u.randomBytes(2).toString("hex")}`}(a),f=e2(i.remoteConfigPath),g=e0(l),h=p?.session===m?p:eX({stateDir:a,session:m});if(h&&(s=h,o={flags:l,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,desiredLeaseBackend:tl(l),daemon:g},s.remoteConfigPath!==o.remoteConfigPath||s.remoteConfigHash!==o.remoteConfigHash||s.session!==o.session||s.tenant!==o.flags.tenant||s.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&s.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&s.platform!==o.flags.platform||void 0!==o.flags.target&&s.target!==o.flags.target||(r=s.daemon,n=o.daemon,(r?.baseUrl??void 0)!==(n?.baseUrl??void 0)||(r?.transport??void 0)!==(n?.transport??void 0)||(r?.serverMode??void 0)!==(n?.serverMode??void 0)))&&!l.force)throw new C("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:m,remoteConfig:h.remoteConfigPath});let v=new Date().toISOString(),y={version:1,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,daemon:g,tenant:c,runId:d,leaseId:h&&!l.force?h.leaseId:void 0,leaseBackend:h&&!l.force?h.leaseBackend:tl(l),platform:l.platform??(h&&!l.force?h.platform:void 0),target:l.target??(h&&!l.force?h.target:void 0),runtime:h&&!l.force?h.runtime:void 0,metro:h&&!l.force?h.metro:void 0,connectedAt:h&&!l.force?h.connectedAt:v,updatedAt:v};eQ({stateDir:a,state:y}),h&&l.force&&(await tn(h.metro),await ta({stateDir:a,state:h}),await ti(t,h));let w=t0(y),b=function(e,t){if(!t.runtime&&(tc(e)||t2(t.remoteConfigPath)))return t1(t.remoteConfigPath)}(l,y);return tf(l,t3(y,b),()=>[`Connected remote session "${m}" tenant "${c}" run "${d}" ${y.leaseId?`lease ${y.leaseId}`:"lease pending"}`,w?.message,b?.message].filter(e=>!!e).join("\n")),!0};async function tZ(e,t){if(e.noLogin)throw new C("INVALID_ARGS","connect without --remote-config requires cloud auth.",{hint:"Remove --no-login, pass --remote-config <path>, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});return tz({flags:e,stateDir:t,cwd:process.cwd(),env:process.env})}let tX=async({flags:e,client:t})=>{let s=e.session??"default",o=K(e.stateDir).baseDir,r=eX({stateDir:o,session:s})??(e.session?null:e8({stateDir:o}));if(!r)return tf(e,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tn(r.metro),await ta({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 e1({stateDir:o,session:n}),tf(e,{connected:!1,session:n,released:a},()=>`Disconnected remote session "${n}".`),!0},tQ=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new C("INVALID_ARGS","connection accepts only: status");let s=t.session??"default",o=K(t.stateDir).baseDir,r=eX({stateDir:o,session:s})??(t.session?null:e8({stateDir:o}));if(!r)return tf(t,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=t0(r),a=function(e){if(!e.runtime&&t2(e.remoteConfigPath))return t1(e.remoteConfigPath)}(r);return tf(t,t3(r,a),()=>[`Connected remote session "${r.session}".`,`tenant=${r.tenant} runId=${r.runId} leaseId=${r.leaseId??"pending"} backend=${r.leaseBackend??"pending"}`,`remoteConfig=${r.remoteConfigPath}`,r.runtime?"metro=prepared":"metro=not-prepared",n?.message,a?.message].filter(e=>!!e).join("\n")),!0};function t0(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 t1(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 t2(e){try{let t=I({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function t3(e,t){let s=t0(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 u.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...s?{leasePreparation:s}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t5=async({positionals:e,flags:t})=>{let s=e[0]??"status",o=K(t.stateDir).baseDir;if("status"===s){var r;let e,s=(e=tP({stateDir:(r={stateDir:o}).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:tK(e.expiresAt,r.now)}:{authenticated:!1,source:"none"};return tf(t,s,()=>{var e;return(e=s).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"===s){let e=await tU({stateDir:o,flags:t,commandLabel:"agent-device auth login"});return tf(t,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===s){let e,s=(e=tT({stateDir:o}.stateDir),!!p.existsSync(e)&&(p.rmSync(e,{force:!0}),!0));return tf(t,{authenticated:!1,removed:s},()=>s?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new C("INVALID_ARGS","auth accepts only: status, login, logout")},t8=async({flags:e,client:t})=>{let s=B(await t.capture.snapshot({...tm(e),interactiveOnly:e.snapshotInteractiveOnly,compact:e.snapshotCompact,depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}));return tf(e,s,()=>(function(e,t={}){var s,o,r,n,a,i;let l,c,d,p,u,f=e.nodes,h=Array.isArray(f)?f:[],v="string"==typeof e.backend?e.backend:void 0,w=t.raw||"macos-helper"===v?null:m(h),b=!!e.truncated,k=w?.nodes??h,I=t.raw||"macos-helper"===v?null:function(e,t,s,o){let r=e.visibility;if(r&&"object"==typeof r&&"boolean"==typeof r.partial&&"number"==typeof r.visibleNodeCount&&"number"==typeof r.totalNodeCount&&Array.isArray(r.reasons))return{partial:r.partial,visibleNodeCount:r.visibleNodeCount,totalNodeCount:r.totalNodeCount,reasons:r.reasons.filter(e=>"string"==typeof e)};let n=t?.hiddenCount??0,a=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return n>0?{partial:!0,visibleNodeCount:s,totalNodeCount:o,reasons:["offscreen-nodes"]}:a?{partial:!0,visibleNodeCount:s,totalNodeCount:s,reasons:[]}:null}(e,w,k.length,h.length),D=(s=h.length,o=I,l=b?" (truncated)":"",o?.partial?o.totalNodeCount>o.visibleNodeCount?`Snapshot: ${o.visibleNodeCount} visible nodes (${o.totalNodeCount} total)${l}`:`Snapshot: ${o.visibleNodeCount} visible nodes${l}`:`Snapshot: ${s} nodes${l}`),S=(c="string"==typeof(r=e).appName?r.appName:void 0,d="string"==typeof r.appBundleId?r.appBundleId:void 0,p=[],c&&p.push(`Page: ${c}`),d&&p.push(`App: ${d}`),p.length>0?`${p.join("\n")}
384
+ `)}}function tH(e,t){(e?.stderr??process.stderr).write(t)}function tK(e,t){if(!e)return!1;let s=Date.parse(e);return!Number.isFinite(s)||s<=(t?.()??Date.now())}function tJ(e){return"string"==typeof e&&e.trim().length>0}async function tz(e){await new Promise(t=>setTimeout(t,e))}async function tW(e){let t=await tO({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),s=await tY({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),o=function(e){try{return I(e)}catch(s){let t=C(s);throw new N("COMMAND_FAILED","Cloud connection profile returned invalid remote config.",{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(e){var t;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,s])=>[t,e(s)])):t}(e.profile),o=l.join(e.stateDir,"remote-connections","generated");p.mkdirSync(o,{recursive:!0,mode:448});let r=l.join(o,`cloud-${(t=s,u.createHash("sha256").update(JSON.stringify(t)).digest("hex").slice(0,16))}.json`);p.writeFileSync(r,`${JSON.stringify(s,null,2)}
385
+ `,{mode:384});try{p.chmodSync(r,384)}catch{}return r}({stateDir:e.stateDir,profile:s}),cwd:e.cwd,env:e.env});return{flags:{...te(o.profile),...e.flags,remoteConfig:o.resolvedPath,daemonAuthToken:t.accessToken},remoteConfigPath:o.resolvedPath}}async function tY(e){let t=e.fetchImpl??fetch,s=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)}),o=await s.text(),r={};if(o.trim())try{r=JSON.parse(o)}catch(e){throw new N("COMMAND_FAILED",`Cloud connection profile endpoint returned invalid JSON (${s.status}).`,{status:s.status},e instanceof Error?e:void 0)}if(!s.ok)throw new N("UNAUTHORIZED","Cloud connection profile endpoint rejected the request.",{status:s.status,response:r});var n=r;if(!n||"object"!=typeof n||Array.isArray(n))throw new N("COMMAND_FAILED","Cloud connection profile response is invalid.");let a=n.connection;if(!a||"object"!=typeof a)throw new N("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(void 0!==a.remoteConfigProfile){var i=a.remoteConfigProfile;if(!i||"object"!=typeof i||Array.isArray(i))throw new N("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(i).length)throw new N("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return i}throw new N("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}let tZ=async({flags:e,client:t})=>{var s,o,r,n;let a=H(e.stateDir).baseDir,i=e.remoteConfig?function(e){if(!e.remoteConfig)throw new N("INVALID_ARGS","connect requires --remote-config <path>.");let t=I({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(e):await tW({flags:e,stateDir:a,cwd:process.cwd(),env:process.env}),l=i.flags,c=l.tenant,d=l.runId;if(!c)throw new N("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!d)throw new N("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!l.daemonBaseUrl)throw new N("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let p=l.session?null:e8({stateDir:a}),m=l.session??p?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${u.randomBytes(3).toString("hex")}`;if(!eX({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${u.randomBytes(2).toString("hex")}`}(a),f=e2(i.remoteConfigPath),g=e0(l),h=p?.session===m?p:eX({stateDir:a,session:m});if(h&&(s=h,o={flags:l,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,desiredLeaseBackend:tl(l),daemon:g},s.remoteConfigPath!==o.remoteConfigPath||s.remoteConfigHash!==o.remoteConfigHash||s.session!==o.session||s.tenant!==o.flags.tenant||s.runId!==o.flags.runId||void 0!==o.desiredLeaseBackend&&s.leaseBackend!==o.desiredLeaseBackend||void 0!==o.flags.platform&&s.platform!==o.flags.platform||void 0!==o.flags.target&&s.target!==o.flags.target||(r=s.daemon,n=o.daemon,(r?.baseUrl??void 0)!==(n?.baseUrl??void 0)||(r?.transport??void 0)!==(n?.transport??void 0)||(r?.serverMode??void 0)!==(n?.serverMode??void 0)))&&!l.force)throw new N("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:m,remoteConfig:h.remoteConfigPath});let v=new Date().toISOString(),y={version:1,session:m,remoteConfigPath:i.remoteConfigPath,remoteConfigHash:f,daemon:g,tenant:c,runId:d,leaseId:h&&!l.force?h.leaseId:void 0,leaseBackend:h&&!l.force?h.leaseBackend:tl(l),platform:l.platform??(h&&!l.force?h.platform:void 0),target:l.target??(h&&!l.force?h.target:void 0),runtime:h&&!l.force?h.runtime:void 0,metro:h&&!l.force?h.metro:void 0,connectedAt:h&&!l.force?h.connectedAt:v,updatedAt:v};eQ({stateDir:a,state:y}),h&&l.force&&(await tn(h.metro),await ta({stateDir:a,state:h}),await ti(t,h));let w=t0(y),b=function(e,t){if(!t.runtime&&(tc(e)||t2(t.remoteConfigPath)))return t1(t.remoteConfigPath)}(l,y);return tf(l,t3(y,b),()=>[`Connected remote session "${m}" tenant "${c}" run "${d}" ${y.leaseId?`lease ${y.leaseId}`:"lease pending"}`,w?.message,b?.message].filter(e=>!!e).join("\n")),!0},tX=async({flags:e,client:t})=>{let s=e.session??"default",o=H(e.stateDir).baseDir,r=eX({stateDir:o,session:s})??(e.session?null:e8({stateDir:o}));if(!r)return tf(e,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=r.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tn(r.metro),await ta({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 e1({stateDir:o,session:n}),tf(e,{connected:!1,session:n,released:a},()=>`Disconnected remote session "${n}".`),!0},tQ=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new N("INVALID_ARGS","connection accepts only: status");let s=t.session??"default",o=H(t.stateDir).baseDir,r=eX({stateDir:o,session:s})??(t.session?null:e8({stateDir:o}));if(!r)return tf(t,{connected:!1,session:s},()=>`No remote connection for "${s}".`),!0;let n=t0(r),a=function(e){if(!e.runtime&&t2(e.remoteConfigPath))return t1(e.remoteConfigPath)}(r);return tf(t,t3(r,a),()=>[`Connected remote session "${r.session}".`,`tenant=${r.tenant} runId=${r.runId} leaseId=${r.leaseId??"pending"} backend=${r.leaseBackend??"pending"}`,`remoteConfig=${r.remoteConfigPath}`,r.runtime?"metro=prepared":"metro=not-prepared",n?.message,a?.message].filter(e=>!!e).join("\n")),!0};function t0(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 t1(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 t2(e){try{let t=I({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function t3(e,t){let s=t0(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 u.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...s?{leasePreparation:s}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let t5=async({positionals:e,flags:t})=>{let s=e[0]??"status",o=H(t.stateDir).baseDir;if("status"===s){var r;let e,s=(e=tP({stateDir:(r={stateDir:o}).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:tK(e.expiresAt,r.now)}:{authenticated:!1,source:"none"};return tf(t,s,()=>{var e;return(e=s).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"===s){let e=await tU({stateDir:o,flags:t,commandLabel:"agent-device auth login"});return tf(t,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===s){let e,s=(e=tT({stateDir:o}.stateDir),!!p.existsSync(e)&&(p.rmSync(e,{force:!0}),!0));return tf(t,{authenticated:!1,removed:s},()=>s?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new N("INVALID_ARGS","auth accepts only: status, login, logout")},t8=async({flags:e,client:t})=>{let s=B(await t.capture.snapshot({...tm(e),interactiveOnly:e.snapshotInteractiveOnly,compact:e.snapshotCompact,depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}));return tf(e,s,()=>(function(e,t={}){var s,o,r,n,a,i;let l,c,d,p,u,f=e.nodes,h=Array.isArray(f)?f:[],v="string"==typeof e.backend?e.backend:void 0,w=t.raw||"macos-helper"===v?null:m(h),b=!!e.truncated,k=w?.nodes??h,I=t.raw||"macos-helper"===v?null:function(e,t,s,o){let r=e.visibility;if(r&&"object"==typeof r&&"boolean"==typeof r.partial&&"number"==typeof r.visibleNodeCount&&"number"==typeof r.totalNodeCount&&Array.isArray(r.reasons))return{partial:r.partial,visibleNodeCount:r.visibleNodeCount,totalNodeCount:r.totalNodeCount,reasons:r.reasons.filter(e=>"string"==typeof e)};let n=t?.hiddenCount??0,a=!!t&&t.nodes.some(e=>e.hiddenContentAbove||e.hiddenContentBelow);return n>0?{partial:!0,visibleNodeCount:s,totalNodeCount:o,reasons:["offscreen-nodes"]}:a?{partial:!0,visibleNodeCount:s,totalNodeCount:s,reasons:[]}:null}(e,w,k.length,h.length),D=(s=h.length,o=I,l=b?" (truncated)":"",o?.partial?o.totalNodeCount>o.visibleNodeCount?`Snapshot: ${o.visibleNodeCount} visible nodes (${o.totalNodeCount} total)${l}`:`Snapshot: ${o.visibleNodeCount} visible nodes${l}`:`Snapshot: ${s} nodes${l}`),S=(c="string"==typeof(r=e).appName?r.appName:void 0,d="string"==typeof r.appBundleId?r.appBundleId:void 0,p=[],c&&p.push(`Page: ${c}`),d&&p.push(`App: ${d}`),p.length>0?`${p.join("\n")}
378
386
  `:""),x=(n=e,a=h,i=t,u=eJ(n),!i.raw&&function(e){if(e.length<20)return!1;let t=new Map;for(let s of e){let e=(s.type??"").toLowerCase(),o=y(s).trim().toLowerCase();if(!o)continue;let r=`${e}|${o}`;t.set(r,(t.get(r)??0)+1)}let s=0;for(let e of t.values())e>1&&(s+=e);return s>=8}(a)&&u.push("Warning: possible repeated nav subtree detected."),u),$=x.length>0?`${x.join("\n")}
379
387
  `:"";return 0===h.length?`${S}${D}
380
388
  ${$}`:t.raw?`${S}${D}
@@ -383,15 +391,15 @@ ${$}${h.map(e=>JSON.stringify(e)).join("\n")}
383
391
  ${$}${A(k,{summarizeTextSurfaces:!0}).flatMap(e=>[g(e.node,0,!1,e.type,{summarizeTextSurfaces:!0}),...ez({...e,depth:0})]).join("\n")}${eM(w)}
384
392
  `:`${S}${D}
385
393
  ${$}${(function(e){let t=[],s=[],o=e=>{for(;s.length>0&&e<=s[s.length-1].depth;)t.push(...ez(s.pop(),"below"))};for(let r of e)o(r.depth),t.push(r.text),t.push(...ez(r,"above")),r.node.hiddenContentBelow&&s.push(r);return o(0),t})(A(k,{summarizeTextSurfaces:!0})).join("\n")}${eM(w)}
386
- `})(s,{raw:e.snapshotRaw,flatten:e.snapshotInteractiveOnly})),!0},t4=async({positionals:e,flags:t,client:s})=>{let o=await s.capture.screenshot({path:e[0]??t.out,overlayRefs:t.overlayRefs,maxSize:t.screenshotMaxSize,...void 0!==t.screenshotFullscreen?{fullscreen:t.screenshotFullscreen}:{}});return tf(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},t6=async({positionals:e,flags:t,client:s})=>{var o;if("snapshot"===e[0]){let e=await s.capture.diff({...tm(t),kind:"snapshot",out:t.out,interactiveOnly:t.snapshotInteractiveOnly,compact:t.snapshotCompact,depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw});return tf(t,e,()=>(function(e){var t;let s=!0===e.baselineInitialized,o=e.summary??{},r=eq(o.additions),n=eq(o.removals),a=eq(o.unchanged),i=eK(),l=eJ(e),d=l.length>0?`${l.join("\n")}
394
+ `})(s,{raw:e.snapshotRaw,flatten:e.snapshotInteractiveOnly})),!0},t4=async({positionals:e,flags:t,client:s})=>{let o=await s.capture.screenshot({path:e[0]??t.out,overlayRefs:t.overlayRefs,maxSize:t.screenshotMaxSize,...void 0!==t.screenshotFullscreen?{fullscreen:t.screenshotFullscreen}:{}});return tf(t,{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}},()=>o.overlayRefs?`Annotated ${o.overlayRefs.length} refs onto ${o.path}`:o.path),!0},t6=async({positionals:e,flags:t,client:s})=>{var o;if("snapshot"===e[0]){let e=await s.capture.diff({...tm(t),kind:"snapshot",out:t.out,interactiveOnly:t.snapshotInteractiveOnly,compact:t.snapshotCompact,depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw});return tf(t,e,()=>(function(e){var t;let s=!0===e.baselineInitialized,o=e.summary??{},r=eq(o.additions),n=eq(o.removals),a=eq(o.unchanged),i=eH(),l=eJ(e),d=l.length>0?`${l.join("\n")}
387
395
  `:"";if(s)return`${d}Baseline initialized (${a} lines).
388
396
  `;let p=(function(e){if(0===e.length)return e;let t=e.map((e,t)=>({index:t,kind:e.kind})).filter(e=>"added"===e.kind||"removed"===e.kind).map(e=>e.index);if(0===t.length)return e;let s=Array(e.length).fill(!1);for(let o of t){let t=Math.max(0,o-1),r=Math.min(e.length-1,o+1);for(let e=t;e<=r;e+=1)s[e]=!0}return e.filter((e,t)=>s[t])})(Array.isArray(e.lines)?e.lines:[]).map(e=>{let t="string"==typeof e.text?e.text:"";if("added"===e.kind){let e=t.startsWith(" ")?`+${t}`:`+ ${t}`;return i?c("green",e):e}if("removed"===e.kind){let e=t.startsWith(" ")?`-${t}`:`- ${t}`;return i?c("red",e):e}return i?c("dim",t):t}),u=p.length>0?`${p.join("\n")}
389
397
  `:"";if(!i)return`${d}${u}${r} additions, ${n} removals, ${a} unchanged
390
398
  `;let m=`${(t=String(r),c("green",t))} additions, ${c("red",String(n))} removals, ${c("dim",String(a))} unchanged`;return`${d}${u}${m}
391
- `})(e)),!0}if("screenshot"!==e[0])return!1;let r=t.baseline;if(!r||"string"!=typeof r)throw new C("INVALID_ARGS","diff screenshot requires --baseline <path>");let n=Q(r),a="string"==typeof t.out?Q(t.out):void 0,i=e[1];if(e.length>2)throw new C("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=v({backend:(o=s,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,s)=>{let r=await o.capture.screenshot({path:t,session:e.session,overlayRefs:s?.overlayRefs,fullscreen:s?.fullscreen,surface:s?.surface});return{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}}}}),artifacts:et(),sessions:{get:e=>({name:e}),set:()=>{}},policy:w()}),d=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:n},current:i?{kind:"path",path:Q(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 tf(t,d,()=>{var e,t,s,o;let r,n,a,i,l,p,u,m;return r=eK(),n=!0===d.match,a=d.dimensionMismatch,(i=[]).push(...function(e,t){if(!0===e.match){let e=t?c("green","✓"):"✓";return[`${e} Screenshots match.`]}let s=e.dimensionMismatch,o=t?c("red","✗"):"✗";if(s){let e=s.expected,t=s.actual;return[`${o} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let r=eq(e.differentPixels),n=eq(e.mismatchPercentage),a=0===n&&r>0?"<0.01":String(n),i=`${a}% pixels differ`;return[`${o} ${t?c("red",i):i}`]}(d,r)),i.push(...function(e,t,s){if(t)return[];let o=[];if(e.diffPath){let t=eG(e.diffPath),r=s?c("dim","Diff image:"):"Diff image:",n=s?c("green",t):t;o.push(` ${r} ${n}`)}if(e.currentOverlayPath){let t=eG(e.currentOverlayPath),r=s?c("dim","Current overlay:"):"Current overlay:",n=s?c("green",t):t,a=eq(e.currentOverlayRefCount),i=a>0?` (${a} refs)`:"";o.push(` ${r} ${n}${i}`)}return o}(d,n,r)),n||a||(i.push(...(e=d,t=r,l=eq(e.differentPixels),p=eq(e.totalPixels),u=t?c("red",String(l)):String(l),[` ${u} different / ${p} total pixels`])),i.push(...(s=d,o=r,0===(m=function(e){let t=[];for(let s of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),s=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${s}`}(s.texts)} dx=${eV(s.xRange)}px dy=${eV(s.yRange)}px`);let s=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);s.length>0&&t.push(`non-text controls: ${s.map(ej).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(ej).join("; ")}`),t.slice(0,6)}(s)).length?[]:[` ${eH("Hints:",o)}`,...m.map(e=>` - ${e}`)])),i.push(...function(e,t){let s=Array.isArray(e.regions)?e.regions:[];if(0===s.length)return[];let o=[` ${eH("Changed regions:",t)}`];for(let e of s.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),s=e.rect,o=[` ${e.index}. ${e.location} x=${s.x} y=${s.y} ${s.width}x${s.height}, ${t}% of diff, change=${e.dominantChange}`],r=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);r&&o.push(` ${r}`);let n=e.currentOverlayMatches?.[0];if(n){let e=n.label?` "${n.label}"`:"";o.push(` overlaps @${n.ref}${e}, ${n.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,r)),i.push(...function(e,t){let s=e.ocr?.matches??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eH(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${s.length}; px):`,t)}`,` ${eH("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let s=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${eB(s.x)},${eB(s.y)} | ${eB(s.width)},${eB(s.height)} | ${eF(t.baselineRect)} | ${eF(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,r)),i.push(...function(e,t){let s=e.nonTextDeltas??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eH(`Non-text visual deltas (showing ${o.length}/${s.length}; px):`,t)}`,` ${eH("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of o)r.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${eF(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,r))),`${i.join("\n")}
392
- `}),!0},t7={[eo.wait]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.wait(function(e,t){let s=k(e);if(!s)throw new C("INVALID_ARGS","wait requires <ms>, text <text>, @ref, or <selector> [timeoutMs].");let o={...tm(t),depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw};if("sleep"===s.kind)return{...o,durationMs:s.durationMs};if("text"===s.kind){if(!s.text)throw new C("INVALID_ARGS","wait requires text.");return{...o,text:s.text,...t9(s.timeoutMs)}}return"ref"===s.kind?{...o,ref:s.rawRef,...t9(s.timeoutMs)}:{...o,selector:s.selectorExpression,...t9(s.timeoutMs)}}(e,t))),!0),[eo.alert]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.alert(function(e,t){if(e.length>2)throw new C("INVALID_ARGS","alert accepts at most action and timeout arguments.");let s=function(e){let t=e?.toLowerCase();if(void 0===t||"get"===t||"accept"===t||"dismiss"===t||"wait"===t)return t;throw new C("INVALID_ARGS","alert action must be get, accept, dismiss, or wait.")}(e[0]),o=function(e,t){if(void 0===e)return;let s=Number(e);if(Number.isFinite(s))return s;throw new C("INVALID_ARGS",`${t} must be a finite number.`)}(e[1],"alert timeout");return{...tm(t),...s?{action:s}:{},...void 0!==o?{timeoutMs:o}:{}}}(e,t))),!0),[eo.appState]:async({flags:e,client:t})=>{let s=await t.command.appState(tm(e));return tf(e,s,()=>(function(e){if("ios"===e.platform){let t=[`Foreground app: ${e.appName??e.appBundleId??"unknown"}`];return e.appBundleId&&t.push(`Bundle: ${e.appBundleId}`),e.source&&t.push(`Source: ${e.source}`),t.join("\n")}if("android"===e.platform){let t=[`Foreground app: ${e.package??"unknown"}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join("\n")}return null})(s)),!0},[eo.back]:async({flags:e,client:t})=>(tg(e,await t.command.back({...tm(e),mode:e.backMode})),!0),[eo.home]:async({flags:e,client:t})=>(tg(e,await t.command.home(tm(e))),!0),[eo.rotate]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.rotate(function(e,t){if(e.length>1)throw new C("INVALID_ARGS","rotate accepts exactly one orientation argument.");return{...tm(t),orientation:b(e[0])}}(e,t))),!0),[eo.appSwitcher]:async({flags:e,client:t})=>(tg(e,await t.command.appSwitcher(tm(e))),!0),[eo.keyboard]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.keyboard(function(e,t){if(e.length>1)throw new C("INVALID_ARGS","keyboard accepts at most one action argument.");let s=function(e){let t=e?.toLowerCase();if("get"===t)return"status";if(void 0===t||"status"===t||"dismiss"===t)return t;throw new C("INVALID_ARGS","keyboard action must be status, get, or dismiss.")}(e[0]);return{...tm(t),...s?{action:s}:{}}}(e,t))),!0),[eo.clipboard]:async({positionals:e,flags:t,client:s})=>{var o,r;return o=t,r=await s.command.clipboard(function(e,t){let s=e[0]?.toLowerCase();if("read"!==s&&"write"!==s)throw new C("INVALID_ARGS","clipboard requires a subcommand: read or write.");let o=tm(t);if("read"===s){if(1!==e.length)throw new C("INVALID_ARGS","clipboard read does not accept additional arguments.");return{...o,action:s}}if(e.length<2)throw new C("INVALID_ARGS","clipboard write requires text.");return{...o,action:s,text:e.slice(1).join(" ")}}(e,t)),o.json?tf(o,r):"read"===r.action?process.stdout.write(`${r.text}
399
+ `})(e)),!0}if("screenshot"!==e[0])return!1;let r=t.baseline;if(!r||"string"!=typeof r)throw new N("INVALID_ARGS","diff screenshot requires --baseline <path>");let n=Q(r),a="string"==typeof t.out?Q(t.out):void 0,i=e[1];if(e.length>2)throw new N("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=v({backend:(o=s,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,s)=>{let r=await o.capture.screenshot({path:t,session:e.session,overlayRefs:s?.overlayRefs,fullscreen:s?.fullscreen,surface:s?.surface});return{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}}}}),artifacts:et(),sessions:{get:e=>({name:e}),set:()=>{}},policy:w()}),d=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:n},current:i?{kind:"path",path:Q(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 tf(t,d,()=>{var e,t,s,o;let r,n,a,i,l,p,u,m;return r=eH(),n=!0===d.match,a=d.dimensionMismatch,(i=[]).push(...function(e,t){if(!0===e.match){let e=t?c("green","✓"):"✓";return[`${e} Screenshots match.`]}let s=e.dimensionMismatch,o=t?c("red","✗"):"✗";if(s){let e=s.expected,t=s.actual;return[`${o} Screenshots have different dimensions: expected ${e?.width}x${e?.height}, got ${t?.width}x${t?.height}`]}let r=eq(e.differentPixels),n=eq(e.mismatchPercentage),a=0===n&&r>0?"<0.01":String(n),i=`${a}% pixels differ`;return[`${o} ${t?c("red",i):i}`]}(d,r)),i.push(...function(e,t,s){if(t)return[];let o=[];if(e.diffPath){let t=eG(e.diffPath),r=s?c("dim","Diff image:"):"Diff image:",n=s?c("green",t):t;o.push(` ${r} ${n}`)}if(e.currentOverlayPath){let t=eG(e.currentOverlayPath),r=s?c("dim","Current overlay:"):"Current overlay:",n=s?c("green",t):t,a=eq(e.currentOverlayRefCount),i=a>0?` (${a} refs)`:"";o.push(` ${r} ${n}${i}`)}return o}(d,n,r)),n||a||(i.push(...(e=d,t=r,l=eq(e.differentPixels),p=eq(e.totalPixels),u=t?c("red",String(l)):String(l),[` ${u} different / ${p} total pixels`])),i.push(...(s=d,o=r,0===(m=function(e){let t=[];for(let s of(e.ocr?.movementClusters??[]).slice(0,2))t.push(`text movement cluster: ${function(e){let t=e.slice(0,4).map(e=>JSON.stringify(e)),s=e.length>t.length?` +${e.length-t.length} more`:"";return`${t.join(", ")}${s}`}(s.texts)} dx=${eV(s.xRange)}px dy=${eV(s.yRange)}px`);let s=(e.nonTextDeltas??[]).filter(e=>["icon","toggle","chevron"].includes(e.likelyKind)).slice(0,3);s.length>0&&t.push(`non-text controls: ${s.map(ej).join("; ")}`);let o=(e.nonTextDeltas??[]).filter(e=>"separator"===e.likelyKind).slice(0,2);return o.length>0&&t.push(`non-text boundaries: ${o.map(ej).join("; ")}`),t.slice(0,6)}(s)).length?[]:[` ${eK("Hints:",o)}`,...m.map(e=>` - ${e}`)])),i.push(...function(e,t){let s=Array.isArray(e.regions)?e.regions:[];if(0===s.length)return[];let o=[` ${eK("Changed regions:",t)}`];for(let e of s.slice(0,5))o.push(...function(e){let t=0===e.shareOfDiffPercentage&&e.differentPixels>0?"<0.01":String(e.shareOfDiffPercentage),s=e.rect,o=[` ${e.index}. ${e.location} x=${s.x} y=${s.y} ${s.width}x${s.height}, ${t}% of diff, change=${e.dominantChange}`],r=function(e){let t=[e.size?`size=${e.size}`:null,e.shape?`shape=${e.shape}`:null,"number"==typeof e.densityPercentage?`density=${e.densityPercentage}%`:null,e.averageBaselineColorHex&&e.averageCurrentColorHex?`avgColor=${e.averageBaselineColorHex}->${e.averageCurrentColorHex}`:null,"number"==typeof e.baselineLuminance&&"number"==typeof e.currentLuminance?`luminance=${e.baselineLuminance}->${e.currentLuminance}`:null].filter(e=>null!==e);return t.length>0?t.join(" "):null}(e);r&&o.push(` ${r}`);let n=e.currentOverlayMatches?.[0];if(n){let e=n.label?` "${n.label}"`:"";o.push(` overlaps @${n.ref}${e}, ${n.regionCoveragePercentage}% of region`)}return o}(e));return o}(d,r)),i.push(...function(e,t){let s=e.ocr?.matches??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eK(`OCR text deltas (${e.ocr?.provider}; baselineBlocks=${e.ocr?.baselineBlocks} currentBlocks=${e.ocr?.currentBlocks}; showing ${o.length}/${s.length}; px):`,t)}`,` ${eK("item | text | movePx | sizeDeltaPx | bboxBaseline | bboxCurrent | confidence | issueHint",t)}`];for(let[e,t]of o.entries()){let s=t.delta;r.push(` ${e+1} | ${JSON.stringify(t.text)} | ${eB(s.x)},${eB(s.y)} | ${eB(s.width)},${eB(s.height)} | ${eF(t.baselineRect)} | ${eF(t.currentRect)} | ${t.confidence} | ${t.possibleTextMetricMismatch?"ocr-bbox-size-change":"-"}`)}return r}(d,r)),i.push(...function(e,t){let s=e.nonTextDeltas??[];if(0===s.length)return[];let o=s.slice(0,8),r=[` ${eK(`Non-text visual deltas (showing ${o.length}/${s.length}; px):`,t)}`,` ${eK("item | region | slot | kind | bboxCurrent | nearestText",t)}`];for(let e of o)r.push(` ${e.index} | ${e.regionIndex?`r${e.regionIndex}`:"-"} | ${e.slot} | ${e.likelyKind} | ${eF(e.rect)} | ${e.nearestText?JSON.stringify(e.nearestText):"-"}`);return r}(d,r))),`${i.join("\n")}
400
+ `}),!0},t7={[eo.wait]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.wait(function(e,t){let s=k(e);if(!s)throw new N("INVALID_ARGS","wait requires <ms>, text <text>, @ref, or <selector> [timeoutMs].");let o={...tm(t),depth:t.snapshotDepth,scope:t.snapshotScope,raw:t.snapshotRaw};if("sleep"===s.kind)return{...o,durationMs:s.durationMs};if("text"===s.kind){if(!s.text)throw new N("INVALID_ARGS","wait requires text.");return{...o,text:s.text,...t9(s.timeoutMs)}}return"ref"===s.kind?{...o,ref:s.rawRef,...t9(s.timeoutMs)}:{...o,selector:s.selectorExpression,...t9(s.timeoutMs)}}(e,t))),!0),[eo.alert]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.alert(function(e,t){if(e.length>2)throw new N("INVALID_ARGS","alert accepts at most action and timeout arguments.");let s=function(e){let t=e?.toLowerCase();if(void 0===t||"get"===t||"accept"===t||"dismiss"===t||"wait"===t)return t;throw new N("INVALID_ARGS","alert action must be get, accept, dismiss, or wait.")}(e[0]),o=function(e,t){if(void 0===e)return;let s=Number(e);if(Number.isFinite(s))return s;throw new N("INVALID_ARGS",`${t} must be a finite number.`)}(e[1],"alert timeout");return{...tm(t),...s?{action:s}:{},...void 0!==o?{timeoutMs:o}:{}}}(e,t))),!0),[eo.appState]:async({flags:e,client:t})=>{let s=await t.command.appState(tm(e));return tf(e,s,()=>(function(e){if("ios"===e.platform){let t=[`Foreground app: ${e.appName??e.appBundleId??"unknown"}`];return e.appBundleId&&t.push(`Bundle: ${e.appBundleId}`),e.source&&t.push(`Source: ${e.source}`),t.join("\n")}if("android"===e.platform){let t=[`Foreground app: ${e.package??"unknown"}`];return e.activity&&t.push(`Activity: ${e.activity}`),t.join("\n")}return null})(s)),!0},[eo.back]:async({flags:e,client:t})=>(tg(e,await t.command.back({...tm(e),mode:e.backMode})),!0),[eo.home]:async({flags:e,client:t})=>(tg(e,await t.command.home(tm(e))),!0),[eo.rotate]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.rotate(function(e,t){if(e.length>1)throw new N("INVALID_ARGS","rotate accepts exactly one orientation argument.");return{...tm(t),orientation:b(e[0])}}(e,t))),!0),[eo.appSwitcher]:async({flags:e,client:t})=>(tg(e,await t.command.appSwitcher(tm(e))),!0),[eo.keyboard]:async({positionals:e,flags:t,client:s})=>(tg(t,await s.command.keyboard(function(e,t){if(e.length>1)throw new N("INVALID_ARGS","keyboard accepts at most one action argument.");let s=function(e){let t=e?.toLowerCase();if("get"===t)return"status";if(void 0===t||"status"===t||"dismiss"===t)return t;throw new N("INVALID_ARGS","keyboard action must be status, get, or dismiss.")}(e[0]);return{...tm(t),...s?{action:s}:{}}}(e,t))),!0),[eo.clipboard]:async({positionals:e,flags:t,client:s})=>{var o,r;return o=t,r=await s.command.clipboard(function(e,t){let s=e[0]?.toLowerCase();if("read"!==s&&"write"!==s)throw new N("INVALID_ARGS","clipboard requires a subcommand: read or write.");let o=tm(t);if("read"===s){if(1!==e.length)throw new N("INVALID_ARGS","clipboard read does not accept additional arguments.");return{...o,action:s}}if(e.length<2)throw new N("INVALID_ARGS","clipboard write requires text.");return{...o,action:s,text:e.slice(1).join(" ")}}(e,t)),o.json?tf(o,r):"read"===r.action?process.stdout.write(`${r.text}
393
401
  `):tg(o,r),!0}};function t9(e){return null===e?{}:{timeoutMs:e}}function se(e){let{suite:t,json:s,verbose:o,reportJunit:r}=e;return(r&&function(e,t){let s=l.dirname(e);try{p.mkdirSync(s,{recursive:!0}),p.writeFileSync(e,function(e){let t=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${e.total}" failures="${e.failed}" skipped="${e.skipped}" time="${so(e.durationMs)}">`];for(let s of e.tests)t.push(...function(e){let t=sr(l.basename(e.file)),s=sr("."===l.dirname(e.file)?e.file:l.dirname(e.file)),o=sr(e.file),r=so(e.durationMs),n=[` <testcase classname="${s}" name="${t}" file="${o}" time="${r}">`];"failed"===e.status?n.push(` <failure message="${sr(e.error.message)}">${sr(function(e){let t=[e.error.message];e.error.hint&&t.push(`hint: ${e.error.hint}`),e.error.diagnosticId&&t.push(`diagnosticId: ${e.error.diagnosticId}`),e.error.logPath&&t.push(`logPath: ${e.error.logPath}`),e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`);let s=e.error.details?JSON.stringify(e.error.details,null,2):void 0;return s&&t.push(`details: ${s}`),t.join("\n")}(e))}</failure>`):"skipped"===e.status&&n.push(` <skipped message="${sr(e.message)}" />`);let a=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return"attempts"in e&&t.push(`attempts: ${e.attempts}`),"session"in e&&t.push(`session: ${e.session}`),"replayed"in e&&t.push(`replayed: ${e.replayed}`),"healed"in e&&t.push(`healed: ${e.healed}`),"artifactsDir"in e&&e.artifactsDir&&t.push(`artifactsDir: ${e.artifactsDir}`),"passed"===e.status&&e.attempts>1&&t.push("flaky: true"),t.join("\n")}(e);return a&&n.push(` <system-out>${sr(a)}</system-out>`),n.push(" </testcase>"),n}(s));return t.push(" </testsuite>"),t.push("</testsuites>"),`${t.join("\n")}
394
- `}(t),"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new C("COMMAND_FAILED",`Failed to write JUnit report to ${e}: ${t}`)}}(r,t),s)?(eP({success:!0,data:t}),function(e){return+(e.failed>0)}(t)):function(e,t={}){let s=e.tests.filter(ss);if(t.verbose)for(let t of e.tests)!function(e){if("failed"===e.status)return st(e);let t="passed"===e.status?ss(e)?"FLAKY":"PASS":"skipped"===e.status?"SKIP":"INFO",s="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${t} ${e.file}${s}${o}
402
+ `}(t),"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new N("COMMAND_FAILED",`Failed to write JUnit report to ${e}: ${t}`)}}(r,t),s)?(eP({success:!0,data:t}),function(e){return+(e.failed>0)}(t)):function(e,t={}){let s=e.tests.filter(ss);if(t.verbose)for(let t of e.tests)!function(e){if("failed"===e.status)return st(e);let t="passed"===e.status?ss(e)?"FLAKY":"PASS":"skipped"===e.status?"SKIP":"INFO",s="attempts"in e&&e.attempts>1?` after ${e.attempts} attempts`:"",o=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`${t} ${e.file}${s}${o}
395
403
  `),"skipped"===e.status&&process.stdout.write(` ${e.message??"skipped"}
396
404
  `)}(t);else{for(let t of e.failures)st(t);for(let e of s)!function(e){let t=e.durationMs>0?` (${e.durationMs}ms)`:"";process.stdout.write(`FLAKY ${e.file} after ${e.attempts} attempts${t}
397
405
  `)}(e)}let o="number"==typeof e.durationMs?e.durationMs:void 0,r=s.length>0?`, ${s.length} flaky`:"";return process.stdout.write(`Test summary: ${e.passed} passed, ${e.failed} failed${r}${void 0!==o?` in ${o}ms`:""}
@@ -427,10 +435,10 @@ ${$}${(function(e){let t=[],s=[],o=e=>{for(;s.length>0&&e<=s[s.length-1].depth;)
427
435
  `}(e);t&&process.stdout.write(t)}}(s)})(e),!0)};function sa(e){let t=e.ref??"",s=e.x,o=e.y;return!!t&&"number"==typeof s&&"number"==typeof o&&(process.stdout.write(`Tapped @${t} (${s}, ${o})
428
436
  `),!0)}function si(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:void 0}function sl(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function sc(e){return`${Number.isInteger(e)?e:e.toFixed(1)}%`}function sd(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms`;let s=Math.round(t/1e3);if(s<60)return`${s}s`;let o=Math.floor(s/60),r=s%60;return r>0?`${o}m ${r}s`:`${o}m`}function sp(e,t){"string"==typeof t&&process.stdout.write(` ${e}: ${t}
429
437
  `)}function su(e,t){return t.map(t=>void 0!==e[t]&&null!==e[t]?`${t}=${e[t]}`:"").filter(Boolean).join(" ")}function sm(e){if(Array.isArray(e))for(let t of e)"string"==typeof t&&t.length>0&&process.stderr.write(`${t}
430
- `)}let sf={[eo.boot]:sg(eo.boot,({client:e,flags:t})=>e.devices.boot({...tm(t),headless:t.headless})),[eo.push]:sg(eo.push,({client:e,positionals:t,flags:s})=>e.apps.push({...tm(s),app:sw(t[0],"push requires bundleOrPackage"),payload:sw(t[1],"push requires payloadOrJson")})),[eo.perf]:sg(eo.perf,({client:e,flags:t})=>e.observability.perf(tm(t))),[eo.click]:sg(eo.click,({client:e,positionals:t,flags:s})=>e.interactions.click({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap,button:s.clickButton})),[eo.get]:sg(eo.get,({client:e,positionals:t,flags:s})=>e.interactions.get({...function(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=e.join(" ").trim();if(!t)throw new C("INVALID_ARGS","get requires @ref or selector expression");return{selector:t}}(t.slice(1)),...sh(s),...tm(s),format:function(e){if("text"===e||"attrs"===e)return e;throw new C("INVALID_ARGS","get only supports text or attrs")}(t[0])})),[eo.replay]:sg(eo.replay,({client:e,positionals:t,flags:s})=>e.replay.run({...tm(s),path:sw(t[0],"replay requires path"),update:s.replayUpdate,env:s.replayEnv})),[eo.test]:sg(eo.test,({client:e,positionals:t,flags:s})=>(({json:s.json}).json||process.stderr.write("Running replay suite...\n"),e.replay.test({...tm(s),paths:t,update:s.replayUpdate,env:s.replayEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit}))),[eo.batch]:sg(eo.batch,({client:e,flags:t})=>e.batch.run({...tm(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})),[eo.press]:sg(eo.press,({client:e,positionals:t,flags:s})=>e.interactions.press({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap})),[eo.longPress]:sg(eo.longPress,({client:e,positionals:t,flags:s})=>e.interactions.longPress({...tm(s),x:Number(t[0]),y:Number(t[1]),durationMs:sb(t[2])})),[eo.swipe]:sg(eo.swipe,({client:e,positionals:t,flags:s})=>e.interactions.swipe({...tm(s),from:{x:Number(t[0]),y:Number(t[1])},to:{x:Number(t[2]),y:Number(t[3])},durationMs:sb(t[4]),count:s.count,pauseMs:s.pauseMs,pattern:s.pattern})),[eo.focus]:sg(eo.focus,({client:e,positionals:t,flags:s})=>e.interactions.focus({...tm(s),x:Number(t[0]),y:Number(t[1])})),[eo.type]:sg(eo.type,({client:e,positionals:t,flags:s})=>e.interactions.type({...tm(s),text:t.join(" "),delayMs:s.delayMs})),[eo.fill]:sg(eo.fill,({client:e,positionals:t,flags:s})=>e.interactions.fill({...function(e){if(e[0]?.startsWith("@")){let t=e.length>=3?e.slice(2).join(" "):e.slice(1).join(" ");return{ref:e[0],label:e.length>=3?e[1]:void 0,text:t}}let t=en(e,{preferTrailingValue:!0});return t?{selector:t.selectorExpression,text:t.rest.join(" ")}:{x:Number(e[0]),y:Number(e[1]),text:e.slice(2).join(" ")}}(t),...sh(s),...tm(s),delayMs:s.delayMs})),[eo.scroll]:sg(eo.scroll,({client:e,positionals:t,flags:s})=>e.interactions.scroll({...tm(s),direction:function(e){if("up"===e||"down"===e||"left"===e||"right"===e)return e;throw new C("INVALID_ARGS",`Unknown direction: ${String(e)}`)}(t[0]),amount:sb(t[1]),pixels:s.pixels})),[eo.pinch]:sg(eo.pinch,({client:e,positionals:t,flags:s})=>e.interactions.pinch({...tm(s),scale:Number(t[0]),x:sb(t[1]),y:sb(t[2])})),[eo.triggerAppEvent]:sg(eo.triggerAppEvent,({client:e,positionals:t,flags:s})=>e.apps.triggerEvent({...tm(s),event:sw(t[0],"trigger-app-event requires event"),payload:t[1]?function(e,t){try{let t=JSON.parse(e);if(t&&"object"==typeof t&&!Array.isArray(t))return t}catch{}throw new C("INVALID_ARGS",`${t} must be a JSON object`)}(t[1],"trigger-app-event payload"):void 0})),[eo.record]:sg(eo.record,({client:e,positionals:t,flags:s})=>e.recording.record({...tm(s),action:sy(t[0],"record"),path:t[1],fps:s.fps,quality:s.quality,hideTouches:s.hideTouches})),[eo.trace]:sg(eo.trace,({client:e,positionals:t,flags:s})=>e.recording.trace({...tm(s),action:sy(t[0],"trace"),path:t[1]})),[eo.logs]:sg(eo.logs,({client:e,positionals:t,flags:s})=>e.observability.logs({...tm(s),action:function(e){if(void 0!==e){if("path"===e||"start"===e||"stop"===e||"doctor"===e||"mark"===e||"clear"===e)return e;throw new C("INVALID_ARGS","logs requires path, start, stop, doctor, mark, or clear")}}(t[0]),message:t.slice(1).join(" ")||void 0,restart:s.restart})),[eo.network]:sg(eo.network,({client:e,positionals:t,flags:s})=>e.observability.network({...tm(s),action:function(e){if(void 0!==e){if("dump"===e||"log"===e)return e;throw new C("INVALID_ARGS","network requires dump or log")}}(t[0]),limit:sb(t[1]),include:s.networkInclude??function(e){if(void 0!==e){if("summary"===e||"headers"===e||"body"===e||"all"===e)return e;throw new C("INVALID_ARGS","network include mode must be summary, headers, body, or all")}}(t[2])})),[eo.find]:sg(eo.find,({client:e,positionals:t,flags:s})=>{var o;return e.interactions.find({...function(e){let t=function(e){if("text"===e||"label"===e||"value"===e||"role"===e||"id"===e)return e}(e[0]),s=void 0!==t,o=s?e[1]:e[0],r=s?2:1,n=e[r];if(void 0===n)return{locator:t,query:sw(o,"find requires query")};if("get"===n){let s=e[r+1];if("text"===s)return{locator:t,query:sw(o,"find requires query"),action:"getText"};if("attrs"===s)return{locator:t,query:sw(o,"find requires query"),action:"getAttrs"};throw new C("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:sw(o,"find requires query"),action:"wait",timeoutMs:sb(e[r+1])};if("fill"===n||"type"===n)return{locator:t,query:sw(o,"find requires query"),action:n,value:e.slice(r+1).join(" ")};if("click"===n||"focus"===n||"exists"===n)return{locator:t,query:sw(o,"find requires query"),action:n};throw new C("INVALID_ARGS",`Unsupported find action: ${n}`)}(t),...{depth:(o=s).snapshotDepth,raw:o.snapshotRaw},...tm(s),first:s.findFirst,last:s.findLast})}),[eo.is]:sg(eo.is,({client:e,positionals:t,flags:s})=>e.interactions.is({...function(e){let t=e[0],s=en(e.slice(1),{preferTrailingValue:"text"===t});if(!s)throw new C("INVALID_ARGS","is requires a selector expression");if("text"===t)return{predicate:t,selector:s.selectorExpression,value:s.rest.join(" ")};if("visible"===t||"hidden"===t||"exists"===t||"editable"===t||"selected"===t)return{predicate:t,selector:s.selectorExpression};throw new C("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text")}(t),...sh(s),...tm(s)})),[eo.settings]:sg(eo.settings,({client:e,positionals:t,flags:s})=>e.settings.update(function(e,t){let s=tm(t),o=e[0],r=e[1];if(("wifi"===o||"airplane"===o||"location"===o||"animations"===o)&&("on"===r||"off"===r)||"appearance"===o&&("light"===r||"dark"===r||"toggle"===r)||("faceid"===o||"touchid"===o)&&("match"===r||"nonmatch"===r||"enroll"===r||"unenroll"===r)||"fingerprint"===o&&("match"===r||"nonmatch"===r))return{...s,setting:o,state:r};if("permission"===o&&("grant"===r||"deny"===r||"reset"===r))return{...s,setting:o,state:r,permission:function(e){switch(e){case"camera":case"microphone":case"photos":case"contacts":case"contacts-limited":case"notifications":case"calendar":case"location":case"location-always":case"media-library":case"motion":case"reminders":case"siri":case"accessibility":case"screen-recording":case"input-monitoring":return e;default:throw new C("INVALID_ARGS","settings permission requires a permission target.")}}(e[2]),mode:function(e){if(void 0===e||"full"===e||"limited"===e)return e;throw new C("INVALID_ARGS","settings permission mode must be full or limited.")}(e[3])};throw new C("INVALID_ARGS","Invalid settings arguments.")}(t,s)))};function sg(e,t){return async({positionals:s,flags:o,client:r})=>{let n=await t({client:r,positionals:s,flags:o}),a=function(e,t,s,o){if(s.json){var r,n,a;return r=e,n=s,a=o,r===eo.test?se({suite:a,json:!0,reportJunit:n.reportJunit}):(eP({success:!0,data:a}),0)}if(e===eo.test)return se({suite:o,verbose:s.verbose,reportJunit:s.reportJunit});let i=sn[e];if(i?.({positionals:t,flags:s,data:o}))return 0;let l=G(o);return l&&process.stdout.write(`${l}
431
- `),0}(e,s,o,n);return 0!==a&&process.exit(a),!0}}function sh(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function sv(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=en(e);return t?{selector:t.selectorExpression}:{x:Number(e[0]),y:Number(e[1])}}function sy(e,t){if("start"===e||"stop"===e)return e;throw new C("INVALID_ARGS",`${t} requires start|stop`)}function sw(e,t){if(void 0===e||""===e)throw new C("INVALID_ARGS",t);return e}function sb(e){return void 0===e?void 0:Number(e)}let sk={...{session:th,[eo.devices]:tv,[eo.apps]:tk,"ensure-simulator":tw,metro:tb,install:tS,reinstall:tx,"install-from-source":t$,connect:tY,disconnect:tX,connection:tQ,auth:t5,open:tC,close:tR,[eo.snapshot]:t8,[eo.screenshot]:t4,[eo.diff]:t6},...t7,...sf};async function sA(e){let t=sk[e.command];return!!t&&await t(e)}async function sI(e,t){let{flags:s}=e,o=function(e){if(!e?.metroProxyBaseUrl||(e.leaseBackend?"android-instance"!==e.leaseBackend&&"ios-instance"!==e.leaseBackend:"android"!==e.platform&&"ios"!==e.platform))return null;let t=e?.metroProxyBaseUrl,s=e?.metroBearerToken,o=e?.tenant,r=e?.runId,n=e?.leaseId,a=[];if(t||a.push("metroProxyBaseUrl"),s||a.push("metroBearerToken"),o||a.push("tenant"),r||a.push("runId"),n||a.push("leaseId"),a.length>0)throw new C("INVALID_ARGS",`react-devtools remote bridge requires ${a.join(", ")}.`,{missing:a});if(!t||!s||!o||!r||!n)throw new C("INVALID_ARGS","react-devtools remote bridge is incomplete.");return{serverBaseUrl:t,bearerToken:s,tenantId:o,runId:r,leaseId:n}}(s);if(!o)return t();let r=e.stateDir??process.cwd(),n=e.session??s?.session??"default",a=s?.remoteConfig??`${o.tenantId}:${o.runId}:${o.leaseId}`;await eY({projectRoot:e.cwd??process.cwd(),stateDir:r,serverBaseUrl:o.serverBaseUrl,bearerToken:o.bearerToken,bridgeScope:{tenantId:o.tenantId,runId:o.runId,leaseId:o.leaseId},session:n,profileKey:a,consumerKey:n,env:e.env??process.env});try{return await t()}finally{await eZ({projectRoot:e.cwd??process.cwd(),stateDir:r,profileKey:a,consumerKey:n})}}async function sD(e,t={}){let s=t.cwd??process.cwd(),o=t.env??process.env;return await sI(t,async()=>(await Z("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:s,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode)}function sS(e,t={}){let s=sx(t),o={...e};return s.defaultPlatform&&void 0===o.platform&&(o.platform=s.defaultPlatform),o}function sx(e){var t,s,o,r;let n,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 C("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:(s=e.policyOverrides,o=a,r=l,(n=s?.sessionLock??s?.sessionLockConflicts??s$(o.AGENT_DEVICE_SESSION_LOCK)??s$(o.AGENT_DEVICE_SESSION_LOCK_CONFLICTS))||(s?.sessionLocked===!0||ea(o.AGENT_DEVICE_SESSION_LOCKED)||r?"reject":void 0))}}function s$(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new C("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}let sL={sendToDaemon:er},sN=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),sC=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]);async function sR(e,t=sL){let s=O(),o=W(),r=e.includes("--debug")||e.includes("--verbose")||e.includes("-v"),n=e.includes("--json"),a=function(e){for(let t=0;t<e.length;t+=1){let s=e[t];if(s.startsWith("--session=")){let e=s.slice(10).trim();return e.length>0?e:null}if("--session"===s){let s=e[t+1]?.trim();if(s&&!s.startsWith("-"))return s;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await U({session:a,requestId:s,command:e[0],debug:r},async()=>{var a,i,c,d,u,m,f,g,h,v,y,w,b,k,A,S,$;let R,_,E,O,U,F,B;try{let t,s,o,r,n,w,b,k;a={cwd:process.cwd(),env:process.env},t=function(e){let t={json:!1,help:!1,version:!1},s=null,o=[],r=[],n=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(n&&"--"===c){n=!1;continue}if(!n){s?o.push(c):s=eU(c);continue}let d=c.startsWith("--"),p=c.startsWith("-")&&c.length>1;if(!d&&!p){s?o.push(c):s=eU(c);continue}let[u,m]=d?e_(c):[c,void 0],f=eh.get(u);if(a=s,i=f,"react-devtools"===a&&(!i||!eC(i.key,a))){o.push(c);continue}if(!f){if(function(e,t,s){var o;if(o=s,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=ey(e);return!r||!!r.allowsExtraPositionals||0!==r.positionalArgs.length&&(t.length<r.positionalArgs.length||r.positionalArgs.some(e=>e.includes("?")))}(s,o,c)){s?o.push(c):s=c;continue}throw new C("INVALID_ARGS",`Unknown flag: ${u}`)}let g=function(e,t,s,o){if(void 0!==e.setValue){if(void 0!==s)throw new C("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==s)throw new C("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==s){if(0===s.trim().length)throw new C("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:s,consumeNext:!1}}return void 0===o||eO(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=s??o;if(void 0===r||void 0===s&&eO(r))throw new C("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===s};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new C("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:r,consumeNext:void 0===s}}let n=Number(r);if(!Number.isFinite(n)||"number"==typeof e.min&&n<e.min||"number"==typeof e.max&&n>e.max)throw new C("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:Math.floor(n),consumeNext:void 0===s}}(f,u,m,e[l+1]);g.consumeNext&&(l+=1);let h=t[f.key];if(f.multiple){let e=Array.isArray(h)?[...h,g.value]:void 0===h?[g.value]:[h,g.value];t[f.key]=e}else t[f.key]=g.value;r.push({key:f.key,token:u})}return{command:s,positionals:o,flags:t,warnings:[],providedFlags:r}}(e),s=a?.env??process.env,o=a?.cwd??process.cwd(),d=t.command,r=null!==d&&(i={remoteConfig:t.flags.remoteConfig,cwd:o,env:s}).remoteConfig?{...te(I({configPath:i.remoteConfig,cwd:i.cwd,env:i.env}).profile),remoteConfig:i.remoteConfig}:{},b=ec((n=(c={command:t.command,cwd:o,cliFlags:t.flags,env:s}).env??process.env,w=ec({},function(e){let t={};for(let s of e)ec(t,function(e,t){let s,o;if(!p.existsSync(e)){if(t)throw new C("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{s=p.readFileSync(e,"utf8")}catch(t){throw new C("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(s)}catch(t){throw new C("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new C("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let s={};for(let[o,r]of Object.entries(e)){if("installSource"===o){s.installSource=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new C("INVALID_ARGS",`${t} installSource must be an object.`);if("github-actions-artifact"!==tD(e.type,`${t} installSource.type`))throw new C("INVALID_ARGS",`${t} installSource.type must be "github-actions-artifact".`);let{owner:s,repo:o}=tI(tD(e.repo,`${t} installSource.repo`),`${t} installSource.repo`);return tA(s,o,e.artifact,`${t} installSource.artifact`)}(r,t);continue}let e=eN.get(o);if(!e)throw new C("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new C("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);s[o]=x(eR(e),r,t,o)}return s}(o,`config file ${e}`)}(s.path,s.required));return t}((u=c.cwd,m=c.cliFlags.config,f=n,(k=m??f.AGENT_DEVICE_CONFIG)?[{path:(g=k,h=u,v=f,Q(g,{cwd:h,env:v})),required:!0}]:[{path:(y=f,l.join(ee("~",{env:y}),".agent-device","config.json")),required:!1},{path:l.resolve(u,"agent-device.json"),required:!1}]))),ec(w,function(e,t){var s,o,r;let n={};for(let a of eL.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&&(n[a.key]=(s=t.value,o=`environment variable ${t.name}`,r=t.name,x(eR(a),s,o,r)))}return n}(n,c.command))),r),R={...function(e,t){let s=t?.strictFlags??function(e){if(!e)return!1;let t=e.trim().toLowerCase();return"1"===t||"true"===t||"yes"===t||"on"===t}(process.env.AGENT_DEVICE_STRICT_FLAGS),o=[...e.warnings],r=ec({json:!1,help:!1,version:!1},t?.defaultFlags??{});ec(r,e.flags);let n=ey(e.command),a=e.providedFlags.filter(t=>!eC(t.key,e.command));if(a.length>0){var i,l;let t=a.map(e=>e.token),n=(i=e.command,l=t,i?1===l.length?`Flag ${l[0]} is not supported for command ${i}.`:`Flags ${l.join(", ")} are not supported for command ${i}.`:1===l.length?`Flag ${l[0]} requires a command that supports it.`:`Flags ${l.join(", ")} require a command that supports them.`);if(s)throw new C("INVALID_ARGS",n);for(let e of(o.push(`${n} Enable AGENT_DEVICE_STRICT_FLAGS=1 to fail fast.`),a))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eC(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 C("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),n?.defaults)for(let[e,t]of Object.entries(n.defaults))void 0===r[e]&&(r[e]=t);if("batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new C("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,...s}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:s,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(t,{strictFlags:a?.strictFlags,defaultFlags:b}),providedFlags:t.providedFlags}}catch(t){M({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=N(t,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});n?eP({success:!1,error:e}):eT(e,{showDetails:r}),process.exit(1);return}for(let e of R.warnings)process.stderr.write(`Warning: ${e}
438
+ `)}let sf={[eo.boot]:sg(eo.boot,({client:e,flags:t})=>e.devices.boot({...tm(t),headless:t.headless})),[eo.push]:sg(eo.push,({client:e,positionals:t,flags:s})=>e.apps.push({...tm(s),app:sw(t[0],"push requires bundleOrPackage"),payload:sw(t[1],"push requires payloadOrJson")})),[eo.perf]:sg(eo.perf,({client:e,flags:t})=>e.observability.perf(tm(t))),[eo.click]:sg(eo.click,({client:e,positionals:t,flags:s})=>e.interactions.click({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap,button:s.clickButton})),[eo.get]:sg(eo.get,({client:e,positionals:t,flags:s})=>e.interactions.get({...function(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=e.join(" ").trim();if(!t)throw new N("INVALID_ARGS","get requires @ref or selector expression");return{selector:t}}(t.slice(1)),...sh(s),...tm(s),format:function(e){if("text"===e||"attrs"===e)return e;throw new N("INVALID_ARGS","get only supports text or attrs")}(t[0])})),[eo.replay]:sg(eo.replay,({client:e,positionals:t,flags:s})=>e.replay.run({...tm(s),path:sw(t[0],"replay requires path"),update:s.replayUpdate,env:s.replayEnv})),[eo.test]:sg(eo.test,({client:e,positionals:t,flags:s})=>(({json:s.json}).json||process.stderr.write("Running replay suite...\n"),e.replay.test({...tm(s),paths:t,update:s.replayUpdate,env:s.replayEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit}))),[eo.batch]:sg(eo.batch,({client:e,flags:t})=>e.batch.run({...tm(t),steps:t.batchSteps??[],onError:t.batchOnError,maxSteps:t.batchMaxSteps,out:t.out})),[eo.press]:sg(eo.press,({client:e,positionals:t,flags:s})=>e.interactions.press({...sv(t),...sh(s),...tm(s),count:s.count,intervalMs:s.intervalMs,holdMs:s.holdMs,jitterPx:s.jitterPx,doubleTap:s.doubleTap})),[eo.longPress]:sg(eo.longPress,({client:e,positionals:t,flags:s})=>e.interactions.longPress({...tm(s),x:Number(t[0]),y:Number(t[1]),durationMs:sb(t[2])})),[eo.swipe]:sg(eo.swipe,({client:e,positionals:t,flags:s})=>e.interactions.swipe({...tm(s),from:{x:Number(t[0]),y:Number(t[1])},to:{x:Number(t[2]),y:Number(t[3])},durationMs:sb(t[4]),count:s.count,pauseMs:s.pauseMs,pattern:s.pattern})),[eo.focus]:sg(eo.focus,({client:e,positionals:t,flags:s})=>e.interactions.focus({...tm(s),x:Number(t[0]),y:Number(t[1])})),[eo.type]:sg(eo.type,({client:e,positionals:t,flags:s})=>e.interactions.type({...tm(s),text:t.join(" "),delayMs:s.delayMs})),[eo.fill]:sg(eo.fill,({client:e,positionals:t,flags:s})=>e.interactions.fill({...function(e){if(e[0]?.startsWith("@")){let t=e.length>=3?e.slice(2).join(" "):e.slice(1).join(" ");return{ref:e[0],label:e.length>=3?e[1]:void 0,text:t}}let t=en(e,{preferTrailingValue:!0});return t?{selector:t.selectorExpression,text:t.rest.join(" ")}:{x:Number(e[0]),y:Number(e[1]),text:e.slice(2).join(" ")}}(t),...sh(s),...tm(s),delayMs:s.delayMs})),[eo.scroll]:sg(eo.scroll,({client:e,positionals:t,flags:s})=>e.interactions.scroll({...tm(s),direction:function(e){if("up"===e||"down"===e||"left"===e||"right"===e)return e;throw new N("INVALID_ARGS",`Unknown direction: ${String(e)}`)}(t[0]),amount:sb(t[1]),pixels:s.pixels})),[eo.pinch]:sg(eo.pinch,({client:e,positionals:t,flags:s})=>e.interactions.pinch({...tm(s),scale:Number(t[0]),x:sb(t[1]),y:sb(t[2])})),[eo.triggerAppEvent]:sg(eo.triggerAppEvent,({client:e,positionals:t,flags:s})=>e.apps.triggerEvent({...tm(s),event:sw(t[0],"trigger-app-event requires event"),payload:t[1]?function(e,t){try{let t=JSON.parse(e);if(t&&"object"==typeof t&&!Array.isArray(t))return t}catch{}throw new N("INVALID_ARGS",`${t} must be a JSON object`)}(t[1],"trigger-app-event payload"):void 0})),[eo.record]:sg(eo.record,({client:e,positionals:t,flags:s})=>e.recording.record({...tm(s),action:sy(t[0],"record"),path:t[1],fps:s.fps,quality:s.quality,hideTouches:s.hideTouches})),[eo.trace]:sg(eo.trace,({client:e,positionals:t,flags:s})=>e.recording.trace({...tm(s),action:sy(t[0],"trace"),path:t[1]})),[eo.logs]:sg(eo.logs,({client:e,positionals:t,flags:s})=>e.observability.logs({...tm(s),action:function(e){if(void 0!==e){if("path"===e||"start"===e||"stop"===e||"doctor"===e||"mark"===e||"clear"===e)return e;throw new N("INVALID_ARGS","logs requires path, start, stop, doctor, mark, or clear")}}(t[0]),message:t.slice(1).join(" ")||void 0,restart:s.restart})),[eo.network]:sg(eo.network,({client:e,positionals:t,flags:s})=>e.observability.network({...tm(s),action:function(e){if(void 0!==e){if("dump"===e||"log"===e)return e;throw new N("INVALID_ARGS","network requires dump or log")}}(t[0]),limit:sb(t[1]),include:s.networkInclude??function(e){if(void 0!==e){if("summary"===e||"headers"===e||"body"===e||"all"===e)return e;throw new N("INVALID_ARGS","network include mode must be summary, headers, body, or all")}}(t[2])})),[eo.find]:sg(eo.find,({client:e,positionals:t,flags:s})=>{var o;return e.interactions.find({...function(e){let t=function(e){if("text"===e||"label"===e||"value"===e||"role"===e||"id"===e)return e}(e[0]),s=void 0!==t,o=s?e[1]:e[0],r=s?2:1,n=e[r];if(void 0===n)return{locator:t,query:sw(o,"find requires query")};if("get"===n){let s=e[r+1];if("text"===s)return{locator:t,query:sw(o,"find requires query"),action:"getText"};if("attrs"===s)return{locator:t,query:sw(o,"find requires query"),action:"getAttrs"};throw new N("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:sw(o,"find requires query"),action:"wait",timeoutMs:sb(e[r+1])};if("fill"===n||"type"===n)return{locator:t,query:sw(o,"find requires query"),action:n,value:e.slice(r+1).join(" ")};if("click"===n||"focus"===n||"exists"===n)return{locator:t,query:sw(o,"find requires query"),action:n};throw new N("INVALID_ARGS",`Unsupported find action: ${n}`)}(t),...{depth:(o=s).snapshotDepth,raw:o.snapshotRaw},...tm(s),first:s.findFirst,last:s.findLast})}),[eo.is]:sg(eo.is,({client:e,positionals:t,flags:s})=>e.interactions.is({...function(e){let t=e[0],s=en(e.slice(1),{preferTrailingValue:"text"===t});if(!s)throw new N("INVALID_ARGS","is requires a selector expression");if("text"===t)return{predicate:t,selector:s.selectorExpression,value:s.rest.join(" ")};if("visible"===t||"hidden"===t||"exists"===t||"editable"===t||"selected"===t)return{predicate:t,selector:s.selectorExpression};throw new N("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text")}(t),...sh(s),...tm(s)})),[eo.settings]:sg(eo.settings,({client:e,positionals:t,flags:s})=>e.settings.update(function(e,t){let s=tm(t),o=e[0],r=e[1];if(("wifi"===o||"airplane"===o||"location"===o||"animations"===o)&&("on"===r||"off"===r)||"appearance"===o&&("light"===r||"dark"===r||"toggle"===r)||("faceid"===o||"touchid"===o)&&("match"===r||"nonmatch"===r||"enroll"===r||"unenroll"===r)||"fingerprint"===o&&("match"===r||"nonmatch"===r))return{...s,setting:o,state:r};if("permission"===o&&("grant"===r||"deny"===r||"reset"===r))return{...s,setting:o,state:r,permission:function(e){switch(e){case"camera":case"microphone":case"photos":case"contacts":case"contacts-limited":case"notifications":case"calendar":case"location":case"location-always":case"media-library":case"motion":case"reminders":case"siri":case"accessibility":case"screen-recording":case"input-monitoring":return e;default:throw new N("INVALID_ARGS","settings permission requires a permission target.")}}(e[2]),mode:function(e){if(void 0===e||"full"===e||"limited"===e)return e;throw new N("INVALID_ARGS","settings permission mode must be full or limited.")}(e[3])};throw new N("INVALID_ARGS","Invalid settings arguments.")}(t,s)))};function sg(e,t){return async({positionals:s,flags:o,client:r})=>{let n=await t({client:r,positionals:s,flags:o}),a=function(e,t,s,o){if(s.json){var r,n,a;return r=e,n=s,a=o,r===eo.test?se({suite:a,json:!0,reportJunit:n.reportJunit}):(eP({success:!0,data:a}),0)}if(e===eo.test)return se({suite:o,verbose:s.verbose,reportJunit:s.reportJunit});let i=sn[e];if(i?.({positionals:t,flags:s,data:o}))return 0;let l=G(o);return l&&process.stdout.write(`${l}
439
+ `),0}(e,s,o,n);return 0!==a&&process.exit(a),!0}}function sh(e){return{depth:e.snapshotDepth,scope:e.snapshotScope,raw:e.snapshotRaw}}function sv(e){if(e[0]?.startsWith("@"))return{ref:e[0],label:e.slice(1).join(" ")||void 0};let t=en(e);return t?{selector:t.selectorExpression}:{x:Number(e[0]),y:Number(e[1])}}function sy(e,t){if("start"===e||"stop"===e)return e;throw new N("INVALID_ARGS",`${t} requires start|stop`)}function sw(e,t){if(void 0===e||""===e)throw new N("INVALID_ARGS",t);return e}function sb(e){return void 0===e?void 0:Number(e)}let sk={...{session:th,[eo.devices]:tv,[eo.apps]:tk,"ensure-simulator":tw,metro:tb,install:tS,reinstall:tx,"install-from-source":t$,connect:tZ,disconnect:tX,connection:tQ,auth:t5,open:tN,close:tR,[eo.snapshot]:t8,[eo.screenshot]:t4,[eo.diff]:t6},...t7,...sf};async function sA(e){let t=sk[e.command];return!!t&&await t(e)}function sI(e,t,s){return s||(e.push(t),"")}async function sD(e,t,s){let{flags:o}=t,r=function(e){var t;if(!e?.metroProxyBaseUrl||"android-instance"!==(t=e.leaseBackend)&&"ios-instance"!==t)return null;let s=[],o={serverBaseUrl:sI(s,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:sI(s,"metroBearerToken",e.metroBearerToken),tenantId:sI(s,"tenant",e.tenant),runId:sI(s,"runId",e.runId),leaseId:sI(s,"leaseId",e.leaseId)};if(s.length>0)throw new N("INVALID_ARGS",`react-devtools remote bridge requires ${s.join(", ")}.`,{missing:s});return o}(o);if(!r)return s();let n=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 s()}finally{await eZ({projectRoot:t.cwd??process.cwd(),stateDir:n,profileKey:i,consumerKey:a})}return await eY({projectRoot:t.cwd??process.cwd(),stateDir:n,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 s()}async function sS(e,t={}){let s=t.cwd??process.cwd(),o=t.env??process.env,r=await sD(e,t,async()=>(await Z("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:s,env:o,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var n,a=t.flags;return 0!==r&&"wait"===(n=e)[0]&&n.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}function sx(e,t={}){let s=s$(t),o={...e};return s.defaultPlatform&&void 0===o.platform&&(o.platform=s.defaultPlatform),o}function s$(e){var t,s,o,r;let n,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 N("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:(s=e.policyOverrides,o=a,r=l,(n=s?.sessionLock??s?.sessionLockConflicts??sC(o.AGENT_DEVICE_SESSION_LOCK)??sC(o.AGENT_DEVICE_SESSION_LOCK_CONFLICTS))||(s?.sessionLocked===!0||ea(o.AGENT_DEVICE_SESSION_LOCKED)||r?"reject":void 0))}}function sC(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new N("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}let sL={sendToDaemon:er},sN=new Set(["launchUrl","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),sR=new Set(["connect","connection","close","disconnect","ensure-simulator","metro","session"]);async function s_(e,t=sL){let s=O(),o=W(),r=e.includes("--debug")||e.includes("--verbose")||e.includes("-v"),n=e.includes("--json"),a=function(e){for(let t=0;t<e.length;t+=1){let s=e[t];if(s.startsWith("--session=")){let e=s.slice(10).trim();return e.length>0?e:null}if("--session"===s){let s=e[t+1]?.trim();if(s&&!s.startsWith("-"))return s;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await U({session:a,requestId:s,command:e[0],debug:r},async()=>{var a,i,c,d,u,m,f,g,h,v,y,w,b,k,A,S,$;let R,_,E,O,U,F,B;try{let t,s,o,r,n,w,b,k;a={cwd:process.cwd(),env:process.env},t=function(e){let t={json:!1,help:!1,version:!1},s=null,o=[],r=[],n=!0;for(let l=0;l<e.length;l+=1){var a,i;let c=e[l];if(n&&"--"===c){n=!1;continue}if(!n){s?o.push(c):s=eU(c);continue}let d=c.startsWith("--"),p=c.startsWith("-")&&c.length>1;if(!d&&!p){s?o.push(c):s=eU(c);continue}let[u,m]=d?e_(c):[c,void 0],f=eh.get(u);if(a=s,i=f,"react-devtools"===a&&(!i||!eN(i.key,a))){o.push(c);continue}if(!f){if(function(e,t,s){var o;if(o=s,!/^-\d+(\.\d+)?$/.test(o)||!e)return!1;let r=ey(e);return!r||!!r.allowsExtraPositionals||0!==r.positionalArgs.length&&(t.length<r.positionalArgs.length||r.positionalArgs.some(e=>e.includes("?")))}(s,o,c)){s?o.push(c):s=c;continue}throw new N("INVALID_ARGS",`Unknown flag: ${u}`)}let g=function(e,t,s,o){if(void 0!==e.setValue){if(void 0!==s)throw new N("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==s)throw new N("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==s){if(0===s.trim().length)throw new N("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:s,consumeNext:!1}}return void 0===o||eO(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=s??o;if(void 0===r||void 0===s&&eO(r))throw new N("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:r,consumeNext:void 0===s};if("enum"===e.type){if(!e.enumValues?.includes(r))throw new N("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:r,consumeNext:void 0===s}}let n=Number(r);if(!Number.isFinite(n)||"number"==typeof e.min&&n<e.min||"number"==typeof e.max&&n>e.max)throw new N("INVALID_ARGS",`Invalid ${eE(t)}: ${r}`);return{value:Math.floor(n),consumeNext:void 0===s}}(f,u,m,e[l+1]);g.consumeNext&&(l+=1);let h=t[f.key];if(f.multiple){let e=Array.isArray(h)?[...h,g.value]:void 0===h?[g.value]:[h,g.value];t[f.key]=e}else t[f.key]=g.value;r.push({key:f.key,token:u})}return{command:s,positionals:o,flags:t,warnings:[],providedFlags:r}}(e),s=a?.env??process.env,o=a?.cwd??process.cwd(),d=t.command,r=null!==d&&(i={remoteConfig:t.flags.remoteConfig,cwd:o,env:s}).remoteConfig?{...te(I({configPath:i.remoteConfig,cwd:i.cwd,env:i.env}).profile),remoteConfig:i.remoteConfig}:{},b=ec((n=(c={command:t.command,cwd:o,cliFlags:t.flags,env:s}).env??process.env,w=ec({},function(e){let t={};for(let s of e)ec(t,function(e,t){let s,o;if(!p.existsSync(e)){if(t)throw new N("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{s=p.readFileSync(e,"utf8")}catch(t){throw new N("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(s)}catch(t){throw new N("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new N("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let s={};for(let[o,r]of Object.entries(e)){if("installSource"===o){s.installSource=function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new N("INVALID_ARGS",`${t} installSource must be an object.`);if("github-actions-artifact"!==tD(e.type,`${t} installSource.type`))throw new N("INVALID_ARGS",`${t} installSource.type must be "github-actions-artifact".`);let{owner:s,repo:o}=tI(tD(e.repo,`${t} installSource.repo`),`${t} installSource.repo`);return tA(s,o,e.artifact,`${t} installSource.artifact`)}(r,t);continue}let e=eL.get(o);if(!e)throw new N("INVALID_ARGS",`Unknown config key "${o}" in ${t}.`);if(!e.config.enabled)throw new N("INVALID_ARGS",`Unsupported config key "${o}" in ${t}.`);s[o]=x(eR(e),r,t,o)}return s}(o,`config file ${e}`)}(s.path,s.required));return t}((u=c.cwd,m=c.cliFlags.config,f=n,(k=m??f.AGENT_DEVICE_CONFIG)?[{path:(g=k,h=u,v=f,Q(g,{cwd:h,env:v})),required:!0}]:[{path:(y=f,l.join(ee("~",{env:y}),".agent-device","config.json")),required:!1},{path:l.resolve(u,"agent-device.json"),required:!1}]))),ec(w,function(e,t){var s,o,r;let n={};for(let a of eC.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&&(n[a.key]=(s=t.value,o=`environment variable ${t.name}`,r=t.name,x(eR(a),s,o,r)))}return n}(n,c.command))),r),R={...function(e,t){let s=t?.strictFlags??function(e){if(!e)return!1;let t=e.trim().toLowerCase();return"1"===t||"true"===t||"yes"===t||"on"===t}(process.env.AGENT_DEVICE_STRICT_FLAGS),o=[...e.warnings],r=ec({json:!1,help:!1,version:!1},t?.defaultFlags??{});ec(r,e.flags);let n=ey(e.command),a=e.providedFlags.filter(t=>!eN(t.key,e.command));if(a.length>0){var i,l;let t=a.map(e=>e.token),n=(i=e.command,l=t,i?1===l.length?`Flag ${l[0]} is not supported for command ${i}.`:`Flags ${l.join(", ")} are not supported for command ${i}.`:1===l.length?`Flag ${l[0]} requires a command that supports it.`:`Flags ${l.join(", ")} require a command that supports them.`);if(s)throw new N("INVALID_ARGS",n);for(let e of(o.push(`${n} Enable AGENT_DEVICE_STRICT_FLAGS=1 to fail fast.`),a))delete r[e.key]}for(let t of Object.keys(r))void 0!==r[t]&&(eN(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 N("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),n?.defaults)for(let[e,t]of Object.entries(n.defaults))void 0===r[e]&&(r[e]=t);if("batch"===e.command&&1!=+!!r.steps+ +!!r.stepsFile)throw new N("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,...s}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:s,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:r,warnings:o})}(t,{strictFlags:a?.strictFlags,defaultFlags:b}),providedFlags:t.providedFlags}}catch(t){M({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=L(t,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});n?eP({success:!1,error:e}):eT(e,{showDetails:r}),process.exit(1);return}for(let e of R.warnings)process.stderr.write(`Warning: ${e}
432
440
  `);R.flags.version&&(process.stdout.write(`${o}
433
- `),process.exit(0));let j="help"===R.command,V=R.flags.help;if(j||V){j&&R.positionals.length>1&&(eT(new C("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=j?R.positionals[0]:R.command;e||(process.stdout.write(`${ek}
441
+ `),process.exit(0));let j="help"===R.command,V=R.flags.help;if(j||V){j&&R.positionals.length>1&&(eT(new N("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=j?R.positionals[0]:R.command;e||(process.stdout.write(`${ek}
434
442
  `),process.exit(0));let t=function(e){var t,s;let o,r=(o=eu[e])?`${o.body}
435
443
 
436
444
  Related:
@@ -445,9 +453,9 @@ Usage:
445
453
  agent-device ${a}
446
454
 
447
455
  ${c.join("\n\n")}
448
- `}(eU(e));t&&(process.stdout.write(t),process.exit(0)),eT(new C("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${ek}
456
+ `}(eU(e));t&&(process.stdout.write(t),process.exit(0)),eT(new N("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${ek}
449
457
  `),process.exit(1)}R.command||(process.stdout.write(`${ek}
450
- `),process.exit(1));let{command:G,positionals:q}=R,H=new Set(R.providedFlags.map(e=>e.key));try{E=(_=sx({policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session})).lockPolicy?{...R.flags}:sS(R.flags,{policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session}),O=K(E.stateDir),U=E.session??"default",w={command:G,explicitFlagKeys:H,stateDir:O.baseDir,session:U,remoteConfig:E.remoteConfig},B=(F="connect"===w.command||"connection"===w.command?null:function(e){let t=e.validateRemoteConfigHash??!0,s=e.remoteConfig?D({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=eX(e)??(e.allowActiveFallback?e8({stateDir:e.stateDir}):null);if(!o||s&&o.remoteConfigPath!==s)return null;if(t&&e2(o.remoteConfigPath)!==o.remoteConfigHash)throw new C("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return I({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:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:w.stateDir,session:w.session,remoteConfig:w.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!w.explicitFlagKeys.has("session")&&(!w.remoteConfig||"disconnect"===w.command),validateRemoteConfigHash:"disconnect"!==w.command}))?function(e,t,s){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(s.has(e)||(o[e]=r));return o}(E,F.flags,H):E}catch(t){let e=N(L(t),{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});R.flags.json?eP({success:!1,error:e}):eT(e,{showDetails:R.flags.verbose}),process.exit(1);return}let J=null;try{let e;if("react-devtools"===G){let e=await sD(q,{flags:B,stateDir:O.baseDir,session:B.session??U,cwd:process.cwd(),env:process.env});process.exit(e);return}el({command:G,currentVersion:o,stateDir:O.baseDir,flags:B});let r=F?.runtime,n=(e,t)=>({session:e.session??U,requestId:s,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:_.lockPolicy,lockPlatform:_.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===G){if(q.length>0)throw new C("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t="";if(e.steps)t=e.steps;else if(e.stepsFile)try{t=p.readFileSync(e.stepsFile,"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new C("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}return ei(t)}(E)}if(b=G,"auth"!==b&&"connection"!==b&&(B=(await t_({command:G,flags:B,stateDir:O.baseDir,env:process.env})).flags),B.remoteConfig&&(k=G,!sC.has(k))){let s=es(n(B,r),{transport:t.sendToDaemon}),o=await to({command:G,flags:B,client:s,runtime:r,batchSteps:e,forceRuntimePrepare:function(e){for(let t of sN)if(e.has(t))return!0;return!1}(H)});B=o.flags,r=o.runtime}A={command:G,flags:B,runtime:r,explicitFlagKeys:H,hadConnectionDefaults:!!F},!("open"===A.command&&!A.runtime&&!A.flags.bundleUrl&&!A.flags.metroHost&&!A.flags.metroPort&&!A.flags.remoteConfig&&!A.hadConnectionDefaults&&((S=A.explicitFlagKeys).has("daemonBaseUrl")||S.has("daemonTransport")||S.has("tenant")||S.has("sessionIsolation")||S.has("runId")||S.has("leaseId")||S.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 a=B.daemonBaseUrl;J=!B.verbose||B.json||a?null:function(e){try{let t=0,s=!1,o=setInterval(()=>{if(!s&&p.existsSync(e))try{let s=p.statSync(e);if(s.size<t&&(t=0),s.size<=t)return;let o=p.openSync(e,"r");try{let e=Buffer.alloc(s.size-t);p.readSync(o,e,0,e.length,t),t=s.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{p.closeSync(o)}}catch{}},200);return()=>{s=!0,clearInterval(o)}}catch{return null}}(O.logPath);let i=es(n(B,r),{transport:t.sendToDaemon});if("batch"===G){if(!e)throw new C("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,flags:_.lockPolicy&&void 0===E.platform?{...e.flags??{}}:sS(e.flags??{},{policyOverrides:B,configuredPlatform:B.platform,configuredSession:B.session,inheritedPlatform:B.platform})}));if(await sA({command:G,positionals:q,flags:{...B,batchSteps:t},client:i}))return}else if("runtime"===G)throw new C("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 sA({command:G,positionals:q,flags:B,client:i}))return;throw new C("INVALID_ARGS",`Unknown command: ${G}`)}catch(s){let e=L(s),t=N(e,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});if("close"===G&&"COMMAND_FAILED"===($=e).code&&($.details?.kind==="daemon_startup_failed"||$.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof $.details?.infoPath||"string"==typeof $.details?.lockPath))){B.json&&eP({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(B.json)eP({success:!1,error:t});else if(eT(t,{showDetails:B.verbose}),B.verbose)try{let e=O.logPath;if(p.existsSync(e)){let t=p.readFileSync(e,"utf8").split("\n"),s=t.slice(Math.max(0,t.length-200)).join("\n");s.trim().length>0&&process.stderr.write(`
458
+ `),process.exit(1));let{command:G,positionals:q}=R,K=new Set(R.providedFlags.map(e=>e.key));try{E=(_=s$({policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session})).lockPolicy?{...R.flags}:sx(R.flags,{policyOverrides:R.flags,configuredPlatform:R.flags.platform,configuredSession:R.flags.session}),O=H(E.stateDir),U=E.session??"default",w={command:G,explicitFlagKeys:K,stateDir:O.baseDir,session:U,remoteConfig:E.remoteConfig,hasResolvedSession:void 0!==E.session},B=(F="connect"===w.command||"connection"===w.command?null:function(e){let t=e.validateRemoteConfigHash??!0,s=e.remoteConfig?D({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,o=eX(e)??(e.allowActiveFallback?e8({stateDir:e.stateDir}):null);if(!o||s&&o.remoteConfigPath!==s)return null;if(t&&e2(o.remoteConfigPath)!==o.remoteConfigHash)throw new N("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:o.remoteConfigPath});let r=function(e,t){try{return I({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:{...r,remoteConfig:o.remoteConfigPath,daemonBaseUrl:o.daemon?.baseUrl??r.daemonBaseUrl,daemonTransport:o.daemon?.transport??r.daemonTransport,daemonServerMode:o.daemon?.serverMode??r.daemonServerMode,tenant:o.tenant,sessionIsolation:"tenant",runId:o.runId,leaseId:o.leaseId,leaseBackend:o.leaseBackend,session:o.session,platform:o.platform??r.platform,target:o.target??r.target}}}({stateDir:w.stateDir,session:w.session,remoteConfig:w.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!w.explicitFlagKeys.has("session")&&(!w.remoteConfig||"disconnect"===w.command||!w.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==w.command}))?function(e,t,s){let o={...e};for(let[e,r]of Object.entries(t))void 0!==r&&(s.has(e)||(o[e]=r));return o}(E,F.flags,K):E}catch(t){let e=L(C(t),{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});R.flags.json?eP({success:!1,error:e}):eT(e,{showDetails:R.flags.verbose}),process.exit(1);return}let J=null;try{let e;if("react-devtools"===G){let e=await sS(q,{flags:B,stateDir:O.baseDir,session:B.session??U,cwd:process.cwd(),env:process.env});process.exit(e);return}el({command:G,currentVersion:o,stateDir:O.baseDir,flags:B});let r=F?.runtime,n=(e,t)=>({session:e.session??U,requestId:s,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:_.lockPolicy,lockPlatform:_.defaultPlatform,cwd:process.cwd(),debug:!!e.verbose});if("batch"===G){if(q.length>0)throw new N("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let t="";if(e.steps)t=e.steps;else if(e.stepsFile)try{t=p.readFileSync(e.stepsFile,"utf8")}catch(s){let t=s instanceof Error?s.message:String(s);throw new N("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}return ei(t)}(E)}if(b=G,"auth"!==b&&"connection"!==b&&(B=(await t_({command:G,flags:B,stateDir:O.baseDir,env:process.env})).flags),B.remoteConfig&&(k=G,!sR.has(k))){let s=es(n(B,r),{transport:t.sendToDaemon}),o=await to({command:G,flags:B,client:s,runtime:r,batchSteps:e,forceRuntimePrepare:function(e){for(let t of sN)if(e.has(t))return!0;return!1}(K)});B=o.flags,r=o.runtime}A={command:G,flags:B,runtime:r,explicitFlagKeys:K,hadConnectionDefaults:!!F},!("open"===A.command&&!A.runtime&&!A.flags.bundleUrl&&!A.flags.metroHost&&!A.flags.metroPort&&!A.flags.remoteConfig&&!A.hadConnectionDefaults&&((S=A.explicitFlagKeys).has("daemonBaseUrl")||S.has("daemonTransport")||S.has("tenant")||S.has("sessionIsolation")||S.has("runId")||S.has("leaseId")||S.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 a=B.daemonBaseUrl;J=!B.verbose||B.json||a?null:function(e){try{let t=0,s=!1,o=setInterval(()=>{if(!s&&p.existsSync(e))try{let s=p.statSync(e);if(s.size<t&&(t=0),s.size<=t)return;let o=p.openSync(e,"r");try{let e=Buffer.alloc(s.size-t);p.readSync(o,e,0,e.length,t),t=s.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{p.closeSync(o)}}catch{}},200);return()=>{s=!0,clearInterval(o)}}catch{return null}}(O.logPath);let i=es(n(B,r),{transport:t.sendToDaemon});if("batch"===G){if(!e)throw new N("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,flags:_.lockPolicy&&void 0===E.platform?{...e.flags??{}}:sx(e.flags??{},{policyOverrides:B,configuredPlatform:B.platform,configuredSession:B.session,inheritedPlatform:B.platform})}));if(await sA({command:G,positionals:q,flags:{...B,batchSteps:t},client:i}))return}else if("runtime"===G)throw new N("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await sA({command:G,positionals:q,flags:B,client:i}))return;throw new N("INVALID_ARGS",`Unknown command: ${G}`)}catch(s){let e=C(s),t=L(e,{diagnosticId:P().diagnosticId,logPath:T({force:!0})??void 0});if("close"===G&&"COMMAND_FAILED"===($=e).code&&($.details?.kind==="daemon_startup_failed"||$.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof $.details?.infoPath||"string"==typeof $.details?.lockPath))){B.json&&eP({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(B.json)eP({success:!1,error:t});else if(eT(t,{showDetails:B.verbose}),B.verbose)try{let e=O.logPath;if(p.existsSync(e)){let t=p.readFileSync(e,"utf8").split("\n"),s=t.slice(Math.max(0,t.length-200)).join("\n");s.trim().length>0&&process.stderr.write(`
451
459
  [daemon log]
452
460
  ${s}
453
- `)}}catch{}J&&J(),process.exit(1)}finally{J&&J()}})}d(process.argv[1]??"").href===import.meta.url&&sR(process.argv.slice(2)).catch(e=>{eT(N(L(e)),{showDetails:!0}),process.exit(1)}),sR(process.argv.slice(2));
461
+ `)}}catch{}J&&J(),process.exit(1)}finally{J&&J()}})}d(process.argv[1]??"").href===import.meta.url&&s_(process.argv.slice(2)).catch(e=>{eT(L(C(e)),{showDetails:!0}),process.exit(1)}),s_(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-device",
3
- "version": "0.14.6",
3
+ "version": "0.14.7",
4
4
  "description": "Agent-driven CLI for mobile UI automation, network inspection, and performance diagnostics across iOS, Android, tvOS, and macOS.",
5
5
  "license": "MIT",
6
6
  "author": "Callstack",
@@ -34,6 +34,15 @@ agent-device react-devtools profile slow --limit 5
34
34
  agent-device react-devtools profile rerenders --limit 5
35
35
  ```
36
36
 
37
+ Remote iOS bridge order:
38
+
39
+ ```bash
40
+ agent-device open <bundle-id> --platform ios --relaunch
41
+ agent-device react-devtools start
42
+ agent-device open <bundle-id> --platform ios --relaunch
43
+ agent-device react-devtools wait --connected
44
+ ```
45
+
37
46
  Rules:
38
47
 
39
- Keep reads bounded with `--depth`/`find`, treat `@c` refs as reload-local, profile only the investigated interaction, and run the same command in remote Android sessions; the CLI manages the needed local service tunnel.
48
+ Keep reads bounded with `--depth`/`find`, treat `@c` refs as reload-local, profile only the investigated interaction, and run the same command in remote Android sessions; the CLI manages the needed local service tunnel. For remote iOS, relaunch after `react-devtools start` because React Native opens the legacy DevTools websocket during JavaScript startup.
@@ -1 +0,0 @@
1
- e9a4afcfa6fee4515b0dadacb7a92530d68ec4bb999aa0808651df5d41be78e0 agent-device-android-snapshot-helper-0.14.6.apk