agent-device 0.11.2 → 0.11.4

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.
@@ -1,42 +1,44 @@
1
- let e,t,r,a;import{__webpack_require__ as i}from"./1~rslib-runtime.js";import n,{createHash as o}from"node:crypto";import s,{existsSync as l,promises as d}from"node:fs";import u from"node:os";import c from"node:path";import f from"node:net";import{URL as p,fileURLToPath as m,pathToFileURL as h}from"node:url";import{spawn as w}from"node:child_process";import g from"node:http";import"node:https";import v from"node:dns/promises";import y from"node:fs/promises";import{TextDecoder as I}from"node:util";import{setTimeout as A}from"node:timers/promises";import{PNG as b}from"pngjs";import{readProcessCommand as S,isMacOsSettingSupported as _,normalizeTenantId as N,isAgentDeviceDaemonProcess as D,runCmdDetached as x,runCmdBackground as M,SETTINGS_INVALID_ARGS_MESSAGE as E,validateAndNormalizeBatchSteps as k,runCmd as O,resolveDeployResultTarget as L,displayLabel as C,asAppError as P,expandUserHomePath as R,withSuccessText as T,AppError as $,extractReadableText as F,getUnsupportedMacOsSettingMessage as U,whichCmd as V,buildSnapshotDisplayLines as G,runCmdStreaming as j,formatRole as B,normalizeError as q,resolveSessionIsolationMode as H,resolveUserPath as W,readVersion as z,getDiagnosticsMeta as J,runCmdSync as K,withDiagnosticTimer as X,successText as Y,findProjectRoot as Z,emitDiagnostic as Q,DEFAULT_BATCH_MAX_STEPS as ee,isProcessAlive as et,readProcessStartTime as er,withDiagnosticsScope as ea,resolveDaemonPaths as ei,flushDiagnosticsToSessionFile as en,resolveDaemonServerMode as eo,resolveInstallFromSourceResultTarget as es,parseSessionSurface as el,decodePng as ed,formatSnapshotLine as eu}from"./916.js";var ec={};i.r(ec),i.d(ec,{ensureAndroidEmulatorBooted:()=>av,listAndroidDevices:()=>af,waitForAndroidBoot:()=>ay});var ef={};i.r(ef),i.d(ef,{oI:()=>iE,X$:()=>ix,bV:()=>a6,NX:()=>iH,Mh:()=>r8,fK:()=>iP,w8:()=>iC,getAndroidAppState:()=>a2,K0:()=>iq,PW:()=>i$,V0:()=>iM,inferAndroidAppName:()=>a1,installAndroidApp:()=>id,installAndroidInstallablePathAndResolvePackageName:()=>il,listAndroidApps:()=>aY,pw:()=>ik,vU:()=>a4,gy:()=>a5,Nd:()=>iN,hF:()=>i5,$f:()=>iW,gh:()=>ij,reinstallAndroidApp:()=>iu,resolveAndroidApp:()=>aX,UB:()=>i9,VJ:()=>iR,m1:()=>iT,GZ:()=>iQ,kt:()=>iI,sP:()=>iD,wb:()=>iO,ac:()=>iz});var ep={};i.r(ep),i.d(ep,{prepareAndroidInstallArtifact:()=>aq});var em={};i.r(em),i.d(em,{hp:()=>sd,listAppleDevices:()=>su});var eh={};i.r(eh),i.d(eh,{TM:()=>oN,ensureBootedSimulator:()=>ng,installIosApp:()=>ox,installIosInstallablePath:()=>oE,listIosApps:()=>oP,L5:()=>oS,IJ:()=>o_,TJ:()=>oL,J7:()=>ok,reinstallIosApp:()=>oM,resolveIosApp:()=>ob,kc:()=>os,Cm:()=>oC,ap:()=>oO});var ew={};i.r(ew),i.d(ew,{prepareIosInstallArtifact:()=>nA});let eg=ev(process.env.AGENT_DEVICE_RETRY_LOGS);function ev(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let ey=2e4,eI=12e4,eA=1e4;class eb{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new eb(t,e)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return 0>=this.remainingMs(e)}}async function eS(e,t={},r={}){let a,i={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=i.maxAttempts;t+=1){if(r.signal?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),eN({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),eN(n),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,r,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*r*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),eN(l),await function(e,t){return new Promise(r=>{if(t?.aborted)return void r();let a=!1,i=()=>{a||(a=!0,t&&t.removeEventListener("abort",o),r())},n=setTimeout(i,e);function o(){clearTimeout(n),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,r.signal)}}let n={phase:r.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};if(r.onEvent?.(n),eN(n),a)throw a;throw new $("COMMAND_FAILED","retry failed")}async function e_(e,t={}){return eS(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eN(e){Q({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eg&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
- `)}let eD=new Set,ex=new Map,eM="request_canceled",eE="request canceled";function ek(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",a=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${a}`}function eO(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let r of e.keys()){if(t>=1e4)break;e.delete(r),t++}}(ex);let t=new AbortController;ex.set(e,t),eD.has(e)&&t.abort()}function eL(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let r of e){if(t>=1e4)break;e.delete(r),t++}}(eD),eD.add(e),ex.get(e)?.abort())}function eC(e){e&&(eD.delete(e),ex.delete(e))}function eP(e){return!!e&&eD.has(e)}function eR(e){if(e)return ex.get(e)?.signal}function eT(){return new $("COMMAND_FAILED",eE,{reason:eM})}function e$(e){return e instanceof $&&"COMMAND_FAILED"===e.code&&(e.details?.reason===eM||e.message===eE)}function eF(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}function eU(e){let t=e.error?P(e.error):null,r=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},n="string"==typeof i.message?i.message:void 0,o="string"==typeof i.stdout?i.stdout:void 0,s="string"==typeof i.stderr?i.stderr:void 0,l=i.boot&&"object"==typeof i.boot?i.boot:null,d=i.bootstatus&&"object"==typeof i.bootstatus?i.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,n,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===a&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function eV(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI consider increasing AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}let eG=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],ej=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function eB(e){return e?.trim()||void 0}function eq(e,t){for(let r of e){let e=eB(t[r]);if(e)return e}}function eH(e,t=process.env){return eB(e)??eq(eG,t)}function eW(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ez(e,t=process.env){let r=eB(e)??eq(ej,t);if(r)return eW(r)}function eJ(e,t={}){let r=eH(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eK(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eJ(t,{simulatorSetPath:e.simulatorSetPath})}function eX(e){return!(e instanceof $)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eY(e){let{port:t,endpoints:r,logPath:a,lastError:i}=e,n="Runner did not accept connection";return new $("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:a,lastError:i?String(i):void 0,reason:eU({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:eV("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eZ(e){var t,r;let a,{session:i,port:n,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=eU({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new $("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
1
+ let e,t,r,a;import{__webpack_require__ as i}from"./1~rslib-runtime.js";import n,{createHash as o}from"node:crypto";import s,{existsSync as l,promises as d}from"node:fs";import u from"node:os";import c from"node:path";import p from"node:net";import{URL as f,fileURLToPath as m,pathToFileURL as h}from"node:url";import{spawn as w}from"node:child_process";import g from"node:http";import"node:https";import y from"node:dns/promises";import v from"node:fs/promises";import{TextDecoder as I}from"node:util";import{setTimeout as A}from"node:timers/promises";import{PNG as b}from"pngjs";import{readProcessCommand as S,isMacOsSettingSupported as _,normalizeTenantId as N,isAgentDeviceDaemonProcess as D,runCmdDetached as x,runCmdBackground as k,SETTINGS_INVALID_ARGS_MESSAGE as M,validateAndNormalizeBatchSteps as E,runCmd as O,resolveDeployResultTarget as L,displayLabel as C,asAppError as P,expandUserHomePath as R,withSuccessText as T,AppError as $,extractReadableText as F,getUnsupportedMacOsSettingMessage as U,whichCmd as V,buildSnapshotDisplayLines as G,runCmdStreaming as j,formatRole as B,normalizeError as q,resolveSessionIsolationMode as H,resolveUserPath as W,readVersion as z,getDiagnosticsMeta as J,runCmdSync as K,withDiagnosticTimer as X,successText as Y,findProjectRoot as Z,emitDiagnostic as Q,DEFAULT_BATCH_MAX_STEPS as ee,isProcessAlive as et,readProcessStartTime as er,withDiagnosticsScope as ea,resolveDaemonPaths as ei,flushDiagnosticsToSessionFile as en,resolveDaemonServerMode as eo,resolveInstallFromSourceResultTarget as es,parseSessionSurface as el,decodePng as ed,formatSnapshotLine as eu}from"./916.js";var ec={};i.r(ec),i.d(ec,{ensureAndroidEmulatorBooted:()=>ay,listAndroidDevices:()=>ap,waitForAndroidBoot:()=>av});var ep={};i.r(ep),i.d(ep,{oI:()=>iP,X$:()=>iL,bV:()=>ir,NX:()=>iZ,Mh:()=>r8,fK:()=>iU,w8:()=>iF,getAndroidAppState:()=>a3,K0:()=>iY,PW:()=>iq,V0:()=>iC,inferAndroidAppName:()=>a2,installAndroidApp:()=>ih,installAndroidInstallablePathAndResolvePackageName:()=>im,listAndroidApps:()=>aZ,pw:()=>iR,vU:()=>a8,gy:()=>it,Nd:()=>iE,hF:()=>na,$f:()=>iQ,gh:()=>iK,reinstallAndroidApp:()=>iw,resolveAndroidApp:()=>aY,UB:()=>nn,VJ:()=>ij,m1:()=>iB,GZ:()=>i5,kt:()=>iN,sP:()=>iO,wb:()=>iT,ac:()=>i0});var ef={};i.r(ef),i.d(ef,{prepareAndroidInstallArtifact:()=>aq});var em={};i.r(em),i.d(em,{hp:()=>sw,listAppleDevices:()=>sg});var eh={};i.r(eh),i.d(eh,{TM:()=>oL,ensureBootedSimulator:()=>n_,installIosApp:()=>oP,installIosInstallablePath:()=>oT,listIosApps:()=>oG,L5:()=>oE,IJ:()=>oO,TJ:()=>oU,J7:()=>o$,reinstallIosApp:()=>oR,resolveIosApp:()=>oM,kc:()=>om,Cm:()=>oV,ap:()=>oF});var ew={};i.r(ew),i.d(ew,{prepareIosInstallArtifact:()=>nk});let eg=ey(process.env.AGENT_DEVICE_RETRY_LOGS);function ey(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let ev=2e4,eI=12e4,eA=1e4;class eb{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new eb(t,e)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return 0>=this.remainingMs(e)}}async function eS(e,t={},r={}){let a,i={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=i.maxAttempts;t+=1){if(r.signal?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),eN({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),eN(n),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,r,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*r*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),eN(l),await function(e,t){return new Promise(r=>{if(t?.aborted)return void r();let a=!1,i=()=>{a||(a=!0,t&&t.removeEventListener("abort",o),r())},n=setTimeout(i,e);function o(){clearTimeout(n),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,r.signal)}}let n={phase:r.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};if(r.onEvent?.(n),eN(n),a)throw a;throw new $("COMMAND_FAILED","retry failed")}async function e_(e,t={}){return eS(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eN(e){Q({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eg&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
+ `)}let eD=new Set,ex=new Map,ek="request_canceled",eM="request canceled";function eE(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",a=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${a}`}function eO(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let r of e.keys()){if(t>=1e4)break;e.delete(r),t++}}(ex);let t=new AbortController;ex.set(e,t),eD.has(e)&&t.abort()}function eL(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let r of e){if(t>=1e4)break;e.delete(r),t++}}(eD),eD.add(e),ex.get(e)?.abort())}function eC(e){e&&(eD.delete(e),ex.delete(e))}function eP(e){return!!e&&eD.has(e)}function eR(e){if(e)return ex.get(e)?.signal}function eT(){return new $("COMMAND_FAILED",eM,{reason:ek})}function e$(e){return e instanceof $&&"COMMAND_FAILED"===e.code&&(e.details?.reason===ek||e.message===eM)}function eF(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}function eU(e){let t=e.error?P(e.error):null,r=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},n="string"==typeof i.message?i.message:void 0,o="string"==typeof i.stdout?i.stdout:void 0,s="string"==typeof i.stderr?i.stderr:void 0,l=i.boot&&"object"==typeof i.boot?i.boot:null,d=i.bootstatus&&"object"==typeof i.bootstatus?i.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,n,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===a&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function eV(e){switch(e){case"IOS_BOOT_TIMEOUT":return"Retry simulator boot and inspect simctl bootstatus logs; in CI consider increasing AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS.";case"IOS_RUNNER_CONNECT_TIMEOUT":return"Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.";case"ANDROID_BOOT_TIMEOUT":return"Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.";case"ADB_TRANSPORT_UNAVAILABLE":return"Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.";case"CI_RESOURCE_STARVATION_SUSPECTED":return"CI machine may be resource constrained; reduce parallel jobs or use a larger runner.";case"IOS_TOOL_MISSING":return"Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.";case"BOOT_COMMAND_FAILED":return"Inspect command stderr/stdout for the failing boot phase and retry after environment validation.";default:return"Retry once and inspect verbose logs for the failing phase."}}let eG=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],ej=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function eB(e){return e?.trim()||void 0}function eq(e,t){for(let r of e){let e=eB(t[r]);if(e)return e}}function eH(e,t=process.env){return eB(e)??eq(eG,t)}function eW(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ez(e,t=process.env){let r=eB(e)??eq(ej,t);if(r)return eW(r)}function eJ(e,t={}){let r=eH(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eK(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eJ(t,{simulatorSetPath:e.simulatorSetPath})}function eX(e){return!(e instanceof $)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eY(e){let{port:t,endpoints:r,logPath:a,lastError:i}=e,n="Runner did not accept connection";return new $("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:a,lastError:i?String(i):void 0,reason:eU({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:eV("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eZ(e){var t,r;let a,{session:i,port:n,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=eU({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new $("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
3
3
  ${t}
4
- ${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":eV("IOS_RUNNER_CONNECT_TIMEOUT"))})}function eQ(e){if(eP(e))throw eT()}let e0=eF(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),e1=eF(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),e2=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),e3=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),e4=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),e8=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),e5=eF(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),e6=eF(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function e9(e,t,r,a,i=e0,n,o){let s=eb.fromTimeoutMs(i),l=await e7(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/e2));try{return await eS(async({deadline:s})=>{if(s?.isExpired())throw new $("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eZ({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await e7(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new $("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await te(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(e8,e),o)}catch(e){if(o?.aborted||e$(e))throw eT();d=e}throw new $("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:e3,maxDelayMs:e4,jitter:.2,shouldRetry:eX},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||e$(e))throw eT();d||(d=e)}if(o?.aborted)throw eT();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw eY({port:t,endpoints:l,logPath:a,lastError:d});let n=await tr(e,t,r,i);return new Response(n.body,{status:n.status})}throw eY({port:t,endpoints:l,logPath:a,lastError:d})}async function e7(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await tt(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function te(e,t,r,a){let i,n=new AbortController,o=setTimeout(()=>n.abort(),r);a&&(a.aborted?(clearTimeout(o),n.abort()):(i=()=>n.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function tt(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(e5,t)):e5,a=c.join(u.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),i=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==i.exitCode||!s.existsSync(a))return null;let n=JSON.parse(s.readFileSync(a,"utf8"));if(n.info?.outcome&&"success"!==n.info.outcome)return null;let o=(n.result?.connectionProperties?.tunnelIPAddress??n.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{tn(a)}}async function tr(e,t,r,a){let i=JSON.stringify(r),n=eK(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",i,`http://127.0.0.1:${t}/command`]),o=await O("xcrun",n,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=eU({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new $("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:eV(e)})}return{status:200,body:s}}async function ta(){return await new Promise((e,t)=>{let r=f.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();if("object"==typeof a&&a?.port){let t=a.port;r.close(()=>e(t))}else r.close(()=>t(new $("COMMAND_FAILED","Failed to allocate port")))}),r.on("error",t)})}function ti(e,t,r,a){t&&s.appendFile(t,e,()=>{}),r&&s.appendFile(r,e,()=>{}),a&&process.stderr.write(e)}function tn(e){try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}async function to(e,t,r){let a=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,a),a.finally(()=>{e.get(t)===a&&e.delete(t)})}function ts(e){return"apple"===e||"ios"===e||"macos"===e}function tl(e,t){return!t||("apple"===t?ts(e):e===t)}function td(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function tu(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>tl(e.platform,t.platform))),t.target&&(a=a.filter(e=>(e.target??"mobile")===t.target)),t.udid){let e=a.find(e=>e.id===t.udid&&ts(e.platform));if(!e)throw new $("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=a.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new $("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),r=a.find(t=>i(t.name)===e);if(!r)throw new $("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){var n;let e=r.simulatorSetPath;if(e&&(!(n=t.platform)||"apple"===n||"ios"===n))throw new $("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
5
- xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let tc=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tf(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new $("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!s.existsSync(e))throw new $("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==K("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await O("codesign",["--remove-signature",e],{allowFailure:!0});try{await O("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof $?a:new $("COMMAND_FAILED",String(a));throw new $("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let tp=c.join(u.homedir(),".agent-device","ios-runner"),tm=new Map,th=new Set;function tw(e){return e?.trim()??""}function tg(e=process.env){return tw(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tw(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tv(e=process.env){let t=tw(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tg(e)}.uitests`}let ty=function(e=process.env){let t=tg(e),r=tv(e);return Array.from(new Set([tw(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function tI(e,t){var r;let a,i=(r=e,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?c.resolve(a):"macos"===r.platform?c.join(tp,"derived","macos"):"simulator"===r.kind?c.join(tp,"derived"):c.join(tp,"derived",r.kind)),n=function(){let e=c.dirname(m(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=c.join(t,"package.json");if(s.existsSync(e))return t;t=c.dirname(t)}return e}();return await to(tm,i,async()=>{ev(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(tL("clean","forced_clean",{derived:i}),tO(i),tA(i));let r=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:i,projectRoot:n,findXctestrun:t=>tS(t,e),xctestrunReferencesProjectRoot:tN,resolveExistingXctestrunProductPaths:tC});if("reuse_ready"!==r.reason&&tL("rebuild",r.reason,{derived:i,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await tf(e,r.productPaths,r.xctestrunPath),tL("reuse","reuse_ready",{derived:i,xctestrunPath:r.xctestrunPath}),r.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof $))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tc.has(t)}(e))throw e;tL("rebuild","repair_failed",{derived:i,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(tO(i),tA(i));let a=c.join(n,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!s.existsSync(a))throw new $("COMMAND_FAILED","iOS runner project not found",{projectPath:a});await tx(e,a,i,t);let o=tS(i,e);if(!o)throw new $("COMMAND_FAILED","Failed to locate .xctestrun after build");let l=tC(o);if(!l)throw new $("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await tf(e,l,o),tL("build","built_new",{derived:i,xctestrunPath:o}),o})}function tA(e){try{if(!s.existsSync(e))return;if("derived"!==c.basename(e))return void s.rmSync(e,{recursive:!0,force:!0});for(let r of s.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tb.has(t)&&s.rmSync(c.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let tb=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tS(e,t){if(!s.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of s.readdirSync(e,{withFileTypes:!0})){let i=c.join(e,t.name);if(t.isDirectory()){a.push(i);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=s.statSync(i);r.push({path:i,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=t_(r.path,t)-t_(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function t_(e,t){var r;let a=0,i=e.toLowerCase();c.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${c.sep}macos${c.sep}`)&&(a-=5e3);let n="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return n.preferred.length>0&&(n.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),n.disallowed.some(e=>i.includes(e))&&(a-=2500),a}function tN(e,t){try{let r=s.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(s.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}}async function tD(e,t,r){let a,i=c.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=c.join(i,`AgentDeviceRunner.env.${n}.json`),l=c.join(i,`AgentDeviceRunner.env.${n}.xctestrun`),d=await O("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new $("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new $("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},f=a.TestConfigurations;if(Array.isArray(f))for(let e of f){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);s.writeFileSync(o,JSON.stringify(a,null,2));let p=await O("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==p.exitCode)throw new $("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:p.stderr});return{xctestrunPath:l,jsonPath:o}}async function tx(e,t,r,a){let i=function(e=process.env){let t=tg(e),r=tv(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await j("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tk(e),"1","-destination",(s=e,l=tM(s),"macOS"===l?`platform=macOS,arch=${tE()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{th.add(e),e.on("close",()=>{th.delete(e)})},onStdoutChunk:e=>{ti(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{ti(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof $?n:new $("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
6
- ${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new $("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:i})}}function tM(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function tE(){return"arm64"===process.arch?"arm64":"x86_64"}function tk(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function tO(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return ev(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new $("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:"Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or set AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN=1 if you trust this path."})}function tL(e,t,r){Q({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}function tC(e){let t=function(e){let t=function(e){try{let t=K("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=s.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=c.dirname(e),a=new Set,i=new Set,n=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),n=c.join(r,t);if(!s.existsSync(n))return null;a.add(n);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&i.add(c.join(r,o));continue}e.startsWith("__TESTHOST__/")&&n.push(e.slice(13))}for(let e of n){let t=Array.from(i).find(t=>s.existsSync(c.join(t,e)));if(!t)return null;a.add(c.join(t,e))}return Array.from(a)}let tP=new Map,tR=new Map;async function tT(e,t){return await to(tR,e.id,async()=>{var r;let a,i=tP.get(e.id);if(i){if(function(e){return!!e&&et(e)}(i.child.pid))return i;await tU(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():tq(r)),await t$(e);let n=await tI(e,t),o=await ta(),{xctestrunPath:s,jsonPath:l}=await tD(n,{AGENT_DEVICE_RUNNER_PORT:String(o)},`session-${e.id}-${o}`),{child:d,wait:u}=M("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",tk(e),"1","-destination-timeout",String(e6),"-xctestrun",s,"-destination","macOS"===(a=tM(e))?`platform=macOS,arch=${tE()}`:"simulator"===e.kind?`platform=${a} Simulator,id=${e.id}`:`platform=${a},id=${e.id}`],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(o)},detached:!0});d.stdout?.on("data",e=>{ti(e,t.logPath,t.traceLogPath,t.verbose)}),d.stderr?.on("data",e=>{ti(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${o}:${Date.now()}`,device:e,deviceId:e.id,port:o,xctestrunPath:s,jsonPath:l,testPromise:u,child:d,ready:!1};return tP.set(e.id,c),c})}async function t$(e){if("simulator"===e.kind)for(let t of ty){let r=await O("xcrun",eK(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
7
- ${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function tF(e){await to(tR,e.deviceId,async()=>{await tU(e.deviceId,e)})}async function tU(e,t){let r=t??tP.get(e);if(r){try{await e9(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await tB(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await tB(r.child.pid,"SIGKILL"),tn(r.xctestrunPath),tn(r.jsonPath),tP.get(e)===r&&tP.delete(e)}}async function tV(e){await to(tR,e,async()=>{await tU(e)})}async function tG(){let e=Array.from(tP.values()),t=Array.from(th);await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGKILL"),th.delete(e)}))}async function tj(){await tG();let e=Array.from(tP.keys());await Promise.allSettled(e.map(async e=>{await tV(e)}));let t=Array.from(th);await Promise.allSettled(t.map(async e=>{try{await tB(e.pid,"SIGTERM"),await tB(e.pid,"SIGKILL")}finally{th.delete(e)}}))}async function tB(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await O("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function tq(e){await O("xcrun",eK(e,["bootstatus",e.id,"-b"]),{timeoutMs:e0})}async function tH(e,t,r,a,i,n){let o=await e9(e,t.port,r,a,i,t,n);return await tW(o,t,a)}async function tW(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new $("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new $("string"==typeof i.error?.code&&i.error.code.trim().length>0?i.error.code:"COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tz(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new $("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(eQ(r.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?e_(()=>(eQ(r.requestId),tJ(e,t,r)),{shouldRetry:e=>{eQ(r.requestId);if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.message??""}`.toLowerCase();return!(t.includes("xcodebuild exited early")||t.includes("device is busy")&&t.includes("connecting"))&&!!(t.includes("runner did not accept connection")||t.includes("fetch failed")||t.includes("econnrefused")||t.includes("socket hang up"))}}):tJ(e,t,r)}async function tJ(e,t,r={}){let a;eQ(r.requestId);let i=eR(r.requestId);try{let n=(a=await tT(e,r)).ready?e1:e0;return await tH(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof $?o:new $("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eX(n)&&a?.ready){eQ(r.requestId),a?await tF(a):await tV(e.id),a=await tT(e,r);let n=await e9(a.device,a.port,t,r.logPath,e0,void 0,i);return await tW(n,a,r.logPath)}throw o}}function tK(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function tX(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tY=/^-?\d+(\.\d+)?$/,tZ=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tQ=new Map([["--count","count"],["--pause-ms","pauseMs"]]),t0=new Map([["--delay-ms","delayMs"]]);function t1(e){return"click"===e||"press"===e}function t2(e){return"type"===e||"fill"===e}function t3(e){let t=e.trim();return t.startsWith("@")||tY.test(t)?t:JSON.stringify(t)}function t4(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function t8(e,t){let r=t.flags??{};if(t1(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("swipe"===t.command){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern);return}t2(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function t5(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",t4(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",t4(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",t4(t.launchUrl)))}function t6(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(t4(r)),a))e.push(t3(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function t9(e,t){let r=[],a={},i=t1(e)?tZ:"swipe"===e?tQ:t2(e)?t0:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(t1(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(t1(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=re(t[n+1]);if(null!==e){a[s]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function t7(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=re(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function re(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function rt(e,t){for(let r of t.positionals??[])e.push(t3(r));t.flags?.relaunch&&e.push("--relaunch"),t5(e,t.runtime)}class rr{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=rr.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:f,snapshotDepth:p,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:v,noRecord:y,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:M,pauseMs:E,pattern:k}=e;return{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:f,snapshotDepth:p,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:v,noRecord:y,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:M,pauseMs:E,pattern:k}}(t.flags),result:t.result}),Q({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=c.dirname(t);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),i=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${a}"${i} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(t1(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(t3(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(t3(a)),t8(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(t3(r)),t8(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(t3(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(t3(a)),i&&t.push(t3(i)),t8(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(t3(r)),t.push(t3(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(t3(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",t3(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t3(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return rt(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(t4(r)),t5(t,e.flags),t.join(" ")}if("record"===e.command)return t6(t,e),t.join(" ");for(let r of e.positionals??[])t.push(t3(r));return t8(t,e),t.join(" ")}(n));return`${r.join("\n")}
4
+ ${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":eV("IOS_RUNNER_CONNECT_TIMEOUT"))})}function eQ(e){if(eP(e))throw eT()}let e0=eF(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),e1=eF(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),e2=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),e3=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),e4=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),e8=eF(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),e5=eF(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),e6=eF(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function e9(e,t,r,a,i=e0,n,o){let s=eb.fromTimeoutMs(i),l=await e7(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/e2));try{return await eS(async({deadline:s})=>{if(s?.isExpired())throw new $("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eZ({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await e7(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new $("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await te(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(e8,e),o)}catch(e){if(o?.aborted||e$(e))throw eT();d=e}throw new $("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:e3,maxDelayMs:e4,jitter:.2,shouldRetry:eX},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||e$(e))throw eT();d||(d=e)}if(o?.aborted)throw eT();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw eY({port:t,endpoints:l,logPath:a,lastError:d});let n=await tr(e,t,r,i);return new Response(n.body,{status:n.status})}throw eY({port:t,endpoints:l,logPath:a,lastError:d})}async function e7(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await tt(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function te(e,t,r,a){let i,n=new AbortController,o=setTimeout(()=>n.abort(),r);a&&(a.aborted?(clearTimeout(o),n.abort()):(i=()=>n.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function tt(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(e5,t)):e5,a=c.join(u.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),i=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==i.exitCode||!s.existsSync(a))return null;let n=JSON.parse(s.readFileSync(a,"utf8"));if(n.info?.outcome&&"success"!==n.info.outcome)return null;let o=(n.result?.connectionProperties?.tunnelIPAddress??n.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{tn(a)}}async function tr(e,t,r,a){let i=JSON.stringify(r),n=eK(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",i,`http://127.0.0.1:${t}/command`]),o=await O("xcrun",n,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=eU({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new $("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:eV(e)})}return{status:200,body:s}}async function ta(){return await new Promise((e,t)=>{let r=p.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();if("object"==typeof a&&a?.port){let t=a.port;r.close(()=>e(t))}else r.close(()=>t(new $("COMMAND_FAILED","Failed to allocate port")))}),r.on("error",t)})}function ti(e,t,r,a){t&&s.appendFile(t,e,()=>{}),r&&s.appendFile(r,e,()=>{}),a&&process.stderr.write(e)}function tn(e){try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}async function to(e,t,r){let a=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,a),a.finally(()=>{e.get(t)===a&&e.delete(t)})}function ts(e){return"apple"===e||"ios"===e||"macos"===e}function tl(e,t){return!t||("apple"===t?ts(e):e===t)}function td(e){let{simulatorSetPath:t,platform:r,target:a}=e;if(t&&"macos"!==r&&"desktop"!==a)return t}async function tu(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>tl(e.platform,t.platform))),t.target&&(a=a.filter(e=>(e.target??"mobile")===t.target)),t.udid){let e=a.find(e=>e.id===t.udid&&ts(e.platform));if(!e)throw new $("DEVICE_NOT_FOUND",`No Apple device with UDID ${t.udid}`);return e}if(t.serial){let e=a.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new $("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),r=a.find(t=>i(t.name)===e);if(!r)throw new $("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){var n;let e=r.simulatorSetPath;if(e&&(!(n=t.platform)||"apple"===n||"ios"===n))throw new $("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
5
+ xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}let o=a.filter(e=>"device"!==e.kind);o.length>0&&(a=o);let s=a.filter(e=>e.booted);return 1===s.length?s[0]:s[0]??a[0]}let tc=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tp(e,t,r){if("macos"!==e.platform)return;if(0===t.length)throw new $("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:r});let a=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of a)if(!s.existsSync(e))throw new $("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:r});for(let e of a)if(0!==K("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await O("codesign",["--remove-signature",e],{allowFailure:!0});try{await O("codesign",["--force","--sign","-",e])}catch(a){let t=a instanceof $?a:new $("COMMAND_FAILED",String(a));throw new $("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:r,error:t.message,details:t.details})}}}let tf=c.join(u.homedir(),".agent-device","ios-runner"),tm=new Map,th=new Set;function tw(e){return e?.trim()??""}function tg(e=process.env){return tw(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tw(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function ty(e=process.env){let t=tw(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tg(e)}.uitests`}let tv=function(e=process.env){let t=tg(e),r=ty(e);return Array.from(new Set([tw(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function tI(e,t){var r;let a,i=(r=e,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?c.resolve(a):"macos"===r.platform?c.join(tf,"derived","macos"):"simulator"===r.kind?c.join(tf,"derived"):c.join(tf,"derived",r.kind)),n=function(){let e=c.dirname(m(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=c.join(t,"package.json");if(s.existsSync(e))return t;t=c.dirname(t)}return e}();return await to(tm,i,async()=>{ey(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(tL("clean","forced_clean",{derived:i}),tO(i),tA(i));let r=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let r=e.resolveExistingXctestrunProductPaths(t);return r?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:r}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:r}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:i,projectRoot:n,findXctestrun:t=>tS(t,e),xctestrunReferencesProjectRoot:tN,resolveExistingXctestrunProductPaths:tC});if("reuse_ready"!==r.reason&&tL("rebuild",r.reason,{derived:i,xctestrunPath:r.xctestrunPath}),"reuse_ready"===r.reason)try{return await tp(e,r.productPaths,r.xctestrunPath),tL("reuse","reuse_ready",{derived:i,xctestrunPath:r.xctestrunPath}),r.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof $))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tc.has(t)}(e))throw e;tL("rebuild","repair_failed",{derived:i,xctestrunPath:r.xctestrunPath})}r.xctestrunPath&&(tO(i),tA(i));let a=c.join(n,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!s.existsSync(a))throw new $("COMMAND_FAILED","iOS runner project not found",{projectPath:a});await tx(e,a,i,t);let o=tS(i,e);if(!o)throw new $("COMMAND_FAILED","Failed to locate .xctestrun after build");let l=tC(o);if(!l)throw new $("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:o});return await tp(e,l,o),tL("build","built_new",{derived:i,xctestrunPath:o}),o})}function tA(e){try{if(!s.existsSync(e))return;if("derived"!==c.basename(e))return void s.rmSync(e,{recursive:!0,force:!0});for(let r of s.readdirSync(e,{withFileTypes:!0})){var t;t=r.name,tb.has(t)&&s.rmSync(c.join(e,r.name),{recursive:!0,force:!0})}}catch{}}let tb=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tS(e,t){if(!s.existsSync(e))return null;let r=[],a=[e];for(;a.length>0;){let e=a.pop();for(let t of s.readdirSync(e,{withFileTypes:!0})){let i=c.join(e,t.name);if(t.isDirectory()){a.push(i);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=s.statSync(i);r.push({path:i,mtimeMs:e.mtimeMs})}catch{}}}return 0===r.length?null:(r.sort((e,r)=>{if(t){let a=t_(r.path,t)-t_(e.path,t);if(0!==a)return a}return r.mtimeMs-e.mtimeMs||e.path.localeCompare(r.path)}),r[0]?.path??null)}function t_(e,t){var r;let a=0,i=e.toLowerCase();c.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${c.sep}macos${c.sep}`)&&(a-=5e3);let n="macos"===(r=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===r.target?"simulator"===r.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===r.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return n.preferred.length>0&&(n.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),n.disallowed.some(e=>i.includes(e))&&(a-=2500),a}function tN(e,t){try{let r=s.readFileSync(e,"utf8"),a=new Set([t]);try{a.add(s.realpathSync(t))}catch{}for(let e of a)if(r.includes(e))return!0;return!1}catch{return!1}}async function tD(e,t,r){let a,i=c.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),o=c.join(i,`AgentDeviceRunner.env.${n}.json`),l=c.join(i,`AgentDeviceRunner.env.${n}.xctestrun`),d=await O("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new $("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new $("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},p=a.TestConfigurations;if(Array.isArray(p))for(let e of p){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);s.writeFileSync(o,JSON.stringify(a,null,2));let f=await O("plutil",["-convert","xml1","-o",l,o],{allowFailure:!0});if(0!==f.exitCode)throw new $("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:o}}async function tx(e,t,r,a){let i=function(e=process.env){let t=tg(e),r=ty(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),n=function(e=process.env,t=!1,r="ios"){if("macos"===r)return["CODE_SIGNING_ALLOWED=NO","CODE_SIGNING_REQUIRED=NO","CODE_SIGN_IDENTITY=","DEVELOPMENT_TEAM="];if(!t)return[];let a=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",n=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",o=["CODE_SIGN_STYLE=Automatic"];return a&&o.push(`DEVELOPMENT_TEAM=${a}`),i&&o.push(`CODE_SIGN_IDENTITY=${i}`),n&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${n}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var s;let l;await j("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",tE(e),"1","-destination",(s=e,l=tk(s),"macOS"===l?`platform=macOS,arch=${tM()}`:"simulator"===s.kind?`platform=${l} Simulator,id=${s.id}`:`generic/platform=${l}`),"-derivedDataPath",r,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...n],{detached:!0,onSpawn:e=>{th.add(e),e.on("close",()=>{th.delete(e)})},onStdoutChunk:e=>{ti(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{ti(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(n){let e,t,r=n instanceof $?n:new $("COMMAND_FAILED",String(n)),i=(e=r.details?JSON.stringify(r.details):"",(t=`${r.message}
6
+ ${e}`.toLowerCase()).includes("failed registering bundle identifier")||t.includes("app identifier")&&t.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":t.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":t.includes("no profiles for")||t.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":t.includes("code signing")?"Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.":void 0);throw new $("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:r.message,details:r.details,logPath:a.logPath,hint:i})}}function tk(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"macos"===e.platform?"macOS":"macos"===(t=e.target)||"desktop"===t?"macOS":"tv"===t?"tvOS":"iOS"}function tM(){return"arm64"===process.arch?"arm64":"x86_64"}function tE(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function tO(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return ey(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new $("COMMAND_FAILED","Refusing to clean AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH automatically",{derivedPath:e,hint:"Unset AGENT_DEVICE_IOS_CLEAN_DERIVED, or set AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN=1 if you trust this path."})}function tL(e,t,r){Q({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...r}})}function tC(e){let t=function(e){let t=function(e){try{let t=K("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==t.exitCode||!t.stdout.trim())return null;return JSON.parse(t.stdout)}catch{return null}}(e);if(t){var r,a=t;let e=new Set,i=t=>{if(t&&"object"==typeof t)for(let r of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),r=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){r.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&r.add(e)}return Array.from(r)}(t))e.add(r)};i(a);let n=a.TestConfigurations;if(Array.isArray(n))for(let e of n){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)i(e)}for(let e of Object.values(a))e&&"object"==typeof e&&"TestBundlePath"in e&&i(e);return Array.from(e)}if("darwin"===process.platform)return null;try{return r=s.readFileSync(e,"utf8"),Array.from(new Set([...["ProductPaths","DependentProductPaths"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<array>([\\s\\S]*?)</array>`,"g"),i=/<string>([\s\S]*?)<\/string>/g,n=new Set;for(;null!==(r=a.exec(e));){let e,t=r[1]??"";for(;null!==(e=i.exec(t));){let t=e[1]?.trim();t&&n.add(t)}}return Array.from(n)})(r,e)),...["TestHostPath","TestBundlePath","UITargetAppPath"].flatMap(e=>(function(e,t){let r,a=RegExp(`<key>${t}</key>\\s*<string>([\\s\\S]*?)</string>`,"g"),i=new Set;for(;null!==(r=a.exec(e));){let e=r[1]?.trim();e&&i.add(e)}return Array.from(i)})(r,e))]))}catch{return null}}(e);if(!t||0===t.length)return null;let r=c.dirname(e),a=new Set,i=new Set,n=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),n=c.join(r,t);if(!s.existsSync(n))return null;a.add(n);let o=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);o&&i.add(c.join(r,o));continue}e.startsWith("__TESTHOST__/")&&n.push(e.slice(13))}for(let e of n){let t=Array.from(i).find(t=>s.existsSync(c.join(t,e)));if(!t)return null;a.add(c.join(t,e))}return Array.from(a)}let tP=new Map,tR=new Map;async function tT(e,t){return await to(tR,e.id,async()=>{var r;let a,i=tP.get(e.id);if(i){if(function(e){return!!e&&et(e)}(i.child.pid))return i;await tU(e.id,i)}await ("simulator"!==(r=e).kind?Promise.resolve():tq(r)),await t$(e);let n=await tI(e,t),o=await ta(),{xctestrunPath:s,jsonPath:l}=await tD(n,{AGENT_DEVICE_RUNNER_PORT:String(o)},`session-${e.id}-${o}`),{child:d,wait:u}=k("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",tE(e),"1","-destination-timeout",String(e6),"-xctestrun",s,"-destination","macOS"===(a=tk(e))?`platform=macOS,arch=${tM()}`:"simulator"===e.kind?`platform=${a} Simulator,id=${e.id}`:`platform=${a},id=${e.id}`],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(o)},detached:!0});d.stdout?.on("data",e=>{ti(e,t.logPath,t.traceLogPath,t.verbose)}),d.stderr?.on("data",e=>{ti(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${o}:${Date.now()}`,device:e,deviceId:e.id,port:o,xctestrunPath:s,jsonPath:l,testPromise:u,child:d,ready:!1};return tP.set(e.id,c),c})}async function t$(e){if("simulator"===e.kind)for(let t of tv){let r=await O("xcrun",eK(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==r.exitCode){let e=`${r.stdout}
7
+ ${r.stderr}`.toLowerCase();if(!e.includes("not installed")&&!e.includes("found nothing")&&!e.includes("no such file")&&!e.includes("invalid device")&&!e.includes("could not find"))continue}}}async function tF(e){await to(tR,e.deviceId,async()=>{await tU(e.deviceId,e)})}async function tU(e,t){let r=t??tP.get(e);if(r){try{await e9(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await tB(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await tB(r.child.pid,"SIGKILL"),tn(r.xctestrunPath),tn(r.jsonPath),tP.get(e)===r&&tP.delete(e)}}async function tV(e){await to(tR,e,async()=>{await tU(e)})}async function tG(){let e=Array.from(tP.values()),t=Array.from(th);await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await tB(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await tB(e.pid,"SIGKILL"),th.delete(e)}))}async function tj(){await tG();let e=Array.from(tP.keys());await Promise.allSettled(e.map(async e=>{await tV(e)}));let t=Array.from(th);await Promise.allSettled(t.map(async e=>{try{await tB(e.pid,"SIGTERM"),await tB(e.pid,"SIGKILL")}finally{th.delete(e)}}))}async function tB(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await O("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function tq(e){await O("xcrun",eK(e,["bootstatus",e.id,"-b"]),{timeoutMs:e0})}async function tH(e,t,r,a,i,n){let o=await e9(e,t.port,r,a,i,t,n);return await tW(o,t,a)}async function tW(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new $("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new $("string"==typeof i.error?.code&&i.error.code.trim().length>0?i.error.code:"COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tz(e,t,r={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new $("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(eQ(r.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?e_(()=>(eQ(r.requestId),tJ(e,t,r)),{shouldRetry:e=>{eQ(r.requestId);if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.message??""}`.toLowerCase();return!(t.includes("xcodebuild exited early")||t.includes("device is busy")&&t.includes("connecting"))&&!!(t.includes("runner did not accept connection")||t.includes("fetch failed")||t.includes("econnrefused")||t.includes("socket hang up"))}}):tJ(e,t,r)}async function tJ(e,t,r={}){let a;eQ(r.requestId);let i=eR(r.requestId);try{let n=(a=await tT(e,r)).ready?e1:e0;return await tH(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof $?o:new $("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eX(n)&&a?.ready){eQ(r.requestId),a?await tF(a):await tV(e.id),a=await tT(e,r);let n=await e9(a.device,a.port,t,r.logPath,e0,void 0,i);return await tW(n,a,r.logPath)}throw o}}function tK(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function tX(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tY=/^-?\d+(\.\d+)?$/,tZ=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tQ=new Map([["--count","count"],["--pause-ms","pauseMs"]]),t0=new Map([["--delay-ms","delayMs"]]);function t1(e){return"click"===e||"press"===e}function t2(e){return"type"===e||"fill"===e}function t3(e){let t=e.trim();return t.startsWith("@")||tY.test(t)?t:JSON.stringify(t)}function t4(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function t8(e,t){let r=t.flags??{};if(t1(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");let t=r.clickButton;t&&"primary"!==t&&e.push("--button",t);return}if("swipe"===t.command){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern);return}t2(t.command)&&"number"==typeof r.delayMs&&e.push("--delay-ms",String(r.delayMs))}function t5(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",t4(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",t4(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",t4(t.launchUrl)))}function t6(e,t){let[r,...a]=t.positionals??[];for(let t of(r&&e.push(t4(r)),a))e.push(t3(t));"number"==typeof t.flags?.fps&&e.push("--fps",String(t.flags.fps)),t.flags?.hideTouches&&e.push("--hide-touches")}function t9(e,t){let r=[],a={},i=t1(e)?tZ:"swipe"===e?tQ:t2(e)?t0:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(t1(e)&&"--double-tap"===o){a.doubleTap=!0;continue}if(t1(e)&&"--button"===o&&n+1<t.length){let e=t[n+1];("primary"===e||"secondary"===e||"middle"===e)&&(a.clickButton=e),n+=1;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=re(t[n+1]);if(null!==e){a[s]=e,n+=1;continue}}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function t7(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=re(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}function re(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}function rt(e,t){for(let r of t.positionals??[])e.push(t3(r));t.flags?.relaunch&&e.push("--relaunch"),t5(e,t.runtime)}class rr{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=rr.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,runtime:t.runtime,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:k,pauseMs:M,pattern:E}=e;return{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,screenshotFullscreen:w,relaunch:g,saveScript:y,noRecord:v,fps:I,hideTouches:A,count:b,intervalMs:S,delayMs:_,holdMs:N,jitterPx:D,doubleTap:x,clickButton:k,pauseMs:M,pattern:E}}(t.flags),result:t.result}),Q({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=c.dirname(t);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),i=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${a}"${i} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(t1(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(t3(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(t3(a)),t8(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(t3(r)),t8(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(t3(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(t3(a)),i&&t.push(t3(i)),t8(t,e),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(t3(r)),t.push(t3(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(t3(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",t3(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t3(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}if("open"===e.command)return rt(t,e),t.join(" ");if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(t4(r)),t5(t,e.flags),t.join(" ")}if("record"===e.command)return t6(t,e),t.join(" ");for(let r of e.positionals??[])t.push(t3(r));return t8(t,e),t.join(" ")}(n));return`${r.join("\n")}
8
8
  `}(e,this.buildOptimizedActions(e));s.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=rr.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return c.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return c.join(this.sessionsDir,rr.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return c.join(this.sessionsDir,rr.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return W(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return rr.expandHome(e.saveScriptPath);s.existsSync(this.sessionsDir)||s.mkdirSync(this.sessionsDir,{recursive:!0});let t=rr.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return c.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(t1(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(t1(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tK(r);if(a.length>0){t.push({...r,positionals:[e,a]});continue}}if("get"===r.command){let a=r.positionals?.[0];if("text"===a||"attrs"===a){t.push({...r,positionals:[a,e]});continue}}}if(t1(r.command)||"fill"===r.command||"get"===r.command){let a=r.result?.refLabel;"string"==typeof a&&a.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:a.trim()},result:{scope:a.trim()}})}t.push(r)}return t}}function ra(e,t){if(!e)return;let r=c.dirname(e);s.existsSync(r)||s.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:er(t)??void 0,command:S(t)??void 0};s.writeFileSync(e,`${JSON.stringify(a)}
9
9
  `)}function ri(e){if(e&&s.existsSync(e))try{s.unlinkSync(e)}catch{}}async function rn(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function ro(e){await new Promise(t=>setTimeout(t,e))}function rs(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",i=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))i(`${e}
10
- `)},flush:()=>{a&&(i(a),a="")}}}function rl(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function rd(e,t){let r=(await O("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function ru(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await rd(e,t);if(!d){await ro(1e3);continue}let u=w("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=rs(r,{redactionPatterns:a});o=rl(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&ra(i,u.pid);let f=await o;if(ri(i),n=void 0,o=void 0,l)break;0!==f.exitCode&&(s="failed"),await ro(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),ri(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await rn(o),n&&!n.killed&&n.kill("SIGKILL"),await rn(d),ri(i)}}}function rc(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`}async function rf(e,t,r,a){let i="active",n=w("log",["stream","--style","compact","--predicate",rc(e)],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}async function rp(e,t,r,a){let i="active",n=w("log",["stream","--style","compact","--predicate",rc(e)],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}async function rm(e,t,r,a){let i="active",n=w("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}function rh(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function rw(e){let t=c.dirname(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),function(e,t){if(s.existsSync(e)&&!(s.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;s.existsSync(t)&&(s.existsSync(a)&&s.unlinkSync(a),s.renameSync(t,a))}}(e,{maxBytes:rh("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rh("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rg(e,t,r,a){rw(r);let i=s.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await rm(e.id,i,n,a):await rf(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new $("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await ru(e.id,t,i,n,a)}if("macos"===e.platform)return await rp(t,i,n,a);throw i.end(),new $("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function rv(e){await e.stop(),await rn(e.wait)}async function ry(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await O("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await O("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await O("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await O("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await O("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rI(e){let t=c.dirname(e),r=c.basename(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),s.existsSync(e)?s.truncateSync(e,0):s.writeFileSync(e,"","utf8");let a=0;for(let e of s.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let i=e.slice(r.length+1);if(/^\d+$/.test(i))try{s.unlinkSync(c.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rA=new Map;function rb(e){let t=rA.get(e);if(t&&(clearTimeout(t.timer),rA.delete(e),t.deleteAfterDownload))try{s.rmSync(t.artifactPath,{force:!0})}catch{}}let rS=new Map;function r_(e,t){let r=rS.get(e);if(!r)throw new $("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rN(e){let t=rS.get(e);t&&(clearTimeout(t.timer),rS.delete(e),s.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rD(e){let t=await rx(e);await O("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=c.join(e.tempDir,t);if(!s.existsSync(r))throw new $("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rx(e){let t=await O("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new $("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new $("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rM),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new $("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new $("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new $("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new $("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new $("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await O("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new $("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rM(e){if(e.includes("\0"))throw new $("INVALID_ARGS",`Invalid archive entry: ${e}`);if(c.posix.isAbsolute(e))throw new $("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=c.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new $("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rE=eF(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rk(e,t){return new Promise((r,a)=>{let i,n=s.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,i&&clearTimeout(i),e){n.destroy(),s.rmSync(t,{force:!0}),a(e);return}r()}},c=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new $("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rE});o(e),n.destroy(e),u(e)},rE)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new $("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new $("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",u),n.on("finish",()=>u()),c(),e.pipe(n)})}async function rO(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new $("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new $("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new $("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let i=function(e){let t=e.trim(),r=c.basename(t);if(!r||"."===r||".."===r)throw new $("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),s.mkdtempSync(c.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=c.join(n,i);return await rk(e,t),{artifactPath:t,tempDir:n}}let t=c.join(n,"artifact.tar");await rk(e,t);let a=await rD({archivePath:t,tempDir:n,platform:"ios",expectedRootName:i});return s.rmSync(t,{force:!0}),{artifactPath:a,tempDir:n}}catch(e){throw s.rmSync(n,{recursive:!0,force:!0}),e}}let rL=new Set(["agent_device.command","agent-device.command"]),rC=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rP=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rR={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},rT=new Set([...rL,...rC,...rP,...Object.keys(rR)]);function r$(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rF(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rU(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rV(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rG(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rj(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rB(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=q(new $("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=q(new $(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=N(r.tenantId);if(!e){let e=q(new $("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:r$(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rq(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=c.isAbsolute(t)?t:c.resolve(t);try{e=await import(h(a).href)}catch(e){throw new $("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new $("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rH(e){let t=await rq(),{handleRequest:r,token:a}=e;return g.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rW(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rz(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rF(i,r$(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rF(i,r$(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rF(i,r$(a.id??null,-32600,"Invalid Request"),400);if(!rT.has(a.method))return void rF(i,r$(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rF(i,r$(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rL.has(e))return{token:rV(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(rC.has(e)){let e,a=rG(t,"platform");if("ios"!==a&&"android"!==a)throw new $("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rV(t,r),session:rG(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rG(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new $("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new $("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new $("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new $("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new $("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rj(t,"retentionMs")}}}if(rP.has(e)){let e=rG(t,"materializationId")?.trim();if(!e)throw new $("INVALID_ARGS","Invalid params: materializationId is required");return{token:rV(t,r),session:rG(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rG(t,"requestId"),materializationId:e}}}let a=rR[e];if(a)return{token:rV(t,r),session:rG(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rG(t,"tenantId")??rG(t,"tenant"),runId:rG(t,"runId"),leaseId:rG(t,"leaseId"),leaseTtlMs:rj(t,"ttlMs"),leaseBackend:rG(t,"backend")}};throw new $("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rL.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rF(i,r$(a.id??null,-32602,"Invalid params: command is required"),400);o=ek(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eO(o);let d=()=>{i.writableFinished||eL(o)};e.on("aborted",d),i.on("close",d);let u=await rB(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rF(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rF(i,{jsonrpc:"2.0",id:a.id??null,result:c});rF(i,r$(a.id??null,-32e3,c.error.message,c.error),rU(c.error.code))}catch(t){let e=q(t);rF(i,r$(a.id??null,-32e3,e.message,e),rU(e.code))}finally{eC(o)}})})}async function rW(e,t,r,a){try{var i;let o,s,l=rV({},e.headers),d=rJ(l,a);if(d){t.statusCode=rU(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rB(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rO(e),f=(i={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=n.randomUUID(),(s=setTimeout(()=>{rN(o)},3e5)).unref(),rS.set(o,{artifactPath:i.artifactPath,tempDir:i.tempDir,tenantId:i.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:f}))}catch(r){let e=q(r);t.statusCode=rU(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rz(e,t,r,a){let i=e.url?.slice("/upload/".length)??"";if(!i){t.statusCode=400,t.end("Missing artifact id");return}try{let n=rV({},e.headers),o=rJ(n,a);if(o){t.statusCode=rU(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await rB(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[i]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=rA.get(e);if(!r)throw new $("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Artifact belongs to a different tenant");if(!s.existsSync(r.artifactPath))throw rb(e),new $("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,l.tenantId),u=s.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=q(e);t.statusCode=rU(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rb(i)}),u.pipe(t)}catch(r){let e=q(r);t.statusCode=rU(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rJ(e,t){return t&&e!==t?q(new $("UNAUTHORIZED","Invalid token")):null}function rK(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rX(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rY(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new $("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rZ{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=rY(e.backend),r=N(e.tenantId);if(!r)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=rK(e.runId);if(!a)throw new $("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let i=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,a,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,i);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:n.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+i};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=rX(e.leaseId);if(!t)throw new $("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new $("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=rX(e.leaseId);if(!t)throw new $("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=rY(e.backend),r=N(e.tenantId);if(!r)throw new $("INVALID_ARGS","tenant isolation requires tenant id.");let a=rK(e.runId);if(!a)throw new $("INVALID_ARGS","tenant isolation requires run id.");let i=rX(e.leaseId);if(!i)throw new $("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new $("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new $("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new $("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new $("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=N(t),i=rK(r);if(t&&!a)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new $("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new $("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rQ=["emulator","platform-tools",c.join("cmdline-tools","latest","bin"),c.join("cmdline-tools","tools","bin")];function r0(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function r1(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||u.homedir();return r0([t??"",r??"",a?c.join(a,"Android","Sdk"):""])}async function r2(e){try{return await d.access(e,d.constants.X_OK),!0}catch{return!1}}async function r3(e=process.env){let t,r=[];for(let a of r1(e)){let e=[];for(let t of rQ){let r=c.join(a,t);await r2(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(c.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=r0([...r,...a]).join(c.delimiter)}function r4(e,t){return["-s",e.id,...t]}async function r8(){if(await r3(),!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH")}function r5(e,t){let r=`${e}
10
+ `)},flush:()=>{a&&(i(a),a="")}}}function rl(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function rd(e,t){let r=(await O("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function ru(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await rd(e,t);if(!d){await ro(1e3);continue}let u=w("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=rs(r,{redactionPatterns:a});o=rl(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&ra(i,u.pid);let p=await o;if(ri(i),n=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await ro(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),ri(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await rn(o),n&&!n.killed&&n.kill("SIGKILL"),await rn(d),ri(i)}}}function rc(e){return`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`}async function rp(e,t,r,a){let i="active",n=w("log",["stream","--style","compact","--predicate",rc(e)],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}async function rf(e,t,r,a){let i="active",n=w("log",["stream","--style","compact","--predicate",rc(e)],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"macos",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}async function rm(e,t,r,a){let i="active",n=w("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=rs(t,{redactionPatterns:r});"number"==typeof n.pid&&ra(a,n.pid);let s=rl(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),ri(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await rn(s),n.killed||n.kill("SIGKILL"),await rn(s),ri(a)}}}function rh(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function rw(e){let t=c.dirname(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),function(e,t){if(s.existsSync(e)&&!(s.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;s.existsSync(t)&&(s.existsSync(a)&&s.unlinkSync(a),s.renameSync(t,a))}}(e,{maxBytes:rh("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:rh("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function rg(e,t,r,a){rw(r);let i=s.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await rm(e.id,i,n,a):await rp(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new $("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await ru(e.id,t,i,n,a)}if("macos"===e.platform)return await rf(t,i,n,a);throw i.end(),new $("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function ry(e){await e.stop(),await rn(e.wait)}async function rv(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await O("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await O("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await O("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await O("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}if("macos"===e.platform)try{let e=await O("log",["help"],{allowFailure:!0});r.logAvailable=0===e.exitCode}catch{r.logAvailable=!1}return{checks:r,notes:a}}function rI(e){let t=c.dirname(e),r=c.basename(e);s.existsSync(t)||s.mkdirSync(t,{recursive:!0}),s.existsSync(e)?s.truncateSync(e,0):s.writeFileSync(e,"","utf8");let a=0;for(let e of s.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let i=e.slice(r.length+1);if(/^\d+$/.test(i))try{s.unlinkSync(c.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let rA=new Map;function rb(e){let t=rA.get(e);if(t&&(clearTimeout(t.timer),rA.delete(e),t.deleteAfterDownload))try{s.rmSync(t.artifactPath,{force:!0})}catch{}}let rS=new Map;function r_(e,t){let r=rS.get(e);if(!r)throw new $("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function rN(e){let t=rS.get(e);t&&(clearTimeout(t.timer),rS.delete(e),s.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function rD(e){let t=await rx(e);await O("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=c.join(e.tempDir,t);if(!s.existsSync(r))throw new $("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function rx(e){let t=await O("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new $("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new $("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(rk),i=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new $("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new $("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new $("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===i||e.startsWith(`${i}/`)))throw new $("INVALID_ARGS",`Uploaded archive must contain a top-level "${i}" bundle`);for(let e of a){var n=e,o=i;if(n!==o&&!n.startsWith(`${o}/`))throw new $("INVALID_ARGS",`Archive entry must stay inside top-level "${o}" bundle: ${n}`)}for(let t of(await O("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean))if("l"===t[0]||"h"===t[0])throw new $("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links");return i}function rk(e){if(e.includes("\0"))throw new $("INVALID_ARGS",`Invalid archive entry: ${e}`);if(c.posix.isAbsolute(e))throw new $("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=c.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new $("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t}let rM=eF(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function rE(e,t){return new Promise((r,a)=>{let i,n=s.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},l=!1,d=0,u=e=>{if(!l){if(l=!0,i&&clearTimeout(i),e){n.destroy(),s.rmSync(t,{force:!0}),a(e);return}r()}},c=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new $("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:rM});o(e),n.destroy(e),u(e)},rM)};e.on("data",e=>{c();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((d+=t)>0x80000000){let e=new $("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),u(e)}}),e.on("error",u),e.on("aborted",()=>{u(new $("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",u),n.on("finish",()=>u()),c(),e.pipe(n)})}async function rO(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new $("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new $("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new $("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let i=function(e){let t=e.trim(),r=c.basename(t);if(!r||"."===r||".."===r)throw new $("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),s.mkdtempSync(c.join(u.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=c.join(n,i);return await rE(e,t),{artifactPath:t,tempDir:n}}let t=c.join(n,"artifact.tar");await rE(e,t);let a=await rD({archivePath:t,tempDir:n,platform:"ios",expectedRootName:i});return s.rmSync(t,{force:!0}),{artifactPath:a,tempDir:n}}catch(e){throw s.rmSync(n,{recursive:!0,force:!0}),e}}let rL=new Set(["agent_device.command","agent-device.command"]),rC=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),rP=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),rR={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},rT=new Set([...rL,...rC,...rP,...Object.keys(rR)]);function r$(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function rF(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function rU(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function rV(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function rG(e,t){let r=e[t];return"string"==typeof r?r:void 0}function rj(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function rB(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=q(new $("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=q(new $(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:r$(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=N(r.tenantId);if(!e){let e=q(new $("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:r$(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function rq(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=c.isAbsolute(t)?t:c.resolve(t);try{e=await import(h(a).href)}catch(e){throw new $("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let i=e[r];if("function"!=typeof i)throw new $("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return i}async function rH(e){let t=await rq(),{handleRequest:r,token:a}=e;return g.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rW(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rz(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||rF(i,r$(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{rF(i,r$(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void rF(i,r$(a.id??null,-32600,"Invalid Request"),400);if(!rT.has(a.method))return void rF(i,r$(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void rF(i,r$(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(rL.has(e))return{token:rV(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(rC.has(e)){let e,a=rG(t,"platform");if("ios"!==a&&"android"!==a)throw new $("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:rV(t,r),session:rG(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:rG(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new $("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new $("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new $("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new $("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new $("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:rj(t,"retentionMs")}}}if(rP.has(e)){let e=rG(t,"materializationId")?.trim();if(!e)throw new $("INVALID_ARGS","Invalid params: materializationId is required");return{token:rV(t,r),session:rG(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:rG(t,"requestId"),materializationId:e}}}let a=rR[e];if(a)return{token:rV(t,r),session:rG(t,"session")??"default",command:a,positionals:[],meta:{tenantId:rG(t,"tenantId")??rG(t,"tenant"),runId:rG(t,"runId"),leaseId:rG(t,"leaseId"),leaseTtlMs:rj(t,"ttlMs"),leaseBackend:rG(t,"backend")}};throw new $("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,rL.has(s)&&("string"!=typeof l.command||0===l.command.length))return void rF(i,r$(a.id??null,-32602,"Invalid params: command is required"),400);o=eE(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},eO(o);let d=()=>{i.writableFinished||eL(o)};e.on("aborted",d),i.on("close",d);let u=await rB(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void rF(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void rF(i,{jsonrpc:"2.0",id:a.id??null,result:c});rF(i,r$(a.id??null,-32e3,c.error.message,c.error),rU(c.error.code))}catch(t){let e=q(t);rF(i,r$(a.id??null,-32e3,e.message,e),rU(e.code))}finally{eC(o)}})})}async function rW(e,t,r,a){try{var i;let o,s,l=rV({},e.headers),d=rJ(l,a);if(d){t.statusCode=rU(d.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.message,code:d.code}));return}let u=await rB(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:l,session:"default",command:"upload",positionals:[]}});if(!u.ok){t.statusCode=u.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:u.response.error?.data?.message??u.response.error?.message??"Unauthorized"}));return}let c=await rO(e),p=(i={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:u.tenantId},o=n.randomUUID(),(s=setTimeout(()=>{rN(o)},3e5)).unref(),rS.set(o,{artifactPath:i.artifactPath,tempDir:i.tempDir,tenantId:i.tenantId,timer:s}),o);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=q(r);t.statusCode=rU(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rz(e,t,r,a){let i=e.url?.slice("/upload/".length)??"";if(!i){t.statusCode=400,t.end("Missing artifact id");return}try{let n=rV({},e.headers),o=rJ(n,a);if(o){t.statusCode=rU(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let l=await rB(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[i]}});if(!l.ok){t.statusCode=l.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.response.error?.data?.message??l.response.error?.message??"Unauthorized"}));return}let d=function(e,t){let r=rA.get(e);if(!r)throw new $("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Artifact belongs to a different tenant");if(!s.existsSync(r.artifactPath))throw rb(e),new $("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,l.tenantId),u=s.createReadStream(d.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),d.fileName&&t.setHeader("content-disposition",`attachment; filename="${d.fileName.replace(/"/g,"")}"`),u.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=q(e);t.statusCode=rU(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&rb(i)}),u.pipe(t)}catch(r){let e=q(r);t.statusCode=rU(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function rJ(e,t){return t&&e!==t?q(new $("UNAUTHORIZED","Invalid token")):null}function rK(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rX(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function rY(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new $("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rZ{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=rY(e.backend),r=N(e.tenantId);if(!r)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=rK(e.runId);if(!a)throw new $("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let i=this.resolveLeaseTtlMs(e.ttlMs),o=this.bindingKey(r,a,t),s=this.runBindings.get(o);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,i);this.runBindings.delete(o)}this.enforceCapacity(t);let l=this.now(),d={leaseId:n.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+i};return this.leases.set(d.leaseId,d),this.runBindings.set(o,d.leaseId),{...d}}heartbeatLease(e){let t=rX(e.leaseId);if(!t)throw new $("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new $("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=rX(e.leaseId);if(!t)throw new $("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=rY(e.backend),r=N(e.tenantId);if(!r)throw new $("INVALID_ARGS","tenant isolation requires tenant id.");let a=rK(e.runId);if(!a)throw new $("INVALID_ARGS","tenant isolation requires run id.");let i=rX(e.leaseId);if(!i)throw new $("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new $("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new $("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new $("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new $("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=N(t),i=rK(r);if(t&&!a)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new $("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new $("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}let rQ=["emulator","platform-tools",c.join("cmdline-tools","latest","bin"),c.join("cmdline-tools","tools","bin")];function r0(e){let t=new Set,r=[];for(let a of e){let e=a.trim();!e||t.has(e)||(t.add(e),r.push(e))}return r}function r1(e=process.env){let t=e.ANDROID_SDK_ROOT?.trim(),r=e.ANDROID_HOME?.trim(),a=e.HOME?.trim()||u.homedir();return r0([t??"",r??"",a?c.join(a,"Android","Sdk"):""])}async function r2(e){try{return await d.access(e,d.constants.X_OK),!0}catch{return!1}}async function r3(e=process.env){let t,r=[];for(let a of r1(e)){let e=[];for(let t of rQ){let r=c.join(a,t);await r2(r)&&e.push(r)}0!==e.length&&(t||(t=a),r.push(...e))}if(t&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||t,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||t),0===r.length)return;let a=(e.PATH??"").split(c.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=r0([...r,...a]).join(c.delimiter)}function r4(e,t){return["-s",e.id,...t]}async function r8(){if(await r3(),!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH")}function r5(e,t){let r=`${e}
11
11
  ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function r6(e){await new Promise(t=>setTimeout(t,e))}function r9(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let a=r[1]?.toLowerCase(),i=r[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function r7(e,t){let r,a=e?.trim();return a?a:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let ae=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function at(e){return`${e.stdout}
12
- ${e.stderr}`}function ar(e,t){return["-s",e,...t]}function aa(e){return e.startsWith("emulator-")}function ai(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function an(e,t=eA){return O("adb",ar(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function ao(e,t){let r=t.replace(/_/g," ").trim();if(!aa(e))return r||e;let a=await al(e);return a?a.replace(/_/g," "):r||e}async function as(e,t,r){try{return await r("adb",ar(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=P(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function al(e,t=O){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await as(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await as(e,["emu","avd","name"],t);if(!r)return;let a=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(r.stdout);if(0===r.exitCode&&a)return a}async function ad(e,t){let r=at(await O("adb",ar(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eA})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function au(e){return(await Promise.all(ae.map(async t=>await ad(e,t)))).some(e=>!0===e)}async function ac(e){var t;let r;return"tv"===((r=at(await O("adb",ar(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eA})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await au(e)?"tv":(t=at(await O("adb",ar(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eA})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function af(e={}){if(await r3(),!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ez(void 0),r=(await ap()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([ao(e,t),ag(e),ac(e)]);return{platform:"android",id:e,name:r,kind:aa(e)?"emulator":"device",target:i,booted:a}}))}async function ap(){return(await O("adb",["devices","-l"],{timeoutMs:eA})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}async function am(){let e=await O("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eA});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function ah(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await aw(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await new Promise(e=>setTimeout(e,1e3))}throw new $("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function aw(e,t){let r=ai(e);for(let e of(await ap()).filter(e=>(!t||e.serial===t)&&aa(e.serial)))if(ai(e.rawModel)===r||ai(await ao(e.serial,e.rawModel))===r)return e.serial}async function ag(e){try{let t=await an(e);return"1"===t.stdout.trim()}catch{return!1}}async function av(e){var t,r;let a;await r3();let i=e.avdName.trim();if(!i)throw new $("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");if(!await V("emulator"))throw new $("TOOL_MISSING","emulator not found in PATH");let o=await am(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=ai(t);return e.find(e=>ai(e)===a)}(o,i);if(!s)throw new $("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await af(),r=e.serial,a=ai(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&ai(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),x("emulator",t)}let u=d??await ah({avdName:s,serial:e.serial,timeoutMs:n}),c=Math.max(1e3,n-(Date.now()-l));await ay(u.id,c);let f=(await af()).find(e=>e.id===u.id);return f?{...f,name:s,booted:!0}:{...u,name:s,booted:!0}}async function ay(e,t=6e4){let r,a=eb.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await eS(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new $("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,i?.remainingMs()??t),s=await an(e,Math.min(o,eA));if(r=s,"1"!==s.stdout.trim())throw new $("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:i,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=P(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eU({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===i.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),reason:d,hint:eV(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new $("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new $("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new $("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new $(i.code,i.message,{...u,...i.details??{}},i.cause)}}let aI=/\.(?:apk|aab)$/i,aA=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ab(e){var t,r;let a=e.trim();return 0===a.length?"other":aI.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!aA.test(t))?"binary":"package":(r=a,aA.test(r))?"package":"other"}function aS(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let a_=[".zip",".tar",".tar.gz",".tgz"],aN=eF(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),aD=["1","true","yes","on"];async function ax(e){let t=[];try{let r=await aM(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await aC(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await a$(t)}}}catch(e){throw await a$(t),e}}async function aM(e,t){if("path"===e.kind)return{localPath:R(e.path),cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-source-"));try{return{localPath:await aE(r,e.url,e.headers,t),cleanup:async()=>{await d.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(r,{recursive:!0,force:!0}),e}}async function aE(e,t,r,a){let i;try{i=new URL(t)}catch{throw new $("INVALID_ARGS",`Invalid source URL: ${t}`)}await ak(i);let n=a?.signal;if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(n?.reason)};n?.addEventListener("abort",s,{once:!0});let l=a?.downloadTimeoutMs??aN,u=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new $("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return c.basename(i);let n=c.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=c.join(e,a),s=t.body;if(!s)throw new $("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let l=await d.open(n,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return n}catch(e){if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new $("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",s),clearTimeout(u)}}async function ak(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new $("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!aD.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||aL(t))throw new $("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await v.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>aL(e.address)))throw new $("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function aO(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function aL(e){let t,r=f.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function aC(e,t){let r=await d.stat(e).catch(()=>null);if(!r)throw new $("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&aT(e)){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await aR(e);return t.registerCleanup(r.cleanup),await aC(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await aP(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new $("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await aP(e,(e,t)=>t.isFile()&&aT(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await aR(a[0]);return t.registerCleanup(e.cleanup),await aC(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new $("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new $("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function aP(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await d.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=c.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function aR(e){let t=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await O("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await O("tar",["-xzf",e,"-C",t]):await O("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(t,{recursive:!0,force:!0}),e}}function aT(e){let t=e.toLowerCase();return a_.some(e=>t.endsWith(e))}async function a$(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let aF=new I("utf-16le");async function aU(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await aV(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=aG(e,t),[a,i]=aG(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return aF.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await aj(e)}async function aV(e,t){try{let r=await O("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function aG(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aj(e){let t=await aB();if(!t)return;let r=await O(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aB(){if(void 0!==e)return e??void 0;try{for(let t of r1()){let r=c.join(t,"build-tools");try{for(let t of(await y.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=c.join(r,t,"aapt");try{return await y.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function aq(e,t){let r="url"===e.kind&&aO(e.url),a=await ax({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=c.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await aH(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function aH(e){let t=c.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aU(e)}}let aW={settings:{type:"intent",value:"android.settings.SETTINGS"}},az="android.intent.category.LAUNCHER",aJ="android.intent.category.LEANBACK_LAUNCHER",aK="android.intent.category.DEFAULT";async function aX(e,t){let r=t.trim();if("package"===ab(r))return{type:"package",value:r};let a=aW[r.toLowerCase()];if(a)return a;let i=(await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new $("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new $("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function aY(e,t="all"){let r=await aZ(e);return("user-installed"===t?(await a0(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:a1(e)}))}async function aZ(e){let t=new Set;for(let r of aQ(e,{includeFallbackWhenUnknown:!0})){let a=await O("adb",r4(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function aQ(e,t={}){return"tv"===e.target?[aJ]:"mobile"===e.target?[az]:t.includeFallbackWhenUnknown?[az,aJ]:[az]}async function a0(e){return(await O("adb",r4(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function a1(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function a2(e){let t=await a3(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await a3(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function a3(e,t){for(let r of t){let t=function(e){for(let t of[/mCurrentFocus=Window\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mFocusedApp=AppWindowToken\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/,/ResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/]){let r=t.exec(e);if(r)return{package:r[1],activity:r[2]}}return null}((await O("adb",r4(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function a4(e,t,r){var a,i;let n;e.booted||await ay(e.id);let o=t.trim();if(r9(o)){if(r)throw new $("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aX(e,t),l=aQ(e)[0]??az;if("intent"===s.type){if(r)throw new $("INVALID_ARGS","Activity override requires a package name, not an intent");await O("adb",r4(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",t]));return}let d=await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,n=`${a}
13
- ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)))return;let u=await a8(e,s.value);if(!u)throw new $("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr});await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",u]))}async function a8(e,t){for(let r of Array.from(new Set(aQ(e,{includeFallbackWhenUnknown:!0})))){let a=await O("adb",r4(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function a5(e){e.booted||await ay(e.id)}async function a6(e,t){if("settings"===t.trim().toLowerCase())return void await O("adb",r4(e,["shell","am","force-stop","com.android.settings"]));let r=await aX(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","Close requires a package name, not an intent");await O("adb",r4(e,["shell","am","force-stop",r.value]))}async function a9(e,t){let r=await aX(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await O("adb",r4(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
14
- ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new $("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let a7=null;async function ie(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(a7?.key===e)return a7.invocation;if(await V("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return a7={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new $("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new $("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return a7={key:e,invocation:r},r}async function it(e){let t=await ie();await O(t.cmd,[...t.prefixArgs,...e])}async function ir(e,t){let r,a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-aab-")),i=c.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await it(["build-apks","--bundle",t,"--output",i,"--mode",n]),await it(["install-apks","--apks",i,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function ia(e,t){".aab"===c.extname(t).toLowerCase()?await ir(e,t):await O("adb",r4(e,["install","-r",t]))}async function ii(e){return new Set((await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function io(e,t){let r=Array.from(await ii(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function is(e,t){e.booted||await ay(e.id),await ia(e,t)}async function il(e,t,r){let a=r?void 0:await ii(e);return await is(e,t),r??(a?await io(e,a):void 0)}async function id(e,t){e.booted||await ay(e.id);let r=await aq({kind:"path",path:t});try{let t=await il(e,r.installablePath,r.packageName),a=t?a1(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function iu(e,t,r){e.booted||await ay(e.id);let{package:a}=await a9(e,t),i=await aq({kind:"path",path:r},{resolveIdentity:!1});try{return await is(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function ic(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),i=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),n=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(i,Math.max(1,r-2*n))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,i,n)=>({direction:t,x1:r,y1:a,x2:i,y2:n,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function ip(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=ih(i[0]),n=(iw(t,"text")??"").toLowerCase(),o=(iw(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=ig(iw(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}function im(e){let t=ih(e),r=e=>{let r=iw(t,e);if(null!==r)return"true"===r};return{text:iw(t,"text"),desc:iw(t,"content-desc"),resourceId:iw(t,"resource-id"),className:iw(t,"class"),bounds:iw(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ih(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function iw(e,t){return e.get(t)??null}function ig(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function iv(e){return e?e.toLowerCase():""}function iy(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function iI(e,t={}){return function(e,t){let r=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=im(t),o=ig(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),a=[],i=!1,n=t.depth??1/0,o=t.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(r,t.scope):null,s=o?[o]:r.children,l=new Map,d=e=>{let t=l.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||d(t))return l.set(e,!0),!0;return l.set(e,!1),!1},u=(e,r,o,s=!1,l=!1)=>{var c,f,p,m,h,w;let g,v,y,I,A,b,S,_;if(a.length>=800){i=!0;return}if(r>n)return;let N=!!t.raw||(c=e,f=t,p=s,m=d(e),h=l,v=iv(c.type),y=!!(c.label&&c.label.trim().length>0),I=!!(c.identifier&&c.identifier.trim().length>0),A=y&&!iy(c.label??""),b=I&&!iy(c.identifier??""),S=(g=(w=v).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===v||"imagebutton"===v,f.interactiveOnly?!!c.hittable||!!(A||b)&&!_&&(!S||!!h)&&(p||m||h):f.compact?A||b||!!c.hittable:!S&&!_||!!c.hittable||!!A||!!b&&!!m||m),D=o;N&&(D=a.length,a.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:r,parentIndex:o}));let x=s||!!e.hittable,M=l||function(e){if(!e)return!1;let t=iv(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(u(t,r+1,D,x,M),i)return};for(let e of s)if(u(e,0,void 0,!1,!1),i)break;return i?{nodes:a,truncated:i}:{nodes:a}}(await iA(e),t)}async function iA(e){return e_(()=>ib(e),{shouldRetry:i_})}async function ib(e){var t,r,a;let i,n,o=await O("adb",r4(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=iS(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await O("adb",r4(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,a=l.stderr,i=`${r}
15
- ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await O("adb",r4(e,["shell","cat",d])),c=iS(u.stdout,u.stderr);if(!c)throw new $("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function iS(e,t){let r=`${e}
16
- ${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function i_(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function iN(e,t,r){await O("adb",r4(e,["shell","input","tap",String(t),String(r)]))}async function iD(e,t,r,a,i,n=250){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function ix(e){await O("adb",r4(e,["shell","input","keyevent","4"]))}async function iM(e){await O("adb",r4(e,["shell","input","keyevent","3"]))}async function iE(e){await O("adb",r4(e,["shell","input","keyevent","187"]))}async function ik(e,t,r,a=800){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iO(e,t,r=0){r>0&&Array.from(t).length>1?await iF(e,t,1,r):await iL(e,t)}async function iL(e,t){let r=iU(t);if(!r||"ok"!==await iV(e,t))try{let r=t.replace(/ /g,"%s");await O("adb",r4(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return!!(t.includes("exception occurred while executing 'text'")||t.includes("nullpointerexception")&&t.includes("inputshellcommand.sendtext"))}(e))throw new $("COMMAND_FAILED","Non-ASCII text input is not supported on this Android shell. Install an ADB keyboard IME or use ASCII input.",{textPreview:t.slice(0,32)},e instanceof Error?e:void 0);throw e}}async function iC(e,t,r){await iN(e,t,r)}async function iP(e,t,r,a,i=0){let n=Array.from(a).length,o=iU(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&i<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||i>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iC(e,t,r);let s=(d=n+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await iG(e,s),"input_text"===o.strategy)await iO(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await iV(e,a))continue}else await iF(e,a,1,i>0?i:15);if((l=await ij(e,t,r))===a)return}throw new $("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iR(e,t,r){let a=await i$(e),i=ic({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await O("adb",r4(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function iT(e,t,r){let a=r?.maxScrolls??8,i="";try{i=await iA(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ip(i,t))return{attempts:0};for(let r=1;r<=a;r+=1){await iR(e,"down",{amount:.5});let a="";try{a=await iA(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(ip(a,t))return{attempts:r};if(a===i)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});i=a}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function i$(e){let t=(await O("adb",r4(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new $("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iF(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await iL(e,r),a>0&&t+i<n.length&&await r6(a)}}function iU(e){for(let t of e){let e=t.codePointAt(0);if(void 0!==e&&(e<32||e>126))return!0}return!1}async function iV(e,t){let r=await O("adb",r4(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":r5(r.stdout,r.stderr)?"unsupported":0===(await O("adb",r4(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await O("adb",r4(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iG(e,t){let r=Math.max(0,t);await O("adb",r4(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await O("adb",r4(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function ij(e,t,r){let a,i=await iA(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=im(a[0]),i=ig(e.bounds);if(!i)continue;let n=e.className??"",d=(e.text??"").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),u=e.focused??!1;if(!d)continue;let c=Math.max(1,i.width*i.height),f=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&iB(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(f&&iB(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}f&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function iB(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iq(e){let t=await O("adb",r4(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function iH(e){let t=await iq(e),r=t,a=0;for(;r.visible&&a<2;)await O("adb",r4(e,["shell","input","keyevent","111"])),a+=1,await r6(120),r=await iq(e);if(t.visible&&r.visible)throw new $("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:r.inputType,type:r.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function iW(e){let t,r;return(r=(t=(await iJ(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?r[1]??"":"null"===t.trim().toLowerCase()?"":t}async function iz(e,t){await iJ(e,["shell","cmd","clipboard","set","text",t],"write")}async function iJ(e,t,r){let a=await O("adb",r4(e,t),{allowFailure:!0});if(r5(a.stdout,a.stderr))throw new $("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new $("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let iK=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function iX(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new $("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iY(e){let t=e?.trim().toLowerCase();if("camera"===t||"microphone"===t||"photos"===t||"contacts"===t||"contacts-limited"===t||"notifications"===t||"calendar"===t||"location"===t||"location-always"===t||"media-library"===t||"motion"===t||"reminders"===t||"siri"===t)return t;throw new $("INVALID_ARGS",`permission setting requires a target: ${iK.join("|")}`)}function iZ(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new $("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function iQ(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=i1(r);await O("adb",r4(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=i1(r);await O("adb",r4(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await O("adb",r4(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=i1(r);await O("adb",r4(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await i2(e,r);await O("adb",r4(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]));return}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new $("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await i0(e,t);return}case"permission":{if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t=iX(r),n=function(e,t){let r=iY(e);if(t?.trim())throw new $("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new $("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await i4(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await i3(e,a,o);await O("adb",r4(e,["shell","pm",o,a,n.value]));return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function i0(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await O("adb",r4(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
17
- ${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new $("UNSUPPORTED_OPERATION","Android fingerprint simulation is not supported on this target/runtime.",{deviceId:e.id,action:t,hint:"Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.",attempts:s});throw new $("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function i1(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function i2(e,t){let r=iZ(t);if("toggle"!==r)return r;let a=await O("adb",r4(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
18
- ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"auto"===i?"dark":"dark"===i?"light":"dark"}async function i3(e,t,r){let a=await i8(e),i=[];for(let n of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await O("adb",r4(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:n,stderr:a.stderr,exitCode:a.exitCode})}throw new $("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function i4(e,t,r,a){"grant"===r?await O("adb",r4(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await O("adb",r4(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await O("adb",r4(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function i8(e){let t=await O("adb",r4(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}async function i5(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&i.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new $("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,r){if("string"==typeof r)return e.push("--es",t,r);if("boolean"==typeof r)return e.push("--ez",t,r?"true":"false");if("number"==typeof r&&Number.isFinite(r))return Number.isInteger(r)?e.push("--ei",t,String(r)):e.push("--ef",t,String(r));throw new $("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await O("adb",r4(e,i)),{action:a,extrasCount:s}}let i6=Buffer.from([137,80,78,71,13,10,26,10]);async function i9(e,t){await i7(e);try{await r6(1e3),await nt(e,t)}finally{await ne(e).catch(()=>{})}}async function i7(e){let t=t=>O("adb",r4(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let r=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await r("clock -e hhmm 0941"),await r("notifications -e visible false")}async function ne(e){await O("adb",r4(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function nt(e,t){let r=await O("adb",r4(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new $("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(i6);if(a<0)throw new $("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+i6.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,i=e.toString("ascii",a,a+4),n=r+12+t;if(n>e.length)break;if("IEND"===i)return n;r=n}return null}(r.stdoutBuffer,a);if(!i)throw new $("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await d.writeFile(t,r.stdoutBuffer.subarray(a,i))}let nr=eF(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eI,5e3),na=eF(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,ey,1e3),ni=eF(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),nn=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),no=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),ns=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),nl=eF(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function nd(e,t){let r=["devicectl",...e],a=await O("xcrun",r,{allowFailure:!0,timeoutMs:nn});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new $("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:nf(i,n)??nc})}async function nu(e,t){let r=c.join(u.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],i=await O("xcrun",a,{allowFailure:!0,timeoutMs:nn});try{var n,o;if(0!==i.exitCode){let t=String(i.stdout??""),r=String(i.stderr??"");throw new $("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:i.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:nf(t,r)??nc})}let s=await d.readFile(r,"utf8");return n=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let a="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:a})}return r}(JSON.parse(s)),o=t,"user-installed"===o?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof $)throw t;throw new $("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await d.unlink(r).catch(()=>{})}}let nc="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function nf(e,t){let r=`${e}
19
- ${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function np(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let r=String(t.stderr??"").toLowerCase();return r.includes("fbsopenapplicationserviceerrordomain")&&r.includes("the request to open")}async function nm(e,t){let r=await O("xcrun",eK(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let a=r.stdout.trim();if(!a)return{installed:!1};let i=await O("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let n=i.stdout.trim(),o=`${a}/${n}`,s=await O("otool",["-l",o],{allowFailure:!0});if(0!==s.exitCode)return{installed:!0};let l=s.stdout.toLowerCase();return{installed:!0,simulatorCompatible:l.includes("iossimulator")||l.includes("platform 7")}}function nh(e,t){if("simulator"!==e.kind)throw new $("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function nw(){await O("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:no})}async function ng(e){let t,r;if("simulator"!==e.kind||"Booted"===await ny(e))return;let a=eb.fromTimeoutMs(nr);try{await eS(async({deadline:a})=>{if(a?.isExpired())throw new $("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:nr});let i=Math.max(1e3,a?.remainingMs()??nr),n=await O("xcrun",eK(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode};let o=`${t.stdout}
20
- ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new $("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await O("xcrun",eK(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new $("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await ny(e);if("Booted"!==d)throw new $("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=eU({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>eU({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=eU({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new $("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:nr,elapsedMs:a.elapsedMs(),reason:i,hint:eV(i),boot:t,bootstatus:r})}await nw()}async function nv(e){let t=eK(e,["shutdown",e.id]),r=await O("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function ny(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eJ(["list","devices","-j"]):eK(e,["list","devices","-j"]),a=await O("xcrun",r,{allowFailure:!0,timeoutMs:na});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function nI(e,t){try{let r=await O("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await d.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!a?.[1])return;let i=a[1].trim().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&amp;/g,"&");return i.length>0?i:void 0}(r,t)}catch{return}}async function nA(e,t){if("url"===e.kind&&!aO(e.url))throw new $("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let r=await ax({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(".app")||t.isFile()&&e.toLowerCase().endsWith(".ipa"),installableLabel:"iOS installable (.app or .ipa)",allowArchiveExtraction:"url"!==e.kind||aO(e.url),signal:t?.signal}),a=await nS(r.installablePath,t),i=await nb(a.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await r.cleanup()}}}async function nb(e){let t=c.join(e,"Info.plist"),[r,a,i]=await Promise.all([nI(t,"CFBundleIdentifier"),nI(t,"CFBundleDisplayName"),nI(t,"CFBundleName")]);return{bundleId:r,appName:a??i}}async function nS(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await d.rm(r,{recursive:!0,force:!0})};try{await O("ditto",["-x","-k",e,r]);let i=c.join(r,"Payload"),n=(await d.readdir(i,{withFileTypes:!0}).catch(()=>{throw new $("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:c.join(i,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===n.length)return{installPath:n[0].installPath,cleanup:a};if(0===n.length)throw new $("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await n_(n);let o=t?.appIdentifierHint?.trim();if(o){let e=function(e,t){let r=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===a.length)return a[0];if(a.length>1)throw new $("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(n,o);if(e)return{installPath:e.installPath,cleanup:a};throw new $("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload and none matched "${o}". Available bundles: ${n.map(nN).join(", ")}`)}throw new $("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${n.map(nN).join(", ")}`)}catch(e){throw await a(),e}}async function n_(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await nb(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function nN(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function nD(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let nx="agent-device-macos-helper",nM="AGENT_DEVICE_MACOS_HELPER_BIN",nE=c.join(u.homedir(),".agent-device","macos-helper","current"),nk=c.join(nE,"manifest.json"),nO=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function nL(e){let t=e.trim();if(!nO.test(t))throw new $("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function nC(){return function(e){let t=c.dirname(e);for(;;){let e=c.join(t,"macos-helper");if(l(c.join(e,"Package.swift")))return e;let r=c.dirname(t);if(r===t)break;t=r}throw new $("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(m(import.meta.url))}async function nP(e){let t=await d.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=c.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await nP(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function nR(e){let t=await nP(e),r=o("sha256");for(let a of t)r.update(c.relative(e,a)),r.update("\0"),r.update(await d.readFile(a)),r.update("\0");let a=await O("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return r.update("swift-version"),r.update("\0"),r.update(a.stdout||a.stderr||`exit:${a.exitCode}`),r.update("\0"),r.digest("hex")}async function nT(){try{let e=JSON.parse(await d.readFile(nk,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function n$(){let e=process.env[nM]?.trim();if(e)return e;let t=nC(),r=await nR(t),a=c.join(nE,nx);try{if(await nT()===r)return await d.access(a),a}catch{}let i=c.join(nC(),".build","release",nx);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await O("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await d.mkdir(nE,{recursive:!0});let n=`${a}.tmp`;return await d.copyFile(i,n),await d.rename(n,a),await d.chmod(a,493),await d.writeFile(nk,`${JSON.stringify({fingerprint:r},null,2)}
21
- `,"utf8"),a}async function nF(e){let t=process.env[nM]?.trim();if("darwin"!==process.platform&&!t)throw new $("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let r=await n$(),a=await O(r,e,{allowFailure:!0,timeoutMs:3e4}),i=a.stdout.trim(),n=null;if(i)try{n=JSON.parse(i)}catch{n=null}if(0===a.exitCode&&n?.ok)return n.data;throw new $("COMMAND_FAILED",n&&!n.ok?n.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:r,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...n&&!n.ok?n.error?.details:{}})}async function nU(){return await nF(["app","frontmost"])}async function nV(e){return await nF(["app","quit","--bundle-id",nL(e)])}async function nG(e,t){return await nF(["permission",e,t])}async function nj(e,t={}){let r=["alert",e];return t.bundleId&&r.push("--bundle-id",nL(t.bundleId)),t.surface&&r.push("--surface",t.surface),await nF(r)}async function nB(e,t={}){let r=["snapshot","--surface",e];return t.bundleId&&r.push("--bundle-id",nL(t.bundleId)),await nF(r)}async function nq(e,t,r={}){let a=["read","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",nL(r.bundleId)),r.surface&&a.push("--surface",r.surface),await nF(a)}async function nH(e,t,r={}){let a=["press","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",nL(r.bundleId)),r.surface&&a.push("--surface",r.surface),await nF(a)}async function nW(e,t={}){let r=["screenshot","--out",e];return t.surface&&r.push("--surface",t.surface),t.fullscreen&&r.push("--fullscreen"),await nF(r)}let nz={settings:"com.apple.systempreferences"},nJ=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function nK(e,t){let r=["-b",e];return t&&r.push(t),r}async function nX(e){for(let t of[c.join(e,"Contents","Info.plist"),c.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([nI(t,"CFBundleIdentifier"),nI(t,"CFBundleDisplayName"),nI(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function nY(e){let t=e.trim(),r=nz[t.toLowerCase()];if(r)return r;if(nJ.test(t))return t;let a=(await n4("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new $("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new $("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function nZ(e,t,r){let a=r?.url?.trim();if(a){if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await nY(t);await O("open",nK(e,a));return}let i=t.trim();if(r9(i))return void await O("open",[i]);let n=r?.appBundleId??await nY(i);await O("open",nK(n))}async function nQ(e,t){let r=await nY(t),a=await nV(r);if(a.running&&!a.terminated&&!a.forceTerminated)throw new $("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function n0(){let e=await O("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});return e.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function n1(e){let t=await O("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function n2(){let e=await O("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to read macOS appearance",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});let t=e.stdout.trim().toLowerCase();if("true"===t)return!0;if("false"===t)return!1;throw new $("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function n3(e){let t=iZ(e),r="toggle"===t?!await n2():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,i=await O("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new $("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function n4(e="all"){let t=["/Applications","/System/Applications",c.join(u.homedir(),"Applications")],r=new Set;for(let e of t){let t=await d.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await O("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===a.exitCode)for(let e of a.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return nD((await Promise.all(Array.from(r).map(async e=>{let t=await nX(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??c.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let n8=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],n5={0:"hide",1:"wifi",6:"3g",7:"4g",8:"lte",9:"lte-a",10:"lte+",11:"5g",12:"5g+",13:"5g-uwb",14:"5g-uc"},n6={1:"searching",2:"failed",3:"active"},n9={0:"notSupported",1:"searching",2:"failed",3:"active"};function n7(e,t,r){return O("xcrun",eK(e,t),r)}async function oe(e,t){var r,a;let i;await or(e),t&&await oa(e,(i=[],(r=t).dataNetwork&&i.push("--dataNetwork",r.dataNetwork),r.wifiMode&&i.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&i.push("--wifiBars",r.wifiBars),r.cellularMode&&i.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(a=r.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==r.operatorName)&&i.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&i.push("--operatorName",r.operatorName),i))}async function ot(e){let t=await n7(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to read simulator status bar overrides",{exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr});return function(e){let t={};for(let r of e.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&"Current Status Bar Overrides:"!==e&&!/^=+$/.test(e))){let e=/^DataNetworkType:\s+(\d+)$/.exec(r);if(e){let r=Number(e[1]),a=n5[r];if(!a)throw new $("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(a){let e=n6[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(i){let e=Number(i[1]),r=n9[e];if(!r)throw new $("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=i[2];continue}let n=/^Operator Name:\s*(.*)$/.exec(r);if(n){t.operatorName=n[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function or(e){await n7(e,["status_bar",e.id,"clear"])}async function oa(e,t){0!==t.length&&await n7(e,["status_bar",e.id,"override",...t])}function oi(e,t,r){Q({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof $))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}(r)}})}function on(e,t,r){return O("xcrun",eK(e,t),r)}let oo={ensureBooted:ng,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await ot(e),r=!0}catch(t){oi(e,"snapshot_failed",t)}try{await or(e),await oa(e,n8)}catch(t){oi(e,"prepare_failed",t)}return async()=>{await oe(e,r?t:null)}},captureWithRetry:od,captureWithRunner:ou,shouldFallbackToRunner:og};async function os(e,t,r,a){if("macos"===e.platform)return void await ou(e,t,r,a);if("simulator"===e.kind)return void await ol(e,t,r,a);try{await nd(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
12
+ ${e.stderr}`}function ar(e,t){return["-s",e,...t]}function aa(e){return e.startsWith("emulator-")}function ai(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function an(e,t=eA){return O("adb",ar(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function ao(e,t){let r=t.replace(/_/g," ").trim();if(!aa(e))return r||e;let a=await al(e);return a?a.replace(/_/g," "):r||e}async function as(e,t,r){try{return await r("adb",ar(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=P(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function al(e,t=O){for(let r of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await as(e,["shell","getprop",r],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let r=await as(e,["emu","avd","name"],t);if(!r)return;let a=function(e){let t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0);if(0!==t.length)return"OK"===t.at(-1)&&t.pop(),t.join("\n").trim()||void 0}(r.stdout);if(0===r.exitCode&&a)return a}async function ad(e,t){let r=at(await O("adb",ar(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eA})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function au(e){return(await Promise.all(ae.map(async t=>await ad(e,t)))).some(e=>!0===e)}async function ac(e){var t;let r;return"tv"===((r=at(await O("adb",ar(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eA})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await au(e)?"tv":(t=at(await O("adb",ar(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eA})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function ap(e={}){if(await r3(),!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ez(void 0),r=(await af()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([ao(e,t),ag(e),ac(e)]);return{platform:"android",id:e,name:r,kind:aa(e)?"emulator":"device",target:i,booted:a}}))}async function af(){return(await O("adb",["devices","-l"],{timeoutMs:eA})).stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith("List of devices")).map(e=>e.split(/\s+/)).filter(e=>"device"===e[1]).map(e=>({serial:e[0],rawModel:(e.find(e=>e.startsWith("model:"))??"").replace("model:","")}))}async function am(){let e=await O("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eA});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to list Android emulator AVDs",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode,hint:"Verify Android emulator tooling is installed and available in PATH."});return e.stdout.split("\n").map(e=>e.trim()).filter(e=>e.length>0)}async function ah(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await aw(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await new Promise(e=>setTimeout(e,1e3))}throw new $("COMMAND_FAILED","Android emulator did not appear in time",{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:"Check emulator logs and verify the AVD can start from command line."})}async function aw(e,t){let r=ai(e);for(let e of(await af()).filter(e=>(!t||e.serial===t)&&aa(e.serial)))if(ai(e.rawModel)===r||ai(await ao(e.serial,e.rawModel))===r)return e.serial}async function ag(e){try{let t=await an(e);return"1"===t.stdout.trim()}catch{return!1}}async function ay(e){var t,r;let a;await r3();let i=e.avdName.trim();if(!i)throw new $("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await V("adb"))throw new $("TOOL_MISSING","adb not found in PATH");if(!await V("emulator"))throw new $("TOOL_MISSING","emulator not found in PATH");let o=await am(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=ai(t);return e.find(e=>ai(e)===a)}(o,i);if(!s)throw new $("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:i,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await ap(),r=e.serial,a=ai(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&ai(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),x("emulator",t)}let u=d??await ah({avdName:s,serial:e.serial,timeoutMs:n}),c=Math.max(1e3,n-(Date.now()-l));await av(u.id,c);let p=(await ap()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function av(e,t=6e4){let r,a=eb.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await eS(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new $("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),message:"timeout"});let o=Math.max(1e3,i?.remainingMs()??t),s=await an(e,Math.min(o,eA));if(r=s,"1"!==s.stdout.trim())throw new $("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:i,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>eU({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=P(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eU({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===i.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:a.elapsedMs(),reason:d,hint:eV(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new $("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new $("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new $("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new $(i.code,i.message,{...u,...i.details??{}},i.cause)}}let aI=/\.(?:apk|aab)$/i,aA=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function ab(e){var t,r;let a=e.trim();return 0===a.length?"other":aI.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!aA.test(t))?"binary":"package":(r=a,aA.test(r))?"package":"other"}function aS(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let a_=[".zip",".tar",".tar.gz",".tgz"],aN=eF(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),aD=["1","true","yes","on"];async function ax(e){let t=[];try{let r=await ak(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await aC(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await a$(t)}}}catch(e){throw await a$(t),e}}async function ak(e,t){if("path"===e.kind)return{localPath:R(e.path),cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-source-"));try{return{localPath:await aM(r,e.url,e.headers,t),cleanup:async()=>{await d.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(r,{recursive:!0,force:!0}),e}}async function aM(e,t,r,a){let i;try{i=new URL(t)}catch{throw new $("INVALID_ARGS",`Invalid source URL: ${t}`)}await aE(i);let n=a?.signal;if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let o=new AbortController,s=()=>{o.abort(n?.reason)};n?.addEventListener("abort",s,{once:!0});let l=a?.downloadTimeoutMs??aN,u=setTimeout(()=>{o.abort(Error("download timeout"))},l);try{let t=await fetch(i,{headers:r,redirect:"follow",signal:o.signal});if(!t.ok)throw new $("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:i.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=a?.[1]?.trim();if(i)return c.basename(i);let n=c.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,i),n=c.join(e,a),s=t.body;if(!s)throw new $("COMMAND_FAILED","Download response body was empty",{url:i.toString()});let l=await d.open(n,"w");try{for await(let e of s)await l.write(e)}finally{await l.close()}return n}catch(e){if(n?.aborted)throw new $("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(o.signal.aborted)throw new $("COMMAND_FAILED",`App source download timed out after ${l}ms`,{timeoutMs:l,url:i.toString()},e);throw e}finally{n?.removeEventListener("abort",s),clearTimeout(u)}}async function aE(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new $("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!aD.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||aL(t))throw new $("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await y.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>aL(e.address)))throw new $("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function aO(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function aL(e){let t,r=p.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function aC(e,t){let r=await d.stat(e).catch(()=>null);if(!r)throw new $("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&aT(e)){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await aR(e);return t.registerCleanup(r.cleanup),await aC(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await aP(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new $("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await aP(e,(e,t)=>t.isFile()&&aT(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new $("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await aR(a[0]);return t.registerCleanup(e.cleanup),await aC(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new $("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new $("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function aP(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let i=await d.readdir(e.path,{withFileTypes:!0});for(let n of(i.sort((e,t)=>e.name.localeCompare(t.name)),i)){let i=c.join(e.path,n.name);if(t(i,n)){r.push(i);continue}n.isDirectory()&&e.depth<5&&a.push({path:i,depth:e.depth+1})}}return r}async function aR(e){let t=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await O("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await O("tar",["-xzf",e,"-C",t]):await O("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await d.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await d.rm(t,{recursive:!0,force:!0}),e}}function aT(e){let t=e.toLowerCase();return a_.some(e=>t.endsWith(e))}async function a$(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let aF=new I("utf-16le");async function aU(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await aV(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=aG(e,t),[a,i]=aG(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return aF.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await aj(e)}async function aV(e,t){try{let r=await O("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function aG(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function aj(e){let t=await aB();if(!t)return;let r=await O(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function aB(){if(void 0!==e)return e??void 0;try{for(let t of r1()){let r=c.join(t,"build-tools");try{for(let t of(await v.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let a=c.join(r,t,"aapt");try{return await v.access(a),e=a,a}catch{}}}catch{}}}catch{}e=null}async function aq(e,t){let r="url"===e.kind&&aO(e.url),a=await ax({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=c.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await aH(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function aH(e){let t=c.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await aU(e)}}let aW={settings:{type:"intent",value:"android.settings.SETTINGS"}},az="android.intent.category.LAUNCHER",aJ="android.intent.category.LEANBACK_LAUNCHER",aK="android.intent.category.DEFAULT",aX="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function aY(e,t){let r=t.trim();if("package"===ab(r))return{type:"package",value:r};let a=aW[r.toLowerCase()];if(a)return a;let i=(await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new $("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i,hint:"Run agent-device apps --platform android to see the exact installed package names before retrying open."});throw new $("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:aX})}async function aZ(e,t="all"){let r=await aQ(e);return("user-installed"===t?(await a1(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:a2(e)}))}async function aQ(e){let t=new Set;for(let r of a0(e,{includeFallbackWhenUnknown:!0})){let a=await O("adb",r4(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function a0(e,t={}){return"tv"===e.target?[aJ]:"mobile"===e.target?[az]:t.includeFallbackWhenUnknown?[az,aJ]:[az]}async function a1(e){return(await O("adb",r4(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function a2(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function a3(e){let t=await a4(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await a4(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function a4(e,t){for(let r of t){let t=function(e){for(let t of[/mCurrentFocus=Window\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mFocusedApp=AppWindowToken\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/,/ResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/]){let r=t.exec(e);if(r)return{package:r[1],activity:r[2]}}return null}((await O("adb",r4(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function a8(e,t,r){var a,i;let n;e.booted||await av(e.id);let o=t.trim();if(r9(o)){if(r)throw new $("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aY(e,t),l=a0(e)[0]??az;if("intent"===s.type){if(r)throw new $("INVALID_ARGS","Activity override requires a package name, not an intent");await O("adb",r4(e,["shell","am","start","-W","-a",s.value]));return}if(r){let t=r.includes("/")?r:`${s.value}/${r.startsWith(".")?r:`.${r}`}`;try{await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",t]))}catch(t){throw await a9(e,s.value,t),t}return}let d=await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,n=`${a}
13
+ ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)))return;let u=await ie(e,s.value);if(!u){if(!await a6(e,s.value))throw a5(s.value);throw new $("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr})}await O("adb",r4(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",aK,"-c",l,"-n",u]))}function a5(e){return new $("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:aX})}async function a6(e,t){let r=await O("adb",r4(e,["shell","pm","path",t]),{allowFailure:!0}),a=`${r.stdout}
14
+ ${r.stderr}`;return!!(0===r.exitCode&&/\bpackage:/i.test(a))||(a7(a),!1)}async function a9(e,t,r){if(a7(r instanceof $?`${String(r.details?.stdout??"")}
15
+ ${String(r.details?.stderr??"")}`:"")||!await a6(e,t))throw a5(t)}function a7(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function ie(e,t){for(let r of Array.from(new Set(a0(e,{includeFallbackWhenUnknown:!0})))){let a=await O("adb",r4(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=function(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function it(e){e.booted||await av(e.id)}async function ir(e,t){if("settings"===t.trim().toLowerCase())return void await O("adb",r4(e,["shell","am","force-stop","com.android.settings"]));let r=await aY(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","Close requires a package name, not an intent");await O("adb",r4(e,["shell","am","force-stop",r.value]))}async function ia(e,t){let r=await aY(e,t);if("intent"===r.type)throw new $("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await O("adb",r4(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
16
+ ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new $("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let ii=null;async function io(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(ii?.key===e)return ii.invocation;if(await V("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return ii={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new $("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await d.access(t)}catch{throw new $("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return ii={key:e,invocation:r},r}async function is(e){let t=await io();await O(t.cmd,[...t.prefixArgs,...e])}async function il(e,t){let r,a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-aab-")),i=c.join(a,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await is(["build-apks","--bundle",t,"--output",i,"--mode",n]),await is(["install-apks","--apks",i,"--device-id",e.id])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function id(e,t){".aab"===c.extname(t).toLowerCase()?await il(e,t):await O("adb",r4(e,["install","-r",t]))}async function iu(e){return new Set((await O("adb",r4(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function ic(e,t){let r=Array.from(await iu(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function ip(e,t){e.booted||await av(e.id),await id(e,t)}async function im(e,t,r){let a=r?void 0:await iu(e);return await ip(e,t),r??(a?await ic(e,a):void 0)}async function ih(e,t){e.booted||await av(e.id);let r=await aq({kind:"path",path:t});try{let t=await im(e,r.installablePath,r.packageName),a=t?a2(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function iw(e,t,r){e.booted||await av(e.id);let{package:a}=await ia(e,t),i=await aq({kind:"path",path:r},{resolveIdentity:!1});try{return await ip(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function ig(e){let t=e.direction,r="up"===t||"down"===t?e.referenceHeight:e.referenceWidth,a=function(e){if(void 0===e)return .6;if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll amount must be a positive number");return e}(e.amount),i=void 0!==e.pixels?function(e){if(!Number.isFinite(e)||e<=0)throw new $("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(r*a),n=Math.max(1,Math.round(.05*r)),o=Math.max(1,Math.min(i,Math.max(1,r-2*n))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(r,a,i,n)=>({direction:t,x1:r,y1:a,x2:i,y2:n,referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight,amount:e.amount,pixels:o});switch(t){case"up":return u(l,d-s,l,d+s);case"down":return u(l,d+s,l,d-s);case"left":return u(l-s,d,l+s,d);case"right":return u(l+s,d,l-s,d)}}function iy(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=iI(i[0]),n=(iA(t,"text")??"").toLowerCase(),o=(iA(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=ib(iA(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}function iv(e){let t=iI(e),r=e=>{let r=iA(t,e);if(null!==r)return"true"===r};return{text:iA(t,"text"),desc:iA(t,"content-desc"),resourceId:iA(t,"resource-id"),className:iA(t,"class"),bounds:iA(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function iI(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function iA(e,t){return e.get(t)??null}function ib(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function iS(e){return e?e.toLowerCase():""}function i_(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function iN(e,t={}){return function(e,t){let r=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=iv(t),o=ib(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),a=function(e){let t=0,r=0,a=[...e.children];for(;a.length>0;){let e=a.pop();t+=1,r=Math.max(r,e.depth),a.push(...e.children)}return{rawNodeCount:t,maxDepth:r}}(r),i=[],n=!1,o=t.depth??1/0,s=t.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(r,t.scope):null,l=s?[s]:r.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,r,a,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,y,v,I,A,b,S,_;if(i.length>=800){n=!0;return}if(r>o)return;let N=!!t.raw||(d=e,p=t,f=s,m=u(e),h=l,y=iS(d.type),v=!!(d.label&&d.label.trim().length>0),I=!!(d.identifier&&d.identifier.trim().length>0),A=v&&!i_(d.label??""),b=I&&!i_(d.identifier??""),S=(g=(w=y).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===y||"imagebutton"===y,p.interactiveOnly?!!d.hittable||!!(A||b)&&!_&&(!S||!!h)&&(f||m||h):p.compact?A||b||!!d.hittable:!S&&!_||!!d.hittable||!!A||!!b&&!!m||m),D=a;N&&(D=i.length,i.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:r,parentIndex:a}));let x=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=iS(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(c(t,r+1,D,x,k),n)return};for(let e of l)if(c(e,0,void 0,!1,!1),n)break;return n?{nodes:i,truncated:n,analysis:a}:{nodes:i,analysis:a}}(await iD(e),t)}async function iD(e){return e_(()=>ix(e),{shouldRetry:iM})}async function ix(e){var t,r,a;let i,n,o=await O("adb",r4(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=ik(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await O("adb",r4(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),u=(t=l,r=d.stdout,a=d.stderr,i=`${r}
17
+ ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),c=await O("adb",r4(e,["shell","cat",u])),p=ik(c.stdout,c.stderr);if(!p)throw new $("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function ik(e,t){let r=`${e}
18
+ ${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function iM(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function iE(e,t,r){await O("adb",r4(e,["shell","input","tap",String(t),String(r)]))}async function iO(e,t,r,a,i,n=250){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function iL(e){await O("adb",r4(e,["shell","input","keyevent","4"]))}async function iC(e){await O("adb",r4(e,["shell","input","keyevent","3"]))}async function iP(e){await O("adb",r4(e,["shell","input","keyevent","187"]))}async function iR(e,t,r,a=800){await O("adb",r4(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function iT(e,t,r=0){r>0&&Array.from(t).length>1?await iH(e,t,1,r):await i$(e,t)}async function i$(e,t){let r=iW(t);if(!r||"ok"!==await iz(e,t))try{let r=t.replace(/ /g,"%s");await O("adb",r4(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return!!(t.includes("exception occurred while executing 'text'")||t.includes("nullpointerexception")&&t.includes("inputshellcommand.sendtext"))}(e))throw new $("COMMAND_FAILED","Non-ASCII text input is not supported on this Android shell. Install an ADB keyboard IME or use ASCII input.",{textPreview:t.slice(0,32)},e instanceof Error?e:void 0);throw e}}async function iF(e,t,r){await iE(e,t,r)}async function iU(e,t,r,a,i=0){let n=Array.from(a).length,o=iW(a),s=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];!o&&i<=0&&s.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),(!o||i>0)&&s.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96});let l=null;for(let o of s){var d,u;await iF(e,t,r);let s=(d=n+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await iJ(e,s),"input_text"===o.strategy)await iT(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await iz(e,a))continue}else await iH(e,a,1,i>0?i:15);let c=await iV(e,t,r,a);if(l=c.actual,c.ok)return}throw new $("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function iV(e,t,r,a){let i=null;for(let n of[0,150,350])if(n>0&&await r6(n),function(e,t){if(e===t)return!0;let r=iG(e),a=iG(t);return!!r&&!!a&&(!!(r===a||r.includes(a))||a.includes(r)&&r.length>=Math.max(4,Math.floor(.8*a.length)))}(i=await iK(e,t,r),a))return{ok:!0,actual:i};return{ok:!1,actual:i}}function iG(e){return(e??"").replace(/\s+/g," ").trim()}async function ij(e,t,r){let a=await iq(e),i=ig({direction:t,amount:r?.amount,pixels:r?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await O("adb",r4(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function iB(e,t,r){let a=r?.maxScrolls??8,i="";try{i=await iD(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(iy(i,t))return{attempts:0};for(let r=1;r<=a;r+=1){await ij(e,"down",{amount:.5});let a="";try{a=await iD(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new $("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(iy(a,t))return{attempts:r};if(a===i)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:r,stalled:!0});i=a}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${t}`,{reason:"not_found",attempts:a})}async function iq(e){let t=(await O("adb",r4(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new $("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iH(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await i$(e,r),a>0&&t+i<n.length&&await r6(a)}}function iW(e){for(let t of e){let e=t.codePointAt(0);if(void 0!==e&&(e<32||e>126))return!0}return!1}async function iz(e,t){let r=await O("adb",r4(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":r5(r.stdout,r.stderr)?"unsupported":0===(await O("adb",r4(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await O("adb",r4(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function iJ(e,t){let r=Math.max(0,t);await O("adb",r4(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await O("adb",r4(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function iK(e,t,r){let a,i=await iD(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=iv(a[0]),i=ib(e.bounds);if(!i)continue;let n=e.className??"",d=(e.text??"").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),u=e.focused??!1;if(!d)continue;let c=Math.max(1,i.width*i.height),p=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&iX(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iX(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}p&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function iX(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iY(e){let t=await O("adb",r4(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function iZ(e){let t=await iY(e),r=t,a=0;for(;r.visible&&a<2;)await O("adb",r4(e,["shell","input","keyevent","111"])),a+=1,await r6(120),r=await iY(e);if(t.visible&&r.visible)throw new $("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:r.inputType,type:r.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function iQ(e){let t,r;return(r=(t=(await i1(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?r[1]??"":"null"===t.trim().toLowerCase()?"":t}async function i0(e,t){await i1(e,["shell","cmd","clipboard","set","text",t],"write")}async function i1(e,t,r){let a=await O("adb",r4(e,t),{allowFailure:!0});if(r5(a.stdout,a.stderr))throw new $("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new $("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let i2=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function i3(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new $("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function i4(e){let t=e?.trim().toLowerCase();if("camera"===t||"microphone"===t||"photos"===t||"contacts"===t||"contacts-limited"===t||"notifications"===t||"calendar"===t||"location"===t||"location-always"===t||"media-library"===t||"motion"===t||"reminders"===t||"siri"===t)return t;throw new $("INVALID_ARGS",`permission setting requires a target: ${i2.join("|")}`)}function i8(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new $("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function i5(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=i9(r);await O("adb",r4(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=i9(r);await O("adb",r4(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await O("adb",r4(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=i9(r);await O("adb",r4(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await i7(e,r);await O("adb",r4(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]));return}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new $("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await i6(e,t);return}case"permission":{if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t=i3(r),n=function(e,t){let r=i4(e);if(t?.trim())throw new $("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new $("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await nt(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await ne(e,a,o);await O("adb",r4(e,["shell","pm",o,a,n.value]));return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function i6(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await O("adb",r4(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
19
+ ${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new $("UNSUPPORTED_OPERATION","Android fingerprint simulation is not supported on this target/runtime.",{deviceId:e.id,action:t,hint:"Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.",attempts:s});throw new $("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function i9(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function i7(e,t){let r=i8(t);if("toggle"!==r)return r;let a=await O("adb",r4(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
20
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"auto"===i?"dark":"dark"===i?"light":"dark"}async function ne(e,t,r){let a=await nr(e),i=[];for(let n of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await O("adb",r4(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:n,stderr:a.stderr,exitCode:a.exitCode})}throw new $("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function nt(e,t,r,a){"grant"===r?await O("adb",r4(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await O("adb",r4(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await O("adb",r4(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await O("adb",r4(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function nr(e){let t=await O("adb",r4(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}async function na(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&i.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new $("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,r){if("string"==typeof r)return e.push("--es",t,r);if("boolean"==typeof r)return e.push("--ez",t,r?"true":"false");if("number"==typeof r&&Number.isFinite(r))return Number.isInteger(r)?e.push("--ei",t,String(r)):e.push("--ef",t,String(r));throw new $("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await O("adb",r4(e,i)),{action:a,extrasCount:s}}let ni=Buffer.from([137,80,78,71,13,10,26,10]);async function nn(e,t){await no(e);try{await r6(1e3),await nl(e,t)}finally{await ns(e).catch(()=>{})}}async function no(e){let t=t=>O("adb",r4(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let r=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await r("clock -e hhmm 0941"),await r("notifications -e visible false")}async function ns(e){await O("adb",r4(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function nl(e,t){let r=await O("adb",r4(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new $("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(ni);if(a<0)throw new $("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+ni.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,i=e.toString("ascii",a,a+4),n=r+12+t;if(n>e.length)break;if("IEND"===i)return n;r=n}return null}(r.stdoutBuffer,a);if(!i)throw new $("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await d.writeFile(t,r.stdoutBuffer.subarray(a,i))}let nd=eF(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eI,5e3),nu=eF(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,ev,1e3),nc=eF(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),np=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),nf=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),nm=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),nh=eF(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function nw(e,t){let r=["devicectl",...e],a=await O("xcrun",r,{allowFailure:!0,timeoutMs:np});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new $("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:nv(i,n)??ny})}async function ng(e,t){let r=c.join(u.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],i=await O("xcrun",a,{allowFailure:!0,timeoutMs:np});try{var n,o;if(0!==i.exitCode){let t=String(i.stdout??""),r=String(i.stderr??"");throw new $("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:i.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:nv(t,r)??ny})}let s=await d.readFile(r,"utf8");return n=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let a="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:a})}return r}(JSON.parse(s)),o=t,"user-installed"===o?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof $)throw t;throw new $("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await d.unlink(r).catch(()=>{})}}let ny="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function nv(e,t){let r=`${e}
21
+ ${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function nI(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let r=String(t.stderr??"").toLowerCase();return r.includes("fbsopenapplicationserviceerrordomain")&&r.includes("the request to open")}async function nA(e,t){let r=await O("xcrun",eK(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let a=r.stdout.trim();if(!a)return{installed:!1};let i=await O("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let n=i.stdout.trim(),o=`${a}/${n}`,s=await O("otool",["-l",o],{allowFailure:!0});if(0!==s.exitCode)return{installed:!0};let l=s.stdout.toLowerCase();return{installed:!0,simulatorCompatible:l.includes("iossimulator")||l.includes("platform 7")}}function nb(e,t){if("simulator"!==e.kind)throw new $("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function nS(){await O("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:nf})}async function n_(e){let t,r;if("simulator"!==e.kind||"Booted"===await nD(e))return;let a=eb.fromTimeoutMs(nd);try{await eS(async({deadline:a})=>{if(a?.isExpired())throw new $("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:nd});let i=Math.max(1e3,a?.remainingMs()??nd),n=await O("xcrun",eK(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode};let o=`${t.stdout}
22
+ ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new $("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await O("xcrun",eK(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new $("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await nD(e);if("Booted"!==d)throw new $("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=eU({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>eU({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=eU({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new $("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:nd,elapsedMs:a.elapsedMs(),reason:i,hint:eV(i),boot:t,bootstatus:r})}await nS()}async function nN(e){let t=eK(e,["shutdown",e.id]),r=await O("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function nD(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eJ(["list","devices","-j"]):eK(e,["list","devices","-j"]),a=await O("xcrun",r,{allowFailure:!0,timeoutMs:nu});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function nx(e,t){try{let r=await O("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await d.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!a?.[1])return;let i=a[1].trim().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&amp;/g,"&");return i.length>0?i:void 0}(r,t)}catch{return}}async function nk(e,t){if("url"===e.kind&&!aO(e.url))throw new $("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let r=await ax({source:e,isInstallablePath:(e,t)=>t.isDirectory()&&e.toLowerCase().endsWith(".app")||t.isFile()&&e.toLowerCase().endsWith(".ipa"),installableLabel:"iOS installable (.app or .ipa)",allowArchiveExtraction:"url"!==e.kind||aO(e.url),signal:t?.signal}),a=await nE(r.installablePath,t),i=await nM(a.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await r.cleanup()}}}async function nM(e){let t=c.join(e,"Info.plist"),[r,a,i]=await Promise.all([nx(t,"CFBundleIdentifier"),nx(t,"CFBundleDisplayName"),nx(t,"CFBundleName")]);return{bundleId:r,appName:a??i}}async function nE(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await d.rm(r,{recursive:!0,force:!0})};try{await O("ditto",["-x","-k",e,r]);let i=c.join(r,"Payload"),n=(await d.readdir(i,{withFileTypes:!0}).catch(()=>{throw new $("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:c.join(i,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===n.length)return{installPath:n[0].installPath,cleanup:a};if(0===n.length)throw new $("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await nO(n);let o=t?.appIdentifierHint?.trim();if(o){let e=function(e,t){let r=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===a.length)return a[0];if(a.length>1)throw new $("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(n,o);if(e)return{installPath:e.installPath,cleanup:a};throw new $("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload and none matched "${o}". Available bundles: ${n.map(nL).join(", ")}`)}throw new $("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${n.map(nL).join(", ")}`)}catch(e){throw await a(),e}}async function nO(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await nM(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function nL(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function nC(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let nP="agent-device-macos-helper",nR="AGENT_DEVICE_MACOS_HELPER_BIN",nT=c.join(u.homedir(),".agent-device","macos-helper","current"),n$=c.join(nT,"manifest.json"),nF=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function nU(e){let t=e.trim();if(!nF.test(t))throw new $("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function nV(){return function(e){let t=c.dirname(e);for(;;){let e=c.join(t,"macos-helper");if(l(c.join(e,"Package.swift")))return e;let r=c.dirname(t);if(r===t)break;t=r}throw new $("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(m(import.meta.url))}async function nG(e){let t=await d.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let r=c.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await nG(r):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[r]:[]}))).flat().sort()}async function nj(e){let t=await nG(e),r=o("sha256");for(let a of t)r.update(c.relative(e,a)),r.update("\0"),r.update(await d.readFile(a)),r.update("\0");let a=await O("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return r.update("swift-version"),r.update("\0"),r.update(a.stdout||a.stderr||`exit:${a.exitCode}`),r.update("\0"),r.digest("hex")}async function nB(){try{let e=JSON.parse(await d.readFile(n$,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function nq(){let e=process.env[nR]?.trim();if(e)return e;let t=nV(),r=await nj(t),a=c.join(nT,nP);try{if(await nB()===r)return await d.access(a),a}catch{}let i=c.join(nV(),".build","release",nP);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await O("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await d.mkdir(nT,{recursive:!0});let n=`${a}.tmp`;return await d.copyFile(i,n),await d.rename(n,a),await d.chmod(a,493),await d.writeFile(n$,`${JSON.stringify({fingerprint:r},null,2)}
23
+ `,"utf8"),a}async function nH(e){let t=process.env[nR]?.trim();if("darwin"!==process.platform&&!t)throw new $("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let r=await nq(),a=await O(r,e,{allowFailure:!0,timeoutMs:3e4}),i=a.stdout.trim(),n=null;if(i)try{n=JSON.parse(i)}catch{n=null}if(0===a.exitCode&&n?.ok)return n.data;throw new $("COMMAND_FAILED",n&&!n.ok?n.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:r,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...n&&!n.ok?n.error?.details:{}})}async function nW(){return await nH(["app","frontmost"])}async function nz(e){return await nH(["app","quit","--bundle-id",nU(e)])}async function nJ(e,t){return await nH(["permission",e,t])}async function nK(e,t={}){let r=["alert",e];return t.bundleId&&r.push("--bundle-id",nU(t.bundleId)),t.surface&&r.push("--surface",t.surface),await nH(r)}async function nX(e,t={}){let r=["snapshot","--surface",e];return t.bundleId&&r.push("--bundle-id",nU(t.bundleId)),await nH(r)}async function nY(e,t,r={}){let a=["read","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",nU(r.bundleId)),r.surface&&a.push("--surface",r.surface),await nH(a)}async function nZ(e,t,r={}){let a=["press","--x",String(e),"--y",String(t)];return r.bundleId&&a.push("--bundle-id",nU(r.bundleId)),r.surface&&a.push("--surface",r.surface),await nH(a)}async function nQ(e,t={}){let r=["screenshot","--out",e];return t.surface&&r.push("--surface",t.surface),t.fullscreen&&r.push("--fullscreen"),await nH(r)}let n0={settings:"com.apple.systempreferences"},n1=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function n2(e,t){let r=["-b",e];return t&&r.push(t),r}async function n3(e){for(let t of[c.join(e,"Contents","Info.plist"),c.join(e,"Info.plist")]){let[e,r,a]=await Promise.all([nx(t,"CFBundleIdentifier"),nx(t,"CFBundleDisplayName"),nx(t,"CFBundleName")]);if(e||r||a)return{bundleId:e,appName:r??a}}return{}}async function n4(e){let t=e.trim(),r=n0[t.toLowerCase()];if(r)return r;if(n1.test(t))return t;let a=(await ot("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new $("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new $("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function n8(e,t,r){let a=r?.url?.trim();if(a){if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=r?.appBundleId??await n4(t);await O("open",n2(e,a));return}let i=t.trim();if(r9(i))return void await O("open",[i]);let n=r?.appBundleId??await n4(i);await O("open",n2(n))}async function n5(e,t){let r=await n4(t),a=await nz(r);if(a.running&&!a.terminated&&!a.forceTerminated)throw new $("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:r,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function n6(){let e=await O("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to read macOS clipboard",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});return e.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function n9(e){let t=await O("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function n7(){let e=await O("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new $("COMMAND_FAILED","Failed to read macOS appearance",{stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode});let t=e.stdout.trim().toLowerCase();if("true"===t)return!0;if("false"===t)return!1;throw new $("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function oe(e){let t=i8(e),r="toggle"===t?!await n7():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${r?"true":"false"}`,i=await O("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new $("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function ot(e="all"){let t=["/Applications","/System/Applications",c.join(u.homedir(),"Applications")],r=new Set;for(let e of t){let t=await d.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await O("find",[e,"-maxdepth","4","-type","d","-name","*.app"],{allowFailure:!0});if(0===a.exitCode)for(let e of a.stdout.split("\n")){let t=e.trim();t&&r.add(t)}}return nC((await Promise.all(Array.from(r).map(async e=>{let t=await n3(e).catch(()=>({})),r=t.bundleId;return r?{bundleId:r,name:t.appName??c.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let or=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],oa={0:"hide",1:"wifi",6:"3g",7:"4g",8:"lte",9:"lte-a",10:"lte+",11:"5g",12:"5g+",13:"5g-uwb",14:"5g-uc"},oi={1:"searching",2:"failed",3:"active"},on={0:"notSupported",1:"searching",2:"failed",3:"active"};function oo(e,t,r){return O("xcrun",eK(e,t),r)}async function os(e,t){var r,a;let i;await od(e),t&&await ou(e,(i=[],(r=t).dataNetwork&&i.push("--dataNetwork",r.dataNetwork),r.wifiMode&&i.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&i.push("--wifiBars",r.wifiBars),r.cellularMode&&i.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(a=r.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==r.operatorName)&&i.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&i.push("--operatorName",r.operatorName),i))}async function ol(e){let t=await oo(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to read simulator status bar overrides",{exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr});return function(e){let t={};for(let r of e.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&"Current Status Bar Overrides:"!==e&&!/^=+$/.test(e))){let e=/^DataNetworkType:\s+(\d+)$/.exec(r);if(e){let r=Number(e[1]),a=oa[r];if(!a)throw new $("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(a){let e=oi[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(i){let e=Number(i[1]),r=on[e];if(!r)throw new $("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=i[2];continue}let n=/^Operator Name:\s*(.*)$/.exec(r);if(n){t.operatorName=n[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function od(e){await oo(e,["status_bar",e.id,"clear"])}async function ou(e,t){0!==t.length&&await oo(e,["status_bar",e.id,"override",...t])}function oc(e,t,r){Q({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof $))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}(r)}})}function op(e,t,r){return O("xcrun",eK(e,t),r)}let of={ensureBooted:n_,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await ol(e),r=!0}catch(t){oc(e,"snapshot_failed",t)}try{await od(e),await ou(e,or)}catch(t){oc(e,"prepare_failed",t)}return async()=>{await os(e,r?t:null)}},captureWithRetry:ow,captureWithRunner:og,shouldFallbackToRunner:o_};async function om(e,t,r,a){if("macos"===e.platform)return void await og(e,t,r,a);if("simulator"===e.kind)return void await oh(e,t,r,a);try{await nw(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
22
24
  ${r}
23
- ${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;om(e,"devicectl_screenshot",t)}await ou(e,t,r,a)}async function ol(e,t,r,a,i=oo){if("simulator"!==e.kind)throw new $("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let n="object"==typeof a&&null!==a?a:i;await n.ensureBooted(e);let o=async()=>{};try{o=await n.prepareStatusBarForScreenshot(e)}catch(t){oh(e,"prepare_failed",t)}try{try{await n.captureWithRetry(e,t);return}catch(t){if(!n.shouldFallbackToRunner(t))throw t;om(e,"simctl_screenshot",t)}await n.captureWithRunner(e,t,r,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>oh(e,"restore_failed",t))}}async function od(e,t){let r=eb.fromTimeoutMs(ns);await eS(async({deadline:r})=>{await on(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,r?.remainingMs()??ns)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>og(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function ou(e,t,r,a){let i=(await tz(e,{command:"screenshot",appBundleId:r,fullscreen:a})).message;if(!i)throw new $("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await d.copyFile(i,t):"simulator"===e.kind?await of(e,i,t):await oc(e,i,t)}async function oc(e,t,r){let a=eb.fromTimeoutMs(nl),i={exitCode:1,stdout:"",stderr:""};for(let n of ty)if(0===(i=await O("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:op(a,nl,"runner screenshot copy")})).exitCode)return;let n=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new $("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function of(e,t,r){let a=eb.fromTimeoutMs(nl),i="Unable to locate runner container for simulator screenshot";for(let n of ty){let o=await on(e,["get_app_container",e.id,n,"data"],{allowFailure:!0,timeoutMs:op(a,nl,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(i=e);continue}let s=o.stdout.trim();if(!s){i="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=c.resolve(e),a=t.trim();if(!a)return[];let i=[],n=new Set,o=e=>{let t=c.normalize(e);n.has(t)||(n.add(t),i.push(t))},s=a.replace(/^\/+/,""),l=s.replace(/\\/g,"/");if(s&&o(c.join(r,s)),c.isAbsolute(a)&&o(c.normalize(a)),l.startsWith("tmp/"))o(c.join(r,l));else{let e=l.lastIndexOf("/tmp/");if(e>=0){let t=l.slice(e+1);o(c.join(r,t))}}let d=c.basename(a);return d&&o(c.join(r,"tmp",d)),i}(s,t))try{await d.copyFile(e,r);return}catch(e){i=e instanceof Error?e.message:String(e)}}throw new $("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}function op(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new $("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function om(e,t,r){let a=ow(r);Q({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function oh(e,t,r){Q({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...ow(r)}})}function ow(e){if(!(e instanceof $))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}function og(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",n=`${e.message}
25
+ ${a}`.toLowerCase();return i.includes("unknown option '--device'")||i.includes("unknown subcommand")&&i.includes("screenshot")||i.includes("unrecognized subcommand")&&i.includes("screenshot")}(t))throw t;oA(e,"devicectl_screenshot",t)}await og(e,t,r,a)}async function oh(e,t,r,a,i=of){if("simulator"!==e.kind)throw new $("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let n="object"==typeof a&&null!==a?a:i;await n.ensureBooted(e);let o=async()=>{};try{o=await n.prepareStatusBarForScreenshot(e)}catch(t){ob(e,"prepare_failed",t)}try{try{await n.captureWithRetry(e,t);return}catch(t){if(!n.shouldFallbackToRunner(t))throw t;oA(e,"simctl_screenshot",t)}await n.captureWithRunner(e,t,r,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>ob(e,"restore_failed",t))}}async function ow(e,t){let r=eb.fromTimeoutMs(nm);await eS(async({deadline:r})=>{await op(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,r?.remainingMs()??nm)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>o_(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function og(e,t,r,a){let i=(await tz(e,{command:"screenshot",appBundleId:r,fullscreen:a})).message;if(!i)throw new $("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await d.copyFile(i,t):"simulator"===e.kind?await ov(e,i,t):await oy(e,i,t)}async function oy(e,t,r){let a=eb.fromTimeoutMs(nh),i={exitCode:1,stdout:"",stderr:""};for(let n of tv)if(0===(i=await O("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:oI(a,nh,"runner screenshot copy")})).exitCode)return;let n=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new $("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function ov(e,t,r){let a=eb.fromTimeoutMs(nh),i="Unable to locate runner container for simulator screenshot";for(let n of tv){let o=await op(e,["get_app_container",e.id,n,"data"],{allowFailure:!0,timeoutMs:oI(a,nh,"runner screenshot container lookup")});if(0!==o.exitCode){let e=o.stderr.trim();e&&(i=e);continue}let s=o.stdout.trim();if(!s){i="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=c.resolve(e),a=t.trim();if(!a)return[];let i=[],n=new Set,o=e=>{let t=c.normalize(e);n.has(t)||(n.add(t),i.push(t))},s=a.replace(/^\/+/,""),l=s.replace(/\\/g,"/");if(s&&o(c.join(r,s)),c.isAbsolute(a)&&o(c.normalize(a)),l.startsWith("tmp/"))o(c.join(r,l));else{let e=l.lastIndexOf("/tmp/");if(e>=0){let t=l.slice(e+1);o(c.join(r,t))}}let d=c.basename(a);return d&&o(c.join(r,"tmp",d)),i}(s,t))try{await d.copyFile(e,r);return}catch(e){i=e instanceof Error?e.message:String(e)}}throw new $("COMMAND_FAILED",`Failed to capture iOS screenshot: ${i}`)}function oI(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new $("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function oA(e,t,r){let a=oS(r);Q({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function ob(e,t,r){Q({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...oS(r)}})}function oS(e){if(!(e instanceof $))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}function o_(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",n=`${e.message}
24
26
  ${r}
25
27
  ${a}
26
- ${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let ov={settings:"com.apple.Preferences"},oy=null;function oI(e,t,r){return O("xcrun",eK(e,t),r)}function oA(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function ob(e,t){if("macos"===e.platform)return await nY(t);let r=t.trim();if(r.includes("."))return r;let a=ov[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await oR(e):await nu(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new $("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new $("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function oS(e,t,r){if("macos"===e.platform)return void await nZ(e,t,r);let a=r?.url?.trim();if(a){if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await ng(e),await oI(e,["openurl",e.id,a]);return}let i=r7(r?.appBundleId??await ob(e,t),a);if(!i)throw new $("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oq(e,i,{payloadUrl:a});return}let i=t.trim();if(r9(i)){if("simulator"===e.kind){await ng(e),await oI(e,["openurl",e.id,i]);return}let t=r7(r?.appBundleId,i);if(!t)throw new $("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oq(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await ob(e,t);"simulator"===e.kind?await oB(e,n):await oq(e,n)}async function o_(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await ny(e)&&await ng(e)}async function oN(e,t){if("macos"===e.platform)return void await nQ(e,t);let r=await ob(e,t);if("simulator"===e.kind){await ng(e);let t=eK(e,["terminate",e.id,r]),a=await O("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new $("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await nd(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function oD(e,t){let r=await ob(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await O("xcrun",t,{allowFailure:!0,timeoutMs:nn});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!oA(`${i}
27
- ${n}`.toLowerCase()))throw new $("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:e.id,hint:nf(i,n)??nc})}return{bundleId:r}}await ng(e);let a=await oI(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!oA(`${a.stdout}
28
- ${a.stderr}`.toLowerCase()))throw new $("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function ox(e,t,r){let a=await nA({kind:"path",path:t},r);try{return await oE(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function oM(e,t,r){let{bundleId:a}=await oD(e,t);return await ox(e,r,{appIdentifierHint:t}),{bundleId:a}}async function oE(e,t){"simulator"!==e.kind?await nd(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await ng(e),await oI(e,["install",e.id,t]))}async function ok(e){if("macos"===e.platform)return await n0();nh(e,"clipboard"),await ng(e);let t=await oI(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to read iOS simulator clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function oO(e,t){if("macos"===e.platform)return void await n1(t);nh(e,"clipboard"),await ng(e);let r=await oI(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new $("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function oL(e,t,r){nh(e,"push"),await ng(e);let a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-ios-push-")),i=c.join(a,"payload.apns");try{await d.writeFile(i,`${JSON.stringify(r)}
29
- `,"utf8"),await oI(e,["push",e.id,t,i])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function oC(e,t,r,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await n3(r);if("permission"===e){let e=iX(r);if("deny"===e)throw new $("INVALID_ARGS",U("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new $("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nG(e,t)}throw new $("INVALID_ARGS",U(t))}nh(e,"settings"),await ng(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=oT(r);await oI(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(oT(r)?await oI(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await oI(e,["status_bar",e.id,"clear"]));case"location":{let t=oT(r);if(!a)throw new $("INVALID_ARGS","location setting requires an active app in session");await oI(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=oF[n],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new $("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await oj(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await o$(e,r);await oI(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=iX(r))?"revoke":o,n=function(e,t){let r=iY(e);if("photos"!==r&&t?.trim())throw new $("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return"camera";if("microphone"===r)return"microphone";if("contacts"===r)return"contacts";if("contacts-limited"===r)return"contacts-limited";if("notifications"===r)return"notifications";if("calendar"===r)return"calendar";if("location"===r)return"location";if("location-always"===r)return"location-always";if("media-library"===r)return"media-library";if("motion"===r)return"motion";if("reminders"===r)return"reminders";if("siri"===r)return"siri";if("photos"===r){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new $("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new $("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(i?.permissionTarget,i?.permissionMode);await oU(e,t,n,a);return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function oP(e,t="all"){return"macos"===e.platform?await n4(t):"simulator"===e.kind?nD(await oR(e),t):await nu(e,t)}async function oR(e){let t=(await oI(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await O("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function oT(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function o$(e,t){let r=iZ(t);if("toggle"!==r)return r;let a=await oI(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
30
- ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let oF={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function oU(e,t,r,a){let i=await oG(e);if(!i.has(r))throw new $("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let n=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await oI(e,n);return}catch(t){if(!(o&&oV(t)))throw t;throw new $("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:a,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await oI(e,n);return}catch(e){if(!oV(e))throw e}try{await oI(e,["privacy",e.id,"reset","all",a])}catch(t){throw new $("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:a,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function oV(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return(t.includes("failed to grant access")||t.includes("failed to revoke access")||t.includes("failed to reset access"))&&t.includes("operation not permitted")}async function oG(e){let r=eH(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(oy&&t===a)return oy;let i=await oI(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
31
- ${i.stderr}`);if(0===n.size)throw new $("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return oy=n,t=a,n}async function oj(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),i=[];for(let t of a){let r=eK(e,t),a=await O("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
32
- ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new $("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new $("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oB(e,t){await ng(e);let r=0,a=eb.fromTimeoutMs(ni);try{await eS(async({deadline:r})=>{var a;if(r?.isExpired())throw new $("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:ni});let i=(a=["launch",e.id,t],eK(e,a)),n=await O("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!np(e)&&(r+=1)<3},{deadline:a})}catch(r){if(np(r)){var i;let a=(i=await nm(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oq(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await nd(a,{action:"launch iOS app",deviceId:e.id})}async function oH(e,t,r,a){let i=a?.maxScrolls??48,n=await e({command:"findText",text:r});if(n?.found)return{attempts:0};let o=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=i;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let i=await e({command:"findText",text:r});if(i?.found)return{attempts:a};let n=oW(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(n===o)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=n}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:i})}function oW(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function oz(e,t,r,a,i,n,o){if("tv"===t.target)return oX(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(i),appBundleId:r.appBundleId},a),n);let s=o??await oJ(e,t,r,a),l=ic({direction:i,amount:n?.amount,pixels:n?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return oX(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function oJ(e,t,r,a){let i=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),n=oK(i.x),o=oK(i.y),s=oK(i.referenceWidth),l=oK(i.referenceHeight);if(void 0===n||void 0===o||void 0===s||void 0===l)throw new $("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:n,originY:o,referenceWidth:s,referenceHeight:l}}function oK(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function oX(e,t){var r;let{x1:a,y1:i,x2:n,y2:o}={x1:oK((r=e).x),y1:oK(r.y),x2:oK(r.x2),y2:oK(r.y2)},s=oK(e.referenceWidth),l=oK(e.referenceHeight),d=void 0!==a&&void 0!==n?Math.round(Math.abs(n-a)):void 0,u=void 0!==i&&void 0!==o?Math.round(Math.abs(o-i)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==i?{y1:i}:{},...void 0!==n?{x2:n}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function oY(e){return e?.clickButton??"primary"}function oZ(e){return"primary"===e.button?null:"click"!==e.commandLabel?new $("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new $("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new $("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new $("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let oQ=/^[A-Za-z0-9_.:-]{1,64}$/,o0=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function o1(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new $("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function o2(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await o3(t)}async function o3(e){await new Promise(t=>setTimeout(t,e))}function o4(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new $("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!s.statSync(n).isFile())throw new $("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof $)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new $("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new $("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new $("INVALID_ARGS",`${a} file not found: ${n}`)}async function o8(e){let t=o4(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await o5(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new $("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function o5(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new $("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new $("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new $("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new $("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let o6=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),o9=/^(iphone|ipad|ipod|appletv)/i,o7=/^appletv/i,se=["apple tv","appletv","tvos"];function st(e){return(e??"").trim().toLowerCase()}function sr(e){return st(e.hardwareProperties?.platform)}function sa(e){return e.includes("tvos")}function si(e){return sa(st(e))?"tv":"mobile"}function sn(e){let t=st(e);return t.includes("ios")||t.includes("tvos")}function so(e){let t=st(e);return se.some(e=>t.includes(e))}function ss(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function sl(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function sd(e={}){let t,r,a=eH(e.simulatorSetPath),i=e.target;try{t=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!sn(e))continue;let r=si(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function su(e={}){if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await V("xcrun"))throw new $("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eH(e.simulatorSetPath),a=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(sn(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:si(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new $("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=c.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await O("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:o6});if(0!==e.exitCode)return t;let r=await d.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=sr(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=sl(e),!!o9.test(t.trim())||ss(e).some(so))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return sa(sr(e))?"tv":(t=sl(e),o7.test(t.trim())||ss(e).some(so))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{i&&await d.rm(i,{force:!0}).catch(()=>{})}return t}async function sc(e,t,r){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await tu(e,t,r)}catch(e){if(i||!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!i&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await sd({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function sf(e){let t=e.platform,r=td({simulatorSetPath:eH(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=ez(e.androidDeviceAllowlist);return await X("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new $("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await r8();let e=await af({serialAllowlist:a});return await tu(e,i)}if(i.platform){let e=await su({simulatorSetPath:r});return await sc(e,i,{simulatorSetPath:r})}let n=[];try{n.push(...await af({serialAllowlist:a}))}catch{}try{n.push(...await su({simulatorSetPath:r}))}catch{}return await tu(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function sp(e,t,r,a,i){let n={requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>a4(e,t,r?.activity),openDevice:()=>a5(e),close:t=>a6(e,t),tap:(t,r)=>iN(e,t,r),doubleTap:async(t,r)=>{await iN(e,t,r),await iN(e,t,r)},swipe:(t,r,a,i,n)=>iD(e,t,r,a,i,n),longPress:(t,r,a)=>ik(e,t,r,a),focus:(t,r)=>iC(e,t,r),type:(t,r)=>iO(e,t,r),fill:(t,r,a,i)=>iP(e,t,r,a,i),scroll:(t,r)=>iR(e,t,r),scrollIntoView:(t,r)=>iT(e,t,r),screenshot:t=>i9(e,t),back:t=>ix(e),home:()=>iM(e),appSwitcher:()=>iE(e),readClipboard:()=>iW(e),writeClipboard:t=>iz(e,t),setSetting:(t,r,a,i)=>iQ(e,t,r,a,i)};case"ios":case"macos":{let r,a,{overrides:i,runnerOpts:n}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eP(t.requestId))throw eT()},{runnerOpts:r,overrides:{tap:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),doubleTap:async(a,i)=>await tz(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,i,n,o,s)=>await tz(e,{command:"drag",x:a,y:i,x2:n,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,i,n)=>await tz(e,{command:"longPress",x:a,y:i,durationMs:n,appBundleId:t.appBundleId},r),focus:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),type:async(a,i)=>{await tz(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},r)},fill:async(a,i,n,o)=>{let s=await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r);return await tz(e,{command:"type",x:a,y:i,text:n,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,i)=>await oz(tz,e,t,r,a,i),scrollIntoView:async(i,n)=>await oH(a=>tz(e,{...a,appBundleId:t.appBundleId},r),a,i,n)}});return{open:(t,r)=>oS(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>o_(e),close:t=>oN(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await nW(t,{surface:r.surface,fullscreen:r.fullscreen}):await os(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await tz(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},n)},home:async()=>{await tz(e,{command:"home",appBundleId:t.appBundleId},n)},appSwitcher:async()=>{await tz(e,{command:"appSwitcher",appBundleId:t.appBundleId},n)},readClipboard:()=>ok(e),writeClipboard:t=>oO(e,t),setSetting:(t,r,a,i)=>oC(e,t,r,a,i),...i}}default:throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,n);return Q({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await X("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new $("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null,...Y("Opened device")};if(void 0!==a){if("android"===e.platform)throw new $("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(r9(t))throw new $("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a,...Y(`Opened: ${t}`)}}return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t,...Y(`Opened: ${t}`)}}case"close":{let e=r[0];if(!e)return{closed:"session",...Y("Closed session")};return await o.close(e),{app:e,...Y(`Closed: ${e}`)}}case"press":{let t,[a,n]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(n))throw new $("INVALID_ARGS","press requires x y");if("macos"===e.platform&&i?.surface&&"app"!==i.surface){let e=oY(i);if("primary"!==e)throw new $("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${i.surface} sessions.`);return await nH(a,n,{bundleId:i.appBundleId,surface:i.surface}),{x:a,y:n,...Y(sm({x:a,y:n}))}}let s=oY(i);if("primary"!==s){let t=oZ({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tz(e,{command:"mouseClick",x:a,y:n,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:n,button:s,...Y(sm({x:a,y:n,button:s}))}}let l=o1(i?.count??1,"count",1,200),d=o1(i?.intervalMs??0,"interval-ms",0,1e4),u=o1(i?.holdMs??0,"hold-ms",0,1e4),c=o1(i?.jitterPx??0,"jitter-px",0,100),f=i?.doubleTap===!0;if(f&&u>0)throw new $("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&c>0)throw new $("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tz(e,{command:"tapSeries",x:a,y:n,count:l,intervalMs:d,doubleTap:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,timingMode:"runner-series",...t,...Y(sm({x:a,y:n}))}}return await o2(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=o0[e%o0.length];return[r*t,a*t]}(e,c),s=a+r,l=n+i;if(f){t??=await o.doubleTap(s,l)??void 0;return}u>0?t??=await o.longPress(s,l,u)??void 0:t??=await o.tap(s,l)??void 0}),T({x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:f,...t},sm({x:a,y:n}))}case"swipe":{let t=Number(r[0]),a=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,a,n,s].some(Number.isNaN))throw new $("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=o1(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=o1(i?.count??1,"count",1,200),c=o1(i?.pauseMs??0,"pause-ms",0,1e4),f=i?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new $("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tz(e,{command:"dragSeries",x:t,y:a,x2:n,y2:s,durationMs:d,count:u,pauseMs:c,pattern:f,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:f,...r,...Y(sh(u,f))}}return await o2(u,c,async e=>{"ping-pong"===f&&e%2==1?await o.swipe(n,s,t,a,d):await o.swipe(t,a,n,s,d)}),T({x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:f},sh(u,f))}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...Y(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...Y(`Focused (${e}, ${t})`)}}case"type":{let e=r.join(" ");if(!e)throw new $("INVALID_ARGS","type requires text");let t=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.type(e,t),{text:e,delayMs:t,...Y(sw("Typed",e))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new $("INVALID_ARGS","fill requires x y text");let n=o1(i?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,n),{x:e,y:t,text:a,delayMs:n,...Y(sw("Filled",a))}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0,a=i?.pixels;if(!e)throw new $("INVALID_ARGS","scroll requires direction");if(void 0!==t&&!Number.isFinite(t))throw new $("INVALID_ARGS","scroll amount must be a number");if(void 0!==t&&void 0!==a)throw new $("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let n=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new $("INVALID_ARGS",`Unknown direction: ${e}`)}}(e),s=await o.scroll(n,{amount:t,pixels:a});return T({direction:n,...void 0!==t?{amount:t}:{},...void 0!==a?{pixels:a}:{},...s},void 0!==a?`Scrolled ${n} by ${a}px`:void 0!==t?`Scrolled ${n} by ${t}`:`Scrolled ${n}`)}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new $("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:i?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...Y(`Scrolled into view: ${e}`)};return{text:e,...Y(`Scrolled into view: ${e}`)}}case"pinch":{if("android"===e.platform)throw new $("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&i?.surface&&"app"!==i.surface)throw new $("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new $("INVALID_ARGS","pinch requires scale > 0");return await tz(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n,...Y(`Pinched to scale ${t}`)}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new $("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oQ.test(t))throw new $("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new $("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),n=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new $("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new $("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(n,{appBundleId:i?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link",...Y(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(c.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:i?.appBundleId,fullscreen:i?.screenshotFullscreen,surface:i?.surface}),{path:e,...Y(`Saved screenshot: ${e}`)}}case"back":return await o.back(i?.backMode),{action:"back",mode:i?.backMode??"in-app",...Y("Back")};case"home":return await o.home(),{action:"home",...Y("Home")};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...Y("Opened app switcher")};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new $("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new $("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new $("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length,...Y("Clipboard updated")}}case"keyboard":{let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new $("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new $("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===t){let t=await iH(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let r=await iq(e);return{platform:"android",action:"status",visible:r.visible,inputType:r.inputType,type:r.type}}if("ios"===e.platform){if("dismiss"!==t)throw new $("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let r=await tz(e,{command:"keyboardDismiss",appBundleId:i?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:r.wasVisible,dismissed:r.dismissed,visible:r.visible,...Y(r.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new $("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}case"settings":{var s;let[t,a,n,l,d]=r,u="permission"===t?{permissionTarget:n,permissionMode:l}:void 0;Q({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:n,mode:l,platform:e.platform}});let c=await o.setSetting(t,a,d??i?.appBundleId,u);return c&&"object"==typeof c?T({setting:t,state:a,...c},("string"==typeof(s=c).message&&s.message.length>0?s.message:void 0)??`Updated setting: ${t}`):{setting:t,state:a,...Y(`Updated setting: ${t}`)}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new $("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await o8(a);if("ios"===e.platform)return await oL(e,t,i),{platform:"ios",bundleId:t,...Y(`Pushed notification to ${t}`)};let n=await i5(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount,...Y(`Pushed notification to ${t}`)}}case"snapshot":{if("android"!==e.platform){let t=await X("snapshot_capture",async()=>await tz(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new $("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await X("snapshot_capture",async()=>await iI(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new $("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await ij(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nq(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tz(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new $("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}function sm(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sh(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sw(e,t){return`${e} ${Array.from(t).length} chars`}let sg=e=>"macos"!==e.platform,sv=e=>"macos"===e.platform||"simulator"===e.kind,sy={alert:{apple:{simulator:!0,device:!0},android:{},supports:sv},pinch:{apple:{simulator:!0,device:!0},android:{},supports:sv},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:sg},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function sI(e,t){let r=sy[e];if(!r)return!0;let a=ts(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function sA(e,t,r,a,i){return{requestId:i??J().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:oY(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let sb=eF(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sS(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eh);await t(e);return}if("device"===e.kind)return void await s_(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ec);await t(e.id)}}async function s_(e){let t=c.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(sb/1e3));try{let a=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:sb+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await sN(t);if(0===a.exitCode){if(!o.parsed)throw new $("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sD(i,n)})}catch(t){if(t instanceof $&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??sb),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sD(a,i):o},t)}throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function sN(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sD(e,t){let r=nf(e,t);return r||(`${e}
33
- ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":nc)}let sx=eF(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sM=new Map;async function sE(e){let t=await y.mkdtemp(c.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await sL(e.installablePath,c.join(t,"installable")),a=e.archivePath?await sL(e.archivePath,c.join(t,"archive")):void 0,i=n.randomUUID(),o=e.ttlMs??sx,s=Date.now()+o,l=setTimeout(()=>{sk(i)},o);return sM.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await y.rm(t,{recursive:!0,force:!0}),e}}async function sk(e,t){let r=sM.get(e);if(!r)throw new $("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),sM.delete(e),await y.rm(r.rootPath,{recursive:!0,force:!0})}async function sO(e){let t=Array.from(sM.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sk(e)}))}async function sL(e,t){let r=await y.stat(e);await y.mkdir(t,{recursive:!0});let a=c.join(t,c.basename(e));return r.isDirectory()?await y.cp(e,a,{recursive:!0}):await y.copyFile(e,a),a}async function sC(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new $("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await sS(e.session.device),e.session.device}if(!r)throw new $("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await sf(e.flags??{});return await sS(a),a}async function sP(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new $("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new $("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new $("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:r_(o,t.meta?.tenantId)},cleanup:()=>{rN(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new $("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await sC({session:i,flags:t.flags});if(!sI("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eR(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await Promise.resolve(eh),{prepareIosInstallArtifact:o}=await Promise.resolve(ew),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await sE({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new $("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=T(o,sR(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await sk(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(ep),{installAndroidInstallablePathAndResolvePackageName:f}=await Promise.resolve(ef),p=await c(s.source,{signal:u});try{l.enabled&&(e=await sE({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await f(d,p.installablePath,p.packageName);if(!n)throw new $("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve(ef),s=o(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=T(u,sR(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await sk(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:q(e)}}}function sR(e){return`Installed: ${es(e)}`}async function sT(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new $("INVALID_ARGS","release_materialized_paths requires a materializationId");return await sk(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:q(e)}}}let s$=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sF=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function sU(e,t,r){return t||sV(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sV(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sG(e){return"ios"===e.platform&&"simulator"===e.kind}async function sj(e,t){sG(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sB(e){let t=sV(e.flags)||!e.session?await sf(e.flags??{}):await sq(e.session.device);return!1!==e.ensureReady&&await sS(t),t}async function sq(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await sf(t)}catch(e){if(!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await sf({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function sH(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let sW="shared_prefs/ReactNativeDevPrefs.xml",sz="debug_http_host",sJ="dev_server_https",sK="RCT_jsLocation",sX="RCT_packager_scheme",sY="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",sZ='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function sQ(e){return void 0!==s0(e)}function s0(e){if(!e)return;let t=lr(e.metroHost),r=li(e.metroPort),a="http",i=lr(e.bundleUrl);if(i){var n;let e;try{e=new p(i)}catch(e){throw new $("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=lr(e.hostname),r??=li(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function s1(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=s0(a);if(i){if("android"===t.platform)return void await s3(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await s6(t,r,i)}}async function s2(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await s4(t,r);"ios"===t.platform&&"simulator"===t.kind&&await s9(t,r)}}async function s3(e,t,r){var a,i,n,o,s,l;let d,u;la(t);let c=(a=await s8(e,t),i=sz,n=`${r.host}:${r.port}`,d=` <string name="${ln(i)}">${ln(n)}</string>`,le(lt(a,i),d));o=c,s=sJ,l="https"===r.scheme,u=` <boolean name="${ln(s)}" value="${l?"true":"false"}" />`,c=le(lt(o,s),u),await s5(e,t,c)}async function s4(e,t){la(t);let r=await s8(e,t),a=lt(r,sz),i=lt(a,sJ);i!==r&&await s5(e,t,i)}async function s8(e,t){let r=await O("adb",r4(e,["shell","run-as",t,"cat",sW]),{allowFailure:!0});return 0!==r.exitCode?sZ:s7(r.stdout)}async function s5(e,t,r){let a=r4(e,["shell","run-as",t,"id"]),i=await O("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=lo(i.stdout,i.stderr);throw new $("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?sY:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await O("adb",r4(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await O("adb",r4(e,["shell","run-as",t,"tee",sW]),{stdin:r.trimEnd()})}catch(a){let e=P(a);if("TOOL_MISSING"===e.code)throw e;let r=lo("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new $("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?sY:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function s6(e,t,r){await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,sK,"-string",`${r.host}:${r.port}`])),await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,sX,"-string",r.scheme]))}async function s9(e,t){await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,sK]),{allowFailure:!0}),await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,sX]),{allowFailure:!0})}function s7(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
34
- `:sZ}function le(e,t){return s7(e).replace("</map>",`${t}
35
- </map>`)}function lt(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return s7(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function lr(e){let t=e?.trim();return t&&t.length>0?t:void 0}function la(e){if("binary"!==ab(e))return;let t=aS(e);throw new $("INVALID_ARGS",t,{package:e,hint:t})}function li(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function ln(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function lo(e,t){let r=`${e}
36
- ${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let ls=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function ll(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ld(e){let t=e?.trim();return t&&t.length>0?t:void 0}function lu(e,t){if(void 0!==e){if("string"!=typeof e)throw new $("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ld(e)}}function lc(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new $("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function lf(e){if("ios"===e||"android"===e)return e}async function lp(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!sQ(r)||sQ(a)||await s2({device:i.device,appId:i.appBundleId})}async function lm(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===o){sQ(l)&&s?.appBundleId&&await s2({device:s.device,appId:s.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===o)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let d=lf(a.flags?.platform??l?.platform??s?.device.platform);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(s&&s.device.platform!==d)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`}};let u={platform:(t=a.flags,r={platform:d,metroHost:ld(t?.metroHost),metroPort:lc(t?.metroPort),bundleUrl:ld(t?.bundleUrl),launchUrl:ld(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===ll(u)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let lh="open-command-roundtrip",lw="Not implemented for this platform in this release.";async function lg(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await nU();return{appBundleId:t.bundleId,appName:t.appName}}async function lv(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return r9(t)?"macos"===e.platform?void 0:"device"===e.kind?r7(r,t):void 0:await ly(e,t)}async function ly(e,t){try{let{resolveIosApp:r}=await Promise.resolve(eh);return await r(e,t)}catch{return}}async function lI(e,t){if(!("android"!==e.platform||!t||r9(t)))try{let{resolveAndroidApp:r}=await Promise.resolve(ef),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function lA(e,t,r,a){return await lv(e,t,r)??await a(e,t)??("android"===e.platform&&t&&r9(t)?r:void 0)}function lb(e){return{ok:!1,error:{code:"INVALID_ARGS",message:e}}}function lS(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if("macos"===t.platform&&!r)return i??"app";if("macos"!==t.platform){if(r)throw new $("INVALID_ARGS","surface is only supported on macOS");return"app"}let n=r?el(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new $("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return{ok:!1,error:{code:e instanceof $?e.code:"INVALID_ARGS",message:String(e.message)}}}}function l_(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&r9(r)?lb("open --relaunch does not support URL targets."):"app"!==a?lb("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ab(r)?lb(aS(r)):null:null}async function lN(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await sS(i);let{appBundleId:l,appName:d}=await lD({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new $("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!ls.includes(e));if(i)throw new $("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${ls.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new $("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new $("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:lu(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new $("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return lc(e)}}(t.metroPort),bundleUrl:lu(t.bundleUrl,"bundleUrl"),launchUrl:lu(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:lf(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=lf(i);if(a.platform&&r&&!n)throw new $("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new $("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&ll(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=P(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u.response};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await lp({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function lD(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await lg(r);return{appBundleId:n.appBundleId??await lA(t,a,i,lI),appName:n.appName??a}}async function lx(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await tV(t.id),await sp(t,"close",[r],a,i),await sj(t,s$)}async function lM(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let d=s[0]?.trim();!d||r9(d)||await sp(r,"open",[l],a.flags?.out,{...sA(i,a.flags,n,o)})}async function lE(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:f,appBundleId:p,runtime:m,existingSession:h}=e,w=i.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&d){let e=p??d;await lx({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...sA(s,i.flags,p??h?.appBundleId,g)}})}await s1({device:l,appId:p,runtime:m});let v=Date.now();await sp(l,"open",u,i.flags?.out,{...sA(s,i.flags,p)}),await lM({runtime:m,device:l,req:i,logPath:s,appBundleId:p,traceLogPath:g,openPositionals:u});let y=d?{durationMs:Math.max(0,Date.now()-v),measuredAt:new Date().toISOString(),method:lh,appTarget:d,appBundleId:p}:void 0;if(await sj(l,sF),eP(i.meta?.requestId)){let e=eT();return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:f,appBundleId:p,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===ll(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s,runtimeHintCount:l}=e,d={session:t,surface:i};return r&&(d.appName=r),a&&(d.appBundleId=a),n&&(d.startup=n),s&&l(s)>0&&(d.runtime=s),o&&(d.platform=o.platform,d.target=o.target??"mobile",d.device=o.name,d.id=o.id,d.kind=o.kind,"android"===o.platform&&(d.serial=o.id)),o?.platform==="ios"&&(d.device_udid=o.id,d.ios_simulator_device_set=o.simulatorSetPath??null),{...d,...Y(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:p,surface:f,startup:y,device:l,runtime:m,runtimeHintCount:ll});return o.recordAction(I,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,I),{ok:!0,data:A}}async function lk(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${r}" not found.`}};let n=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=lS(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?lb("open --relaunch requires an app name or an active session app."):lb("Session already active. Close it first or pass a new --session name.");let d=l_({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await sq(e.device),c=await lN({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await lE({req:t,sessionName:r,sessionStore:i,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return lb("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&r9(r)?lb("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ab(r)?lb(aS(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await sf(t.flags??{}),d=lS(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=l_({shouldRelaunch:n,openTarget:o,surface:d,device:l});if(u)return u;let c=i.toArray().find(e=>e.device.id===l.id);if(c)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${c.name}".`,details:{session:c.name,deviceId:l.id,deviceName:l.name}}};let f=await lN({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===f.type?f.response:await lE({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:f.details.appBundleId,appName:f.details.appName,runtime:f.details.runtime,surface:d})}async function lO(e){let t=await O("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function lL(e){let{device:t,shutdownRequested:r}=e;if(r&&(sG(t)||"android"===t.platform&&"emulator"===t.kind))try{return sG(t)?await nv(t):await lO(t)}catch(t){let e=q(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function lC(e){if(await tV(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await nj("dismiss",t).catch(t=>{Q({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function lP(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};n.appLog&&await rv(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await lC(n),await sp(n.device,"close",t.positionals,t.flags?.out,{...sA(a,t.flags,n.appBundleId,n.trace?.outPath)}),await sj(n.device,s$)),("ios"===n.device.platform||"macos"===n.device.platform)&&await lC(n),sQ(i.getRuntimeHints(r))&&n.appBundleId&&await s2({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...Y(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await sO(r).catch(()=>{}),i.delete(r);let o=await lL({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:T({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...Y(`Closed: ${r}`)}}}function lR(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}let lT={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve(eh);return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve(ef);return await a(e,t,r)}},l$={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve(eh),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve(ef),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function lF(e){let{req:t,command:r,sessionName:a,sessionStore:i,deployOps:n}=e,o=i.get(a),l=t.flags??{},d=sU(r,o,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return lR("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let f=t.meta?.uploadedArtifactId;try{var p;let e,a=f?r_(f,t.meta?.tenantId):rr.expandHome(c);if(!s.existsSync(a))return lR("INVALID_ARGS",`App binary not found: ${a}`);let d=await sB({session:o,flags:l,ensureReady:!1});if(!sI(r,d))return lR("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await n.ios(d,u,a),r=t.bundleId;e=r?{app:u,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await n.android(d,u,a),r=t.package;e=r?{app:u,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=T(e,(p=e,`Installed: ${p.appName??L(p)}`));return o&&i.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{f&&rN(f)}}let lU=["platform","target","device","udid","serial","verbose","out"];async function lV(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let i=e.flags?.batchMaxSteps??ee;if(!Number.isInteger(i)||i<1||i>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let a=k(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await lG(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function lG(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of lU)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}async function lj(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await lB({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await lq({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lH(t,u),a=!0)}else t=(await lq({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lH(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function lB(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await O("xcrun",eJ(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:na});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||lW(a).includes(lW(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function lq(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await O("xcrun",eJ(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new $("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function lH(e,t){let r=await O("xcrun",eJ(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:na});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function lW(e){return e.toLowerCase().replace(/[._-]/g,"")}async function lz(e){let{req:t,sessionName:r,sessionStore:a}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:a.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("ensure-simulator"===t.command)try{let e=t.flags??{},r=e.device,a=e.runtime,i=eH(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=await lj({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:sS});return{ok:!0,data:{udid:n.udid,device:n.device,runtime:n.runtime,ios_simulator_device_set:i??null,created:n.created,booted:n.booted}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===t.command)try{let e=[],r=ez(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=td({simulatorSetPath:eH(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await Promise.resolve(ec);e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await Promise.resolve(em);e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await Promise.resolve(ec);try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve(em);try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=sU(t.command,e,i);if(n)return n;let o=await sB({session:e,flags:i,ensureReady:!0});if(!sI("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(ts(o.platform)){let{listIosApps:e}=await Promise.resolve(eh);return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve(ef);return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function lJ(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve(ec);return await t(e)}let lK='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',lX='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function lY(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=n.platform;if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`}};let s=sU("appstate",i,n);if(s)return s;let l=(i?.device.platform==="ios"||i?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!sV(e))return!0;let r=e?.platform;return!(r&&!tl(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(n,i);if("ios"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lK}};if("macos"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lX}};if(l&&i){let e=i.appName??i.appBundleId;if(!i.appName&&!i.appBundleId){if("macos"===i.device.platform&&i.surface&&"app"!==i.surface&&"frontmost-app"!==i.surface)return{ok:!0,data:{platform:i.device.platform,appName:i.surface,appBundleId:i.appBundleId,source:"session",surface:i.surface}};let e="macos"===i.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:i.device.platform,appName:e??"unknown",appBundleId:i.appBundleId,source:"session",surface:i.surface??"app",..."ios"===i.device.platform?{device_udid:i.device.id,ios_simulator_device_set:i.device.simulatorSetPath??null}:{}}}}let d=await sB({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lK}};if("macos"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:lX}};let{getAndroidAppState:u}=await Promise.resolve(ef),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function lZ(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=sU(t.command,i,n);if(o)return o;let s="android"===(n.platform??i?.device.platform),l=!0===n.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=sH({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await sB({session:i,flags:n,ensureReady:!1})}catch(r){let t=P(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await lJ({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${n.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let t=sH({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await lJ({avdName:t,serial:n.serial,headless:!0})}await sS(e)}else("android"!==e.platform||!0!==e.booted)&&await sS(e);return sI("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"boot is not supported on this device"}}}return"appstate"===t.command?await lY({req:t,sessionName:r,sessionStore:a}):null}let lQ=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),l0=/https?:\/\/[^\s"'<>\])]+/i,l1=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function l2(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function l3(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return l4(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function l4(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function l8(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function l5(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let l6=["path","start","stop","doctor","mark","clear"],l9=`logs requires ${l6.slice(0,-1).join(", ")}, or ${l6.at(-1)}`,l7=["dump","log"],de=`network requires ${l7.join(" or ")}`,dt=["summary","headers","body","all"],dr=`network include mode must be one of: ${dt.join(", ")}`;function da(e){return e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function di(e){let{req:t,sessionName:r,sessionStore:a}=e;if("perf"===t.command){let e,t,i,n=a.get(r);return n?{ok:!0,data:(i=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===lh&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lh,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:lh,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lh},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:i,fps:{available:!1,reason:lw},memory:{available:!1,reason:lw},cpu:{available:!1,reason:lw}},sampling:{startup:{method:lh,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("logs"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!sI("logs",e.device))return{ok:!1,error:q(new $("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let i=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!l6.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:l9}};if(n&&"clear"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===i){let t=a.resolveAppLogPath(r),i=function(e){if(!s.existsSync(e))return{exists:!1,sizeBytes:0};let t=s.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:da(e),sizeBytes:i.sizeBytes,modifiedAt:i.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===i){let t=a.resolveAppLogPath(r),i=await ry(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}if("mark"===i){let e,i=t.positionals?.slice(1).join(" ")??"",n=a.resolveAppLogPath(r);return rw(n),e=`[agent-device][mark][${new Date().toISOString()}] ${i.trim()||"marker"}
37
- `,s.appendFileSync(n,e,"utf8"),{ok:!0,data:{path:n,marked:!0}}}if("clear"===i){if(e.appLog&&!n)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(n&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r);if(!n)return{ok:!0,data:rI(t)};e.appLog&&await rv(e.appLog);let i=rI(t),o=a.resolveAppLogPidPath(r);try{let n=await rg(e.device,e.appBundleId,t,o);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(t){return a.set(r,{...e,appLog:void 0}),{ok:!1,error:q(t)}}}if("start"===i){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r),i=a.resolveAppLogPidPath(r);try{let n=await rg(e.device,e.appBundleId,t,i);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:q(e)}}}if("stop"===i){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await rv(e.appLog),a.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!sI("network",e.device))return{ok:!1,error:q(new $("UNSUPPORTED_OPERATION","network is not supported on this device"))};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!l7.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:de}};let n=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(n)||n<1||n>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let o=(t.positionals?.[2]??"summary").toLowerCase();if(!dt.includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:dr}};let l=function(e,t){let r=l5(t?.maxEntries,25,1,200),a=t?.include??"summary",i=l5(t?.maxPayloadChars,2048,64,16384),n=l5(t?.maxScanLines,4e3,100,2e4);if(!s.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=s.readFileSync(e,"utf8").split("\n"),l=Math.max(0,o.length-n),d=o.slice(l),u=[];for(let e=d.length-1;e>=0&&u.length<r;e-=1){let t=d[e]?.trim();if(!t)continue;let r=function(e,t,r,a){let i=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(e),n=l2(i,["method","httpMethod"]),o=l2(i,["url","requestUrl"]),s=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(i,["status","statusCode","responseCode"]),l=lQ.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=l0.exec(e),f=o??c?.[0];if(!f)return null;let p={method:u,url:f,status:s??function(e){for(let t of l1){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:l8(e,a),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return l4(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(p.headers=l8(t,a))}if("body"===r||"all"===r){let t=l3(e,i,["requestBody","body","payload","request"]),r=l3(e,i,["responseBody","response"]);t&&(p.requestBody=l8(t,a)),r&&(p.responseBody=l8(r,a))}return p}(t,l+e+1,a,i);r&&u.push(r)}return{path:e,exists:!0,scannedLines:d.length,matchedLines:u.length,entries:u,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}}}(a.resolveAppLogPath(r),{maxEntries:n,include:o,maxPayloadChars:2048,maxScanLines:4e3}),d=[];return e.appLog||d.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&d.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:da(e),notes:d}}}return null}let dn=new Set(["ios","android","macos"]);function ds(e,t,r){let a=e[t];if(void 0!==a)throw new $("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function dl(e){return!!e&&!Number.isNaN(Number(e))}let dd=/[*?[\]{}]/;async function du(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;eO(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=P(e);return{ok:!1,error:{code:t.code,message:t.message}}}).finally(()=>{eC(i)});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,eL(i),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(n,[...d]))},n)})]):await c}finally{t&&clearTimeout(t),u&&(await dc(c)||Q({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await l(a)}catch(e){Q({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:P(e).message}})}}}async function dc(e){return await Promise.race([e.then(()=>!0),A(2e3).then(()=>!1)])}async function df(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:i}=e;if((t.positionals?.length??0)===0)return{ok:!1,error:{code:"INVALID_ARGS",message:"test requires at least one path or glob"}};try{var n,o,l,d,u,f;let e,p,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,i=r??process.cwd(),n=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let i=rr.expandHome(e,t);if(s.existsSync(i)){let t=s.statSync(i);if(t.isDirectory())return s.globSync("**/*.ad",{cwd:i}).map(e=>c.join(i,e));if(t.isFile()){if(".ad"!==c.extname(i))throw new $("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[i]}return[]}if(r=e,!dd.test(r)&&(a=i,!dd.test(a)))throw new $("INVALID_ARGS",`test input not found: ${e}`);let n=c.isAbsolute(i)?i:e;return s.globSync(n,{cwd:c.isAbsolute(i)?void 0:t}).map(e=>c.isAbsolute(e)?e:c.resolve(t,e)).filter(e=>".ad"===c.extname(e)&&function(e){try{return s.statSync(e).isFile()}catch{return!1}}(e))})(e,i)))].map(e=>c.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of n){var l,d;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&dn.has(e)&&ds(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&ds(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&ds(r,"retries",Math.floor(e))}}return r}(s.readFileSync(e,"utf8"));if(!a){o.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){o.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}l=a,d=t.platform,("apple"===l?"apple"===d||"ios"===d||"macos"===d:d===l)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new $("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),v=(n=t.meta?.requestId,(n?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),y=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,i=rr.expandHome(t??".agent-device/test-artifacts",r);return c.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:v}),I=[],A=Date.now(),b=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}b+=1;let n=await dp({entry:e,sessionName:r,suiteInvocationId:v,caseIndex:b-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,l=e.metadata.timeoutMs,"number"==typeof o?o:l),suiteArtifactsDir:y,runReplay:a,cleanupSession:i});if(I.push(n),t.flags?.failFast===!0)break}let S=(d=g.length,u=I,f=Date.now()-A,e=u.filter(e=>"passed"===e.status).length,m=(p=u.filter(e=>"failed"===e.status)).length,h=u.filter(e=>"skipped"===e.status).length,w=e+m,{total:d,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-w-h),durationMs:f,failures:p,tests:u});return{ok:!0,data:S}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message}}}}async function dp(e){var t,r;let a,i,{entry:n,sessionName:o,suiteInvocationId:l,caseIndex:d,cwd:u,requestId:f,retries:p,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,v=Date.now(),y=c.join(h,(t=n.path,(0===(i=u?c.relative(u,t):c.basename(t)).length||i.startsWith("..")?c.basename(t):i).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",A=0;for(let e=0;e<=p;e+=1){A=e+1;let t=function(e,t,r,a,i=0){let n=c.basename(r,c.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(o,l,n.path,d,e),i=c.join(y,`attempt-${A}`);r=n.path,s.mkdirSync(i,{recursive:!0}),s.copyFileSync(r,c.join(i,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return ek(`${t??r}:test:${i+1}:${c.basename(a)}:attempt:${n+1}`,r)}({requestId:f,suiteInvocationId:l,filePath:n.path,caseIndex:d,attemptIndex:e}),h=await du({filePath:n.path,sessionName:t,requestId:u,timeoutMs:m,platform:n.metadata.platform,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:i,maxAttempts:n,attemptArtifactsDir:o}=e,l=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||l.push(t.error.logPath);let d=function(e,t){let r=[],a=new Map;for(let i of e){if(!function(e){try{return s.statSync(e).isFile()}catch{return!1}}(i))continue;let e=function(e,t){let r=c.extname(e),a=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${a}-${i+1}${r}`}(c.basename(i),a),n=c.join(t,e);c.resolve(i)!==c.resolve(n)&&s.copyFileSync(i,n),r.push(n)}return r}(l,o),u=[`file: ${r}`,`session: ${a}`,`attempt: ${i}/${n}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;u.push(`replayed: ${e}`,`healed: ${r}`)}else u.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&u.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&u.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&u.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&u.push("timeoutMode: cooperative");d.length>0&&u.push(`copiedArtifacts: ${d.map(e=>c.basename(e)).join(", ")}`);let f=c.join(o,"result.txt"),p=`${u.join("\n")}
38
- `;s.writeFileSync(f,p),t.ok||s.writeFileSync(c.join(o,"failure.txt"),p)}({response:h,filePath:n.path,sessionName:t,attempts:A,maxAttempts:p+1,attemptArtifactsDir:i}),a=h,I=t,h.ok)break}let b=Date.now()-v;if(a?.ok)return{file:n.path,session:I,status:"passed",durationMs:b,attempts:A,artifactsDir:y,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let S=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:n.path,session:I,status:"failed",durationMs:b,attempts:A,artifactsDir:y,error:S}}function dm(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function dh(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function dw(e,t){return e.find(e=>e.ref===t)??null}function dg(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function dv(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),i=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||i.includes(r)})??null}function dy(e,t){let r=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);return r&&dI(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,a=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!dI(t))continue;let i=Math.abs(e.rect.y+e.rect.height/2-r);(!a||i<a.distance)&&(a={label:t,distance:i})}return a?.label}(e,t)??(r&&dI(r)?r:void 0)}function dI(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function dA(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let i=db(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&dI(n);if(("group"===i||"ioscontentgroup"===i)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function db(e){let t=e.trim().replace(/XCUIElementType/gi,"");t.startsWith("AX")&&(t=t.slice(2));let r=Math.max((t=t.toLowerCase()).lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function dS(e,t){let r=db(e);return!r||("android"===t?r.includes("edittext")||r.includes("autocompletetextview"):r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("textview")||r.includes("textarea")||"search"===r)}function d_(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}function dN(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let dD=new Set(["id","role","text","label","value"]),dx=new Set(["visible","hidden","editable","selected","enabled","hittable"]),dM=new Set([...dD,...dx]);function dE(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dT(e,i)){a=dP(a,n),r+=n;continue}if(!a&&"|"===n&&"|"===e[i+1]){let a=r.trim();if(!a)throw new $("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new $("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new $("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dT(e,i)){a=dP(a,n),r+=n;continue}if(!a&&/\s/.test(n)){r.trim()&&t.push(r.trim()),r="";continue}r+=n}if(a)throw new $("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new $("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(dC)}})(e))}}function dk(e){try{return dE(e)}catch{return null}}function dO(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,i=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return dM.has(e)}return dM.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&dk(t)&&i.push(a)}if(0===i.length)return null;let n=i[i.length-1];if(r){for(let t=i.length-1;t>=0;t-=1)if(i[t]<e.length){n=i[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function dL(e){let t=e[0]??"",r=dO(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function dC(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!dx.has(r))throw new $("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),i=t.slice(r+1).trim();if(!dM.has(a))throw new $("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new $("INVALID_ARGS",`Missing selector value for key: ${a}`);if(dx.has(a)){let e,t="true"===(e=dR(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new $("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:dR(i)}}function dP(e,t){return e?e===t?null:e:t}function dR(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function dT(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function d$(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return dV(e.identifier,String(t.value));case"role":return dV(db(e.type??""),String(t.value));case"label":return dV(e.label,String(t.value));case"value":return dV(e.value,String(t.value));case"text":return dV(dN(e),String(t.value));case"visible":return dF(e)===!!t.value;case"hidden":return!dF(e)==!!t.value;case"editable":return dU(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function dF(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function dU(e,t){return dS(e.type??"",t)&&!1!==e.enabled}function dV(e,t){return dG(e??"")===dG(t)}function dG(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function dj(e,t,r){let a=r.requireRect??!1,i=r.requireUnique??!0,n=[];for(let o=0;o<t.selectors.length;o+=1){let s=t.selectors[o],l=function(e,t,r,a){let i=0,n=null,o=null,s=!1;for(let l of e){if(a&&!l.rect||!d$(l,t,r))continue;if(i+=1,n??=l,!o){o=l;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let i=dH(e),n=dH(t);return i!==n?i<n?1:-1:0}(l,o);e>0?(o=l,s=!1):0===e&&(s=!0)}return{count:i,firstNode:n,disambiguated:s?null:o}}(e,s,r.platform,a);if(n.push({selector:s.raw,matches:l.count}),0!==l.count&&l.firstNode){if(i&&1!==l.count){if(!r.disambiguateAmbiguous||!l.disambiguated)continue;return{node:l.disambiguated,selector:s,selectorIndex:o,matches:l.count,diagnostics:n}}return{node:l.firstNode,selector:s,selectorIndex:o,matches:l.count,diagnostics:n}}}return null}function dB(e,t,r){let a=r.requireRect??!1,i=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r,a){let i=0;for(let n of e)(!a||n.rect)&&d$(n,t,r)&&(i+=1);return i}(e,o,r.platform,a);if(i.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:i}}return null}function dq(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let a=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${a})`:`Selector did not match (${a})`}function dH(e){return e.rect?e.rect.width*e.rect.height:1/0}function dW(e,t,r={}){let a=[],i=db(e.type??""),n=dJ(e.identifier),o=dJ(e.label),s=dJ(e.value),l=dJ(dN(e)),d="fill"===r.action;n&&a.push(`id=${dz(n)}`),i&&o&&a.push(d?`role=${dz(i)} label=${dz(o)} editable=true`:`role=${dz(i)} label=${dz(o)}`),o&&a.push(d?`label=${dz(o)} editable=true`:`label=${dz(o)}`),s&&a.push(d?`value=${dz(s)} editable=true`:`value=${dz(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${dz(l)} editable=true`:`text=${dz(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${dz(i)} editable=true`);let u=tX(a);return 0===u.length&&i&&u.push(d?`role=${dz(i)} editable=true`:`role=${dz(i)}`),0===u.length&&dF(e)&&u.push("visible=true"),u}function dz(e){return JSON.stringify(e)}function dJ(e){if(!e)return null;let t=e.trim();return t||null}function dK(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=dO(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}async function dX(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(t1(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),t1(e.command)){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&t.push(e.positionals.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=dL(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=dK(e.positionals??[]);r&&t.push(r)}return tX(t).filter(e=>e.trim().length>0)})(t).map(e=>dk(e)).filter(e=>null!==e);if(0===o.length)return null;let s=t1(t.command)||"fill"===t.command,l=t1(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await dY(n,t,a,s,i);for(let e of o){let r=dj(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=dW(r.node,n.device.platform,{action:t1(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(t1(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tK(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=dL(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",n=[e,a];return"text"===e&&i.length>0&&n.push(i),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=dK(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function dY(e,t,r,a,i){let n=await sp(e.device,"snapshot",[],t.flags?.out,{...sA(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:dm(t.flags?.snapshotRaw?o:dA(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}let dZ=["platform","target","device","udid","serial","verbose","out"];async function dQ(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.positionals?.[0];if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};let l="",d=new Set;try{l=rr.expandHome(o,t.meta?.cwd);let e=s.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new $("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=t7(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=t7(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(t1(a)){let e=t9(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return dl(r)&&dl(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=t9(a,i);if(Object.assign(n.flags,e.flags),e.positionals.length<2)return n.positionals=e.positionals,n;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(n.positionals=[t,e.positionals.slice(2).join(" ")],n.result={refLabel:e.positionals[1]}):n.positionals=[t,e.positionals[1]],n):(n.positionals=[t,e.positionals.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a||"type"===a){let e=t9(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}if("screenshot"===a){let e=[];for(let t of i){if("--fullscreen"===t){n.flags.screenshotFullscreen=!0;continue}e.push(t)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(e),f=t.flags?.replayUpdate===!0,p=0;for(let e=0;e<c.length;e+=1){let o=c[e];if(!o||"replay"===o.command)continue;let s=await d0({req:t,sessionName:r,action:o,invoke:n});if(s.ok){d2(s).forEach(e=>d.add(e));continue}if(!f)return d1(s,o,e,l,[...d]);let u=await dX({action:o,sessionName:r,logPath:a,sessionStore:i});if(!u)return d1(s,o,e,l,[...d]);if(c[e]=u,!(s=await d0({req:t,sessionName:r,action:u,invoke:n})).ok)return d1(s,u,e,l,[...d]);d2(s).forEach(e=>d.add(e)),p+=1}return f&&p>0&&function(e,t,r){let a=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",i=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${i} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",t3(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return rt(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(t4(r));return t5(t,e.flags),t.join(" ")}if("record"===e.command)return t6(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t3(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(t3(r));return t8(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
39
- `,n=`${e}.tmp-${process.pid}-${Date.now()}`;s.writeFileSync(n,i),s.renameSync(n,e)}(l,c,i.get(r)),{ok:!0,data:{replayed:c.length,healed:p,session:r,artifactPaths:[...d]}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:d.size>0?{artifactPaths:[...d]}:void 0}}}}async function d0(e){let{req:t,sessionName:r,action:a,invoke:i}=e;return await i({token:t.token,session:r,command:a.command,positionals:a.positionals??[],flags:function(e,t){let r={...t??{}},a=e??{};for(let e of dZ)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}(t.flags,a.flags),runtime:a.runtime,meta:t.meta})}function d1(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>t3(e)),[t.command,...n].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function d2(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,a="string"==typeof r.path?r.path:void 0;e?t.push(e):a&&t.push(a)}return[...new Set(t.filter(e=>(function(e){try{return s.statSync(e).isFile()}catch{return!1}})(e)))]}async function d3(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await dQ({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await df({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await dQ({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),l&&d2(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await lP({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let d4=new Set(["session_list","ensure-simulator","devices","apps"]),d8=new Set(["boot","appstate"]),d5=new Set(["perf","logs","network"]),d6=new Set(["replay","test"]);async function d9(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=sU(n,d,u);if(c)return c;let f=await sB({session:d,flags:u,ensureReady:!0});if(!sI(n,f))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${n} is not supported on this device`}};let p=await sp(f,n,o,t.flags?.out,{...sA(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,p,f):d;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:p??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:p??{}}}async function d7(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=sU("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let d=await sB({session:n,flags:o,ensureReady:!0});if(!sI("clipboard",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let u=await sp(d,"clipboard",t.positionals??[],t.flags?.out,{...sA(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function ue(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(d4.has(t.command))return await lz({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await lm({req:t,sessionName:r,sessionStore:i});if(d8.has(t.command))return await lZ({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await d7({req:t,sessionName:r,logPath:a,sessionStore:i});if("keyboard"===t.command){let e=i.get(r),n=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==n||"ios"!==(t.flags??{}).platform?await d9({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first."}}}if(d5.has(t.command))return await di({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await lF({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?l$:lT});if("install_source"===t.command)return await sP({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await sT({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await d9({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=o4(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>rr.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}}}return"trigger-app-event"===t.command?await d9({req:t,sessionName:r,logPath:a,sessionStore:i,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await lA(e.device,r,e.appBundleId,lI)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await lk({req:t,sessionName:r,logPath:a,sessionStore:i}):d6.has(t.command)?await d3({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await lV(t,r,n):"close"===t.command?await lP({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function ut(e,t){let r=B(e.type??"Element"),a=C(e,r),i=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,i,n,o].join("|")}function ur(e,t){return t.flatten?e.map(e=>({text:eu(e,0,!1),comparable:ut(e,0)})):G(e).map(e=>({text:e.text,comparable:ut(e.node,e.depth)}))}function ua(e,t){return e.get(t)??0}async function ui(e){return{snapshot:uo(await un(e),e.flags?.snapshotRaw)}}async function un(e){var t,r,a,i;let n,{device:o,session:s,flags:l,outPath:d,logPath:u,snapshotScope:c}=e;return"macos"===o.platform&&s?.surface&&"app"!==s.surface?(t=await nB(s.surface,{bundleId:"menubar"===s.surface?s.appBundleId:void 0}),r={snapshotDepth:l?.snapshotDepth,snapshotInteractiveOnly:l?.snapshotInteractiveOnly,snapshotScope:c},n=t.nodes??[],r.snapshotScope&&(n=function(e,t){let r=dv(dm(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let i=e[a]?.depth??0,n=[];for(let t=a;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>a&&o<=i)break;n.push(r)}return us(n,i)}(n,r.snapshotScope)),r.snapshotInteractiveOnly&&(n=function(e){if(0===e.length)return e;let t=new Map;for(let r of e)t.set(r.index,r);let r=new Set;for(let a of e){if(!function(e){if(e.hittable||e.rect)return!0;let t=`${e.type??""} ${e.role??""} ${e.subrole??""}`.toLowerCase();return t.includes("button")||t.includes("menu")||t.includes("textfield")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")}(a))continue;let e=a;for(;e&&!r.has(e.index);)r.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===r.size?e:us(e.filter(e=>r.has(e.index)))}(n)),"number"==typeof r.snapshotDepth&&(a=n,i=r.snapshotDepth,n=us(a.filter(e=>(e.depth??0)<=i))),{...t,nodes:n}):await sp(o,"snapshot",[],d,{...sA(u,{...l,snapshotScope:c},s?.appBundleId,s?.trace?.outPath)})}function uo(e,t){let r=e?.nodes??[];return{nodes:dm(t?r:dA(r)),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend}}function us(e,t=0){let r=new Map;for(let[t,a]of e.entries())r.set(a.index,t);return e.map((e,a)=>({...e,index:a,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function ul(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref scope requires an existing snapshot in session."}}};let r=dh(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=dw(t.snapshot.nodes,r),i=a?dy(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function ud(e,t,r){let a=e.get(t),i=a?.device??await sf(r??{});return a||await sS(i),{session:a,device:i}}async function uu(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tV(t.id)}}function uc(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function uf(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function up(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function um(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),uc(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!sI("wait",s))return lR("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===t.kind)return await uh({device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});let l=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=dh(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=dw(t.snapshot.nodes,r),i=a?dy(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return l.ok?await uw({device:s,logPath:i,req:r,session:o,sessionStore:n,text:l.text,timeoutMs:l.timeoutMs}):l.response}async function uh(e){let{device:t,logPath:r,parsed:a,req:i,session:n,sessionName:o,sessionStore:s}=e,l=a.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let e=dB((await ug({device:t,logPath:r,req:i,session:n,sessionName:o,sessionStore:s})).nodes,a.selector,{platform:t.platform});if(e)return uv(s,n,i,{selector:e.selector.raw,waitedMs:Date.now()-d});await new Promise(e=>setTimeout(e,300))}return lR("COMMAND_FAILED",`wait timed out for selector: ${a.selectorExpression}`)}async function uw(e){let{device:t,logPath:r,req:a,session:i,sessionStore:n,text:o,timeoutMs:s}=e,l=s??1e4,d=Date.now();for(;Date.now()-d<l;){if("macos"===t.platform&&i?.surface&&"app"!==i.surface){if(dv((await ug({device:t,logPath:r,req:a,session:i,sessionName:i?.name??a.session??"default",sessionStore:n})).nodes,o))return uv(n,i,a,{text:o,waitedMs:Date.now()-d})}else if(ts(t.platform)){let e=await tz(t,{command:"findText",text:o,appBundleId:i?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return uc(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}}}else if("android"===t.platform&&dv(dm((await iI(t,{scope:o})).nodes??[]),o))return uc(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return lR("COMMAND_FAILED",`wait timed out for text: ${o}`)}async function ug(e){let{device:t,logPath:r,req:a,session:i,sessionName:n,sessionStore:o}=e,{snapshot:s}=await ui({device:t,session:i,flags:{...a.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:a.flags?.out,logPath:r});return i&&(i.snapshot=s,o.set(n,i)),s}function uv(e,t,r,a){return uc(e,t,r,a),{ok:!0,data:a}}async function uy(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!sI("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===n.platform){let e=async()=>await nj("wait"===o?"get":o,s);if("wait"===o){let r=up(t.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<r;){try{let r=await e();return uc(a,i,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===o||"dismiss"===o?o:"get";if("accept"===r||"dismiss"===r){let e,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await nj(r,s);return uc(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let n=await nj("get",s);return uc(a,i,t,n),{ok:!0,data:n}}if("wait"===o){let e=up(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await tz(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return uc(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await tz(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return uc(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let u=await tz(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return uc(a,i,t,u),{ok:!0,data:u}}async function uI(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!sI("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};if("macos"===n.platform&&!_(s))return{ok:!1,error:{code:"INVALID_ARGS",message:U(s)}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],f=await sp(n,"settings",c,t.flags?.out,{...sA(r,t.flags,u,i?.trace?.outPath)});return uc(a,i,t,f??{setting:s,state:l}),{ok:!0,data:f??{setting:s,state:l}}}let uA=new Set(["snapshot","diff","wait","alert","settings"]);async function ub(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=t.command;if(!uA.has(n))return null;if("snapshot"===n){let{session:e,device:n}=await ud(i,r,t.flags);if(!sI("snapshot",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let o=ul(t.flags?.snapshotScope,e);return o.ok?await uu(e,n,async()=>{let s=await ui({device:n,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope}),l=uf({session:e,sessionName:r,device:n,snapshot:s.snapshot,appBundleId:e?.appBundleId});return uc(i,l,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,l),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,appName:l.appBundleId?l.appName??l.appBundleId:void 0,appBundleId:l.appBundleId}}}):o.response}if("diff"===n){if(t.positionals?.[0]!=="snapshot")return{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}};let{session:e,device:n}=await ud(i,r,t.flags);if(!sI("diff",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let o=ul(t.flags?.snapshotScope,e);if(!o.ok)return o.response;let s=t.flags?.snapshotInteractiveOnly===!0;return await uu(e,n,async()=>{let l=(await ui({device:n,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return ur(e,t).length}(l.nodes,{flatten:s}),o=uf({session:e,sessionName:r,device:n,snapshot:l,appBundleId:e?.appBundleId});return uc(i,o,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a}}),i.set(r,o),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a},lines:[]}}}let d=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,i=r+a,n=new Map,o=[];n.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(n));for(let i=-s;i<=s;i+=2){let l=i===-s||i!==s&&ua(n,i-1)<ua(n,i+1)?ua(n,i+1):ua(n,i-1)+1,d=l-i;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(i,l),l>=r&&d>=a)return function(e,t,r,a,i){let n=[],o=a,s=i;for(let a=e.length-1;a>=0;a-=1){let i=e[a],l=o-s,d=l===-a||l!==a&&ua(i,l-1)<ua(i,l+1)?l+1:l-1,u=ua(i,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,a)}}return[]}(ur(e,r),ur(t,r)),i={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(i.additions+=1),"removed"===e.kind&&(i.removals+=1),"unchanged"===e.kind&&(i.unchanged+=1);return{summary:i,lines:a}}(e.snapshot.nodes,l.nodes,{flatten:s}),u={...e,snapshot:l};return uc(i,u,t,{mode:"snapshot",baselineInitialized:!1,summary:d.summary}),i.set(r,u),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:d.summary,lines:d.lines}}})}if("wait"===n){let{session:e,device:n}=await ud(i,r,t.flags),o=function(e){if(0===e.length)return null;let t=up(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=up(e[e.length-1]);return{kind:"text",text:(null!==t?e.slice(1,-1).join(" "):e.slice(1).join(" ")).trim(),timeoutMs:t}}if(e[0].startsWith("@")){let t=up(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=up(e[e.length-1]),a=dO(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=dk(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let s=()=>um({parsed:o,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:n});return"sleep"===o.kind?await s():await uu(e,n,s)}if("alert"===n){let{session:e,device:n}=await ud(i,r,t.flags);return await uu(e,n,async()=>await uy({req:t,logPath:a,sessionStore:i,session:e,device:n}))}if("settings"===n){let e,n,o,s=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:E}}});if(!s.ok)return s.response;let{session:l,device:d}=await ud(i,r,t.flags);return await uu(l,d,async()=>await uI({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}function uS(e,t,r,a={}){let i=uN(r);if(!i)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return u_(e.label,r);case"value":return u_(e.value,r);case"id":return u_(e.identifier,r);default:return Math.max(u_(e.label,r),u_(e.value,r),u_(e.identifier,r))}}(r,t,i);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function u_(e,t){let r=uN(e??"");return r?r===t?2:+!!r.includes(t):0}function uN(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function uD(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=dh(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=dw(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=dv(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function ux(e){let t=uM(e);if(!t)return null;let r=dg(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function uM(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}async function uE(e){let{session:t,refInput:r,fallbackLabel:a,promoteToHittableAncestor:i,invalidRefMessage:n,missingBoundsMessage:o,invalidBoundsMessage:s,reqFlags:l,sessionStore:d,contextFromFlags:u,captureSnapshotForSession:c,resolveRefTarget:f}=e,p=f({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:n,notFoundMessage:o});if(!p.ok)return{ok:!1,response:p.response};let{ref:m}=p.target,h=i?uk(p.target.snapshotNodes,p.target.node):p.target.node,w=p.target.snapshotNodes,g=ux(h.rect);if(!g){let e=await c(t,l,d,u,{interactiveOnly:!0}),r=dw(e.nodes,m),n=a.length>0?dv(e.nodes,a):null,o=r&&i?uk(e.nodes,r):r,s=n&&i?uk(e.nodes,n):n,f=ux(s?.rect),p=ux(o?.rect)?o:f?s:o??s,v=ux(p?.rect);p&&v&&(h=p,w=e.nodes,g=v)}return g?{ok:!0,target:{ref:m,node:h,snapshotNodes:w,point:g}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:s}}}}function uk(e,t){let r=function(e,t){let r=uM(t.rect);if(!r)return null;let a=t,i=new Set;for(;!i.has(a.ref);){i.add(a.ref);let t=e.filter(e=>{var t,i;if(e.parentIndex!==a.index||!e.hittable)return!1;let n=uM(e.rect);return!!n&&(t=n,i=r,.5>=Math.abs(t.x-i.x)&&.5>=Math.abs(t.y-i.y)&&.5>=Math.abs(t.width-i.width)&&.5>=Math.abs(t.height-i.height))});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&ux(r.rect))return r;let a=d_(e,t);return a?.rect&&ux(a.rect)?a:t}async function uO(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=F(r),d=ux(r.rect);if(!d)return l;try{let e=await sp(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,n),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return Q({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return Q({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function uL(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return lR("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:f}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let a=e[r]??"",i=e.slice(r+1);if(0===i.length)return{locator:t,query:a,action:"click"};let n=i[0].toLowerCase();if("get"===n){let e=i[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new $("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:up(i[1])??void 0};if("exists"===n)return{locator:t,query:a,action:"exists"};if("click"===n)return{locator:t,query:a,action:"click"};if("focus"===n)return{locator:t,query:a,action:"focus"};if("fill"===n)return{locator:t,query:a,action:"fill",value:i.slice(1).join(" ")};if("type"===n)return{locator:t,query:a,action:"type",value:i.slice(1).join(" ")};throw new $("INVALID_ARGS",`Unsupported find action: ${i[0]}`)}(s);if(!d)return lR("INVALID_ARGS","find requires a value");let p=i.get(r);if(!p&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return lR("SESSION_NOT_FOUND","No active session. Run open first.");let m=p?.device??await sf(t.flags??{});p||await sS(m);let h="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,g=0,v=null,y=async()=>{let e=Date.now();if(v&&e-g<750)return{nodes:v};let{snapshot:n}=await ui({device:m,session:p,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return g=e,v=o,p&&(p.snapshot=n,i.set(r,p)),{nodes:o,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:p,device:m,command:o,locator:l,query:d};if("wait"===u)return uC(I,y,l,d,f);let{nodes:A}=await y(),b=uS(A,l,d,{requireRect:w});if(w&&b.matches.length>1){var S,_,N;let e;return S=b.matches,_=l,N=d,e=S.slice(0,8).map(e=>{let t=dN(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.length} elements for ${_} "${N}". Use a more specific locator or selector.`,details:{locator:_,query:N,matches:S.length,candidates:e}}}}let D=b.matches[0]??null;if(!D)return lR("COMMAND_FAILED","find did not match any element");let x="click"===u||"focus"===u||"fill"===u||"type"===u?d_(A,D)??D:D,M=`@${x.ref}`,E={node:D,resolvedNode:x,ref:M,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},k={exists:()=>uP(I),get_text:()=>uR(I,E),get_attrs:()=>uT(I,E),click:()=>u$(I,E),fill:()=>uF(I,E,c),focus:()=>uU(I,E),type:()=>uV(I,E,c)}[u];return k?k():null}async function uC(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(uS(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}async function uP(e){let{req:t,sessionStore:r,session:a,command:i}=e;return a&&r.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function uR(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await uO({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>sA(s,e,t,r)});return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function uT(e,t){let{req:r,sessionStore:a,session:i,command:n}=e;return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function u$(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?dg(t.resolvedNode.rect):null,f={ref:t.ref,locator:l,query:d};return c&&(f.x=c.x,f.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:f}}async function uF(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let d=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function uU(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?dg(t.node.rect):null;if(!l)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let d=await sp(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...sA(s,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function uV(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let d=t.node.rect?dg(t.node.rect):null;if(!d)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await sp(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...sA(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await sp(o,"type",[r],a.flags?.out,{...sA(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let uG=`
28
+ ${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let oN={settings:"com.apple.Preferences"},oD=null;function ox(e,t,r){return O("xcrun",eK(e,t),r)}function ok(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function oM(e,t){if("macos"===e.platform)return await n4(t);let r=t.trim();if(r.includes("."))return r;let a=oN[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await oj(e):await ng(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new $("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new $("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function oE(e,t,r){if("macos"===e.platform)return void await n8(e,t,r);let a=r?.url?.trim();if(a){if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await n_(e),await ox(e,["openurl",e.id,a]);return}let i=r7(r?.appBundleId??await oM(e,t),a);if(!i)throw new $("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oY(e,i,{payloadUrl:a});return}let i=t.trim();if(r9(i)){if("simulator"===e.kind){await n_(e),await ox(e,["openurl",e.id,i]);return}let t=r7(r?.appBundleId,i);if(!t)throw new $("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oY(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await oM(e,t);"simulator"===e.kind?await oX(e,n):await oY(e,n)}async function oO(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await nD(e)&&await n_(e)}async function oL(e,t){if("macos"===e.platform)return void await n5(e,t);let r=await oM(e,t);if("simulator"===e.kind){await n_(e);let t=eK(e,["terminate",e.id,r]),a=await O("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new $("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await nw(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function oC(e,t){let r=await oM(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await O("xcrun",t,{allowFailure:!0,timeoutMs:np});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!ok(`${i}
29
+ ${n}`.toLowerCase()))throw new $("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:e.id,hint:nv(i,n)??ny})}return{bundleId:r}}await n_(e);let a=await ox(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!ok(`${a.stdout}
30
+ ${a.stderr}`.toLowerCase()))throw new $("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function oP(e,t,r){let a=await nk({kind:"path",path:t},r);try{return await oT(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function oR(e,t,r){let{bundleId:a}=await oC(e,t);return await oP(e,r,{appIdentifierHint:t}),{bundleId:a}}async function oT(e,t){"simulator"!==e.kind?await nw(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await n_(e),await ox(e,["install",e.id,t]))}async function o$(e){if("macos"===e.platform)return await n6();nb(e,"clipboard"),await n_(e);let t=await ox(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new $("COMMAND_FAILED","Failed to read iOS simulator clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return t.stdout.replace(/\r\n/g,"\n").replace(/\n$/,"")}async function oF(e,t){if("macos"===e.platform)return void await n9(t);nb(e,"clipboard"),await n_(e);let r=await ox(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new $("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function oU(e,t,r){nb(e,"push"),await n_(e);let a=await d.mkdtemp(c.join(u.tmpdir(),"agent-device-ios-push-")),i=c.join(a,"payload.apns");try{await d.writeFile(i,`${JSON.stringify(r)}
31
+ `,"utf8"),await ox(e,["push",e.id,t,i])}finally{await d.rm(a,{recursive:!0,force:!0})}}async function oV(e,t,r,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await oe(r);if("permission"===e){let e=i3(r);if("deny"===e)throw new $("INVALID_ARGS",U("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new $("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nJ(e,t)}throw new $("INVALID_ARGS",U(t))}nb(e,"settings"),await n_(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=oB(r);await ox(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(oB(r)?await ox(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await ox(e,["status_bar",e.id,"clear"]));case"location":{let t=oB(r);if(!a)throw new $("INVALID_ARGS","location setting requires an active app in session");await ox(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=oH[n],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new $("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await oK(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await oq(e,r);await ox(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new $("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=i3(r))?"revoke":o,n=function(e,t){let r=i4(e);if("photos"!==r&&t?.trim())throw new $("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return"camera";if("microphone"===r)return"microphone";if("contacts"===r)return"contacts";if("contacts-limited"===r)return"contacts-limited";if("notifications"===r)return"notifications";if("calendar"===r)return"calendar";if("location"===r)return"location";if("location-always"===r)return"location-always";if("media-library"===r)return"media-library";if("motion"===r)return"motion";if("reminders"===r)return"reminders";if("siri"===r)return"siri";if("photos"===r){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new $("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new $("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(i?.permissionTarget,i?.permissionMode);await oW(e,t,n,a);return}default:throw new $("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function oG(e,t="all"){return"macos"===e.platform?await ot(t):"simulator"===e.kind?nC(await oj(e),t):await ng(e,t)}async function oj(e){let t=(await ox(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await O("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function oB(e){let t=e.toLowerCase();if("on"===t||"true"===t||"1"===t)return!0;if("off"===t||"false"===t||"0"===t)return!1;throw new $("INVALID_ARGS",`Invalid setting state: ${e}`)}async function oq(e,t){let r=i8(t);if("toggle"!==r)return r;let a=await ox(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new $("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
32
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new $("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let oH={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function oW(e,t,r,a){let i=await oJ(e);if(!i.has(r))throw new $("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let n=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await ox(e,n);return}catch(t){if(!(o&&oz(t)))throw t;throw new $("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:a,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await ox(e,n);return}catch(e){if(!oz(e))throw e}try{await ox(e,["privacy",e.id,"reset","all",a])}catch(t){throw new $("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:a,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function oz(e){if(!(e instanceof $)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return(t.includes("failed to grant access")||t.includes("failed to revoke access")||t.includes("failed to reset access"))&&t.includes("operation not permitted")}async function oJ(e){let r=eH(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(oD&&t===a)return oD;let i=await ox(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
33
+ ${i.stderr}`);if(0===n.size)throw new $("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return oD=n,t=a,n}async function oK(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),i=[];for(let t of a){let r=eK(e,t),a=await O("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
34
+ ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new $("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new $("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function oX(e,t){await n_(e);let r=0,a=eb.fromTimeoutMs(nc);try{await eS(async({deadline:r})=>{var a;if(r?.isExpired())throw new $("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:nc});let i=(a=["launch",e.id,t],eK(e,a)),n=await O("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!nI(e)&&(r+=1)<3},{deadline:a})}catch(r){if(nI(r)){var i;let a=(i=await nA(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function oY(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await nw(a,{action:"launch iOS app",deviceId:e.id})}async function oZ(e,t,r,a){let i=a?.maxScrolls??48,n=await e({command:"findText",text:r});if(n?.found)return{attempts:0};let o=oQ(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));for(let a=1;a<=i;a+=1){t(),await e({command:"swipe",direction:"up"}),await new Promise(e=>setTimeout(e,80));let i=await e({command:"findText",text:r});if(i?.found)return{attempts:a};let n=oQ(await e({command:"snapshot",interactiveOnly:!0,compact:!0}));if(n===o)throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:a,stalled:!0});o=n}throw new $("COMMAND_FAILED",`scrollintoview could not find text: ${r}`,{reason:"not_found",attempts:i})}function oQ(e){let t=e.nodes;return JSON.stringify(Array.isArray(t)?t:e)}async function o0(e,t,r,a,i,n,o){if("tv"===t.target)return o3(await e(t,{command:"swipe",direction:function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left";default:return e}}(i),appBundleId:r.appBundleId},a),n);let s=o??await o1(e,t,r,a),l=ig({direction:i,amount:n?.amount,pixels:n?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return o3(await e(t,{command:"drag",x:s.originX+l.x1,y:s.originY+l.y1,x2:s.originX+l.x2,y2:s.originY+l.y2,appBundleId:r.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function o1(e,t,r,a){let i=await e(t,{command:"interactionFrame",appBundleId:r.appBundleId},a),n=o2(i.x),o=o2(i.y),s=o2(i.referenceWidth),l=o2(i.referenceHeight);if(void 0===n||void 0===o||void 0===s||void 0===l)throw new $("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:n,originY:o,referenceWidth:s,referenceHeight:l}}function o2(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function o3(e,t){var r;let{x1:a,y1:i,x2:n,y2:o}={x1:o2((r=e).x),y1:o2(r.y),x2:o2(r.x2),y2:o2(r.y2)},s=o2(e.referenceWidth),l=o2(e.referenceHeight),d=void 0!==a&&void 0!==n?Math.round(Math.abs(n-a)):void 0,u=void 0!==i&&void 0!==o?Math.round(Math.abs(o-i)):void 0,c=t?.preferProvidedPixels&&void 0!==t.pixels?t.pixels:d&&d>0?d:u&&u>0?u:void 0;return{...void 0!==a?{x1:a}:{},...void 0!==i?{y1:i}:{},...void 0!==n?{x2:n}:{},...void 0!==o?{y2:o}:{},...void 0!==s?{referenceWidth:s}:{},...void 0!==l?{referenceHeight:l}:{},...t?.amount!==void 0?{amount:t.amount}:{},...void 0!==c?{pixels:c}:{}}}function o4(e){return e?.clickButton??"primary"}function o8(e){return"primary"===e.button?null:"click"!==e.commandLabel?new $("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform?new $("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS`):"middle"===e.button?new $("UNSUPPORTED_OPERATION","click --button middle is not supported by the macOS runner yet"):"number"==typeof e.count||"number"==typeof e.intervalMs||"number"==typeof e.holdMs||"number"==typeof e.jitterPx||!0===e.doubleTap?new $("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}let o5=/^[A-Za-z0-9_.:-]{1,64}$/,o6=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function o9(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new $("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function o7(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await se(t)}async function se(e){await new Promise(t=>setTimeout(t,e))}function st(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new $("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!s.statSync(n).isFile())throw new $("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof $)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new $("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new $("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new $("INVALID_ARGS",`${a} file not found: ${n}`)}async function sr(e){let t=st(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await sa(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new $("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function sa(e){try{return await d.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new $("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new $("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new $("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new $("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let si=eF(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),sn=/^(iphone|ipad|ipod|appletv)/i,so=/^appletv/i,ss=["apple tv","appletv","tvos"];function sl(e){return(e??"").trim().toLowerCase()}function sd(e){return sl(e.hardwareProperties?.platform)}function su(e){return e.includes("tvos")}function sc(e){return su(sl(e))?"tv":"mobile"}function sp(e){let t=sl(e);return t.includes("ios")||t.includes("tvos")}function sf(e){let t=sl(e);return ss.some(e=>t.includes(e))}function sm(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function sh(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function sw(e={}){let t,r,a=eH(e.simulatorSetPath),i=e.target;try{t=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!sp(e))continue;let r=sc(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function sg(e={}){if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await V("xcrun"))throw new $("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eH(e.simulatorSetPath),a=await O("xcrun",eJ(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(sp(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:sc(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new $("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(t.push({platform:"macos",id:"host-macos-local",name:u.hostname(),kind:"device",target:"desktop",booted:!0}),r)return t;let i=null;try{i=c.join(u.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await O("xcrun",["devicectl","list","devices","--json-output",i],{allowFailure:!0,timeoutMs:si});if(0!==e.exitCode)return t;let r=await d.readFile(i,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=sd(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=sh(e),!!sn.test(t.trim())||sm(e).some(sf))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return su(sd(e))?"tv":(t=sh(e),so.test(t.trim())||sm(e).some(sf))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{i&&await d.rm(i,{force:!0}).catch(()=>{})}return t}async function sy(e,t,r){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await tu(e,t,r)}catch(e){if(i||!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!i&&(!t.platform||"apple"===t.platform||"ios"===t.platform)&&"desktop"!==t.target&&(!a||"device"===a.kind)){let e=await sw({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new $("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function sv(e){let t=e.platform,r=td({simulatorSetPath:eH(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=ez(e.androidDeviceAllowlist);return await X("resolve_target_device",async()=>{let i={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(i.target&&!i.platform)throw new $("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|apple with --target mobile|tv|desktop.");if("android"===i.platform){await r8();let e=await ap({serialAllowlist:a});return await tu(e,i)}if(i.platform){let e=await sg({simulatorSetPath:r});return await sy(e,i,{simulatorSetPath:r})}let n=[];try{n.push(...await ap({serialAllowlist:a}))}catch{}try{n.push(...await sg({simulatorSetPath:r}))}catch{}return await tu(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function sI(e,t,r,a,i){let n={requestId:i?.requestId,appBundleId:i?.appBundleId,verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath},o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>a8(e,t,r?.activity),openDevice:()=>it(e),close:t=>ir(e,t),tap:(t,r)=>iE(e,t,r),doubleTap:async(t,r)=>{await iE(e,t,r),await iE(e,t,r)},swipe:(t,r,a,i,n)=>iO(e,t,r,a,i,n),longPress:(t,r,a)=>iR(e,t,r,a),focus:(t,r)=>iF(e,t,r),type:(t,r)=>iT(e,t,r),fill:(t,r,a,i)=>iU(e,t,r,a,i),scroll:(t,r)=>ij(e,t,r),scrollIntoView:(t,r)=>iB(e,t,r),screenshot:t=>nn(e,t),back:t=>iL(e),home:()=>iC(e),appSwitcher:()=>iP(e),readClipboard:()=>iQ(e),writeClipboard:t=>i0(e,t),setSetting:(t,r,a,i)=>i5(e,t,r,a,i)};case"ios":case"macos":{let r,a,{overrides:i,runnerOpts:n}=(r={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},a=()=>{if(eP(t.requestId))throw eT()},{runnerOpts:r,overrides:{tap:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),doubleTap:async(a,i)=>await tz(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},r),swipe:async(a,i,n,o,s)=>await tz(e,{command:"drag",x:a,y:i,x2:n,y2:o,durationMs:s,appBundleId:t.appBundleId},r),longPress:async(a,i,n)=>await tz(e,{command:"longPress",x:a,y:i,durationMs:n,appBundleId:t.appBundleId},r),focus:async(a,i)=>await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r),type:async(a,i)=>{await tz(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},r)},fill:async(a,i,n,o)=>{let s=await tz(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},r);return await tz(e,{command:"type",text:n,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},r),s},scroll:async(a,i)=>await o0(tz,e,t,r,a,i),scrollIntoView:async(i,n)=>await oZ(a=>tz(e,{...a,appBundleId:t.appBundleId},r),a,i,n)}});return{open:(t,r)=>oE(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>oO(e),close:t=>oL(e,t),screenshot:async(t,r)=>{"macos"===e.platform&&r?.surface&&"app"!==r.surface?await nQ(t,{surface:r.surface,fullscreen:r.fullscreen}):await om(e,t,r?.appBundleId,r?.fullscreen)},back:async r=>{await tz(e,{command:"system"===r?"backSystem":"backInApp",appBundleId:t.appBundleId},n)},home:async()=>{await tz(e,{command:"home",appBundleId:t.appBundleId},n)},appSwitcher:async()=>{await tz(e,{command:"appSwitcher",appBundleId:t.appBundleId},n)},readClipboard:()=>o$(e),writeClipboard:t=>oF(e,t),setSetting:(t,r,a,i)=>oV(e,t,r,a,i),...i}}default:throw new $("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,n);return Q({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await X("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new $("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null,...Y("Opened device")};if(void 0!==a){if("android"===e.platform)throw new $("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(r9(t))throw new $("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!r9(a))throw new $("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId,url:a}),{app:t,url:a,...Y(`Opened: ${t}`)}}return await o.open(t,{activity:i?.activity,appBundleId:i?.appBundleId}),{app:t,...Y(`Opened: ${t}`)}}case"close":{let e=r[0];if(!e)return{closed:"session",...Y("Closed session")};return await o.close(e),{app:e,...Y(`Closed: ${e}`)}}case"press":{let t,[a,n]=r.map(Number);if(Number.isNaN(a)||Number.isNaN(n))throw new $("INVALID_ARGS","press requires x y");if("macos"===e.platform&&i?.surface&&"app"!==i.surface){let e=o4(i);if("primary"!==e)throw new $("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${i.surface} sessions.`);return await nZ(a,n,{bundleId:i.appBundleId,surface:i.surface}),{x:a,y:n,...Y(sA({x:a,y:n}))}}let s=o4(i);if("primary"!==s){let t=o8({commandLabel:"click",platform:e.platform,button:s,count:i?.count,intervalMs:i?.intervalMs,holdMs:i?.holdMs,jitterPx:i?.jitterPx,doubleTap:i?.doubleTap});if(t)throw t;return await tz(e,{command:"mouseClick",x:a,y:n,button:s,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{x:a,y:n,button:s,...Y(sA({x:a,y:n,button:s}))}}let l=o9(i?.count??1,"count",1,200),d=o9(i?.intervalMs??0,"interval-ms",0,1e4),u=o9(i?.holdMs??0,"hold-ms",0,1e4),c=o9(i?.jitterPx??0,"jitter-px",0,100),p=i?.doubleTap===!0;if(p&&u>0)throw new $("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(p&&c>0)throw new $("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&l>1&&0===u&&0===c){let t=await tz(e,{command:"tapSeries",x:a,y:n,count:l,intervalMs:d,doubleTap:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,timingMode:"runner-series",...t,...Y(sA({x:a,y:n}))}}return await o7(l,d,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=o6[e%o6.length];return[r*t,a*t]}(e,c),s=a+r,l=n+i;if(p){t??=await o.doubleTap(s,l)??void 0;return}u>0?t??=await o.longPress(s,l,u)??void 0:t??=await o.tap(s,l)??void 0}),T({x:a,y:n,count:l,intervalMs:d,holdMs:u,jitterPx:c,doubleTap:p,...t},sA({x:a,y:n}))}case"swipe":{let t=Number(r[0]),a=Number(r[1]),n=Number(r[2]),s=Number(r[3]);if([t,a,n,s].some(Number.isNaN))throw new $("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=o9(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=o9(i?.count??1,"count",1,200),c=o9(i?.pauseMs??0,"pause-ms",0,1e4),p=i?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new $("INVALID_ARGS",`Invalid pattern: ${p}`);if(("ios"===e.platform||"macos"===e.platform)&&u>1){let r=await tz(e,{command:"dragSeries",x:t,y:a,x2:n,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p,...r,...Y(sb(u,p))}}return await o7(u,c,async e=>{"ping-pong"===p&&e%2==1?await o.swipe(n,s,t,a,d):await o.swipe(t,a,n,s,d)}),T({x1:t,y1:a,x2:n,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:p},sb(u,p))}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a,...Y(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new $("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t,...Y(`Focused (${e}, ${t})`)}}case"type":{let e=function(e){let t=e[0]?.trim();if(!t||!t.startsWith("@")||t.length<3)return null;let r=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(r)||/^(?:ref|node|element|el)[\w-]*$/i.test(r)?t:null}(r);if(e)throw new $("INVALID_ARGS",`type does not accept a target ref like "${e}"`,{hint:`Use fill ${e} "text" to target that field, or press ${e} then type "text" to append.`});let t=r.join(" ");if(!t)throw new $("INVALID_ARGS","type requires text");let a=o9(i?.delayMs??0,"delay-ms",0,1e4);return await o.type(t,a),{text:t,delayMs:a,...Y(sS("Typed",t))}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new $("INVALID_ARGS","fill requires x y text");let n=o9(i?.delayMs??0,"delay-ms",0,1e4);return await o.fill(e,t,a,n),{x:e,y:t,text:a,delayMs:n,...Y(sS("Filled",a))}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0,a=i?.pixels;if(!e)throw new $("INVALID_ARGS","scroll requires direction");if(void 0!==t&&!Number.isFinite(t))throw new $("INVALID_ARGS","scroll amount must be a number");if(void 0!==t&&void 0!==a)throw new $("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let n=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new $("INVALID_ARGS",`Unknown direction: ${e}`)}}(e),s=await o.scroll(n,{amount:t,pixels:a});return T({direction:n,...void 0!==t?{amount:t}:{},...void 0!==a?{pixels:a}:{},...s},void 0!==a?`Scrolled ${n} by ${a}px`:void 0!==t?`Scrolled ${n} by ${t}`:`Scrolled ${n}`)}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new $("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e,{maxScrolls:i?.maxScrolls});if("number"==typeof t?.attempts)return{text:e,attempts:t.attempts,...Y(`Scrolled into view: ${e}`)};return{text:e,...Y(`Scrolled into view: ${e}`)}}case"pinch":{if("android"===e.platform)throw new $("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&i?.surface&&"app"!==i.surface)throw new $("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new $("INVALID_ARGS","pinch requires scale > 0");return await tz(e,{command:"pinch",scale:t,x:a,y:n,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{scale:t,x:a,y:n,...Y(`Pinched to scale ${t}`)}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new $("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!o5.test(t))throw new $("INVALID_ARGS",`Invalid trigger-app-event event name: ${t}`,{hint:"Use 1-64 chars: letters, numbers, underscore, dot, colon, or dash."});if(e.length>2)throw new $("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new $("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof $)throw t;throw new $("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),n=function(e,t,r){var a;let i,n=(i=("ios"===(a=e)?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:"macos"===a?process.env.AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,i?.trim()||void 0);if(!n)throw new $("UNSUPPORTED_OPERATION",`No app event URL template configured for ${e}.`,{hint:`Set AGENT_DEVICE_${e.toUpperCase()}_APP_EVENT_URL_TEMPLATE or AGENT_DEVICE_APP_EVENT_URL_TEMPLATE, for example "myapp://agent-device/event?name={event}&payload={payload}".`});let o=r?JSON.stringify(r):"",s=n.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new $("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:s.length,maxLength:4096});return s}(e.platform,t,a);return await o.open(n,{appBundleId:i?.appBundleId}),{event:t,eventUrl:n,transport:"deep-link",...Y(`Triggered app event: ${t}`)}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await d.mkdir(c.dirname(e),{recursive:!0}),await o.screenshot(e,{appBundleId:i?.appBundleId,fullscreen:i?.screenshotFullscreen,surface:i?.surface}),{path:e,...Y(`Saved screenshot: ${e}`)}}case"back":return await o.back(i?.backMode),{action:"back",mode:i?.backMode??"in-app",...Y("Back")};case"home":return await o.home(),{action:"home",...Y("Home")};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher",...Y("Opened app switcher")};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new $("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new $("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new $("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length,...Y("Clipboard updated")}}case"keyboard":{let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new $("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new $("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===t){let t=await iZ(e);return{platform:"android",action:"dismiss",attempts:t.attempts,wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,inputType:t.inputType,type:t.type}}let r=await iY(e);return{platform:"android",action:"status",visible:r.visible,inputType:r.inputType,type:r.type}}if("ios"===e.platform){if("dismiss"!==t)throw new $("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let r=await tz(e,{command:"keyboardDismiss",appBundleId:i?.appBundleId},n);return{platform:"ios",action:"dismiss",wasVisible:r.wasVisible,dismissed:r.dismissed,visible:r.visible,...Y(r.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new $("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}case"settings":{var s;let[t,a,n,l,d]=r,u="permission"===t?{permissionTarget:n,permissionMode:l}:void 0;Q({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:n,mode:l,platform:e.platform}});let c=await o.setSetting(t,a,d??i?.appBundleId,u);return c&&"object"==typeof c?T({setting:t,state:a,...c},("string"==typeof(s=c).message&&s.message.length>0?s.message:void 0)??`Updated setting: ${t}`):{setting:t,state:a,...Y(`Updated setting: ${t}`)}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new $("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await sr(a);if("ios"===e.platform)return await oU(e,t,i),{platform:"ios",bundleId:t,...Y(`Pushed notification to ${t}`)};let n=await na(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount,...Y(`Pushed notification to ${t}`)}}case"snapshot":{if("android"!==e.platform){let t=await X("snapshot_capture",async()=>await tz(e,{command:"snapshot",appBundleId:i?.appBundleId,interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new $("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await X("snapshot_capture",async()=>await iN(e,{interactiveOnly:i?.snapshotInteractiveOnly,compact:i?.snapshotCompact,depth:i?.snapshotDepth,scope:i?.snapshotScope,raw:i?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android",analysis:t.analysis}}case"read":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new $("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await iK(e,t,a)??""};if("macos"===e.platform&&i?.surface&&"app"!==i.surface)return{action:"read",text:(await nY(t,a,{bundleId:i.appBundleId,surface:i.surface})).text};let n=await tz(e,{command:"readText",x:t,y:a,appBundleId:i?.appBundleId},{verbose:i?.verbose,logPath:i?.logPath,traceLogPath:i?.traceLogPath,requestId:i?.requestId});return{action:"read",text:"string"==typeof n.text?n.text:"string"==typeof n.message?n.message:""}}default:throw new $("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}function sA(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sb(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sS(e,t){return`${e} ${Array.from(t).length} chars`}let s_=e=>"macos"!==e.platform,sN=e=>"macos"===e.platform||"simulator"===e.kind,sD={alert:{apple:{simulator:!0,device:!0},android:{},supports:sN},pinch:{apple:{simulator:!0,device:!0},android:{},supports:sN},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},supports:s_},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function sx(e,t){let r=sD[e];if(!r)return!0;let a=ts(t.platform)?r.apple:r.android;return!!a&&(!r.supports||!!r.supports(t))&&!0===a[t.kind??"unknown"]}function sk(e,t,r,a,i){return{requestId:i??J().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,screenshotFullscreen:t?.screenshotFullscreen,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:o4(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern,maxScrolls:t?.maxScrolls}}let sM=eF(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sE(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(eh);await t(e);return}if("device"===e.kind)return void await sO(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ec);await t(e.id)}}async function sO(e){let t=c.join(u.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(sM/1e3));try{let a=await O("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:sM+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await sL(t);if(0===a.exitCode){if(!o.parsed)throw new $("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,tunnelState:t,hint:"Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry."});return}throw new $("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sC(i,n)})}catch(t){if(t instanceof $&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??sM),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?sC(a,i):o},t)}throw new $("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,hint:"Reconnect the device, keep it unlocked, and retry."},t instanceof Error?t:void 0)}finally{await d.rm(t,{force:!0}).catch(()=>{})}}async function sL(e){try{let t=await d.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sC(e,t){let r=nv(e,t);return r||(`${e}
35
+ ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":ny)}let sP=eF(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),sR=new Map;async function sT(e){let t=await v.mkdtemp(c.join(u.tmpdir(),"agent-device-materialized-"));try{let r=await sU(e.installablePath,c.join(t,"installable")),a=e.archivePath?await sU(e.archivePath,c.join(t,"archive")):void 0,i=n.randomUUID(),o=e.ttlMs??sP,s=Date.now()+o,l=setTimeout(()=>{s$(i)},o);return sR.set(i,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:i,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await v.rm(t,{recursive:!0,force:!0}),e}}async function s$(e,t){let r=sR.get(e);if(!r)throw new $("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new $("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),sR.delete(e),await v.rm(r.rootPath,{recursive:!0,force:!0})}async function sF(e){let t=Array.from(sR.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await s$(e)}))}async function sU(e,t){let r=await v.stat(e);await v.mkdir(t,{recursive:!0});let a=c.join(t,c.basename(e));return r.isDirectory()?await v.cp(e,a,{recursive:!0}):await v.copyFile(e,a),a}async function sV(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new $("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await sE(e.session.device),e.session.device}if(!r)throw new $("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await sv(e.flags??{});return await sE(a),a}async function sG(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r);try{let e,n,o,s=(n=function(e){let t=e.meta?.installSource;if(!t)throw new $("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new $("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new $("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(o=t.meta?.uploadedArtifactId)&&"path"===n.kind?{source:{kind:"path",path:r_(o,t.meta?.tenantId)},cleanup:()=>{rN(o)}}:{source:n,cleanup:()=>{}}),l=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new $("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),d=await sV({session:i,flags:t.flags});if(!sx("install",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let u=eR(t.meta?.requestId);if("ios"===d.platform){let e,{installIosInstallablePath:n}=await Promise.resolve(eh),{prepareIosInstallArtifact:o}=await Promise.resolve(ew),c=await o(s.source,{signal:u});try{if(l.enabled&&(e=await sT({archivePath:c.archivePath,installablePath:c.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs})),await n(d,c.installablePath),!c.bundleId)throw new $("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let o={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:c.bundleId,...c.appName?{appName:c.appName}:{},launchTarget:c.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},s=T(o,sj(o));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:s}),{ok:!0,data:s}}catch(r){throw e&&await s$(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await c.cleanup(),s.cleanup()}}let{prepareAndroidInstallArtifact:c}=await Promise.resolve(ef),{installAndroidInstallablePathAndResolvePackageName:p}=await Promise.resolve(ep),f=await c(s.source,{signal:u});try{l.enabled&&(e=await sT({archivePath:f.archivePath,installablePath:f.installablePath,tenantId:t.meta?.tenantId,sessionName:i?r:void 0,ttlMs:l.ttlMs}));let n=await p(d,f.installablePath,f.packageName);if(!n)throw new $("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let{inferAndroidAppName:o}=await Promise.resolve(ep),s=o(n),u={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:n,...s?{appName:s}:{},launchTarget:n,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}},c=T(u,sj(u));return i&&a.recordAction(i,{command:"install_source",positionals:[],flags:t.flags??{},result:c}),{ok:!0,data:c}}catch(r){throw e&&await s$(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await f.cleanup(),s.cleanup()}}catch(e){return{ok:!1,error:q(e)}}}function sj(e){return`Installed: ${es(e)}`}async function sB(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new $("INVALID_ARGS","release_materialized_paths requires a materializationId");return await s$(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:q(e)}}}let sq=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sH=eF(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function sW(e,t,r){return t||sz(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sz(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sJ(e){return"ios"===e.platform&&"simulator"===e.kind}async function sK(e,t){sJ(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sX(e){let t=sz(e.flags)||!e.session?await sv(e.flags??{}):await sY(e.session.device);return!1!==e.ensureReady&&await sE(t),t}async function sY(e){if("ios"!==e.platform||"simulator"!==e.kind||"darwin"!==process.platform)return e;let t={platform:"ios",target:e.target,udid:e.id,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}};try{return await sv(t)}catch(e){if(!(e instanceof $)||"DEVICE_NOT_FOUND"!==e.code)throw e}return await sv({platform:"ios",target:e.target,device:e.name,...e.simulatorSetPath?{iosSimulatorDeviceSet:e.simulatorSetPath}:{}})}function sZ(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let sQ="shared_prefs/ReactNativeDevPrefs.xml",s0="debug_http_host",s1="dev_server_https",s2="RCT_jsLocation",s3="RCT_packager_scheme",s4="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",s8='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function s5(e){return void 0!==s6(e)}function s6(e){if(!e)return;let t=ld(e.metroHost),r=lc(e.metroPort),a="http",i=ld(e.bundleUrl);if(i){var n;let e;try{e=new f(i)}catch(e){throw new $("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=ld(e.hostname),r??=lc(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function s9(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=s6(a);if(i){if("android"===t.platform)return void await le(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await li(t,r,i)}}async function s7(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await lt(t,r);"ios"===t.platform&&"simulator"===t.kind&&await ln(t,r)}}async function le(e,t,r){var a,i,n,o,s,l;let d,u;lu(t);let c=(a=await lr(e,t),i=s0,n=`${r.host}:${r.port}`,d=` <string name="${lp(i)}">${lp(n)}</string>`,ls(ll(a,i),d));o=c,s=s1,l="https"===r.scheme,u=` <boolean name="${lp(s)}" value="${l?"true":"false"}" />`,c=ls(ll(o,s),u),await la(e,t,c)}async function lt(e,t){lu(t);let r=await lr(e,t),a=ll(r,s0),i=ll(a,s1);i!==r&&await la(e,t,i)}async function lr(e,t){let r=await O("adb",r4(e,["shell","run-as",t,"cat",sQ]),{allowFailure:!0});return 0!==r.exitCode?s8:lo(r.stdout)}async function la(e,t,r){let a=r4(e,["shell","run-as",t,"id"]),i=await O("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=lf(i.stdout,i.stderr);throw new $("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?s4:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await O("adb",r4(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await O("adb",r4(e,["shell","run-as",t,"tee",sQ]),{stdin:r.trimEnd()})}catch(a){let e=P(a);if("TOOL_MISSING"===e.code)throw e;let r=lf("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new $("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?s4:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function li(e,t,r){await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,s2,"-string",`${r.host}:${r.port}`])),await O("xcrun",eK(e,["spawn",e.id,"defaults","write",t,s3,"-string",r.scheme]))}async function ln(e,t){await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,s2]),{allowFailure:!0}),await O("xcrun",eK(e,["spawn",e.id,"defaults","delete",t,s3]),{allowFailure:!0})}function lo(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
36
+ `:s8}function ls(e,t){return lo(e).replace("</map>",`${t}
37
+ </map>`)}function ll(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return lo(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function ld(e){let t=e?.trim();return t&&t.length>0?t:void 0}function lu(e){if("binary"!==ab(e))return;let t=aS(e);throw new $("INVALID_ARGS",t,{package:e,hint:t})}function lc(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function lp(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function lf(e,t){let r=`${e}
38
+ ${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}let lm=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function lh(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function lw(e){let t=e?.trim();return t&&t.length>0?t:void 0}function lg(e,t){if(void 0!==e){if("string"!=typeof e)throw new $("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return lw(e)}}function ly(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new $("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function lv(e){if("ios"===e||"android"===e)return e}async function lI(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i}=e;!t||!i?.appBundleId||!s5(r)||s5(a)||await s7({device:i.device,appId:i.appBundleId})}async function lA(e){var t,r;let{req:a,sessionName:i,sessionStore:n}=e,o=(a.positionals?.[0]??"show").toLowerCase(),s=n.get(i),l=n.getRuntimeHints(i);if(!["set","show","clear"].includes(o))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===o){s5(l)&&s?.appBundleId&&await s7({device:s.device,appId:s.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===o)return{ok:!0,data:{session:i,configured:!!l,runtime:l}};let d=lv(a.flags?.platform??l?.platform??s?.device.platform);if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set only supports iOS and Android sessions. Pass --platform ios|android or open an iOS/Android session first."}};if(s&&s.device.platform!==d)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${d}, but session "${i}" is already bound to ${s.device.platform}.`}};let u={platform:(t=a.flags,r={platform:d,metroHost:lw(t?.metroHost),metroPort:ly(t?.metroPort),bundleUrl:lw(t?.bundleUrl),launchUrl:lw(t?.launchUrl)}).platform??l?.platform,metroHost:r.metroHost??l?.metroHost,metroPort:r.metroPort??l?.metroPort,bundleUrl:r.bundleUrl??l?.bundleUrl,launchUrl:r.launchUrl??l?.launchUrl};return 0===lh(u)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(n.setRuntimeHints(i,u),{ok:!0,data:{session:i,configured:!0,runtime:u}})}let lb="open-command-roundtrip",lS="Not implemented for this platform in this release.";async function l_(e){if("app"===e||"desktop"===e||"menubar"===e)return{};let t=await nW();return{appBundleId:t.bundleId,appName:t.appName}}async function lN(e,t,r){if(("ios"===e.platform||"macos"===e.platform)&&t)return r9(t)?"macos"===e.platform?void 0:"device"===e.kind?r7(r,t):void 0:await lD(e,t)}async function lD(e,t){try{let{resolveIosApp:r}=await Promise.resolve(eh);return await r(e,t)}catch{return}}async function lx(e,t){if(!("android"!==e.platform||!t||r9(t)))try{let{resolveAndroidApp:r}=await Promise.resolve(ep),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function lk(e,t,r,a){return await lN(e,t,r)??await a(e,t)??("android"===e.platform&&t&&r9(t)?r:void 0)}function lM(e){return{ok:!1,error:{code:"INVALID_ARGS",message:e}}}function lE(e,t,r,a){try{return function(e){let{device:t,surfaceFlag:r,openTarget:a,existingSurface:i}=e;if("macos"===t.platform&&!r)return i??"app";if("macos"!==t.platform){if(r)throw new $("INVALID_ARGS","surface is only supported on macOS");return"app"}let n=r?el(r):"app";if("app"!==n&&"menubar"!==n&&a)throw new $("INVALID_ARGS",`open --surface ${n} does not accept an app target`);return n}({device:e,surfaceFlag:t,openTarget:r,existingSurface:a})}catch(e){return{ok:!1,error:{code:e instanceof $?e.code:"INVALID_ARGS",message:String(e.message)}}}}function lO(e){let{shouldRelaunch:t,openTarget:r,surface:a,device:i}=e;return t?r&&r9(r)?lM("open --relaunch does not support URL targets."):"app"!==a?lM("open --relaunch is supported only for app surfaces."):"android"===i.platform&&r&&"binary"===ab(r)?lM(aS(r)):null:null}async function lL(e){let{req:t,sessionName:r,sessionStore:a,device:i,surface:n,openTarget:o,existingSession:s}=e;await sE(i);let{appBundleId:l,appName:d}=await lC({device:i,surface:n,openTarget:o,existingAppBundleId:s?.appBundleId}),u=function(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new $("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!lm.includes(e));if(i)throw new $("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${lm.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new $("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new $("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:lg(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new $("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return ly(e)}}(t.metroPort),bundleUrl:lg(t.bundleUrl,"bundleUrl"),launchUrl:lg(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:lv(i.platform)});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(!a)return;let i=r?.platform,n=lv(i);if(a.platform&&r&&!n)throw new $("INVALID_ARGS",`Session runtime hints are only supported on iOS and Android sessions, but session "${t}" is bound to ${i}.`);if(a.platform&&n&&a.platform!==n)throw new $("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${i}. Clear the runtime hints or use a different session.`);return n&&a.platform!==n?{...a,platform:n}:a}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&lh(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=P(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}({req:t,sessionStore:a,sessionName:r,device:i});if(!u.ok)return{type:"response",response:u.response};if(s){let{runtime:e,previousRuntime:t,replacedStoredRuntime:r}=u.data;await lI({replacedStoredRuntime:r,previousRuntime:t,runtime:e,session:s})}return{type:"details",details:{appBundleId:l,appName:d,runtime:u.data.runtime}}}async function lC(e){let{device:t,surface:r,openTarget:a,existingAppBundleId:i}=e,n=await l_(r);return{appBundleId:n.appBundleId??await lk(t,a,i,lx),appName:n.appName??a}}async function lP(e){let{device:t,closeTarget:r,outFlag:a,context:i}=e;"android"!==t.platform&&await tV(t.id),await sI(t,"close",[r],a,i),await sK(t,sq)}async function lR(e){let{runtime:t,device:r,req:a,logPath:i,appBundleId:n,traceLogPath:o,openPositionals:s}=e,l=t?.launchUrl;if(!l||0===s.length||s.length>1)return;let d=s[0]?.trim();!d||r9(d)||await sI(r,"open",[l],a.flags?.out,{...sk(i,a.flags,n,o)})}async function lT(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,openTarget:d,openPositionals:u,appName:c,surface:p,appBundleId:f,runtime:m,existingSession:h}=e,w=i.flags?.relaunch===!0,g=h?.trace?.outPath;if(w&&d){let e=f??d;await lP({device:l,closeTarget:e,outFlag:i.flags?.out,context:{...sk(s,i.flags,f??h?.appBundleId,g)}})}await s9({device:l,appId:f,runtime:m});let y=Date.now();await sI(l,"open",u,i.flags?.out,{...sk(s,i.flags,f)}),await lR({runtime:m,device:l,req:i,logPath:s,appBundleId:f,traceLogPath:g,openPositionals:u});let v=d?{durationMs:Math.max(0,Date.now()-y),measuredAt:new Date().toISOString(),method:lb,appTarget:d,appBundleId:f}:void 0;if(await sK(l,sH),eP(i.meta?.requestId)){let e=eT();return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}let I=function(e){let{existingSession:t,sessionName:r,device:a,surface:i,appBundleId:n,appName:o,saveScript:s}=e;return t?{...t,device:a,surface:i,appBundleId:n,appName:o,recordSession:t.recordSession||s,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),surface:i,appBundleId:n,appName:o,recordSession:s,actions:[]}}({existingSession:h,sessionName:n,device:l,surface:p,appBundleId:f,appName:c,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=m)&&(0===lh(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let A=function(e){let{sessionName:t,appName:r,appBundleId:a,surface:i,startup:n,device:o,runtime:s,runtimeHintCount:l}=e,d={session:t,surface:i};return r&&(d.appName=r),a&&(d.appBundleId=a),n&&(d.startup=n),s&&l(s)>0&&(d.runtime=s),o&&(d.platform=o.platform,d.target=o.target??"mobile",d.device=o.name,d.id=o.id,d.kind=o.kind,"android"===o.platform&&(d.serial=o.id)),o?.platform==="ios"&&(d.device_udid=o.id,d.ios_simulator_device_set=o.simulatorSetPath??null),{...d,...Y(`Opened: ${r??a??t}`)}}({sessionName:n,appName:c,appBundleId:f,surface:p,startup:v,device:l,runtime:m,runtimeHintCount:lh});return o.recordAction(I,{command:"open",positionals:u,flags:i.flags??{},runtime:void 0!==i.runtime?m:void 0,result:A}),o.set(n,I),{ok:!0,data:A}}async function l$(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e;if(i.has(r)){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:`Session "${r}" not found.`}};let n=t.flags?.relaunch===!0,o=t.positionals?.[0],s=o??(n?e.appName:void 0),l=lE(e.device,t.flags?.surface,s,e.surface);if("string"!=typeof l)return l;if(!s&&"app"===l)return n?lM("open --relaunch requires an app name or an active session app."):lM("Session already active. Close it first or pass a new --session name.");let d=lO({shouldRelaunch:n,openTarget:s,surface:l,device:e.device});if(d)return d;let u=await sY(e.device),c=await lL({req:t,sessionName:r,sessionStore:i,device:u,surface:l,openTarget:s,existingSession:e});return"response"===c.type?c.response:await lT({req:t,sessionName:r,sessionStore:i,logPath:a,device:u,openTarget:s,openPositionals:o?t.positionals??[]:s?[s]:[],appBundleId:c.details.appBundleId,appName:c.details.appName,runtime:c.details.runtime,surface:l,existingSession:e})}let n=t.flags?.relaunch===!0,o=t.positionals?.[0];if(n&&!o)return lM("open --relaunch requires an app argument.");let s=function(e){let{shouldRelaunch:t,openTarget:r,platform:a}=e;return t?r&&r9(r)?lM("open --relaunch does not support URL targets."):"android"===a&&r&&"binary"===ab(r)?lM(aS(r)):null:null}({shouldRelaunch:n,openTarget:o,platform:t.flags?.platform==="android"?"android":void 0});if(s)return s;let l=await sv(t.flags??{}),d=lE(l,t.flags?.surface,o);if("string"!=typeof d)return d;let u=lO({shouldRelaunch:n,openTarget:o,surface:d,device:l});if(u)return u;let c=i.toArray().find(e=>e.device.id===l.id);if(c)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${c.name}".`,details:{session:c.name,deviceId:l.id,deviceName:l.name}}};let p=await lL({req:t,sessionName:r,sessionStore:i,device:l,surface:d,openTarget:o});return"response"===p.type?p.response:await lT({req:t,sessionName:r,sessionStore:i,logPath:a,device:l,openTarget:o,openPositionals:t.positionals??[],appBundleId:p.details.appBundleId,appName:p.details.appName,runtime:p.details.runtime,surface:d})}async function lF(e){let t=await O("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function lU(e){let{device:t,shutdownRequested:r}=e;if(r&&(sJ(t)||"android"===t.platform&&"emulator"===t.kind))try{return sJ(t)?await nN(t):await lF(t)}catch(t){let e=q(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function lV(e){if(await tV(e.device.id),"macos"!==e.device.platform)return;let t="frontmost-app"===e.surface?{surface:"frontmost-app"}:e.appBundleId?{bundleId:e.appBundleId}:{};await nK("dismiss",t).catch(t=>{Q({level:"debug",phase:"macos_close_alert_dismiss_failed",data:{session:e.name,error:t instanceof Error?t.message:String(t)}})})}async function lG(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};n.appLog&&await ry(n.appLog),t.positionals&&t.positionals.length>0&&(("ios"===n.device.platform||"macos"===n.device.platform)&&await lV(n),await sI(n.device,"close",t.positionals,t.flags?.out,{...sk(a,t.flags,n.appBundleId,n.trace?.outPath)}),await sK(n.device,sq)),("ios"===n.device.platform||"macos"===n.device.platform)&&await lV(n),s5(i.getRuntimeHints(r))&&n.appBundleId&&await s7({device:n.device,appId:n.appBundleId}).catch(()=>{}),i.recordAction(n,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r,...Y(`Closed: ${r}`)}}),t.flags?.saveScript&&(n.recordSession=!0),i.writeSessionLog(n),await sF(r).catch(()=>{}),i.delete(r);let o=await lU({device:n.device,shutdownRequested:t.flags?.shutdown});return o?{ok:!0,data:T({session:r,shutdown:o},`Closed: ${r}`)}:{ok:!0,data:{session:r,...Y(`Closed: ${r}`)}}}function lj(e,t,r){return{ok:!1,error:{code:e,message:t,...r?{details:r}:{}}}}let lB={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve(eh);return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve(ep);return await a(e,t,r)}},lq={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve(eh),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve(ep),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function lH(e){let{req:t,command:r,sessionName:a,sessionStore:i,deployOps:n}=e,o=i.get(a),l=t.flags??{},d=sW(r,o,l);if(d)return d;let u=t.positionals?.[0]?.trim(),c=t.positionals?.[1]?.trim();if(!u||!c)return lj("INVALID_ARGS",`${r} requires: ${r} <app> <path-to-app-binary>`);let p=t.meta?.uploadedArtifactId;try{var f;let e,a=p?r_(p,t.meta?.tenantId):rr.expandHome(c);if(!s.existsSync(a))return lj("INVALID_ARGS",`App binary not found: ${a}`);let d=await sX({session:o,flags:l,ensureReady:!1});if(!sx(r,d))return lj("UNSUPPORTED_OPERATION",`${r} is not supported on this device`);if("ios"===d.platform){let t=await n.ios(d,u,a),r=t.bundleId;e=r?{app:u,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await n.android(d,u,a),r=t.package;e=r?{app:u,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:u,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}let m=T(e,(f=e,`Installed: ${f.appName??L(f)}`));return o&&i.recordAction(o,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:m??{}}),{ok:!0,data:m}}finally{p&&rN(p)}}let lW=["platform","target","device","udid","serial","verbose","out"];async function lz(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let i=e.flags?.batchMaxSteps??ee;if(!Number.isInteger(i)||i<1||i>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let a=E(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await lJ(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function lJ(e,t,r,a,i){let n=Date.now(),o=function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of lW)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags);void 0===o.session&&(o.session=t);let s=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:o,runtime:r.runtime,meta:e.meta}),l=Date.now()-n;return s.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:s.data??{},durationMs:l}}:{ok:!1,step:i,error:s.error}}async function lK(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new $("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await lX({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await lY({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lZ(t,u),a=!0)}else t=(await lY({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await lZ(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function lX(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await O("xcrun",eJ(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:nu});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||lQ(a).includes(lQ(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function lY(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await O("xcrun",eJ(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new $("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new $("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function lZ(e,t){let r=await O("xcrun",eJ(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:nu});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function lQ(e){return e.toLowerCase().replace(/[._-]/g,"")}async function l0(e){let{req:t,sessionName:r,sessionStore:a}=e;if("session_list"===t.command)return{ok:!0,data:{sessions:a.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",surface:e.surface??"app",device:e.device.name,id:e.device.id,device_id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("ensure-simulator"===t.command)try{let e=t.flags??{},r=e.device,a=e.runtime,i=eH(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=await lK({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:!1!==e.reuseExisting,boot:!0===e.boot,ensureReady:sE});return{ok:!0,data:{udid:n.udid,device:n.device,runtime:n.runtime,ios_simulator_device_set:i??null,created:n.created,booted:n.booted}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===t.command)try{let e=[],r=ez(t.flags?.androidDeviceAllowlist),a=t.flags?.platform,i=td({simulatorSetPath:eH(t.flags?.iosSimulatorDeviceSet),platform:a,target:t.flags?.target});if("android"===a){let{listAndroidDevices:t}=await Promise.resolve(ec);e.push(...await t({serialAllowlist:r}))}else if("ios"===a||"macos"===a){let{listAppleDevices:t}=await Promise.resolve(em);e.push(...await t({simulatorSetPath:i}))}else{if("apple"!==a){let{listAndroidDevices:t}=await Promise.resolve(ec);try{e.push(...await t({serialAllowlist:r}))}catch{}}let{listAppleDevices:t}=await Promise.resolve(em);try{e.push(...await t({simulatorSetPath:i}))}catch{}}let n="ios"===a||"macos"===a?e.filter(e=>e.platform===a):e,o=(t.flags?.target?n.filter(e=>(e.target??"mobile")===t.flags?.target):n).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:o}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===t.command){let e=a.get(r),i=t.flags??{},n=sW(t.command,e,i);if(n)return n;let o=await sX({session:e,flags:i,ensureReady:!0});if(!sx("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if(ts(o.platform)){let{listIosApps:e}=await Promise.resolve(eh);return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve(ep);return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}return null}async function l1(e){let{ensureAndroidEmulatorBooted:t}=await Promise.resolve(ec);return await t(e)}let l2='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',l3='macOS appstate requires an active session on the target device. Run open first (for example: open --session macos --platform macos "System Settings").';async function l4(e){let{req:t,sessionName:r,sessionStore:a}=e,i=a.get(r),n=t.flags??{},o=n.platform;if(!i&&"string"==typeof n?.session&&n.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===o?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`}};let s=sW("appstate",i,n);if(s)return s;let l=(i?.device.platform==="ios"||i?.device.platform==="macos")&&function(e,t){if(!t)return!1;if(!sz(e))return!0;let r=e?.platform;return!(r&&!tl(t.device.platform,r)||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(n,i);if("ios"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l2}};if("macos"===o&&!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l3}};if(l&&i){let e=i.appName??i.appBundleId;if(!i.appName&&!i.appBundleId){if("macos"===i.device.platform&&i.surface&&"app"!==i.surface&&"frontmost-app"!==i.surface)return{ok:!0,data:{platform:i.device.platform,appName:i.surface,appBundleId:i.appBundleId,source:"session",surface:i.surface}};let e="macos"===i.device.platform?"macOS":"iOS";return{ok:!1,error:{code:"COMMAND_FAILED",message:`No foreground app is tracked for this ${e} session. Open an app in the session, then retry appstate.`}}}return{ok:!0,data:{platform:i.device.platform,appName:e??"unknown",appBundleId:i.appBundleId,source:"session",surface:i.surface??"app",..."ios"===i.device.platform?{device_udid:i.device.id,ios_simulator_device_set:i.device.simulatorSetPath??null}:{}}}}let d=await sX({session:i,flags:n,ensureReady:!0});if("ios"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l2}};if("macos"===d.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:l3}};let{getAndroidAppState:u}=await Promise.resolve(ep),c=await u(d);return{ok:!0,data:{platform:"android",package:c.package,activity:c.activity}}}async function l8(e){let{req:t,sessionName:r,sessionStore:a}=e;if("boot"===t.command){let e,i=a.get(r),n=t.flags??{},o=sW(t.command,i,n);if(o)return o;let s="android"===(n.platform??i?.device.platform),l=!0===n.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=sZ({flags:n,sessionDevice:i?.device}),u=s&&!!d,c=!1;try{e=await sX({session:i,flags:n,ensureReady:!1})}catch(r){let t=P(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await l1({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${n.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let t=sZ({flags:n,sessionDevice:i?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await l1({avdName:t,serial:n.serial,headless:!0})}await sE(e)}else("android"!==e.platform||!0!==e.booted)&&await sE(e);return sx("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"boot is not supported on this device"}}}return"appstate"===t.command?await l4({req:t,sessionName:r,sessionStore:a}):null}let l5=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),l6=/https?:\/\/[^\s"'<>\])]+/i,l9=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function l7(e,t,r){let a=[],i=Math.max(0,t-r),n=Math.min(e.length-1,t+r);for(let t=i;t<=n;t+=1){let r=e[t]?.trim();r&&a.push(r)}return a}function de(e){for(let t of l9){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}function dt(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function dr(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function da(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function di(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function dn(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return ds(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function ds(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function dl(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function dd(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let du=["path","start","stop","doctor","mark","clear"],dc=`logs requires ${du.slice(0,-1).join(", ")}, or ${du.at(-1)}`,dp=["dump","log"],df=`network requires ${dp.join(" or ")}`,dm=["summary","headers","body","all"],dh=`network include mode must be one of: ${dm.join(", ")}`;function dw(e){return e.appLog?e.appLog.backend:"macos"===e.device.platform?"macos":"ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"}async function dg(e){let{req:t,sessionName:r,sessionStore:a}=e;if("perf"===t.command){let e,t,i,n=a.get(r);return n?{ok:!0,data:(i=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===lb&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:lb,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:lb,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:lb},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:i,fps:{available:!1,reason:lS},memory:{available:!1,reason:lS},cpu:{available:!1,reason:lS}},sampling:{startup:{method:lb,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("logs"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};if(!sx("logs",e.device))return{ok:!1,error:q(new $("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let i=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!du.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:dc}};if(n&&"clear"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===i){let t=a.resolveAppLogPath(r),i=function(e){if(!s.existsSync(e))return{exists:!1,sizeBytes:0};let t=s.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:dw(e),sizeBytes:i.sizeBytes,modifiedAt:i.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===i){let t=a.resolveAppLogPath(r),i=await rv(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:i.checks,notes:i.notes}}}if("mark"===i){let e,i=t.positionals?.slice(1).join(" ")??"",n=a.resolveAppLogPath(r);return rw(n),e=`[agent-device][mark][${new Date().toISOString()}] ${i.trim()||"marker"}
39
+ `,s.appendFileSync(n,e,"utf8"),{ok:!0,data:{path:n,marked:!0}}}if("clear"===i){if(e.appLog&&!n)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(n&&!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r);if(!n)return{ok:!0,data:rI(t)};e.appLog&&await ry(e.appLog);let i=rI(t),o=a.resolveAppLogPidPath(r);try{let n=await rg(e.device,e.appBundleId,t,o);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{...i,restarted:!0}}}catch(t){return a.set(r,{...e,appLog:void 0}),{ok:!1,error:q(t)}}}if("start"===i){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};let t=a.resolveAppLogPath(r),i=a.resolveAppLogPidPath(r);try{let n=await rg(e.device,e.appBundleId,t,i);return a.set(r,{...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}}),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:q(e)}}}if("stop"===i){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await ry(e.appLog),a.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===t.command){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};if(!sx("network",e.device))return{ok:!1,error:q(new $("UNSUPPORTED_OPERATION","network is not supported on this device"))};let i=(t.positionals?.[0]??"dump").toLowerCase();if(!dp.includes(i))return{ok:!1,error:{code:"INVALID_ARGS",message:df}};let n=t.positionals?.[1]?Number.parseInt(t.positionals[1],10):25;if(!Number.isInteger(n)||n<1||n>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let o=t.positionals?.[2]?.toLowerCase(),l=t.flags?.networkInclude;if(o&&l&&o!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:"network include mode was provided both positionally and via --include with different values"}};let d=(l??o??"summary").toLowerCase();if(!dm.includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:dh}};let u=dw(e),c=function(e,t){let r=dd(t?.maxEntries,25,1,200),a=t?.backend,i=t?.include??"summary",n=dd(t?.maxPayloadChars,2048,64,16384),o=dd(t?.maxScanLines,4e3,100,2e4);if(!s.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}};let l=s.readFileSync(e,"utf8").split("\n"),d=Math.max(0,l.length-o),u=l.slice(d),c=[];for(let e=u.length-1;e>=0&&c.length<r;e-=1){let t=u[e];if(!t?.trim())continue;let r=function(e,t,r,a,i,n){let o=e[t]?.trim();if(!o)return null;let s=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(o),l=di(s,["method","httpMethod"]),d=di(s,["url","requestUrl"]),u=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(s,["status","statusCode","responseCode"]),c=l5.exec(o),p=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),f=(l??p?.[1]??c?.[1])?.toUpperCase(),m=l6.exec(o),h=d??m?.[0];if(!h)return null;let w={method:f,url:h,status:u??de(o)??void 0,timestamp:dt(o),packetId:dr(o)??void 0,durationMs:da(o)??void 0,raw:dl(o,n),line:r};if("android"===a&&function(e,t,r){let a=l7(t,r,5),i=e.packetId??a.map(e=>dr(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let n=i?l7(t,r,12).filter(e=>dr(e)===i):a;e.timestamp||(e.timestamp=n.map(e=>dt(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=n.map(e=>de(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=n.map(e=>da(e)).find(e=>"number"==typeof e))}(w,e,t),"headers"===i||"all"===i){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return ds(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,s);e&&(w.headers=dl(e,n))}if("body"===i||"all"===i){let e=dn(o,s,["requestBody","body","payload","request"]),t=dn(o,s,["responseBody","response"]);e&&(w.requestBody=dl(e,n)),t&&(w.responseBody=dl(t,n))}return w}(u,e,d+e+1,a,i,n);r&&c.push(r)}return{path:e,exists:!0,scannedLines:u.length,matchedLines:c.length,entries:c,include:i,limits:{maxEntries:r,maxPayloadChars:n,maxScanLines:o}}}(a.resolveAppLogPath(r),{backend:u,maxEntries:n,include:d,maxPayloadChars:2048,maxScanLines:4e3}),p=[];return e.appLog?"active"!==e.appLog.getState()&&p.push("Session app log stream is inactive. Run logs clear --restart, reproduce the request window again, then rerun network dump."):p.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===c.entries.length&&p.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...c,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:dw(e),notes:p}}}return null}let dy=new Set(["ios","android","macos"]);function dv(e,t,r){let a=e[t];if(void 0!==a)throw new $("INVALID_ARGS",a===r?`Duplicate replay test metadata "${t}" in context header.`:`Conflicting replay test metadata "${t}" in context header: ${String(a)} vs ${String(r)}.`);e[t]=r}function dI(e){return!!e&&!Number.isNaN(Number(e))}let dA=/[*?[\]{}]/;async function db(e){let t,{filePath:r,sessionName:a,requestId:i,timeoutMs:n,platform:o,runReplay:s,cleanupSession:l}=e;eO(i);let d=new Set,u=!1,c=s({filePath:r,sessionName:a,platform:o,requestId:i,artifactPaths:d}).catch(e=>{let t=P(e);return{ok:!1,error:{code:t.code,message:t.message}}}).finally(()=>{eC(i)});try{return"number"==typeof n?await Promise.race([c,new Promise(e=>{t=setTimeout(()=>{u=!0,eL(i),e(function(e,t=[]){return{ok:!1,error:{code:"COMMAND_FAILED",message:`TIMEOUT after ${e}ms`,hint:"Replay test timeouts are cooperative; the active command may take a short grace period to stop.",details:{reason:"timeout",timeoutMs:e,timeoutMode:"cooperative",artifactPaths:t}}}}(n,[...d]))},n)})]):await c}finally{t&&clearTimeout(t),u&&(await dS(c)||Q({level:"warn",phase:"test_timeout_cleanup_race",data:{session:a,requestId:i,graceMs:2e3}}));try{await l(a)}catch(e){Q({level:"warn",phase:"test_cleanup_failed",data:{session:a,error:P(e).message}})}}}async function dS(e){return await Promise.race([e.then(()=>!0),A(2e3).then(()=>!1)])}async function d_(e){let{req:t,sessionName:r,runReplay:a,cleanupSession:i}=e;if((t.positionals?.length??0)===0)return{ok:!1,error:{code:"INVALID_ARGS",message:"test requires at least one path or glob"}};try{var n,o,l,d,u,p;let e,f,m,h,w,g=function(e){let{inputs:t,cwd:r,platformFilter:a}=e,i=r??process.cwd(),n=[...new Set(t.flatMap(e=>(function(e,t){var r,a;let i=rr.expandHome(e,t);if(s.existsSync(i)){let t=s.statSync(i);if(t.isDirectory())return s.globSync("**/*.ad",{cwd:i}).map(e=>c.join(i,e));if(t.isFile()){if(".ad"!==c.extname(i))throw new $("INVALID_ARGS",`test requires .ad files. Received: ${e}`);return[i]}return[]}if(r=e,!dA.test(r)&&(a=i,!dA.test(a)))throw new $("INVALID_ARGS",`test input not found: ${e}`);let n=c.isAbsolute(i)?i:e;return s.globSync(n,{cwd:c.isAbsolute(i)?void 0:t}).map(e=>c.isAbsolute(e)?e:c.resolve(t,e)).filter(e=>".ad"===c.extname(e)&&function(e){try{return s.statSync(e).isFile()}catch{return!1}}(e))})(e,i)))].map(e=>c.normalize(e)).sort((e,t)=>e.localeCompare(t)),o=[];for(let e of n){var l,d;let t=function(e){let t=e.split(/\r?\n/),r={};for(let e of t){let t=e.trim();if(0===t.length||t.startsWith("#"))continue;if(!t.startsWith("context "))break;let a=t.match(/(?:^|\s)platform=([^\s]+)/);if(a){let e=a[1];e&&dy.has(e)&&dv(r,"platform",e)}let i=t.match(/(?:^|\s)timeout=(\d+)/);if(i){let e=Number(i[1]);Number.isFinite(e)&&e>=1&&dv(r,"timeoutMs",Math.floor(e))}let n=t.match(/(?:^|\s)retries=(\d+)/);if(n){let e=Number(n[1]);Number.isFinite(e)&&e>=0&&dv(r,"retries",Math.floor(e))}}return r}(s.readFileSync(e,"utf8"));if(!a){o.push({kind:"run",path:e,metadata:t});continue}if(!t.platform){o.push({kind:"skip",path:e,reason:"skipped-by-filter",message:`missing platform metadata for --platform ${a}`});continue}l=a,d=t.platform,("apple"===l?"apple"===d||"ios"===d||"macos"===d:d===l)&&o.push({kind:"run",path:e,metadata:t})}if(0===o.filter(e=>"run"===e.kind).length){let e=a?` for --platform ${a}`:"";throw new $("INVALID_ARGS",`No .ad tests matched${e}.`)}return o}({inputs:t.positionals,cwd:t.meta?.cwd,platformFilter:t.flags?.platform}),y=(n=t.meta?.requestId,(n?.trim()||`${process.pid}-${Date.now().toString(36)}`).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"suite"),v=function(e){let{artifactsDir:t,cwd:r,suiteInvocationId:a}=e,i=rr.expandHome(t??".agent-device/test-artifacts",r);return c.join(i,a)}({artifactsDir:"string"==typeof t.flags?.artifactsDir?t.flags.artifactsDir:void 0,cwd:t.meta?.cwd,suiteInvocationId:y}),I=[],A=Date.now(),b=0;for(let e of g){if("skip"===e.kind){I.push({file:e.path,status:"skipped",durationMs:0,reason:e.reason,message:e.message});continue}b+=1;let n=await dN({entry:e,sessionName:r,suiteInvocationId:y,caseIndex:b-1,cwd:t.meta?.cwd,requestId:t.meta?.requestId,retries:function(e,t){let r="number"==typeof e?e:t;return"number"!=typeof r?0:Math.max(0,Math.min(3,r))}(t.flags?.retries,e.metadata.retries),timeoutMs:(o=t.flags?.timeoutMs,l=e.metadata.timeoutMs,"number"==typeof o?o:l),suiteArtifactsDir:v,runReplay:a,cleanupSession:i});if(I.push(n),t.flags?.failFast===!0)break}let S=(d=g.length,u=I,p=Date.now()-A,e=u.filter(e=>"passed"===e.status).length,m=(f=u.filter(e=>"failed"===e.status)).length,h=u.filter(e=>"skipped"===e.status).length,w=e+m,{total:d,executed:w,passed:e,failed:m,skipped:h,notRun:Math.max(0,d-w-h),durationMs:p,failures:f,tests:u});return{ok:!0,data:S}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message}}}}async function dN(e){var t,r;let a,i,{entry:n,sessionName:o,suiteInvocationId:l,caseIndex:d,cwd:u,requestId:p,retries:f,timeoutMs:m,suiteArtifactsDir:h,runReplay:w,cleanupSession:g}=e,y=Date.now(),v=c.join(h,(t=n.path,(0===(i=u?c.relative(u,t):c.basename(t)).length||i.startsWith("..")?c.basename(t):i).toLowerCase().replace(/[\\/]+/g,"__").replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"test")),I="",A=0;for(let e=0;e<=f;e+=1){A=e+1;let t=function(e,t,r,a,i=0){let n=c.basename(r,c.extname(r)).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${e}:test:${t}:${a+1}${n?`-${n}`:""}:attempt-${i+1}`}(o,l,n.path,d,e),i=c.join(v,`attempt-${A}`);r=n.path,s.mkdirSync(i,{recursive:!0}),s.copyFileSync(r,c.join(i,"replay.ad"));let u=function(e){let{requestId:t,suiteInvocationId:r,filePath:a,caseIndex:i,attemptIndex:n}=e;return eE(`${t??r}:test:${i+1}:${c.basename(a)}:attempt:${n+1}`,r)}({requestId:p,suiteInvocationId:l,filePath:n.path,caseIndex:d,attemptIndex:e}),h=await db({filePath:n.path,sessionName:t,requestId:u,timeoutMs:m,platform:n.metadata.platform,runReplay:w,cleanupSession:g});if(!function(e){let{response:t,filePath:r,sessionName:a,attempts:i,maxAttempts:n,attemptArtifactsDir:o}=e,l=[...function(e){let t=e.ok?e.data?.artifactPaths:e.error.details?.artifactPaths;return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e))]:[]}(t)];t.ok||"string"!=typeof t.error.logPath||l.push(t.error.logPath);let d=function(e,t){let r=[],a=new Map;for(let i of e){if(!function(e){try{return s.statSync(e).isFile()}catch{return!1}}(i))continue;let e=function(e,t){let r=c.extname(e),a=r?e.slice(0,-r.length):e,i=t.get(e)??0;return(t.set(e,i+1),0===i)?e:`${a}-${i+1}${r}`}(c.basename(i),a),n=c.join(t,e);c.resolve(i)!==c.resolve(n)&&s.copyFileSync(i,n),r.push(n)}return r}(l,o),u=[`file: ${r}`,`session: ${a}`,`attempt: ${i}/${n}`,`status: ${t.ok?"passed":"failed"}`];if(t.ok){let e="number"==typeof t.data?.replayed?t.data.replayed:0,r="number"==typeof t.data?.healed?t.data.healed:0;u.push(`replayed: ${e}`,`healed: ${r}`)}else u.push(`code: ${t.error.code}`,`message: ${t.error.message}`),t.error.hint&&u.push(`hint: ${t.error.hint}`),t.error.diagnosticId&&u.push(`diagnosticId: ${t.error.diagnosticId}`),t.error.logPath&&u.push(`logPath: ${t.error.logPath}`),t.error.details?.reason==="timeout"&&u.push("timeoutMode: cooperative");d.length>0&&u.push(`copiedArtifacts: ${d.map(e=>c.basename(e)).join(", ")}`);let p=c.join(o,"result.txt"),f=`${u.join("\n")}
40
+ `;s.writeFileSync(p,f),t.ok||s.writeFileSync(c.join(o,"failure.txt"),f)}({response:h,filePath:n.path,sessionName:t,attempts:A,maxAttempts:f+1,attemptArtifactsDir:i}),a=h,I=t,h.ok)break}let b=Date.now()-y;if(a?.ok)return{file:n.path,session:I,status:"passed",durationMs:b,attempts:A,artifactsDir:v,replayed:"number"==typeof a.data?.replayed?a.data.replayed:0,healed:"number"==typeof a.data?.healed?a.data.healed:0};let S=a?.ok?{code:"COMMAND_FAILED",message:"Unknown replay test failure"}:a?.error??{code:"COMMAND_FAILED",message:"Unknown replay test failure"};return{file:n.path,session:I,status:"failed",durationMs:b,attempts:A,artifactsDir:v,error:S}}function dD(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function dx(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function dk(e,t){return e.find(e=>e.ref===t)??null}function dM(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function dE(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),i=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||i.includes(r)})??null}function dO(e,t){let r=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);return r&&dL(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,a=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!dL(t))continue;let i=Math.abs(e.rect.y+e.rect.height/2-r);(!a||i<a.distance)&&(a={label:t,distance:i})}return a?.label}(e,t)??(r&&dL(r)?r:void 0)}function dL(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function dC(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let i=dP(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&dL(n);if(("group"===i||"ioscontentgroup"===i)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function dP(e){let t=e.trim().replace(/XCUIElementType/gi,"");t.startsWith("AX")&&(t=t.slice(2));let r=Math.max((t=t.toLowerCase()).lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function dR(e,t){let r=dP(e);return!r||("android"===t?r.includes("edittext")||r.includes("autocompletetextview"):r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("textview")||r.includes("textarea")||"search"===r)}function dT(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}function d$(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let dF=new Set(["id","role","text","label","value"]),dU=new Set(["visible","hidden","editable","selected","enabled","hittable"]),dV=new Set([...dF,...dU]);function dG(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dJ(e,i)){a=dW(a,n),r+=n;continue}if(!a&&"|"===n&&"|"===e[i+1]){let a=r.trim();if(!a)throw new $("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new $("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new $("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!dJ(e,i)){a=dW(a,n),r+=n;continue}if(!a&&/\s/.test(n)){r.trim()&&t.push(r.trim()),r="";continue}r+=n}if(a)throw new $("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new $("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(dH)}})(e))}}function dj(e){try{return dG(e)}catch{return null}}function dB(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,i=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return dV.has(e)}return dV.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&dj(t)&&i.push(a)}if(0===i.length)return null;let n=i[i.length-1];if(r){for(let t=i.length-1;t>=0;t-=1)if(i[t]<e.length){n=i[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function dq(e){let t=e[0]??"",r=dB(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function dH(e){let t=e.trim();if(!t)throw new $("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!dU.has(r))throw new $("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),i=t.slice(r+1).trim();if(!dV.has(a))throw new $("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new $("INVALID_ARGS",`Missing selector value for key: ${a}`);if(dU.has(a)){let e,t="true"===(e=dz(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new $("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:dz(i)}}function dW(e,t){return e?e===t?null:e:t}function dz(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function dJ(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function dK(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return dZ(e.identifier,String(t.value));case"role":return dZ(dP(e.type??""),String(t.value));case"label":return dZ(e.label,String(t.value));case"value":return dZ(e.value,String(t.value));case"text":return dZ(d$(e),String(t.value));case"visible":return dX(e)===!!t.value;case"hidden":return!dX(e)==!!t.value;case"editable":return dY(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function dX(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function dY(e,t){return dR(e.type??"",t)&&!1!==e.enabled}function dZ(e,t){return dQ(e??"")===dQ(t)}function dQ(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function d0(e,t,r){let a=r.requireRect??!1,i=r.requireUnique??!0,n=[];for(let o=0;o<t.selectors.length;o+=1){let s=t.selectors[o],l=function(e,t,r,a){let i=0,n=null,o=null,s=!1;for(let l of e){if(a&&!l.rect||!dK(l,t,r))continue;if(i+=1,n??=l,!o){o=l;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let i=d3(e),n=d3(t);return i!==n?i<n?1:-1:0}(l,o);e>0?(o=l,s=!1):0===e&&(s=!0)}return{count:i,firstNode:n,disambiguated:s?null:o}}(e,s,r.platform,a);if(n.push({selector:s.raw,matches:l.count}),0!==l.count&&l.firstNode){if(i&&1!==l.count){if(!r.disambiguateAmbiguous||!l.disambiguated)continue;return{node:l.disambiguated,selector:s,selectorIndex:o,matches:l.count,diagnostics:n}}return{node:l.firstNode,selector:s,selectorIndex:o,matches:l.count,diagnostics:n}}}return null}function d1(e,t,r){let a=r.requireRect??!1,i=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r,a){let i=0;for(let n of e)(!a||n.rect)&&dK(n,t,r)&&(i+=1);return i}(e,o,r.platform,a);if(i.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:i}}return null}function d2(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let a=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${a})`:`Selector did not match (${a})`}function d3(e){return e.rect?e.rect.width*e.rect.height:1/0}function d4(e,t,r={}){let a=[],i=dP(e.type??""),n=d5(e.identifier),o=d5(e.label),s=d5(e.value),l=d5(d$(e)),d="fill"===r.action;n&&a.push(`id=${d8(n)}`),i&&o&&a.push(d?`role=${d8(i)} label=${d8(o)} editable=true`:`role=${d8(i)} label=${d8(o)}`),o&&a.push(d?`label=${d8(o)} editable=true`:`label=${d8(o)}`),s&&a.push(d?`value=${d8(s)} editable=true`:`value=${d8(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${d8(l)} editable=true`:`text=${d8(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${d8(i)} editable=true`);let u=tX(a);return 0===u.length&&i&&u.push(d?`role=${d8(i)} editable=true`:`role=${d8(i)}`),0===u.length&&dX(e)&&u.push("visible=true"),u}function d8(e){return JSON.stringify(e)}function d5(e){if(!e)return null;let t=e.trim();return t||null}function d6(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=dB(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}async function d9(e){let{action:t,sessionName:r,logPath:a,sessionStore:i}=e;if(!(t1(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let n=i.get(r);if(!n)return null;let o=(function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),t1(e.command)){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&t.push(e.positionals.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=dq(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=d6(e.positionals??[]);r&&t.push(r)}return tX(t).filter(e=>e.trim().length>0)})(t).map(e=>dj(e)).filter(e=>null!==e);if(0===o.length)return null;let s=t1(t.command)||"fill"===t.command,l=t1(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await d7(n,t,a,s,i);for(let e of o){let r=d0(d.nodes,e,{platform:n.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!r)continue;let a=d4(r.node,n.device.platform,{action:t1(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(t1(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tK(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=dq(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",n=[e,a];return"text"===e&&i.length>0&&n.push(i),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=d6(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}return null}async function d7(e,t,r,a,i){let n=await sI(e.device,"snapshot",[],t.flags?.out,{...sk(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),o=n?.nodes??[],s={nodes:dD(t.flags?.snapshotRaw?o:dC(o)),truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend};return e.snapshot=s,i.set(e.name,e),s}let ue=["platform","target","device","udid","serial","verbose","out"];async function ut(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.positionals?.[0];if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};let l="",d=new Set;try{l=rr.expandHome(o,t.meta?.cwd);let e=s.readFileSync(l,"utf8"),u=e.trimStart()[0];if("{"===u||"["===u)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let c=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new $("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){let e=function(e){var t;let r=[],a={};for(let t of e){if("--relaunch"===t){a.relaunch=!0;continue}r.push(t)}let i=t7(r);return{positionals:i.positionals,flags:a,runtime:(t=i.flags).platform||t.metroHost||void 0!==t.metroPort||t.bundleUrl||t.launchUrl?i.flags:void 0}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n.runtime=e.runtime,n}if("runtime"===a){let e=t7(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(t1(a)){let e=t9(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return dI(r)&&dI(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){let e=t9(a,i);if(Object.assign(n.flags,e.flags),e.positionals.length<2)return n.positionals=e.positionals,n;let t=e.positionals[0];return t.startsWith("@")?(e.positionals.length>=3?(n.positionals=[t,e.positionals.slice(2).join(" ")],n.result={refLabel:e.positionals[1]}):n.positionals=[t,e.positionals[1]],n):(n.positionals=[t,e.positionals.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a||"type"===a){let e=t9(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}if("record"===a){let e=[];for(let t=0;t<i.length;t+=1){let r=i[t];if("--hide-touches"===r){n.flags.hideTouches=!0;continue}if("--fps"===r&&t+1<i.length){let e=Number(i[t+1]);Number.isFinite(e)&&(n.flags.fps=Math.floor(e)),t+=1;continue}e.push(r)}return n.positionals=e,n}if("screenshot"===a){let e=[];for(let t of i){if("--fullscreen"===t){n.flags.screenshotFullscreen=!0;continue}e.push(t)}return n.positionals=e,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(e),p=t.flags?.replayUpdate===!0,f=0;for(let e=0;e<c.length;e+=1){let o=c[e];if(!o||"replay"===o.command)continue;let s=await ur({req:t,sessionName:r,action:o,invoke:n});if(s.ok){ui(s).forEach(e=>d.add(e));continue}if(!p)return ua(s,o,e,l,[...d]);let u=await d9({action:o,sessionName:r,logPath:a,sessionStore:i});if(!u)return ua(s,o,e,l,[...d]);if(c[e]=u,!(s=await ur({req:t,sessionName:r,action:u,invoke:n})).ok)return ua(s,u,e,l,[...d]);ui(s).forEach(e=>d.add(e)),f+=1}return p&&f>0&&function(e,t,r){let a=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",i=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${i} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",t3(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command)return rt(t,e),t.join(" ");if("runtime"===e.command){for(let r of e.positionals??[])t.push(t4(r));return t5(t,e.flags),t.join(" ")}if("record"===e.command)return t6(t,e),t.join(" ");if("screenshot"===e.command){for(let r of e.positionals??[])t.push(t3(r));return e.flags?.screenshotFullscreen&&t.push("--fullscreen"),t.join(" ")}for(let r of e.positionals??[])t.push(t3(r));return t8(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
41
+ `,n=`${e}.tmp-${process.pid}-${Date.now()}`;s.writeFileSync(n,i),s.renameSync(n,e)}(l,c,i.get(r)),{ok:!0,data:{replayed:c.length,healed:f,session:r,artifactPaths:[...d]}}}catch(t){let e=P(t);return{ok:!1,error:{code:e.code,message:e.message,details:d.size>0?{artifactPaths:[...d]}:void 0}}}}async function ur(e){let{req:t,sessionName:r,action:a,invoke:i}=e;return await i({token:t.token,session:r,command:a.command,positionals:a.positionals??[],flags:function(e,t){let r={...t??{}},a=e??{};for(let e of ue)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}(t.flags,a.flags),runtime:a.runtime,meta:t.meta})}function ua(e,t,r,a,i=[]){let n;if(e.ok)return e;let o=r+1;return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${o} (${n=(t.positionals??[]).map(e=>t3(e)),[t.command,...n].join(" ")}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:{...e.error.details??{},replayPath:a,step:o,action:t.command,positionals:t.positionals??[],artifactPaths:i}}}}function ui(e){if(!e.ok||!e.data)return[];let t=[];if("string"==typeof e.data.path&&t.push(e.data.path),"string"==typeof e.data.outPath&&t.push(e.data.outPath),Array.isArray(e.data.artifacts))for(let r of e.data.artifacts){if(!r||"object"!=typeof r)continue;let e="string"==typeof r.localPath?r.localPath:void 0,a="string"==typeof r.path?r.path:void 0;e?t.push(e):a&&t.push(a)}return[...new Set(t.filter(e=>(function(e){try{return s.statSync(e).isFile()}catch{return!1}})(e)))]}async function un(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;return"replay"===t.command?await ut({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"test"===t.command?await d_({req:t,sessionName:r,runReplay:async({filePath:e,sessionName:r,platform:o,requestId:s,artifactPaths:l})=>await ut({req:{...t,command:"replay",session:r,positionals:[e],flags:void 0===o?t.flags:{...t.flags??{},platform:o},meta:s?{...t.meta??{},requestId:s}:t.meta},sessionName:r,logPath:a,sessionStore:i,invoke:async e=>{var t;return t=await n(e),l&&ui(t).forEach(e=>l.add(e)),t}}),cleanupSession:async e=>{i.get(e)&&await lG({req:{token:t.token,session:e,command:"close",positionals:[],flags:{},meta:t.meta},sessionName:e,logPath:a,sessionStore:i})}}):null}let uo=new Set(["session_list","ensure-simulator","devices","apps"]),us=new Set(["boot","appstate"]),ul=new Set(["perf","logs","network"]),ud=new Set(["replay","test"]);async function uu(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,command:n,positionals:o,recordPositionals:s,deriveNextSession:l}=e,d=i.get(r),u=t.flags??{},c=sW(n,d,u);if(c)return c;let p=await sX({session:d,flags:u,ensureReady:!0});if(!sx(n,p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${n} is not supported on this device`}};let f=await sI(p,n,o,t.flags?.out,{...sk(a,t.flags,d?.appBundleId,d?.trace?.outPath)});if(d){let e=l?await l(d,f,p):d;i.recordAction(e,{command:n,positionals:s??o,flags:t.flags??{},result:f??{}}),e!==d&&i.set(r,e)}return{ok:!0,data:f??{}}}async function uc(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=i.get(r),o=t.flags??{},s=sW("clipboard",n,o);if(s)return s;let l=(t.positionals?.[0]??"").toLowerCase();if("read"!==l&&"write"!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let d=await sX({session:n,flags:o,ensureReady:!0});if(!sx("clipboard",d))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let u=await sI(d,"clipboard",t.positionals??[],t.flags?.out,{...sk(a,t.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:u??{}}),{ok:!0,data:{platform:d.platform,...u??{}}}}async function up(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e;if(uo.has(t.command))return await l0({req:t,sessionName:r,sessionStore:i});if("runtime"===t.command)return await lA({req:t,sessionName:r,sessionStore:i});if(us.has(t.command))return await l8({req:t,sessionName:r,sessionStore:i});if("clipboard"===t.command)return await uc({req:t,sessionName:r,logPath:a,sessionStore:i});if("keyboard"===t.command){let e=i.get(r),n=t.positionals?.[0]?.trim().toLowerCase();return e||"dismiss"!==n||"ios"!==(t.flags??{}).platform?await uu({req:t,sessionName:r,logPath:a,sessionStore:i,command:"keyboard",positionals:t.positionals??[]}):{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"iOS keyboard dismiss requires an active session so the target app stays foregrounded. Run open first."}}}if(ul.has(t.command))return await dg({req:t,sessionName:r,sessionStore:i});if("install"===t.command||"reinstall"===t.command)return await lH({req:t,command:t.command,sessionName:r,sessionStore:i,deployOps:"install"===t.command?lq:lB});if("install_source"===t.command)return await sG({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===t.command)return await sB({req:t});if("push"===t.command){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();return n&&o?await uu({req:t,sessionName:r,logPath:a,sessionStore:i,command:"push",positionals:[n,"file"===(e=st(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>rr.expandHome(e,t)})).kind?e.path:e.text],recordPositionals:[n,o]}):{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}}}return"trigger-app-event"===t.command?await uu({req:t,sessionName:r,logPath:a,sessionStore:i,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await lk(e.device,r,e.appBundleId,lx)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}}):"open"===t.command?await l$({req:t,sessionName:r,logPath:a,sessionStore:i}):ud.has(t.command)?await un({req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}):"batch"===t.command?await lz(t,r,n):"close"===t.command?await lG({req:t,sessionName:r,logPath:a,sessionStore:i}):null}function uf(e,t){let r=B(e.type??"Element"),a=C(e,r),i=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,i,n,o].join("|")}function um(e,t){return t.flatten?e.map(e=>({text:eu(e,0,!1),comparable:uf(e,0)})):G(e).map(e=>({text:e.text,comparable:uf(e.node,e.depth)}))}function uh(e,t){return e.get(t)??0}async function uw(e){let t=await ug(e);return{snapshot:uy(t,e.flags?.snapshotRaw),analysis:t.analysis}}async function ug(e){var t,r,a,i;let n,{device:o,session:s,flags:l,outPath:d,logPath:u,snapshotScope:c}=e;return"macos"===o.platform&&s?.surface&&"app"!==s.surface?(t=await nX(s.surface,{bundleId:"menubar"===s.surface?s.appBundleId:void 0}),r={snapshotDepth:l?.snapshotDepth,snapshotInteractiveOnly:l?.snapshotInteractiveOnly,snapshotScope:c},n=t.nodes??[],r.snapshotScope&&(n=function(e,t){let r=dE(dD(e),t);if(!r)return[];let a=e.findIndex(e=>e.index===r.index);if(-1===a)return[];let i=e[a]?.depth??0,n=[];for(let t=a;t<e.length;t+=1){let r=e[t];if(!r)continue;let o=r.depth??0;if(t>a&&o<=i)break;n.push(r)}return uv(n,i)}(n,r.snapshotScope)),r.snapshotInteractiveOnly&&(n=function(e){if(0===e.length)return e;let t=new Map;for(let r of e)t.set(r.index,r);let r=new Set;for(let a of e){if(!function(e){if(e.hittable||e.rect)return!0;let t=`${e.type??""} ${e.role??""} ${e.subrole??""}`.toLowerCase();return t.includes("button")||t.includes("menu")||t.includes("textfield")||t.includes("searchfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")}(a))continue;let e=a;for(;e&&!r.has(e.index);)r.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===r.size?e:uv(e.filter(e=>r.has(e.index)))}(n)),"number"==typeof r.snapshotDepth&&(a=n,i=r.snapshotDepth,n=uv(a.filter(e=>(e.depth??0)<=i))),{...t,nodes:n}):await sI(o,"snapshot",[],d,{...sk(u,{...l,snapshotScope:c},s?.appBundleId,s?.trace?.outPath)})}function uy(e,t){let r=e?.nodes??[];return{nodes:dD(t?r:dC(r)),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend}}function uv(e,t=0){let r=new Map;for(let[t,a]of e.entries())r.set(a.index,t);return e.map((e,a)=>({...e,index:a,depth:Math.max(0,(e.depth??0)-t),parentIndex:"number"==typeof e.parentIndex?r.get(e.parentIndex):void 0}))}function uI(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref scope requires an existing snapshot in session."}}};let r=dx(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=dk(t.snapshot.nodes,r),i=a?dO(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function uA(e,t,r){let a=e.get(t),i=a?.device??await sv(r??{});return a||await sE(i),{session:a,device:i}}async function ub(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await tV(t.id)}}function uS(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function u_(e){let{session:t,sessionName:r,device:a,snapshot:i,appBundleId:n}=e;return t?{...t,snapshot:i}:{name:r,device:a,createdAt:Date.now(),appBundleId:n,snapshot:i,actions:[]}}function uN(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}async function uD(e){let{parsed:t,req:r,sessionName:a,logPath:i,sessionStore:n,session:o,device:s}=e;if("sleep"===t.kind)return await new Promise(e=>setTimeout(e,t.durationMs)),uS(n,o,r,{waitedMs:t.durationMs}),{ok:!0,data:{waitedMs:t.durationMs}};if(!sx("wait",s))return lj("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===t.kind)return await ux({device:s,logPath:i,parsed:t,req:r,session:o,sessionName:a,sessionStore:n});let l=function(e,t){if("ref"===e.kind){if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}}};let r=dx(e.rawRef);if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${e.rawRef}`}}};let a=dk(t.snapshot.nodes,r),i=a?dO(a,t.snapshot.nodes):void 0;return i?{ok:!0,text:i,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e.rawRef} not found or has no label`}}}}return e.text?{ok:!0,text:e.text,timeoutMs:e.timeoutMs}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}}}}(t,o);return l.ok?await uk({device:s,logPath:i,req:r,session:o,sessionStore:n,text:l.text,timeoutMs:l.timeoutMs}):l.response}async function ux(e){let{device:t,logPath:r,parsed:a,req:i,session:n,sessionName:o,sessionStore:s}=e,l=a.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let e=d1((await uM({device:t,logPath:r,req:i,session:n,sessionName:o,sessionStore:s})).nodes,a.selector,{platform:t.platform});if(e)return uE(s,n,i,{selector:e.selector.raw,waitedMs:Date.now()-d});await new Promise(e=>setTimeout(e,300))}return lj("COMMAND_FAILED",`wait timed out for selector: ${a.selectorExpression}`)}async function uk(e){let{device:t,logPath:r,req:a,session:i,sessionStore:n,text:o,timeoutMs:s}=e,l=s??1e4,d=Date.now();for(;Date.now()-d<l;){if("macos"===t.platform&&i?.surface&&"app"!==i.surface){if(dE((await uM({device:t,logPath:r,req:a,session:i,sessionName:i?.name??a.session??"default",sessionStore:n})).nodes,o))return uE(n,i,a,{text:o,waitedMs:Date.now()-d})}else if(ts(t.platform)){let e=await tz(t,{command:"findText",text:o,appBundleId:i?.appBundleId},{verbose:a.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:a.meta?.requestId});if(e?.found)return uS(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}}}else if("android"===t.platform&&dE(dD((await iN(t,{scope:o})).nodes??[]),o))return uS(n,i,a,{text:o,waitedMs:Date.now()-d}),{ok:!0,data:{text:o,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return lj("COMMAND_FAILED",`wait timed out for text: ${o}`)}async function uM(e){let{device:t,logPath:r,req:a,session:i,sessionName:n,sessionStore:o}=e,{snapshot:s}=await uw({device:t,session:i,flags:{...a.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:a.flags?.out,logPath:r});return i&&(i.snapshot=s,o.set(n,i)),s}function uE(e,t,r,a){return uS(e,t,r,a),{ok:!0,data:a}}async function uO(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!sx("alert",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is not supported on this device"}};if("macos"===n.platform){let e=async()=>await nK("wait"===o?"get":o,s);if("wait"===o){let r=uN(t.positionals?.[1])??1e4,n=Date.now();for(;Date.now()-n<r;){try{let r=await e();return uS(a,i,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===o||"dismiss"===o?o:"get";if("accept"===r||"dismiss"===r){let e,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await nK(r,s);return uS(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let n=await nK("get",s);return uS(a,i,t,n),{ok:!0,data:n}}if("wait"===o){let e=uN(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await tz(n,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return uS(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:r,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await tz(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return uS(a,i,t,e),{ok:!0,data:e}}catch(r){e=r;let t=String(r?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw e}let u=await tz(n,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return uS(a,i,t,u),{ok:!0,data:u}}async function uL(e){let{req:t,logPath:r,sessionStore:a,session:i,device:n,parsed:o}=e,{setting:s,state:l,permissionTarget:d}=o;if(!sx("settings",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}};if("macos"===n.platform&&!_(s))return{ok:!1,error:{code:"INVALID_ARGS",message:U(s)}};let u=i?.appBundleId,c="permission"===s?[s,l,d??"",t.positionals?.[3]??"",u??""]:[s,l,u??""],p=await sI(n,"settings",c,t.flags?.out,{...sk(r,t.flags,u,i?.trace?.outPath)});return uS(a,i,t,p??{setting:s,state:l}),{ok:!0,data:p??{setting:s,state:l}}}let uC=new Set(["snapshot","diff","wait","alert","settings"]);async function uP(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=t.command;if(!uC.has(n))return null;if("snapshot"===n){let{session:e,device:n}=await uA(i,r,t.flags);if(!sx("snapshot",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let o=uI(t.flags?.snapshotScope,e);return o.ok?await ub(e,n,async()=>{let s=await uw({device:n,session:e,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:o.scope}),l=uR({capture:s,flags:t.flags,session:e}),d=u_({session:e,sessionName:r,device:n,snapshot:s.snapshot,appBundleId:e?.appBundleId});return uS(i,d,t,{nodes:s.snapshot.nodes.length,truncated:s.snapshot.truncated??!1}),i.set(r,d),{ok:!0,data:{nodes:s.snapshot.nodes,truncated:s.snapshot.truncated??!1,...l.length>0?{warnings:l}:{},appName:d.appBundleId?d.appName??d.appBundleId:void 0,appBundleId:d.appBundleId}}}):o.response}if("diff"===n)return t.positionals?.[0]!=="snapshot"?{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}}:await u$({req:t,sessionName:r,logPath:a,sessionStore:i});if("wait"===n){let{session:e,device:n}=await uA(i,r,t.flags),o=function(e){if(0===e.length)return null;let t=uN(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=uN(e[e.length-1]);return{kind:"text",text:(null!==t?e.slice(1,-1).join(" "):e.slice(1).join(" ")).trim(),timeoutMs:t}}if(e[0].startsWith("@")){let t=uN(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=uN(e[e.length-1]),a=dB(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=dj(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);if(!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}};let s=()=>uD({parsed:o,req:t,sessionName:r,logPath:a,sessionStore:i,session:e,device:n});return"sleep"===o.kind?await s():await ub(e,n,s)}if("alert"===n){let{session:e,device:n}=await uA(i,r,t.flags);return await ub(e,n,async()=>await uO({req:t,logPath:a,sessionStore:i,session:e,device:n}))}if("settings"===n){let e,n,o,s=(e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&n&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:n,permissionTarget:o}}:{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:M}}});if(!s.ok)return s.response;let{session:l,device:d}=await uA(i,r,t.flags);return await ub(l,d,async()=>await uL({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}function uR(e){var t,r,a;let{capture:i,flags:n,session:o}=e,s=[],l=i.analysis,d=n?.snapshotInteractiveOnly===!0;"android"===i.snapshot.backend&&d&&0===i.snapshot.nodes.length&&l&&l.rawNodeCount>=12&&(s.push(`Interactive snapshot is empty after filtering ${l.rawNodeCount} raw Android nodes. Likely causes: depth too low, transient route change, or collector filtering.`),"number"==typeof n?.snapshotDepth&&l.maxDepth>=n.snapshotDepth+2&&s.push(`Interactive output is empty at depth ${n.snapshotDepth}; retry without -d.`));let u=o?.snapshot;u&&Date.now()-u.createdAt<=2e3&&(t=u.nodes.length,r=i.snapshot.nodes.length,!(t<12)&&r<=Math.floor(.2*t))&&s.push("Recent snapshots dropped sharply in node count, which suggests stale or mid-transition UI. Use screenshot as visual truth, wait briefly, then re-snapshot once.");let c=o?.actions.at(-1);return"android"===i.snapshot.backend&&d&&u&&c&&Date.now()-c.ts<=2e3&&function(e,t){let r=Math.max(e.length,t.length);if(r<12)return!1;let a=Math.min(e.length,t.length),i=0;for(let r=0;r<a;r+=1)uT(e[r])===uT(t[r])&&(i+=1);let n=Math.max(0,t.length-e.length),o=Math.max(0,e.length-t.length),s=Math.max(3,Math.floor(.15*r));return i>=Math.floor(.9*r)&&n<=s&&o<=s}(u.nodes,i.snapshot.nodes)&&("press"===(a=c.command)||"click"===a||"back"===a||"open"===a)&&s.push(`Recent ${c.command} was followed by a nearly identical snapshot. If you expected navigation or submit, the tree may still be stale. Use screenshot as visual truth, wait briefly, then re-snapshot once.`),tX(s)}function uT(e){return[e.depth??0,e.type??"",e.role??"",e.label??"",e.value??"",e.identifier??"",!1===e.enabled?"disabled":"enabled",!0===e.selected?"selected":"unselected",!0===e.hittable?"hittable":"not-hittable"].join("|")}async function u$(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,{session:n,device:o}=await uA(i,r,t.flags);if(!sx("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=uI(t.flags?.snapshotScope,n);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await ub(n,o,async()=>{let e=await uw({device:o,session:n,flags:t.flags,outPath:t.flags?.out,logPath:a,snapshotScope:s.scope}),d=e.snapshot,u=uR({capture:e,flags:t.flags,session:n});if(!n?.snapshot){let e=function(e,t={}){return um(e,t).length}(d.nodes,{flatten:l}),a=u_({session:n,sessionName:r,device:o,snapshot:d,appBundleId:n?.appBundleId});return uS(i,a,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e}}),i.set(r,a),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:e},lines:[],...u.length>0?{warnings:u}:{}}}}let c=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,i=r+a,n=new Map,o=[];n.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(n));for(let i=-s;i<=s;i+=2){let l=i===-s||i!==s&&uh(n,i-1)<uh(n,i+1)?uh(n,i+1):uh(n,i-1)+1,d=l-i;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(i,l),l>=r&&d>=a)return function(e,t,r,a,i){let n=[],o=a,s=i;for(let a=e.length-1;a>=0;a-=1){let i=e[a],l=o-s,d=l===-a||l!==a&&uh(i,l-1)<uh(i,l+1)?l+1:l-1,u=uh(i,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,a)}}return[]}(um(e,r),um(t,r)),i={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(i.additions+=1),"removed"===e.kind&&(i.removals+=1),"unchanged"===e.kind&&(i.unchanged+=1);return{summary:i,lines:a}}(n.snapshot.nodes,d.nodes,{flatten:l}),p={...n,snapshot:d};return uS(i,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),i.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines,...u.length>0?{warnings:u}:{}}}})}function uF(e,t,r,a={}){let i=uV(r);if(!i)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return uU(e.label,r);case"value":return uU(e.value,r);case"id":return uU(e.identifier,r);default:return Math.max(uU(e.label,r),uU(e.value,r),uU(e.identifier,r))}}(r,t,i);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function uU(e,t){let r=uV(e??"");return r?r===t?2:+!!r.includes(t):0}function uV(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function uG(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=dx(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=dk(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=dE(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function uj(e){let t=uB(e);if(!t)return null;let r=dM(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function uB(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}async function uq(e){let{session:t,refInput:r,fallbackLabel:a,promoteToHittableAncestor:i,invalidRefMessage:n,missingBoundsMessage:o,invalidBoundsMessage:s,reqFlags:l,sessionStore:d,contextFromFlags:u,captureSnapshotForSession:c,resolveRefTarget:p}=e,f=p({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:n,notFoundMessage:o});if(!f.ok)return{ok:!1,response:f.response};let{ref:m}=f.target,h=i?uH(f.target.snapshotNodes,f.target.node):f.target.node,w=f.target.snapshotNodes,g=uj(h.rect);if(!g){let e=await c(t,l,d,u,{interactiveOnly:!0}),r=dk(e.nodes,m),n=a.length>0?dE(e.nodes,a):null,o=r&&i?uH(e.nodes,r):r,s=n&&i?uH(e.nodes,n):n,p=uj(s?.rect),f=uj(o?.rect)?o:p?s:o??s,y=uj(f?.rect);f&&y&&(h=f,w=e.nodes,g=y)}return g?{ok:!0,target:{ref:m,node:h,snapshotNodes:w,point:g}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:s}}}}function uH(e,t){let r=function(e,t){let r=uB(t.rect);if(!r)return null;let a=t,i=new Set;for(;!i.has(a.ref);){i.add(a.ref);let t=e.filter(e=>{var t,i;if(e.parentIndex!==a.index||!e.hittable)return!1;let n=uB(e.rect);return!!n&&(t=n,i=r,.5>=Math.abs(t.x-i.x)&&.5>=Math.abs(t.y-i.y)&&.5>=Math.abs(t.width-i.width)&&.5>=Math.abs(t.height-i.height))});if(1!==t.length)break;a=t[0]}return a===t?null:a}(e,t);if(r?.rect&&uj(r.rect))return r;let a=dT(e,t);return a?.rect&&uj(a.rect)?a:t}async function uW(e){let{device:t,node:r,flags:a,appBundleId:i,traceOutPath:n,surface:o,contextFromFlags:s}=e,l=F(r),d=uj(r.rect);if(!d)return l;try{let e=await sI(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,n),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return Q({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:o,platform:t.platform}}),l}catch(e){return Q({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}async function uz(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=t.command;if("find"!==o)return null;let s=t.positionals??[];if(0===s.length)return lj("INVALID_ARGS","find requires a locator or text");let{locator:l,query:d,action:u,value:c,timeoutMs:p}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let a=e[r]??"",i=e.slice(r+1);if(0===i.length)return{locator:t,query:a,action:"click"};let n=i[0].toLowerCase();if("get"===n){let e=i[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new $("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:uN(i[1])??void 0};if("exists"===n)return{locator:t,query:a,action:"exists"};if("click"===n)return{locator:t,query:a,action:"click"};if("focus"===n)return{locator:t,query:a,action:"focus"};if("fill"===n)return{locator:t,query:a,action:"fill",value:i.slice(1).join(" ")};if("type"===n)return{locator:t,query:a,action:"type",value:i.slice(1).join(" ")};throw new $("INVALID_ARGS",`Unsupported find action: ${i[0]}`)}(s);if(!d)return lj("INVALID_ARGS","find requires a value");let f=i.get(r);if(!f&&"exists"!==u&&"wait"!==u&&"get_text"!==u&&"get_attrs"!==u)return lj("SESSION_NOT_FOUND","No active session. Run open first.");let m=f?.device??await sv(t.flags??{});f||await sE(m);let h="role"!==l?d:void 0,w="click"===u||"focus"===u||"fill"===u||"type"===u,g=0,y=null,v=async()=>{let e=Date.now();if(y&&e-g<750)return{nodes:y};let{snapshot:n}=await uw({device:m,session:f,flags:{...t.flags,snapshotInteractiveOnly:w,snapshotCompact:w},outPath:t.flags?.out,logPath:a,snapshotScope:h}),o=n.nodes;return g=e,y=o,f&&(f.snapshot=n,i.set(r,f)),{nodes:o,truncated:n.truncated,backend:n.backend}},I={req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,session:f,device:m,command:o,locator:l,query:d};if("wait"===u)return uJ(I,v,l,d,p);let{nodes:A}=await v(),b=uF(A,l,d,{requireRect:w});if(w&&b.matches.length>1){var S,_,N;let e;return S=b.matches,_=l,N=d,e=S.slice(0,8).map(e=>{let t=d$(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`}),{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.length} elements for ${_} "${N}". Use a more specific locator or selector.`,details:{locator:_,query:N,matches:S.length,candidates:e}}}}let D=b.matches[0]??null;if(!D)return lj("COMMAND_FAILED","find did not match any element");let x="click"===u||"focus"===u||"fill"===u||"type"===u?dT(A,D)??D:D,k=`@${x.ref}`,M={node:D,resolvedNode:x,ref:k,nodes:A,actionFlags:{...t.flags??{},noRecord:!0}},E={exists:()=>uK(I),get_text:()=>uX(I,M),get_attrs:()=>uY(I,M),click:()=>uZ(I,M),fill:()=>uQ(I,M,c),focus:()=>u0(I,M),type:()=>u1(I,M,c)}[u];return E?E():null}async function uJ(e,t,r,a,i){let{req:n,sessionStore:o,session:s,command:l}=e,d=i??1e4,u=Date.now();for(;Date.now()-u<d;){let{nodes:e}=await t();if(uF(e,r,a,{requireRect:!1}).matches[0])return s&&o.recordAction(s,{command:l,positionals:n.positionals??[],flags:n.flags??{},result:{found:!0,waitedMs:Date.now()-u}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-u}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}async function uK(e){let{req:t,sessionStore:r,session:a,command:i}=e;return a&&r.recordAction(a,{command:i,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}}}async function uX(e,t){let{req:r,sessionStore:a,session:i,command:n,device:o,logPath:s}=e,l=await uW({device:o,node:t.node,flags:r.flags,appBundleId:i?.appBundleId,traceOutPath:i?.trace?.outPath,surface:i?.surface,contextFromFlags:(e,t,r)=>sk(s,e,t,r)});return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get text",text:l}}),{ok:!0,data:{ref:t.ref,text:l,node:t.node}}}async function uY(e,t){let{req:r,sessionStore:a,session:i,command:n}=e;return i&&a.recordAction(i,{command:n,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"get attrs"}}),{ok:!0,data:{ref:t.ref,node:t.node}}}async function uZ(e,t){let{req:r,sessionName:a,sessionStore:i,session:n,invoke:o,command:s,locator:l,query:d}=e,u=await o({token:r.token,session:a,command:"click",positionals:[t.ref],flags:t.actionFlags});if(!u.ok)return u;let c=t.resolvedNode.rect?dM(t.resolvedNode.rect):null,p={ref:t.ref,locator:l,query:d};return c&&(p.x=c.x,p.y=c.y),n&&i.recordAction(n,{command:s,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"click",locator:l,query:d}}),{ok:!0,data:p}}async function uQ(e,t,r){let{req:a,sessionName:i,sessionStore:n,session:o,invoke:s,command:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let d=await s({token:a.token,session:i,command:"fill",positionals:[t.ref,r],flags:t.actionFlags});return d.ok&&o&&n.recordAction(o,{command:l,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"fill"}}),d}async function u0(e,t){let{req:r,sessionStore:a,session:i,device:n,command:o,logPath:s}=e,l=t.node.rect?dM(t.node.rect):null;if(!l)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let d=await sI(n,"focus",[String(l.x),String(l.y)],r.flags?.out,{...sk(s,r.flags,i?.appBundleId,i?.trace?.outPath)});return i&&a.recordAction(i,{command:o,positionals:r.positionals??[],flags:r.flags??{},result:{ref:t.ref,action:"focus"}}),{ok:!0,data:d??{ref:t.ref}}}async function u1(e,t,r){let{req:a,sessionStore:i,session:n,device:o,command:s,logPath:l}=e;if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let d=t.node.rect?dM(t.node.rect):null;if(!d)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await sI(o,"focus",[String(d.x),String(d.y)],a.flags?.out,{...sk(l,a.flags,n?.appBundleId,n?.trace?.outPath)});let u=await sI(o,"type",[r],a.flags?.out,{...sk(l,a.flags,n?.appBundleId,n?.trace?.outPath)});return n&&i.recordAction(n,{command:s,positionals:a.positionals??[],flags:a.flags??{},result:{ref:t.ref,action:"type"}}),{ok:!0,data:u??{ref:t.ref}}}let u2=`
40
42
  import Foundation
41
43
  import AVFoundation
42
44
 
@@ -60,11 +62,11 @@ Task {
60
62
 
61
63
  semaphore.wait()
62
64
  exit(exitCode)
63
- `.trim();async function uj(e,t={}){let r,a=t.pollMs??150,i=t.attempts??12,n=0;for(let t=0;t<i;t+=1){let t=0;try{t=s.statSync(e).size}catch{t=0}if(t>0&&t===r){if((n+=1)>=2)return}else n=0;r=t,await new Promise(e=>setTimeout(e,a))}}async function uB(e){try{var t,r;let a,i=await O("swift",["-",e],{stdin:uG,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
64
- ${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return uH(e);return!1}catch(t){if(t instanceof $&&"TOOL_MISSING"===t.code)return uH(e);throw t}}async function uq(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await uB(e))return;await new Promise(e=>setTimeout(e,r))}}function uH(e){try{let t=s.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=s.openSync(e,"r");try{let e=s.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{s.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function uW(e){let t=c.parse(e);return c.join(t.dir,`${t.name}.gesture-telemetry.json`)}function uz(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function uJ(e){var t,r,a;let i,n,{recording:o,trimStartMs:l}=e,d=(i=uW((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),n={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?uz(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):uz(r))},s.writeFileSync(i,JSON.stringify(n,null,2)),i);return o.telemetryPath=d,d}function uK(e){let t=c.dirname(m(import.meta.url)),r=[m(new URL(`./${e}`,import.meta.url)),c.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(s.existsSync(e))return e;throw new $("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}function uX(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}async function uY(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:i}=e;await uj(t),await uq(t);let n=s.mkdtempSync(c.join(u.tmpdir(),"agent-device-record-overlay-")),o=c.join(n,`input${c.extname(t)||".mp4"}`),l=c.join(n,c.basename(t)),d=c.join(n,"home"),f=c.join(n,"module-cache");s.copyFileSync(t,o),s.mkdirSync(d,{recursive:!0}),s.mkdirSync(f,{recursive:!0});try{await O("xcrun",["swift",r,"--input",o,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:f}}),await uq(l),s.copyFileSync(l,t)}catch(a){let e=a instanceof $?a:new $("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new $("COMMAND_FAILED",i,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{s.rmSync(n,{recursive:!0,force:!0})}}async function uZ(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await uY({videoPath:t,scriptPath:a??=uK("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function uQ(e){let{videoPath:t,telemetryPath:a,targetLabel:i="recording"}=e;await uY({videoPath:t,scriptPath:r??=uK("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function u0(e){return e instanceof Error?e.message:String(e)}function u1(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function u2(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function u3(e,t,r){for(let a=0;a<40;a+=1){if(!await u2(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await u2(e,t,r)}async function u4(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function u8(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await u2(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function u5(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{s.rmSync(n,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",i,n],{allowFailure:!0});if(0!==o.exitCode)t=u1(o,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(Q({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:(()=>{try{return s.statSync(n).size}catch{return 0}})(),playable:t}}),t)return;Q({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function u6(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function u9(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return Q({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await u2(e,t,r))&&await u3(e,t,r)}async function u7(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${u1(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await u6(a,i.id,e);continue}if(Q({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await u8(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await u9(a,i.id,r),await u6(a,i.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function ce(e){let t,r,{deps:a,device:i,recording:n}=e;Q({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(Q({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await u2(a,i.id,n.remotePid)&&!await u9(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${u1(o,"adb shell kill")}`):await u3(a,i.id,n.remotePid)||await u9(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await u4(a,i.id,n.remotePath);let e=await u5({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(uJ({recording:n}),n.showTouches&&n.telemetryPath){let e=uX();if(e)n.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:n.outPath,telemetryPath:n.telemetryPath,targetLabel:"Android recording"})}catch(e){n.overlayWarning=`failed to overlay recording touches: ${u0(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});Q({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${u1(e,"adb shell rm")}`)}}function ct(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function cr(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function ca(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=ct(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},cr(t,i,r))}catch(e){Q({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:u0(e)}})}}async function ci(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,f=`agent-device-recording-${Date.now()}.mp4`,p=`tmp/${f}`,m=cr(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:f,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!u0(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${u0(a)}`}};Q({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:u0(a)}});let e=(w=o.id,g=i.name,n.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${u0(e)}`}}}}return{platform:"ios-device-runner",remotePath:p,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function cn(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},cr(t,i,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${u0(e)}`}}}return{platform:"macos-runner",...s}}async function co(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=ct(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},cr(t,i,r))}catch(e){Q({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:u0(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of ty)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=uJ({recording:o,trimStartMs:d});if(o.showTouches){let e=uX();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${u0(e)}`}}return null}async function cs(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=ct(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},cr(t,i,r))}catch(e){Q({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:u0(e)}})}let l=uJ({recording:o});if(o.showTouches){let e=uX();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${u0(e)}`}}return null}async function cl(e){for(let t=0;t<2;t+=1){try{if(s.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function cd(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await ca({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",eK(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),f=await cl(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:ct(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:f,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function cu(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:n,device:o,logPath:l,deps:d}=e;if(n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!sI("record",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let f=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,p=rr.expandHome(f,r.meta?.cwd),m={outPath:p,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(s.mkdirSync(c.dirname(p),{recursive:!0}),s.rmSync(p,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=ct(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await ci({req:r,activeSession:n,sessionStore:i,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else if("macos"===o.platform){let e=ct(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await cn({req:r,activeSession:n,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else t="ios"===o.platform?await cd({req:r,activeSession:n,device:o,logPath:l,deps:d,recordingBase:m,resolvedOut:p}):await u7({deps:d,device:o,recordingBase:m});return"ok"in t?t:(n.recording=t,i.set(a,n),i.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??f,showTouches:t.showTouches}})}async function cc(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await ce({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${u1(i,"simctl recordVideo")}`}};let n=uJ({recording:a});if(a.showTouches){let e=uX();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:n,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${u0(e)}`}}return null}async function cf(e){var t;let r,{req:a,activeSession:i,device:n,logPath:o,deps:s}=e;if(!i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let l=i.recording,d=l.invalidatedReason;i.recording=void 0;let u="ios-device-runner"===l.platform?await co({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await cs({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:l}):await cc({deps:s,device:n,recording:l});return u||(d?{ok:!1,error:{code:"COMMAND_FAILED",message:d}}:(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:c.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return uW(e.clientOutPath)}(t),fileName:c.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function cp(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:O,runCmdBackground:M,runIosRunnerCommand:tz,waitForStableFile:uj,isPlayableVideo:uB,trimRecordingStart:uZ,overlayRecordingTouches:uQ},o=a.get(r),s=o?.device??await sf(t.flags??{});o||await sS(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};if("start"===d)return cu({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await cf({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function cm(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n=t.command;if("record"===n)return cp({req:t,sessionName:r,sessionStore:a,logPath:i});if("trace"===n){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return lR("INVALID_ARGS","trace requires start|stop");let i=a.get(r);if(!i)return lR("SESSION_NOT_FOUND","No active session");if("start"===e){if(i.trace)return lR("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(i),r=rr.expandHome(e);return s.mkdirSync(c.dirname(r),{recursive:!0}),s.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return lR("INVALID_ARGS","no active trace");let o=i.trace.outPath;if(t.positionals?.[1]){let e=rr.expandHome(t.positionals[1]);s.mkdirSync(c.dirname(e),{recursive:!0}),s.existsSync(o)?s.renameSync(o,e):s.appendFileSync(e,""),o=e}return i.trace=void 0,a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function ch(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let cw=new WeakMap;function cg(e){if(!e)return;let t=cw.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&cv(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(cv);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return cw.set(e,r),r}function cv(e){return!!e&&e.width>0&&e.height>0}let cy={referenceWidth:1e3,referenceHeight:1e3};function cI(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,f=e.recording;if(!f)return;let p={...i,...a??{}},m=c_(p.effectiveDurationMs)??c_(p.durationMs),h={recordingStartedAt:f.startedAt,gestureClockOriginAtMs:f.gestureClockOriginAtMs,gestureClockOriginUptimeMs:f.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===f.platform?f.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:c_(p.gestureStartUptimeMs),gestureEndUptimeMs:c_(p.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:c_(p.gestureStartUptimeMs),gestureEndUptimeMs:c_(p.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===c_(p.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=cN(c_(t.count),1)??1,r=!0===t.doubleTap,a=cN(c_(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,p)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return ch(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):ch(h),v=(l=e.snapshot,u=c_((d=p).referenceWidth),c=c_(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:cg(l)),y=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=cD(t,e);if(!i)return[];let{x:n,y:o}=i,s=cN(c_(t.count),1)??1,l=cN(c_(t.intervalMs),0)??0,d=!0===t.doubleTap,u=cN(c_(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(cb(t,n,o,u,a));continue}c.push(cA(t,n,o,a)),d&&c.push(cA(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=cD(t,e);if(!i)return[];let{x:n,y:o}=i;return[cA(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=cD(t,e);if(!n)return[];let{x:o,y:s}=n;return[cb(r,o,s,cM(a,[c_(t.durationMs),c_(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=cx(t,e),o=cS(t.contentDirection)??cS(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=cM(a,[],250),f=c_(t.amount)??c_(e[1]),p=c_(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==f?{amount:f}:{},...void 0!==p?{pixels:p}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=cx(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=cM(a,[c_(t.effectiveDurationMs),c_(t.durationMs),c_(e[4])],250),c=cN(c_(t.count),1)??1,f=cN(c_(t.pauseMs),0)??0,p="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===p&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+f);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=cD(t,e,1),o=c_(t.scale)??c_(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:cM(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,p,g,w,v);0!==y.length&&(f.gestureEvents.push(...y),Q({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:y.length,tMs:g,gestureDurationMs:w,kinds:y.map(e=>e.kind)}}))}function cA(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function cb(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function cS(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function c_(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function cN(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function cD(e,t,r=0){let a=c_(e.x)??c_(t[r]),i=c_(e.y)??c_(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function cx(e,t){let r=c_(e.x1)??c_(t[0]),a=c_(e.y1)??c_(t[1]),i=c_(e.x2)??c_(t[2]),n=c_(e.y2)??c_(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function cM(e,t,r){return cN(e,1)??t.map(e=>cN(e,1)).find(e=>void 0!==e)??r}function cE(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=s,a=l,i="string"==typeof t?.ref?t.ref:void 0,n="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:i?n&&"primary"!==n?`Clicked ${n} @${i} (${r}, ${a})`:`Tapped @${i} (${r}, ${a})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...d??{},...u??{},...o??{},...Y(c)}}async function ck(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,buildPayloads:u}=e,c=await cO({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d}),{result:f,responseData:p=f}=await u(c.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),cI(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:f,responseData:p,actionStartedAt:c.actionStartedAt,actionFinishedAt:c.actionFinishedAt})}async function cO(e){let{session:t,flags:r,contextFromFlags:a,command:i,positionals:n,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await sp(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function cL(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await i$(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=cg(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=cg(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function cC(e){try{return await cL(e)}catch(t){Q({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function cP(e){return cg({nodes:e,createdAt:0})}function cR(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`}}}async function cT(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return lR("SESSION_NOT_FOUND","No active session. Run open first.");let c=cR(l,u);if(c)return c;if(!sI("press",l.device))return lR("UNSUPPORTED_OPERATION","press is not supported on this device");let f=oY(t.flags),p="primary"===f?{}:{button:f};if("primary"!==f){let e=oZ({commandLabel:u,platform:l.device.platform,button:f,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return lR(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return ck({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,buildPayloads:async e=>{let r=await cC({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=cE({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:p});return{result:o,responseData:o}}});let h="click",w=t.positionals?.[0]??"";if(w.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await uE({session:l,refInput:w,fallbackLabel:r,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${w} not found or has no bounds`,invalidBoundsMessage:`Ref ${w} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!c.ok)return c.response;let{ref:f,node:m,snapshotNodes:g,point:v}=c.target,y=dy(m,g),I=dW(m,l.device.platform,{action:h}),{x:A,y:b}=v;return ck({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(A),String(b)],outPath:t.flags?.out,buildPayloads:e=>{let t=cE({data:e,fallbackX:A,fallbackY:b,referenceFrame:cP(g),extra:{ref:f,refLabel:y,selectorChain:I,...p}});return{result:t,responseData:t}}})}let g=(t.positionals??[]).join(" ").trim();if(!g)return{ok:!1,error:{code:"INVALID_ARGS",message:`${u} requires @ref, selector expression, or x y coordinates`}};let v=dE(g),y=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await X("selector_resolve",()=>dj(y.nodes,v,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:dq(v,I?.diagnostics??[],{unique:!0})}};let A=uk(y.nodes,I.node),b=ux(A.rect);if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${I.selector.raw} resolved to invalid bounds`}};let{x:S,y:_}=b,N=dW(A,l.device.platform,{action:h}),D=dy(A,y.nodes);return ck({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,buildPayloads:e=>{let t=cE({data:e,fallbackX:S,fallbackY:_,referenceFrame:cP(y.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:D,...p}});return{result:t,responseData:t}}})}async function c$(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=cR(l,"fill");if(e)return e}if(l&&!sI("fill",l.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let u=await uE({session:l,refInput:t.positionals[0],fallbackLabel:r,promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u.response;let{ref:c,node:f,snapshotNodes:p,point:m}=u.target,h=f.type??"",w=h&&!dS(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=dy(f,p),v=dW(f,l.device.platform,{action:"fill"}),{x:y,y:I}=m;return ck({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(y),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=cE({data:e,fallbackX:y,fallbackY:I,referenceFrame:cP(p),extra:{ref:c,refLabel:g,selectorChain:v,text:d}}),r={...e??{ref:c,x:y,y:I}};return w&&(t.warning=w,r.warning=w),{result:t,responseData:r}}})}if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=dO(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let e=d.rest.join(" ").trim();if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=dE(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await X("selector_resolve",()=>dj(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:dq(r,s?.diagnostics??[],{unique:!0})}};let u=s.node,c=s.node.rect,f=u.type??"",p=f&&!dS(f,l.device.platform)?`fill target ${s.selector.raw} resolved to "${f}", attempting fill anyway.`:void 0,{x:m,y:h}=dg(c),w=dW(u,l.device.platform,{action:"fill"});return ck({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=cE({data:t,fallbackX:m,fallbackY:h,referenceFrame:cP(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:dy(u,o.nodes)}});return p&&(r.warning=p),{result:r,responseData:r}}})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}async function cF(e){switch(e.req.command){case"press":case"click":return await cT(e);case"fill":return await c$(e);default:return null}}let cU=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function cV(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of cU)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}async function cG(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await ui({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function cj(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=dE(r),f=await cG(a,i,n,o,{interactiveOnly:s}),p=await X("selector_resolve",()=>dj(f.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return p&&(!l||p.node.rect)?{ok:!0,chain:c,snapshot:f,resolved:p}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:dq(c,p?.diagnostics??[],{unique:d})}}}}async function cB(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sI("get",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=cV("get",t.flags);if(e)return e;let r=uD({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r.response;let{ref:l,node:d}=r.target,u=dW(d,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await uO({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:cq(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let d=await cj({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===n});if(!d.ok)return d.response;let{resolved:u}=d,c=u.node,f=dW(c,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let p=await uO({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:p,refLabel:cq(p),selector:u.selector.raw,selectorChain:f}}),{ok:!0,data:{selector:u.selector.raw,text:p,node:c}}}function cq(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function cH(e,t){let r=dg(t),a=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=a.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=cK(i.map(e=>e.rect).filter(e=>cJ(e,r.x,r.y)));if(n)return n;let o=cK(i.map(e=>e.rect));if(o)return o;let s=cK(a.map(e=>e.rect).filter(e=>cJ(e,r.x,r.y)));return s||null}function cW(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=s-.25*i,c=Math.max(8,.1*n),f=e.y+e.height/2,p=e.x+e.width/2;if(f>=o+.25*i&&f<=u)return null;let m=Math.round((r=p,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*i),w=Math.round(o+.14*i);return f>u?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}function cz(e,t){let r=Math.max(1,t.height),a=t.y,i=t.y+r,n=a+.25*r,o=i-.25*r,s=e.y+e.height/2;return s<n?Math.ceil(n-s):s>o?Math.ceil(s-o):0}function cJ(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function cK(e){let t=null,r=-1;for(let a of e){let e=a.width*a.height;e>r&&(t=a,r=e)}return t}function cX(e,t){var r,a;let i=cH(t,e);return!i||(r=e,a=i,r.x<a.x+a.width&&r.x+r.width>a.x&&r.y<a.y+a.height&&r.y+r.height>a.y)}function cY(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function cZ(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(n))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sI("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:s}=dL(t.positionals);if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let l=s.rest.join(" ").trim();if("text"===n&&!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==n&&s.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${n} does not accept trailing values`}};let d=dE(s.selectorExpression);if("exists"===n){let e=dB((await cG(o,t.flags,a,i,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:n,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:dq(d,[],{unique:!1})}}}let u=await cj({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u.response;let{resolved:c}=u,f=function(e){let{predicate:t,node:r,nodes:a,expectedText:i,platform:n}=e,o=dN(r),s=dU(r,n),l=!0===r.selected,d="text"===t?dF(r):function(e,t){if(!0===e.hittable)return!0;if(cY(e.rect))return cX(e.rect,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,i=new Set;for(;"number"==typeof a.parentIndex&&!i.has(a.index);){i.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=db(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||cY(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!cY(r.rect)&&cX(r.rect,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(i??"")}let c="text"===t?`expected="${i??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:n,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return f.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===n?f.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${n} failed for selector ${c.selector.raw}: ${f.details}`}}}async function cQ(e){let t,r,{req:a,sessionName:i,sessionStore:n,contextFromFlags:o}=e,s=n.get(i);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sI("scrollintoview",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let l=a.positionals?.[0]??"";if(!l.startsWith("@"))return null;let d=cV("scrollintoview",a.flags);if(d)return d;let u=a.positionals&&a.positionals.length>1?a.positionals.slice(1).join(" ").trim():"",c=function(e,t,r){let a=uD({session:e,refInput:t,fallbackLabel:r,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`});if(!a.ok){let{response:e}=a;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:c1(t,0,{message:e.error.message})}}return c0(t,0,a.target)}(s,l,u);if(!c.ok)return c.response;let{ref:f}=c.state,{node:p,snapshotNodes:m,viewportRect:h}=c.state,w=dy(p,m),g=dW(p,s.device.platform,{action:"get"}),v=u||w||p.label||"";if(!cW(p.rect,h))return n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{ref:f,attempts:0,alreadyVisible:!0,refLabel:w,selectorChain:g,...Y(`Scrolled into view: @${f}`)}}),{ok:!0,data:{ref:f,attempts:0,alreadyVisible:!0,...Y(`Scrolled into view: @${f}`)}};let y=a.flags?.maxScrolls??48,I=0,A=0,b=cz(p.rect,h);for(;I<y;){let e=cW(p.rect,h);if(!e)break;t=e.direction,r=await sp(s.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],a.flags?.out,{...o(a.flags,s.appBundleId,s.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),I+=1,await cG(s,a.flags,n,o,{interactiveOnly:!0});let i=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:i,ref:n,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=dj(e,dE(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?dv(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return c0(r,i,{ref:n,node:e,snapshotNodes:t.snapshot.nodes})}let l=uD({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});if(!l.ok){let{response:e}=l;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:c1(r,i,{message:`scrollintoview lost track of ${r} after ${i} scroll${1===i?"":"s"}`,ref:n})}}return c0(r,i,l.target,{ref:n,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${i} scroll${1===i?"":"s"}`})}({session:s,targetInput:l,fallbackLabel:v,attempts:I,ref:f,selectorChain:g,platform:s.device.platform});if(!i.ok)return i.response;({node:p,snapshotNodes:m,viewportRect:h}=i.state);let d=cz(p.rect,h);if(0===d)break;if(d>=b){if((A+=1)>=2)return c1(l,I,{message:`scrollintoview made no progress toward ${l} after ${I} scroll${1===I?"":"s"}`,ref:f,stalled:!0})}else A=0;b=d}return cz(p.rect,h)>0?c1(l,I,{message:`scrollintoview reached --max-scrolls=${y} before ${l} entered view`,ref:f,maxScrolls:y}):(n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{...r??{},ref:f,attempts:I,direction:t,refLabel:w,selectorChain:g,...Y(`Scrolled into view: @${f}`)}}),{ok:!0,data:{...r??{},ref:f,attempts:I,direction:t,...Y(`Scrolled into view: @${f}`)}})}function c0(e,t,r,a={}){let{ref:i,missingBoundsMessage:n}=a,o=r.node;if(!o.rect)return{ok:!1,response:c1(e,t,{message:n??`Ref ${e} not found or has no bounds`,ref:i??r.ref})};let s=cH(r.snapshotNodes,o.rect);return s?{ok:!0,state:{ref:r.ref,node:o,snapshotNodes:r.snapshotNodes,viewportRect:s}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${e}`}}}}function c1(e,t,r={}){let{message:a,...i}=r;return{ok:!1,error:{code:"COMMAND_FAILED",message:"string"==typeof a?a:`scrollintoview could not find ${e}`,details:{reason:"not_found",attempts:t,...i}}}}async function c2(e){let t=await cF({...e,captureSnapshotForSession:cG,resolveRefTarget:uD,refSnapshotFlagGuardResponse:cV});if(t)return t;switch(e.req.command){case"get":return await cB(e);case"is":return await cZ(e);case"scrollintoview":return await cQ(e);default:return null}}function c3(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function c4(e){let{req:t,leaseRegistry:r}=e,a=c3(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function c8(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!tl(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eW(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function c5(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let c6=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],c9=/\bis(?:n't| not)\s+responding\b/i,c7=/^close app$/i;async function fe(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await ft(t),r=function(e){if(fn(e))return e.find(e=>{let t=fi(e);return t.length>0&&c7.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=dg(r.rect),n=await O("adb",r4(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return Q({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),"failed";if(!await fr(t))return Q({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await a4(t.device,t.appBundleId),!await fa(t,t.appBundleId)))return Q({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return Q({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:i}}),"recovered"}catch(e){return Q({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function ft(e){return dm(dA((await iI(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function fr(e){for(let t=0;t<12;t+=1){if(!fn(await ft(e)))return!0;await fo(500)}return!fn(await ft(e))}async function fa(e,t){for(let r=0;r<12;r+=1){if((await a2(e.device)).package===t)return!0;await fo(500)}return(await a2(e.device)).package===t}function fi(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function fn(e){return e.some(e=>{let t=fi(e);return t.length>0&&c9.test(t)})}function fo(e){return new Promise(t=>setTimeout(t,e))}let fs=[255,59,48,255],fl=[255,214,10,255],fd=[0,0,0,255],fu={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function fc(e){let t=ed(await d.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)fp(r)&&fv(r.rect)&&(!t||fy(r.rect)>fy(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,i=-1/0;for(let n of e)n.rect&&fv(n.rect)&&(t=Math.min(t,n.rect.x),r=Math.min(r,n.rect.y),a=Math.max(a,n.rect.x+n.rect.width),i=Math.max(i,n.rect.y+n.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||i<=r?null:{x:t,y:r,width:a-t,height:i-r}}(e.filter(e=>{var t;return fv(e.rect)&&!("image"===db((t=e).type??"")&&!fm(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(fh)||fw(e.identifier);return ff(e)?t:t&&function(e){let t=db(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return ff(e)&&!fp(e)}(t)&&fv(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(ff(t)&&!fp(t)&&fv(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&fv(r.rect))return r;if(t.hittable&&fv(t.rect)&&!fp(t))return t;let a=d_(e,t);return a?.rect&&fv(a.rect)&&!fp(a)?a:null}(e.nodes,a);if(!o?.rect||!fv(o.rect))continue;let s=function(e,t,r){let a=fg(e);if(e.ref!==t.ref&&a)return a;let i=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let i=fg(a);if(!i)continue;let n=function(e){let t=0;return db(e.type??"").includes("text")&&(t+=2),fh(e.label)&&(t+=2),fh(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(fg(t)??dy(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),ff(t)&&(a+=3),ff(e)&&(a+=2),r&&(a+=2),fw(t.identifier)&&(a+=1),fm(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return fb({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let i=r/e.width,n=a/e.height;return fb({x:Math.round((t.x-e.x)*i),y:Math.round((t.y-e.y)*n),width:Math.max(1,Math.round(t.width*i)),height:Math.max(1,Math.round(t.height*n))},r,a)}(i,o.rect,t,r);if(!fv(d))continue;let u=n.get(o.ref);(!u||l>u.score)&&n.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>fy(e.overlayRect)-fy(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(fI(e.overlayRect,r.overlayRect)||fI(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}fy(r.overlayRect)<fy(t[e].overlayRect)&&(t[e]=r)}return t})([...n.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:fA(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:fA(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:dg(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,i;(function(e,t,r){for(let a=0;a<2;a+=1)f_(e,t.x,t.x+t.width-1,t.y+a,r),f_(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),fN(e,t.x+a,t.y,t.y+t.height-1,r),fN(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,fs),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=fS(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:fS(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i){for(let n=0;n<11;n+=1)for(let o=0;o<a;o+=1)fD(e,t+o,r+n,i)})(e,i,o,a,fl),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=fu[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&fD(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,fd)}(a,i.overlayRect,i.ref)}return await d.writeFile(e.screenshotPath,b.sync.write(t)),r}function ff(e){let t=[e.type,e.role,e.subrole].map(e=>db(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function fp(e){let t=[e.type,e.role,e.subrole].map(e=>db(e??"")).join(" ");return t.includes("application")||t.includes("window")}function fm(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function fh(e){var t;let r;return!!fm(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function fw(e){var t;return"string"==typeof e&&!!fh(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function fg(e){let t=[e.label,e.value].find(fh);return t?t.trim():fw(e.identifier)?e.identifier.trim():void 0}function fv(e){return!!(e&&e.width>0&&e.height>0)}function fy(e){return e.width*e.height}function fI(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function fA(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function fb(e,t,r){let a=fS(e.x,0,Math.max(0,t-1)),i=fS(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:fS(e.width,1,n),height:fS(e.height,1,o)}}function fS(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function f_(e,t,r,a,i){for(let n=t;n<=r;n+=1)fD(e,n,a,i)}function fN(e,t,r,a,i){for(let n=r;n<=a;n+=1)fD(e,t,n,i)}function fD(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let i=(e.width*r+t)*4;e.data[i]=a[0],e.data[i+1]=a[1],e.data[i+2]=a[2],e.data[i+3]=a[3]}let fx=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),fM=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function fE(e,t,r,a){let i=J().requestId;return{...sA(e,t,r,a,i),requestId:i}}function fk(e){s.existsSync(e)&&s.unlinkSync(e)}function fO(e){if(!s.existsSync(e))return null;try{let t=JSON.parse(s.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function fL(e){let t=fO(e);if(!t||t.pid===process.pid)try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}function fC(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:fP,infoPath:fR,lockPath:fT,logPath:f$,sessionsDir:fF}=ei(process.env.AGENT_DEVICE_STATE_DIR),fU=eo(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var fV=fF;if(s.existsSync(fV))for(let e of s.readdirSync(fV,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=c.join(fV,e.name,"app-log.pid");if(s.existsSync(t))try{let e=function(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}(s.readFileSync(t,"utf8"));if(e&&function(e){let t,r=er(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=S(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{ri(t)}}let fG=new rr(fF),fj=new rZ({maxActiveSimulatorLeases:fC(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:fC(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:fC(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:fC(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),fB=z(),fq=n.randomBytes(24).toString("hex"),fH=er(process.pid)??void 0,fW=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=s.statSync(e),r=Z(),a=c.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),fz=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await ea({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:q(new $("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=H(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=N(r);if(r&&!a)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new $("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);Q({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,l=c3(r);fM.has(s)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:l.tenantId,runId:l.runId,leaseId:l.leaseId,backend:l.leaseBackend});let d=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),u=a.get(d);u&&(!function(e){var t,r;let a,i=e.recording;if(!i||"ios"!==e.device.platform)return;let n=(t=e.device.id,(a=tP.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&et(r)}:null);if(!i.runnerSessionId){n?.alive&&(i.runnerSessionId=n.sessionId);return}if(!n?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}n.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(u),a.set(d,u));let f=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?c8(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!ts(a):"apple"!==a||!ts(r)))&&i.push({key:"platform",value:e.platform}),c6)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of c6)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new $("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(c5).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,u),p=e=>(function(e,t,r){let a=J();if(!t.ok){Q({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=en({force:!0})??void 0;return{ok:!1,error:q(new $(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return Q({level:"info",phase:"request_success"}),en(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let o=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:c.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(f,e,n);if(u?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return p({ok:!1,error:{code:"COMMAND_FAILED",message:u.recording.invalidatedReason}});!u||f.meta?.lockPolicy||fx.has(s)||function(e,t){let r=c8(e,t);if(0!==r.length){var a;let t,i,n;throw new $("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(c5).join(", ")}. Use a different --session name or close this session first.`)}}(u,f.flags);let m=await c4({req:f,leaseRegistry:i});if(m)return p(m);let h=await ue({req:f,sessionName:d,logPath:t,sessionStore:a,invoke:o});if(h)return p(h);let w=await ub({req:f,sessionName:d,logPath:t,sessionStore:a});if(w)return p(w);let g=await cm({req:f,sessionName:d,sessionStore:a,logPath:t});if(g)return p(g);let v=await uL({req:f,sessionName:d,logPath:t,sessionStore:a,invoke:o});if(v)return p(v);let y=await c2({req:f,sessionName:d,sessionStore:a,contextFromFlags:(e,r,i)=>({...fE(t,e,r,i),surface:a.get(d)?.surface})});if(y)return p(y);let I=a.get(d);if(!I)return p({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!sI(s,I.device))return p({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${s} is not supported on this device`}});if("android"===I.device.platform&&I.recording&&"record"!==s){let e=await fe({session:I});if("failed"===e)return p({ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}})}let A=f.positionals??[],b=f.flags?.out,S="screenshot"===s&&A[0]?[rr.expandHome(A[0],f.meta?.cwd),...A.slice(1)]:A,_="screenshot"===s&&b?rr.expandHome(b,f.meta?.cwd):b,D="screenshot"===s?S:A,x="screenshot"===s&&_?{...f.flags??{},out:_}:f.flags??{},M=Date.now(),E={...fE(t,f.flags,I.appBundleId,I.trace?.outPath),surface:I.surface},k=await sp(I.device,s,S,_,{...E});if("screenshot"===s&&f.flags?.overlayRefs&&"string"==typeof k?.path){let e=await un({device:I.device,session:I,flags:void 0,logPath:t,snapshotScope:void 0}),r=uo(e,!1);I.snapshot=r;let a=await fc({screenshotPath:k.path,snapshot:r});k.overlayRefs=a}let O=Date.now(),L=function(e,t,r,a){if("scroll"!==t)return a;let i=cg(e.snapshot),n={...a??{}},o=cS(n.direction)??cS(r[0]);if(!o)return a;let s=c_(n.amount)??c_(r[1]),l=c_(n.pixels),d=cx(n,[]),u=c_(n.referenceWidth),c=c_(n.referenceHeight),f=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??cy;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...n,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250};let p=ic({direction:o,amount:s,pixels:l,referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight});return{...n,x1:p.x1,y1:p.y1,x2:p.x2,y2:p.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==p.pixels?{pixels:p.pixels}:{},referenceWidth:f.referenceWidth,referenceHeight:f.referenceHeight,durationMs:250}}(I,s,S,k);return cI(I,s,S,L,f.flags??{},M,O),a.recordAction(I,{command:s,positionals:D,flags:x,result:k??{}}),p({ok:!0,data:k??{}})}catch(r){Q({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=J(),t=en({force:!0})??void 0;return{ok:!1,error:q(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:f$,token:fq,sessionStore:fG,leaseRegistry:fj,trackDownloadableArtifact:function(e){let t=n.randomUUID(),r=setTimeout(()=>{rb(t)},9e5);return r.unref(),rA.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){s.existsSync(e)||s.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return s.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=fO(t);if(n?.pid&&n.pid!==process.pid&&D(n.pid,n.processStartTime))return!1;try{s.unlinkSync(t)}catch{}return i()}(fP,fT,{pid:process.pid,version:fB,startedAt:Date.now(),processStartTime:fH})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let i;if("socket"===fU||"dual"===fU){let t=f.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eL(e);Q({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await tG(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){Q({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=ek(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eO(o),eP(o))throw eT();i=await fz(e)}catch(e){i={ok:!1,error:q(e)}}finally{r-=1,o&&(a.delete(o),eC(o))}e.destroyed||e.write(`${JSON.stringify(i)}
65
- `),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new $("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===fU||"dual"===fU){let e=await rH({handleRequest:fz,token:fq});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let a=e.address();"object"==typeof a&&a?.port?t(a.port):r(new $("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:fq,version:fB,codeSignature:fW,processStartTime:fH},s.existsSync(fP)||s.mkdirSync(fP,{recursive:!0}),s.writeFileSync(f$,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",s.writeFileSync(fR,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:i,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:fP},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
65
+ `.trim();async function u3(e,t={}){let r,a=t.pollMs??150,i=t.attempts??12,n=0;for(let t=0;t<i;t+=1){let t=0;try{t=s.statSync(e).size}catch{t=0}if(t>0&&t===r){if((n+=1)>=2)return}else n=0;r=t,await new Promise(e=>setTimeout(e,a))}}async function u4(e){try{var t,r;let a,i=await O("swift",["-",e],{stdin:u2,allowFailure:!0,timeoutMs:1e4});if(0===i.exitCode)return!0;if(t=i.stderr,r=i.stdout,a=`${t}
66
+ ${r}`,/\b(no such module ['"]AVFoundation['"]|unable to find utility ["']swift["']|xcrun: error: unable to find utility ["']swift["'])\b/i.test(a))return u5(e);return!1}catch(t){if(t instanceof $&&"TOOL_MISSING"===t.code)return u5(e);throw t}}async function u8(e,t={}){let r=t.pollMs??150,a=t.attempts??12;for(let t=0;t<a;t+=1){if(await u4(e))return;await new Promise(e=>setTimeout(e,r))}}function u5(e){try{let t=s.statSync(e);if(!t.isFile()||t.size<=0)return!1}catch{return!1}let t=function(e){try{let t=s.openSync(e,"r");try{let e=s.fstatSync(t).size,r=0,a=[];for(;r+8<=e&&a.length<16;){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r))break;let i=e.readUInt32BE(0),n=e.toString("latin1",4,8);if(a.push(n),1===i){let e=Buffer.alloc(8);if(8>s.readSync(t,e,0,8,r+8))break;i=Number(e.readBigUInt64BE(0))}if(!Number.isFinite(i)||i<=0)break;r+=i}return a}finally{s.closeSync(t)}}catch{return[]}}(e);return t.includes("ftyp")&&t.includes("moov")}function u6(e){let t=c.parse(e);return c.join(t.dir,`${t.name}.gesture-telemetry.json`)}function u9(e){return[...e].sort((e,t)=>e.tMs-t.tMs)}function u7(e){var t,r,a;let i,n,{recording:o,trimStartMs:l}=e,d=(i=u6((t={videoPath:o.outPath,events:o.gestureEvents,trimStartMs:l}).videoPath),n={version:1,generatedAt:new Date().toISOString(),events:(r=t.events,(a=t.trimStartMs??0)>0?u9(r.flatMap(e=>{let t=e.tMs-a,r="durationMs"in e?e.durationMs:void 0;return("number"==typeof r?t+r:t)<=0?[]:[{...e,tMs:Math.max(0,t)}]})):u9(r))},s.writeFileSync(i,JSON.stringify(n,null,2)),i);return o.telemetryPath=d,d}function ce(e){let t=c.dirname(m(import.meta.url)),r=[m(new URL(`./${e}`,import.meta.url)),c.resolve(t,`../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(t,`../../../ios-runner/AgentDeviceRunner/RecordingScripts/${e}`),c.resolve(process.cwd(),`ios-runner/AgentDeviceRunner/RecordingScripts/${e}`)];for(let e of r)if(s.existsSync(e))return e;throw new $("COMMAND_FAILED",`Missing recording helper script: ${e}`,{hint:"Ensure ios-runner/AgentDeviceRunner/RecordingScripts is present in this checkout or bundled with the package.",scriptName:e,searchedPaths:r})}function ct(e=process.platform){if("darwin"!==e)return"touch overlay burn-in is only available on macOS hosts; returning raw video plus gesture telemetry"}async function cr(e){let{videoPath:t,scriptPath:r,scriptArgs:a,commandDescription:i}=e;await u3(t),await u8(t);let n=s.mkdtempSync(c.join(u.tmpdir(),"agent-device-record-overlay-")),o=c.join(n,`input${c.extname(t)||".mp4"}`),l=c.join(n,c.basename(t)),d=c.join(n,"home"),p=c.join(n,"module-cache");s.copyFileSync(t,o),s.mkdirSync(d,{recursive:!0}),s.mkdirSync(p,{recursive:!0});try{await O("xcrun",["swift",r,"--input",o,"--output",l,...a],{timeoutMs:12e4,env:{...process.env,HOME:d,CLANG_MODULE_CACHE_PATH:p}}),await u8(l),s.copyFileSync(l,t)}catch(a){let e=a instanceof $?a:new $("COMMAND_FAILED",String(a),void 0,a instanceof Error?a:void 0);throw new $("COMMAND_FAILED",i,{videoPath:t,script:r,stderr:e.details?.stderr,stdout:e.details?.stdout,exitCode:e.details?.exitCode,processExitError:e.details?.processExitError},e)}finally{s.rmSync(n,{recursive:!0,force:!0})}}async function ca(e){let{videoPath:t,trimStartMs:r}=e;r>0&&await cr({videoPath:t,scriptPath:a??=ce("recording-trim.swift"),scriptArgs:["--trim-start-ms",String(r)],commandDescription:"Failed to trim the start of the iOS recording"})}async function ci(e){let{videoPath:t,telemetryPath:a,targetLabel:i="recording"}=e;await cr({videoPath:t,scriptPath:r??=ce("recording-overlay.swift"),scriptArgs:["--events",a],commandDescription:`Failed to add touch overlays to the ${i}`})}function cn(e){return e instanceof Error?e.message:String(e)}function co(e,t){return e.stderr.trim()||e.stdout.trim()||`${t} exited with code ${e.exitCode}`}async function cs(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","ps","-o","pid=","-p",r],{allowFailure:!0});return 0===a.exitCode&&a.stdout.split(/\s+/).map(e=>e.trim()).includes(r)}async function cl(e,t,r){for(let a=0;a<40;a+=1){if(!await cs(e,t,r))return!0;await new Promise(e=>setTimeout(e,250))}return!await cs(e,t,r)}async function cd(e,t,r){let a,i=0;for(let n=0;n<20;n+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?n.stdout.trim():"";if(o.length>0&&o===a){if((i+=1)>=4)return}else i=0;a=o,await new Promise(e=>setTimeout(e,250))}}async function cu(e,t,r,a){for(let i=0;i<8;i+=1){let n=await e.runCmd("adb",["-s",t,"shell","stat","-c","%s",r],{allowFailure:!0}),o=0===n.exitCode?Number(n.stdout.trim()):NaN;if(Number.isFinite(o)&&o>0)return!0;if(!await cs(e,t,a))break;if(i+1>=2)return!0;await new Promise(e=>setTimeout(e,250))}return!1}async function cc(e){let t,{deps:r,deviceId:a,remotePath:i,outPath:n}=e;for(let e=0;e<2;e+=1){try{s.rmSync(n,{force:!0})}catch{}let o=await r.runCmd("adb",["-s",a,"pull",i,n],{allowFailure:!0});if(0!==o.exitCode)t=co(o,"adb pull");else{await r.waitForStableFile(n,{pollMs:250,attempts:20});let t=await r.isPlayableVideo(n);if(Q({level:"debug",phase:"record_stop_android_pull_validation",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1,fileSize:(()=>{try{return s.statSync(n).size}catch{return 0}})(),playable:t}}),t)return;Q({level:"warn",phase:"record_stop_android_invalid_video_retry",data:{deviceId:a,remotePath:i,outPath:n,attempt:e+1}})}e<1&&await new Promise(e=>setTimeout(e,750))}return t?`failed to copy recording from device: ${t}`:"failed to copy recording from device: pulled file is not a playable MP4"}async function cp(e,t,r){await e.runCmd("adb",["-s",t,"shell","rm","-f",r],{allowFailure:!0})}async function cf(e,t,r){let a=await e.runCmd("adb",["-s",t,"shell","kill","-9",r],{allowFailure:!0});return Q({level:"warn",phase:"record_stop_android_force_signal",data:{deviceId:t,remotePid:r,exitCode:a.exitCode,stdout:a.stdout.trim(),stderr:a.stderr.trim()}}),!(0!==a.exitCode&&await cs(e,t,r))&&await cl(e,t,r)}async function cm(e){var t;let r,{deps:a,device:i,recordingBase:n}=e,o="failed to start recording: Android screenrecord did not begin producing frames";for(let e of(t=Date.now(),r=`agent-device-recording-${t}.mp4`,[`/sdcard/${r}`,`/data/local/tmp/${r}`])){let t=await a.runCmd("adb",["-s",i.id,"shell",`screenrecord ${e} >/dev/null 2>&1 & echo $!`],{allowFailure:!0});if(0!==t.exitCode){o=`failed to start recording: ${co(t,"adb shell screenrecord")}`;continue}let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(e=>/^\d+$/.test(e)).at(-1);if(!r){o="failed to start recording: adb did not return a valid Android screenrecord pid",await cp(a,i.id,e);continue}if(Q({level:"debug",phase:"record_start_android_started",data:{deviceId:i.id,remotePath:e,remotePid:r}}),await cu(a,i.id,e,r))return{platform:"android",remotePath:e,remotePid:r,...n,startedAt:Date.now()};o="failed to start recording: Android screenrecord did not begin producing frames",await cf(a,i.id,r),await cp(a,i.id,e)}return{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}async function ch(e){let t,r,{deps:a,device:i,recording:n}=e;Q({level:"debug",phase:"record_stop_android_enter",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid}});let o=await a.runCmd("adb",["-s",i.id,"shell","kill","-2",n.remotePid],{allowFailure:!0});if(Q({level:"debug",phase:"record_stop_android_signal",data:{deviceId:i.id,remotePath:n.remotePath,remotePid:n.remotePid,exitCode:o.exitCode,stdout:o.stdout.trim(),stderr:o.stderr.trim()}}),0!==o.exitCode?await cs(a,i.id,n.remotePid)&&!await cf(a,i.id,n.remotePid)&&(t=`failed to stop recording: ${co(o,"adb shell kill")}`):await cl(a,i.id,n.remotePid)||await cf(a,i.id,n.remotePid)||(t=`failed to stop recording: Android screenrecord pid ${n.remotePid} did not exit`),!t){await cd(a,i.id,n.remotePath);let e=await cc({deps:a,deviceId:i.id,remotePath:n.remotePath,outPath:n.outPath});if(e)return await s(),{ok:!1,error:{code:"COMMAND_FAILED",message:e}};if(u7({recording:n}),n.showTouches&&n.telemetryPath){let e=ct();if(e)n.overlayWarning=e;else try{await a.overlayRecordingTouches({videoPath:n.outPath,telemetryPath:n.telemetryPath,targetLabel:"Android recording"})}catch(e){n.overlayWarning=`failed to overlay recording touches: ${cn(e)}`}}}if(await s(),t)return{ok:!1,error:{code:"COMMAND_FAILED",message:t}};if(r)return{ok:!1,error:{code:"COMMAND_FAILED",message:r}};return null;async function s(){let e=await a.runCmd("adb",["-s",i.id,"shell","rm","-f",n.remotePath],{allowFailure:!0});Q({level:"debug",phase:"record_stop_android_cleanup",data:{deviceId:i.id,remotePath:n.remotePath,exitCode:e.exitCode,stdout:e.stdout.trim(),stderr:e.stderr.trim()}}),0===e.exitCode||t||(r=`failed to clean up remote recording: ${co(e,"adb shell rm")}`)}}function cw(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function cg(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function cy(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n}=e,o=cw(r);if(o)try{await n.runIosRunnerCommand(a,{command:"snapshot",appBundleId:o,interactiveOnly:!0,compact:!0,depth:1},cg(t,i,r))}catch(e){Q({level:"warn",phase:"record_start_simulator_runner_warm_failed",data:{deviceId:a.id,session:r.name,appBundleId:o,error:cn(e)}})}}async function cv(e){let t,r,{req:a,activeSession:i,sessionStore:n,device:o,logPath:s,deps:l,fpsFlag:d,recordingBase:u,appBundleId:c}=e,p=`agent-device-recording-${Date.now()}.mp4`,f=`tmp/${p}`,m=cg(a,s,i),h=async()=>l.runIosRunnerCommand(o,{command:"recordStart",outPath:p,fps:d,appBundleId:c},m);try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(a){var w,g;if(!cn(a).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${cn(a)}`}};Q({level:"warn",phase:"record_start_runner_desynced",data:{platform:o.platform,kind:o.kind,deviceId:o.id,session:i.name,error:cn(a)}});let e=(w=o.id,g=i.name,n.toArray().find(e=>e.name!==g&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===w&&e.recording?.platform==="ios-device-runner"));if(e)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${e.name}'`}};try{await l.runIosRunnerCommand(o,{command:"recordStop",appBundleId:c},m)}catch{}try{let e=await h();t="number"==typeof e.recorderStartUptimeMs?e.recorderStartUptimeMs:void 0,r="number"==typeof e.targetAppReadyUptimeMs?e.targetAppReadyUptimeMs:void 0}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${cn(e)}`}}}}return{platform:"ios-device-runner",remotePath:f,runnerStartedAtUptimeMs:t,targetAppReadyUptimeMs:r,...u}}async function cI(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,fpsFlag:o,recordingBase:s,appBundleId:l}=e;try{await n.runIosRunnerCommand(a,{command:"recordStart",outPath:s.outPath,fps:o,appBundleId:l},cg(t,i,r))}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${cn(e)}`}}}return{platform:"macos-runner",...s}}async function cA(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=cw(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},cg(t,i,r))}catch(e){Q({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:cn(e)}})}let l={stdout:"",stderr:"",exitCode:1};for(let e of tv)if(0===(l=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",a.id,"--source",o.remotePath,"--destination",o.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(0!==l.exitCode){let e=l.stderr.trim()||l.stdout.trim()||`devicectl exited with code ${l.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}let d="number"!=typeof o.runnerStartedAtUptimeMs||"number"!=typeof o.targetAppReadyUptimeMs?0:Math.max(0,o.targetAppReadyUptimeMs-o.runnerStartedAtUptimeMs);d>0&&await n.trimRecordingStart({videoPath:o.outPath,trimStartMs:d});let u=u7({recording:o,trimStartMs:d});if(o.showTouches){let e=ct();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:u,targetLabel:"iOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${cn(e)}`}}return null}async function cb(e){let{req:t,activeSession:r,device:a,logPath:i,deps:n,recording:o}=e,s=cw(r);try{await n.runIosRunnerCommand(a,{command:"recordStop",appBundleId:s},cg(t,i,r))}catch(e){Q({level:"warn",phase:"record_stop_runner_failed",data:{platform:a.platform,kind:a.kind,deviceId:a.id,session:r.name,error:cn(e)}})}let l=u7({recording:o});if(o.showTouches){let e=ct();if(e)o.overlayWarning=e;else try{await n.overlayRecordingTouches({videoPath:o.outPath,telemetryPath:l,targetLabel:"macOS recording"})}catch(e){o.overlayWarning=`failed to overlay recording touches: ${cn(e)}`}}return null}async function cS(e){for(let t=0;t<2;t+=1){try{if(s.statSync(e).size>0)return Date.now()}catch{}if(t+1>=2)break;await new Promise(e=>setTimeout(e,250))}return Date.now()}async function c_(e){let t,r,{req:a,activeSession:i,device:n,logPath:o,deps:s,recordingBase:l,resolvedOut:d}=e;await cy({req:a,activeSession:i,device:n,logPath:o,deps:s});let{child:u,wait:c}=s.runCmdBackground("xcrun",eK(n,["io",n.id,"recordVideo",d]),{allowFailure:!0}),p=await cS(d);try{let e=Date.now(),l=await s.runIosRunnerCommand(n,{command:"uptime",appBundleId:cw(i)},{verbose:a.flags?.verbose,logPath:o,traceLogPath:i.trace?.outPath}),d=Date.now();t=Math.round((e+d)/2),r="number"==typeof l.currentUptimeMs?l.currentUptimeMs:void 0}catch{}return{platform:"ios",child:u,wait:c,...l,startedAt:p,gestureClockOriginAtMs:void 0===r?void 0:t,gestureClockOriginUptimeMs:r}}async function cN(e){let t,{req:r,sessionName:a,sessionStore:i,activeSession:n,device:o,logPath:l,deps:d}=e;if(n.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let u=r.flags?.fps;if(void 0!==u&&(!Number.isInteger(u)||u<1||u>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};if(!sx("record",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let p=r.positionals?.[1]??`./recording-${Date.now()}.mp4`,f=rr.expandHome(p,r.meta?.cwd),m={outPath:f,clientOutPath:r.meta?.clientArtifactPaths?.outPath,startedAt:Date.now(),showTouches:r.flags?.hideTouches!==!0,gestureEvents:[]};if(s.mkdirSync(c.dirname(f),{recursive:!0}),s.rmSync(f,{force:!0}),"ios"===o.platform&&"device"===o.kind){let e=cw(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};t=await cv({req:r,activeSession:n,sessionStore:i,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else if("macos"===o.platform){let e=cw(n);if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on macOS requires an active app session; run open <app> first"}};t=await cI({req:r,activeSession:n,device:o,logPath:l,deps:d,fpsFlag:u,recordingBase:m,appBundleId:e})}else t="ios"===o.platform?await c_({req:r,activeSession:n,device:o,logPath:l,deps:d,recordingBase:m,resolvedOut:f}):await cm({deps:d,device:o,recordingBase:m});return"ok"in t?t:(n.recording=t,i.set(a,n),i.recordAction(n,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:{action:"start",showTouches:t.showTouches}}),{ok:!0,data:{recording:"started",outPath:t.clientOutPath??p,showTouches:t.showTouches}})}async function cD(e){let{deps:t,device:r,recording:a}=e;if("android"===a.platform)return await ch({deps:t,device:r,recording:a});a.child.kill("SIGINT");let i=await a.wait;if(0!==i.exitCode)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to stop recording: ${co(i,"simctl recordVideo")}`}};let n=u7({recording:a});if(a.showTouches){let e=ct();if(e)a.overlayWarning=e;else try{await t.overlayRecordingTouches({videoPath:a.outPath,telemetryPath:n,targetLabel:"iOS recording"})}catch(e){a.overlayWarning=`failed to overlay recording touches: ${cn(e)}`}}return null}async function cx(e){var t;let r,{req:a,activeSession:i,device:n,logPath:o,deps:s}=e;if(!i.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let l=i.recording,d=l.invalidatedReason;i.recording=void 0;let u="ios-device-runner"===l.platform?await cA({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:l}):"macos-runner"===l.platform?await cb({req:a,activeSession:i,device:n,logPath:o,deps:s,recording:l}):await cD({deps:s,device:n,recording:l});return u||(d?{ok:!1,error:{code:"COMMAND_FAILED",message:d}}:(r=[{field:"outPath",path:(t=l).outPath,localPath:t.clientOutPath,fileName:c.basename(t.clientOutPath??t.outPath)}],t.telemetryPath&&r.push({field:"telemetryPath",path:t.telemetryPath,localPath:function(e){if(e.clientOutPath)return u6(e.clientOutPath)}(t),fileName:c.basename(t.telemetryPath)}),{ok:!0,data:{recording:"stopped",outPath:t.outPath,telemetryPath:t.telemetryPath,artifacts:r,showTouches:t.showTouches,overlayWarning:t.overlayWarning}}))}async function ck(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n={runCmd:O,runCmdBackground:k,runIosRunnerCommand:tz,waitForStableFile:u3,isPlayableVideo:u4,trimRecordingStart:ca,overlayRecordingTouches:ci},o=a.get(r),s=o?.device??await sv(t.flags??{});o||await sE(s);let l=o??{name:r,device:s,createdAt:Date.now(),actions:[]},d=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(d))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};if("start"===d)return cN({req:t,sessionName:r,sessionStore:a,activeSession:l,device:s,logPath:i,deps:n});let u=await cx({req:t,activeSession:l,device:s,logPath:i,deps:n});return u.ok&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:u.data?.outPath,showTouches:u.data?.showTouches}}),u}async function cM(e){let{req:t,sessionName:r,sessionStore:a,logPath:i}=e,n=t.command;if("record"===n)return ck({req:t,sessionName:r,sessionStore:a,logPath:i});if("trace"===n){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return lj("INVALID_ARGS","trace requires start|stop");let i=a.get(r);if(!i)return lj("SESSION_NOT_FOUND","No active session");if("start"===e){if(i.trace)return lj("INVALID_ARGS","trace already in progress");let e=t.positionals?.[1]??a.defaultTracePath(i),r=rr.expandHome(e);return s.mkdirSync(c.dirname(r),{recursive:!0}),s.appendFileSync(r,""),i.trace={outPath:r,startedAt:Date.now()},a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!i.trace)return lj("INVALID_ARGS","no active trace");let o=i.trace.outPath;if(t.positionals?.[1]){let e=rr.expandHome(t.positionals[1]);s.mkdirSync(c.dirname(e),{recursive:!0}),s.existsSync(o)?s.renameSync(o,e):s.appendFileSync(e,""),o=e}return i.trace=void 0,a.recordAction(i,{command:n,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function cE(e){return"number"==typeof e.gestureClockOriginAtMs&&"number"==typeof e.gestureClockOriginUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureClockOriginAtMs+(e.gestureStartUptimeMs-e.gestureClockOriginUptimeMs)-e.recordingStartedAt):"number"==typeof e.runnerStartedAtUptimeMs&&"number"==typeof e.gestureStartUptimeMs?Math.max(0,e.gestureStartUptimeMs-e.runnerStartedAtUptimeMs):"number"==typeof e.gestureStartUptimeMs&&"number"==typeof e.gestureEndUptimeMs?Math.max(0,e.fallbackFinishedAtMs-(e.gestureEndUptimeMs-e.gestureStartUptimeMs)-e.recordingStartedAt):Math.max(0,e.fallbackStartedAtMs-e.recordingStartedAt)}let cO=new WeakMap;function cL(e){if(!e)return;let t=cO.get(e);if(t)return t;let r=function(e){let t=function(e){let t=e.filter(e=>(function(e){if(!e)return!1;let t=e.toLowerCase();return t.includes("application")||t.includes("window")})(e.type)&&cC(e.rect)).map(e=>e.rect).sort((e,t)=>(t?.width??0)*(t?.height??0)-(e?.width??0)*(e?.height??0))[0];if(t)return t;let r=e.map(e=>e.rect).filter(cC);if(0===r.length)return;let a=Math.max(...r.map(e=>e.x+e.width)),i=Math.max(...r.map(e=>e.y+e.height));if(!(a<=0)&&!(i<=0))return{x:0,y:0,width:a,height:i}}(e);if(t)return{referenceWidth:t.width,referenceHeight:t.height}}(e.nodes??[]);if(r)return cO.set(e,r),r}function cC(e){return!!e&&e.width>0&&e.height>0}let cP={referenceWidth:1e3,referenceHeight:1e3};function cR(e,t,r,a,i={},n=Date.now(),o=Date.now()){var s,l,d;let u,c,p=e.recording;if(!p)return;let f={...i,...a??{}},m=cU(f.effectiveDurationMs)??cU(f.durationMs),h={recordingStartedAt:p.startedAt,gestureClockOriginAtMs:p.gestureClockOriginAtMs,gestureClockOriginUptimeMs:p.gestureClockOriginUptimeMs,runnerStartedAtUptimeMs:"ios-device-runner"===p.platform?p.runnerStartedAtUptimeMs:void 0,gestureStartUptimeMs:cU(f.gestureStartUptimeMs),gestureEndUptimeMs:cU(f.gestureEndUptimeMs),fallbackStartedAtMs:n,fallbackFinishedAtMs:o},w="number"==typeof(s={gestureStartUptimeMs:cU(f.gestureStartUptimeMs),gestureEndUptimeMs:cU(f.gestureEndUptimeMs),reportedDurationMs:m,fallbackStartedAtMs:n,fallbackFinishedAtMs:o}).gestureStartUptimeMs&&"number"==typeof s.gestureEndUptimeMs?Math.max(0,s.gestureEndUptimeMs-s.gestureStartUptimeMs):"number"==typeof s.reportedDurationMs?Math.max(0,s.reportedDurationMs):Math.max(0,s.fallbackFinishedAtMs-s.fallbackStartedAtMs),g="ios"===e.device.platform&&void 0===cU(f.gestureStartUptimeMs)&&function(e,t){switch(e){case"click":case"fill":case"focus":return!0;case"press":{let e=cV(cU(t.count),1)??1,r=!0===t.doubleTap,a=cV(cU(t.holdMs),1);return 1===e&&!r&&void 0===a}default:return!1}}(t,f)?function(e){let t=Math.max(0,e.gestureDurationMs);if(t<600)return cE(e);let r=Math.min(Math.max(.15*t,120),260);return Math.max(0,e.fallbackFinishedAtMs-r-e.recordingStartedAt)}({...h,gestureDurationMs:w}):cE(h),y=(l=e.snapshot,u=cU((d=f).referenceWidth),c=cU(d.referenceHeight),void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:cL(l)),v=function(e,t,r,a,i,n){switch(e){case"click":case"press":return function(e,t,r,a){let i=cG(t,e);if(!i)return[];let{x:n,y:o}=i,s=cV(cU(t.count),1)??1,l=cV(cU(t.intervalMs),0)??0,d=!0===t.doubleTap,u=cV(cU(t.holdMs),1),c=[];for(let e=0;e<s;e+=1){let t=r+e*l;if(void 0!==u&&u>0){c.push(c$(t,n,o,u,a));continue}c.push(cT(t,n,o,a)),d&&c.push(cT(t+90,n,o,a))}return c}(t,r,a,n);case"fill":case"focus":return function(e,t,r,a){let i=cG(t,e);if(!i)return[];let{x:n,y:o}=i;return[cT(r,n,o,a)]}(t,r,a,n);case"longpress":return function(e,t,r,a,i){let n=cG(t,e);if(!n)return[];let{x:o,y:s}=n;return[c$(r,o,s,cB(a,[cU(t.durationMs),cU(e[2])],800),i)]}(t,r,a,i,n);case"scroll":return function(e,t,r,a,i){let n=cj(t,e),o=cF(t.contentDirection)??cF(t.direction);if(!n||!o)return[];let{x1:s,y1:l,x2:d,y2:u}=n,c=cB(a,[],250),p=cU(t.amount)??cU(e[1]),f=cU(t.pixels);return[{kind:"scroll",tMs:r,x:s,y:l,x2:d,y2:u,...i,durationMs:c,contentDirection:o,...void 0!==p?{amount:p}:{},...void 0!==f?{pixels:f}:{}}]}(t,r,a,i,n);case"swipe":return function(e,t,r,a,i){let n=cj(t,e);if(!n)return[];let{x1:o,y1:s,x2:l,y2:d}=n,u=cB(a,[cU(t.effectiveDurationMs),cU(t.durationMs),cU(e[4])],250),c=cV(cU(t.count),1)??1,p=cV(cU(t.pauseMs),0)??0,f="ping-pong"===t.pattern?"ping-pong":"one-way",m=[];for(let e=0;e<c;e+=1){let t="ping-pong"===f&&e%2==1,a=t?l:o,n=t?d:s,c=t?o:l,h=t?s:d,w=r+e*(u+p);if("back-swipe"===function(e,t,r,a,i){if(!i||Math.abs(r-e)<=1.25*Math.abs(a-t))return"swipe";let n=.08*i.referenceWidth;return e<=n&&r>e||e>=i.referenceWidth-n&&r<e?"back-swipe":"swipe"}(a,n,c,h,i)){m.push({kind:"back-swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u,edge:function(e,t,r){if(r){let t=.08*r.referenceWidth;if(e<=t)return"left";if(e>=r.referenceWidth-t)return"right"}return t>=e?"left":"right"}(a,c,i)});continue}m.push({kind:"swipe",tMs:w,x:a,y:n,x2:c,y2:h,...i,durationMs:u})}return m}(t,r,a,i,n);case"pinch":return function(e,t,r,a,i){let n=cG(t,e,1),o=cU(t.scale)??cU(e[0]);if(!n||void 0===o||o<=0)return[];let{x:s,y:l}=n;return[{kind:"pinch",tMs:r,x:s,y:l,...i,scale:o,durationMs:cB(a,[],280)}]}(t,r,a,i,n);default:return[]}}(t,r,f,g,w,y);0!==v.length&&(p.gestureEvents.push(...v),Q({level:"debug",phase:"record_touch_visualization_event",data:{session:e.name,command:t,count:v.length,tMs:g,gestureDurationMs:w,kinds:v.map(e=>e.kind)}}))}function cT(e,t,r,a){return{kind:"tap",tMs:e,x:t,y:r,...a}}function c$(e,t,r,a,i){return{kind:"longpress",tMs:e,x:t,y:r,...i,durationMs:a}}function cF(e){if("string"!=typeof e)return;let t=e.trim().toLowerCase();switch(t){case"up":case"down":case"left":case"right":return t;default:return}}function cU(e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"!=typeof e||0===e.trim().length)return;let t=Number(e);return Number.isFinite(t)?t:void 0}function cV(e,t){if(void 0===e)return;let r=Math.floor(e);return r>=t?r:void 0}function cG(e,t,r=0){let a=cU(e.x)??cU(t[r]),i=cU(e.y)??cU(t[r+1]);if(void 0!==a&&void 0!==i)return{x:a,y:i}}function cj(e,t){let r=cU(e.x1)??cU(t[0]),a=cU(e.y1)??cU(t[1]),i=cU(e.x2)??cU(t[2]),n=cU(e.y2)??cU(t[3]);if(void 0!==r&&void 0!==a&&void 0!==i&&void 0!==n)return{x1:r,y1:a,x2:i,y2:n}}function cB(e,t,r){return cV(e,1)??t.map(e=>cV(e,1)).find(e=>void 0!==e)??r}function cq(e){var t,r,a;let i,n,{data:o,fallbackX:s,fallbackY:l,referenceFrame:d,extra:u}=e,c=(t=u,r=s,a=l,i="string"==typeof t?.ref?t.ref:void 0,n="string"==typeof t?.button?t.button:void 0,("string"==typeof t?.text?`Filled ${Array.from(t.text).length} chars`:i?n&&"primary"!==n?`Clicked ${n} @${i} (${r}, ${a})`:`Tapped @${i} (${r}, ${a})`:void 0)??("string"==typeof o?.message?o.message:void 0));return{x:s,y:l,...d??{},...u??{},...o??{},...Y(c)}}async function cH(e){let{session:t,sessionStore:r,requestCommand:a,requestPositionals:i,flags:n,contextFromFlags:o,interactionCommand:s,interactionPositionals:l,outPath:d,afterDispatch:u,buildPayloads:c}=e,p=await cW({session:t,flags:n,contextFromFlags:o,command:s,positionals:l,outPath:d});await u?.(p.data);let{result:f,responseData:m=f}=await c(p.data);return function(e){let{session:t,sessionStore:r,command:a,positionals:i,flags:n,result:o,responseData:s,actionStartedAt:l,actionFinishedAt:d}=e;return r.recordAction(t,{command:a,positionals:i,flags:n??{},result:o}),cR(t,a,i,o,n??{},l,d),{ok:!0,data:s}}({session:t,sessionStore:r,command:a,positionals:i,flags:n,result:f,responseData:m,actionStartedAt:p.actionStartedAt,actionFinishedAt:p.actionFinishedAt})}async function cW(e){let{session:t,flags:r,contextFromFlags:a,command:i,positionals:n,outPath:o}=e,s=Date.now(),l={...a(r,t.appBundleId,t.trace?.outPath)},d=await sI(t.device,i,n,o,l);return{data:d&&"object"==typeof d?d:void 0,actionStartedAt:s,actionFinishedAt:Date.now()}}async function cz(e){let{session:t,flags:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if("android"===t.device.platform){let e=await iq(t.device),r={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=r),r}let o=cL(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=cL(await n(t,r,a,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}async function cJ(e){try{return await cz(e)}catch(t){Q({level:"warn",phase:"touch_reference_frame_resolve_failed",data:{platform:e.session.device.platform,error:t instanceof Error?t.message:String(t)}});return}}function cK(e){return cL({nodes:e,createdAt:0})}function cX(e,t){return"macos"!==e.device.platform||"desktop"!==e.surface&&"menubar"!==e.surface||"menubar"===e.surface&&("click"===t||"press"===t)?null:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`}}}async function cY(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r),d=t.command,u="click"===d?"click":"press";if(!l)return lj("SESSION_NOT_FOUND","No active session. Run open first.");let c=cX(l,u);if(c)return c;if(!sx("press",l.device))return lj("UNSUPPORTED_OPERATION","press is not supported on this device");let p=o4(t.flags),f="primary"===p?{}:{button:p};if("primary"!==p){let e=o8({commandLabel:u,platform:l.device.platform,button:p,count:t.flags?.count,intervalMs:t.flags?.intervalMs,holdMs:t.flags?.holdMs,jitterPx:t.flags?.jitterPx,doubleTap:t.flags?.doubleTap});if(e)return lj(e.code,e.message,e.details)}let m=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(m)return cH({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[String(m.x),String(m.y)],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(m.x),String(m.y)],outPath:t.flags?.out,afterDispatch:async()=>{await cZ(l,"coordinate tap")},buildPayloads:async e=>{let r=await cJ({session:l,flags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n}),o=cq({data:e,fallbackX:m.x,fallbackY:m.y,referenceFrame:r,extra:f});return{result:o,responseData:o}}});let h="click",w=t.positionals?.[0]??"";if(w.startsWith("@")){let e=s("press",t.flags);if(e)return e;let r=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",c=await uq({session:l,refInput:w,fallbackLabel:r,promoteToHittableAncestor:!0,invalidRefMessage:`${u} requires a ref like @e2`,missingBoundsMessage:`Ref ${w} not found or has no bounds`,invalidBoundsMessage:`Ref ${w} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!c.ok)return c.response;let{ref:p,node:m,snapshotNodes:g,point:y}=c.target,v=dO(m,g),I=d4(m,l.device.platform,{action:h}),{x:A,y:b}=y;return cH({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(A),String(b)],outPath:t.flags?.out,afterDispatch:async()=>{await cZ(l,`@${p}`)},buildPayloads:e=>{let t=cq({data:e,fallbackX:A,fallbackY:b,referenceFrame:cK(g),extra:{ref:p,refLabel:v,selectorChain:I,...f}});return{result:t,responseData:t}}})}let g=(t.positionals??[]).join(" ").trim();if(!g)return{ok:!1,error:{code:"INVALID_ARGS",message:`${u} requires @ref, selector expression, or x y coordinates`}};let y=dG(g),v=await n(l,t.flags,a,i,{interactiveOnly:!0}),I=await X("selector_resolve",()=>d0(v.nodes,y,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:d});if(!I||!I.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:d2(y,I?.diagnostics??[],{unique:!0})}};let A=uH(v.nodes,I.node),b=uj(A.rect);if(!b)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${I.selector.raw} resolved to invalid bounds`}};let{x:S,y:_}=b,N=d4(A,l.device.platform,{action:h}),D=dO(A,v.nodes);return cH({session:l,sessionStore:a,requestCommand:d,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"press",interactionPositionals:[String(S),String(_)],outPath:t.flags?.out,afterDispatch:async()=>{await cZ(l,I.selector.raw)},buildPayloads:e=>{let t=cq({data:e,fallbackX:S,fallbackY:_,referenceFrame:cK(v.nodes),extra:{selector:I.selector.raw,selectorChain:N,refLabel:D,...f}});return{result:t,responseData:t}}})}async function cZ(e,t){if("android"!==e.device.platform||!e.appBundleId)return;let r=await a3(e.device),a=r.package?.trim();if(a&&a!==e.appBundleId){var i;if("com.android.settings"===(i=a)||"com.android.systemui"===i||"com.google.android.permissioncontroller"===i||i.includes("launcher"))throw new $("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${a}. The tap likely escaped the app.`,{expectedPackage:e.appBundleId,foregroundPackage:a,activity:r.activity,hint:"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."})}}async function cQ(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o,refSnapshotFlagGuardResponse:s}=e,l=a.get(r);if(l){let e=cX(l,"fill");if(e)return e}if(l&&!sx("fill",l.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let e=s("fill",t.flags);if(e)return e;let r=t.positionals.length>=3?t.positionals[1]:"",d=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let u=await uq({session:l,refInput:t.positionals[0],fallbackLabel:r,promoteToHittableAncestor:!1,invalidRefMessage:"fill requires a ref like @e2",missingBoundsMessage:`Ref ${t.positionals[0]} not found or has no bounds`,invalidBoundsMessage:`Ref ${t.positionals[0]} not found or has invalid bounds`,reqFlags:t.flags,sessionStore:a,contextFromFlags:i,captureSnapshotForSession:n,resolveRefTarget:o});if(!u.ok)return u.response;let{ref:c,node:p,snapshotNodes:f,point:m}=u.target,h=p.type??"",w=h&&!dR(h,l.device.platform)?`fill target ${t.positionals[0]} resolved to "${h}", attempting fill anyway.`:void 0,g=dO(p,f),y=d4(p,l.device.platform,{action:"fill"}),{x:v,y:I}=m;return cH({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(v),String(I),d],outPath:t.flags?.out,buildPayloads:e=>{let t=cq({data:e,fallbackX:v,fallbackY:I,referenceFrame:cK(f),extra:{ref:c,refLabel:g,selectorChain:y,text:d}}),r={...e??{ref:c,x:v,y:I}};return w&&(t.warning=w,r.warning=w),{result:t,responseData:r}}})}if(!l)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let d=dB(t.positionals??[],{preferTrailingValue:!0});if(d){if(0===d.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let e=d.rest.join(" ").trim();if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=dG(d.selectorExpression),o=await n(l,t.flags,a,i,{interactiveOnly:!0}),s=await X("selector_resolve",()=>d0(o.nodes,r,{platform:l.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:t.command});if(!s||!s.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:d2(r,s?.diagnostics??[],{unique:!0})}};let u=s.node,c=s.node.rect,p=u.type??"",f=p&&!dR(p,l.device.platform)?`fill target ${s.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=dM(c),w=d4(u,l.device.platform,{action:"fill"});return cH({session:l,sessionStore:a,requestCommand:t.command,requestPositionals:t.positionals??[],flags:t.flags,contextFromFlags:i,interactionCommand:"fill",interactionPositionals:[String(m),String(h),e],outPath:t.flags?.out,buildPayloads:t=>{let r=cq({data:t,fallbackX:m,fallbackY:h,referenceFrame:cK(o.nodes),extra:{text:e,selector:s.selector.raw,selectorChain:w,refLabel:dO(u,o.nodes)}});return f&&(r.warning=f),{result:r,responseData:r}}})}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}async function c0(e){switch(e.req.command){case"press":case"click":return await cY(e);case"fill":return await cQ(e);default:return null}}let c1=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function c2(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of c1)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}async function c3(e,t,r,a,i){let n={...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},o=a(n,e.appBundleId,e.trace?.outPath),{snapshot:s}=await uw({device:e.device,session:e,flags:n,outPath:n.out,logPath:o.logPath??""});return e.snapshot=s,r.set(e.name,e),e.snapshot}async function c4(e){let{command:t,selectorExpression:r,session:a,flags:i,sessionStore:n,contextFromFlags:o,interactiveOnly:s,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}=e,c=dG(r),p=await c3(a,i,n,o,{interactiveOnly:s}),f=await X("selector_resolve",()=>d0(p.nodes,c,{platform:a.device.platform,requireRect:l,requireUnique:d,disambiguateAmbiguous:u}),{command:t});return f&&(!l||f.node.rect)?{ok:!0,chain:c,snapshot:p,resolved:f}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:d2(c,f?.diagnostics??[],{unique:d})}}}}async function c8(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sx("get",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let s=t.positionals?.[1]??"";if(s.startsWith("@")){let e=c2("get",t.flags);if(e)return e;let r=uG({session:o,refInput:s,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${s} not found`});if(!r.ok)return r.response;let{ref:l,node:d}=r.target,u=d4(d,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,selectorChain:u}}),{ok:!0,data:{ref:l,node:d}};let c=await uW({device:o.device,node:d,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{ref:l,text:c,refLabel:c5(c),selectorChain:u}}),{ok:!0,data:{ref:l,text:c,node:d}}}let l=t.positionals.slice(1).join(" ").trim();if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let d=await c4({command:t.command,selectorExpression:l,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===n});if(!d.ok)return d.response;let{resolved:u}=d,c=u.node,p=d4(c,o.device.platform,{action:"get"});if("attrs"===n)return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,node:c}};let f=await uW({device:o.device,node:c,flags:t.flags,appBundleId:o.appBundleId,traceOutPath:o.trace?.outPath,surface:o.surface,contextFromFlags:i});return a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{text:f,refLabel:c5(f),selector:u.selector.raw,selectorChain:p}}),{ok:!0,data:{selector:u.selector.raw,text:f,node:c}}}function c5(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}function c6(e,t){let r=dM(t),a=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=a.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=pt(i.map(e=>e.rect).filter(e=>pe(e,r.x,r.y)));if(n)return n;let o=pt(i.map(e=>e.rect));if(o)return o;let s=pt(a.map(e=>e.rect).filter(e=>pe(e,r.x,r.y)));return s||null}function c9(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=s-.25*i,c=Math.max(8,.1*n),p=e.y+e.height/2,f=e.x+e.width/2;if(p>=o+.25*i&&p<=u)return null;let m=Math.round((r=f,a=l+c,Math.min(d-c,Math.max(a,r)))),h=Math.round(o+.86*i),w=Math.round(o+.14*i);return p>u?{x:m,startY:h,endY:w,direction:"down"}:{x:m,startY:w,endY:h,direction:"up"}}function c7(e,t){let r=Math.max(1,t.height),a=t.y,i=t.y+r,n=a+.25*r,o=i-.25*r,s=e.y+e.height/2;return s<n?Math.ceil(n-s):s>o?Math.ceil(s-o):0}function pe(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function pt(e){let t=null,r=-1;for(let a of e){let e=a.width*a.height;e>r&&(t=a,r=e)}return t}function pr(e,t){var r,a;let i=c6(t,e);return!i||(r=e,a=i,r.x<a.x+a.width&&r.x+r.width>a.x&&r.y<a.y+a.height&&r.y+r.height>a.y)}function pa(e){return!!(e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.width)&&Number.isFinite(e.height)&&e.width>0&&e.height>0)}async function pi(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(n))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let o=a.get(r);if(!o)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sx("is",o.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:s}=dq(t.positionals);if(!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let l=s.rest.join(" ").trim();if("text"===n&&!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==n&&s.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${n} does not accept trailing values`}};let d=dG(s.selectorExpression);if("exists"===n){let e=d1((await c3(o,t.flags,a,i,{interactiveOnly:!1})).nodes,d,{platform:o.device.platform});return e?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:e.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,matches:e.matches}}),{ok:!0,data:{predicate:n,pass:!0,selector:e.selector.raw,matches:e.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:d2(d,[],{unique:!1})}}}let u=await c4({command:"is",selectorExpression:s.selectorExpression,session:o,flags:t.flags,sessionStore:a,contextFromFlags:i,interactiveOnly:!1,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:!1});if(!u.ok)return u.response;let{resolved:c}=u,p=function(e){let{predicate:t,node:r,nodes:a,expectedText:i,platform:n}=e,o=d$(r),s=dY(r,n),l=!0===r.selected,d="text"===t?dX(r):function(e,t){if(!0===e.hittable)return!0;if(pa(e.rect))return pr(e.rect,t);if(e.rect)return!1;let r=function(e,t){let r=new Map(t.map(e=>[e.index,e])),a=e,i=new Set;for(;"number"==typeof a.parentIndex&&!i.has(a.index);){i.add(a.index);let e=r.get(a.parentIndex);if(!e)break;if(function(e){let t=dP(e.type??"");return!(t.includes("application")||t.includes("window")||t.includes("scrollview")||t.includes("tableview")||t.includes("collectionview"))&&"table"!==t&&"list"!==t&&"listview"!==t&&(!0===e.hittable||pa(e.rect))}(e))return e;a=e}return null}(e,t);return!!r&&(!0===r.hittable||!!pa(r.rect)&&pr(r.rect,t))}(r,a),u=!1;switch(t){case"visible":u=d;break;case"hidden":u=!d;break;case"editable":u=s;break;case"selected":u=l;break;case"text":u=o===(i??"")}let c="text"===t?`expected="${i??""}" actual="${o}"`:`actual=${JSON.stringify({visible:d,editable:s,selected:l})}`;return{pass:u,actualText:o,details:c}}({predicate:n,node:c.node,nodes:u.snapshot.nodes,expectedText:l,platform:o.device.platform});return p.pass?(a.recordAction(o,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:n,selector:c.selector.raw,selectorChain:d.selectors.map(e=>e.raw),pass:!0,text:"text"===n?p.actualText:void 0}}),{ok:!0,data:{predicate:n,pass:!0,selector:c.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${n} failed for selector ${c.selector.raw}: ${p.details}`}}}async function pn(e){let t,r,{req:a,sessionName:i,sessionStore:n,contextFromFlags:o}=e,s=n.get(i);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!sx("scrollintoview",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let l=a.positionals?.[0]??"";if(!l.startsWith("@"))return null;let d=c2("scrollintoview",a.flags);if(d)return d;let u=a.positionals&&a.positionals.length>1?a.positionals.slice(1).join(" ").trim():"",c=function(e,t,r){let a=uG({session:e,refInput:t,fallbackLabel:r,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${t} not found or has no bounds`});if(!a.ok){let{response:e}=a;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:ps(t,0,{message:e.error.message})}}return po(t,0,a.target)}(s,l,u);if(!c.ok)return c.response;let{ref:p}=c.state,{node:f,snapshotNodes:m,viewportRect:h}=c.state,w=dO(f,m),g=d4(f,s.device.platform,{action:"get"}),y=u||w||f.label||"";if(!c9(f.rect,h))return n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{ref:p,attempts:0,alreadyVisible:!0,refLabel:w,selectorChain:g,...Y(`Scrolled into view: @${p}`)}}),{ok:!0,data:{ref:p,attempts:0,alreadyVisible:!0,...Y(`Scrolled into view: @${p}`)}};let v=a.flags?.maxScrolls??48,I=0,A=0,b=c7(f.rect,h);for(;I<v;){let e=c9(f.rect,h);if(!e)break;t=e.direction,r=await sI(s.device,"swipe",[String(e.x),String(e.startY),String(e.x),String(e.endY),"16"],a.flags?.out,{...o(a.flags,s.appBundleId,s.trace?.outPath),count:1,pauseMs:0,pattern:"one-way"}),I+=1,await c3(s,a.flags,n,o,{interactiveOnly:!0});let i=function(e){let{session:t,targetInput:r,fallbackLabel:a,attempts:i,ref:n,selectorChain:o,platform:s}=e;if(t.snapshot){let e=function(e,t,r,a){for(let r of t){let t=d0(e,dG(r),{platform:a,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0});if(t?.node.rect)return t.node}return r?dE(e,r):null}(t.snapshot.nodes,o,a,s);if(e)return po(r,i,{ref:n,node:e,snapshotNodes:t.snapshot.nodes})}let l=uG({session:t,refInput:r,fallbackLabel:a,requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${r} not found or has no bounds`});if(!l.ok){let{response:e}=l;return e.ok||"COMMAND_FAILED"!==e.error.code?{ok:!1,response:e}:{ok:!1,response:ps(r,i,{message:`scrollintoview lost track of ${r} after ${i} scroll${1===i?"":"s"}`,ref:n})}}return po(r,i,l.target,{ref:n,missingBoundsMessage:`scrollintoview lost bounds for ${r} after ${i} scroll${1===i?"":"s"}`})}({session:s,targetInput:l,fallbackLabel:y,attempts:I,ref:p,selectorChain:g,platform:s.device.platform});if(!i.ok)return i.response;({node:f,snapshotNodes:m,viewportRect:h}=i.state);let d=c7(f.rect,h);if(0===d)break;if(d>=b){if((A+=1)>=2)return ps(l,I,{message:`scrollintoview made no progress toward ${l} after ${I} scroll${1===I?"":"s"}`,ref:p,stalled:!0})}else A=0;b=d}return c7(f.rect,h)>0?ps(l,I,{message:`scrollintoview reached --max-scrolls=${v} before ${l} entered view`,ref:p,maxScrolls:v}):(n.recordAction(s,{command:a.command,positionals:a.positionals??[],flags:a.flags??{},result:{...r??{},ref:p,attempts:I,direction:t,refLabel:w,selectorChain:g,...Y(`Scrolled into view: @${p}`)}}),{ok:!0,data:{...r??{},ref:p,attempts:I,direction:t,...Y(`Scrolled into view: @${p}`)}})}function po(e,t,r,a={}){let{ref:i,missingBoundsMessage:n}=a,o=r.node;if(!o.rect)return{ok:!1,response:ps(e,t,{message:n??`Ref ${e} not found or has no bounds`,ref:i??r.ref})};let s=c6(r.snapshotNodes,o.rect);return s?{ok:!0,state:{ref:r.ref,node:o,snapshotNodes:r.snapshotNodes,viewportRect:s}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${e}`}}}}function ps(e,t,r={}){let{message:a,...i}=r;return{ok:!1,error:{code:"COMMAND_FAILED",message:"string"==typeof a?a:`scrollintoview could not find ${e}`,details:{reason:"not_found",attempts:t,...i}}}}async function pl(e){let t=await c0({...e,captureSnapshotForSession:c3,resolveRefTarget:uG,refSnapshotFlagGuardResponse:c2});if(t)return t;switch(e.req.command){case"get":return await c8(e);case"is":return await pi(e);case"scrollintoview":return await pn(e);default:return null}}function pd(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function pu(e){let{req:t,leaseRegistry:r}=e,a=pd(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function pc(e,t){if(!t)return[];let r=[],a=e.device,i=t.platform;if(i&&!tl(a.platform,i)&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eW(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function pp(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let pf=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],pm=/\bis(?:n't| not)\s+responding\b/i,ph=/^close app$/i;async function pw(e){let{session:t}=e;if("android"!==t.device.platform||!t.recording)return"absent";try{let e=await pg(t),r=function(e){if(pA(e))return e.find(e=>{let t=pI(e);return t.length>0&&ph.test(t)&&e.rect})}(e);if(!r?.rect)return"absent";let{x:a,y:i}=dM(r.rect),n=await O("adb",r4(t.device,["shell","input","tap",String(Math.round(a)),String(Math.round(i))]),{allowFailure:!0});if(0!==n.exitCode)return Q({level:"warn",phase:"android_blocking_dialog_tap_failed",data:{session:t.name,deviceId:t.device.id,exitCode:n.exitCode,stdout:n.stdout.trim(),stderr:n.stderr.trim()}}),"failed";if(!await py(t))return Q({level:"warn",phase:"android_blocking_dialog_still_present",data:{session:t.name,deviceId:t.device.id}}),"failed";if(t.appBundleId&&(await a8(t.device,t.appBundleId),!await pv(t,t.appBundleId)))return Q({level:"warn",phase:"android_blocking_dialog_relaunch_unfocused",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId}}),"failed";return Q({level:"warn",phase:"android_blocking_dialog_recovered",data:{session:t.name,deviceId:t.device.id,appBundleId:t.appBundleId,x:a,y:i}}),"recovered"}catch(e){return Q({level:"warn",phase:"android_blocking_dialog_recovery_failed",data:{session:t.name,deviceId:t.device.id,error:e instanceof Error?e.message:String(e)}}),"failed"}}async function pg(e){return dD(dC((await iN(e.device,{interactiveOnly:!1,compact:!1})).nodes))}async function py(e){for(let t=0;t<12;t+=1){if(!pA(await pg(e)))return!0;await pb(500)}return!pA(await pg(e))}async function pv(e,t){for(let r=0;r<12;r+=1){if((await a3(e.device)).package===t)return!0;await pb(500)}return(await a3(e.device)).package===t}function pI(e){let t=[e.label,e.identifier];return"string"==typeof e.value&&e.value.trim().length>0&&t.push(e.value),t.filter(e=>"string"==typeof e&&e.trim().length>0).join(" ").trim()}function pA(e){return e.some(e=>{let t=pI(e);return t.length>0&&pm.test(t)})}function pb(e){return new Promise(t=>setTimeout(t,e))}let pS=[255,59,48,255],p_=[255,214,10,255],pN=[0,0,0,255],pD={e:["01110","10000","11110","10000","10000","10001","01110"],0:["01110","10001","10011","10101","11001","10001","01110"],1:["00100","01100","00100","00100","00100","00100","01110"],2:["01110","10001","00001","00010","00100","01000","11111"],3:["11110","00001","00001","01110","00001","00001","11110"],4:["00010","00110","01010","10010","11111","00010","00010"],5:["11111","10000","10000","11110","00001","00001","11110"],6:["01110","10000","10000","11110","10001","10001","01110"],7:["11111","00001","00010","00100","01000","01000","01000"],8:["01110","10001","10001","01110","10001","10001","01110"],9:["01110","10001","10001","01111","00001","00001","01110"]};async function px(e){let t=ed(await d.readFile(e.screenshotPath),"screenshot"),r=function(e,t,r,a={}){let i=function(e){let t=null;for(let r of e)pM(r)&&pP(r.rect)&&(!t||pR(r.rect)>pR(t))&&(t=r.rect);return t||function(e){let t=1/0,r=1/0,a=-1/0,i=-1/0;for(let n of e)n.rect&&pP(n.rect)&&(t=Math.min(t,n.rect.x),r=Math.min(r,n.rect.y),a=Math.max(a,n.rect.x+n.rect.width),i=Math.max(i,n.rect.y+n.rect.height));return!Number.isFinite(t)||!Number.isFinite(r)||a<=t||i<=r?null:{x:t,y:r,width:a-t,height:i-r}}(e.filter(e=>{var t;return pP(e.rect)&&!("image"===dP((t=e).type??"")&&!pE(t.label))}))}(e.nodes),n=new Map;for(let a of e.nodes){if(!function(e){let t=[e.label,e.value].some(pO)||pL(e.identifier);return pk(e)?t:t&&function(e){let t=dP(e.type??"");return t.includes("statictext")||t.includes("image")||t.includes("text")||t.includes("other")}(e)}(a))continue;let o=function(e,t){if(function(e){return pk(e)&&!pM(e)}(t)&&pP(t.rect))return t;let r=function(e,t){let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){;a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(pk(t)&&!pM(t)&&pP(t.rect))return t;r=t}return null}(e,t);if(r?.rect&&pP(r.rect))return r;if(t.hittable&&pP(t.rect)&&!pM(t))return t;let a=dT(e,t);return a?.rect&&pP(a.rect)&&!pM(a)?a:null}(e.nodes,a);if(!o?.rect||!pP(o.rect))continue;let s=function(e,t,r){let a=pC(e);if(e.ref!==t.ref&&a)return a;let i=function(e,t){let r=null;for(let a of t){if(a.ref===e.ref||!function(e,t,r){let a=e;for(;void 0!==a.parentIndex;){let e=r[a.parentIndex];if(!e)break;if(e.ref===t.ref)return!0;a=e}return!1}(a,e,t))continue;let i=pC(a);if(!i)continue;let n=function(e){let t=0;return dP(e.type??"").includes("text")&&(t+=2),pO(e.label)&&(t+=2),pO(e.value)&&(t+=1),t}(a);(!r||n>r.score)&&(r={label:i,score:n})}return r?.label}(t,r);return i||(pC(t)??dO(t,r))}(a,o,e.nodes),l=function(e,t,r){let a=0;return e.ref===t.ref&&(a+=4),t.hittable&&(a+=3),pk(t)&&(a+=3),pk(e)&&(a+=2),r&&(a+=2),pL(t.identifier)&&(a+=1),pE(t.value)&&(a+=1),a}(a,o,s),d=function(e,t,r,a){if(!e)return pF({x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},r,a);let i=r/e.width,n=a/e.height;return pF({x:Math.round((t.x-e.x)*i),y:Math.round((t.y-e.y)*n),width:Math.max(1,Math.round(t.width*i)),height:Math.max(1,Math.round(t.height*n))},r,a)}(i,o.rect,t,r);if(!pP(d))continue;let u=n.get(o.ref);(!u||l>u.score)&&n.set(o.ref,{ref:o.ref,label:s,rect:o.rect,overlayRect:d,score:l})}return(function(e){let t=[];for(let r of e.sort((e,t)=>pR(e.overlayRect)-pR(t.overlayRect))){let e=t.findIndex(e=>e.label===r.label&&(pT(e.overlayRect,r.overlayRect)||pT(r.overlayRect,e.overlayRect)));if(-1===e){t.push(r);continue}pR(r.overlayRect)<pR(t[e].overlayRect)&&(t[e]=r)}return t})([...n.values()]).sort((e,t)=>{if(t.score!==e.score)return t.score-e.score;let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:p$(e.ref,t.ref)}).slice(0,a.maxRefs??24).sort((e,t)=>{let r=e.overlayRect.y-t.overlayRect.y;if(0!==r)return r;let a=e.overlayRect.x-t.overlayRect.x;return 0!==a?a:p$(e.ref,t.ref)}).map(e=>({ref:e.ref,label:e.label,rect:e.rect,overlayRect:e.overlayRect,center:dM(e.overlayRect)}))}(e.snapshot,t.width,t.height,{maxRefs:e.maxRefs});for(let e of r){var a,i;(function(e,t,r){for(let a=0;a<2;a+=1)pV(e,t.x,t.x+t.width-1,t.y+a,r),pV(e,t.x,t.x+t.width-1,t.y+t.height-1-a,r),pG(e,t.x+a,t.y,t.y+t.height-1,r),pG(e,t.x+t.width-1-a,t.y,t.y+t.height-1,r)})(a=t,(i=e).overlayRect,pS),function(e,t,r){let a=6+5*r.length+ +Math.max(0,r.length-1),i=pU(t.x,0,Math.max(0,e.width-a)),n=t.y-11-2,o=n>=0?n:pU(t.y+2,0,Math.max(0,e.height-11));(function(e,t,r,a,i){for(let n=0;n<11;n+=1)for(let o=0;o<a;o+=1)pj(e,t+o,r+n,i)})(e,i,o,a,p_),function(e,t,r,a,i){let n=t;for(let t of a.toLowerCase()){let a=pD[t];if(a)for(let t=0;t<a.length;t+=1)for(let o=0;o<a[t].length;o+=1)"1"===a[t][o]&&pj(e,n+o,r+t,i);n+=6}}(e,i+3,o+2,r,pN)}(a,i.overlayRect,i.ref)}return await d.writeFile(e.screenshotPath,b.sync.write(t)),r}function pk(e){let t=[e.type,e.role,e.subrole].map(e=>dP(e??"")).join(" ");return t.includes("button")||t.includes("link")||t.includes("menu")||t.includes("tab")||t.includes("textfield")||t.includes("searchfield")||t.includes("securetextfield")||t.includes("checkbox")||t.includes("radio")||t.includes("switch")||t.includes("cell")}function pM(e){let t=[e.type,e.role,e.subrole].map(e=>dP(e??"")).join(" ");return t.includes("application")||t.includes("window")}function pE(e){if("string"!=typeof e)return!1;let t=e.trim();return!(!t||/^(true|false)$/i.test(t))}function pO(e){var t;let r;return!!pE(e)&&(t=e,"toolbar"!==(r=t?.trim().toLowerCase())&&"window"!==r&&"application"!==r&&r?.startsWith("vertical scroll bar")!==!0)}function pL(e){var t;return"string"==typeof e&&!!pO(e)&&(t=e,!/^[a-z0-9_.]+:id\/[a-z0-9_.-]+$/i.test(t.trim()))}function pC(e){let t=[e.label,e.value].find(pO);return t?t.trim():pL(e.identifier)?e.identifier.trim():void 0}function pP(e){return!!(e&&e.width>0&&e.height>0)}function pR(e){return e.width*e.height}function pT(e,t){return t.x>=e.x&&t.y>=e.y&&t.x+t.width<=e.x+e.width&&t.y+t.height<=e.y+e.height}function p$(e,t){return Number.parseInt(e.replace(/^\D+/,""),10)-Number.parseInt(t.replace(/^\D+/,""),10)}function pF(e,t,r){let a=pU(e.x,0,Math.max(0,t-1)),i=pU(e.y,0,Math.max(0,r-1)),n=Math.max(1,t-a),o=Math.max(1,r-i);return{x:a,y:i,width:pU(e.width,1,n),height:pU(e.height,1,o)}}function pU(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function pV(e,t,r,a,i){for(let n=t;n<=r;n+=1)pj(e,n,a,i)}function pG(e,t,r,a,i){for(let n=r;n<=a;n+=1)pj(e,t,n,i)}function pj(e,t,r,a){if(t<0||r<0||t>=e.width||r>=e.height)return;let i=(e.width*r+t)*4;e.data[i]=a[0],e.data[i+1]=a[1],e.data[i+2]=a[2],e.data[i+3]=a[3]}let pB=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),pq=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function pH(e,t,r,a){let i=J().requestId;return{...sk(e,t,r,a,i),requestId:i}}function pW(e){s.existsSync(e)&&s.unlinkSync(e)}function pz(e){if(!s.existsSync(e))return null;try{let t=JSON.parse(s.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function pJ(e){let t=pz(e);if(!t||t.pid===process.pid)try{s.existsSync(e)&&s.unlinkSync(e)}catch{}}function pK(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:pX,infoPath:pY,lockPath:pZ,logPath:pQ,sessionsDir:p0}=ei(process.env.AGENT_DEVICE_STATE_DIR),p1=eo(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var p2=p0;if(s.existsSync(p2))for(let e of s.readdirSync(p2,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=c.join(p2,e.name,"app-log.pid");if(s.existsSync(t))try{let e=function(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}(s.readFileSync(t,"utf8"));if(e&&function(e){let t,r=er(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=S(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{ri(t)}}let p3=new rr(p0),p4=new rZ({maxActiveSimulatorLeases:pK(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:pK(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:pK(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:pK(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),p8=z(),p5=n.randomBytes(24).toString("hex"),p6=er(process.pid)??void 0,p9=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=s.statSync(e),r=Z(),a=c.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),p7=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:i,trackDownloadableArtifact:n}=e;async function o(e){let s=!!(e.meta?.debug||e.flags?.verbose);return await ea({session:e.session,requestId:e.meta?.requestId,command:e.command,debug:s,logPath:t},async()=>{if(e.token!==r)return{ok:!1,error:q(new $("UNAUTHORIZED","Invalid token"))};try{let r=function(e){let t=H(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=N(r);if(r&&!a)throw new $("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new $("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");let i=e.session||"default";return i.startsWith(`${a}:`)?{...e,meta:{...e.meta,tenantId:a,sessionIsolation:t}}:{...e,session:`${a}:${i}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(e);Q({level:"info",phase:"request_start",data:{session:r.session,command:r.command,tenant:r.meta?.tenantId,isolation:r.meta?.sessionIsolation}});let s=r.command,l=pd(r);pq.has(s)||r.meta?.sessionIsolation!=="tenant"||i.assertLeaseAdmission({tenantId:l.tenantId,runId:l.runId,leaseId:l.leaseId,backend:l.leaseBackend});let d=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(r,a),u=a.get(d);u&&(!function(e){var t,r;let a,i=e.recording;if(!i||"ios"!==e.device.platform)return;let n=(t=e.device.id,(a=tP.get(t))?{sessionId:a.sessionId,alive:!!(r=a.child.pid)&&et(r)}:null);if(!i.runnerSessionId){n?.alive&&(i.runnerSessionId=n.sessionId);return}if(!n?.alive){i.invalidatedReason??="iOS runner session exited during recording";return}n.sessionId!==i.runnerSessionId&&(i.invalidatedReason??="iOS runner session restarted during recording")}(u),a.set(d,u));let p=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?pc(t,a):function(e,t){var r,a;let i=[];for(let n of(void 0!==e.platform&&t&&(r=e.platform,a=t,r&&a&&r!==a&&("apple"===r?!ts(a):"apple"!==a||!ts(r)))&&i.push({key:"platform",value:e.platform}),pf)){let t=e[n];"string"==typeof t&&t.trim().length>0&&i.push({key:n,value:t})}return i}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of pf)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new $("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(pp).join(", ")}. Unset those selectors or remove the request lock policy.`)}(r,u),f=e=>(function(e,t,r){let a=J();if(!t.ok){Q({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=en({force:!0})??void 0;return{ok:!1,error:q(new $(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return Q({level:"info",phase:"request_success"}),en(),{ok:!0,data:function(e,t,r){var a,i;let n;if(!t)return t;let o=(a=e,i=t,n=Array.isArray(i.artifacts)?[...i.artifacts]:[],"screenshot"!==a.command||n.some(e=>e?.field==="path")||"string"!=typeof i.path||n.push({field:"path",path:i.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:c.basename(a.meta?.clientArtifactPaths?.path??i.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===o.length?t:{...t,artifacts:o.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(p,e,n);if(u?.recording?.invalidatedReason&&"record"!==s&&"close"!==s)return f({ok:!1,error:{code:"COMMAND_FAILED",message:u.recording.invalidatedReason}});!u||p.meta?.lockPolicy||pB.has(s)||function(e,t){let r=pc(e,t);if(0!==r.length){var a;let t,i,n;throw new $("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(pp).join(", ")}. Use a different --session name or close this session first.`)}}(u,p.flags);let m=await pu({req:p,leaseRegistry:i});if(m)return f(m);let h=await up({req:p,sessionName:d,logPath:t,sessionStore:a,invoke:o});if(h)return f(h);let w=await uP({req:p,sessionName:d,logPath:t,sessionStore:a});if(w)return f(w);let g=await cM({req:p,sessionName:d,sessionStore:a,logPath:t});if(g)return f(g);let y=await uz({req:p,sessionName:d,logPath:t,sessionStore:a,invoke:o});if(y)return f(y);let v=await pl({req:p,sessionName:d,sessionStore:a,contextFromFlags:(e,r,i)=>({...pH(t,e,r,i),surface:a.get(d)?.surface})});if(v)return f(v);let I=a.get(d);if(!I)return f({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!sx(s,I.device))return f({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${s} is not supported on this device`}});if("android"===I.device.platform&&I.recording&&"record"!==s){let e=await pw({session:I});if("failed"===e)return f({ok:!1,error:{code:"COMMAND_FAILED",message:"Android system dialog blocked the recording session"}})}let A=p.positionals??[],b=p.flags?.out,S="screenshot"===s&&A[0]?[rr.expandHome(A[0],p.meta?.cwd),...A.slice(1)]:A,_="screenshot"===s&&b?rr.expandHome(b,p.meta?.cwd):b,D="screenshot"===s?S:A,x="screenshot"===s&&_?{...p.flags??{},out:_}:p.flags??{},k=Date.now(),M={...pH(t,p.flags,I.appBundleId,I.trace?.outPath),surface:I.surface},E=await sI(I.device,s,S,_,{...M});if("screenshot"===s&&p.flags?.overlayRefs&&"string"==typeof E?.path){let e=await ug({device:I.device,session:I,flags:void 0,logPath:t,snapshotScope:void 0}),r=uy(e,!1);I.snapshot=r;let a=await px({screenshotPath:E.path,snapshot:r});E.overlayRefs=a}let O=Date.now(),L=function(e,t,r,a){if("scroll"!==t)return a;let i=cL(e.snapshot),n={...a??{}},o=cF(n.direction)??cF(r[0]);if(!o)return a;let s=cU(n.amount)??cU(r[1]),l=cU(n.pixels),d=cj(n,[]),u=cU(n.referenceWidth),c=cU(n.referenceHeight),p=void 0!==u&&u>0&&void 0!==c&&c>0?{referenceWidth:u,referenceHeight:c}:i??cP;if(d&&(d.x1!==d.x2||d.y1!==d.y2))return{...n,x1:d.x1,y1:d.y1,x2:d.x2,y2:d.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==l?{pixels:l}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250};let f=ig({direction:o,amount:s,pixels:l,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return{...n,x1:f.x1,y1:f.y1,x2:f.x2,y2:f.y2,contentDirection:o,...void 0!==s?{amount:s}:{},...void 0!==f.pixels?{pixels:f.pixels}:{},referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight,durationMs:250}}(I,s,S,E);return cR(I,s,S,L,p.flags??{},k,O),a.recordAction(I,{command:s,positionals:D,flags:x,result:E??{}}),f({ok:!0,data:E??{}})}catch(r){Q({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=J(),t=en({force:!0})??void 0;return{ok:!1,error:q(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return o}({logPath:pQ,token:p5,sessionStore:p3,leaseRegistry:p4,trackDownloadableArtifact:function(e){let t=n.randomUUID(),r=setTimeout(()=>{rb(t)},9e5);return r.unref(),rA.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){s.existsSync(e)||s.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return s.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=pz(t);if(n?.pid&&n.pid!==process.pid&&D(n.pid,n.processStartTime))return!1;try{s.unlinkSync(t)}catch{}return i()}(pX,pZ,{pid:process.pid,version:p8,startedAt:Date.now(),processStartTime:p6})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let i;if("socket"===p1||"dual"===p1){let t=p.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))eL(e);Q({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{try{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await tG(),!(r<=0));)await new Promise(e=>setTimeout(e,200))}catch(e){Q({level:"error",phase:"request_client_disconnect_abort_failed",data:{message:e instanceof Error?e.message:String(e),inFlightRequests:r}})}})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=eE(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),eO(o),eP(o))throw eT();i=await p7(e)}catch(e){i={ok:!1,error:q(e)}}finally{r-=1,o&&(a.delete(o),eC(o))}e.destroyed||e.write(`${JSON.stringify(i)}
67
+ `),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new $("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===p1||"dual"===p1){let e=await rH({handleRequest:p7,token:p5});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let a=e.address();"object"==typeof a&&a?.port?t(a.port):r(new $("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:p5,version:p8,codeSignature:p9,processStartTime:p6},s.existsSync(pX)||s.mkdirSync(pX,{recursive:!0}),s.writeFileSync(pQ,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",s.writeFileSync(pY,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:i,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:pX},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
66
68
  `),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
67
69
  `)}catch(t){let e=P(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
68
- `),r))try{t.close(()=>{})}catch{}fk(fR),fL(fT),process.exit(1);return}let i=!1,n=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!i){for(let e of(i=!0,await n(),fG.toArray()))fG.writeSessionLog(e);await tj(),fk(fR),fL(fT),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof $?e:P(e);process.stderr.write(`Daemon error: ${t.message}
70
+ `),r))try{t.close(()=>{})}catch{}pW(pY),pJ(pZ),process.exit(1);return}let i=!1,n=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!i){for(let e of(i=!0,await n(),p3.toArray()))p3.writeSessionLog(e);await tj(),pW(pY),pJ(pZ),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof $?e:P(e);process.stderr.write(`Daemon error: ${t.message}
69
71
  `),o()}),process.on("unhandledRejection",e=>{let t=e instanceof Error?e:Error(String(e)),r=t instanceof $?t:P(t);process.stderr.write(`Daemon error: ${r.message}
70
72
  `),o()})}();