agent-device 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/3918.js CHANGED
@@ -1,32 +1,33 @@
1
- let e;import{__webpack_require__ as t}from"./rslib-runtime.js";import n,{existsSync as a,promises as i}from"node:fs";import r,{hostname as o}from"node:os";import s from"node:path";import l from"node:net";import{AsyncLocalStorage as d}from"node:async_hooks";import{fileURLToPath as u}from"node:url";import{XMLParser as c}from"fast-xml-parser";import{createHash as p}from"node:crypto";import{asAppError as f,toAppErrorCode as m,AppError as h}from"./9152.js";import{splitSelectorFromArgs as w,tryParseSelectorChain as y,extractNodeReadText as g,splitIsSelectorArgs as I,pruneGroupNodes as A,findNodeByLabel as v,resolveRefLabel as b}from"./7847.js";import{createAgentDevice as _,getDiagnosticsMeta as S,localCommandPolicy as N,withDiagnosticTimer as x,emitDiagnostic as E}from"./8564.js";import{runCmdStreaming as D,runCmdDetached as M,runCmdBackground as C,runCmdSync as O,runCmd as L,resolveFileOverridePath as T,resolveExecutableOverridePath as k,whichCmd as R}from"./9818.js";import{sleep as P,resolveTimeoutMs as F,resolveTimeoutSeconds as $}from"./4829.js";import{resolveIosSimulatorDeviceSetPath as U,buildSimctlArgs as G,classifyAndroidAppTarget as V,adbArgs as B,ensureAdb as j,resolveAndroidSerialAllowlist as q,isClipboardShellUnsupported as W,buildSimctlArgsForDevice as H}from"./9323.js";import{isProcessAlive as K,readProcessStartTime as z}from"./3883.js";import{ensureAndroidSdkPathConfigured as J}from"./8164.js";import{materializeInstallablePath as X,isTrustedInstallSourceUrl as Y}from"./989.js";import{resolveAndroidArchivePackageName as Z}from"./7651.js";import{parseAndroidForegroundApp as Q,parseAndroidLaunchablePackages as ee,parseAndroidUserInstalledPackages as et}from"./9366.js";import{deriveMobileSnapshotHiddenContentHints as en,normalizeSnapshotTree as ea,requireIntInRange as ei,successText as er,isSupportedPredicate as eo,withSuccessText as es,isScrollableType as el}from"./9076.js";import{findNodeByRef as ed,centerOfRect as eu,normalizeRef as ec,attachRefs as ep}from"./4057.js";import{parseFindArgs as ef}from"./7556.js";var em={};t.r(em),t.d(em,{ensureAndroidEmulatorBooted:()=>n4,listAndroidDevices:()=>nZ,waitForAndroidBoot:()=>n5});var eh={};t.r(eh),t.d(eh,{TM:()=>rF,ensureBootedSimulator:()=>iJ,installIosApp:()=>rU,installIosInstallablePath:()=>rV,listIosApps:()=>rH,L5:()=>rR,IJ:()=>rP,TJ:()=>rq,J7:()=>rB,reinstallIosApp:()=>rG,resolveIosApp:()=>rk,kc:()=>rI,Cm:()=>rW,ap:()=>rj});let ew="<wifi|airplane|location> <on|off>",ey="animations <on|off>",eg="appearance <light|dark|toggle>",eI="faceid <match|nonmatch|enroll|unenroll>",eA="touchid <match|nonmatch|enroll|unenroll>",ev="fingerprint <match|nonmatch>",eb="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",e_="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",eS=`macOS supports only settings ${eg} and settings ${e_}. wifi|airplane|location|animations remain unsupported on macOS.`,eN=`settings ${ew} | settings ${ey} | settings ${eg} | settings ${eI} | settings ${eA} | settings ${ev} | settings ${eb} | settings ${e_}`,ex=`settings requires ${ew}, ${ey}, ${eg}, ${eI}, ${eA}, ${ev}, ${eb}, or ${e_}`;function eE(e){return`Unsupported macOS setting: ${e}. ${eS}`}let eD=["app","frontmost-app","desktop","menubar"];function eM(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new h("INVALID_ARGS",`Invalid surface: ${e}. Use ${eD.join("|")}.`)}let eC=100,eO=new Set(["batch","replay"]),eL=new Set(["command","positionals","flags","runtime"]);function eT(e){let t;try{t=JSON.parse(e)}catch{throw new h("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(t)||0===t.length)throw new h("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return t}function ek(e,t){if(!Array.isArray(e)||0===e.length)throw new h("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>t)throw new h("INVALID_ARGS",`batch has ${e.length} steps; max allowed is ${t}.`);let n=[];for(let t=0;t<e.length;t+=1){let a=e[t];if(!a||"object"!=typeof a)throw new h("INVALID_ARGS",`Invalid batch step at index ${t}.`);let i=Object.keys(a).filter(e=>!eL.has(e));if(i.length>0){let e=i.map(e=>`"${e}"`).join(", ");throw new h("INVALID_ARGS",`Batch step ${t+1} has unknown field(s): ${e}. Allowed fields: command, positionals, flags, runtime.`)}let r="string"==typeof a.command?a.command.trim().toLowerCase():"";if(!r)throw new h("INVALID_ARGS",`Batch step ${t+1} requires command.`);if(eO.has(r))throw new h("INVALID_ARGS",`Batch step ${t+1} cannot run ${r}.`);if(void 0!==a.positionals&&!Array.isArray(a.positionals))throw new h("INVALID_ARGS",`Batch step ${t+1} positionals must be an array.`);let o=a.positionals??[];if(o.some(e=>"string"!=typeof e))throw new h("INVALID_ARGS",`Batch step ${t+1} positionals must contain only strings.`);if(void 0!==a.flags&&("object"!=typeof a.flags||Array.isArray(a.flags)||!a.flags))throw new h("INVALID_ARGS",`Batch step ${t+1} flags must be an object.`);if(void 0!==a.runtime&&("object"!=typeof a.runtime||Array.isArray(a.runtime)||!a.runtime))throw new h("INVALID_ARGS",`Batch step ${t+1} runtime must be an object.`);n.push({command:r,positionals:o,flags:a.flags??{},runtime:a.runtime})}return n}function eR(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function eP(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function eF(e){if(0===e.length)return null;let t=eP(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=eP(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=eP(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let n=eP(e[e.length-1]),a=w(null!==n?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=y(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:n}}return{kind:"text",text:(null!==n?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:n}}function e$(e){return e}function eU(e){return"apple"===e||"ios"===e||"macos"===e}function eG(e,t){return!t||("apple"===t?eU(e):e===t)}function eV(e){let{simulatorSetPath:t,platform:n,target:a}=e;if(t&&"macos"!==n&&"desktop"!==a)return t}async function eB(e,t,n={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>eG(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&&eU(e.platform));if(!e)throw new h("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 h("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),n=a.find(t=>i(t.name)===e);if(!n)throw new h("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return n}if(1===a.length)return a[0];if(0===a.length){var r;let e=n.simulatorSetPath;if(e&&(!(r=t.platform)||"apple"===r||"ios"===r))throw new h("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:
2
- xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new h("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 ej=e=>"macos"!==e.platform,eq=e=>"macos"===e.platform||"simulator"===e.kind,eW={device:!0},eH={},eK={alert:{apple:{simulator:!0,device:!0},android:{},linux:eH,supports:eq},pinch:{apple:{simulator:!0,device:!0},android:{},linux:eH,supports:eq},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW,supports:e=>"android"===e.platform||"linux"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW,supports:ej},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:ej},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eH},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eW}};function ez(e,t){let n=eK[e];if(!n)return!0;let a=eU(t.platform)?n.apple:"linux"===t.platform?n.linux:n.android;return!!a&&(!n.supports||!!n.supports(t))&&!0===a[t.kind??"unknown"]}let eJ=eX(process.env.AGENT_DEVICE_RETRY_LOGS);function eX(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}let eY=2e4,eZ=12e4,eQ=1e4;class e0{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new e0(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 e1(e,t={},n={}){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(n.signal?.aborted)throw new h("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(n.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:n.deadline});return n.onEvent?.({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),e3({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),a}catch(d){a=d;let e=n.classifyReason?.(d),r={phase:n.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};if(n.onEvent?.(r),e3(r),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,n,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*n*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=n.deadline?Math.min(o,n.deadline.remainingMs()):o;if(s<=0)break;let l={phase:n.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};n.onEvent?.(l),e3(l),await function(e,t){return new Promise(n=>{if(t?.aborted)return void n();let a=!1,i=()=>{a||(a=!0,t&&t.removeEventListener("abort",o),n())},r=setTimeout(i,e);function o(){clearTimeout(r),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,n.signal)}}let r={phase:n.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:n.classifyReason?.(a)};if(n.onEvent?.(r),e3(r),a)throw a;throw new h("COMMAND_FAILED","retry failed")}async function e2(e,t={}){return e1(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function e3(e){E({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eJ&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
3
- `)}let e4=new Set,e5=new Map,e8="request_canceled",e6="request canceled";function e9(e,t){if("string"==typeof e&&e.length>0)return e;let n=("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:${n}:${process.pid}:${Date.now()}:${a}`}function e7(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let n of e.keys()){if(t>=1e4)break;e.delete(n),t++}}(e5);let t=new AbortController;e5.set(e,t),e4.has(e)&&t.abort()}function te(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let n of e){if(t>=1e4)break;e.delete(n),t++}}(e4),e4.add(e),e5.get(e)?.abort())}function tt(e){e&&(e4.delete(e),e5.delete(e))}function tn(e){return!!e&&e4.has(e)}function ta(e){if(e)return e5.get(e)?.signal}function ti(){return new h("COMMAND_FAILED",e6,{reason:e8})}function tr(e){return e instanceof h&&"COMMAND_FAILED"===e.code&&(e.details?.reason===e8||e.message===e6)}function to(e){let t=e.error?f(e.error):null,n=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===n?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},r="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,r,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"===n&&(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"===n&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===n&&"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"===n&&(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 ts(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."}}function tl(e){return!(e instanceof h)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function td(e){let{port:t,endpoints:n,logPath:a,lastError:i}=e,r="Runner did not accept connection";return new h("COMMAND_FAILED",r,{port:t,endpoints:n,logPath:a,lastError:i?String(i):void 0,reason:to({error:i,message:r,context:{platform:"ios",phase:"connect"}}),hint:ts("IOS_RUNNER_CONNECT_TIMEOUT")})}async function tu(e){var t,n;let a,{session:i,port:r,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=to({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new h("COMMAND_FAILED",l,{port:r,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,n=s.stderr,(a=`${l}
1
+ let e;import{__webpack_require__ as t}from"./rslib-runtime.js";import n,{existsSync as a,promises as i}from"node:fs";import r,{hostname as o}from"node:os";import s from"node:path";import l from"node:net";import{AsyncLocalStorage as d}from"node:async_hooks";import{fileURLToPath as u}from"node:url";import{XMLParser as c}from"fast-xml-parser";import{createHash as p}from"node:crypto";import{asAppError as f,toAppErrorCode as m,AppError as h}from"./9152.js";import{splitSelectorFromArgs as w,tryParseSelectorChain as y,extractNodeReadText as g,splitIsSelectorArgs as I,pruneGroupNodes as A,findNodeByLabel as v,resolveRefLabel as b}from"./7847.js";import{createAgentDevice as _,getDiagnosticsMeta as S,localCommandPolicy as N,withDiagnosticTimer as x,emitDiagnostic as E}from"./8564.js";import{runCmdStreaming as D,runCmdDetached as M,runCmdBackground as C,runCmdSync as O,runCmd as L,resolveFileOverridePath as T,resolveExecutableOverridePath as k,whichCmd as R}from"./9818.js";import{sleep as P,resolveTimeoutMs as F,resolveTimeoutSeconds as $}from"./4829.js";import{isProcessAlive as U,readProcessStartTime as G}from"./8656.js";import{ensureAndroidSdkPathConfigured as V,resolveAndroidArchivePackageName as B}from"./7651.js";import{materializeInstallablePath as j,isTrustedInstallSourceUrl as q}from"./989.js";import{parseAndroidForegroundApp as W,parseAndroidLaunchablePackages as H,parseAndroidUserInstalledPackages as z}from"./9366.js";import{deriveMobileSnapshotHiddenContentHints as K,normalizeSnapshotTree as J,requireIntInRange as X,successText as Y,isSupportedPredicate as Z,withSuccessText as Q,isScrollableType as ee}from"./9076.js";import{findNodeByRef as et,centerOfRect as en,normalizeRef as ea,attachRefs as ei}from"./4057.js";import{parseFindArgs as er}from"./7556.js";var eo={};t.r(eo),t.d(eo,{ensureAndroidEmulatorBooted:()=>n9,listAndroidDevices:()=>n2,waitForAndroidBoot:()=>n7});var es={};t.r(es),t.d(es,{TM:()=>rW,ensureBootedSimulator:()=>i3,installIosApp:()=>rz,installIosInstallablePath:()=>rJ,listIosApps:()=>r0,L5:()=>rj,IJ:()=>rq,TJ:()=>rZ,J7:()=>rX,reinstallIosApp:()=>rK,resolveIosApp:()=>rB,kc:()=>rE,Cm:()=>rQ,ap:()=>rY});let el="<wifi|airplane|location> <on|off>",ed="animations <on|off>",eu="appearance <light|dark|toggle>",ec="faceid <match|nonmatch|enroll|unenroll>",ep="touchid <match|nonmatch|enroll|unenroll>",ef="fingerprint <match|nonmatch>",em="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",eh="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",ew=`macOS supports only settings ${eu} and settings ${eh}. wifi|airplane|location|animations remain unsupported on macOS.`,ey=`settings ${el} | settings ${ed} | settings ${eu} | settings ${ec} | settings ${ep} | settings ${ef} | settings ${em} | settings ${eh}`,eg=`settings requires ${el}, ${ed}, ${eu}, ${ec}, ${ep}, ${ef}, ${em}, or ${eh}`;function eI(e){return`Unsupported macOS setting: ${e}. ${ew}`}let eA=["app","frontmost-app","desktop","menubar"];function ev(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new h("INVALID_ARGS",`Invalid surface: ${e}. Use ${eA.join("|")}.`)}let eb=100,e_=new Set(["batch","replay"]),eS=new Set(["command","positionals","flags","runtime"]);function eN(e){let t;try{t=JSON.parse(e)}catch{throw new h("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(t)||0===t.length)throw new h("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return t}function ex(e,t){if(!Array.isArray(e)||0===e.length)throw new h("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>t)throw new h("INVALID_ARGS",`batch has ${e.length} steps; max allowed is ${t}.`);let n=[];for(let t=0;t<e.length;t+=1){let a=e[t];if(!a||"object"!=typeof a)throw new h("INVALID_ARGS",`Invalid batch step at index ${t}.`);let i=Object.keys(a).filter(e=>!eS.has(e));if(i.length>0){let e=i.map(e=>`"${e}"`).join(", ");throw new h("INVALID_ARGS",`Batch step ${t+1} has unknown field(s): ${e}. Allowed fields: command, positionals, flags, runtime.`)}let r="string"==typeof a.command?a.command.trim().toLowerCase():"";if(!r)throw new h("INVALID_ARGS",`Batch step ${t+1} requires command.`);if(e_.has(r))throw new h("INVALID_ARGS",`Batch step ${t+1} cannot run ${r}.`);if(void 0!==a.positionals&&!Array.isArray(a.positionals))throw new h("INVALID_ARGS",`Batch step ${t+1} positionals must be an array.`);let o=a.positionals??[];if(o.some(e=>"string"!=typeof e))throw new h("INVALID_ARGS",`Batch step ${t+1} positionals must contain only strings.`);if(void 0!==a.flags&&("object"!=typeof a.flags||Array.isArray(a.flags)||!a.flags))throw new h("INVALID_ARGS",`Batch step ${t+1} flags must be an object.`);if(void 0!==a.runtime&&("object"!=typeof a.runtime||Array.isArray(a.runtime)||!a.runtime))throw new h("INVALID_ARGS",`Batch step ${t+1} runtime must be an object.`);n.push({command:r,positionals:o,flags:a.flags??{},runtime:a.runtime})}return n}function eE(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function eD(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function eM(e){if(0===e.length)return null;let t=eD(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=eD(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=eD(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let n=eD(e[e.length-1]),a=w(null!==n?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=y(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:n}}return{kind:"text",text:(null!==n?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:n}}function eC(e){return e}function eO(e){return"apple"===e||"ios"===e||"macos"===e}function eL(e,t){return!t||("apple"===t?eO(e):e===t)}function eT(e){let{simulatorSetPath:t,platform:n,target:a}=e;if(t&&"macos"!==n&&"desktop"!==a)return t}async function ek(e,t,n={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>eL(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&&eO(e.platform));if(!e)throw new h("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 h("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),n=a.find(t=>i(t.name)===e);if(!n)throw new h("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return n}if(1===a.length)return a[0];if(0===a.length){var r;let e=n.simulatorSetPath;if(e&&(!(r=t.platform)||"apple"===r||"ios"===r))throw new h("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:
2
+ xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new h("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 eR=e=>"macos"!==e.platform,eP=e=>"macos"===e.platform||"simulator"===e.kind,eF={device:!0},e$={},eU={alert:{apple:{simulator:!0,device:!0},android:{},linux:e$,supports:eP},pinch:{apple:{simulator:!0,device:!0},android:{},linux:e$,supports:eP},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF,supports:e=>"android"===e.platform||"linux"===e.platform||"macos"===e.platform||"simulator"===e.kind},keyboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},close:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF,supports:eR},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:eR},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:e=>"android"===e.platform||"ios"===e.platform&&"tv"!==e.target},screenshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$,supports:e=>"android"===e.platform||"macos"===e.platform||"simulator"===e.kind},snapshot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:e$},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eF}};function eG(e,t){let n=eU[e];if(!n)return!0;let a=eO(t.platform)?n.apple:"linux"===t.platform?n.linux:n.android;return!!a&&(!n.supports||!!n.supports(t))&&!0===a[t.kind??"unknown"]}let eV=eB(process.env.AGENT_DEVICE_RETRY_LOGS);function eB(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}let ej=2e4,eq=12e4,eW=1e4;class eH{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new eH(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 ez(e,t={},n={}){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(n.signal?.aborted)throw new h("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(n.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:n.deadline});return n.onEvent?.({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),eJ({phase:n.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs()}),a}catch(d){a=d;let e=n.classifyReason?.(d),r={phase:n.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};if(n.onEvent?.(r),eJ(r),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,n,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*n*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=n.deadline?Math.min(o,n.deadline.remainingMs()):o;if(s<=0)break;let l={phase:n.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:e};n.onEvent?.(l),eJ(l),await function(e,t){return new Promise(n=>{if(t?.aborted)return void n();let a=!1,i=()=>{a||(a=!0,t&&t.removeEventListener("abort",o),n())},r=setTimeout(i,e);function o(){clearTimeout(r),i()}t&&t.addEventListener("abort",o,{once:!0})})}(s,n.signal)}}let r={phase:n.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:n.deadline?.elapsedMs(),remainingMs:n.deadline?.remainingMs(),reason:n.classifyReason?.(a)};if(n.onEvent?.(r),eJ(r),a)throw a;throw new h("COMMAND_FAILED","retry failed")}async function eK(e,t={}){return ez(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eJ(e){E({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eV&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
3
+ `)}let eX=new Set,eY=new Map,eZ="request_canceled",eQ="request canceled";function e0(e,t){if("string"==typeof e&&e.length>0)return e;let n=("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:${n}:${process.pid}:${Date.now()}:${a}`}function e1(e){if(!e)return;!function(e){if(e.size<=5e4)return;let t=0;for(let n of e.keys()){if(t>=1e4)break;e.delete(n),t++}}(eY);let t=new AbortController;eY.set(e,t),eX.has(e)&&t.abort()}function e2(e){e&&(!function(e){if(e.size<=5e4)return;let t=0;for(let n of e){if(t>=1e4)break;e.delete(n),t++}}(eX),eX.add(e),eY.get(e)?.abort())}function e3(e){e&&(eX.delete(e),eY.delete(e))}function e4(e){return!!e&&eX.has(e)}function e5(e){if(e)return eY.get(e)?.signal}function e8(){return new h("COMMAND_FAILED",eQ,{reason:eZ})}function e6(e){return e instanceof h&&"COMMAND_FAILED"===e.code&&(e.details?.reason===eZ||e.message===eQ)}function e9(e){let t=e.error?f(e.error):null,n=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===n?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},r="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,r,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"===n&&(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"===n&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===n&&"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"===n&&(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 e7(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 te=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],tt=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function tn(e){return e?.trim()||void 0}function ta(e,t){for(let n of e){let e=tn(t[n]);if(e)return e}}function ti(e,t=process.env){return tn(e)??ta(te,t)}function tr(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function to(e,t=process.env){let n=tn(e)??ta(tt,t);if(n)return tr(n)}function ts(e,t={}){let n=ti(t.simulatorSetPath);return n?["simctl","--set",n,...e]:["simctl",...e]}function tl(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:ts(t,{simulatorSetPath:e.simulatorSetPath})}function td(e){return!(e instanceof h)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function tu(e){let{port:t,endpoints:n,logPath:a,lastError:i}=e,r="Runner did not accept connection";return new h("COMMAND_FAILED",r,{port:t,endpoints:n,logPath:a,lastError:i?String(i):void 0,reason:e9({error:i,message:r,context:{platform:"ios",phase:"connect"}}),hint:e7("IOS_RUNNER_CONNECT_TIMEOUT")})}async function tc(e){var t,n;let a,{session:i,port:r,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=e9({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new h("COMMAND_FAILED",l,{port:r,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,n=s.stderr,(a=`${l}
4
4
  ${t}
5
- ${n}`.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.":ts("IOS_RUNNER_CONNECT_TIMEOUT"))})}function tc(e){if(tn(e))throw ti()}let tp=F(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),tf=F(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),tm=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),th=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),tw=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),ty=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),tg=F(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),tI=$(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function tA(e,t,n,a,i=tp,r,o){let s=e0.fromTimeoutMs(i),l=await tv(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/tm));try{return await e1(async({deadline:s})=>{if(s?.isExpired())throw new h("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(r&&null!==r.child.exitCode&&void 0!==r.child.exitCode)throw await tu({session:r,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await tv(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new h("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await tb(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)},Math.min(ty,e),o)}catch(e){if(o?.aborted||tr(e))throw ti();d=e}throw new h("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:th,maxDelayMs:tw,jitter:.2,shouldRetry:tl},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||tr(e))throw ti();d||(d=e)}if(o?.aborted)throw ti();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw td({port:t,endpoints:l,logPath:a,lastError:d});let r=await tS(e,t,n,i);return new Response(r.body,{status:r.status})}throw td({port:t,endpoints:l,logPath:a,lastError:d})}async function tv(e,t,n){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await t_(e.id,n);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function tb(e,t,n,a){let i,r=new AbortController,o=setTimeout(()=>r.abort(),n);a&&(a.aborted?(clearTimeout(o),r.abort()):(i=()=>r.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:r.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function t_(e,t){if("number"==typeof t&&t<=0)return null;let a="number"==typeof t?Math.max(1,Math.min(tg,t)):tg,i=s.join(r.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(a/1e3)),r=await L("xcrun",["devicectl","device","info","details","--device",e,"--json-output",i,"--timeout",String(t)],{allowFailure:!0,timeoutMs:a});if(0!==r.exitCode||!n.existsSync(i))return null;let o=JSON.parse(n.readFileSync(i,"utf8"));if(o.info?.outcome&&"success"!==o.info.outcome)return null;let s=(o.result?.connectionProperties?.tunnelIPAddress??o.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return s&&s.length>0?s:null}catch{return null}finally{tE(i)}}async function tS(e,t,n,a){let i=JSON.stringify(n),r=H(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 L("xcrun",r,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=to({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new h("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:ts(e)})}return{status:200,body:s}}async function tN(){return await new Promise((e,t)=>{let n=l.createServer();n.listen(0,"127.0.0.1",()=>{let a=n.address();if("object"==typeof a&&a?.port){let t=a.port;n.close(()=>e(t))}else n.close(()=>t(new h("COMMAND_FAILED","Failed to allocate port")))}),n.on("error",t)})}function tx(e,t,a,i){t&&n.appendFile(t,e,()=>{}),a&&n.appendFile(a,e,()=>{}),i&&process.stderr.write(e)}function tE(e){try{n.existsSync(e)&&n.unlinkSync(e)}catch{}}let tD=new d;async function tM(e,t,n){let a=tD.getStore()??[];if(a.some(n=>n.locks===e&&n.key===t))return await n();let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(()=>tD.run([...a,{locks:e,key:t}],n));return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}let tC=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tO(e,t,a){if("macos"!==e.platform)return;if(0===t.length)throw new h("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:a});let i=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of i)if(!n.existsSync(e))throw new h("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:a});for(let e of i)if(0!==O("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await L("codesign",["--remove-signature",e],{allowFailure:!0});try{await L("codesign",["--force","--sign","-",e])}catch(n){let t=n instanceof h?n:new h("COMMAND_FAILED",String(n));throw new h("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:a,error:t.message,details:t.details})}}}let tL=null;function tT(e){return function e(t){if(!Array.isArray(t))return[];let n=[];for(let a of t)if(!(!a||"object"!=typeof a||Array.isArray(a)))for(let[t,i]of Object.entries(a))":@"!==t&&"#text"!==t&&n.push({name:t,attributes:function(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[n,a]of Object.entries(e))"string"==typeof a&&(t[n]=a);return t}(a[":@"]),text:tR(i)??tR(a["#text"]),children:e(i)});return n}((tL??=new c({ignoreAttributes:!1,attributeNamePrefix:"",preserveOrder:!0,trimValues:!0,parseTagValue:!1})).parse(e))}function tk(e,t){for(let n of e){if("dict"===n.name)for(let e=0;e<n.children.length-1;e+=1){let a=n.children[e],i=n.children[e+1];a?.name==="key"&&a.text&&i&&t(a.text,i)}tk(n.children,t)}}function tR(e){if("string"==typeof e){let t=e.trim();return t.length>0?t:null}if(!Array.isArray(e))return null;let t=e.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return null;let t=e["#text"];return"string"==typeof t?t.trim():null}).filter(e=>null!==e&&e.length>0).join("").trim();return t.length>0?t:null}let tP="XCTestDevices",tF=".agent-device-backup",t$=".agent-device-xctestdevices-backup-",tU=s.join(r.homedir(),".agent-device","ios-runner"),tG=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),tV=new Map,tB=new Set;function tj(e){return e?.trim()??""}function tq(e=process.env){return tj(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tj(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tW(e=process.env){let t=tj(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tq(e)}.uitests`}let tH=function(e=process.env){let t=tq(e),n=tW(e);return Array.from(new Set([tj(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${n}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function tK(e=r.homedir()){return s.join(e,"Library","Developer","XCTestDevices")}async function tz(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let a=U(e.simulatorSetPath);if(!a)return null;let i=s.resolve(a),o=s.resolve(t.xctestDeviceSetPath??tK()),l=s.resolve(t.backupPath??function(e=tK()){return`${e}${tF}`}(o)),d=s.resolve(t.lockDirPath??function(e=r.homedir()){return s.join(e,".agent-device","xctest-device-set.lock")}()),u=t.ownerStartTime??z(process.pid),c=await tY({lockDirPath:d,owner:{pid:t.ownerPid??process.pid,startTime:u,acquiredAtMs:t.nowMs??Date.now()}});try{if(tJ({xctestDeviceSetPath:o,backupPath:l}),function(e,t){if(s.resolve(e)===s.resolve(t))return!0;try{return n.realpathSync.native(e)===n.realpathSync.native(t)}catch{return!1}}(i,o))return await c(),null;n.mkdirSync(i,{recursive:!0}),n.existsSync(o)&&n.renameSync(o,l),function(e){let{requestedSetPath:t,xctestDeviceSetPath:a}=e,i=s.dirname(a),r=s.join(i,`${tP}.agent-device-link-${process.pid}-${Date.now()}`);n.mkdirSync(i,{recursive:!0});try{n.symlinkSync(t,r,"dir"),n.renameSync(r,a)}catch(e){throw n.existsSync(r)&&tX(r),e}}({requestedSetPath:i,xctestDeviceSetPath:o})}catch(e){throw tJ({xctestDeviceSetPath:o,backupPath:l}),await c(),new h("COMMAND_FAILED","Failed to redirect XCTest device set path",{requestedSetPath:i,xctestDeviceSetPath:o,backupPath:l,error:String(e)})}let p=!1;return{release:async()=>{if(!p){p=!0;try{tJ({xctestDeviceSetPath:o,backupPath:l})}finally{await c()}}}}}function tJ(e){let{xctestDeviceSetPath:t,backupPath:a}=e,i=[a,...function(e){let t=s.dirname(e),a=s.basename(e).replace(tF,""),i=a===tP?t$:`${a}${t$}`;try{return n.readdirSync(t).filter(e=>e.startsWith(i)).sort().map(e=>s.join(t,e))}catch{return[]}}(a)],r=i.find(e=>n.existsSync(e)),o=n.existsSync(t)&&n.lstatSync(t).isSymbolicLink();if(r){if(o&&tX(t),n.existsSync(t))if(!o)return void E({level:"warn",phase:"ios_runner_xctest_device_set_restore_collision",data:{xctestDeviceSetPath:t,activeBackupPath:r}});else r!==a?n.rmSync(r,{recursive:!0,force:!0}):n.rmSync(a,{recursive:!0,force:!0});else n.mkdirSync(s.dirname(t),{recursive:!0}),n.renameSync(r,t);for(let e of i)e!==r&&n.existsSync(e)&&n.rmSync(e,{recursive:!0,force:!0});return}o&&(E({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),tX(t))}function tX(e){!n.existsSync(e)||n.lstatSync(e).isSymbolicLink()&&n.unlinkSync(e)}async function tY(e){let{lockDirPath:t,owner:a}=e,i=s.join(t,"owner.json"),r=Date.now()+3e4;for(n.mkdirSync(s.dirname(t),{recursive:!0});Date.now()<r;)try{n.mkdirSync(t),function(e,t){let a=`${e}.${process.pid}.${Date.now()}.tmp`;n.writeFileSync(a,JSON.stringify(t),"utf8"),n.renameSync(a,e)}(i,a);let e=!1;return async()=>{e||(e=!0,n.rmSync(t,{recursive:!0,force:!0}))}}catch(e){if("EEXIST"!==e.code)throw e;if(function(e,t){let a=null;try{a=n.statSync(e)}catch{return!0}let i=function(e){try{return JSON.parse(n.readFileSync(e,"utf8"))}catch{return null}}(t);if(i){var r;return!(Number.isInteger((r=i).pid)&&!(r.pid<=0)&&K(r.pid)&&(!r.startTime||z(r.pid)===r.startTime))&&(n.rmSync(e,{recursive:!0,force:!0}),!0)}return!(Date.now()-a.mtimeMs<5e3)&&(n.rmSync(e,{recursive:!0,force:!0}),!0)}(t,i))continue;await P(100)}throw new h("COMMAND_FAILED","Timed out waiting for XCTest device set lock",{lockDirPath:t})}async function tZ(e,t){var a;let i,r=(a=e,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?s.resolve(i):"macos"===a.platform?s.join(tU,"derived","macos"):"simulator"===a.kind?s.join(tU,"derived"):s.join(tU,"derived",a.kind)),o=function(){let e=s.dirname(u(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=s.join(t,"package.json");if(n.existsSync(e))return t;t=s.dirname(t)}return e}();return await tM(tV,r,async()=>{eX(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(ne("clean","forced_clean",{derived:r}),t7(r),tQ(r));let a=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let n=e.resolveExistingXctestrunProductPaths(t);return n?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:n}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:n}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:r,projectRoot:o,findXctestrun:t=>t1(t,e),xctestrunReferencesProjectRoot:t3,resolveExistingXctestrunProductPaths:nt});if("reuse_ready"!==a.reason&&ne("rebuild",a.reason,{derived:r,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await tO(e,a.productPaths,a.xctestrunPath),ne("reuse","reuse_ready",{derived:r,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof h))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;ne("rebuild","repair_failed",{derived:r,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(t7(r),tQ(r));let i=s.join(o,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!n.existsSync(i))throw new h("COMMAND_FAILED","iOS runner project not found",{projectPath:i});await t5(e,i,r,t);let l=t1(r,e);if(!l)throw new h("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=nt(l);if(!d)throw new h("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await tO(e,d,l),ne("build","built_new",{derived:r,xctestrunPath:l}),l})}function tQ(e){try{if(!n.existsSync(e))return;if("derived"!==s.basename(e))return void n.rmSync(e,{recursive:!0,force:!0});for(let a of n.readdirSync(e,{withFileTypes:!0})){var t;t=a.name,t0.has(t)&&n.rmSync(s.join(e,a.name),{recursive:!0,force:!0})}}catch{}}let t0=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function t1(e,t){if(!n.existsSync(e))return null;let a=[],i=[e];for(;i.length>0;){let e=i.pop();for(let t of n.readdirSync(e,{withFileTypes:!0})){let r=s.join(e,t.name);if(t.isDirectory()){i.push(r);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=n.statSync(r);a.push({path:r,mtimeMs:e.mtimeMs})}catch{}}}return 0===a.length?null:(a.sort((e,n)=>{if(t){let a=t2(n.path,t)-t2(e.path,t);if(0!==a)return a}return n.mtimeMs-e.mtimeMs||e.path.localeCompare(n.path)}),a[0]?.path??null)}function t2(e,t){var n;let a=0,i=e.toLowerCase();s.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${s.sep}macos${s.sep}`)&&(a-=5e3);let r="macos"===(n=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===n.target?"simulator"===n.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===n.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return r.preferred.length>0&&(r.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),r.disallowed.some(e=>i.includes(e))&&(a-=2500),a}function t3(e,t){try{let a=n.readFileSync(e,"utf8"),i=new Set([t]);try{i.add(n.realpathSync(t))}catch{}for(let e of i)if(a.includes(e))return!0;return!1}catch{return!1}}async function t4(e,t,a){let i,r=s.dirname(e),o=a.replace(/[^a-zA-Z0-9._-]/g,"_"),l=s.join(r,`AgentDeviceRunner.env.${o}.json`),d=s.join(r,`AgentDeviceRunner.env.${o}.xctestrun`),u=await L("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==u.exitCode||!u.stdout.trim())throw new h("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:u.stderr});try{let e=JSON.parse(u.stdout);if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Root must be an object");i=e}catch(t){throw new h("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let c=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},p=i.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&&c(e)}for(let[e,t]of Object.entries(i))t&&"object"==typeof t&&!Array.isArray(t)&&t.TestBundlePath&&(c(t),i[e]=t);n.writeFileSync(l,JSON.stringify(i,null,2));let f=await L("plutil",["-convert","xml1","-o",d,l],{allowFailure:!0});if(0!==f.exitCode)throw new h("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:d,stderr:f.stderr});return{xctestrunPath:d,jsonPath:l}}async function t5(e,t,n,a){let i=function(e=process.env){let t=tq(e),n=tW(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${n}`]}(process.env),r=function(e=process.env,t=!1,n="ios"){if("macos"===n)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()||"",r=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}`),r&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${r}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[],s=await tz(e);try{var l;let s;await D("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",t9(e),"1","-destination",(l=e,s=t8(l),"macOS"===s?`platform=macOS,arch=${t6()}`:"simulator"===l.kind?`platform=${s} Simulator,id=${l.id}`:`generic/platform=${s}`),"-derivedDataPath",n,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...r],{detached:!0,onSpawn:e=>{tB.add(e),e.on("close",()=>{tB.delete(e)})},onStdoutChunk:e=>{tx(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{tx(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(r){let e,t,n=r instanceof h?r:new h("COMMAND_FAILED",String(r)),i=(e=n.details?JSON.stringify(n.details):"",(t=`${n.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 h("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:n.message,details:n.details,logPath:a.logPath,hint:i})}finally{await s?.release()}}function t8(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new h("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 t6(){return"arm64"===process.arch?"arm64":"x86_64"}function t9(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function t7(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return eX(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new h("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 ne(e,t,n){E({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...n}})}function nt(e){let t=function(e){let t=function(e){try{let t=O("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 a,i,r=t;let e=new Set,n=t=>{if(t&&"object"==typeof t)for(let n of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),n=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){n.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&n.add(e)}return Array.from(n)}(t))e.add(n)};n(r);let o=r.TestConfigurations;if(Array.isArray(o))for(let e of o){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)n(e)}for(let e of Object.values(r))e&&"object"==typeof e&&"TestBundlePath"in e&&n(e);return Array.from(e)}if("darwin"===process.platform)return null;try{let t;return a=n.readFileSync(e,"utf8"),i=tT(a),t=new Set,tk(i,(e,n)=>{if(tG.has(e)){if("string"===n.name&&n.text)return void t.add(n.text);if("array"===n.name)for(let e of n.children)"string"===e.name&&e.text&&t.add(e.text)}}),Array.from(t)}catch{return null}}(e);if(!t||0===t.length)return null;let a=s.dirname(e),i=new Set,r=new Set,o=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),o=s.join(a,t);if(!n.existsSync(o))return null;i.add(o);let l=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);l&&r.add(s.join(a,l));continue}e.startsWith("__TESTHOST__/")&&o.push(e.slice(13))}for(let e of o){let t=Array.from(r).find(t=>n.existsSync(s.join(t,e)));if(!t)return null;i.add(s.join(t,e))}return Array.from(i)}let nn=new Map,na=new Map;async function ni(e,t){return await tM(na,e.id,async()=>{var n;let a,i,r=nn.get(e.id);if(r){if(function(e){return!!e&&K(e)}(r.child.pid))return r;await nl(e.id,r)}await ("simulator"!==(n=e).kind?Promise.resolve():nf(n)),await nr(e);let o=await tZ(e,t),s=await tN(),{xctestrunPath:l,jsonPath:d}=await t4(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),u=await tz(e);try{let t;({child:a,wait:i}=C("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",t9(e),"1","-destination-timeout",String(tI),"-xctestrun",l,"-destination",(t=t8(e),"macOS"===t?`platform=macOS,arch=${t6()}`:"simulator"===e.kind?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0}))}catch(e){throw await u?.release(),e}a.stdout?.on("data",e=>{tx(e,t.logPath,t.traceLogPath,t.verbose)}),a.stderr?.on("data",e=>{tx(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${s}:${Date.now()}`,device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:d,testPromise:i,child:a,ready:!1,simulatorSetRedirect:u??void 0};return nn.set(e.id,c),c})}async function nr(e){if("simulator"===e.kind)for(let t of tH){let n=await L("xcrun",H(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==n.exitCode){let e=`${n.stdout}
7
- ${n.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}}}function no(e){let t=nn.get(e);return t?{sessionId:t.sessionId,alive:function(e){return!!e&&K(e)}(t.child.pid)}:null}async function ns(e){await tM(na,e.deviceId,async()=>{await nl(e.deviceId,e)})}async function nl(e,t){let n=t??nn.get(e);if(n){try{await tA(n.device,n.port,{command:"shutdown"},void 0,15e3)}catch{await np(n.child.pid,"SIGTERM")}try{await Promise.race([n.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await np(n.child.pid,"SIGKILL"),tE(n.xctestrunPath),tE(n.jsonPath),await n.simulatorSetRedirect?.release(),nn.get(e)===n&&nn.delete(e)}}async function nd(e){await tM(na,e,async()=>{await nl(e)})}async function nu(){let e=Array.from(nn.values()),t=Array.from(tB);await Promise.allSettled(e.map(async e=>{await np(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await np(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await np(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await np(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await np(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await np(e.pid,"SIGKILL"),tB.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function nc(){await nu();let e=Array.from(nn.keys());await Promise.allSettled(e.map(async e=>{await nd(e)}));let t=Array.from(tB);await Promise.allSettled(t.map(async e=>{try{await np(e.pid,"SIGTERM"),await np(e.pid,"SIGKILL")}finally{tB.delete(e)}}))}async function np(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let n="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await L("pkill",[`-${n}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function nf(e){await L("xcrun",H(e,["bootstatus",e.id,"-b"]),{timeoutMs:tp})}async function nm(e,t,n,a,i,r){let o=await tA(e,t.port,n,a,i,t,r);return await nh(o,t,a)}async function nh(e,t,n){let a,i=await e.text();try{let e=JSON.parse(i);a=e&&"object"==typeof e?e:{}}catch{throw new h("COMMAND_FAILED","Invalid runner response",{text:i})}if(!a.ok){let e=a.error?.code;throw new h("string"==typeof e&&e.trim().length>0?m(e):"COMMAND_FAILED",("string"==typeof a.error?.message?a.error.message:void 0)??"Runner error",{runner:a,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:n})}return(t.ready=!0,a.data&&"object"==typeof a.data&&!Array.isArray(a.data))?a.data:{}}async function nw(e,t,n={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new h("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new h("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(tc(n.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?e2(()=>(tc(n.requestId),ny(e,t,n)),{shouldRetry:e=>{tc(n.requestId);if(!(e instanceof h)||"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"))}}):ny(e,t,n)}async function ny(e,t,n={}){let a;tc(n.requestId);let i=ta(n.requestId);try{let r=(a=await ni(e,n)).ready?tf:tp;return await nm(e,a,t,n.logPath,r,i)}catch(o){let r=o instanceof h?o:new h("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===r.code&&"string"==typeof r.message&&r.message.includes("Runner did not accept connection")&&tl(r)&&a?.ready){tc(n.requestId),a?await ns(a):await nd(e.id),a=await ni(e,n);let r=await tA(a.device,a.port,t,n.logPath,tp,void 0,i);return await nh(r,a,n.logPath)}throw o}}let ng="agent-device-macos-helper",nI="AGENT_DEVICE_MACOS_HELPER_BIN",nA=s.join(r.homedir(),".agent-device","macos-helper","current"),nv=s.join(nA,"manifest.json"),nb=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function n_(e){let t=e.trim();if(!nb.test(t))throw new h("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function nS(){return function(e){let t=s.dirname(e);for(;;){let e=s.join(t,"macos-helper");if(a(s.join(e,"Package.swift")))return e;let n=s.dirname(t);if(n===t)break;t=n}throw new h("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(u(import.meta.url))}async function nN(e){let t=await i.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=s.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await nN(n):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[n]:[]}))).flat().sort()}async function nx(e){let t=await nN(e),n=p("sha256");for(let a of t)n.update(s.relative(e,a)),n.update("\0"),n.update(await i.readFile(a)),n.update("\0");let a=await L("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return n.update("swift-version"),n.update("\0"),n.update(a.stdout||a.stderr||`exit:${a.exitCode}`),n.update("\0"),n.digest("hex")}async function nE(){try{let e=JSON.parse(await i.readFile(nv,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function nD(){let e=await k(process.env[nI],nI);if(e)return e;let t=nS(),n=await nx(t),a=s.join(nA,ng);try{if(await nE()===n)return await i.access(a),a}catch{}let r=s.join(nS(),".build","release",ng);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await L("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await i.mkdir(nA,{recursive:!0});let o=`${a}.tmp`;return await i.copyFile(r,o),await i.rename(o,a),await i.chmod(a,493),await i.writeFile(nv,`${JSON.stringify({fingerprint:n},null,2)}
8
- `,"utf8"),a}async function nM(e){let t=process.env[nI]?.trim();if("darwin"!==process.platform&&!t)throw new h("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let n=await nD(),a=await L(n,e,{allowFailure:!0,timeoutMs:3e4}),i=a.stdout.trim(),r=null;if(i)try{r=JSON.parse(i)}catch{r=null}if(0===a.exitCode&&r?.ok)return r.data;throw new h("COMMAND_FAILED",r&&!r.ok?r.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:n,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...r&&!r.ok?r.error?.details:{}})}async function nC(){return await nM(["app","frontmost"])}async function nO(e){return await nM(["app","quit","--bundle-id",n_(e)])}async function nL(e,t){return await nM(["permission",e,t])}async function nT(e,t={}){let n=["alert",e];return t.bundleId&&n.push("--bundle-id",n_(t.bundleId)),t.surface&&n.push("--surface",t.surface),await nM(n)}async function nk(e,t={}){let n=["snapshot","--surface",e];return t.bundleId&&n.push("--bundle-id",n_(t.bundleId)),await nM(n)}async function nR(e,t,n={}){let a=["read","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",n_(n.bundleId)),n.surface&&a.push("--surface",n.surface),await nM(a)}async function nP(e,t,n={}){let a=["press","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",n_(n.bundleId)),n.surface&&a.push("--surface",n.surface),await nM(a)}async function nF(e,t={}){let n=["screenshot","--out",e];return t.surface&&n.push("--surface",t.surface),t.fullscreen&&n.push("--fullscreen"),await nM(n)}function n$(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let n=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!n)return!1;let a=n[1]?.toLowerCase(),i=n[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function nU(e,t){let n,a=e?.trim();return a?a:"http"===(n=t.trim().split(":")[0]?.toLowerCase())||"https"===n?"com.apple.mobilesafari":void 0}let nG=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function nV(e){return`${e.stdout}
9
- ${e.stderr}`}function nB(e,t){return["-s",e,...t]}function nj(e){return e.startsWith("emulator-")}function nq(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function nW(e,t=eQ){return L("adb",nB(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function nH(e,t){let n=t.replace(/_/g," ").trim();if(!nj(e))return n||e;let a=await nz(e);return a?a.replace(/_/g," "):n||e}async function nK(e,t,n){try{return await n("adb",nB(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=f(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function nz(e,t=L){for(let n of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await nK(e,["shell","getprop",n],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let n=await nK(e,["emu","avd","name"],t);if(!n)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}(n.stdout);if(0===n.exitCode&&a)return a}async function nJ(e,t){let n=nV(await L("adb",nB(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eQ})).toLowerCase();return!!n.includes("true")||!n.includes("false")&&null}async function nX(e){return(await Promise.all(nG.map(async t=>await nJ(e,t)))).some(e=>!0===e)}async function nY(e){var t;let n;return"tv"===((n=nV(await L("adb",nB(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eQ})).toLowerCase()).includes("tv")||n.includes("leanback")?"tv":null)||await nX(e)?"tv":(t=nV(await L("adb",nB(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eQ})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function nZ(e={}){if(await J(),!await R("adb"))throw new h("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??q(void 0),n=(await nQ()).filter(e=>!t||t.has(e.serial));return await Promise.all(n.map(async({serial:e,rawModel:t})=>{let[n,a,i]=await Promise.all([nH(e,t),n3(e),nY(e)]);return{platform:"android",id:e,name:n,kind:nj(e)?"emulator":"device",target:i,booted:a}}))}async function nQ(){return(await L("adb",["devices","-l"],{timeoutMs:eQ})).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 n0(){let e=await L("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eQ});if(0!==e.exitCode)throw new h("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 n1(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await n2(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await P(1e3)}throw new h("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 n2(e,t){let n=nq(e);for(let e of(await nQ()).filter(e=>(!t||e.serial===t)&&nj(e.serial)))if(nq(e.rawModel)===n||nq(await nH(e.serial,e.rawModel))===n)return e.serial}async function n3(e){try{let t=await nW(e);return"1"===t.stdout.trim()}catch{return!1}}async function n4(e){var t,n;let a;await J();let i=e.avdName.trim();if(!i)throw new h("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let r=e.timeoutMs??12e4;if(!await R("adb"))throw new h("TOOL_MISSING","adb not found in PATH");if(!await R("emulator"))throw new h("TOOL_MISSING","emulator not found in PATH");let o=await n0(),s=function(e,t){let n=e.find(e=>e===t);if(n)return n;let a=nq(t);return e.find(e=>nq(e)===a)}(o,i);if(!s)throw new h("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 nZ(),n=e.serial,a=nq(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!n||e.id===n)&&nq(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),M("emulator",t)}let u=d??await n1({avdName:s,serial:e.serial,timeoutMs:r}),c=Math.max(1e3,r-(Date.now()-l));await n5(u.id,c);let p=(await nZ()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function n5(e,t=6e4){let n,a=e0.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),r=!1;try{await e1(async({deadline:i})=>{if(i?.isExpired())throw r=!0,new h("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 nW(e,Math.min(o,eQ));if(n=s,"1"!==s.stdout.trim())throw new h("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=to({error:e,stdout:n?.stdout,stderr:n?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>to({error:e,stdout:n?.stdout,stderr:n?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=f(c),o=n?.stdout,s=n?.stderr,l=n?.exitCode,d=to({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:ts(d),stdout:o,stderr:s,exitCode:l};if(r||"ANDROID_BOOT_TIMEOUT"===d)throw new h("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new h("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new h("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new h(i.code,i.message,{...u,...i.details??{}},i.cause)}}async function n8(e,t){let n="url"===e.kind&&Y(e.url),a=await X({source:e,isInstallablePath:(e,t)=>{var n;let a;return t.isFile()&&(n=e,".apk"===(a=s.extname(n).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||n,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await n6(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function n6(e){let t=s.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await Z(e)}}let n9={settings:{type:"intent",value:"android.settings.SETTINGS"}},n7="android.intent.category.LAUNCHER",ae="android.intent.category.LEANBACK_LAUNCHER",at="android.intent.category.DEFAULT",an="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function aa(e,t){let n=t.trim();if("package"===V(n))return{type:"package",value:n};let a=n9[n.toLowerCase()];if(a)return a;let i=(await L("adb",B(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(n.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new h("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 h("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:an})}async function ai(e,t="all"){let n=await ar(e);return("user-installed"===t?(await as(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:al(e)}))}async function ar(e){let t=new Set;for(let n of ao(e,{includeFallbackWhenUnknown:!0})){let a=await L("adb",B(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",n]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of ee(a.stdout))t.add(e)}return t}function ao(e,t={}){return"tv"===e.target?[ae]:"mobile"===e.target?[n7]:t.includeFallbackWhenUnknown?[n7,ae]:[n7]}async function as(e){return et((await L("adb",B(e,["shell","pm","list","packages","-3"]))).stdout)}function al(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),n=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=n[n.length-1]??e;for(let e=n.length-1;e>=0;e-=1){let i=n[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 ad(e){let t=await au(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let n=await au(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return n||{}}async function au(e,t){for(let n of t){let t=Q((await L("adb",B(e,n),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function ac(e,t,n){var a,i;let r;e.booted||await n5(e.id);let o=t.trim();if(n$(o)){if(n)throw new h("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await L("adb",B(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await aa(e,t),l=ao(e)[0]??n7;if("intent"===s.type){if(n)throw new h("INVALID_ARGS","Activity override requires a package name, not an intent");await L("adb",B(e,["shell","am","start","-W","-a",s.value]));return}if(n){let t=n.includes("/")?n:`${s.value}/${n.startsWith(".")?n:`.${n}`}`;try{await L("adb",B(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",at,"-c",l,"-n",t]))}catch(t){throw await am(e,s.value,t),t}return}let d=await L("adb",B(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",at,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,r=`${a}
10
- ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)))return;let u=await aw(e,s.value);if(!u){if(!await af(e,s.value))throw ap(s.value);throw new h("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr})}await L("adb",B(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",at,"-c",l,"-n",u]))}function ap(e){return new h("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:an})}async function af(e,t){let n=await L("adb",B(e,["shell","pm","path",t]),{allowFailure:!0}),a=`${n.stdout}
11
- ${n.stderr}`;return!!(0===n.exitCode&&/\bpackage:/i.test(a))||(ah(a),!1)}async function am(e,t,n){if(ah(n instanceof h?`${String(n.details?.stdout??"")}
12
- ${String(n.details?.stderr??"")}`:"")||!await af(e,t))throw ap(t)}function ah(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 aw(e,t){for(let n of Array.from(new Set(ao(e,{includeFallbackWhenUnknown:!0})))){let a=await L("adb",B(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",n,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 n=t[e];if(n.includes("/"))return n.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function ay(e){e.booted||await n5(e.id)}async function ag(e,t){if("settings"===t.trim().toLowerCase())return void await L("adb",B(e,["shell","am","force-stop","com.android.settings"]));let n=await aa(e,t);if("intent"===n.type)throw new h("INVALID_ARGS","Close requires a package name, not an intent");await L("adb",B(e,["shell","am","force-stop",n.value]))}async function aI(e,t){let n=await aa(e,t);if("intent"===n.type)throw new h("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await L("adb",B(e,["uninstall",n.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
13
- ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new h("COMMAND_FAILED",`adb uninstall failed for ${n.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:n.value}}let aA=null;async function av(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(aA?.key===e)return aA.invocation;if(await R("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return aA={key:e,invocation:t},t}let t=await T(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,"AGENT_DEVICE_BUNDLETOOL_JAR");if(!t)throw new h("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");let n={cmd:"java",prefixArgs:["-jar",t]};return aA={key:e,invocation:n},n}async function ab(e){let t=await av();await L(t.cmd,[...t.prefixArgs,...e])}async function a_(e,t){let n,a=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-aab-")),o=s.join(a,"bundle.apks"),l=(n=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&n.length>0?n:"universal";try{await ab(["build-apks","--bundle",t,"--output",o,"--mode",l]),await ab(["install-apks","--apks",o,"--device-id",e.id])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function aS(e,t){".aab"===s.extname(t).toLowerCase()?await a_(e,t):await L("adb",B(e,["install","-r",t]))}async function aN(e){return new Set((await L("adb",B(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function ax(e,t){let n=Array.from(await aN(e)).filter(e=>!t.has(e));if(1===n.length)return n[0]}async function aE(e,t){e.booted||await n5(e.id),await aS(e,t)}async function aD(e,t,n){let a=n?void 0:await aN(e);return await aE(e,t),n??(a?await ax(e,a):void 0)}async function aM(e,t){e.booted||await n5(e.id);let n=await n8({kind:"path",path:t});try{let t=await aD(e,n.installablePath,n.packageName),a=t?al(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await n.cleanup()}}async function aC(e,t,n){e.booted||await n5(e.id);let{package:a}=await aI(e,t),i=await n8({kind:"path",path:n},{resolveIdentity:!1});try{return await aE(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function aO(e){let t=e.direction,n="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 h("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 h("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(n*a),r=Math.max(1,Math.round(.05*n)),o=Math.max(1,Math.min(i,Math.max(1,n-2*r))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(n,a,i,r)=>({direction:t,x1:n,y1:a,x2:i,y2:r,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 aL(e,t,n){let a=function(e){let t=0,n=0,a=[...e.children];for(;a.length>0;){let e=a.pop();t+=1,n=Math.max(n,e.depth),a.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}(e),i=[],r=[],o=!1,s=n.depth??1/0,l=n.scope?function(e,t){let n=t.toLowerCase(),a=[...e.children],i=0;for(;i<a.length;){let e=a[i++],t=e.label?.toLowerCase()??"",r=e.value?.toLowerCase()??"",o=e.identifier?.toLowerCase()??"";if(t.includes(n)||r.includes(n)||o.includes(n))return e;a.push(...e.children)}return null}(e,n.scope):null,d=l?[l]:e.children,u=new Map,c=e=>{let t=u.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||c(t))return u.set(e,!0),!0;return u.set(e,!1),!1},p=(e,a,l,d=!1,u=!1)=>{var f,m,h,w,y,g;let I,A,v,b,_,S,N,x;if(i.length>=t){o=!0;return}if(a>s)return;let E=!!n.raw||(f=e,m=n,h=d,w=c(e),y=u,A=aF(f.type),v=!!(f.label&&f.label.trim().length>0),b=!!(f.identifier&&f.identifier.trim().length>0),_=v&&!a$(f.label??""),S=b&&!a$(f.identifier??""),N=(I=(g=A).split(".").pop()??g).includes("layout")||"viewgroup"===I||"view"===I,x="imageview"===A||"imagebutton"===A,m.interactiveOnly?!!(f.hittable||el(A)&&w)||!!(_||S)&&!x&&(!N||!!y)&&(h||w||y):m.compact?_||S||!!f.hittable:!N&&!x||!!f.hittable||!!_||!!S&&!!w||w),D=l;E&&(D=i.length,r.push(e),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:a,parentIndex:l,...e.hiddenContentAbove?{hiddenContentAbove:!0}:{},...e.hiddenContentBelow?{hiddenContentBelow:!0}:{}}));let M=d||!!e.hittable,C=u||function(e){if(!e)return!1;let t=aF(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(p(t,a+1,D,M,C),o)return};for(let e of d)if(p(e,0,void 0,!1,!1),o)break;return o?{nodes:i,sourceNodes:r,truncated:o,analysis:a}:{nodes:i,sourceNodes:r,analysis:a}}function aT(e){let t=function(e){let t=new Map,n=e.indexOf(" "),a=e.lastIndexOf(">");if(n<0||a<=n)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,r=n;for(;r<a;){for(;r<a;){let t=e[r];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;r+=1}if(r>=a)break;let n=e[r];if("/"===n||">"===n)break;i.lastIndex=r;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),r=i.lastIndex}return t}(e),n=e=>{let n=ak(t,e);if(null!==n)return"true"===n};return{text:ak(t,"text"),desc:ak(t,"content-desc"),resourceId:ak(t,"resource-id"),className:ak(t,"class"),bounds:ak(t,"bounds"),clickable:n("clickable"),enabled:n("enabled"),focusable:n("focusable"),focused:n("focused")}}function ak(e,t){return e.get(t)??null}function aR(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let n=Number(t[1]),a=Number(t[2]);return{x:n,y:a,width:Math.max(0,Number(t[3])-n),height:Math.max(0,Number(t[4])-a)}}function aP(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},n=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){n.length>1&&n.pop(),i=a.exec(e);continue}let r=aT(t),o=aR(r.bounds),s=n[n.length-1],l={type:r.className,label:r.text||r.desc,value:r.text,identifier:r.resourceId,rect:o,enabled:r.enabled,hittable:r.clickable??r.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||n.push(l),i=a.exec(e)}return t}function aF(e){return e?e.toLowerCase():""}function a$(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function aU(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function aG(e,t){let n=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),a=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=n&&Math.abs(e.crossSize-t.crossSize)<=a}function aV(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function aB(e,t={}){let n=await aq(e);if(!t.interactiveOnly){let a=function(e,t){let{sourceNodes:n,...a}=aL(aP(e),800,t);return a}(n,t);return function(e,t){for(let[n,a]of e){let e=t[n];e&&(a.hiddenContentAbove&&(e.hiddenContentAbove=!0),a.hiddenContentBelow&&(e.hiddenContentBelow=!0))}}(await aj(e,a.nodes),a.nodes),a}let a=aP(n),i=aL(a,800,{...t,interactiveOnly:!1}),r=aL(a,800,t),o=await aj(e,i.nodes);aJ(o,i,r),0===o.size&&aJ(en(ep(i.nodes)),i,r);let{sourceNodes:s,...l}=r;return l}async function aj(e,t){if(!t.some(e=>el(e.type)))return new Map;let n=await az(e);return n?function(e,t){let n=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},n=[{indent:-1,node:t}],a=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=a.exec(t);if(!e)continue;let i=e[1].length,r=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),d={className:e[2],rect:{x:r,y:o,width:Math.max(0,s-r),height:Math.max(0,l-o)},children:[]};for(;n.length>1&&i<=n[n.length-1].indent;)n.pop();n[n.length-1].node.children.push(d),n.push({indent:i,node:d})}return t.children.length>0?t:null}(t);if(!n)return new Map;let a=function(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();if(el(e.className)){let n=function(e){let t=e.children[0];if(!t)return null;let n=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),a=t.children.filter(e=>e.rect.height>0).map(t=>aV(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===a.length?null:{rect:e.rect,contentExtent:n,contentBlocks:a}}(e);n&&t.push(n)}n.push(...e.children)}return t}(n);if(0===a.length)return new Map;let i=new Map;for(let t of e){if(!t.rect||!el(t.type))continue;let n=function(e,t){let n=null,a=1/0;for(let i of t){let t=Math.abs(i.rect.width-e.width)+Math.abs(i.rect.height-e.height);if(t>32)continue;let r=4*t+(Math.abs(i.rect.x-e.x)+Math.abs(i.rect.y-e.y));r<a&&(n=i,a=r)}return n}(t.rect,a);if(!n)continue;let r=function(e,t){let n=function(e,t){let n=t,a=new Set;for(;!a.has(n.index);){var i,r;a.add(n.index);let o=e.filter(e=>e.parentIndex===n.index&&e.rect);if(1!==o.length)return n;let s=o[0];if(i=s.rect,r=t.rect,i.x!==r.x||i.y!==r.y||i.width!==r.width||i.height!==r.height)return n;n=s}return t}(e,t);return e.filter(e=>e.parentIndex===n.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>aV(e,t.rect))}(e,t),o=function(e){let{viewportRect:t,visibleBlocks:n,nativeScrollView:a}=e;if(0===n.length||0===a.contentBlocks.length)return null;let i=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],n=e.contentBlocks[e.contentBlocks.length-1];if(!t||!n)return null;let a=aU(e.contentBlocks.map(e=>e.size))??e.rect.height,i=Math.max(48,Math.round(.5*a)),r=Math.max(24,Math.round(.25*a)),o=t.start>=i,s=e.contentExtent-(n.start+n.size)>=r;return o||s?{above:o,below:s}:null}(a),r=function(e,t){let n=new Map;for(let a of e)for(let e of t){if(!aG(a,e))continue;let t=a.start-e.start,i=8*Math.round(t/8),r=n.get(i)??[];r.push(t),n.set(i,r)}let a=null;for(let e of n.values())(!a||e.length>a.length)&&(a=e);if(!a||a.length<2)return null;let i=[...a].sort((e,t)=>e-t);return i[Math.floor(i.length/2)]??null}(a.contentBlocks,n)??function(e){let{nativeBlocks:t,visibleBlocks:n,viewportExtent:a,contentExtent:i}=e,r=[],o=[];for(let e of t)for(let t of n){if(!aG(e,t))continue;let n=e.start-t.start;16>=Math.abs(n)&&r.push(n),16>=Math.abs(n+a-i)&&o.push(n)}return o.length>0?aU(o):r.length>0?aU(r):null}({nativeBlocks:a.contentBlocks,visibleBlocks:n,viewportExtent:t.height,contentExtent:a.contentExtent});if(null===r)return i;let o=t.height;return{above:(i?.above??!1)||r>16,below:(i?.below??!1)||r+o<a.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:r,nativeScrollView:n});if(!o)continue;let s={};o.above&&(s.hiddenContentAbove=!0),o.below&&(s.hiddenContentBelow=!0),(s.hiddenContentAbove||s.hiddenContentBelow)&&i.set(t.index,s)}return i}(t,n):new Map}async function aq(e){try{return await e2(()=>aW(e),{shouldRetry:aK})}catch(e){if(function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code||"number"!=typeof e.details?.timeoutMs)return!1;let t=e.details?.cmd,n=e.details?.args,a=Array.isArray(n)?n.map(String):"string"==typeof n?n.split(/\s+/):[];return"adb"===t&&a.includes("uiautomator")&&a.includes("dump")}(e)){let t="If the app has looping animations, use screenshot as visual truth, try settings animations off, then retry snapshot. Stock Android UIAutomator may still time out on app-owned infinite animations.";throw new h("COMMAND_FAILED",`Android UI hierarchy dump timed out while waiting for the UI to become idle. ${t}`,{...e.details??{},hint:t},e)}throw e}}async function aW(e){var t,n,a;let i,r,o=await L("adb",B(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0,timeoutMs:8e3}),s=aH(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await L("adb",B(e,["shell","uiautomator","dump",l]),{allowFailure:!0,timeoutMs:8e3}),u=(t=l,n=d.stdout,a=d.stderr,i=`${n}
14
- ${a}`,r=/dumped to:\s*(\S+)/i.exec(i),r?.[1]??t),c=await L("adb",B(e,["shell","cat",u])),p=aH(c.stdout,c.stderr);if(!p)throw new h("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function aH(e,t){let n=`${e}
15
- ${t}`,a=n.indexOf("<?xml"),i=a>=0?a:n.indexOf("<hierarchy");if(i<0)return null;let r=n.lastIndexOf("</hierarchy>");if(r<0||r<i)return null;let o=n.slice(i,r+12).trim();return o.length>0?o:null}function aK(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,n=("string"==typeof t?t:"").toLowerCase();return!!(n.includes("device offline")||n.includes("device not found")||n.includes("transport error")||n.includes("connection reset")||n.includes("broken pipe")||n.includes("timed out")||n.includes("no such file or directory"))}async function az(e){try{let t=await L("adb",B(e,["shell","dumpsys","activity","top"]),{allowFailure:!0,timeoutMs:8e3}),n=`${t.stdout}
16
- ${t.stderr}`.trim();return n.length>0?n:null}catch{return null}}function aJ(e,t,n){if(0===e.size)return;let a=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&a.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let r=a.get(e);r&&(i.hiddenContentAbove&&(r.hiddenContentAbove=!0),i.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}async function aX(e,t,n){await L("adb",B(e,["shell","input","tap",String(t),String(n)]))}async function aY(e,t,n,a,i,r=250){await L("adb",B(e,["shell","input","swipe",String(t),String(n),String(a),String(i),String(r)]))}async function aZ(e){await L("adb",B(e,["shell","input","keyevent","4"]))}async function aQ(e){await L("adb",B(e,["shell","input","keyevent","3"]))}async function a0(e,t){let n=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new h("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await L("adb",B(e,["shell","settings","put","system","accelerometer_rotation","0"])),await L("adb",B(e,["shell","settings","put","system","user_rotation",n]))}async function a1(e){await L("adb",B(e,["shell","input","keyevent","187"]))}async function a2(e,t,n,a=800){await L("adb",B(e,["shell","input","swipe",String(t),String(n),String(t),String(n),String(a)]))}async function a3(e,t,n=0){n>0&&Array.from(t).length>1?await it(e,t,1,n):await a4(e,t)}async function a4(e,t){let n=ia(t);if(!n||"ok"!==await ii(e,t))try{let n=t.replace(/ /g,"%s");await L("adb",B(e,["shell","input","text",n]))}catch(e){if(n&&function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,n=("string"==typeof t?t:"").toLowerCase();return!!(n.includes("exception occurred while executing 'text'")||n.includes("nullpointerexception")&&n.includes("inputshellcommand.sendtext"))}(e))throw new h("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 a5(e,t,n){await aX(e,t,n)}async function a8(e,t,n,a,i=0){let r=Array.from(a).length,o=ia(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 a5(e,t,n);let s=(d=r+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await ir(e,s),"input_text"===o.strategy)await a3(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await ii(e,a))continue}else await it(e,a,1,i>0?i:15);let c=await a6(e,t,n,a);if(l=c.actual,c.ok)return}throw new h("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function a6(e,t,n,a){let i=null;for(let r of[0,150,350])if(r>0&&await P(r),function(e,t){if(e===t)return!0;let n=a9(e),a=a9(t);return!!n&&!!a&&(!!(n===a||n.includes(a))||a.includes(n)&&n.length>=Math.max(4,Math.floor(.8*a.length)))}(i=await io(e,t,n),a))return{ok:!0,actual:i};return{ok:!1,actual:i}}function a9(e){return(e??"").replace(/\s+/g," ").trim()}async function a7(e,t,n){let a=await ie(e),i=aO({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await L("adb",B(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function ie(e){let t=(await L("adb",B(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new h("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function it(e,t,n,a){let i=Math.max(1,Math.floor(n)),r=Array.from(t);for(let t=0;t<r.length;t+=i){let n=r.slice(t,t+i).join("");await a4(e,n),a>0&&t+i<r.length&&await P(a)}}function ia(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 ii(e,t){let n=await L("adb",B(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==n.exitCode?"failed":W(n.stdout,n.stderr)?"unsupported":0===(await L("adb",B(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await L("adb",B(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function ir(e,t){let n=Math.max(0,t);await L("adb",B(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<n;t+=24){let a=Math.min(24,n-t);await L("adb",B(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function io(e,t,n){let a,i=await aq(e),r=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=r.exec(i));){let e=aT(a[0]),i=aR(e.bounds);if(!i)continue;let r=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&&n>=i.y&&n<=i.y+i.height;if(u&&is(r)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&is(r)){(!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 is(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function il(e){let t=await L("adb",B(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new h("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 n of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=n[1],a=n[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),n=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)||(n=(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,r=i?`0x${i.toLowerCase()}`:void 0;return{visible:n,inputType:r,type:r?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let n=15&t;if(2===n)return"number";if(3===n)return"phone";if(4===n)return"datetime";if(1!==n)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(r):void 0}}(t.stdout)}async function id(e){let t=await il(e),n=t,a=0;for(;n.visible&&a<2;)await L("adb",B(e,["shell","input","keyevent","111"])),a+=1,await P(120),n=await il(e);if(t.visible&&n.visible)throw new h("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:n.inputType,type:n.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!n.visible,visible:n.visible,inputType:n.inputType,type:n.type}}async function iu(e){let t,n;return(n=(t=(await ip(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?n[1]??"":"null"===t.trim().toLowerCase()?"":t}async function ic(e,t){await ip(e,["shell","cmd","clipboard","set","text",t],"write")}async function ip(e,t,n){let a=await L("adb",B(e,t),{allowFailure:!0});if(W(a.stdout,a.stderr))throw new h("UNSUPPORTED_OPERATION",`Android shell clipboard ${n} is not supported on this device.`);if(0!==a.exitCode)throw new h("COMMAND_FAILED",`Failed to ${n} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let im=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function ih(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new h("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iw(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 h("INVALID_ARGS",`permission setting requires a target: ${im.join("|")}`)}function iy(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new h("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}let ig=["window_animation_scale","transition_animation_scale","animator_duration_scale"];async function iI(e,t,n,a,i){switch(t.toLowerCase()){case"wifi":{let t=iv(n);await L("adb",B(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iv(n);await L("adb",B(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await L("adb",B(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iv(n);await L("adb",B(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"animations":{let t=iv(n)?"1":"0";for(let n of ig)await L("adb",B(e,["shell","settings","put","global",n,t]));return{scale:t,keys:[...ig]}}case"appearance":{let t=await ib(e,n);await L("adb",B(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 h("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(n);await iA(e,t);return}case"permission":{if(!a)throw new h("INVALID_ARGS","permission setting requires an active app in session");let t=ih(n),r=function(e,t){let n=iw(e);if(t?.trim())throw new h("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===n)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===n)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===n)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===n)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===n)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new h("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===r.kind)return void await iS(e,a,t,r);let o="grant"===t?"grant":"revoke";if("photos"===r.type)return void await i_(e,a,o);await L("adb",B(e,["shell","pm",o,a,r.value]));return}default:throw new h("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iA(e,t){var n;let a,i,r=(n=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===n.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of r){let n=await L("adb",B(e,t),{allowFailure:!0});if(0===n.exitCode)return;o.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.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,n;let a;return t=e.stdout,n=e.stderr,(a=`${t}
17
- ${n}`.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 h("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 h("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function iv(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 h("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ib(e,t){let n=iy(t);if("toggle"!==n)return n;let a=await L("adb",B(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new h("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
18
- ${t}`);if(!n)return null;let a=n[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new h("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 i_(e,t,n){let a=await iN(e),i=[];for(let r 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 L("adb",B(e,["shell","pm",n,t,r]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:r,stderr:a.stderr,exitCode:a.exitCode})}throw new h("COMMAND_FAILED",`Failed to ${n} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function iS(e,t,n,a){"grant"===n?await L("adb",B(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await L("adb",B(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===n&&(await L("adb",B(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await L("adb",B(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await L("adb",B(e,["shell","appops","set",t,a.appOps,"grant"===n?"allow":"deny"===n?"deny":"default"]))}async function iN(e){let t=await L("adb",B(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}async function ix(e,t,n){let a="string"==typeof n.action&&n.action.trim()?n.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],r="string"==typeof n.receiver?n.receiver.trim():"";r&&i.push("-n",r);let o=n.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new h("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,n){if("string"==typeof n)return e.push("--es",t,n);if("boolean"==typeof n)return e.push("--ez",t,n?"true":"false");if("number"==typeof n&&Number.isFinite(n))return Number.isInteger(n)?e.push("--ei",t,String(n)):e.push("--ef",t,String(n));throw new h("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await L("adb",B(e,i)),{action:a,extrasCount:s}}let iE=Buffer.from([137,80,78,71,13,10,26,10]);async function iD(e,t){await iM(e);try{await P(1e3),await iO(e,t)}finally{await iC(e).catch(()=>{})}}async function iM(e){let t=t=>L("adb",B(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n("clock -e hhmm 0941"),await n("notifications -e visible false")}async function iC(e){await L("adb",B(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function iO(e,t){let n=await L("adb",B(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!n.stdoutBuffer)throw new h("COMMAND_FAILED","Failed to capture screenshot");let a=n.stdoutBuffer.indexOf(iE);if(a<0)throw new h("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let r=function(e,t){let n=t+iE.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),a=n+4,i=e.toString("ascii",a,a+4),r=n+12+t;if(r>e.length)break;if("IEND"===i)return r;n=r}return null}(n.stdoutBuffer,a);if(!r)throw new h("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await i.writeFile(t,n.stdoutBuffer.subarray(a,r))}let iL=F(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eZ,5e3),iT=F(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,eY,1e3),ik=F(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),iR=F(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),iP=F(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),iF=F(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),i$=F(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3),iU=eX(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK);async function iG(e,t){let n=["devicectl",...e],a=await L("xcrun",n,{allowFailure:!0,timeoutMs:iR});if(0===a.exitCode)return;let i=String(a.stdout??""),r=String(a.stderr??"");throw new h("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:t.deviceId,hint:iq(i,r)??ij})}async function iV(e,t){let n=s.join(r.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",n],o=await L("xcrun",a,{allowFailure:!0,timeoutMs:iR});try{var l,d;if(0!==o.exitCode){let t=String(o.stdout??""),n=String(o.stderr??"");throw new h("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:o.exitCode,stdout:t,stderr:n,deviceId:e.id,hint:iq(t,n)??ij})}let r=await i.readFile(n,"utf8");return l=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let n=[];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,i="string"==typeof e.url&&e.url.trim().length>0?e.url.trim():void 0;n.push({bundleId:t,name:a,url:i})}return n}(JSON.parse(r)),d=t,"user-installed"===d?l.filter(e=>!e.bundleId.startsWith("com.apple.")):l}catch(t){if(t instanceof h)throw t;throw new h("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await i.unlink(n).catch(()=>{})}}async function iB(e){let t=s.join(r.tmpdir(),`agent-device-ios-processes-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=["devicectl","device","info","processes","--device",e.id,"--json-output",t],a=await L("xcrun",n,{allowFailure:!0,timeoutMs:iR});try{if(0!==a.exitCode){let t=String(a.stdout??""),i=String(a.stderr??"");throw new h("COMMAND_FAILED","Failed to list iOS processes",{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:t,stderr:i,deviceId:e.id,hint:iq(t,i)??ij})}let r=await i.readFile(t,"utf8");return function(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.executable?e.executable.trim():"",a="number"==typeof e.processIdentifier&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;t&&Number.isFinite(a)&&n.push({executable:t,pid:a})}return n}(JSON.parse(r))}catch(t){if(t instanceof h)throw t;throw new h("COMMAND_FAILED","Failed to parse iOS process list",{deviceId:e.id,cause:String(t)})}finally{await i.unlink(t).catch(()=>{})}}let ij="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function iq(e,t){let n=`${e}
19
- ${t}`.toLowerCase();return n.includes("device is busy")&&n.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":n.includes("coredeviceservice")&&n.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function iW(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let n=String(t.stderr??"").toLowerCase();return n.includes("fbsopenapplicationserviceerrordomain")&&n.includes("the request to open")}async function iH(e,t){let n=await L("xcrun",H(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==n.exitCode)return{installed:!1};let a=n.stdout.trim();if(!a)return{installed:!1};let i=await L("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let r=i.stdout.trim(),o=`${a}/${r}`,s=await L("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 iK(e,t){if("simulator"!==e.kind)throw new h("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function iz(){await L("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:iP})}async function iJ(e){let t,n;if("simulator"!==e.kind||"Booted"===await iY(e))return;let a=e0.fromTimeoutMs(iL);try{await e1(async({deadline:a})=>{if(a?.isExpired())throw new h("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:iL});let i=Math.max(1e3,a?.remainingMs()??iL),r=await L("xcrun",H(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(r.stdout??""),stderr:String(r.stderr??""),exitCode:r.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 h("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await L("xcrun",H(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(n={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==n.exitCode)throw new h("COMMAND_FAILED","simctl bootstatus failed",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let d=await iY(e);if("Booted"!==d)throw new h("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=to({error:e,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>to({error:e,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(r){let i=to({error:r,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new h("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:iL,elapsedMs:a.elapsedMs(),reason:i,hint:ts(i),boot:t,bootstatus:n})}await iz()}async function iX(e){let t=H(e,["shutdown",e.id]),n=await L("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===n.exitCode,exitCode:n.exitCode,stdout:String(n.stdout??""),stderr:String(n.stderr??"")}}async function iY(e){let t="string"==typeof e?e:e.id,n="string"==typeof e?G(["list","devices","-j"]):H(e,["list","devices","-j"]),a=await L("xcrun",n,{allowFailure:!0,timeoutMs:iT});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let n of Object.values(e.devices??{})){let e=n.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function iZ(e,t){try{let n=await L("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===n.exitCode){let e=String(n.stdout??"").trim();if(e.length>0)return e}}catch{}try{var n,a;let r;return n=await i.readFile(e,"utf8"),a=t,tk(tT(n),(e,t)=>{void 0===r&&e===a&&"string"===t.name&&(r=t.text??void 0)}),r}catch{return}}async function iQ(e,t){if("url"===e.kind&&!Y(e.url))throw new h("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 n=await X({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||Y(e.url),signal:t?.signal}),a=await i1(n.installablePath,t),i=await i0(a.installPath);return{archivePath:n.archivePath??(n.installablePath.toLowerCase().endsWith(".ipa")?n.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await n.cleanup()}}}async function i0(e){let t=s.join(e,"Info.plist"),[n,a,i]=await Promise.all([iZ(t,"CFBundleIdentifier"),iZ(t,"CFBundleDisplayName"),iZ(t,"CFBundleName")]);return{bundleId:n,appName:a??i}}async function i1(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let n=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await i.rm(n,{recursive:!0,force:!0})};try{await L("unzip",["-q",e,"-d",n]);let r=s.join(n,"Payload"),o=(await i.readdir(r,{withFileTypes:!0}).catch(()=>{throw new h("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:s.join(r,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===o.length)return{installPath:o[0].installPath,cleanup:a};if(0===o.length)throw new h("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await i2(o);let l=t?.appIdentifierHint?.trim();if(l){let e=function(e,t){let n=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===n);if(1===a.length)return a[0];if(a.length>1)throw new h("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()===n);if(1===t.length)return t[0]}}(o,l);if(e)return{installPath:e.installPath,cleanup:a};throw new h("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload and none matched "${l}". Available bundles: ${o.map(i3).join(", ")}`)}throw new h("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${o.map(i3).join(", ")}`)}catch(e){throw await a(),e}}async function i2(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await i0(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function i3(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function i4(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let i5={settings:"com.apple.systempreferences"},i8=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function i6(e,t){let n=["-b",e];return t&&n.push(t),n}async function i9(e){for(let t of[s.join(e,"Contents","Info.plist"),s.join(e,"Info.plist")]){let[e,n,a]=await Promise.all([iZ(t,"CFBundleIdentifier"),iZ(t,"CFBundleDisplayName"),iZ(t,"CFBundleName")]);if(e||n||a)return{bundleId:e,appName:n??a}}return{}}async function i7(e){let t=e.trim(),n=i5[t.toLowerCase()];if(n)return n;if(i8.test(t))return t;let a=(await ro("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new h("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new h("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function re(e,t,n){let a=n?.url?.trim();if(a){if(!n$(a))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=n?.appBundleId??await i7(t);await L("open",i6(e,a));return}let i=t.trim();if(n$(i))return void await L("open",[i]);let r=n?.appBundleId??await i7(i);await L("open",i6(r))}async function rt(e,t){let n=await i7(t),a=await nO(n);if(a.running&&!a.terminated&&!a.forceTerminated)throw new h("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:n,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function rn(){let e=await L("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new h("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 ra(e){let t=await L("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new h("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function ri(){let e=await L("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new h("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 h("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function rr(e){let t=iy(e),n="toggle"===t?!await ri():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${n?"true":"false"}`,i=await L("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new h("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function ro(e="all"){let t=["/Applications","/System/Applications",s.join(r.homedir(),"Applications")],n=new Set;for(let e of t){let t=await i.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await L("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&&n.add(t)}}return i4((await Promise.all(Array.from(n).map(async e=>{let t=await i9(e).catch(()=>({})),n=t.bundleId;return n?{bundleId:n,name:t.appName??s.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let rs=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],rl={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"},rd={1:"searching",2:"failed",3:"active"},ru={0:"notSupported",1:"searching",2:"failed",3:"active"};function rc(e,t,n){return L("xcrun",H(e,t),n)}async function rp(e,t){var n,a;let i;await rm(e),t&&await rh(e,(i=[],(n=t).dataNetwork&&i.push("--dataNetwork",n.dataNetwork),n.wifiMode&&i.push("--wifiMode",n.wifiMode),void 0!==n.wifiBars&&("wifi"===n.dataNetwork||n.wifiMode)&&i.push("--wifiBars",n.wifiBars),n.cellularMode&&i.push("--cellularMode",n.cellularMode),void 0!==n.cellularBars&&(n.cellularMode||(a=n.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==n.operatorName)&&i.push("--cellularBars",n.cellularBars),void 0!==n.operatorName&&i.push("--operatorName",n.operatorName),i))}async function rf(e){let t=await rc(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new h("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 n 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(n);if(e){let n=Number(e[1]),a=rl[n];if(!a)throw new h("COMMAND_FAILED",`Unsupported simulator data network type: ${n}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(n);if(a){let e=rd[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(n);if(i){let e=Number(i[1]),n=ru[e];if(!n)throw new h("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=n,t.cellularBars=i[2];continue}let r=/^Operator Name:\s*(.*)$/.exec(n);if(r){t.operatorName=r[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function rm(e){await rc(e,["status_bar",e.id,"clear"])}async function rh(e,t){0!==t.length&&await rc(e,["status_bar",e.id,"override",...t])}function rw(e,t,n){E({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof h))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},n=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:n}}(n)}})}function ry(e,t,n){return L("xcrun",H(e,t),n)}let rg={ensureBooted:iJ,prepareStatusBarForScreenshot:async function e(e){let t=null,n=!1;try{t=await rf(e),n=!0}catch(t){rw(e,"snapshot_failed",t)}try{await rm(e),await rh(e,rs)}catch(t){rw(e,"prepare_failed",t)}return async()=>{await rp(e,n?t:null)}},captureWithRetry:rv,runnerFallbackEnabled:iU,captureWithRunner:rb,shouldFallbackToRunner:rM};async function rI(e,t,n,a){if("macos"===e.platform)return void await rb(e,t,n,a);if("simulator"===e.kind)return void await rA(e,t,n,a);try{await iG(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},n="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
5
+ ${n}`.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.":e7("IOS_RUNNER_CONNECT_TIMEOUT"))})}function tp(e){if(e4(e))throw e8()}let tf=F(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),tm=F(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),th=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),tw=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),ty=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),tg=F(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),tI=F(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),tA=$(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function tv(e,t,n,a,i=tf,r,o){let s=eH.fromTimeoutMs(i),l=await tb(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/th));try{return await ez(async({deadline:s})=>{if(s?.isExpired())throw new h("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(r&&null!==r.child.exitCode&&void 0!==r.child.exitCode)throw await tc({session:r,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await tb(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new h("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await t_(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)},Math.min(tg,e),o)}catch(e){if(o?.aborted||e6(e))throw e8();d=e}throw new h("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:tw,maxDelayMs:ty,jitter:.2,shouldRetry:td},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||e6(e))throw e8();d||(d=e)}if(o?.aborted)throw e8();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw tu({port:t,endpoints:l,logPath:a,lastError:d});let r=await tN(e,t,n,i);return new Response(r.body,{status:r.status})}throw tu({port:t,endpoints:l,logPath:a,lastError:d})}async function tb(e,t,n){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await tS(e.id,n);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function t_(e,t,n,a){let i,r=new AbortController,o=setTimeout(()=>r.abort(),n);a&&(a.aborted?(clearTimeout(o),r.abort()):(i=()=>r.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:r.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function tS(e,t){if("number"==typeof t&&t<=0)return null;let a="number"==typeof t?Math.max(1,Math.min(tI,t)):tI,i=s.join(r.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(a/1e3)),r=await L("xcrun",["devicectl","device","info","details","--device",e,"--json-output",i,"--timeout",String(t)],{allowFailure:!0,timeoutMs:a});if(0!==r.exitCode||!n.existsSync(i))return null;let o=JSON.parse(n.readFileSync(i,"utf8"));if(o.info?.outcome&&"success"!==o.info.outcome)return null;let s=(o.result?.connectionProperties?.tunnelIPAddress??o.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return s&&s.length>0?s:null}catch{return null}finally{tD(i)}}async function tN(e,t,n,a){let i=JSON.stringify(n),r=tl(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 L("xcrun",r,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=e9({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new h("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:e7(e)})}return{status:200,body:s}}async function tx(){return await new Promise((e,t)=>{let n=l.createServer();n.listen(0,"127.0.0.1",()=>{let a=n.address();if("object"==typeof a&&a?.port){let t=a.port;n.close(()=>e(t))}else n.close(()=>t(new h("COMMAND_FAILED","Failed to allocate port")))}),n.on("error",t)})}function tE(e,t,a,i){t&&n.appendFile(t,e,()=>{}),a&&n.appendFile(a,e,()=>{}),i&&process.stderr.write(e)}function tD(e){try{n.existsSync(e)&&n.unlinkSync(e)}catch{}}let tM=new d;async function tC(e,t,n){let a=tM.getStore()??[];if(a.some(n=>n.locks===e&&n.key===t))return await n();let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(()=>tM.run([...a,{locks:e,key:t}],n));return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}let tO=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tL(e,t,a){if("macos"!==e.platform)return;if(0===t.length)throw new h("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",xctestrunPath:a});let i=Array.from(new Set(t)).sort((e,t)=>t.length-e.length);for(let e of i)if(!n.existsSync(e))throw new h("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:a});for(let e of i)if(0!==O("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await L("codesign",["--remove-signature",e],{allowFailure:!0});try{await L("codesign",["--force","--sign","-",e])}catch(n){let t=n instanceof h?n:new h("COMMAND_FAILED",String(n));throw new h("COMMAND_FAILED","Failed to repair macOS runner product signature",{reason:"RUNNER_PRODUCT_REPAIR_FAILED",productPath:e,xctestrunPath:a,error:t.message,details:t.details})}}}let tT=null;function tk(e){return function e(t){if(!Array.isArray(t))return[];let n=[];for(let a of t)if(!(!a||"object"!=typeof a||Array.isArray(a)))for(let[t,i]of Object.entries(a))":@"!==t&&"#text"!==t&&n.push({name:t,attributes:function(e){if(!e||"object"!=typeof e||Array.isArray(e))return{};let t={};for(let[n,a]of Object.entries(e))"string"==typeof a&&(t[n]=a);return t}(a[":@"]),text:tP(i)??tP(a["#text"]),children:e(i)});return n}((tT??=new c({ignoreAttributes:!1,attributeNamePrefix:"",preserveOrder:!0,trimValues:!0,parseTagValue:!1})).parse(e))}function tR(e,t){for(let n of e){if("dict"===n.name)for(let e=0;e<n.children.length-1;e+=1){let a=n.children[e],i=n.children[e+1];a?.name==="key"&&a.text&&i&&t(a.text,i)}tR(n.children,t)}}function tP(e){if("string"==typeof e){let t=e.trim();return t.length>0?t:null}if(!Array.isArray(e))return null;let t=e.map(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return null;let t=e["#text"];return"string"==typeof t?t.trim():null}).filter(e=>null!==e&&e.length>0).join("").trim();return t.length>0?t:null}let tF="XCTestDevices",t$=".agent-device-backup",tU=".agent-device-xctestdevices-backup-",tG=s.join(r.homedir(),".agent-device","ios-runner"),tV=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),tB=new Map,tj=new Set;function tq(e){return e?.trim()??""}function tW(e=process.env){return tq(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tq(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tH(e=process.env){let t=tq(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tW(e)}.uitests`}let tz=function(e=process.env){let t=tW(e),n=tH(e);return Array.from(new Set([tq(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${n}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function tK(e=r.homedir()){return s.join(e,"Library","Developer","XCTestDevices")}async function tJ(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let a=ti(e.simulatorSetPath);if(!a)return null;let i=s.resolve(a),o=s.resolve(t.xctestDeviceSetPath??tK()),l=s.resolve(t.backupPath??function(e=tK()){return`${e}${t$}`}(o)),d=s.resolve(t.lockDirPath??function(e=r.homedir()){return s.join(e,".agent-device","xctest-device-set.lock")}()),u=t.ownerStartTime??G(process.pid),c=await tZ({lockDirPath:d,owner:{pid:t.ownerPid??process.pid,startTime:u,acquiredAtMs:t.nowMs??Date.now()}});try{if(tX({xctestDeviceSetPath:o,backupPath:l}),function(e,t){if(s.resolve(e)===s.resolve(t))return!0;try{return n.realpathSync.native(e)===n.realpathSync.native(t)}catch{return!1}}(i,o))return await c(),null;n.mkdirSync(i,{recursive:!0}),n.existsSync(o)&&n.renameSync(o,l),function(e){let{requestedSetPath:t,xctestDeviceSetPath:a}=e,i=s.dirname(a),r=s.join(i,`${tF}.agent-device-link-${process.pid}-${Date.now()}`);n.mkdirSync(i,{recursive:!0});try{n.symlinkSync(t,r,"dir"),n.renameSync(r,a)}catch(e){throw n.existsSync(r)&&tY(r),e}}({requestedSetPath:i,xctestDeviceSetPath:o})}catch(e){throw tX({xctestDeviceSetPath:o,backupPath:l}),await c(),new h("COMMAND_FAILED","Failed to redirect XCTest device set path",{requestedSetPath:i,xctestDeviceSetPath:o,backupPath:l,error:String(e)})}let p=!1;return{release:async()=>{if(!p){p=!0;try{tX({xctestDeviceSetPath:o,backupPath:l})}finally{await c()}}}}}function tX(e){let{xctestDeviceSetPath:t,backupPath:a}=e,i=[a,...function(e){let t=s.dirname(e),a=s.basename(e).replace(t$,""),i=a===tF?tU:`${a}${tU}`;try{return n.readdirSync(t).filter(e=>e.startsWith(i)).sort().map(e=>s.join(t,e))}catch{return[]}}(a)],r=i.find(e=>n.existsSync(e)),o=n.existsSync(t)&&n.lstatSync(t).isSymbolicLink();if(r){if(o&&tY(t),n.existsSync(t))if(!o)return void E({level:"warn",phase:"ios_runner_xctest_device_set_restore_collision",data:{xctestDeviceSetPath:t,activeBackupPath:r}});else r!==a?n.rmSync(r,{recursive:!0,force:!0}):n.rmSync(a,{recursive:!0,force:!0});else n.mkdirSync(s.dirname(t),{recursive:!0}),n.renameSync(r,t);for(let e of i)e!==r&&n.existsSync(e)&&n.rmSync(e,{recursive:!0,force:!0});return}o&&(E({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),tY(t))}function tY(e){!n.existsSync(e)||n.lstatSync(e).isSymbolicLink()&&n.unlinkSync(e)}async function tZ(e){let{lockDirPath:t,owner:a}=e,i=s.join(t,"owner.json"),r=Date.now()+3e4;for(n.mkdirSync(s.dirname(t),{recursive:!0});Date.now()<r;)try{n.mkdirSync(t),function(e,t){let a=`${e}.${process.pid}.${Date.now()}.tmp`;n.writeFileSync(a,JSON.stringify(t),"utf8"),n.renameSync(a,e)}(i,a);let e=!1;return async()=>{e||(e=!0,n.rmSync(t,{recursive:!0,force:!0}))}}catch(e){if("EEXIST"!==e.code)throw e;if(function(e,t){let a=null;try{a=n.statSync(e)}catch{return!0}let i=function(e){try{return JSON.parse(n.readFileSync(e,"utf8"))}catch{return null}}(t);if(i){var r;return!(Number.isInteger((r=i).pid)&&!(r.pid<=0)&&U(r.pid)&&(!r.startTime||G(r.pid)===r.startTime))&&(n.rmSync(e,{recursive:!0,force:!0}),!0)}return!(Date.now()-a.mtimeMs<5e3)&&(n.rmSync(e,{recursive:!0,force:!0}),!0)}(t,i))continue;await P(100)}throw new h("COMMAND_FAILED","Timed out waiting for XCTest device set lock",{lockDirPath:t})}async function tQ(e,t){var a;let i,r=(a=e,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?s.resolve(i):"macos"===a.platform?s.join(tG,"derived","macos"):"simulator"===a.kind?s.join(tG,"derived"):s.join(tG,"derived",a.kind)),o=function(){let e=s.dirname(u(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=s.join(t,"package.json");if(n.existsSync(e))return t;t=s.dirname(t)}return e}();return await tC(tB,r,async()=>{eB(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(nt("clean","forced_clean",{derived:r}),ne(r),t0(r));let a=function(e){let t=e.findXctestrun(e.derived);if(!t)return{reason:"missing_xctestrun",xctestrunPath:null};let n=e.resolveExistingXctestrunProductPaths(t);return n?e.xctestrunReferencesProjectRoot(t,e.projectRoot)?{reason:"reuse_ready",xctestrunPath:t,productPaths:n}:{reason:"project_root_mismatch",xctestrunPath:t,productPaths:n}:{reason:"missing_products",xctestrunPath:t,productPaths:[]}}({derived:r,projectRoot:o,findXctestrun:t=>t2(t,e),xctestrunReferencesProjectRoot:t4,resolveExistingXctestrunProductPaths:nn});if("reuse_ready"!==a.reason&&nt("rebuild",a.reason,{derived:r,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await tL(e,a.productPaths,a.xctestrunPath),nt("reuse","reuse_ready",{derived:r,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof h))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tO.has(t)}(e))throw e;nt("rebuild","repair_failed",{derived:r,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(ne(r),t0(r));let i=s.join(o,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!n.existsSync(i))throw new h("COMMAND_FAILED","iOS runner project not found",{projectPath:i});await t8(e,i,r,t);let l=t2(r,e);if(!l)throw new h("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=nn(l);if(!d)throw new h("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await tL(e,d,l),nt("build","built_new",{derived:r,xctestrunPath:l}),l})}function t0(e){try{if(!n.existsSync(e))return;if("derived"!==s.basename(e))return void n.rmSync(e,{recursive:!0,force:!0});for(let a of n.readdirSync(e,{withFileTypes:!0})){var t;t=a.name,t1.has(t)&&n.rmSync(s.join(e,a.name),{recursive:!0,force:!0})}}catch{}}let t1=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function t2(e,t){if(!n.existsSync(e))return null;let a=[],i=[e];for(;i.length>0;){let e=i.pop();for(let t of n.readdirSync(e,{withFileTypes:!0})){let r=s.join(e,t.name);if(t.isDirectory()){i.push(r);continue}if(t.isFile()&&t.name.endsWith(".xctestrun"))try{let e=n.statSync(r);a.push({path:r,mtimeMs:e.mtimeMs})}catch{}}}return 0===a.length?null:(a.sort((e,n)=>{if(t){let a=t3(n.path,t)-t3(e.path,t);if(0!==a)return a}return n.mtimeMs-e.mtimeMs||e.path.localeCompare(n.path)}),a[0]?.path??null)}function t3(e,t){var n;let a=0,i=e.toLowerCase();s.basename(i).startsWith("agentdevicerunner.env.")&&(a-=1e3),i.includes(`${s.sep}macos${s.sep}`)&&(a-=5e3);let r="macos"===(n=t).platform?{preferred:["macos"],disallowed:["iphoneos","iphonesimulator","appletvos","appletvsimulator"]}:"tv"===n.target?"simulator"===n.kind?{preferred:["appletvsimulator"],disallowed:["appletvos","iphoneos","iphonesimulator","macos"]}:{preferred:["appletvos"],disallowed:["appletvsimulator","iphoneos","iphonesimulator","macos"]}:"simulator"===n.kind?{preferred:["iphonesimulator"],disallowed:["iphoneos","appletvos","appletvsimulator","macos"]}:{preferred:["iphoneos"],disallowed:["iphonesimulator","appletvos","appletvsimulator","macos"]};return r.preferred.length>0&&(r.preferred.some(e=>i.includes(e))?a+=2e3:a-=500),r.disallowed.some(e=>i.includes(e))&&(a-=2500),a}function t4(e,t){try{let a=n.readFileSync(e,"utf8"),i=new Set([t]);try{i.add(n.realpathSync(t))}catch{}for(let e of i)if(a.includes(e))return!0;return!1}catch{return!1}}async function t5(e,t,a){let i,r=s.dirname(e),o=a.replace(/[^a-zA-Z0-9._-]/g,"_"),l=s.join(r,`AgentDeviceRunner.env.${o}.json`),d=s.join(r,`AgentDeviceRunner.env.${o}.xctestrun`),u=await L("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==u.exitCode||!u.stdout.trim())throw new h("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:u.stderr});try{let e=JSON.parse(u.stdout);if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Root must be an object");i=e}catch(t){throw new h("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let c=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},p=i.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&&c(e)}for(let[e,t]of Object.entries(i))t&&"object"==typeof t&&!Array.isArray(t)&&t.TestBundlePath&&(c(t),i[e]=t);n.writeFileSync(l,JSON.stringify(i,null,2));let f=await L("plutil",["-convert","xml1","-o",d,l],{allowFailure:!0});if(0!==f.exitCode)throw new h("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:d,stderr:f.stderr});return{xctestrunPath:d,jsonPath:l}}async function t8(e,t,n,a){let i=function(e=process.env){let t=tW(e),n=tH(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${n}`]}(process.env),r=function(e=process.env,t=!1,n="ios"){if("macos"===n)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()||"",r=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}`),r&&o.push(`PROVISIONING_PROFILE_SPECIFIER=${r}`),o}(process.env,"device"===e.kind,e.platform),o="device"===e.kind?["-allowProvisioningUpdates"]:[],s=await tJ(e);try{var l;let s;await D("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",t7(e),"1","-destination",(l=e,s=t6(l),"macOS"===s?`platform=macOS,arch=${t9()}`:"simulator"===l.kind?`platform=${s} Simulator,id=${l.id}`:`generic/platform=${s}`),"-derivedDataPath",n,"COMPILER_INDEX_STORE_ENABLE=NO","ENABLE_CODE_COVERAGE=NO",...i,...o,...r],{detached:!0,onSpawn:e=>{tj.add(e),e.on("close",()=>{tj.delete(e)})},onStdoutChunk:e=>{tE(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{tE(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(r){let e,t,n=r instanceof h?r:new h("COMMAND_FAILED",String(r)),i=(e=n.details?JSON.stringify(n.details):"",(t=`${n.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 h("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:n.message,details:n.details,logPath:a.logPath,hint:i})}finally{await s?.release()}}function t6(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new h("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 t9(){return"arm64"===process.arch?"arm64":"x86_64"}function t7(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function ne(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return eB(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new h("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 nt(e,t,n){E({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...n}})}function nn(e){let t=function(e){let t=function(e){try{let t=O("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 a,i,r=t;let e=new Set,n=t=>{if(t&&"object"==typeof t)for(let n of function(e){let t=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),n=new Set;for(let[a,i]of Object.entries(e))if(t.has(a)){if("string"==typeof i){n.add(i);continue}if(Array.isArray(i))for(let e of i)"string"==typeof e&&n.add(e)}return Array.from(n)}(t))e.add(n)};n(r);let o=r.TestConfigurations;if(Array.isArray(o))for(let e of o){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)n(e)}for(let e of Object.values(r))e&&"object"==typeof e&&"TestBundlePath"in e&&n(e);return Array.from(e)}if("darwin"===process.platform)return null;try{let t;return a=n.readFileSync(e,"utf8"),i=tk(a),t=new Set,tR(i,(e,n)=>{if(tV.has(e)){if("string"===n.name&&n.text)return void t.add(n.text);if("array"===n.name)for(let e of n.children)"string"===e.name&&e.text&&t.add(e.text)}}),Array.from(t)}catch{return null}}(e);if(!t||0===t.length)return null;let a=s.dirname(e),i=new Set,r=new Set,o=[];for(let e of t){if(e.startsWith("__TESTROOT__/")){let t=e.slice(13),o=s.join(a,t);if(!n.existsSync(o))return null;i.add(o);let l=function(e){let t=/\.app(?:\/|$)/.exec(e);return t&&void 0!==t.index?e.slice(0,t.index+4):null}(t);l&&r.add(s.join(a,l));continue}e.startsWith("__TESTHOST__/")&&o.push(e.slice(13))}for(let e of o){let t=Array.from(r).find(t=>n.existsSync(s.join(t,e)));if(!t)return null;i.add(s.join(t,e))}return Array.from(i)}let na=new Map,ni=new Map;async function nr(e,t){return await tC(ni,e.id,async()=>{var n;let a,i,r=na.get(e.id);if(r){if(function(e){return!!e&&U(e)}(r.child.pid))return r;await nd(e.id,r)}await ("simulator"!==(n=e).kind?Promise.resolve():nm(n)),await no(e);let o=await tQ(e,t),s=await tx(),{xctestrunPath:l,jsonPath:d}=await t5(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),u=await tJ(e);try{let t;({child:a,wait:i}=C("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",t7(e),"1","-destination-timeout",String(tA),"-xctestrun",l,"-destination",(t=t6(e),"macOS"===t?`platform=macOS,arch=${t9()}`:"simulator"===e.kind?`platform=${t} Simulator,id=${e.id}`:`platform=${t},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0}))}catch(e){throw await u?.release(),e}a.stdout?.on("data",e=>{tE(e,t.logPath,t.traceLogPath,t.verbose)}),a.stderr?.on("data",e=>{tE(e,t.logPath,t.traceLogPath,t.verbose)});let c={sessionId:`${e.id}:${s}:${Date.now()}`,device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:d,testPromise:i,child:a,ready:!1,simulatorSetRedirect:u??void 0};return na.set(e.id,c),c})}async function no(e){if("simulator"===e.kind)for(let t of tz){let n=await L("xcrun",tl(e,["uninstall",e.id,t]),{allowFailure:!0});if(0!==n.exitCode){let e=`${n.stdout}
7
+ ${n.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}}}function ns(e){let t=na.get(e);return t?{sessionId:t.sessionId,alive:function(e){return!!e&&U(e)}(t.child.pid)}:null}async function nl(e){await tC(ni,e.deviceId,async()=>{await nd(e.deviceId,e)})}async function nd(e,t){let n=t??na.get(e);if(n){try{await tv(n.device,n.port,{command:"shutdown"},void 0,15e3)}catch{await nf(n.child.pid,"SIGTERM")}try{await Promise.race([n.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await nf(n.child.pid,"SIGKILL"),tD(n.xctestrunPath),tD(n.jsonPath),await n.simulatorSetRedirect?.release(),na.get(e)===n&&na.delete(e)}}async function nu(e){await tC(ni,e,async()=>{await nd(e)})}async function nc(){let e=Array.from(na.values()),t=Array.from(tj);await Promise.allSettled(e.map(async e=>{await nf(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await nf(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await nf(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await nf(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await nf(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await nf(e.pid,"SIGKILL"),tj.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function np(){await nc();let e=Array.from(na.keys());await Promise.allSettled(e.map(async e=>{await nu(e)}));let t=Array.from(tj);await Promise.allSettled(t.map(async e=>{try{await nf(e.pid,"SIGTERM"),await nf(e.pid,"SIGKILL")}finally{tj.delete(e)}}))}async function nf(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let n="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await L("pkill",[`-${n}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function nm(e){await L("xcrun",tl(e,["bootstatus",e.id,"-b"]),{timeoutMs:tf})}async function nh(e,t,n,a,i,r){let o=await tv(e,t.port,n,a,i,t,r);return await nw(o,t,a)}async function nw(e,t,n){let a,i=await e.text();try{let e=JSON.parse(i);a=e&&"object"==typeof e?e:{}}catch{throw new h("COMMAND_FAILED","Invalid runner response",{text:i})}if(!a.ok){let e=a.error?.code;throw new h("string"==typeof e&&e.trim().length>0?m(e):"COMMAND_FAILED",("string"==typeof a.error?.message?a.error.message:void 0)??"Runner error",{runner:a,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:n})}return(t.ready=!0,a.data&&"object"==typeof a.data&&!Array.isArray(a.data))?a.data:{}}async function ny(e,t,n={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new h("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new h("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(tp(n.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?eK(()=>(tp(n.requestId),ng(e,t,n)),{shouldRetry:e=>{tp(n.requestId);if(!(e instanceof h)||"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"))}}):ng(e,t,n)}async function ng(e,t,n={}){let a;tp(n.requestId);let i=e5(n.requestId);try{let r=(a=await nr(e,n)).ready?tm:tf;return await nh(e,a,t,n.logPath,r,i)}catch(o){let r=o instanceof h?o:new h("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===r.code&&"string"==typeof r.message&&r.message.includes("Runner did not accept connection")&&td(r)&&a?.ready){tp(n.requestId),a?await nl(a):await nu(e.id),a=await nr(e,n);let r=await tv(a.device,a.port,t,n.logPath,tf,void 0,i);return await nw(r,a,n.logPath)}throw o}}let nI="agent-device-macos-helper",nA="AGENT_DEVICE_MACOS_HELPER_BIN",nv=s.join(r.homedir(),".agent-device","macos-helper","current"),nb=s.join(nv,"manifest.json"),n_=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function nS(e){let t=e.trim();if(!n_.test(t))throw new h("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function nN(){return function(e){let t=s.dirname(e);for(;;){let e=s.join(t,"macos-helper");if(a(s.join(e,"Package.swift")))return e;let n=s.dirname(t);if(n===t)break;t=n}throw new h("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(u(import.meta.url))}async function nx(e){let t=await i.readdir(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=s.join(e,t.name);return t.isDirectory()?".build"===t.name?[]:await nx(n):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[n]:[]}))).flat().sort()}async function nE(e){let t=await nx(e),n=p("sha256");for(let a of t)n.update(s.relative(e,a)),n.update("\0"),n.update(await i.readFile(a)),n.update("\0");let a=await L("swift",["--version"],{allowFailure:!0,cwd:e,timeoutMs:1e4});return n.update("swift-version"),n.update("\0"),n.update(a.stdout||a.stderr||`exit:${a.exitCode}`),n.update("\0"),n.digest("hex")}async function nD(){try{let e=JSON.parse(await i.readFile(nb,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function nM(){let e=await k(process.env[nA],nA);if(e)return e;let t=nN(),n=await nE(t),a=s.join(nv,nI);try{if(await nD()===n)return await i.access(a),a}catch{}let r=s.join(nN(),".build","release",nI);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await L("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await i.mkdir(nv,{recursive:!0});let o=`${a}.tmp`;return await i.copyFile(r,o),await i.rename(o,a),await i.chmod(a,493),await i.writeFile(nb,`${JSON.stringify({fingerprint:n},null,2)}
8
+ `,"utf8"),a}async function nC(e){let t=process.env[nA]?.trim();if("darwin"!==process.platform&&!t)throw new h("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let n=await nM(),a=await L(n,e,{allowFailure:!0,timeoutMs:3e4}),i=a.stdout.trim(),r=null;if(i)try{r=JSON.parse(i)}catch{r=null}if(0===a.exitCode&&r?.ok)return r.data;throw new h("COMMAND_FAILED",r&&!r.ok?r.error?.message??`macOS helper exited with code ${a.exitCode}`:i||a.stderr.trim()||`macOS helper exited with code ${a.exitCode}`,{helperPath:n,args:e,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,...r&&!r.ok?r.error?.details:{}})}async function nO(){return await nC(["app","frontmost"])}async function nL(e){return await nC(["app","quit","--bundle-id",nS(e)])}async function nT(e,t){return await nC(["permission",e,t])}async function nk(e,t={}){let n=["alert",e];return t.bundleId&&n.push("--bundle-id",nS(t.bundleId)),t.surface&&n.push("--surface",t.surface),await nC(n)}async function nR(e,t={}){let n=["snapshot","--surface",e];return t.bundleId&&n.push("--bundle-id",nS(t.bundleId)),await nC(n)}async function nP(e,t,n={}){let a=["read","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",nS(n.bundleId)),n.surface&&a.push("--surface",n.surface),await nC(a)}async function nF(e,t,n={}){let a=["press","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",nS(n.bundleId)),n.surface&&a.push("--surface",n.surface),await nC(a)}async function n$(e,t={}){let n=["screenshot","--out",e];return t.surface&&n.push("--surface",t.surface),t.fullscreen&&n.push("--fullscreen"),await nC(n)}function nU(e,t){return["-s",e.id,...t]}async function nG(){if(await V(),!await R("adb"))throw new h("TOOL_MISSING","adb not found in PATH")}function nV(e,t){let n=`${e}
9
+ ${t}`.toLowerCase();return n.includes("no shell command implementation")||n.includes("unknown command")}function nB(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let n=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!n)return!1;let a=n[1]?.toLowerCase(),i=n[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function nj(e,t){let n,a=e?.trim();return a?a:"http"===(n=t.trim().split(":")[0]?.toLowerCase())||"https"===n?"com.apple.mobilesafari":void 0}let nq=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function nW(e){return`${e.stdout}
10
+ ${e.stderr}`}function nH(e,t){return["-s",e,...t]}function nz(e){return e.startsWith("emulator-")}function nK(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function nJ(e,t=eW){return L("adb",nH(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function nX(e,t){let n=t.replace(/_/g," ").trim();if(!nz(e))return n||e;let a=await nZ(e);return a?a.replace(/_/g," "):n||e}async function nY(e,t,n){try{return await n("adb",nH(e,t),{allowFailure:!0,timeoutMs:1e4})}catch(e){var a;if("COMMAND_FAILED"===(a=f(e)).code&&"number"==typeof a.details?.timeoutMs)return;throw e}}async function nZ(e,t=L){for(let n of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await nY(e,["shell","getprop",n],t);if(!a)continue;let i=a.stdout.trim();if(0===a.exitCode&&i.length>0)return i}let n=await nY(e,["emu","avd","name"],t);if(!n)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}(n.stdout);if(0===n.exitCode&&a)return a}async function nQ(e,t){let n=nW(await L("adb",nH(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eW})).toLowerCase();return!!n.includes("true")||!n.includes("false")&&null}async function n0(e){return(await Promise.all(nq.map(async t=>await nQ(e,t)))).some(e=>!0===e)}async function n1(e){var t;let n;return"tv"===((n=nW(await L("adb",nH(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eW})).toLowerCase()).includes("tv")||n.includes("leanback")?"tv":null)||await n0(e)?"tv":(t=nW(await L("adb",nH(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eW})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function n2(e={}){if(await V(),!await R("adb"))throw new h("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??to(void 0),n=(await n3()).filter(e=>!t||t.has(e.serial));return await Promise.all(n.map(async({serial:e,rawModel:t})=>{let[n,a,i]=await Promise.all([nX(e,t),n6(e),n1(e)]);return{platform:"android",id:e,name:n,kind:nz(e)?"emulator":"device",target:i,booted:a}}))}async function n3(){return(await L("adb",["devices","-l"],{timeoutMs:eW})).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 n4(){let e=await L("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eW});if(0!==e.exitCode)throw new h("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 n5(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await n8(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await P(1e3)}throw new h("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 n8(e,t){let n=nK(e);for(let e of(await n3()).filter(e=>(!t||e.serial===t)&&nz(e.serial)))if(nK(e.rawModel)===n||nK(await nX(e.serial,e.rawModel))===n)return e.serial}async function n6(e){try{let t=await nJ(e);return"1"===t.stdout.trim()}catch{return!1}}async function n9(e){var t,n;let a;await V();let i=e.avdName.trim();if(!i)throw new h("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let r=e.timeoutMs??12e4;if(!await R("adb"))throw new h("TOOL_MISSING","adb not found in PATH");if(!await R("emulator"))throw new h("TOOL_MISSING","emulator not found in PATH");let o=await n4(),s=function(e,t){let n=e.find(e=>e===t);if(n)return n;let a=nK(t);return e.find(e=>nK(e)===a)}(o,i);if(!s)throw new h("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 n2(),n=e.serial,a=nK(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!n||e.id===n)&&nK(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),M("emulator",t)}let u=d??await n5({avdName:s,serial:e.serial,timeoutMs:r}),c=Math.max(1e3,r-(Date.now()-l));await n7(u.id,c);let p=(await n2()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function n7(e,t=6e4){let n,a=eH.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),r=!1;try{await ez(async({deadline:i})=>{if(i?.isExpired())throw r=!0,new h("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 nJ(e,Math.min(o,eW));if(n=s,"1"!==s.stdout.trim())throw new h("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=e9({error:e,stdout:n?.stdout,stderr:n?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>e9({error:e,stdout:n?.stdout,stderr:n?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=f(c),o=n?.stdout,s=n?.stderr,l=n?.exitCode,d=e9({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:e7(d),stdout:o,stderr:s,exitCode:l};if(r||"ANDROID_BOOT_TIMEOUT"===d)throw new h("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new h("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new h("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new h(i.code,i.message,{...u,...i.details??{}},i.cause)}}let ae=/\.(?:apk|aab)$/i,at=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function an(e){var t,n;let a=e.trim();return 0===a.length?"other":ae.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!at.test(t))?"binary":"package":(n=a,at.test(n))?"package":"other"}function aa(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}async function ai(e,t){let n="url"===e.kind&&q(e.url),a=await j({source:e,isInstallablePath:(e,t)=>{var n;let a;return t.isFile()&&(n=e,".apk"===(a=s.extname(n).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||n,signal:t?.signal}),i=t?.resolveIdentity===!1?{}:await ar(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function ar(e){let t=s.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await B(e)}}let ao={settings:{type:"intent",value:"android.settings.SETTINGS"}},as="android.intent.category.LAUNCHER",al="android.intent.category.LEANBACK_LAUNCHER",ad="android.intent.category.DEFAULT",au="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function ac(e,t){let n=t.trim();if("package"===an(n))return{type:"package",value:n};let a=ao[n.toLowerCase()];if(a)return a;let i=(await L("adb",nU(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(n.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new h("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 h("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:au})}async function ap(e,t="all"){let n=await af(e);return("user-installed"===t?(await ah(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:aw(e)}))}async function af(e){let t=new Set;for(let n of am(e,{includeFallbackWhenUnknown:!0})){let a=await L("adb",nU(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",n]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of H(a.stdout))t.add(e)}return t}function am(e,t={}){return"tv"===e.target?[al]:"mobile"===e.target?[as]:t.includeFallbackWhenUnknown?[as,al]:[as]}async function ah(e){return z((await L("adb",nU(e,["shell","pm","list","packages","-3"]))).stdout)}function aw(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),n=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=n[n.length-1]??e;for(let e=n.length-1;e>=0;e-=1){let i=n[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 ay(e){let t=await ag(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let n=await ag(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return n||{}}async function ag(e,t){for(let n of t){let t=W((await L("adb",nU(e,n),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function aI(e,t,n){var a,i;let r;e.booted||await n7(e.id);let o=t.trim();if(nB(o)){if(n)throw new h("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await L("adb",nU(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await ac(e,t),l=am(e)[0]??as;if("intent"===s.type){if(n)throw new h("INVALID_ARGS","Activity override requires a package name, not an intent");await L("adb",nU(e,["shell","am","start","-W","-a",s.value]));return}if(n){let t=n.includes("/")?n:`${s.value}/${n.startsWith(".")?n:`.${n}`}`;try{await L("adb",nU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ad,"-c",l,"-n",t]))}catch(t){throw await ab(e,s.value,t),t}return}let d=await L("adb",nU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ad,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,r=`${a}
11
+ ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)))return;let u=await aS(e,s.value);if(!u){if(!await av(e,s.value))throw aA(s.value);throw new h("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr})}await L("adb",nU(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",ad,"-c",l,"-n",u]))}function aA(e){return new h("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:au})}async function av(e,t){let n=await L("adb",nU(e,["shell","pm","path",t]),{allowFailure:!0}),a=`${n.stdout}
12
+ ${n.stderr}`;return!!(0===n.exitCode&&/\bpackage:/i.test(a))||(a_(a),!1)}async function ab(e,t,n){if(a_(n instanceof h?`${String(n.details?.stdout??"")}
13
+ ${String(n.details?.stderr??"")}`:"")||!await av(e,t))throw aA(t)}function a_(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 aS(e,t){for(let n of Array.from(new Set(am(e,{includeFallbackWhenUnknown:!0})))){let a=await L("adb",nU(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",n,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 n=t[e];if(n.includes("/"))return n.split(/\s+/)[0]}return null}(a.stdout);if(i)return i}return null}async function aN(e){e.booted||await n7(e.id)}async function ax(e,t){if("settings"===t.trim().toLowerCase())return void await L("adb",nU(e,["shell","am","force-stop","com.android.settings"]));let n=await ac(e,t);if("intent"===n.type)throw new h("INVALID_ARGS","Close requires a package name, not an intent");await L("adb",nU(e,["shell","am","force-stop",n.value]))}async function aE(e,t){let n=await ac(e,t);if("intent"===n.type)throw new h("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await L("adb",nU(e,["uninstall",n.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 h("COMMAND_FAILED",`adb uninstall failed for ${n.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:n.value}}let aD=null;async function aM(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(aD?.key===e)return aD.invocation;if(await R("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return aD={key:e,invocation:t},t}let t=await T(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,"AGENT_DEVICE_BUNDLETOOL_JAR");if(!t)throw new h("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");let n={cmd:"java",prefixArgs:["-jar",t]};return aD={key:e,invocation:n},n}async function aC(e){let t=await aM();await L(t.cmd,[...t.prefixArgs,...e])}async function aO(e,t){let n,a=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-aab-")),o=s.join(a,"bundle.apks"),l=(n=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&n.length>0?n:"universal";try{await aC(["build-apks","--bundle",t,"--output",o,"--mode",l]),await aC(["install-apks","--apks",o,"--device-id",e.id])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function aL(e,t){".aab"===s.extname(t).toLowerCase()?await aO(e,t):await L("adb",nU(e,["install","-r",t]))}async function aT(e){return new Set((await L("adb",nU(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function ak(e,t){let n=Array.from(await aT(e)).filter(e=>!t.has(e));if(1===n.length)return n[0]}async function aR(e,t){e.booted||await n7(e.id),await aL(e,t)}async function aP(e,t,n){let a=n?void 0:await aT(e);return await aR(e,t),n??(a?await ak(e,a):void 0)}async function aF(e,t){e.booted||await n7(e.id);let n=await ai({kind:"path",path:t});try{let t=await aP(e,n.installablePath,n.packageName),a=t?aw(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await n.cleanup()}}async function a$(e,t,n){e.booted||await n7(e.id);let{package:a}=await aE(e,t),i=await ai({kind:"path",path:n},{resolveIdentity:!1});try{return await aR(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function aU(e){let t=e.direction,n="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 h("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 h("INVALID_ARGS","scroll pixels must be a positive integer");return Math.max(1,Math.round(e))}(e.pixels):Math.round(n*a),r=Math.max(1,Math.round(.05*n)),o=Math.max(1,Math.min(i,Math.max(1,n-2*r))),s=Math.round(o/2),l=Math.round(e.referenceWidth/2),d=Math.round(e.referenceHeight/2),u=(n,a,i,r)=>({direction:t,x1:n,y1:a,x2:i,y2:r,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 aG(e,t,n){let a=function(e){let t=0,n=0,a=[...e.children];for(;a.length>0;){let e=a.pop();t+=1,n=Math.max(n,e.depth),a.push(...e.children)}return{rawNodeCount:t,maxDepth:n}}(e),i=[],r=[],o=!1,s=n.depth??1/0,l=n.scope?function(e,t){let n=t.toLowerCase(),a=[...e.children],i=0;for(;i<a.length;){let e=a[i++],t=e.label?.toLowerCase()??"",r=e.value?.toLowerCase()??"",o=e.identifier?.toLowerCase()??"";if(t.includes(n)||r.includes(n)||o.includes(n))return e;a.push(...e.children)}return null}(e,n.scope):null,d=l?[l]:e.children,u=new Map,c=e=>{let t=u.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||c(t))return u.set(e,!0),!0;return u.set(e,!1),!1},p=(e,a,l,d=!1,u=!1)=>{var f,m,h,w,y,g;let I,A,v,b,_,S,N,x;if(i.length>=t){o=!0;return}if(a>s)return;let E=!!n.raw||(f=e,m=n,h=d,w=c(e),y=u,A=aW(f.type),v=!!(f.label&&f.label.trim().length>0),b=!!(f.identifier&&f.identifier.trim().length>0),_=v&&!aH(f.label??""),S=b&&!aH(f.identifier??""),N=(I=(g=A).split(".").pop()??g).includes("layout")||"viewgroup"===I||"view"===I,x="imageview"===A||"imagebutton"===A,m.interactiveOnly?!!(f.hittable||ee(A)&&w)||!!(_||S)&&!x&&(!N||!!y)&&(h||w||y):m.compact?_||S||!!f.hittable:!N&&!x||!!f.hittable||!!_||!!S&&!!w||w),D=l;E&&(D=i.length,r.push(e),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:a,parentIndex:l,...e.hiddenContentAbove?{hiddenContentAbove:!0}:{},...e.hiddenContentBelow?{hiddenContentBelow:!0}:{}}));let M=d||!!e.hittable,C=u||function(e){if(!e)return!1;let t=aW(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let t of e.children)if(p(t,a+1,D,M,C),o)return};for(let e of d)if(p(e,0,void 0,!1,!1),o)break;return o?{nodes:i,sourceNodes:r,truncated:o,analysis:a}:{nodes:i,sourceNodes:r,analysis:a}}function aV(e){let t=function(e){let t=new Map,n=e.indexOf(" "),a=e.lastIndexOf(">");if(n<0||a<=n)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,r=n;for(;r<a;){for(;r<a;){let t=e[r];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;r+=1}if(r>=a)break;let n=e[r];if("/"===n||">"===n)break;i.lastIndex=r;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),r=i.lastIndex}return t}(e),n=e=>{let n=aB(t,e);if(null!==n)return"true"===n};return{text:aB(t,"text"),desc:aB(t,"content-desc"),resourceId:aB(t,"resource-id"),className:aB(t,"class"),bounds:aB(t,"bounds"),clickable:n("clickable"),enabled:n("enabled"),focusable:n("focusable"),focused:n("focused")}}function aB(e,t){return e.get(t)??null}function aj(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let n=Number(t[1]),a=Number(t[2]);return{x:n,y:a,width:Math.max(0,Number(t[3])-n),height:Math.max(0,Number(t[4])-a)}}function aq(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},n=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){n.length>1&&n.pop(),i=a.exec(e);continue}let r=aV(t),o=aj(r.bounds),s=n[n.length-1],l={type:r.className,label:r.text||r.desc,value:r.text,identifier:r.resourceId,rect:o,enabled:r.enabled,hittable:r.clickable??r.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||n.push(l),i=a.exec(e)}return t}function aW(e){return e?e.toLowerCase():""}function aH(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function az(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function aK(e,t){let n=Math.max(24,Math.round(.2*Math.min(e.size,t.size))),a=Math.max(48,Math.round(.15*Math.min(e.crossSize,t.crossSize)));return Math.abs(e.size-t.size)<=n&&Math.abs(e.crossSize-t.crossSize)<=a}function aJ(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function aX(e,t={}){let n=await aZ(e);if(!t.interactiveOnly){let a=function(e,t){let{sourceNodes:n,...a}=aG(aq(e),800,t);return a}(n,t);return function(e,t){for(let[n,a]of e){let e=t[n];e&&(a.hiddenContentAbove&&(e.hiddenContentAbove=!0),a.hiddenContentBelow&&(e.hiddenContentBelow=!0))}}(await aY(e,a.nodes),a.nodes),a}let a=aq(n),i=aG(a,800,{...t,interactiveOnly:!1}),r=aG(a,800,t),o=await aY(e,i.nodes);a3(o,i,r),0===o.size&&a3(K(ei(i.nodes)),i,r);let{sourceNodes:s,...l}=r;return l}async function aY(e,t){if(!t.some(e=>ee(e.type)))return new Map;let n=await a2(e);return n?function(e,t){let n=function(e){let t={className:"root",rect:{x:0,y:0,width:0,height:0},children:[]},n=[{indent:-1,node:t}],a=/^(\s*)([\w.$]+)\{[^}]* (-?\d+),(-?\d+)-(-?\d+),(-?\d+) #/;for(let t of e.split("\n")){let e=a.exec(t);if(!e)continue;let i=e[1].length,r=Number(e[3]),o=Number(e[4]),s=Number(e[5]),l=Number(e[6]),d={className:e[2],rect:{x:r,y:o,width:Math.max(0,s-r),height:Math.max(0,l-o)},children:[]};for(;n.length>1&&i<=n[n.length-1].indent;)n.pop();n[n.length-1].node.children.push(d),n.push({indent:i,node:d})}return t.children.length>0?t:null}(t);if(!n)return new Map;let a=function(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();if(ee(e.className)){let n=function(e){let t=e.children[0];if(!t)return null;let n=Math.max(t.rect.height,...t.children.map(e=>e.rect.y+e.rect.height)),a=t.children.filter(e=>e.rect.height>0).map(t=>aJ(t.rect,e.rect)).sort((e,t)=>e.start-t.start);return 0===a.length?null:{rect:e.rect,contentExtent:n,contentBlocks:a}}(e);n&&t.push(n)}n.push(...e.children)}return t}(n);if(0===a.length)return new Map;let i=new Map;for(let t of e){if(!t.rect||!ee(t.type))continue;let n=function(e,t){let n=null,a=1/0;for(let i of t){let t=Math.abs(i.rect.width-e.width)+Math.abs(i.rect.height-e.height);if(t>32)continue;let r=4*t+(Math.abs(i.rect.x-e.x)+Math.abs(i.rect.y-e.y));r<a&&(n=i,a=r)}return n}(t.rect,a);if(!n)continue;let r=function(e,t){let n=function(e,t){let n=t,a=new Set;for(;!a.has(n.index);){var i,r;a.add(n.index);let o=e.filter(e=>e.parentIndex===n.index&&e.rect);if(1!==o.length)return n;let s=o[0];if(i=s.rect,r=t.rect,i.x!==r.x||i.y!==r.y||i.width!==r.width||i.height!==r.height)return n;n=s}return t}(e,t);return e.filter(e=>e.parentIndex===n.index&&e.rect).map(e=>e.rect).filter(e=>e.height>0).sort((e,t)=>e.y-t.y).map(e=>aJ(e,t.rect))}(e,t),o=function(e){let{viewportRect:t,visibleBlocks:n,nativeScrollView:a}=e;if(0===n.length||0===a.contentBlocks.length)return null;let i=function(e){if(0===e.contentBlocks.length)return null;let t=e.contentBlocks[0],n=e.contentBlocks[e.contentBlocks.length-1];if(!t||!n)return null;let a=az(e.contentBlocks.map(e=>e.size))??e.rect.height,i=Math.max(48,Math.round(.5*a)),r=Math.max(24,Math.round(.25*a)),o=t.start>=i,s=e.contentExtent-(n.start+n.size)>=r;return o||s?{above:o,below:s}:null}(a),r=function(e,t){let n=new Map;for(let a of e)for(let e of t){if(!aK(a,e))continue;let t=a.start-e.start,i=8*Math.round(t/8),r=n.get(i)??[];r.push(t),n.set(i,r)}let a=null;for(let e of n.values())(!a||e.length>a.length)&&(a=e);if(!a||a.length<2)return null;let i=[...a].sort((e,t)=>e-t);return i[Math.floor(i.length/2)]??null}(a.contentBlocks,n)??function(e){let{nativeBlocks:t,visibleBlocks:n,viewportExtent:a,contentExtent:i}=e,r=[],o=[];for(let e of t)for(let t of n){if(!aK(e,t))continue;let n=e.start-t.start;16>=Math.abs(n)&&r.push(n),16>=Math.abs(n+a-i)&&o.push(n)}return o.length>0?az(o):r.length>0?az(r):null}({nativeBlocks:a.contentBlocks,visibleBlocks:n,viewportExtent:t.height,contentExtent:a.contentExtent});if(null===r)return i;let o=t.height;return{above:(i?.above??!1)||r>16,below:(i?.below??!1)||r+o<a.contentExtent-16}}({viewportRect:t.rect,visibleBlocks:r,nativeScrollView:n});if(!o)continue;let s={};o.above&&(s.hiddenContentAbove=!0),o.below&&(s.hiddenContentBelow=!0),(s.hiddenContentAbove||s.hiddenContentBelow)&&i.set(t.index,s)}return i}(t,n):new Map}async function aZ(e){try{return await eK(()=>aQ(e),{shouldRetry:a1})}catch(e){if(function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code||"number"!=typeof e.details?.timeoutMs)return!1;let t=e.details?.cmd,n=e.details?.args,a=Array.isArray(n)?n.map(String):"string"==typeof n?n.split(/\s+/):[];return"adb"===t&&a.includes("uiautomator")&&a.includes("dump")}(e)){let t="If the app has looping animations, use screenshot as visual truth, try settings animations off, then retry snapshot. Stock Android UIAutomator may still time out on app-owned infinite animations.";throw new h("COMMAND_FAILED",`Android UI hierarchy dump timed out while waiting for the UI to become idle. ${t}`,{...e.details??{},hint:t},e)}throw e}}async function aQ(e){var t,n,a;let i,r,o=await L("adb",nU(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0,timeoutMs:8e3}),s=a0(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await L("adb",nU(e,["shell","uiautomator","dump",l]),{allowFailure:!0,timeoutMs:8e3}),u=(t=l,n=d.stdout,a=d.stderr,i=`${n}
15
+ ${a}`,r=/dumped to:\s*(\S+)/i.exec(i),r?.[1]??t),c=await L("adb",nU(e,["shell","cat",u])),p=a0(c.stdout,c.stderr);if(!p)throw new h("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function a0(e,t){let n=`${e}
16
+ ${t}`,a=n.indexOf("<?xml"),i=a>=0?a:n.indexOf("<hierarchy");if(i<0)return null;let r=n.lastIndexOf("</hierarchy>");if(r<0||r<i)return null;let o=n.slice(i,r+12).trim();return o.length>0?o:null}function a1(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,n=("string"==typeof t?t:"").toLowerCase();return!!(n.includes("device offline")||n.includes("device not found")||n.includes("transport error")||n.includes("connection reset")||n.includes("broken pipe")||n.includes("timed out")||n.includes("no such file or directory"))}async function a2(e){try{let t=await L("adb",nU(e,["shell","dumpsys","activity","top"]),{allowFailure:!0,timeoutMs:8e3}),n=`${t.stdout}
17
+ ${t.stderr}`.trim();return n.length>0?n:null}catch{return null}}function a3(e,t,n){if(0===e.size)return;let a=new Map;for(let[e,t]of n.sourceNodes.entries()){let i=n.nodes[e];i&&a.set(t,i)}for(let[n,i]of e){let e=t.sourceNodes[n];if(!e)continue;let r=a.get(e);r&&(i.hiddenContentAbove&&(r.hiddenContentAbove=!0),i.hiddenContentBelow&&(r.hiddenContentBelow=!0))}}async function a4(e,t,n){await L("adb",nU(e,["shell","input","tap",String(t),String(n)]))}async function a5(e,t,n,a,i,r=250){await L("adb",nU(e,["shell","input","swipe",String(t),String(n),String(a),String(i),String(r)]))}async function a8(e){await L("adb",nU(e,["shell","input","keyevent","4"]))}async function a6(e){await L("adb",nU(e,["shell","input","keyevent","3"]))}async function a9(e,t){let n=function(e){switch(e){case"portrait":return"0";case"landscape-left":return"1";case"portrait-upside-down":return"2";case"landscape-right":return"3";default:throw new h("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await L("adb",nU(e,["shell","settings","put","system","accelerometer_rotation","0"])),await L("adb",nU(e,["shell","settings","put","system","user_rotation",n]))}async function a7(e){await L("adb",nU(e,["shell","input","keyevent","187"]))}async function ie(e,t,n,a=800){await L("adb",nU(e,["shell","input","swipe",String(t),String(n),String(t),String(n),String(a)]))}async function it(e,t,n=0){n>0&&Array.from(t).length>1?await iu(e,t,1,n):await ia(e,t)}async function ia(e,t){let n=ic(t);if(!n||"ok"!==await ip(e,t))try{let n=t.replace(/ /g,"%s");await L("adb",nU(e,["shell","input","text",n]))}catch(e){if(n&&function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details?.stderr,n=("string"==typeof t?t:"").toLowerCase();return!!(n.includes("exception occurred while executing 'text'")||n.includes("nullpointerexception")&&n.includes("inputshellcommand.sendtext"))}(e))throw new h("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 ii(e,t,n){await a4(e,t,n)}async function ir(e,t,n,a,i=0){let r=Array.from(a).length,o=ic(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 ii(e,t,n);let s=(d=r+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await im(e,s),"input_text"===o.strategy)await it(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await ip(e,a))continue}else await iu(e,a,1,i>0?i:15);let c=await io(e,t,n,a);if(l=c.actual,c.ok)return}throw new h("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function io(e,t,n,a){let i=null;for(let r of[0,150,350])if(r>0&&await P(r),function(e,t){if(e===t)return!0;let n=is(e),a=is(t);return!!n&&!!a&&(!!(n===a||n.includes(a))||a.includes(n)&&n.length>=Math.max(4,Math.floor(.8*a.length)))}(i=await ih(e,t,n),a))return{ok:!0,actual:i};return{ok:!1,actual:i}}function is(e){return(e??"").replace(/\s+/g," ").trim()}async function il(e,t,n){let a=await id(e),i=aU({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await L("adb",nU(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function id(e){let t=(await L("adb",nU(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new h("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iu(e,t,n,a){let i=Math.max(1,Math.floor(n)),r=Array.from(t);for(let t=0;t<r.length;t+=i){let n=r.slice(t,t+i).join("");await ia(e,n),a>0&&t+i<r.length&&await P(a)}}function ic(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 ip(e,t){let n=await L("adb",nU(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==n.exitCode?"failed":nV(n.stdout,n.stderr)?"unsupported":0===(await L("adb",nU(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await L("adb",nU(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function im(e,t){let n=Math.max(0,t);await L("adb",nU(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<n;t+=24){let a=Math.min(24,n-t);await L("adb",nU(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function ih(e,t,n){let a,i=await aZ(e),r=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=r.exec(i));){let e=aV(a[0]),i=aj(e.bounds);if(!i)continue;let r=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&&n>=i.y&&n<=i.y+i.height;if(u&&iw(r)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&iw(r)){(!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 iw(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function iy(e){let t=await L("adb",nU(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new h("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 n of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=n[1],a=n[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),n=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)||(n=(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,r=i?`0x${i.toLowerCase()}`:void 0;return{visible:n,inputType:r,type:r?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let n=15&t;if(2===n)return"number";if(3===n)return"phone";if(4===n)return"datetime";if(1!==n)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(r):void 0}}(t.stdout)}async function ig(e){let t=await iy(e),n=t,a=0;for(;n.visible&&a<2;)await L("adb",nU(e,["shell","input","keyevent","111"])),a+=1,await P(120),n=await iy(e);if(t.visible&&n.visible)throw new h("UNSUPPORTED_OPERATION","Android keyboard dismiss is unavailable for the current IME without back navigation.",{attempts:a,inputType:n.inputType,type:n.type});return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!n.visible,visible:n.visible,inputType:n.inputType,type:n.type}}async function iI(e){let t,n;return(n=(t=(await iv(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?n[1]??"":"null"===t.trim().toLowerCase()?"":t}async function iA(e,t){await iv(e,["shell","cmd","clipboard","set","text",t],"write")}async function iv(e,t,n){let a=await L("adb",nU(e,t),{allowFailure:!0});if(nV(a.stdout,a.stderr))throw new h("UNSUPPORTED_OPERATION",`Android shell clipboard ${n} is not supported on this device.`);if(0!==a.exitCode)throw new h("COMMAND_FAILED",`Failed to ${n} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let ib=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function i_(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new h("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function iS(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 h("INVALID_ARGS",`permission setting requires a target: ${ib.join("|")}`)}function iN(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new h("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}let ix=["window_animation_scale","transition_animation_scale","animator_duration_scale"];async function iE(e,t,n,a,i){switch(t.toLowerCase()){case"wifi":{let t=iM(n);await L("adb",nU(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=iM(n);await L("adb",nU(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await L("adb",nU(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=iM(n);await L("adb",nU(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"animations":{let t=iM(n)?"1":"0";for(let n of ix)await L("adb",nU(e,["shell","settings","put","global",n,t]));return{scale:t,keys:[...ix]}}case"appearance":{let t=await iC(e,n);await L("adb",nU(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 h("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(n);await iD(e,t);return}case"permission":{if(!a)throw new h("INVALID_ARGS","permission setting requires an active app in session");let t=i_(n),r=function(e,t){let n=iS(e);if(t?.trim())throw new h("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===n)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===n)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===n)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===n)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===n)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new h("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===r.kind)return void await iL(e,a,t,r);let o="grant"===t?"grant":"revoke";if("photos"===r.type)return void await iO(e,a,o);await L("adb",nU(e,["shell","pm",o,a,r.value]));return}default:throw new h("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function iD(e,t){var n;let a,i,r=(n=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===n.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of r){let n=await L("adb",nU(e,t),{allowFailure:!0});if(0===n.exitCode)return;o.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.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,n;let a;return t=e.stdout,n=e.stderr,(a=`${t}
18
+ ${n}`.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 h("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 h("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function iM(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 h("INVALID_ARGS",`Invalid setting state: ${e}`)}async function iC(e,t){let n=iN(t);if("toggle"!==n)return n;let a=await L("adb",nU(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new h("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
19
+ ${t}`);if(!n)return null;let a=n[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new h("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 iO(e,t,n){let a=await iT(e),i=[];for(let r 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 L("adb",nU(e,["shell","pm",n,t,r]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:r,stderr:a.stderr,exitCode:a.exitCode})}throw new h("COMMAND_FAILED",`Failed to ${n} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function iL(e,t,n,a){"grant"===n?await L("adb",nU(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await L("adb",nU(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===n&&(await L("adb",nU(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await L("adb",nU(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await L("adb",nU(e,["shell","appops","set",t,a.appOps,"grant"===n?"allow":"deny"===n?"deny":"default"]))}async function iT(e){let t=await L("adb",nU(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}async function ik(e,t,n){let a="string"==typeof n.action&&n.action.trim()?n.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],r="string"==typeof n.receiver?n.receiver.trim():"";r&&i.push("-n",r);let o=n.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new h("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,n){if("string"==typeof n)return e.push("--es",t,n);if("boolean"==typeof n)return e.push("--ez",t,n?"true":"false");if("number"==typeof n&&Number.isFinite(n))return Number.isInteger(n)?e.push("--ei",t,String(n)):e.push("--ef",t,String(n));throw new h("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await L("adb",nU(e,i)),{action:a,extrasCount:s}}let iR=Buffer.from([137,80,78,71,13,10,26,10]);async function iP(e,t){await iF(e);try{await P(1e3),await iU(e,t)}finally{await i$(e).catch(()=>{})}}async function iF(e){let t=t=>L("adb",nU(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n("clock -e hhmm 0941"),await n("notifications -e visible false")}async function i$(e){await L("adb",nU(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function iU(e,t){let n=await L("adb",nU(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!n.stdoutBuffer)throw new h("COMMAND_FAILED","Failed to capture screenshot");let a=n.stdoutBuffer.indexOf(iR);if(a<0)throw new h("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let r=function(e,t){let n=t+iR.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),a=n+4,i=e.toString("ascii",a,a+4),r=n+12+t;if(r>e.length)break;if("IEND"===i)return r;n=r}return null}(n.stdoutBuffer,a);if(!r)throw new h("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await i.writeFile(t,n.stdoutBuffer.subarray(a,r))}let iG=F(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,eq,5e3),iV=F(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,ej,1e3),iB=F(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),ij=F(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),iq=F(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),iW=F(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),iH=F(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3),iz=eB(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK);async function iK(e,t){let n=["devicectl",...e],a=await L("xcrun",n,{allowFailure:!0,timeoutMs:ij});if(0===a.exitCode)return;let i=String(a.stdout??""),r=String(a.stderr??"");throw new h("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:t.deviceId,hint:iZ(i,r)??iY})}async function iJ(e,t){let n=s.join(r.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",n],o=await L("xcrun",a,{allowFailure:!0,timeoutMs:ij});try{var l,d;if(0!==o.exitCode){let t=String(o.stdout??""),n=String(o.stderr??"");throw new h("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:o.exitCode,stdout:t,stderr:n,deviceId:e.id,hint:iZ(t,n)??iY})}let r=await i.readFile(n,"utf8");return l=function(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let n=[];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,i="string"==typeof e.url&&e.url.trim().length>0?e.url.trim():void 0;n.push({bundleId:t,name:a,url:i})}return n}(JSON.parse(r)),d=t,"user-installed"===d?l.filter(e=>!e.bundleId.startsWith("com.apple.")):l}catch(t){if(t instanceof h)throw t;throw new h("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await i.unlink(n).catch(()=>{})}}async function iX(e){let t=s.join(r.tmpdir(),`agent-device-ios-processes-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=["devicectl","device","info","processes","--device",e.id,"--json-output",t],a=await L("xcrun",n,{allowFailure:!0,timeoutMs:ij});try{if(0!==a.exitCode){let t=String(a.stdout??""),i=String(a.stderr??"");throw new h("COMMAND_FAILED","Failed to list iOS processes",{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:t,stderr:i,deviceId:e.id,hint:iZ(t,i)??iY})}let r=await i.readFile(t,"utf8");return function(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.executable?e.executable.trim():"",a="number"==typeof e.processIdentifier&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;t&&Number.isFinite(a)&&n.push({executable:t,pid:a})}return n}(JSON.parse(r))}catch(t){if(t instanceof h)throw t;throw new h("COMMAND_FAILED","Failed to parse iOS process list",{deviceId:e.id,cause:String(t)})}finally{await i.unlink(t).catch(()=>{})}}let iY="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function iZ(e,t){let n=`${e}
20
+ ${t}`.toLowerCase();return n.includes("device is busy")&&n.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":n.includes("coredeviceservice")&&n.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function iQ(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let n=String(t.stderr??"").toLowerCase();return n.includes("fbsopenapplicationserviceerrordomain")&&n.includes("the request to open")}async function i0(e,t){let n=await L("xcrun",tl(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==n.exitCode)return{installed:!1};let a=n.stdout.trim();if(!a)return{installed:!1};let i=await L("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let r=i.stdout.trim(),o=`${a}/${r}`,s=await L("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 i1(e,t){if("simulator"!==e.kind)throw new h("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function i2(){await L("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:iq})}async function i3(e){let t,n;if("simulator"!==e.kind||"Booted"===await i5(e))return;let a=eH.fromTimeoutMs(iG);try{await ez(async({deadline:a})=>{if(a?.isExpired())throw new h("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:iG});let i=Math.max(1e3,a?.remainingMs()??iG),r=await L("xcrun",tl(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(r.stdout??""),stderr:String(r.stderr??""),exitCode:r.exitCode};let o=`${t.stdout}
21
+ ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new h("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await L("xcrun",tl(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(n={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==n.exitCode)throw new h("COMMAND_FAILED","simctl bootstatus failed",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let d=await i5(e);if("Booted"!==d)throw new h("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=e9({error:e,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>e9({error:e,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(r){let i=e9({error:r,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new h("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:iG,elapsedMs:a.elapsedMs(),reason:i,hint:e7(i),boot:t,bootstatus:n})}await i2()}async function i4(e){let t=tl(e,["shutdown",e.id]),n=await L("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===n.exitCode,exitCode:n.exitCode,stdout:String(n.stdout??""),stderr:String(n.stderr??"")}}async function i5(e){let t="string"==typeof e?e:e.id,n="string"==typeof e?ts(["list","devices","-j"]):tl(e,["list","devices","-j"]),a=await L("xcrun",n,{allowFailure:!0,timeoutMs:iV});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let n of Object.values(e.devices??{})){let e=n.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function i8(e,t){try{let n=await L("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===n.exitCode){let e=String(n.stdout??"").trim();if(e.length>0)return e}}catch{}try{var n,a;let r;return n=await i.readFile(e,"utf8"),a=t,tR(tk(n),(e,t)=>{void 0===r&&e===a&&"string"===t.name&&(r=t.text??void 0)}),r}catch{return}}async function i6(e,t){if("url"===e.kind&&!q(e.url))throw new h("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 n=await j({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||q(e.url),signal:t?.signal}),a=await i7(n.installablePath,t),i=await i9(a.installPath);return{archivePath:n.archivePath??(n.installablePath.toLowerCase().endsWith(".ipa")?n.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await n.cleanup()}}}async function i9(e){let t=s.join(e,"Info.plist"),[n,a,i]=await Promise.all([i8(t,"CFBundleIdentifier"),i8(t,"CFBundleDisplayName"),i8(t,"CFBundleName")]);return{bundleId:n,appName:a??i}}async function i7(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let n=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await i.rm(n,{recursive:!0,force:!0})};try{await L("unzip",["-q",e,"-d",n]);let r=s.join(n,"Payload"),o=(await i.readdir(r,{withFileTypes:!0}).catch(()=>{throw new h("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:s.join(r,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===o.length)return{installPath:o[0].installPath,cleanup:a};if(0===o.length)throw new h("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await re(o);let l=t?.appIdentifierHint?.trim();if(l){let e=function(e,t){let n=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===n);if(1===a.length)return a[0];if(a.length>1)throw new h("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()===n);if(1===t.length)return t[0]}}(o,l);if(e)return{installPath:e.installPath,cleanup:a};throw new h("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload and none matched "${l}". Available bundles: ${o.map(rt).join(", ")}`)}throw new h("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${o.map(rt).join(", ")}`)}catch(e){throw await a(),e}}async function re(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await i9(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function rt(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function rn(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let ra={settings:"com.apple.systempreferences"},ri=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function rr(e,t){let n=["-b",e];return t&&n.push(t),n}async function ro(e){for(let t of[s.join(e,"Contents","Info.plist"),s.join(e,"Info.plist")]){let[e,n,a]=await Promise.all([i8(t,"CFBundleIdentifier"),i8(t,"CFBundleDisplayName"),i8(t,"CFBundleName")]);if(e||n||a)return{bundleId:e,appName:n??a}}return{}}async function rs(e){let t=e.trim(),n=ra[t.toLowerCase()];if(n)return n;if(ri.test(t))return t;let a=(await rm("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new h("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new h("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function rl(e,t,n){let a=n?.url?.trim();if(a){if(!nB(a))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=n?.appBundleId??await rs(t);await L("open",rr(e,a));return}let i=t.trim();if(nB(i))return void await L("open",[i]);let r=n?.appBundleId??await rs(i);await L("open",rr(r))}async function rd(e,t){let n=await rs(t),a=await nL(n);if(a.running&&!a.terminated&&!a.forceTerminated)throw new h("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:n,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function ru(){let e=await L("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new h("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 rc(e){let t=await L("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new h("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function rp(){let e=await L("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new h("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 h("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function rf(e){let t=iN(e),n="toggle"===t?!await rp():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${n?"true":"false"}`,i=await L("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new h("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function rm(e="all"){let t=["/Applications","/System/Applications",s.join(r.homedir(),"Applications")],n=new Set;for(let e of t){let t=await i.stat(e).catch(()=>null);if(!t?.isDirectory())continue;let a=await L("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&&n.add(t)}}return rn((await Promise.all(Array.from(n).map(async e=>{let t=await ro(e).catch(()=>({})),n=t.bundleId;return n?{bundleId:n,name:t.appName??s.basename(e,".app")}:null}))).filter(e=>null!==e).sort((e,t)=>e.name.localeCompare(t.name)),e)}let rh=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],rw={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"},ry={1:"searching",2:"failed",3:"active"},rg={0:"notSupported",1:"searching",2:"failed",3:"active"};function rI(e,t,n){return L("xcrun",tl(e,t),n)}async function rA(e,t){var n,a;let i;await rb(e),t&&await r_(e,(i=[],(n=t).dataNetwork&&i.push("--dataNetwork",n.dataNetwork),n.wifiMode&&i.push("--wifiMode",n.wifiMode),void 0!==n.wifiBars&&("wifi"===n.dataNetwork||n.wifiMode)&&i.push("--wifiBars",n.wifiBars),n.cellularMode&&i.push("--cellularMode",n.cellularMode),void 0!==n.cellularBars&&(n.cellularMode||(a=n.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==n.operatorName)&&i.push("--cellularBars",n.cellularBars),void 0!==n.operatorName&&i.push("--operatorName",n.operatorName),i))}async function rv(e){let t=await rI(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new h("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 n 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(n);if(e){let n=Number(e[1]),a=rw[n];if(!a)throw new h("COMMAND_FAILED",`Unsupported simulator data network type: ${n}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(n);if(a){let e=ry[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(n);if(i){let e=Number(i[1]),n=rg[e];if(!n)throw new h("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=n,t.cellularBars=i[2];continue}let r=/^Operator Name:\s*(.*)$/.exec(n);if(r){t.operatorName=r[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function rb(e){await rI(e,["status_bar",e.id,"clear"])}async function r_(e,t){0!==t.length&&await rI(e,["status_bar",e.id,"override",...t])}function rS(e,t,n){E({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof h))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},n=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:n}}(n)}})}function rN(e,t,n){return L("xcrun",tl(e,t),n)}let rx={ensureBooted:i3,prepareStatusBarForScreenshot:async function e(e){let t=null,n=!1;try{t=await rv(e),n=!0}catch(t){rS(e,"snapshot_failed",t)}try{await rb(e),await r_(e,rh)}catch(t){rS(e,"prepare_failed",t)}return async()=>{await rA(e,n?t:null)}},captureWithRetry:rM,runnerFallbackEnabled:iz,captureWithRunner:rC,shouldFallbackToRunner:rF};async function rE(e,t,n,a){if("macos"===e.platform)return void await rC(e,t,n,a);if("simulator"===e.kind)return void await rD(e,t,n,a);try{await iK(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},n="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
21
22
  ${n}
22
- ${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;rx(e,"devicectl_screenshot",t)}await rb(e,t,n,a)}async function rA(e,t,n,a,i=rg){if("simulator"!==e.kind)throw new h("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let r="object"==typeof a&&null!==a?a:i;await r.ensureBooted(e);let o=async()=>{};try{o=await r.prepareStatusBarForScreenshot(e)}catch(t){rE(e,"prepare_failed",t)}try{try{await r.captureWithRetry(e,t);return}catch(t){if(!r.shouldFallbackToRunner(t))throw t;if(!r.runnerFallbackEnabled){var s,l,d;let n,a;throw s=e,l=t,n=rD(l),E({level:"warn",phase:"ios_screenshot_fallback_skipped",data:{platform:s.platform,deviceKind:s.kind,deviceId:s.id,from:"simctl_screenshot",to:"runner",reason:"Simulator runner fallback is disabled to avoid XCTest automation instability during screenshot capture.",...n}}),a=(d=t)instanceof h?d:new h("COMMAND_FAILED","Failed to capture iOS screenshot: simulator screenshot retries exhausted",void 0,d),new h(a.code,a.message,{...a.details??{},hint:"Restart the simulator and retry. If simctl screenshots keep timing out and you accept the stability tradeoff, set AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK=1 to allow XCTest runner fallback."},a)}rx(e,"simctl_screenshot",t)}await r.captureWithRunner(e,t,n,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>rE(e,"restore_failed",t))}}async function rv(e,t){let n=e0.fromTimeoutMs(iF);await e1(async({deadline:n})=>{await ry(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,n?.remainingMs()??iF)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>rM(e)},{deadline:n,phase:"ios_simulator_screenshot"})}async function rb(e,t,n,a){let r=(await nw(e,{command:"screenshot",appBundleId:n,fullscreen:a})).message;if(!r)throw new h("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await i.copyFile(r,t):"simulator"===e.kind?await rS(e,r,t):await r_(e,r,t)}async function r_(e,t,n){let a=e0.fromTimeoutMs(i$),i={exitCode:1,stdout:"",stderr:""};for(let r of tH)if(0===(i=await L("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",n,"--domain-type","appDataContainer","--domain-identifier",r],{allowFailure:!0,timeoutMs:rN(a,i$,"runner screenshot copy")})).exitCode)return;let r=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new h("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}async function rS(e,t,n){let a=e0.fromTimeoutMs(i$),r="Unable to locate runner container for simulator screenshot";for(let o of tH){let l=await ry(e,["get_app_container",e.id,o,"data"],{allowFailure:!0,timeoutMs:rN(a,i$,"runner screenshot container lookup")});if(0!==l.exitCode){let e=l.stderr.trim();e&&(r=e);continue}let d=l.stdout.trim();if(!d){r="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let n=s.resolve(e),a=t.trim();if(!a)return[];let i=[],r=new Set,o=e=>{let t=s.normalize(e);r.has(t)||(r.add(t),i.push(t))},l=a.replace(/^\/+/,""),d=l.replace(/\\/g,"/");if(l&&o(s.join(n,l)),s.isAbsolute(a)&&o(s.normalize(a)),d.startsWith("tmp/"))o(s.join(n,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);o(s.join(n,t))}}let u=s.basename(a);return u&&o(s.join(n,"tmp",u)),i}(d,t))try{await i.copyFile(e,n);return}catch(e){r=e instanceof Error?e.message:String(e)}}throw new h("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}function rN(e,t,n){let a=e.remainingMs();if(a>0)return a;throw new h("COMMAND_FAILED",`iOS ${n} timed out after ${t}ms`,{timeoutMs:t,step:n})}function rx(e,t,n){let a=rD(n);E({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function rE(e,t,n){E({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...rD(n)}})}function rD(e){if(!(e instanceof h))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},n=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:n}}function rM(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},n="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(" "):"",r=`${e.message}
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;rk(e,"devicectl_screenshot",t)}await rC(e,t,n,a)}async function rD(e,t,n,a,i=rx){if("simulator"!==e.kind)throw new h("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");let r="object"==typeof a&&null!==a?a:i;await r.ensureBooted(e);let o=async()=>{};try{o=await r.prepareStatusBarForScreenshot(e)}catch(t){rR(e,"prepare_failed",t)}try{try{await r.captureWithRetry(e,t);return}catch(t){if(!r.shouldFallbackToRunner(t))throw t;if(!r.runnerFallbackEnabled){var s,l,d;let n,a;throw s=e,l=t,n=rP(l),E({level:"warn",phase:"ios_screenshot_fallback_skipped",data:{platform:s.platform,deviceKind:s.kind,deviceId:s.id,from:"simctl_screenshot",to:"runner",reason:"Simulator runner fallback is disabled to avoid XCTest automation instability during screenshot capture.",...n}}),a=(d=t)instanceof h?d:new h("COMMAND_FAILED","Failed to capture iOS screenshot: simulator screenshot retries exhausted",void 0,d),new h(a.code,a.message,{...a.details??{},hint:"Restart the simulator and retry. If simctl screenshots keep timing out and you accept the stability tradeoff, set AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK=1 to allow XCTest runner fallback."},a)}rk(e,"simctl_screenshot",t)}await r.captureWithRunner(e,t,n,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>rR(e,"restore_failed",t))}}async function rM(e,t){let n=eH.fromTimeoutMs(iW);await ez(async({deadline:n})=>{await rN(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,n?.remainingMs()??iW)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>rF(e)},{deadline:n,phase:"ios_simulator_screenshot"})}async function rC(e,t,n,a){let r=(await ny(e,{command:"screenshot",appBundleId:n,fullscreen:a})).message;if(!r)throw new h("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await i.copyFile(r,t):"simulator"===e.kind?await rL(e,r,t):await rO(e,r,t)}async function rO(e,t,n){let a=eH.fromTimeoutMs(iH),i={exitCode:1,stdout:"",stderr:""};for(let r of tz)if(0===(i=await L("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",n,"--domain-type","appDataContainer","--domain-identifier",r],{allowFailure:!0,timeoutMs:rT(a,iH,"runner screenshot copy")})).exitCode)return;let r=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new h("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}async function rL(e,t,n){let a=eH.fromTimeoutMs(iH),r="Unable to locate runner container for simulator screenshot";for(let o of tz){let l=await rN(e,["get_app_container",e.id,o,"data"],{allowFailure:!0,timeoutMs:rT(a,iH,"runner screenshot container lookup")});if(0!==l.exitCode){let e=l.stderr.trim();e&&(r=e);continue}let d=l.stdout.trim();if(!d){r="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let n=s.resolve(e),a=t.trim();if(!a)return[];let i=[],r=new Set,o=e=>{let t=s.normalize(e);r.has(t)||(r.add(t),i.push(t))},l=a.replace(/^\/+/,""),d=l.replace(/\\/g,"/");if(l&&o(s.join(n,l)),s.isAbsolute(a)&&o(s.normalize(a)),d.startsWith("tmp/"))o(s.join(n,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);o(s.join(n,t))}}let u=s.basename(a);return u&&o(s.join(n,"tmp",u)),i}(d,t))try{await i.copyFile(e,n);return}catch(e){r=e instanceof Error?e.message:String(e)}}throw new h("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}function rT(e,t,n){let a=e.remainingMs();if(a>0)return a;throw new h("COMMAND_FAILED",`iOS ${n} timed out after ${t}ms`,{timeoutMs:t,step:n})}function rk(e,t,n){let a=rP(n);E({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function rR(e,t,n){E({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...rP(n)}})}function rP(e){if(!(e instanceof h))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},n=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:n}}function rF(e){if(!(e instanceof h)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},n="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(" "):"",r=`${e.message}
23
24
  ${n}
24
25
  ${a}
25
- ${i}`.toLowerCase();return r.includes("timeout waiting for screen surfaces")||r.includes("nsposixerrordomain")&&r.includes("code=60")&&r.includes("screenshot")||r.includes("timed out")&&r.includes("screenshot")}let rC={settings:"com.apple.Preferences"},rO=null;function rL(e,t,n){return L("xcrun",H(e,t),n)}function rT(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function rk(e,t){if("macos"===e.platform)return await i7(t);let n=t.trim();if(n.includes("."))return n;let a=rC[n.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await rK(e):await iV(e,"all")).filter(e=>e.name.toLowerCase()===n.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new h("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new h("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function rR(e,t,n){if("macos"===e.platform)return void await re(e,t,n);let a=n?.url?.trim();if(a){if(!n$(a))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await iJ(e),await rL(e,["openurl",e.id,a]);return}let i=nU(n?.appBundleId??await rk(e,t),a);if(!i)throw new h("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await r2(e,i,{payloadUrl:a});return}let i=t.trim();if(n$(i)){if("simulator"===e.kind){await iJ(e),await rL(e,["openurl",e.id,i]);return}let t=nU(n?.appBundleId,i);if(!t)throw new h("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await r2(e,t,{payloadUrl:i});return}let r=n?.appBundleId??await rk(e,t);"simulator"===e.kind?await r1(e,r):await r2(e,r)}async function rP(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await iY(e)&&await iJ(e)}async function rF(e,t){if("macos"===e.platform)return void await rt(e,t);let n=await rk(e,t);if("simulator"===e.kind){await iJ(e);let t=H(e,["terminate",e.id,n]),a=await L("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new h("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await iG(["device","process","terminate","--device",e.id,n],{action:"terminate iOS app",deviceId:e.id})}async function r$(e,t){let n=await rk(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,n],a=await L("xcrun",t,{allowFailure:!0,timeoutMs:iR});if(0!==a.exitCode){let i=String(a.stdout??""),r=String(a.stderr??"");if(!rT(`${i}
26
- ${r}`.toLowerCase()))throw new h("COMMAND_FAILED",`Failed to uninstall iOS app ${n}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:e.id,hint:iq(i,r)??ij})}return{bundleId:n}}await iJ(e);let a=await rL(e,["uninstall",e.id,n],{allowFailure:!0});if(0!==a.exitCode&&!rT(`${a.stdout}
27
- ${a.stderr}`.toLowerCase()))throw new h("COMMAND_FAILED",`simctl uninstall failed for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:n}}async function rU(e,t,n){let a=await iQ({kind:"path",path:t},n);try{return await rV(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function rG(e,t,n){let{bundleId:a}=await r$(e,t);return await rU(e,n,{appIdentifierHint:t}),{bundleId:a}}async function rV(e,t){"simulator"!==e.kind?await iG(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await iJ(e),await rL(e,["install",e.id,t]))}async function rB(e){if("macos"===e.platform)return await rn();iK(e,"clipboard"),await iJ(e);let t=await rL(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new h("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 rj(e,t){if("macos"===e.platform)return void await ra(t);iK(e,"clipboard"),await iJ(e);let n=await rL(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==n.exitCode)throw new h("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}async function rq(e,t,n){iK(e,"push"),await iJ(e);let a=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-ios-push-")),o=s.join(a,"payload.apns");try{await i.writeFile(o,`${JSON.stringify(n)}
28
- `,"utf8"),await rL(e,["push",e.id,t,o])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function rW(e,t,n,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await rr(n);if("permission"===e){let e=ih(n);if("deny"===e)throw new h("INVALID_ARGS",eE("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new h("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nL(e,t)}throw new h("INVALID_ARGS",eE(t))}iK(e,"settings"),await iJ(e);let r=t.toLowerCase();switch(r){case"wifi":{let t=rz(n);await rL(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(rz(n)?await rL(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await rL(e,["status_bar",e.id,"clear"]));case"location":{let t=rz(n);if(!a)throw new h("INVALID_ARGS","location setting requires an active app in session");await rL(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=rX[r],a=function(e,t){let n=e.trim().toLowerCase();if("match"===n)return"match";if("nonmatch"===n)return"nonmatch";if("enroll"===n)return"enroll";if("unenroll"===n)return"unenroll";throw new h("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(n,r);await r0(e,a,{settingName:r,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await rJ(e,n);await rL(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new h("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=ih(n))?"revoke":o,r=function(e,t){let n=iw(e);if("photos"!==n&&t?.trim())throw new h("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===n)return"camera";if("microphone"===n)return"microphone";if("contacts"===n)return"contacts";if("contacts-limited"===n)return"contacts-limited";if("notifications"===n)return"notifications";if("calendar"===n)return"calendar";if("location"===n)return"location";if("location-always"===n)return"location-always";if("media-library"===n)return"media-library";if("motion"===n)return"motion";if("reminders"===n)return"reminders";if("siri"===n)return"siri";if("photos"===n){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new h("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new h("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 rY(e,t,r,a);return}default:throw new h("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function rH(e,t="all"){return"macos"===e.platform?await ro(t):"simulator"===e.kind?i4(await rK(e),t):await iV(e,t)}async function rK(e){let t=(await rL(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith("{"))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith("{"))try{let e=await L("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function rz(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 h("INVALID_ARGS",`Invalid setting state: ${e}`)}async function rJ(e,t){let n=iy(t);if("toggle"!==n)return n;let a=await rL(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new h("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
29
- ${t}`);if(!n)return null;let a=n[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new h("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let rX={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function rY(e,t,n,a){let i=await rQ(e);if(!i.has(n))throw new h("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${n}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let r=["privacy",e.id,t,n,a],o="notifications"===n;if(!("reset"===t&&o))try{await rL(e,r);return}catch(t){if(!(o&&rZ(t)))throw t;throw new h("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 rL(e,r);return}catch(e){if(!rZ(e))throw e}try{await rL(e,["privacy",e.id,"reset","all",a])}catch(t){throw new h("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 rZ(e){if(!(e instanceof h)||"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 rQ(t){let n=U(t.simulatorSetPath),a=`${process.env.PATH??""}::${n??""}`;if(rO&&e===a)return rO;let i=await rL(t,["privacy","help"],{allowFailure:!0}),r=function(e){let t=new Set,n=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){n=!0;continue}if(!n)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
30
- ${i.stderr}`);if(0===r.size)throw new h("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 rO=r,e=a,r}async function r0(e,t,n){let a=function(e,t,n){let a=n.length>0?n:["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,n.modalityAliases),i=[];for(let t of a){let n=H(e,t),a=await L("xcrun",n,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:n,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let r=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,n;let a;return t=e.stdout,n=e.stderr,(a=`${t}
31
- ${n}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new h("UNSUPPORTED_OPERATION",`${n.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r});throw new h("COMMAND_FAILED",`Failed to simulate ${n.settingName}.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r})}async function r1(e,t){await iJ(e);let n=0,a=e0.fromTimeoutMs(ik);try{await e1(async({deadline:n})=>{var a;if(n?.isExpired())throw new h("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:ik});let i=(a=["launch",e.id,t],H(e,a)),r=await L("xcrun",i,{allowFailure:!0});if(0!==r.exitCode)throw new h("COMMAND_FAILED",`xcrun exited with code ${r.exitCode}`,{cmd:"xcrun",args:i,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!iW(e)&&(n+=1)<3},{deadline:a})}catch(n){if(iW(n)){var i;let a=(i=await iH(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";n.details={...n.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 n}}async function r2(e,t,n){let a=["device","process","launch","--device",e.id,t];n?.payloadUrl&&a.push("--payload-url",n.payloadUrl),await iG(a,{action:"launch iOS app",deviceId:e.id})}async function r3(e,t,n,a,i,r,o){if("tv"===t.target)return r8(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:n.appBundleId},a),r);let s=o??await r4(e,t,n,a),l=aO({direction:i,amount:r?.amount,pixels:r?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return r8(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:n.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function r4(e,t,n,a){let i=await e(t,{command:"interactionFrame",appBundleId:n.appBundleId},a),r=r5(i.x),o=r5(i.y),s=r5(i.referenceWidth),l=r5(i.referenceHeight);if(void 0===r||void 0===o||void 0===s||void 0===l)throw new h("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:r,originY:o,referenceWidth:s,referenceHeight:l}}function r5(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function r8(e,t){var n;let{x1:a,y1:i,x2:r,y2:o}={x1:r5((n=e).x),y1:r5(n.y),x2:r5(n.x2),y2:r5(n.y2)},s=r5(e.referenceWidth),l=r5(e.referenceHeight),d=void 0!==a&&void 0!==r?Math.round(Math.abs(r-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!==r?{x2:r}:{},...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 r6(){return process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11"}let r9=null;async function r7(){if(r9)return r9;let e=r6();if("wayland"===e){if(await R("ydotool"))return r9={tool:"ydotool",display:e};throw new h("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await R("xdotool"))return r9={tool:"xdotool",display:e};throw new h("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function oe(...e){await L("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function ot(...e){await L("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}async function on(e,t){let{tool:n}=await r7();"xdotool"===n?await oe("mousemove","--sync",String(e),String(t)):await ot("mousemove","--absolute","-x",String(e),"-y",String(t))}async function oa(e,t){let{tool:n}=await r7();"xdotool"===n?await oe("key","--clearmodifiers",e):await ot("key",...t)}async function oi(e,t,n,a){await on(e,t);let{tool:i}=await r7();"xdotool"===i?await oe("click",n):await ot("click",a)}async function or(e,t){await oi(e,t,"1","0xC0")}async function oo(e,t){await oi(e,t,"3","0xC1")}async function os(e,t){await oi(e,t,"2","0xC2")}async function ol(e,t){let{tool:n}=await r7();await on(e,t),"xdotool"===n?await oe("click","--repeat","2","1"):(await ot("click","0xC0"),await ot("click","0xC0"))}async function od(e,t,n=800){let{tool:a}=await r7();await on(e,t),"xdotool"===a?(await oe("mousedown","1"),await P(n),await oe("mouseup","1")):(await ot("click","--down","0xC0"),await P(n),await ot("click","--up","0xC0"))}async function ou(e,t){await or(e,t)}async function oc(e,t,n,a,i=300){let{tool:r}=await r7();await on(e,t),"xdotool"===r?(await oe("mousedown","1"),await oe("mousemove","--sync",String(n),String(a)),await P(i),await oe("mouseup","1")):(await ot("click","--down","0xC0"),await ot("mousemove","--absolute","-x",String(n),"-y",String(a)),await P(i),await ot("click","--up","0xC0"))}async function op(e,t){let{tool:n}=await r7(),a=5;if(t?.pixels!=null?a="xdotool"===n?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(a=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===n)await oe("click","--repeat",String(a),"up"===e?"4":"down"===e?"5":"left"===e?"6":"7");else if("up"===e||"down"===e){let t="up"===e?String(-a):String(a);await ot("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-a):String(a);await ot("mousemove","--wheel","-x",t)}}async function of(e,t=0){let{tool:n}=await r7();if("xdotool"===n){let n=["type"];t>0&&n.push("--delay",String(t)),n.push("--clearmodifiers","--",e),await oe(...n)}else await ot("type","--",e)}async function om(e,t,n,a=0){await or(e,t),await P(100),await oa("ctrl+a",["29:1","30:1","30:0","29:0"]),await P(50),await of(n,a)}function oh(e){let t=null;return{resolve:async function(){if(t)return t;let n="wayland"===r6()?"wayland":"x11";for(let a of"wayland"===n?e.wayland:e.x11)if(await R(a.command))return t={tool:a.tool,display:n};throw new h("TOOL_MISSING","wayland"===n?e.waylandError:e.x11Error)},resetCache:()=>{t=null}}}let ow=oh({wayland:[{tool:"grim",command:"grim"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],x11:[{tool:"scrot",command:"scrot"},{tool:"import",command:"import"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],waylandError:"grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.",x11Error:"scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager."});async function oy(e){let{tool:t}=await ow.resolve();switch(t){case"grim":await L("grim",[e]);break;case"scrot":await L("scrot",[e]);break;case"import":await L("import",["-window","root",e]);break;case"gnome-screenshot":await L("gnome-screenshot",["-f",e])}}async function og(e){if(e.includes("://")||e.startsWith("/"))return void await L("xdg-open",[e]);if(await R(e)){L(e,[],{allowFailure:!0}).catch(t=>{E({level:"warn",phase:"linux_app_launch",data:{app:e,error:String(t)}})}),await P(500);return}await L("xdg-open",[e],{allowFailure:!0})}async function oI(e){await R("wmctrl")?await L("wmctrl",["-c",e],{allowFailure:!0}):await L("pkill",["-x",e],{allowFailure:!0})}async function oA(){await oa("alt+Left",["56:1","105:1","105:0","56:0"])}async function ov(){await oa("super+d",["125:1","32:1","32:0","125:0"])}let ob=oh({wayland:[{tool:"wl-clipboard",command:"wl-paste"}],x11:[{tool:"xclip",command:"xclip"},{tool:"xsel",command:"xsel"}],waylandError:"wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.",x11Error:"xclip or xsel is required for clipboard access on X11. Install via your package manager."});async function o_(){let{tool:e}=await ob.resolve();switch(e){case"wl-clipboard":return(await L("wl-paste",["--no-newline"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xclip":return(await L("xclip",["-selection","clipboard","-o"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xsel":return(await L("xsel",["--clipboard","--output"],{allowFailure:!0,timeoutMs:5e3})).stdout}}async function oS(e){let{tool:t}=await ob.resolve();switch(t){case"wl-clipboard":await L("wl-copy",["--",e],{allowFailure:!1,timeoutMs:5e3});break;case"xclip":await L("xclip",["-selection","clipboard"],{allowFailure:!1,timeoutMs:5e3,stdin:e});break;case"xsel":await L("xsel",["--clipboard","--input"],{allowFailure:!1,timeoutMs:5e3,stdin:e})}}ob.resetCache;let oN={"push button":"Button","toggle button":"Button","push button menu":"Button",label:"StaticText",static:"StaticText",caption:"StaticText",text:"TextField",entry:"TextField","password text":"TextField","spin button":"TextField",terminal:"TextArea","document text":"TextArea",paragraph:"TextArea",frame:"Window",window:"Window",dialog:"Dialog",alert:"Alert","file chooser":"Dialog","color chooser":"Dialog","font chooser":"Dialog",panel:"Group",filler:"Group",section:"Group",form:"Group",grouping:"Group","layered pane":"Group","glass pane":"Group","root pane":"Group","option pane":"Group","internal frame":"Group","desktop frame":"Group","block quote":"Group",article:"Group",comment:"Group",landmark:"Group",log:"Group",marquee:"Group",math:"Group",notification:"Group","content deletion":"Group","content insertion":"Group",mark:"Group",suggestion:"Group","scroll pane":"ScrollArea","scroll bar":"ScrollBar","menu bar":"MenuBar",menu:"Menu","popup menu":"Menu","menu item":"MenuItem","check menu item":"MenuItem","radio menu item":"MenuItem","tearoff menu item":"MenuItem","check box":"CheckBox","radio button":"RadioButton",switch:"Switch","combo box":"ComboBox","page tab":"Tab","page tab list":"TabList",table:"Table","tree table":"Table","table cell":"Cell","table row":"Row","table column header":"Cell","table row header":"Cell","column header":"Cell","row header":"Cell",list:"List","list item":"ListItem","list box":"List",tree:"Tree","tree item":"TreeItem","description list":"List","description term":"ListItem","description value":"ListItem","tool bar":"Toolbar","status bar":"StatusBar","info bar":"StatusBar",slider:"Slider","progress bar":"ProgressBar","level bar":"ProgressBar",image:"Image",icon:"Image",animation:"Image",canvas:"Image","drawing area":"Image",video:"Video",audio:"Audio",link:"Link",hyperlink:"Link",separator:"Separator",application:"Application","tool tip":"Tooltip",timer:"Timer",heading:"Heading",footnote:"Footnote","title bar":"TitleBar","date editor":"DateEditor",rating:"Slider"},ox="atspi-dump.py",oE=null;async function oD(e,t={}){let a;if("linux"!==process.platform)throw new h("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await R("python3"))throw new h("TOOL_MISSING","python3 is required for AT-SPI2 accessibility snapshots on Linux.");let i=t.maxNodes??1500,r=t.maxDepth??12,o=t.maxApps??24,l=[function(){if(oE)return oE;let e=s.dirname(u(import.meta.url));for(let t=0;t<5;t++){let a=s.join(e,"src","platforms","linux",ox);if(n.existsSync(a))return oE=a,a;if(0===t){let t=s.join(e,ox);if(n.existsSync(t))return oE=t,t}e=s.dirname(e)}throw new h("TOOL_MISSING",`Cannot find ${ox}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(i),"--max-depth",String(r),"--max-apps",String(o)],d=await L("python3",l,{allowFailure:!0,timeoutMs:3e4});if(0!==d.exitCode){let e=d.stderr.trim();if(e.includes("No module named")||e.includes("gi.require_version"))throw new h("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new h("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${d.exitCode}): ${e||d.stdout}`)}try{a=JSON.parse(d.stdout)}catch{throw new h("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${d.stdout.slice(0,200)}`)}if(a.error)throw new h("COMMAND_FAILED",`AT-SPI2: ${a.error}`);return{nodes:(a.nodes??[]).map(e=>{let t,n;return{index:e.index,type:(n=oN[t=e.role.toLowerCase().trim()])||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0}}),truncated:a.truncated,surface:e}}async function oM(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&E({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),n=await oD(t);return{nodes:n.nodes,truncated:n.truncated}}function oC(e){return e?.clickButton??"primary"}function oO(e){return"primary"===e.button?null:"click"!==e.commandLabel?new h("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new h("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"middle"===e.button?new h("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 h("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}function oL(e){return"primary"===e?{}:{button:e}}let oT=/^[A-Za-z0-9_.:-]{1,64}$/,ok=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];async function oR(e,t,n){for(let a=0;a<e;a+=1)await n(a),a<e-1&&t>0&&await P(t)}function oP(e,t){let a,i=t?.subject??"Payload",r=e.trim();if(!r)throw new h("INVALID_ARGS",`${i} cannot be empty`);let o=t?.expandPath?t.expandPath(r,t.cwd):r;try{if(!n.statSync(o).isFile())throw new h("INVALID_ARGS",`${i} path is not a file: ${o}`);return{kind:"file",path:o}}catch(t){if(t instanceof h)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new h("INVALID_ARGS",`${i} file is not readable: ${o}`);if(e&&"ENOENT"!==e)throw new h("COMMAND_FAILED",`Unable to read ${i} file: ${o}`,{cause:String(t)})}if((a=r.trim()).startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))return{kind:"inline",text:r};throw new h("INVALID_ARGS",`${i} file not found: ${o}`)}async function oF(e){let t=oP(e,{subject:"Push payload"}),n="inline"===t.kind?t.text:await o$(t.path);try{let e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new h("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof h)throw t;throw new h("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function o$(e){try{return await i.readFile(e,"utf8")}catch(n){let t=n.code;if("ENOENT"===t)throw new h("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new h("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new h("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new h("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(n)})}}function oU(e){if(void 0===e)throw new h("INVALID_ARGS","rotate requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.");switch(e?.trim().toLowerCase()){case"portrait":return"portrait";case"portrait-upside-down":case"upside-down":return"portrait-upside-down";case"landscape-left":case"left":return"landscape-left";case"landscape-right":case"right":return"landscape-right";default:throw new h("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}let oG=F(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),oV=/^(iphone|ipad|ipod|appletv)/i,oB=/\b(iphone|ipad|ipod)\b/i,oj=/^appletv/i,oq=["apple tv","appletv","tvos"],oW=/^==\s*(.+?)\s*==$/,oH=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function oK(e){return(e??"").trim().toLowerCase()}function oz(e){return oK(e.hardwareProperties?.platform)}function oJ(e){return e.includes("tvos")}function oX(e){let t=oK(e);return oq.some(e=>t.includes(e))}function oY(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function oZ(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function oQ(e={}){let t,n,a=U(e.simulatorSetPath),i=e.target;try{t=await L("xcrun",G(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{n=JSON.parse(t.stdout)}catch{return null}let r=o0(n,a),o=null,s=null,l=null;for(let e of r)i&&e.target!==i||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function o0(e,t){let n=[];for(let[a,i]of Object.entries(e.devices))if(function(e){let t=oK(e);return t.includes("ios")||t.includes("tvos")}(a))for(let e of i)e.isAvailable&&n.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:oJ(oK(a))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return n}function o1(e,t){let n=new Set(e.map(e=>e.id)),a=[...e];for(let e of t)n.has(e.id)||(n.add(e.id),a.push(e));return a}async function o2(){let e=null;try{e=s.join(r.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await L("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:oG});if(0!==t.exitCode)return[];let n=await i.readFile(e,"utf8");return function(e){let t=[];for(let n of e.result?.devices??[]){if(!function(e){var t;let n=oz(e);return!!(n.includes("ios")||n.includes("tvos"))||(t=oZ(e),!!oV.test(t.trim())||oY(e).some(oX))}(n))continue;let e=n.hardwareProperties?.udid??n.identifier??"",a=n.name??n.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:a,kind:"device",target:function(e){var t;return oJ(oz(e))?"tv":(t=oZ(e),oj.test(t.trim())||oY(e).some(oX))?"tv":"mobile"}(n),booted:!0})}return t}(JSON.parse(n))}catch{return[]}finally{e&&await i.rm(e,{force:!0}).catch(()=>{})}}async function o3(){try{let e=await L("xcrun",["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],n=null;for(let a of e.split(/\r?\n/)){let e=a.trim();if(!e)continue;let i=oW.exec(e);if(i){n=i[1]?.trim()??null;continue}if("Devices"!==n)continue;let r=oH.exec(e),o=r?.groups?.id?.trim()??"",s=r?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return oX(e)?"tv":oB.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function o4(e={}){if("darwin"!==process.platform)throw new h("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await R("xcrun"))throw new h("TOOL_MISSING","xcrun not found in PATH");let t=U(e.simulatorSetPath),n=await L("xcrun",G(["list","devices","-j"],{simulatorSetPath:t})),a=[];try{let e=JSON.parse(n.stdout);a=o0(e,t)}catch(e){throw new h("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(a.push({platform:"macos",id:"host-macos-local",name:r.hostname(),kind:"device",target:"desktop",booted:!0}),t)return a;let[i,o]=await Promise.all([o2(),o3()]);return a=o1(a,i),o1(a,o)}async function o5(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:o(),kind:"device",target:"desktop",booted:!0}]}async function o8(e,t,n){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await eB(e,t,n)}catch(e){if(i||!(e instanceof h)||"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 oQ({simulatorSetPath:n.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new h("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function o6(e){let t=e$(e.platform),n=eV({simulatorSetPath:U(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=q(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 h("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|linux|apple with --target mobile|tv|desktop.");if("linux"===i.platform){let e=await o5();return await eB(e,i)}if("android"===i.platform){await j();let e=await nZ({serialAllowlist:a});return await eB(e,i)}if(i.platform){let e=await o4({simulatorSetPath:n});return await o8(e,i,{simulatorSetPath:n})}let r=[];try{r.push(...await nZ({serialAllowlist:a}))}catch{}try{r.push(...await o4({simulatorSetPath:n}))}catch{}try{r.push(...await o5())}catch{}return await eB(r,i,{simulatorSetPath:n})},{platform:t,target:e.target})}async function o9(e,t,n,a,r){let o={requestId:r?.requestId,appBundleId:r?.appBundleId,verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath},l=function(e,t){switch(e.platform){case"android":return{open:(t,n)=>ac(e,t,n?.activity),openDevice:()=>ay(e),close:t=>ag(e,t),tap:(t,n)=>aX(e,t,n),doubleTap:async(t,n)=>{await aX(e,t,n),await aX(e,t,n)},swipe:(t,n,a,i,r)=>aY(e,t,n,a,i,r),longPress:(t,n,a)=>a2(e,t,n,a),focus:(t,n)=>a5(e,t,n),type:(t,n)=>a3(e,t,n),fill:(t,n,a,i)=>a8(e,t,n,a,i),scroll:(t,n)=>a7(e,t,n),screenshot:t=>iD(e,t),back:t=>aZ(e),home:()=>aQ(e),rotate:t=>a0(e,t),appSwitcher:()=>a1(e),readClipboard:()=>iu(e),writeClipboard:t=>ic(e,t),setSetting:(t,n,a,i)=>iI(e,t,n,a,i)};case"linux":return{open:e=>og(e),openDevice:()=>Promise.resolve(),close:e=>oI(e),tap:(e,t)=>or(e,t),doubleTap:(e,t)=>ol(e,t),swipe:(e,t,n,a,i)=>oc(e,t,n,a,i),longPress:(e,t,n)=>od(e,t,n),focus:(e,t)=>ou(e,t),type:(e,t)=>of(e,t),fill:(e,t,n,a)=>om(e,t,n,a),scroll:(e,t)=>op(e,t),screenshot:e=>oy(e),back:()=>oA(),home:()=>ov(),rotate:()=>{throw new h("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new h("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>o_(),writeClipboard:e=>oS(e),setSetting:()=>{throw new h("UNSUPPORTED_OPERATION","setSetting not supported on Linux")}};case"ios":case"macos":{let n,{overrides:a,runnerOpts:i}={runnerOpts:n={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},overrides:{tap:async(a,i)=>await nw(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),doubleTap:async(a,i)=>await nw(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},n),swipe:async(a,i,r,o,s)=>await nw(e,{command:"drag",x:a,y:i,x2:r,y2:o,durationMs:s,appBundleId:t.appBundleId},n),longPress:async(a,i,r)=>await nw(e,{command:"longPress",x:a,y:i,durationMs:r,appBundleId:t.appBundleId},n),focus:async(a,i)=>await nw(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),type:async(a,i)=>{await nw(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},n)},fill:async(a,i,r,o)=>{let s=await nw(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n);return await nw(e,{command:"type",text:r,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},n),s},scroll:async(a,i)=>await r3(nw,e,t,n,a,i)}};return{open:(t,n)=>rR(e,t,{appBundleId:n?.appBundleId,url:n?.url}),openDevice:()=>rP(e),close:t=>rF(e,t),screenshot:async(t,n)=>{"macos"===e.platform&&n?.surface&&"app"!==n.surface?await nF(t,{surface:n.surface,fullscreen:n.fullscreen}):await rI(e,t,n?.appBundleId,n?.fullscreen)},back:async n=>{await nw(e,{command:"system"===n?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await nw(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async n=>{await nw(e,{command:"rotate",orientation:n,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await nw(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>rB(e),writeClipboard:t=>rj(e,t),setSetting:(t,n,a,i)=>rW(e,t,n,a,i),...a}}default:throw new h("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,o);return E({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await x("platform_command",async()=>{switch(t){case"open":return o7(e,l,n,r);case"close":{let e=n[0];if(!e)return{closed:"session",...er("Closed session")};return await l.close(e),{app:e,...er(`Closed: ${e}`)}}case"press":return se(e,l,n,r,o);case"swipe":return st(e,l,n,r,o);case"longpress":{let e=Number(n[0]),t=Number(n[1]),a=n[2]?Number(n[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new h("INVALID_ARGS","longpress requires x y [durationMs]");return await l.longPress(e,t,a),{x:e,y:t,durationMs:a,...er(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=n.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new h("INVALID_ARGS","focus requires x y");return await l.focus(e,t),{x:e,y:t,...er(`Focused (${e}, ${t})`)}}case"type":{let e=function(e){let t=e[0]?.trim();if(!t||!t.startsWith("@")||t.length<3)return null;let n=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(n)||/^(?:ref|node|element|el)[\w-]*$/i.test(n)?t:null}(n);if(e)throw new h("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=n.join(" ");if(!t)throw new h("INVALID_ARGS","type requires text");let a=ei(r?.delayMs??0,"delay-ms",0,1e4);return await l.type(t,a),{text:t,delayMs:a,...er(sp("Typed",t))}}case"fill":{let e=Number(n[0]),t=Number(n[1]),a=n.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new h("INVALID_ARGS","fill requires x y text");let i=ei(r?.delayMs??0,"delay-ms",0,1e4);return await l.fill(e,t,a,i),{x:e,y:t,text:a,delayMs:i,...er(sp("Filled",a))}}case"scroll":return sn(l,n,r);case"pinch":return sa(e,n,r,o);case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),n=e[1]?.trim();if(!t)throw new h("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oT.test(t))throw new h("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 h("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let n=JSON.parse(e);if(!n||"object"!=typeof n||Array.isArray(n))throw new h("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(n);if(Buffer.byteLength(a,"utf8")>8192)throw new h("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return n}catch(t){if(t instanceof h)throw t;throw new h("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(n,t);return{eventName:t,payload:a}}(n),i=function(e,t,n){var a;let i,r=(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(!r)throw new h("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=n?JSON.stringify(n):"",s=r.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new h("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 l.open(i,{appBundleId:r?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...er(`Triggered app event: ${t}`)}}case"screenshot":{let e=n[0]??a??`./screenshot-${Date.now()}.png`;return await i.mkdir(s.dirname(e),{recursive:!0}),await l.screenshot(e,{appBundleId:r?.appBundleId,fullscreen:r?.screenshotFullscreen,surface:r?.surface}),{path:e,...er(`Saved screenshot: ${e}`)}}case"back":return await l.back(r?.backMode),{action:"back",mode:r?.backMode??"in-app",...er("Back")};case"home":return await l.home(),{action:"home",...er("Home")};case"rotate":{let e=oU(n[0]);return await l.rotate(e),{action:"rotate",orientation:e,...er(`Rotated to ${e}`)}}case"app-switcher":return await l.appSwitcher(),{action:"app-switcher",...er("Opened app switcher")};case"clipboard":return si(l,n);case"keyboard":return sr(e,l,n,r,o);case"settings":return so(e,l,n,r);case"push":return ss(e,n,r);case"snapshot":return sl(e,n,r,o);case"read":return sd(e,n,r,o);default:throw new h("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function o7(e,t,n,a){let i=n[0],r=n[1];if(n.length>2)throw new h("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!i)return await t.openDevice(),{app:null,...er("Opened device")};if(void 0!==r){if("android"===e.platform)throw new h("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(n$(i))throw new h("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!n$(r))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(i,{activity:a?.activity,appBundleId:a?.appBundleId,url:r}),{app:i,url:r,...er(`Opened: ${i}`)}}return await t.open(i,{activity:a?.activity,appBundleId:a?.appBundleId}),{app:i,...er(`Opened: ${i}`)}}async function se(e,t,n,a,i){let r,[o,s]=n.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new h("INVALID_ARGS","press requires x y");if("macos"===e.platform&&a?.surface&&"app"!==a.surface){let e=oC(a);if("primary"!==e)throw new h("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${a.surface} sessions.`);return await nP(o,s,{bundleId:a.appBundleId,surface:a.surface}),{x:o,y:s,...er(su({x:o,y:s}))}}let l=oC(a);if("primary"!==l){let t=oO({commandLabel:"click",platform:e.platform,button:l,count:a?.count,intervalMs:a?.intervalMs,holdMs:a?.holdMs,jitterPx:a?.jitterPx,doubleTap:a?.doubleTap});if(t)throw t;return"linux"===e.platform?"secondary"===l?await oo(o,s):await os(o,s):await nw(e,{command:"mouseClick",x:o,y:s,button:l,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:o,y:s,button:l,...er(su({x:o,y:s,button:l}))}}let d=ei(a?.count??1,"count",1,200),u=ei(a?.intervalMs??0,"interval-ms",0,1e4),c=ei(a?.holdMs??0,"hold-ms",0,1e4),p=ei(a?.jitterPx??0,"jitter-px",0,100),f=a?.doubleTap===!0;if(f&&c>0)throw new h("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new h("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(eU(e.platform)&&d>1&&0===c&&0===p){let t=await nw(e,{command:"tapSeries",x:o,y:s,count:d,intervalMs:u,doubleTap:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,timingMode:"runner-series",...t,...er(su({x:o,y:s}))}}return await oR(d,u,async e=>{let[n,a]=function(e,t){if(t<=0)return[0,0];let[n,a]=ok[e%ok.length];return[n*t,a*t]}(e,p),i=o+n,l=s+a;if(f){r??=await t.doubleTap(i,l)??void 0;return}c>0?r??=await t.longPress(i,l,c)??void 0:r??=await t.tap(i,l)??void 0}),es({x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,...r},su({x:o,y:s}))}async function st(e,t,n,a,i){let r=Number(n[0]),o=Number(n[1]),s=Number(n[2]),l=Number(n[3]);if([r,o,s,l].some(Number.isNaN))throw new h("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let d=ei(n[4]?Number(n[4]):250,"durationMs",16,1e4),u="ios"===e.platform?Math.min(60,Math.max(16,Math.round(d))):d,c=ei(a?.count??1,"count",1,200),p=ei(a?.pauseMs??0,"pause-ms",0,1e4),f=a?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new h("INVALID_ARGS",`Invalid pattern: ${f}`);if(eU(e.platform)&&c>1){let t=await nw(e,{command:"dragSeries",x:r,y:o,x2:s,y2:l,durationMs:u,count:c,pauseMs:p,pattern:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x1:r,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"runner-series",count:c,pauseMs:p,pattern:f,...t,...er(sc(c,f))}}return await oR(c,p,async e=>{"ping-pong"===f&&e%2==1?await t.swipe(s,l,r,o,u):await t.swipe(r,o,s,l,u)}),es({x1:r,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:c,pauseMs:p,pattern:f},sc(c,f))}async function sn(e,t,n){let a=t[0],i=t[1]?Number(t[1]):void 0,r=n?.pixels;if(!a)throw new h("INVALID_ARGS","scroll requires direction");if(void 0!==i&&!Number.isFinite(i))throw new h("INVALID_ARGS","scroll amount must be a number");if(void 0!==i&&void 0!==r)throw new h("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let o=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new h("INVALID_ARGS",`Unknown direction: ${e}`)}}(a),s=await e.scroll(o,{amount:i,pixels:r});return es({direction:o,...void 0!==i?{amount:i}:{},...void 0!==r?{pixels:r}:{},...s},void 0!==r?`Scrolled ${o} by ${r}px`:void 0!==i?`Scrolled ${o} by ${i}`:`Scrolled ${o}`)}async function sa(e,t,n,a){if("android"===e.platform)throw new h("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&n?.surface&&"app"!==n.surface)throw new h("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let i=Number(t[0]),r=t[1]?Number(t[1]):void 0,o=t[2]?Number(t[2]):void 0;if(Number.isNaN(i)||i<=0)throw new h("INVALID_ARGS","pinch requires scale > 0");return await nw(e,{command:"pinch",scale:i,x:r,y:o,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{scale:i,x:r,y:o,...er(`Pinched to scale ${i}`)}}async function si(e,t){let n=(t[0]??"").toLowerCase();if("read"!==n&&"write"!==n)throw new h("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===n){if(1!==t.length)throw new h("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:n,text:await e.readClipboard()}}if(t.length<2)throw new h("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let a=t.slice(1).join(" ");return await e.writeClipboard(a),{action:n,textLength:Array.from(a).length,...er("Clipboard updated")}}async function sr(e,t,n,a,i){let r=(n[0]??"status").toLowerCase();if("status"!==r&&"get"!==r&&"dismiss"!==r)throw new h("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(n.length>1)throw new h("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===r){let t=await id(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 t=await il(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==r)throw new h("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await nw(e,{command:"keyboardDismiss",appBundleId:a?.appBundleId},i);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...er(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new h("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function so(e,t,n,a){var i;let[r,o,s,l,d]=n,u="permission"===r?{permissionTarget:s,permissionMode:l}:void 0;E({level:"debug",phase:"settings_apply",data:{setting:r,state:o,target:s,mode:l,platform:e.platform}});let c=await t.setSetting(r,o,d??a?.appBundleId,u);return c&&"object"==typeof c?es({setting:r,state:o,...c},("string"==typeof(i=c).message&&i.message.length>0?i.message:void 0)??`Updated setting: ${r}`):{setting:r,state:o,...er(`Updated setting: ${r}`)}}async function ss(e,t,n){let a=t[0]?.trim(),i=t[1]?.trim();if(!a||!i)throw new h("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let r=await oF(i);if("ios"===e.platform)return await rq(e,a,r),{platform:"ios",bundleId:a,...er(`Pushed notification to ${a}`)};let o=await ix(e,a,r);return{platform:"android",package:a,action:o.action,extrasCount:o.extrasCount,...er(`Pushed notification to ${a}`)}}async function sl(e,t,n,a){if("linux"===e.platform){let e=await x("snapshot_capture",async()=>await oM(n?.surface),{backend:"linux-atspi"});return{nodes:e.nodes??[],truncated:e.truncated??!1,backend:"linux-atspi"}}if("android"!==e.platform){let t=await x("snapshot_capture",async()=>await nw(e,{command:"snapshot",appBundleId:n?.appBundleId,interactiveOnly:n?.snapshotInteractiveOnly,compact:n?.snapshotCompact,depth:n?.snapshotDepth,scope:n?.snapshotScope,raw:n?.snapshotRaw},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{backend:"xctest"}),a=t.nodes??[];if(0===a.length&&"simulator"===e.kind)throw new h("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:a,truncated:t.truncated??!1,backend:"xctest"}}let i=await x("snapshot_capture",async()=>await aB(e,{interactiveOnly:n?.snapshotInteractiveOnly,compact:n?.snapshotCompact,depth:n?.snapshotDepth,scope:n?.snapshotScope,raw:n?.snapshotRaw}),{backend:"android"});return{nodes:i.nodes??[],truncated:i.truncated??!1,backend:"android",analysis:i.analysis}}async function sd(e,t,n,a){let[i,r]=t.map(Number);if(Number.isNaN(i)||Number.isNaN(r))throw new h("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await io(e,i,r)??""};if("macos"===e.platform&&n?.surface&&"app"!==n.surface)return{action:"read",text:(await nR(i,r,{bundleId:n.appBundleId,surface:n.surface})).text};let o=await nw(e,{command:"readText",x:i,y:r,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId});return{action:"read",text:"string"==typeof o.text?o.text:"string"==typeof o.message?o.message:""}}function su(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sc(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sp(e,t){return`${e} ${Array.from(t).length} chars`}let sf=F(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sm(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 sh(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(em);await t(e.id)}}async function sh(e){let t=s.join(r.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=Math.max(1,Math.ceil(sf/1e3));try{let a=await L("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(n)],{allowFailure:!0,timeoutMs:sf+3e3}),i=String(a.stdout??""),r=String(a.stderr??""),o=await sw(t);if(0===a.exitCode){if(!o.parsed)throw new h("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:r,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 h("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 h("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:r,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sy(i,r)})}catch(t){if(t instanceof h&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let n=t.details??{},a=String(n.stdout??""),i=String(n.stderr??""),r=Number(n.timeoutMs??sf),o=`CoreDevice did not respond within ${r}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new h("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:r,stdout:a,stderr:i,hint:a||i?sy(a,i):o},t)}throw new h("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 i.rm(t,{force:!0}).catch(()=>{})}}async function sw(e){try{let t=await i.readFile(e,"utf8"),n=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let n=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof n?n:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(n);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sy(e,t){let n=iq(e,t);return n||(`${e}
32
- ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":ij)}async function sg(e,t,n){let a=e.get(t),i=a?.device??await o6(n??{});return a||await sm(i),{session:a,device:i}}async function sI(e,t,n){let a=!e&&"ios"===t.platform;try{return await n()}finally{a&&await nd(t.id)}}function sA(e,t,n,a){t&&e.recordAction(t,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:a})}async function sv(e){let{req:t,logPath:n,sessionStore:a,session:i,device:r}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!ez("alert",r))return eR("UNSUPPORTED_OPERATION","alert is not supported on this device");if("macos"===r.platform){let e=async()=>await nT("wait"===o?"get":o,s);if("wait"===o){let n=eP(t.positionals?.[1])??1e4,r=Date.now();for(;Date.now()-r<n;){try{let n=await e();return sA(a,i,t,n),{ok:!0,data:n}}catch{}await P(300)}return eR("COMMAND_FAILED","alert wait timed out")}let n="accept"===o||"dismiss"===o?o:"get";if("accept"===n||"dismiss"===n){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await nT(n,s);return sA(a,i,t,e),{ok:!0,data:e}}catch(n){e=n;let t=String(n?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await P(300)}throw sb(e)}let r=await nT("get",s);return sA(a,i,t,r),{ok:!0,data:r}}if("wait"===o){let e=eP(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await nw(r,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:n,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return sA(a,i,t,e),{ok:!0,data:e}}catch{}await P(300)}return eR("COMMAND_FAILED","alert wait timed out")}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:n,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await nw(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sA(a,i,t,e),{ok:!0,data:e}}catch(n){e=n;let t=String(n?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await P(300)}throw sb(e)}let u=await nw(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sA(a,i,t,u),{ok:!0,data:u}}function sb(e){if(!(e instanceof h))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new h(e.code,e.message,{...e.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):e}function s_(e,t,n,a,i){return{requestId:i??S().requestId,appBundleId:n,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,screenshotMaxSize:t?.screenshotMaxSize,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:oC(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}async function sS(e){let t,{req:n,logPath:a,sessionStore:i,session:r,device:o,parsed:s}=e,{setting:l,state:d,permissionTarget:u}=s;if(!ez("settings",o))return eR("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===o.platform&&"appearance"!==(t=l.trim().toLowerCase())&&"permission"!==t)return eR("INVALID_ARGS",eE(l));let c=r?.appBundleId,p="permission"===l?[l,d,u??"",n.positionals?.[3]??"",c??""]:[l,d,c??""],f=await o9(o,"settings",p,n.flags?.out,{...s_(a,n.flags,c,r?.trace?.outPath)});return sA(i,r,n,f??{setting:l,state:d}),{ok:!0,data:f??{setting:l,state:d}}}function sN(e,t={}){let n=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not resolve input artifacts`)},reserveOutput:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not reserve output artifacts`)},createTempFile:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not create temporary files`)}}}let sx=[250,400,600];function sE(e,t,n=e.snapshot){if("android"!==e.device.platform)return;let a=n?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:n?.nodes.length??0,baselineSignatures:a?sO(n?.nodes??[]):void 0,routeComparable:a}}function sD(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function sM(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function sC(e){return"press"===e||"click"===e||"back"===e||"open"===e}function sO(e){return e.map(e=>[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 sL(e){let t=sD(e.session);if(t&&"android"===e.device.platform)return await sk(e,t);let n=await sT(e);return sM(e.session),{snapshot:sF(n,e.flags),analysis:n.analysis}}async function sT(e){let{device:t,session:n,flags:a,outPath:i,logPath:r,snapshotScope:o}=e;if("linux"===t.platform){let e=await oM(n?.surface);return s$({nodes:e.nodes,truncated:e.truncated,backend:"linux-atspi"},{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o})}return"macos"===t.platform&&n?.surface&&"app"!==n.surface?s$(await nk(n.surface,{bundleId:"menubar"===n.surface?n.appBundleId:void 0}),{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o}):await o9(t,"snapshot",[],i,{...s_(r,{...a,snapshotScope:o},n?.appBundleId,n?.trace?.outPath)})}async function sk(e,t){let n=await sR(e),a=sP(n,t,e),i=0,r=t.markedAt+1500;for(let o of sx){if(!a)break;let s=r-Date.now();if(s<=0)break;await P(Math.min(o,s)),n=await sR(e),i+=1,a=sP(n,t,e)}return a||sM(e.session),{snapshot:n.snapshot,analysis:n.data.analysis,freshness:i>0||a?{action:t.action,retryCount:i,staleAfterRetries:!!a,reason:a??void 0}:void 0}}async function sR(e){let t=await sT(e);return{data:t,snapshot:sF(t,e.flags)}}function sP(e,t,n){var a,i;let r=n.flags?.snapshotInteractiveOnly===!0,o=e.data.analysis;if(r&&0===e.snapshot.nodes.length&&o&&o.rawNodeCount>=12)return"empty-interactive";if("ref-refresh"===n.androidFreshnessMode)return null;return(a=t.baselineCount,i=e.snapshot.nodes.length,!(a<12)&&i<=Math.floor(.2*a))?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&sC(t.action)&&function(e,t){if(!e||0===e.length)return!1;let n=Math.max(e.length,t.length);if(n<12)return!1;let a=sO(t),i=Math.min(e.length,a.length),r=0;for(let t=0;t<i;t+=1)e[t]===a[t]&&(r+=1);let o=Math.max(0,a.length-e.length),s=Math.max(0,e.length-a.length),l=Math.max(3,Math.floor(.15*n));return r>=Math.floor(.9*n)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function sF(e,t){let n=e?.nodes??[],a=ea(t?.snapshotRaw?n:A(n));return{nodes:ep(t?.snapshotScope&&e?.backend!=="macos-helper"?sU(a,t.snapshotScope):a),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function s$(e,t){var n,a;let i=e.nodes??[];return t.snapshotScope&&(i=sU(i,t.snapshotScope)),t.snapshotInteractiveOnly&&(i=function(e){if(0===e.length)return e;let t=new Map;for(let n of e)t.set(n.index,n);let n=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&&!n.has(e.index);)n.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===n.size?e:sG(e.filter(e=>n.has(e.index)))}(i)),"number"==typeof t.snapshotDepth&&(n=i,a=t.snapshotDepth,i=sG(n.filter(e=>(e.depth??0)<=a))),{...e,nodes:i}}function sU(e,t){let n=v(ep(e),t);if(!n)return[];let a=e.findIndex(e=>e.index===n.index);if(-1===a)return[];let i=e[a]?.depth??0,r=[];for(let t=a;t<e.length;t+=1){let n=e[t];if(!n)continue;let o=n.depth??0;if(t>a&&o<=i)break;r.push(n)}return sG(r,i)}function sG(e,t=0){let n=new Map;for(let[t,a]of e.entries())n.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?n.get(e.parentIndex):void 0}))}function sV(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return eR("INVALID_ARGS","Ref scope requires an existing snapshot in session.");let n=ec(e.trim());if(!n)return eR("INVALID_ARGS",`Invalid ref scope: ${e}`);let a=ed(t.snapshot.nodes,n),i=a?b(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:eR("COMMAND_FAILED",`Ref ${e} not found or has no label`)}async function sB(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sg(i,n,t.flags);if(!ez("snapshot",o))return eR("UNSUPPORTED_OPERATION","snapshot is not supported on this device");let s=sV(t.flags?.snapshotScope,r);return s.ok?await sI(r,o,async()=>{let e=sq({req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s.scope}),l=await e.capture.snapshot({session:n,interactiveOnly:t.flags?.snapshotInteractiveOnly,compact:t.flags?.snapshotCompact,depth:t.flags?.snapshotDepth,scope:s.scope,raw:t.flags?.snapshotRaw});return sW({req:t,sessionName:n,sessionStore:i,result:{nodes:l.nodes.length,truncated:l.truncated}}),{ok:!0,data:l}}):s}async function sj(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sg(i,n,t.flags);if(!ez("diff",o))return eR("UNSUPPORTED_OPERATION","diff is not supported on this device");let s=sV(t.flags?.snapshotScope,r);return s.ok?await sI(r,o,async()=>{let e=sq({req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s.scope}),l=await e.capture.diffSnapshot({session:n,interactiveOnly:t.flags?.snapshotInteractiveOnly,compact:t.flags?.snapshotCompact,depth:t.flags?.snapshotDepth,scope:s.scope,raw:t.flags?.snapshotRaw});return sW({req:t,sessionName:n,sessionStore:i,result:{mode:"snapshot",baselineInitialized:l.baselineInitialized,summary:l.summary}}),{ok:!0,data:l}}):s}function sq(e){let{req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s}=e;return _({backend:function(e){let{req:t,logPath:n,session:a,device:i,snapshotScope:r}=e;return{platform:i.platform,captureSnapshot:async(e,o)=>{let s=await sL({device:i,session:a,flags:t.flags,outPath:o?.outPath??t.flags?.out,logPath:n,snapshotScope:r});return{snapshot:s.snapshot,analysis:s.analysis,freshness:s.freshness,appName:a?.appBundleId?a.appName??a.appBundleId:void 0,appBundleId:a?.appBundleId}}}}({req:t,logPath:a,session:r,device:o,snapshotScope:s}),artifacts:sN("snapshot"),sessions:{get:e=>e===n?function(e){if(e)return{name:e.name,appBundleId:e.appBundleId,appName:e.appName,snapshot:e.snapshot,metadata:{surface:e.surface}}}(i.get(n)):void 0,set:e=>{if(!e.snapshot)throw new h("UNKNOWN","snapshot runtime did not produce session state");let t=function(e){let{session:t,sessionName:n,device:a,snapshot:i,appBundleId:r}=e;return t?{...t,snapshot:i}:{name:n,device:a,createdAt:Date.now(),appBundleId:r,snapshot:i,actions:[]}}({session:i.get(n),sessionName:n,device:o,snapshot:e.snapshot,appBundleId:e.appBundleId});e.appName&&(t.appName=e.appName),i.set(n,t)}},policy:N()})}function sW(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:e.result})}function sH(e){if(e.length<2)return null;let t=Number(e[0]),n=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(n)?{x:t,y:n}:null}async function sK(e){let{device:t,node:n,flags:a,appBundleId:i,traceOutPath:r,surface:o,contextFromFlags:s}=e,l=g(n),d=function(e){let t=function(e){if(!e)return null;let t=Number(e.x),n=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(n)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:n,width:a,height:i}:null}(e);if(!t)return null;let n=eu(t);return Number.isFinite(n.x)&&Number.isFinite(n.y)?n:null}(n.rect);if(!d)return l;try{let e=await o9(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,r),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return E({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:n.ref,surface:o,platform:t.platform}}),l}catch(e){return E({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:n.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}let sz=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function sJ(e,t){let n=function(e){if(!e)return[];let t=[];for(let[n,a]of sz)void 0!==e[n]&&t.push(a);return t}(t);return 0===n.length?null:eR("INVALID_ARGS",`${e} @ref does not support ${n.join(", ")}.`)}async function sX(e,t){let n=await sY(e);if(n)throw new h("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${n.foregroundPackage}. The tap likely escaped the app.`,n)}async function sY(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let n=await ad(e.device),a=n.package?.trim();return a&&a!==e.appBundleId&&("com.android.settings"===(t=a)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:a,activity:n.activity,hint:"com.google.android.permissioncontroller"===a?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function sZ(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function sQ(e,t,n,a){let i=e.get(t);i&&e.recordAction(i,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:a})}function s0(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function s1(e){return e.startsWith("@")?e.slice(1):e}async function s2(e){var t;let{req:n}=e;if("find"!==n.command)return null;let a=n.positionals??[];if(0===a.length)return eR("INVALID_ARGS","find requires a locator or text");let i=ef(a);if(!i.query)return eR("INVALID_ARGS","find requires a value");if(n.flags?.findFirst&&n.flags?.findLast)return eR("INVALID_ARGS","find accepts only one of --first or --last");let r=i.action;if("exists"!==(t=r)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let o=await s6(e,{requireSession:!1,capability:"find"});return o.ok?await le(async()=>{let t=await o.runtime.selectors.find({session:e.sessionName,requestId:n.meta?.requestId,locator:i.locator,query:i.query,action:r,timeoutMs:i.timeoutMs});return sQ(e.sessionStore,e.sessionName,n,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let n="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:n,action:"get attrs"}:{ref:n,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,r)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):o.response}async function s3(e){let{req:t}=e;if("get"!==t.command)return null;let n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return eR("INVALID_ARGS","get only supports text or attrs");let a=await s6(e,{requireSession:!0,capability:"get"});if(!a.ok)return a.response;let i=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let n=e.positionals?.slice(1).join(" ").trim()??"";return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:eR("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!i.ok)return i.response;if("ref"===i.target.kind){let e=sJ("get",t.flags);if(e)return e}return await le(async()=>{let r,o=await a.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:n,target:i.target});return sQ(e.sessionStore,e.sessionName,t,function(e,t){let n=Array.isArray(e.selectorChain)?e.selectorChain:void 0,a=s0(e),i=a?.kind==="ref"?s1(a.ref):void 0,r=a?.kind==="selector"?a.selector:void 0,o={...i?{ref:i}:{},...r?{selector:r}:{},...n?{selectorChain:n}:{}};if("attrs"===t)return o;let s="string"==typeof e.text?e.text:"";return{...o,text:s,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(s)}}(o,n)),r=s0(o),{...r?.kind==="ref"?{ref:s1(r.ref)}:{},...r?.kind==="selector"?{selector:r.selector}:{},..."string"==typeof o.text?{text:o.text}:{},...o.node&&"object"==typeof o.node?{node:o.node}:{}}})}async function s4(e){let{req:t}=e;if("is"!==t.command)return null;let n=(t.positionals?.[0]??"").toLowerCase();if(!eo(n))return eR("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:a}=I(t.positionals??[]);if(!a)return eR("INVALID_ARGS","is requires a selector expression");let i=a.rest.join(" ").trim();if("text"===n&&!i)return eR("INVALID_ARGS","is text requires expected text value");if("text"!==n&&a.rest.length>0)return eR("INVALID_ARGS",`is ${n} does not accept trailing values`);let r=await s6(e,{requireSession:!0,capability:"is"});if(!r.ok)return r.response;let o=await le(async()=>{let o=await r.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:n,selector:a.selectorExpression,expectedText:i});return sQ(e.sessionStore,e.sessionName,t,o),function(e){let{selectorChain:t,...n}=e;return n}(o)});return await lt(e,o,`is ${n}`)}async function s5(e){let{req:t,sessionName:n,sessionStore:a}=e,i=eF(t.positionals??[]);if(!i)return eR("INVALID_ARGS","wait requires a duration or text");let{session:r,device:o}=await sg(a,n,t.flags);if("sleep"!==i.kind&&!ez("wait",o))return eR("UNSUPPORTED_OPERATION","wait is not supported on this device");let s=async()=>{let s=s8({...e,session:r,device:o}),l=await le(async()=>{let e=await s.selectors.wait({session:n,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new h("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new h("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(i,r)});return sQ(a,n,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}});return await lt(e,l,"wait")};return"sleep"===i.kind?await s():await sI(r,o,s)}function s8(e){return _({backend:function(e){let t,{req:n,session:a,device:i,logPath:r,sessionName:o,sessionStore:s}=e,l=0;return{platform:i.platform,captureSnapshot:async(e,d)=>{var u;let c,p={...n.flags,...(u=d,c={},u?.interactiveOnly!==void 0&&(c.snapshotInteractiveOnly=u.interactiveOnly),u?.compact!==void 0&&(c.snapshotCompact=u.compact),u?.scope!==void 0&&(c.snapshotScope=u.scope),u?.depth!==void 0&&(c.snapshotDepth=u.depth),u?.raw!==void 0&&(c.snapshotRaw=u.raw),c)},f=d?.scope??n.flags?.snapshotScope,m=Date.now();if(t&&m-l<750&&!sD(a))return t;let h=await sL({device:i,session:a,flags:p,outPath:n.flags?.out,logPath:r??"",snapshotScope:f});return a&&(a.snapshot=h.snapshot,s.set(o,a)),l=m,t={snapshot:h.snapshot}},readText:async(t,o)=>({text:await sK({device:i,node:o,flags:n.flags,appBundleId:a?.appBundleId,traceOutPath:a?.trace?.outPath,surface:a?.surface,contextFromFlags:e.contextFromFlags??((e,t,n)=>s_(r??"",e,t,n))})}),findText:async(t,n)=>({found:await s9(e,n)})}}(e),artifacts:sN("selector commands",{plural:!0}),sessions:{get:t=>t===e.sessionName?function(e){if(e)return{name:e.name,appName:e.appName,appBundleId:e.appBundleId,snapshot:e.snapshot,metadata:{surface:e.surface}}}(e.session):void 0,set:t=>{e.session&&t.snapshot&&(e.session.snapshot=t.snapshot,e.sessionStore.set(e.sessionName,e.session))}},policy:N()})}async function s6(e,t){let n=e.sessionStore.get(e.sessionName);if(!n&&t.requireSession)return{ok:!1,response:eR("SESSION_NOT_FOUND","No active session. Run open first.")};let a=n?.device??await o6(e.req.flags??{});return(n||await sm(a),ez(t.capability,a))?{ok:!0,runtime:s8({...e,session:n,device:a})}:{ok:!1,response:eR("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function s9(e,t){let{device:n,session:a,req:i,logPath:r}=e;if("macos"===n.platform&&a?.surface&&"app"!==a.surface)return!!v((await s7(e)).nodes,t);if(eU(n.platform)){let e=await nw(n,{command:"findText",text:t,appBundleId:a?.appBundleId},{verbose:i.flags?.verbose,logPath:r,traceLogPath:a?.trace?.outPath,requestId:i.meta?.requestId});return e?.found===!0}return!!v((await s7(e)).nodes,t)}async function s7(e){let t=await sL({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(e.session.snapshot=t.snapshot,e.sessionStore.set(e.sessionName,e.session)),t.snapshot}async function le(e){try{return{ok:!0,data:await e()}}catch(t){let e=f(t);return eR(e.code,e.message,e.details)}}async function lt(e,t,n){var a;let i;if(t.ok)return t;let r=e.sessionStore.get(e.sessionName);if(!r)return t;try{i=await sY(r)}catch{return t}return i?eR(t.error.code,`${n} failed because ${"com.google.android.permissioncontroller"===(a=i).foregroundPackage?`Android permission dialog is blocking ${a.expectedPackage}`:`${a.foregroundPackage} is foreground instead of ${a.expectedPackage}`}.`,{...t.error.details??{},...i,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}let ln=new Set(["snapshot","diff","wait","alert","settings"]);async function la(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,r=t.command;if(!ln.has(r))return null;if("snapshot"===r)return await sB({req:t,sessionName:n,logPath:a,sessionStore:i});if("diff"===r)return t.positionals?.[0]!=="snapshot"?eR("INVALID_ARGS","diff currently supports only: diff snapshot"):await sj({req:t,sessionName:n,logPath:a,sessionStore:i});if("wait"===r)return await s5({req:t,sessionName:n,logPath:a,sessionStore:i});if("alert"===r){let{session:e,device:r}=await sg(i,n,t.flags);return await sI(e,r,async()=>await sv({req:t,logPath:a,sessionStore:i,session:e,device:r}))}if("settings"===r){let e,r,o,s=(e=t.positionals?.[0]?.toLowerCase(),r=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&r&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:r,permissionTarget:o}}:eR("INVALID_ARGS",ex));if(!s.ok)return s;let{session:l,device:d}=await sg(i,n,t.flags);return await sI(l,d,async()=>await sS({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}export{ensureAdb}from"./9323.js";export{eC as DEFAULT_BATCH_MAX_STEPS,ij as IOS_DEVICECTL_DEFAULT_HINT,tH as IOS_RUNNER_CONTAINER_BUNDLE_IDS,iT as IOS_SIMCTL_LIST_TIMEOUT_MS,eD as SESSION_SURFACES,eN as SETTINGS_USAGE_OVERRIDE,nu as abortAllIosRunnerSessions,a1 as appSwitcherAndroid,sX as assertAndroidPressStayedInApp,aZ as backAndroid,aO as buildScrollGesturePlan,sF as buildSnapshotState,oL as buttonTag,sL as captureSnapshot,sT as captureSnapshotData,tt as clearRequestCanceled,ag as closeAndroidApp,rF as closeIosApp,s_ as context_contextFromFlags,ti as createRequestCanceledError,sN as createUnsupportedArtifactAdapter,n5 as waitForAndroidBoot,id as dismissAndroidKeyboard,o9 as dispatchCommand,s2 as dispatchFindReadOnlyViaRuntime,s3 as dispatchGetViaRuntime,s4 as dispatchIsViaRuntime,n4 as ensureAndroidEmulatorBooted,sm as ensureDeviceReady,a8 as fillAndroid,oQ as findBootableIosSimulator,a5 as focusAndroid,sD as getActiveAndroidSnapshotFreshness,ad as getAndroidAppState,il as getAndroidKeyboardState,ie as getAndroidScreenSize,oO as getClickButtonValidationError,ta as getRequestSignal,no as getRunnerSessionSnapshot,la as handleSnapshotCommands,aQ as homeAndroid,al as inferAndroidAppName,aM as installAndroidApp,aD as installAndroidInstallablePathAndResolvePackageName,rU as installIosApp,rV as installIosInstallablePath,sZ as isAndroidEscapeError,eU as isApplePlatform,ez as isCommandSupportedOnDevice,n$ as isDeepLinkTarget,eX as isEnvTruthy,sC as isNavigationSensitiveAction,tn as isRequestCanceled,ai as listAndroidApps,nZ as listAndroidDevices,o4 as listAppleDevices,rH as listIosApps,iV as listIosDeviceApps,iB as listIosDeviceProcesses,a2 as longPressAndroid,sE as markAndroidSnapshotFreshness,te as markRequestCanceled,eG as matchesPlatformSelector,e$ as normalizePlatformSelector,ac as openAndroidApp,ay as openAndroidDevice,rR as openIosApp,rP as openIosDevice,eT as parseBatchStepsJson,sH as parseCoordinateTarget,oU as parseDeviceRotation,eM as parseSessionSurface,eF as parseWaitArgs,tT as parseXmlDocumentSync,n8 as prepareAndroidInstallArtifact,iQ as prepareIosInstallArtifact,aX as pressAndroid,ix as pushAndroidNotification,rq as pushIosNotification,iu as readAndroidClipboardText,io as readAndroidTextAtPoint,iZ as readInfoPlistString,rB as readIosClipboardText,sK as readTextForNode,sJ as refSnapshotFlagGuardResponse,e7 as registerRequestAbort,aC as reinstallAndroidApp,rG as reinstallIosApp,aa as resolveAndroidApp,eV as resolveAppleSimulatorSetPathForSelector,oC as resolveClickButton,nC as resolveFrontmostMacOsApp,rk as resolveIosApp,nU as resolveIosDeviceDeepLinkBundleId,iq as resolveIosDevicectlHint,oP as resolvePayloadInput,e9 as resolveRequestTrackingId,o6 as resolveTargetDevice,eR as response_errorResponse,a0 as rotateAndroid,nw as runIosRunnerCommand,nT as runMacOsAlertAction,iD as screenshotAndroid,rI as screenshotIos,a7 as scrollAndroid,iI as setAndroidSetting,rW as setIosSetting,iX as shutdownSimulator,iJ as ensureBootedSimulator,aB as snapshotAndroid,nc as stopAllIosRunnerSessions,nd as stopIosRunnerSession,aY as swipeAndroid,a3 as typeAndroid,ek as validateAndNormalizeBatchSteps,tM as withKeyedLock,ic as writeAndroidClipboardText,rj as writeIosClipboardText};
26
+ ${i}`.toLowerCase();return r.includes("timeout waiting for screen surfaces")||r.includes("nsposixerrordomain")&&r.includes("code=60")&&r.includes("screenshot")||r.includes("timed out")&&r.includes("screenshot")}let r$={settings:"com.apple.Preferences"},rU=null;function rG(e,t,n){return L("xcrun",tl(e,t),n)}function rV(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function rB(e,t){if("macos"===e.platform)return await rs(t);let n=t.trim();if(n.includes("."))return n;let a=r$[n.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await r1(e):await iJ(e,"all")).filter(e=>e.name.toLowerCase()===n.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new h("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new h("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function rj(e,t,n){if("macos"===e.platform)return void await rl(e,t,n);let a=n?.url?.trim();if(a){if(!nB(a))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await i3(e),await rG(e,["openurl",e.id,a]);return}let i=nj(n?.appBundleId??await rB(e,t),a);if(!i)throw new h("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oe(e,i,{payloadUrl:a});return}let i=t.trim();if(nB(i)){if("simulator"===e.kind){await i3(e),await rG(e,["openurl",e.id,i]);return}let t=nj(n?.appBundleId,i);if(!t)throw new h("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await oe(e,t,{payloadUrl:i});return}let r=n?.appBundleId??await rB(e,t);"simulator"===e.kind?await r7(e,r):await oe(e,r)}async function rq(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await i5(e)&&await i3(e)}async function rW(e,t){if("macos"===e.platform)return void await rd(e,t);let n=await rB(e,t);if("simulator"===e.kind){await i3(e);let t=tl(e,["terminate",e.id,n]),a=await L("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new h("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await iK(["device","process","terminate","--device",e.id,n],{action:"terminate iOS app",deviceId:e.id})}async function rH(e,t){let n=await rB(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,n],a=await L("xcrun",t,{allowFailure:!0,timeoutMs:ij});if(0!==a.exitCode){let i=String(a.stdout??""),r=String(a.stderr??"");if(!rV(`${i}
27
+ ${r}`.toLowerCase()))throw new h("COMMAND_FAILED",`Failed to uninstall iOS app ${n}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:e.id,hint:iZ(i,r)??iY})}return{bundleId:n}}await i3(e);let a=await rG(e,["uninstall",e.id,n],{allowFailure:!0});if(0!==a.exitCode&&!rV(`${a.stdout}
28
+ ${a.stderr}`.toLowerCase()))throw new h("COMMAND_FAILED",`simctl uninstall failed for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:n}}async function rz(e,t,n){let a=await i6({kind:"path",path:t},n);try{return await rJ(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function rK(e,t,n){let{bundleId:a}=await rH(e,t);return await rz(e,n,{appIdentifierHint:t}),{bundleId:a}}async function rJ(e,t){"simulator"!==e.kind?await iK(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await i3(e),await rG(e,["install",e.id,t]))}async function rX(e){if("macos"===e.platform)return await ru();i1(e,"clipboard"),await i3(e);let t=await rG(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new h("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 rY(e,t){if("macos"===e.platform)return void await rc(t);i1(e,"clipboard"),await i3(e);let n=await rG(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==n.exitCode)throw new h("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}async function rZ(e,t,n){i1(e,"push"),await i3(e);let a=await i.mkdtemp(s.join(r.tmpdir(),"agent-device-ios-push-")),o=s.join(a,"payload.apns");try{await i.writeFile(o,`${JSON.stringify(n)}
29
+ `,"utf8"),await rG(e,["push",e.id,t,o])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function rQ(e,t,n,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await rf(n);if("permission"===e){let e=i_(n);if("deny"===e)throw new h("INVALID_ARGS",eI("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new h("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await nT(e,t)}throw new h("INVALID_ARGS",eI(t))}i1(e,"settings"),await i3(e);let r=t.toLowerCase();switch(r){case"wifi":{let t=r2(n);await rG(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(r2(n)?await rG(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await rG(e,["status_bar",e.id,"clear"]));case"location":{let t=r2(n);if(!a)throw new h("INVALID_ARGS","location setting requires an active app in session");await rG(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=r4[r],a=function(e,t){let n=e.trim().toLowerCase();if("match"===n)return"match";if("nonmatch"===n)return"nonmatch";if("enroll"===n)return"enroll";if("unenroll"===n)return"unenroll";throw new h("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(n,r);await r9(e,a,{settingName:r,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await r3(e,n);await rG(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new h("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=i_(n))?"revoke":o,r=function(e,t){let n=iS(e);if("photos"!==n&&t?.trim())throw new h("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===n)return"camera";if("microphone"===n)return"microphone";if("contacts"===n)return"contacts";if("contacts-limited"===n)return"contacts-limited";if("notifications"===n)return"notifications";if("calendar"===n)return"calendar";if("location"===n)return"location";if("location-always"===n)return"location-always";if("media-library"===n)return"media-library";if("motion"===n)return"motion";if("reminders"===n)return"reminders";if("siri"===n)return"siri";if("photos"===n){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new h("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new h("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 r5(e,t,r,a);return}default:throw new h("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function r0(e,t="all"){return"macos"===e.platform?await rm(t):"simulator"===e.kind?rn(await r1(e),t):await iJ(e,t)}async function r1(e){let t=(await rG(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith("{"))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith("{"))try{let e=await L("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function r2(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 h("INVALID_ARGS",`Invalid setting state: ${e}`)}async function r3(e,t){let n=iN(t);if("toggle"!==n)return n;let a=await rG(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new h("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
30
+ ${t}`);if(!n)return null;let a=n[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new h("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let r4={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function r5(e,t,n,a){let i=await r6(e);if(!i.has(n))throw new h("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${n}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let r=["privacy",e.id,t,n,a],o="notifications"===n;if(!("reset"===t&&o))try{await rG(e,r);return}catch(t){if(!(o&&r8(t)))throw t;throw new h("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 rG(e,r);return}catch(e){if(!r8(e))throw e}try{await rG(e,["privacy",e.id,"reset","all",a])}catch(t){throw new h("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 r8(e){if(!(e instanceof h)||"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 r6(t){let n=ti(t.simulatorSetPath),a=`${process.env.PATH??""}::${n??""}`;if(rU&&e===a)return rU;let i=await rG(t,["privacy","help"],{allowFailure:!0}),r=function(e){let t=new Set,n=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){n=!0;continue}if(!n)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===r.size)throw new h("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 rU=r,e=a,r}async function r9(e,t,n){let a=function(e,t,n){let a=n.length>0?n:["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,n.modalityAliases),i=[];for(let t of a){let n=tl(e,t),a=await L("xcrun",n,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:n,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let r=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,n;let a;return t=e.stdout,n=e.stderr,(a=`${t}
32
+ ${n}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new h("UNSUPPORTED_OPERATION",`${n.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r});throw new h("COMMAND_FAILED",`Failed to simulate ${n.settingName}.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r})}async function r7(e,t){await i3(e);let n=0,a=eH.fromTimeoutMs(iB);try{await ez(async({deadline:n})=>{var a;if(n?.isExpired())throw new h("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:iB});let i=(a=["launch",e.id,t],tl(e,a)),r=await L("xcrun",i,{allowFailure:!0});if(0!==r.exitCode)throw new h("COMMAND_FAILED",`xcrun exited with code ${r.exitCode}`,{cmd:"xcrun",args:i,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!iQ(e)&&(n+=1)<3},{deadline:a})}catch(n){if(iQ(n)){var i;let a=(i=await i0(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";n.details={...n.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 n}}async function oe(e,t,n){let a=["device","process","launch","--device",e.id,t];n?.payloadUrl&&a.push("--payload-url",n.payloadUrl),await iK(a,{action:"launch iOS app",deviceId:e.id})}async function ot(e,t,n,a,i,r,o){if("tv"===t.target)return oi(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:n.appBundleId},a),r);let s=o??await on(e,t,n,a),l=aU({direction:i,amount:r?.amount,pixels:r?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return oi(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:n.appBundleId},a),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function on(e,t,n,a){let i=await e(t,{command:"interactionFrame",appBundleId:n.appBundleId},a),r=oa(i.x),o=oa(i.y),s=oa(i.referenceWidth),l=oa(i.referenceHeight);if(void 0===r||void 0===o||void 0===s||void 0===l)throw new h("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:r,originY:o,referenceWidth:s,referenceHeight:l}}function oa(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function oi(e,t){var n;let{x1:a,y1:i,x2:r,y2:o}={x1:oa((n=e).x),y1:oa(n.y),x2:oa(n.x2),y2:oa(n.y2)},s=oa(e.referenceWidth),l=oa(e.referenceHeight),d=void 0!==a&&void 0!==r?Math.round(Math.abs(r-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!==r?{x2:r}:{},...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 or(){return process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11"}let oo=null;async function os(){if(oo)return oo;let e=or();if("wayland"===e){if(await R("ydotool"))return oo={tool:"ydotool",display:e};throw new h("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await R("xdotool"))return oo={tool:"xdotool",display:e};throw new h("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function ol(...e){await L("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function od(...e){await L("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}async function ou(e,t){let{tool:n}=await os();"xdotool"===n?await ol("mousemove","--sync",String(e),String(t)):await od("mousemove","--absolute","-x",String(e),"-y",String(t))}async function oc(e,t){let{tool:n}=await os();"xdotool"===n?await ol("key","--clearmodifiers",e):await od("key",...t)}async function op(e,t,n,a){await ou(e,t);let{tool:i}=await os();"xdotool"===i?await ol("click",n):await od("click",a)}async function of(e,t){await op(e,t,"1","0xC0")}async function om(e,t){await op(e,t,"3","0xC1")}async function oh(e,t){await op(e,t,"2","0xC2")}async function ow(e,t){let{tool:n}=await os();await ou(e,t),"xdotool"===n?await ol("click","--repeat","2","1"):(await od("click","0xC0"),await od("click","0xC0"))}async function oy(e,t,n=800){let{tool:a}=await os();await ou(e,t),"xdotool"===a?(await ol("mousedown","1"),await P(n),await ol("mouseup","1")):(await od("click","--down","0xC0"),await P(n),await od("click","--up","0xC0"))}async function og(e,t){await of(e,t)}async function oI(e,t,n,a,i=300){let{tool:r}=await os();await ou(e,t),"xdotool"===r?(await ol("mousedown","1"),await ol("mousemove","--sync",String(n),String(a)),await P(i),await ol("mouseup","1")):(await od("click","--down","0xC0"),await od("mousemove","--absolute","-x",String(n),"-y",String(a)),await P(i),await od("click","--up","0xC0"))}async function oA(e,t){let{tool:n}=await os(),a=5;if(t?.pixels!=null?a="xdotool"===n?Math.max(1,Math.round(t.pixels/15)):Math.max(1,Math.round(t.pixels/40)):t?.amount!=null&&(a=Math.max(1,Math.round(5*(t.amount/.6)))),"xdotool"===n)await ol("click","--repeat",String(a),"up"===e?"4":"down"===e?"5":"left"===e?"6":"7");else if("up"===e||"down"===e){let t="up"===e?String(-a):String(a);await od("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-a):String(a);await od("mousemove","--wheel","-x",t)}}async function ov(e,t=0){let{tool:n}=await os();if("xdotool"===n){let n=["type"];t>0&&n.push("--delay",String(t)),n.push("--clearmodifiers","--",e),await ol(...n)}else await od("type","--",e)}async function ob(e,t,n,a=0){await of(e,t),await P(100),await oc("ctrl+a",["29:1","30:1","30:0","29:0"]),await P(50),await ov(n,a)}function o_(e){let t=null;return{resolve:async function(){if(t)return t;let n="wayland"===or()?"wayland":"x11";for(let a of"wayland"===n?e.wayland:e.x11)if(await R(a.command))return t={tool:a.tool,display:n};throw new h("TOOL_MISSING","wayland"===n?e.waylandError:e.x11Error)},resetCache:()=>{t=null}}}let oS=o_({wayland:[{tool:"grim",command:"grim"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],x11:[{tool:"scrot",command:"scrot"},{tool:"import",command:"import"},{tool:"gnome-screenshot",command:"gnome-screenshot"}],waylandError:"grim or gnome-screenshot is required for screenshots on Wayland. Install via your package manager.",x11Error:"scrot, import (ImageMagick), or gnome-screenshot is required for screenshots on X11. Install via your package manager."});async function oN(e){let{tool:t}=await oS.resolve();switch(t){case"grim":await L("grim",[e]);break;case"scrot":await L("scrot",[e]);break;case"import":await L("import",["-window","root",e]);break;case"gnome-screenshot":await L("gnome-screenshot",["-f",e])}}async function ox(e){if(e.includes("://")||e.startsWith("/"))return void await L("xdg-open",[e]);if(await R(e)){L(e,[],{allowFailure:!0}).catch(t=>{E({level:"warn",phase:"linux_app_launch",data:{app:e,error:String(t)}})}),await P(500);return}await L("xdg-open",[e],{allowFailure:!0})}async function oE(e){await R("wmctrl")?await L("wmctrl",["-c",e],{allowFailure:!0}):await L("pkill",["-x",e],{allowFailure:!0})}async function oD(){await oc("alt+Left",["56:1","105:1","105:0","56:0"])}async function oM(){await oc("super+d",["125:1","32:1","32:0","125:0"])}let oC=o_({wayland:[{tool:"wl-clipboard",command:"wl-paste"}],x11:[{tool:"xclip",command:"xclip"},{tool:"xsel",command:"xsel"}],waylandError:"wl-paste (wl-clipboard) is required for clipboard access on Wayland. Install via your package manager.",x11Error:"xclip or xsel is required for clipboard access on X11. Install via your package manager."});async function oO(){let{tool:e}=await oC.resolve();switch(e){case"wl-clipboard":return(await L("wl-paste",["--no-newline"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xclip":return(await L("xclip",["-selection","clipboard","-o"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xsel":return(await L("xsel",["--clipboard","--output"],{allowFailure:!0,timeoutMs:5e3})).stdout}}async function oL(e){let{tool:t}=await oC.resolve();switch(t){case"wl-clipboard":await L("wl-copy",["--",e],{allowFailure:!1,timeoutMs:5e3});break;case"xclip":await L("xclip",["-selection","clipboard"],{allowFailure:!1,timeoutMs:5e3,stdin:e});break;case"xsel":await L("xsel",["--clipboard","--input"],{allowFailure:!1,timeoutMs:5e3,stdin:e})}}oC.resetCache;let oT={"push button":"Button","toggle button":"Button","push button menu":"Button",label:"StaticText",static:"StaticText",caption:"StaticText",text:"TextField",entry:"TextField","password text":"TextField","spin button":"TextField",terminal:"TextArea","document text":"TextArea",paragraph:"TextArea",frame:"Window",window:"Window",dialog:"Dialog",alert:"Alert","file chooser":"Dialog","color chooser":"Dialog","font chooser":"Dialog",panel:"Group",filler:"Group",section:"Group",form:"Group",grouping:"Group","layered pane":"Group","glass pane":"Group","root pane":"Group","option pane":"Group","internal frame":"Group","desktop frame":"Group","block quote":"Group",article:"Group",comment:"Group",landmark:"Group",log:"Group",marquee:"Group",math:"Group",notification:"Group","content deletion":"Group","content insertion":"Group",mark:"Group",suggestion:"Group","scroll pane":"ScrollArea","scroll bar":"ScrollBar","menu bar":"MenuBar",menu:"Menu","popup menu":"Menu","menu item":"MenuItem","check menu item":"MenuItem","radio menu item":"MenuItem","tearoff menu item":"MenuItem","check box":"CheckBox","radio button":"RadioButton",switch:"Switch","combo box":"ComboBox","page tab":"Tab","page tab list":"TabList",table:"Table","tree table":"Table","table cell":"Cell","table row":"Row","table column header":"Cell","table row header":"Cell","column header":"Cell","row header":"Cell",list:"List","list item":"ListItem","list box":"List",tree:"Tree","tree item":"TreeItem","description list":"List","description term":"ListItem","description value":"ListItem","tool bar":"Toolbar","status bar":"StatusBar","info bar":"StatusBar",slider:"Slider","progress bar":"ProgressBar","level bar":"ProgressBar",image:"Image",icon:"Image",animation:"Image",canvas:"Image","drawing area":"Image",video:"Video",audio:"Audio",link:"Link",hyperlink:"Link",separator:"Separator",application:"Application","tool tip":"Tooltip",timer:"Timer",heading:"Heading",footnote:"Footnote","title bar":"TitleBar","date editor":"DateEditor",rating:"Slider"},ok="atspi-dump.py",oR=null;async function oP(e,t={}){let a;if("linux"!==process.platform)throw new h("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await R("python3"))throw new h("TOOL_MISSING","python3 is required for AT-SPI2 accessibility snapshots on Linux.");let i=t.maxNodes??1500,r=t.maxDepth??12,o=t.maxApps??24,l=[function(){if(oR)return oR;let e=s.dirname(u(import.meta.url));for(let t=0;t<5;t++){let a=s.join(e,"src","platforms","linux",ok);if(n.existsSync(a))return oR=a,a;if(0===t){let t=s.join(e,ok);if(n.existsSync(t))return oR=t,t}e=s.dirname(e)}throw new h("TOOL_MISSING",`Cannot find ${ok}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(i),"--max-depth",String(r),"--max-apps",String(o)],d=await L("python3",l,{allowFailure:!0,timeoutMs:3e4});if(0!==d.exitCode){let e=d.stderr.trim();if(e.includes("No module named")||e.includes("gi.require_version"))throw new h("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new h("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${d.exitCode}): ${e||d.stdout}`)}try{a=JSON.parse(d.stdout)}catch{throw new h("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${d.stdout.slice(0,200)}`)}if(a.error)throw new h("COMMAND_FAILED",`AT-SPI2: ${a.error}`);return{nodes:(a.nodes??[]).map(e=>{let t,n;return{index:e.index,type:(n=oT[t=e.role.toLowerCase().trim()])||t.split(/[\s_-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),role:e.role,label:e.label??void 0,value:e.value??void 0,rect:e.rect??void 0,enabled:e.enabled??void 0,selected:e.selected??void 0,hittable:e.hittable??void 0,depth:e.depth,parentIndex:e.parentIndex??void 0,pid:e.pid??void 0,appName:e.appName??void 0,windowTitle:e.windowTitle??void 0}}),truncated:a.truncated,surface:e}}async function oF(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&E({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),n=await oP(t);return{nodes:n.nodes,truncated:n.truncated}}function o$(e){return e?.clickButton??"primary"}function oU(e){return"primary"===e.button?null:"click"!==e.commandLabel?new h("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new h("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"middle"===e.button?new h("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 h("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}function oG(e){return"primary"===e?{}:{button:e}}let oV=/^[A-Za-z0-9_.:-]{1,64}$/,oB=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];async function oj(e,t,n){for(let a=0;a<e;a+=1)await n(a),a<e-1&&t>0&&await P(t)}function oq(e,t){let a,i=t?.subject??"Payload",r=e.trim();if(!r)throw new h("INVALID_ARGS",`${i} cannot be empty`);let o=t?.expandPath?t.expandPath(r,t.cwd):r;try{if(!n.statSync(o).isFile())throw new h("INVALID_ARGS",`${i} path is not a file: ${o}`);return{kind:"file",path:o}}catch(t){if(t instanceof h)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new h("INVALID_ARGS",`${i} file is not readable: ${o}`);if(e&&"ENOENT"!==e)throw new h("COMMAND_FAILED",`Unable to read ${i} file: ${o}`,{cause:String(t)})}if((a=r.trim()).startsWith("{")&&a.endsWith("}")||a.startsWith("[")&&a.endsWith("]"))return{kind:"inline",text:r};throw new h("INVALID_ARGS",`${i} file not found: ${o}`)}async function oW(e){let t=oq(e,{subject:"Push payload"}),n="inline"===t.kind?t.text:await oH(t.path);try{let e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new h("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof h)throw t;throw new h("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function oH(e){try{return await i.readFile(e,"utf8")}catch(n){let t=n.code;if("ENOENT"===t)throw new h("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new h("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new h("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new h("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(n)})}}function oz(e){if(void 0===e)throw new h("INVALID_ARGS","rotate requires an orientation argument. Use portrait|portrait-upside-down|landscape-left|landscape-right.");switch(e?.trim().toLowerCase()){case"portrait":return"portrait";case"portrait-upside-down":case"upside-down":return"portrait-upside-down";case"landscape-left":case"left":return"landscape-left";case"landscape-right":case"right":return"landscape-right";default:throw new h("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}let oK=F(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),oJ=/^(iphone|ipad|ipod|appletv)/i,oX=/\b(iphone|ipad|ipod)\b/i,oY=/^appletv/i,oZ=["apple tv","appletv","tvos"],oQ=/^==\s*(.+?)\s*==$/,o0=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function o1(e){return(e??"").trim().toLowerCase()}function o2(e){return o1(e.hardwareProperties?.platform)}function o3(e){return e.includes("tvos")}function o4(e){let t=o1(e);return oZ.some(e=>t.includes(e))}function o5(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function o8(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function o6(e={}){let t,n,a=ti(e.simulatorSetPath),i=e.target;try{t=await L("xcrun",ts(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{n=JSON.parse(t.stdout)}catch{return null}let r=o9(n,a),o=null,s=null,l=null;for(let e of r)i&&e.target!==i||(e.booted&&(o=o??e),"mobile"===e.target&&(s=s??e),l=l??e);return o??s??l}function o9(e,t){let n=[];for(let[a,i]of Object.entries(e.devices))if(function(e){let t=o1(e);return t.includes("ios")||t.includes("tvos")}(a))for(let e of i)e.isAvailable&&n.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:o3(o1(a))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return n}function o7(e,t){let n=new Set(e.map(e=>e.id)),a=[...e];for(let e of t)n.has(e.id)||(n.add(e.id),a.push(e));return a}async function se(){let e=null;try{e=s.join(r.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let t=await L("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:oK});if(0!==t.exitCode)return[];let n=await i.readFile(e,"utf8");return function(e){let t=[];for(let n of e.result?.devices??[]){if(!function(e){var t;let n=o2(e);return!!(n.includes("ios")||n.includes("tvos"))||(t=o8(e),!!oJ.test(t.trim())||o5(e).some(o4))}(n))continue;let e=n.hardwareProperties?.udid??n.identifier??"",a=n.name??n.deviceProperties?.name??e;e&&t.push({platform:"ios",id:e,name:a,kind:"device",target:function(e){var t;return o3(o2(e))?"tv":(t=o8(e),oY.test(t.trim())||o5(e).some(o4))?"tv":"mobile"}(n),booted:!0})}return t}(JSON.parse(n))}catch{return[]}finally{e&&await i.rm(e,{force:!0}).catch(()=>{})}}async function st(){try{let e=await L("xcrun",["xctrace","list","devices"],{allowFailure:!0});if(0!==e.exitCode)return[];return function(e){let t=[],n=null;for(let a of e.split(/\r?\n/)){let e=a.trim();if(!e)continue;let i=oQ.exec(e);if(i){n=i[1]?.trim()??null;continue}if("Devices"!==n)continue;let r=o0.exec(e),o=r?.groups?.id?.trim()??"",s=r?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return o4(e)?"tv":oX.test(e.trim())?"mobile":null}(s);l&&t.push({platform:"ios",id:o,name:s,kind:"device",target:l,booted:!0})}return t}(e.stdout)}catch{return[]}}async function sn(e={}){if("darwin"!==process.platform)throw new h("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await R("xcrun"))throw new h("TOOL_MISSING","xcrun not found in PATH");let t=ti(e.simulatorSetPath),n=await L("xcrun",ts(["list","devices","-j"],{simulatorSetPath:t})),a=[];try{let e=JSON.parse(n.stdout);a=o9(e,t)}catch(e){throw new h("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(a.push({platform:"macos",id:"host-macos-local",name:r.hostname(),kind:"device",target:"desktop",booted:!0}),t)return a;let[i,o]=await Promise.all([se(),st()]);return a=o7(a,i),o7(a,o)}async function sa(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:o(),kind:"device",target:"desktop",booted:!0}]}async function si(e,t,n){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await ek(e,t,n)}catch(e){if(i||!(e instanceof h)||"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 o6({simulatorSetPath:n.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new h("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function sr(e){let t=eC(e.platform),n=eT({simulatorSetPath:ti(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=to(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 h("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|macos|android|linux|apple with --target mobile|tv|desktop.");if("linux"===i.platform){let e=await sa();return await ek(e,i)}if("android"===i.platform){await nG();let e=await n2({serialAllowlist:a});return await ek(e,i)}if(i.platform){let e=await sn({simulatorSetPath:n});return await si(e,i,{simulatorSetPath:n})}let r=[];try{r.push(...await n2({serialAllowlist:a}))}catch{}try{r.push(...await sn({simulatorSetPath:n}))}catch{}try{r.push(...await sa())}catch{}return await ek(r,i,{simulatorSetPath:n})},{platform:t,target:e.target})}async function so(e,t,n,a,r){let o={requestId:r?.requestId,appBundleId:r?.appBundleId,verbose:r?.verbose,logPath:r?.logPath,traceLogPath:r?.traceLogPath},l=function(e,t){switch(e.platform){case"android":return{open:(t,n)=>aI(e,t,n?.activity),openDevice:()=>aN(e),close:t=>ax(e,t),tap:(t,n)=>a4(e,t,n),doubleTap:async(t,n)=>{await a4(e,t,n),await a4(e,t,n)},swipe:(t,n,a,i,r)=>a5(e,t,n,a,i,r),longPress:(t,n,a)=>ie(e,t,n,a),focus:(t,n)=>ii(e,t,n),type:(t,n)=>it(e,t,n),fill:(t,n,a,i)=>ir(e,t,n,a,i),scroll:(t,n)=>il(e,t,n),screenshot:t=>iP(e,t),back:t=>a8(e),home:()=>a6(e),rotate:t=>a9(e,t),appSwitcher:()=>a7(e),readClipboard:()=>iI(e),writeClipboard:t=>iA(e,t),setSetting:(t,n,a,i)=>iE(e,t,n,a,i)};case"linux":return{open:e=>ox(e),openDevice:()=>Promise.resolve(),close:e=>oE(e),tap:(e,t)=>of(e,t),doubleTap:(e,t)=>ow(e,t),swipe:(e,t,n,a,i)=>oI(e,t,n,a,i),longPress:(e,t,n)=>oy(e,t,n),focus:(e,t)=>og(e,t),type:(e,t)=>ov(e,t),fill:(e,t,n,a)=>ob(e,t,n,a),scroll:(e,t)=>oA(e,t),screenshot:e=>oN(e),back:()=>oD(),home:()=>oM(),rotate:()=>{throw new h("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new h("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>oO(),writeClipboard:e=>oL(e),setSetting:()=>{throw new h("UNSUPPORTED_OPERATION","setSetting not supported on Linux")}};case"ios":case"macos":{let n,{overrides:a,runnerOpts:i}={runnerOpts:n={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId},overrides:{tap:async(a,i)=>await ny(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),doubleTap:async(a,i)=>await ny(e,{command:"tapSeries",x:a,y:i,count:1,intervalMs:0,doubleTap:!0,appBundleId:t.appBundleId},n),swipe:async(a,i,r,o,s)=>await ny(e,{command:"drag",x:a,y:i,x2:r,y2:o,durationMs:s,appBundleId:t.appBundleId},n),longPress:async(a,i,r)=>await ny(e,{command:"longPress",x:a,y:i,durationMs:r,appBundleId:t.appBundleId},n),focus:async(a,i)=>await ny(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),type:async(a,i)=>{await ny(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},n)},fill:async(a,i,r,o)=>{let s=await ny(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n);return await ny(e,{command:"type",text:r,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},n),s},scroll:async(a,i)=>await ot(ny,e,t,n,a,i)}};return{open:(t,n)=>rj(e,t,{appBundleId:n?.appBundleId,url:n?.url}),openDevice:()=>rq(e),close:t=>rW(e,t),screenshot:async(t,n)=>{"macos"===e.platform&&n?.surface&&"app"!==n.surface?await n$(t,{surface:n.surface,fullscreen:n.fullscreen}):await rE(e,t,n?.appBundleId,n?.fullscreen)},back:async n=>{await ny(e,{command:"system"===n?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await ny(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async n=>{await ny(e,{command:"rotate",orientation:n,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await ny(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>rX(e),writeClipboard:t=>rY(e,t),setSetting:(t,n,a,i)=>rQ(e,t,n,a,i),...a}}default:throw new h("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,o);return E({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await x("platform_command",async()=>{switch(t){case"open":return ss(e,l,n,r);case"close":{let e=n[0];if(!e)return{closed:"session",...Y("Closed session")};return await l.close(e),{app:e,...Y(`Closed: ${e}`)}}case"press":return sl(e,l,n,r,o);case"swipe":return sd(e,l,n,r,o);case"longpress":{let e=Number(n[0]),t=Number(n[1]),a=n[2]?Number(n[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new h("INVALID_ARGS","longpress requires x y [durationMs]");return await l.longPress(e,t,a),{x:e,y:t,durationMs:a,...Y(`Long pressed (${e}, ${t})`)}}case"focus":{let[e,t]=n.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new h("INVALID_ARGS","focus requires x y");return await l.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 n=t.slice(1);return/^[A-Za-z_-]*\d[\w-]*$/i.test(n)||/^(?:ref|node|element|el)[\w-]*$/i.test(n)?t:null}(n);if(e)throw new h("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=n.join(" ");if(!t)throw new h("INVALID_ARGS","type requires text");let a=X(r?.delayMs??0,"delay-ms",0,1e4);return await l.type(t,a),{text:t,delayMs:a,...Y(sA("Typed",t))}}case"fill":{let e=Number(n[0]),t=Number(n[1]),a=n.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new h("INVALID_ARGS","fill requires x y text");let i=X(r?.delayMs??0,"delay-ms",0,1e4);return await l.fill(e,t,a,i),{x:e,y:t,text:a,delayMs:i,...Y(sA("Filled",a))}}case"scroll":return su(l,n,r);case"pinch":return sc(e,n,r,o);case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),n=e[1]?.trim();if(!t)throw new h("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oV.test(t))throw new h("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 h("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let n=JSON.parse(e);if(!n||"object"!=typeof n||Array.isArray(n))throw new h("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(n);if(Buffer.byteLength(a,"utf8")>8192)throw new h("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return n}catch(t){if(t instanceof h)throw t;throw new h("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(n,t);return{eventName:t,payload:a}}(n),i=function(e,t,n){var a;let i,r=(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(!r)throw new h("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=n?JSON.stringify(n):"",s=r.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(o)).replaceAll("{platform}",encodeURIComponent(e));if(s.length>4096)throw new h("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 l.open(i,{appBundleId:r?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link",...Y(`Triggered app event: ${t}`)}}case"screenshot":{let e=n[0]??a??`./screenshot-${Date.now()}.png`;return await i.mkdir(s.dirname(e),{recursive:!0}),await l.screenshot(e,{appBundleId:r?.appBundleId,fullscreen:r?.screenshotFullscreen,surface:r?.surface}),{path:e,...Y(`Saved screenshot: ${e}`)}}case"back":return await l.back(r?.backMode),{action:"back",mode:r?.backMode??"in-app",...Y("Back")};case"home":return await l.home(),{action:"home",...Y("Home")};case"rotate":{let e=oz(n[0]);return await l.rotate(e),{action:"rotate",orientation:e,...Y(`Rotated to ${e}`)}}case"app-switcher":return await l.appSwitcher(),{action:"app-switcher",...Y("Opened app switcher")};case"clipboard":return sp(l,n);case"keyboard":return sf(e,l,n,r,o);case"settings":return sm(e,l,n,r);case"push":return sh(e,n,r);case"snapshot":return sw(e,n,r,o);case"read":return sy(e,n,r,o);default:throw new h("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function ss(e,t,n,a){let i=n[0],r=n[1];if(n.length>2)throw new h("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!i)return await t.openDevice(),{app:null,...Y("Opened device")};if(void 0!==r){if("android"===e.platform)throw new h("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(nB(i))throw new h("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!nB(r))throw new h("INVALID_ARGS","open <app> <url> requires a valid URL target");return await t.open(i,{activity:a?.activity,appBundleId:a?.appBundleId,url:r}),{app:i,url:r,...Y(`Opened: ${i}`)}}return await t.open(i,{activity:a?.activity,appBundleId:a?.appBundleId}),{app:i,...Y(`Opened: ${i}`)}}async function sl(e,t,n,a,i){let r,[o,s]=n.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new h("INVALID_ARGS","press requires x y");if("macos"===e.platform&&a?.surface&&"app"!==a.surface){let e=o$(a);if("primary"!==e)throw new h("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${a.surface} sessions.`);return await nF(o,s,{bundleId:a.appBundleId,surface:a.surface}),{x:o,y:s,...Y(sg({x:o,y:s}))}}let l=o$(a);if("primary"!==l){let t=oU({commandLabel:"click",platform:e.platform,button:l,count:a?.count,intervalMs:a?.intervalMs,holdMs:a?.holdMs,jitterPx:a?.jitterPx,doubleTap:a?.doubleTap});if(t)throw t;return"linux"===e.platform?"secondary"===l?await om(o,s):await oh(o,s):await ny(e,{command:"mouseClick",x:o,y:s,button:l,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:o,y:s,button:l,...Y(sg({x:o,y:s,button:l}))}}let d=X(a?.count??1,"count",1,200),u=X(a?.intervalMs??0,"interval-ms",0,1e4),c=X(a?.holdMs??0,"hold-ms",0,1e4),p=X(a?.jitterPx??0,"jitter-px",0,100),f=a?.doubleTap===!0;if(f&&c>0)throw new h("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new h("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(eO(e.platform)&&d>1&&0===c&&0===p){let t=await ny(e,{command:"tapSeries",x:o,y:s,count:d,intervalMs:u,doubleTap:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,timingMode:"runner-series",...t,...Y(sg({x:o,y:s}))}}return await oj(d,u,async e=>{let[n,a]=function(e,t){if(t<=0)return[0,0];let[n,a]=oB[e%oB.length];return[n*t,a*t]}(e,p),i=o+n,l=s+a;if(f){r??=await t.doubleTap(i,l)??void 0;return}c>0?r??=await t.longPress(i,l,c)??void 0:r??=await t.tap(i,l)??void 0}),Q({x:o,y:s,count:d,intervalMs:u,holdMs:c,jitterPx:p,doubleTap:f,...r},sg({x:o,y:s}))}async function sd(e,t,n,a,i){let r=Number(n[0]),o=Number(n[1]),s=Number(n[2]),l=Number(n[3]);if([r,o,s,l].some(Number.isNaN))throw new h("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let d=X(n[4]?Number(n[4]):250,"durationMs",16,1e4),u="ios"===e.platform?Math.min(60,Math.max(16,Math.round(d))):d,c=X(a?.count??1,"count",1,200),p=X(a?.pauseMs??0,"pause-ms",0,1e4),f=a?.pattern??"one-way";if("one-way"!==f&&"ping-pong"!==f)throw new h("INVALID_ARGS",`Invalid pattern: ${f}`);if(eO(e.platform)&&c>1){let t=await ny(e,{command:"dragSeries",x:r,y:o,x2:s,y2:l,durationMs:u,count:c,pauseMs:p,pattern:f,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId});return{x1:r,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"runner-series",count:c,pauseMs:p,pattern:f,...t,...Y(sI(c,f))}}return await oj(c,p,async e=>{"ping-pong"===f&&e%2==1?await t.swipe(s,l,r,o,u):await t.swipe(r,o,s,l,u)}),Q({x1:r,y1:o,x2:s,y2:l,durationMs:d,effectiveDurationMs:u,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:c,pauseMs:p,pattern:f},sI(c,f))}async function su(e,t,n){let a=t[0],i=t[1]?Number(t[1]):void 0,r=n?.pixels;if(!a)throw new h("INVALID_ARGS","scroll requires direction");if(void 0!==i&&!Number.isFinite(i))throw new h("INVALID_ARGS","scroll amount must be a number");if(void 0!==i&&void 0!==r)throw new h("INVALID_ARGS","scroll accepts either a relative amount or --pixels, not both");let o=function(e){switch(e){case"up":case"down":case"left":case"right":return e;default:throw new h("INVALID_ARGS",`Unknown direction: ${e}`)}}(a),s=await e.scroll(o,{amount:i,pixels:r});return Q({direction:o,...void 0!==i?{amount:i}:{},...void 0!==r?{pixels:r}:{},...s},void 0!==r?`Scrolled ${o} by ${r}px`:void 0!==i?`Scrolled ${o} by ${i}`:`Scrolled ${o}`)}async function sc(e,t,n,a){if("android"===e.platform)throw new h("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");if("macos"===e.platform&&n?.surface&&"app"!==n.surface)throw new h("UNSUPPORTED_OPERATION","pinch is only supported in macOS app sessions. Re-open the target app without --surface desktop|menubar|frontmost-app first.");let i=Number(t[0]),r=t[1]?Number(t[1]):void 0,o=t[2]?Number(t[2]):void 0;if(Number.isNaN(i)||i<=0)throw new h("INVALID_ARGS","pinch requires scale > 0");return await ny(e,{command:"pinch",scale:i,x:r,y:o,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{scale:i,x:r,y:o,...Y(`Pinched to scale ${i}`)}}async function sp(e,t){let n=(t[0]??"").toLowerCase();if("read"!==n&&"write"!==n)throw new h("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===n){if(1!==t.length)throw new h("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:n,text:await e.readClipboard()}}if(t.length<2)throw new h("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let a=t.slice(1).join(" ");return await e.writeClipboard(a),{action:n,textLength:Array.from(a).length,...Y("Clipboard updated")}}async function sf(e,t,n,a,i){let r=(n[0]??"status").toLowerCase();if("status"!==r&&"get"!==r&&"dismiss"!==r)throw new h("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(n.length>1)throw new h("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===r){let t=await ig(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 t=await iy(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==r)throw new h("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await ny(e,{command:"keyboardDismiss",appBundleId:a?.appBundleId},i);return{platform:"ios",action:"dismiss",wasVisible:t.wasVisible,dismissed:t.dismissed,visible:t.visible,...Y(t.dismissed?"Keyboard dismissed":"Keyboard already hidden")}}throw new h("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function sm(e,t,n,a){var i;let[r,o,s,l,d]=n,u="permission"===r?{permissionTarget:s,permissionMode:l}:void 0;E({level:"debug",phase:"settings_apply",data:{setting:r,state:o,target:s,mode:l,platform:e.platform}});let c=await t.setSetting(r,o,d??a?.appBundleId,u);return c&&"object"==typeof c?Q({setting:r,state:o,...c},("string"==typeof(i=c).message&&i.message.length>0?i.message:void 0)??`Updated setting: ${r}`):{setting:r,state:o,...Y(`Updated setting: ${r}`)}}async function sh(e,t,n){let a=t[0]?.trim(),i=t[1]?.trim();if(!a||!i)throw new h("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let r=await oW(i);if("ios"===e.platform)return await rZ(e,a,r),{platform:"ios",bundleId:a,...Y(`Pushed notification to ${a}`)};let o=await ik(e,a,r);return{platform:"android",package:a,action:o.action,extrasCount:o.extrasCount,...Y(`Pushed notification to ${a}`)}}async function sw(e,t,n,a){if("linux"===e.platform){let e=await x("snapshot_capture",async()=>await oF(n?.surface),{backend:"linux-atspi"});return{nodes:e.nodes??[],truncated:e.truncated??!1,backend:"linux-atspi"}}if("android"!==e.platform){let t=await x("snapshot_capture",async()=>await ny(e,{command:"snapshot",appBundleId:n?.appBundleId,interactiveOnly:n?.snapshotInteractiveOnly,compact:n?.snapshotCompact,depth:n?.snapshotDepth,scope:n?.snapshotScope,raw:n?.snapshotRaw},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{backend:"xctest"}),a=t.nodes??[];if(0===a.length&&"simulator"===e.kind)throw new h("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:a,truncated:t.truncated??!1,backend:"xctest"}}let i=await x("snapshot_capture",async()=>await aX(e,{interactiveOnly:n?.snapshotInteractiveOnly,compact:n?.snapshotCompact,depth:n?.snapshotDepth,scope:n?.snapshotScope,raw:n?.snapshotRaw}),{backend:"android"});return{nodes:i.nodes??[],truncated:i.truncated??!1,backend:"android",analysis:i.analysis}}async function sy(e,t,n,a){let[i,r]=t.map(Number);if(Number.isNaN(i)||Number.isNaN(r))throw new h("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await ih(e,i,r)??""};if("macos"===e.platform&&n?.surface&&"app"!==n.surface)return{action:"read",text:(await nP(i,r,{bundleId:n.appBundleId,surface:n.surface})).text};let o=await ny(e,{command:"readText",x:i,y:r,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId});return{action:"read",text:"string"==typeof o.text?o.text:"string"==typeof o.message?o.message:""}}function sg(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function sI(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sA(e,t){return`${e} ${Array.from(t).length} chars`}let sv=F(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sb(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(es);await t(e);return}if("device"===e.kind)return void await s_(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(eo);await t(e.id)}}async function s_(e){let t=s.join(r.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),n=Math.max(1,Math.ceil(sv/1e3));try{let a=await L("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(n)],{allowFailure:!0,timeoutMs:sv+3e3}),i=String(a.stdout??""),r=String(a.stderr??""),o=await sS(t);if(0===a.exitCode){if(!o.parsed)throw new h("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:r,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 h("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 h("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:r,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:sN(i,r)})}catch(t){if(t instanceof h&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let n=t.details??{},a=String(n.stdout??""),i=String(n.stderr??""),r=Number(n.timeoutMs??sv),o=`CoreDevice did not respond within ${r}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new h("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:r,stdout:a,stderr:i,hint:a||i?sN(a,i):o},t)}throw new h("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 i.rm(t,{force:!0}).catch(()=>{})}}async function sS(e){try{let t=await i.readFile(e,"utf8"),n=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let n=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof n?n:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(n);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function sN(e,t){let n=iZ(e,t);return n||(`${e}
33
+ ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":iY)}async function sx(e,t,n){let a=e.get(t),i=a?.device??await sr(n??{});return a||await sb(i),{session:a,device:i}}async function sE(e,t,n){let a=!e&&"ios"===t.platform;try{return await n()}finally{a&&await nu(t.id)}}function sD(e,t,n,a){t&&e.recordAction(t,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:a})}async function sM(e){let{req:t,logPath:n,sessionStore:a,session:i,device:r}=e,o=(t.positionals?.[0]??"get").toLowerCase(),s=i?"frontmost-app"===i.surface?{surface:"frontmost-app"}:{bundleId:i.appBundleId,surface:i.surface}:{};if(!eG("alert",r))return eE("UNSUPPORTED_OPERATION","alert is not supported on this device");if("macos"===r.platform){let e=async()=>await nk("wait"===o?"get":o,s);if("wait"===o){let n=eD(t.positionals?.[1])??1e4,r=Date.now();for(;Date.now()-r<n;){try{let n=await e();return sD(a,i,t,n),{ok:!0,data:n}}catch{}await P(300)}return eE("COMMAND_FAILED","alert wait timed out")}let n="accept"===o||"dismiss"===o?o:"get";if("accept"===n||"dismiss"===n){let e,r=Date.now();for(;Date.now()-r<2e3;){try{let e=await nk(n,s);return sD(a,i,t,e),{ok:!0,data:e}}catch(n){e=n;let t=String(n?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await P(300)}throw sC(e)}let r=await nk("get",s);return sD(a,i,t,r),{ok:!0,data:r}}if("wait"===o){let e=eD(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await ny(r,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:n,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return sD(a,i,t,e),{ok:!0,data:e}}catch{}await P(300)}return eE("COMMAND_FAILED","alert wait timed out")}let l="accept"===o||"dismiss"===o?o:"get",d={verbose:t.flags?.verbose,logPath:n,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===l||"dismiss"===l){let e,n=Date.now();for(;Date.now()-n<2e3;){try{let e=await ny(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sD(a,i,t,e),{ok:!0,data:e}}catch(n){e=n;let t=String(n?.message??"").toLowerCase();if(!t.includes("alert not found")&&!t.includes("no alert"))break}await P(300)}throw sC(e)}let u=await ny(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sD(a,i,t,u),{ok:!0,data:u}}function sC(e){if(!(e instanceof h))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new h(e.code,e.message,{...e.details??{},hint:"If the permission sheet is visible in snapshot or screenshot but alert reports no alert, take a scoped snapshot around the visible button label and use press @ref."}):e}function sO(e,t,n,a,i){return{requestId:i??S().requestId,appBundleId:n,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,screenshotMaxSize:t?.screenshotMaxSize,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:o$(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}async function sL(e){let t,{req:n,logPath:a,sessionStore:i,session:r,device:o,parsed:s}=e,{setting:l,state:d,permissionTarget:u}=s;if(!eG("settings",o))return eE("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===o.platform&&"appearance"!==(t=l.trim().toLowerCase())&&"permission"!==t)return eE("INVALID_ARGS",eI(l));let c=r?.appBundleId,p="permission"===l?[l,d,u??"",n.positionals?.[3]??"",c??""]:[l,d,c??""],f=await so(o,"settings",p,n.flags?.out,{...sO(a,n.flags,c,r?.trace?.outPath)});return sD(i,r,n,f??{setting:l,state:d}),{ok:!0,data:f??{setting:l,state:d}}}function sT(e,t={}){let n=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not resolve input artifacts`)},reserveOutput:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not reserve output artifacts`)},createTempFile:async()=>{throw new h("UNSUPPORTED_OPERATION",`${e} ${n} not create temporary files`)}}}let sk=[250,400,600];function sR(e,t,n=e.snapshot){if("android"!==e.device.platform)return;let a=n?.comparisonSafe===!0;e.androidSnapshotFreshness={action:t,markedAt:Date.now(),baselineCount:n?.nodes.length??0,baselineSignatures:a?sU(n?.nodes??[]):void 0,routeComparable:a}}function sP(e){if(!e||"android"!==e.device.platform)return;let t=e.androidSnapshotFreshness;if(t)return Date.now()-t.markedAt>2500?void delete e.androidSnapshotFreshness:t}function sF(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function s$(e){return"press"===e||"click"===e||"back"===e||"open"===e}function sU(e){return e.map(e=>[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 sG(e){let t=sP(e.session);if(t&&"android"===e.device.platform)return await sB(e,t);let n=await sV(e);return sF(e.session),{snapshot:sW(n,e.flags),analysis:n.analysis}}async function sV(e){let{device:t,session:n,flags:a,outPath:i,logPath:r,snapshotScope:o}=e;if("linux"===t.platform){let e=await oF(n?.surface);return sH({nodes:e.nodes,truncated:e.truncated,backend:"linux-atspi"},{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o})}return"macos"===t.platform&&n?.surface&&"app"!==n.surface?sH(await nR(n.surface,{bundleId:"menubar"===n.surface?n.appBundleId:void 0}),{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o}):await so(t,"snapshot",[],i,{...sO(r,{...a,snapshotScope:o},n?.appBundleId,n?.trace?.outPath)})}async function sB(e,t){let n=await sj(e),a=sq(n,t,e),i=0,r=t.markedAt+1500;for(let o of sk){if(!a)break;let s=r-Date.now();if(s<=0)break;await P(Math.min(o,s)),n=await sj(e),i+=1,a=sq(n,t,e)}return a||sF(e.session),{snapshot:n.snapshot,analysis:n.data.analysis,freshness:i>0||a?{action:t.action,retryCount:i,staleAfterRetries:!!a,reason:a??void 0}:void 0}}async function sj(e){let t=await sV(e);return{data:t,snapshot:sW(t,e.flags)}}function sq(e,t,n){var a,i;let r=n.flags?.snapshotInteractiveOnly===!0,o=e.data.analysis;if(r&&0===e.snapshot.nodes.length&&o&&o.rawNodeCount>=12)return"empty-interactive";if("ref-refresh"===n.androidFreshnessMode)return null;return(a=t.baselineCount,i=e.snapshot.nodes.length,!(a<12)&&i<=Math.floor(.2*a))?e.snapshot.nodes.some(e=>!0===e.hittable||!!e.label?.trim()||!!e.value?.trim()||!!e.identifier?.trim())?null:"sharp-drop":t.routeComparable&&s$(t.action)&&function(e,t){if(!e||0===e.length)return!1;let n=Math.max(e.length,t.length);if(n<12)return!1;let a=sU(t),i=Math.min(e.length,a.length),r=0;for(let t=0;t<i;t+=1)e[t]===a[t]&&(r+=1);let o=Math.max(0,a.length-e.length),s=Math.max(0,e.length-a.length),l=Math.max(3,Math.floor(.15*n));return r>=Math.floor(.9*n)&&o<=l&&s<=l}(t.baselineSignatures,e.snapshot.nodes)?"stuck-route":null}function sW(e,t){let n=e?.nodes??[],a=J(t?.snapshotRaw?n:A(n));return{nodes:ei(t?.snapshotScope&&e?.backend!=="macos-helper"?sz(a,t.snapshotScope):a),truncated:e?.truncated,createdAt:Date.now(),backend:e?.backend,comparisonSafe:e?.backend==="android"&&t?.snapshotInteractiveOnly!==!0&&t?.snapshotCompact!==!0&&"number"!=typeof t?.snapshotDepth&&!t?.snapshotScope}}function sH(e,t){var n,a;let i=e.nodes??[];return t.snapshotScope&&(i=sz(i,t.snapshotScope)),t.snapshotInteractiveOnly&&(i=function(e){if(0===e.length)return e;let t=new Map;for(let n of e)t.set(n.index,n);let n=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&&!n.has(e.index);)n.add(e.index),e="number"==typeof e.parentIndex?t.get(e.parentIndex):void 0}return 0===n.size?e:sK(e.filter(e=>n.has(e.index)))}(i)),"number"==typeof t.snapshotDepth&&(n=i,a=t.snapshotDepth,i=sK(n.filter(e=>(e.depth??0)<=a))),{...e,nodes:i}}function sz(e,t){let n=v(ei(e),t);if(!n)return[];let a=e.findIndex(e=>e.index===n.index);if(-1===a)return[];let i=e[a]?.depth??0,r=[];for(let t=a;t<e.length;t+=1){let n=e[t];if(!n)continue;let o=n.depth??0;if(t>a&&o<=i)break;r.push(n)}return sK(r,i)}function sK(e,t=0){let n=new Map;for(let[t,a]of e.entries())n.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?n.get(e.parentIndex):void 0}))}function sJ(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return eE("INVALID_ARGS","Ref scope requires an existing snapshot in session.");let n=ea(e.trim());if(!n)return eE("INVALID_ARGS",`Invalid ref scope: ${e}`);let a=et(t.snapshot.nodes,n),i=a?b(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:eE("COMMAND_FAILED",`Ref ${e} not found or has no label`)}async function sX(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sx(i,n,t.flags);if(!eG("snapshot",o))return eE("UNSUPPORTED_OPERATION","snapshot is not supported on this device");let s=sJ(t.flags?.snapshotScope,r);return s.ok?await sE(r,o,async()=>{let e=sZ({req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s.scope}),l=await e.capture.snapshot({session:n,interactiveOnly:t.flags?.snapshotInteractiveOnly,compact:t.flags?.snapshotCompact,depth:t.flags?.snapshotDepth,scope:s.scope,raw:t.flags?.snapshotRaw});return sQ({req:t,sessionName:n,sessionStore:i,result:{nodes:l.nodes.length,truncated:l.truncated}}),{ok:!0,data:l}}):s}async function sY(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sx(i,n,t.flags);if(!eG("diff",o))return eE("UNSUPPORTED_OPERATION","diff is not supported on this device");let s=sJ(t.flags?.snapshotScope,r);return s.ok?await sE(r,o,async()=>{let e=sZ({req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s.scope}),l=await e.capture.diffSnapshot({session:n,interactiveOnly:t.flags?.snapshotInteractiveOnly,compact:t.flags?.snapshotCompact,depth:t.flags?.snapshotDepth,scope:s.scope,raw:t.flags?.snapshotRaw});return sQ({req:t,sessionName:n,sessionStore:i,result:{mode:"snapshot",baselineInitialized:l.baselineInitialized,summary:l.summary}}),{ok:!0,data:l}}):s}function sZ(e){let{req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s}=e;return _({backend:function(e){let{req:t,logPath:n,session:a,device:i,snapshotScope:r}=e;return{platform:i.platform,captureSnapshot:async(e,o)=>{let s=await sG({device:i,session:a,flags:t.flags,outPath:o?.outPath??t.flags?.out,logPath:n,snapshotScope:r});return{snapshot:s.snapshot,analysis:s.analysis,freshness:s.freshness,appName:a?.appBundleId?a.appName??a.appBundleId:void 0,appBundleId:a?.appBundleId}}}}({req:t,logPath:a,session:r,device:o,snapshotScope:s}),artifacts:sT("snapshot"),sessions:{get:e=>e===n?function(e){if(e)return{name:e.name,appBundleId:e.appBundleId,appName:e.appName,snapshot:e.snapshot,metadata:{surface:e.surface}}}(i.get(n)):void 0,set:e=>{if(!e.snapshot)throw new h("UNKNOWN","snapshot runtime did not produce session state");let t=function(e){let{session:t,sessionName:n,device:a,snapshot:i,appBundleId:r}=e;return t?{...t,snapshot:i}:{name:n,device:a,createdAt:Date.now(),appBundleId:r,snapshot:i,actions:[]}}({session:i.get(n),sessionName:n,device:o,snapshot:e.snapshot,appBundleId:e.appBundleId});e.appName&&(t.appName=e.appName),i.set(n,t)}},policy:N()})}function sQ(e){let t=e.sessionStore.get(e.sessionName);t&&e.sessionStore.recordAction(t,{command:e.req.command,positionals:e.req.positionals??[],flags:e.req.flags??{},result:e.result})}function s0(e){if(e.length<2)return null;let t=Number(e[0]),n=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(n)?{x:t,y:n}:null}async function s1(e){let{device:t,node:n,flags:a,appBundleId:i,traceOutPath:r,surface:o,contextFromFlags:s}=e,l=g(n),d=function(e){let t=function(e){if(!e)return null;let t=Number(e.x),n=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(n)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:n,width:a,height:i}:null}(e);if(!t)return null;let n=en(t);return Number.isFinite(n.x)&&Number.isFinite(n.y)?n:null}(n.rect);if(!d)return l;try{let e=await so(t,"read",[String(d.x),String(d.y)],void 0,{...s(a,i,r),surface:o}),u=e&&"object"==typeof e?e:void 0,c="string"==typeof u?.text?u.text:"";if(c.trim())return c;return E({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:n.ref,surface:o,platform:t.platform}}),l}catch(e){return E({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:n.ref,surface:o,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),l}}let s2=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function s3(e,t){let n=function(e){if(!e)return[];let t=[];for(let[n,a]of s2)void 0!==e[n]&&t.push(a);return t}(t);return 0===n.length?null:eE("INVALID_ARGS",`${e} @ref does not support ${n.join(", ")}.`)}async function s4(e,t){let n=await s5(e);if(n)throw new h("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${n.foregroundPackage}. The tap likely escaped the app.`,n)}async function s5(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let n=await ay(e.device),a=n.package?.trim();return a&&a!==e.appBundleId&&("com.android.settings"===(t=a)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:a,activity:n.activity,hint:"com.google.android.permissioncontroller"===a?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function s8(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function s6(e,t,n,a){let i=e.get(t);i&&e.recordAction(i,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:a})}function s9(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function s7(e){return e.startsWith("@")?e.slice(1):e}async function le(e){var t;let{req:n}=e;if("find"!==n.command)return null;let a=n.positionals??[];if(0===a.length)return eE("INVALID_ARGS","find requires a locator or text");let i=er(a);if(!i.query)return eE("INVALID_ARGS","find requires a value");if(n.flags?.findFirst&&n.flags?.findLast)return eE("INVALID_ARGS","find accepts only one of --first or --last");let r=i.action;if("exists"!==(t=r)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let o=await lr(e,{requireSession:!1,capability:"find"});return o.ok?await ll(async()=>{let t=await o.runtime.selectors.find({session:e.sessionName,requestId:n.meta?.requestId,locator:i.locator,query:i.query,action:r,timeoutMs:i.timeoutMs});return s6(e.sessionStore,e.sessionName,n,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let n="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:n,action:"get attrs"}:{ref:n,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,r)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):o.response}async function lt(e){let{req:t}=e;if("get"!==t.command)return null;let n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return eE("INVALID_ARGS","get only supports text or attrs");let a=await lr(e,{requireSession:!0,capability:"get"});if(!a.ok)return a.response;let i=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let n=e.positionals?.slice(1).join(" ").trim()??"";return n?{ok:!0,target:{kind:"selector",selector:n}}:{ok:!1,response:eE("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!i.ok)return i.response;if("ref"===i.target.kind){let e=s3("get",t.flags);if(e)return e}return await ll(async()=>{let r,o=await a.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:n,target:i.target});return s6(e.sessionStore,e.sessionName,t,function(e,t){let n=Array.isArray(e.selectorChain)?e.selectorChain:void 0,a=s9(e),i=a?.kind==="ref"?s7(a.ref):void 0,r=a?.kind==="selector"?a.selector:void 0,o={...i?{ref:i}:{},...r?{selector:r}:{},...n?{selectorChain:n}:{}};if("attrs"===t)return o;let s="string"==typeof e.text?e.text:"";return{...o,text:s,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(s)}}(o,n)),r=s9(o),{...r?.kind==="ref"?{ref:s7(r.ref)}:{},...r?.kind==="selector"?{selector:r.selector}:{},..."string"==typeof o.text?{text:o.text}:{},...o.node&&"object"==typeof o.node?{node:o.node}:{}}})}async function ln(e){let{req:t}=e;if("is"!==t.command)return null;let n=(t.positionals?.[0]??"").toLowerCase();if(!Z(n))return eE("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:a}=I(t.positionals??[]);if(!a)return eE("INVALID_ARGS","is requires a selector expression");let i=a.rest.join(" ").trim();if("text"===n&&!i)return eE("INVALID_ARGS","is text requires expected text value");if("text"!==n&&a.rest.length>0)return eE("INVALID_ARGS",`is ${n} does not accept trailing values`);let r=await lr(e,{requireSession:!0,capability:"is"});if(!r.ok)return r.response;let o=await ll(async()=>{let o=await r.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:n,selector:a.selectorExpression,expectedText:i});return s6(e.sessionStore,e.sessionName,t,o),function(e){let{selectorChain:t,...n}=e;return n}(o)});return await ld(e,o,`is ${n}`)}async function la(e){let{req:t,sessionName:n,sessionStore:a}=e,i=eM(t.positionals??[]);if(!i)return eE("INVALID_ARGS","wait requires a duration or text");let{session:r,device:o}=await sx(a,n,t.flags);if("sleep"!==i.kind&&!eG("wait",o))return eE("UNSUPPORTED_OPERATION","wait is not supported on this device");let s=async()=>{let s=li({...e,session:r,device:o}),l=await ll(async()=>{let e=await s.selectors.wait({session:n,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new h("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new h("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(i,r)});return s6(a,n,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}});return await ld(e,l,"wait")};return"sleep"===i.kind?await s():await sE(r,o,s)}function li(e){return _({backend:function(e){let t,{req:n,session:a,device:i,logPath:r,sessionName:o,sessionStore:s}=e,l=0;return{platform:i.platform,captureSnapshot:async(e,d)=>{var u;let c,p={...n.flags,...(u=d,c={},u?.interactiveOnly!==void 0&&(c.snapshotInteractiveOnly=u.interactiveOnly),u?.compact!==void 0&&(c.snapshotCompact=u.compact),u?.scope!==void 0&&(c.snapshotScope=u.scope),u?.depth!==void 0&&(c.snapshotDepth=u.depth),u?.raw!==void 0&&(c.snapshotRaw=u.raw),c)},f=d?.scope??n.flags?.snapshotScope,m=Date.now();if(t&&m-l<750&&!sP(a))return t;let h=await sG({device:i,session:a,flags:p,outPath:n.flags?.out,logPath:r??"",snapshotScope:f});return a&&(a.snapshot=h.snapshot,s.set(o,a)),l=m,t={snapshot:h.snapshot}},readText:async(t,o)=>({text:await s1({device:i,node:o,flags:n.flags,appBundleId:a?.appBundleId,traceOutPath:a?.trace?.outPath,surface:a?.surface,contextFromFlags:e.contextFromFlags??((e,t,n)=>sO(r??"",e,t,n))})}),findText:async(t,n)=>({found:await lo(e,n)})}}(e),artifacts:sT("selector commands",{plural:!0}),sessions:{get:t=>t===e.sessionName?function(e){if(e)return{name:e.name,appName:e.appName,appBundleId:e.appBundleId,snapshot:e.snapshot,metadata:{surface:e.surface}}}(e.session):void 0,set:t=>{e.session&&t.snapshot&&(e.session.snapshot=t.snapshot,e.sessionStore.set(e.sessionName,e.session))}},policy:N()})}async function lr(e,t){let n=e.sessionStore.get(e.sessionName);if(!n&&t.requireSession)return{ok:!1,response:eE("SESSION_NOT_FOUND","No active session. Run open first.")};let a=n?.device??await sr(e.req.flags??{});return(n||await sb(a),eG(t.capability,a))?{ok:!0,runtime:li({...e,session:n,device:a})}:{ok:!1,response:eE("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function lo(e,t){let{device:n,session:a,req:i,logPath:r}=e;if("macos"===n.platform&&a?.surface&&"app"!==a.surface)return!!v((await ls(e)).nodes,t);if(eO(n.platform)){let e=await ny(n,{command:"findText",text:t,appBundleId:a?.appBundleId},{verbose:i.flags?.verbose,logPath:r,traceLogPath:a?.trace?.outPath,requestId:i.meta?.requestId});return e?.found===!0}return!!v((await ls(e)).nodes,t)}async function ls(e){let t=await sG({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(e.session.snapshot=t.snapshot,e.sessionStore.set(e.sessionName,e.session)),t.snapshot}async function ll(e){try{return{ok:!0,data:await e()}}catch(t){let e=f(t);return eE(e.code,e.message,e.details)}}async function ld(e,t,n){var a;let i;if(t.ok)return t;let r=e.sessionStore.get(e.sessionName);if(!r)return t;try{i=await s5(r)}catch{return t}return i?eE(t.error.code,`${n} failed because ${"com.google.android.permissioncontroller"===(a=i).foregroundPackage?`Android permission dialog is blocking ${a.expectedPackage}`:`${a.foregroundPackage} is foreground instead of ${a.expectedPackage}`}.`,{...t.error.details??{},...i,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}let lu=new Set(["snapshot","diff","wait","alert","settings"]);async function lc(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,r=t.command;if(!lu.has(r))return null;if("snapshot"===r)return await sX({req:t,sessionName:n,logPath:a,sessionStore:i});if("diff"===r)return t.positionals?.[0]!=="snapshot"?eE("INVALID_ARGS","diff currently supports only: diff snapshot"):await sY({req:t,sessionName:n,logPath:a,sessionStore:i});if("wait"===r)return await la({req:t,sessionName:n,logPath:a,sessionStore:i});if("alert"===r){let{session:e,device:r}=await sx(i,n,t.flags);return await sE(e,r,async()=>await sM({req:t,logPath:a,sessionStore:i,session:e,device:r}))}if("settings"===r){let e,r,o,s=(e=t.positionals?.[0]?.toLowerCase(),r=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase(),e&&r&&("permission"!==e||o)?{ok:!0,parsed:{setting:e,state:r,permissionTarget:o}}:eE("INVALID_ARGS",eg));if(!s.ok)return s;let{session:l,device:d}=await sx(i,n,t.flags);return await sE(l,d,async()=>await sL({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}export{eb as DEFAULT_BATCH_MAX_STEPS,iY as IOS_DEVICECTL_DEFAULT_HINT,tz as IOS_RUNNER_CONTAINER_BUNDLE_IDS,iV as IOS_SIMCTL_LIST_TIMEOUT_MS,eA as SESSION_SURFACES,ey as SETTINGS_USAGE_OVERRIDE,nc as abortAllIosRunnerSessions,nU as adbArgs,a7 as appSwitcherAndroid,s4 as assertAndroidPressStayedInApp,a8 as backAndroid,aU as buildScrollGesturePlan,ts as buildSimctlArgs,tl as buildSimctlArgsForDevice,sW as buildSnapshotState,oG as buttonTag,sG as captureSnapshot,sV as captureSnapshotData,an as classifyAndroidAppTarget,e3 as clearRequestCanceled,ax as closeAndroidApp,rW as closeIosApp,sO as context_contextFromFlags,e8 as createRequestCanceledError,sT as createUnsupportedArtifactAdapter,n7 as waitForAndroidBoot,ig as dismissAndroidKeyboard,so as dispatchCommand,le as dispatchFindReadOnlyViaRuntime,lt as dispatchGetViaRuntime,ln as dispatchIsViaRuntime,nG as ensureAdb,n9 as ensureAndroidEmulatorBooted,sb as ensureDeviceReady,ir as fillAndroid,o6 as findBootableIosSimulator,ii as focusAndroid,aa as formatAndroidInstalledPackageRequiredMessage,sP as getActiveAndroidSnapshotFreshness,ay as getAndroidAppState,iy as getAndroidKeyboardState,id as getAndroidScreenSize,oU as getClickButtonValidationError,e5 as getRequestSignal,ns as getRunnerSessionSnapshot,lc as handleSnapshotCommands,a6 as homeAndroid,aw as inferAndroidAppName,aF as installAndroidApp,aP as installAndroidInstallablePathAndResolvePackageName,rz as installIosApp,rJ as installIosInstallablePath,s8 as isAndroidEscapeError,eO as isApplePlatform,eG as isCommandSupportedOnDevice,nB as isDeepLinkTarget,eB as isEnvTruthy,s$ as isNavigationSensitiveAction,e4 as isRequestCanceled,ap as listAndroidApps,n2 as listAndroidDevices,sn as listAppleDevices,r0 as listIosApps,iJ as listIosDeviceApps,iX as listIosDeviceProcesses,ie as longPressAndroid,sR as markAndroidSnapshotFreshness,e2 as markRequestCanceled,eL as matchesPlatformSelector,eC as normalizePlatformSelector,aI as openAndroidApp,aN as openAndroidDevice,rj as openIosApp,rq as openIosDevice,eN as parseBatchStepsJson,s0 as parseCoordinateTarget,oz as parseDeviceRotation,tr as parseSerialAllowlist,ev as parseSessionSurface,eM as parseWaitArgs,tk as parseXmlDocumentSync,ai as prepareAndroidInstallArtifact,i6 as prepareIosInstallArtifact,a4 as pressAndroid,ik as pushAndroidNotification,rZ as pushIosNotification,iI as readAndroidClipboardText,ih as readAndroidTextAtPoint,i8 as readInfoPlistString,rX as readIosClipboardText,s1 as readTextForNode,s3 as refSnapshotFlagGuardResponse,e1 as registerRequestAbort,a$ as reinstallAndroidApp,rK as reinstallIosApp,ac as resolveAndroidApp,to as resolveAndroidSerialAllowlist,eT as resolveAppleSimulatorSetPathForSelector,o$ as resolveClickButton,nO as resolveFrontmostMacOsApp,rB as resolveIosApp,nj as resolveIosDeviceDeepLinkBundleId,iZ as resolveIosDevicectlHint,ti as resolveIosSimulatorDeviceSetPath,oq as resolvePayloadInput,e0 as resolveRequestTrackingId,sr as resolveTargetDevice,eE as response_errorResponse,a9 as rotateAndroid,ny as runIosRunnerCommand,nk as runMacOsAlertAction,iP as screenshotAndroid,rE as screenshotIos,il as scrollAndroid,iE as setAndroidSetting,rQ as setIosSetting,i4 as shutdownSimulator,i3 as ensureBootedSimulator,aX as snapshotAndroid,np as stopAllIosRunnerSessions,nu as stopIosRunnerSession,a5 as swipeAndroid,it as typeAndroid,ex as validateAndNormalizeBatchSteps,tC as withKeyedLock,iA as writeAndroidClipboardText,rY as writeIosClipboardText};