agent-device 0.12.7 → 0.12.8

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.
Files changed (44) hide show
  1. package/dist/src/113.js +1 -1
  2. package/dist/src/1974.js +2 -0
  3. package/dist/src/3883.js +1 -0
  4. package/dist/src/3918.js +32 -0
  5. package/dist/src/4057.js +1 -0
  6. package/dist/src/7556.js +1 -0
  7. package/dist/src/7651.js +1 -0
  8. package/dist/src/7847.js +1 -0
  9. package/dist/src/8164.js +1 -0
  10. package/dist/src/8564.js +3 -0
  11. package/dist/src/9076.js +1 -0
  12. package/dist/src/9323.js +5 -0
  13. package/dist/src/9366.js +1 -0
  14. package/dist/src/9542.js +2 -0
  15. package/dist/src/9818.js +1 -0
  16. package/dist/src/989.js +1 -0
  17. package/dist/src/android-apps.js +1 -1
  18. package/dist/src/artifacts.js +1 -1
  19. package/dist/src/bin.d.ts +1 -0
  20. package/dist/src/bin.js +68 -70
  21. package/dist/src/commands/index.js +1 -1
  22. package/dist/src/contracts.js +1 -1
  23. package/dist/src/daemon.d.ts +1 -0
  24. package/dist/src/daemon.js +14 -14
  25. package/dist/src/finders.js +1 -1
  26. package/dist/src/index.js +1 -3
  27. package/dist/src/install-source.js +1 -1
  28. package/dist/src/io.js +1 -1
  29. package/dist/src/metro-companion.d.ts +1 -0
  30. package/dist/src/metro.js +1 -1
  31. package/dist/src/remote-config.js +1 -1
  32. package/dist/src/selectors.js +1 -1
  33. package/dist/src/testing/conformance.js +1 -1
  34. package/dist/src/update-check-entry.d.ts +1 -0
  35. package/package.json +1 -1
  36. package/dist/src/164.js +0 -1
  37. package/dist/src/556.js +0 -1
  38. package/dist/src/57.js +0 -1
  39. package/dist/src/641.js +0 -38
  40. package/dist/src/818.js +0 -1
  41. package/dist/src/974.js +0 -2
  42. /package/dist/src/{267.js → 3267.js} +0 -0
  43. /package/dist/src/{152.js → 9152.js} +0 -0
  44. /package/dist/src/{1~rslib-runtime.js → rslib-runtime.js} +0 -0
@@ -0,0 +1,32 @@
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,AppError as m}from"./9152.js";import{createAgentDevice as h,getDiagnosticsMeta as w,localCommandPolicy as y,withDiagnosticTimer as g,emitDiagnostic as I}from"./8564.js";import{runCmdStreaming as A,runCmdDetached as v,runCmdBackground as b,runCmdSync as _,runCmd as S,resolveFileOverridePath as N,whichCmd as x,resolveExecutableOverridePath as E}from"./9818.js";import{resolveTimeoutMs as D,isTrustedInstallSourceUrl as M,materializeInstallablePath as C,resolveTimeoutSeconds as O}from"./989.js";import{sleep as T,resolveIosSimulatorDeviceSetPath as L,buildSimctlArgs as k,classifyAndroidAppTarget as R,adbArgs as P,ensureAdb as F,resolveAndroidSerialAllowlist as $,isClipboardShellUnsupported as U,buildSimctlArgsForDevice as G}from"./9323.js";import{isProcessAlive as V,readProcessStartTime as B}from"./3883.js";import{ensureAndroidSdkPathConfigured as j}from"./8164.js";import{resolveAndroidArchivePackageName as q}from"./7651.js";import{parseAndroidForegroundApp as W,parseAndroidLaunchablePackages as H,parseAndroidUserInstalledPackages as K}from"./9366.js";import{buildMobileSnapshotPresentation as z,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{splitSelectorFromArgs as er,tryParseSelectorChain as eo,extractNodeReadText as es,splitIsSelectorArgs as el,pruneGroupNodes as ed,findNodeByLabel as eu,resolveRefLabel as ec}from"./7847.js";import{parseFindArgs as ep}from"./7556.js";var ef={};t.r(ef),t.d(ef,{ensureAndroidEmulatorBooted:()=>nk,listAndroidDevices:()=>nD,waitForAndroidBoot:()=>nR});var em={};t.r(em),t.d(em,{TM:()=>rO,ensureBootedSimulator:()=>i_,installIosApp:()=>rL,installIosInstallablePath:()=>rR,listIosApps:()=>rG,L5:()=>rM,IJ:()=>rC,TJ:()=>r$,J7:()=>rP,reinstallIosApp:()=>rk,resolveIosApp:()=>rD,kc:()=>rf,Cm:()=>rU,ap:()=>rF});let eh="<wifi|airplane|location> <on|off>",ew="appearance <light|dark|toggle>",ey="faceid <match|nonmatch|enroll|unenroll>",eg="touchid <match|nonmatch|enroll|unenroll>",eI="fingerprint <match|nonmatch>",eA="permission <grant|deny|reset> <camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri> [full|limited]",ev="permission <grant|reset> <accessibility|screen-recording|input-monitoring>",eb=`macOS supports only settings ${ew} and settings ${ev}. wifi|airplane|location remain unsupported on macOS.`,e_=`settings ${eh} | settings ${ew} | settings ${ey} | settings ${eg} | settings ${eI} | settings ${eA} | settings ${ev}`,eS=`settings requires ${eh}, ${ew}, ${ey}, ${eg}, ${eI}, ${eA}, or ${ev}`;function eN(e){return`Unsupported macOS setting: ${e}. ${eb}`}let ex=["app","frontmost-app","desktop","menubar"];function eE(e){let t=e?.trim().toLowerCase();if("app"===t||"frontmost-app"===t||"desktop"===t||"menubar"===t)return t;throw new m("INVALID_ARGS",`Invalid surface: ${e}. Use ${ex.join("|")}.`)}let eD=100,eM=new Set(["batch","replay"]),eC=new Set(["command","positionals","flags","runtime"]);function eO(e){let t;try{t=JSON.parse(e)}catch{throw new m("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(t)||0===t.length)throw new m("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return t}function eT(e,t){if(!Array.isArray(e)||0===e.length)throw new m("INVALID_ARGS","batch requires a non-empty batchSteps array.");if(e.length>t)throw new m("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 m("INVALID_ARGS",`Invalid batch step at index ${t}.`);let i=Object.keys(a).filter(e=>!eC.has(e));if(i.length>0){let e=i.map(e=>`"${e}"`).join(", ");throw new m("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 m("INVALID_ARGS",`Batch step ${t+1} requires command.`);if(eM.has(r))throw new m("INVALID_ARGS",`Batch step ${t+1} cannot run ${r}.`);if(void 0!==a.positionals&&!Array.isArray(a.positionals))throw new m("INVALID_ARGS",`Batch step ${t+1} positionals must be an array.`);let o=a.positionals??[];if(o.some(e=>"string"!=typeof e))throw new m("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 m("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 m("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 eL(e,t,n){return{ok:!1,error:{code:e,message:t,...n?{details:n}:{}}}}function ek(e){return e}function eR(e){return"apple"===e||"ios"===e||"macos"===e}function eP(e,t){return!t||("apple"===t?eR(e):e===t)}function eF(e){let{simulatorSetPath:t,platform:n,target:a}=e;if(t&&"macos"!==n&&"desktop"!==a)return t}async function e$(e,t,n={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>eP(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&&eR(e.platform));if(!e)throw new m("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 m("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 m("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 m("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 m("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 eU=e=>"macos"!==e.platform,eG=e=>"macos"===e.platform||"simulator"===e.kind,eV={device:!0},eB={},ej={alert:{apple:{simulator:!0,device:!0},android:{},linux:eB,supports:eG},pinch:{apple:{simulator:!0,device:!0},android:{},linux:eB,supports:eG},"app-switcher":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},apps:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},back:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},boot:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},click:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},clipboard:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV,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:eB,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:eV},fill:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},diff:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},find:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},focus:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},get:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},is:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},home:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV,supports:eU},logs:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},network:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},longpress:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},open:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},perf:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},install:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},"install-from-source":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},reinstall:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},press:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},push:{apple:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,supports:eU},record:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},rotate:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,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:eV},scroll:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},swipe:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},settings:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB,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:eV},"trigger-app-event":{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eB},type:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV},wait:{apple:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0},linux:eV}};function eq(e,t){let n=ej[e];if(!n)return!0;let a=eR(t.platform)?n.apple:"linux"===t.platform?n.linux:n.android;return!!a&&(!n.supports||!!n.supports(t))&&!0===a[t.kind??"unknown"]}let eW=eH(process.env.AGENT_DEVICE_RETRY_LOGS);function eH(e){return["1","true","yes","on"].includes((e??"").trim().toLowerCase())}let eK=2e4,ez=12e4,eJ=1e4;class eX{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new eX(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 eY(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 m("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()}),eQ({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),eQ(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),eQ(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),eQ(r),a)throw a;throw new m("COMMAND_FAILED","retry failed")}async function eZ(e,t={}){return eY(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function eQ(e){I({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),eW&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
3
+ `)}let e0=new Set,e1=new Map,e2="request_canceled",e3="request canceled";function e4(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 e5(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++}}(e1);let t=new AbortController;e1.set(e,t),e0.has(e)&&t.abort()}function e8(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++}}(e0),e0.add(e),e1.get(e)?.abort())}function e6(e){e&&(e0.delete(e),e1.delete(e))}function e9(e){return!!e&&e0.has(e)}function e7(e){if(e)return e1.get(e)?.signal}function te(){return new m("COMMAND_FAILED",e3,{reason:e2})}function tt(e){return e instanceof m&&"COMMAND_FAILED"===e.code&&(e.details?.reason===e2||e.message===e3)}function tn(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 ta(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 ti(e){return!(e instanceof m)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function tr(e){let{port:t,endpoints:n,logPath:a,lastError:i}=e,r="Runner did not accept connection";return new m("COMMAND_FAILED",r,{port:t,endpoints:n,logPath:a,lastError:i?String(i):void 0,reason:tn({error:i,message:r,context:{platform:"ios",phase:"connect"}}),hint:ta("IOS_RUNNER_CONNECT_TIMEOUT")})}async function to(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=tn({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new m("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
+ ${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.":ta("IOS_RUNNER_CONNECT_TIMEOUT"))})}function ts(e){if(e9(e))throw te()}let tl=D(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),td=D(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),tu=D(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),tc=D(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),tp=D(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),tf=D(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),tm=D(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),th=O(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function tw(e,t,n,a,i=tl,r,o){let s=eX.fromTimeoutMs(i),l=await ty(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/tu));try{return await eY(async({deadline:s})=>{if(s?.isExpired())throw new m("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(r&&null!==r.child.exitCode&&void 0!==r.child.exitCode)throw await to({session:r,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await ty(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new m("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await tg(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)},Math.min(tf,e),o)}catch(e){if(o?.aborted||tt(e))throw te();d=e}throw new m("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:tc,maxDelayMs:tp,jitter:.2,shouldRetry:ti},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||tt(e))throw te();d||(d=e)}if(o?.aborted)throw te();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw tr({port:t,endpoints:l,logPath:a,lastError:d});let r=await tA(e,t,n,i);return new Response(r.body,{status:r.status})}throw tr({port:t,endpoints:l,logPath:a,lastError:d})}async function ty(e,t,n){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await tI(e.id,n);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function tg(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 tI(e,t){if("number"==typeof t&&t<=0)return null;let a="number"==typeof t?Math.max(1,Math.min(tm,t)):tm,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 S("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{t_(i)}}async function tA(e,t,n,a){let i=JSON.stringify(n),r=G(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 S("xcrun",r,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=tn({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new m("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:ta(e)})}return{status:200,body:s}}async function tv(){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 m("COMMAND_FAILED","Failed to allocate port")))}),n.on("error",t)})}function tb(e,t,a,i){t&&n.appendFile(t,e,()=>{}),a&&n.appendFile(a,e,()=>{}),i&&process.stderr.write(e)}function t_(e){try{n.existsSync(e)&&n.unlinkSync(e)}catch{}}let tS=new d;async function tN(e,t,n){let a=tS.getStore()??[];if(a.some(n=>n.locks===e&&n.key===t))return await n();let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(()=>tS.run([...a,{locks:e,key:t}],n));return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}let tx=new Set(["RUNNER_PRODUCT_MISSING","RUNNER_PRODUCT_REPAIR_FAILED"]);async function tE(e,t,a){if("macos"!==e.platform)return;if(0===t.length)throw new m("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 m("COMMAND_FAILED","Missing macOS runner product",{reason:"RUNNER_PRODUCT_MISSING",productPath:e,xctestrunPath:a});for(let e of i)if(0!==_("codesign",["--verify","--deep","--strict",e],{allowFailure:!0}).exitCode){await S("codesign",["--remove-signature",e],{allowFailure:!0});try{await S("codesign",["--force","--sign","-",e])}catch(n){let t=n instanceof m?n:new m("COMMAND_FAILED",String(n));throw new m("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 tD=null;function tM(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:tO(i)??tO(a["#text"]),children:e(i)});return n}((tD??=new c({ignoreAttributes:!1,attributeNamePrefix:"",preserveOrder:!0,trimValues:!0,parseTagValue:!1})).parse(e))}function tC(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)}tC(n.children,t)}}function tO(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 tT="XCTestDevices",tL=".agent-device-backup",tk=".agent-device-xctestdevices-backup-",tR=s.join(r.homedir(),".agent-device","ios-runner"),tP=new Set(["ProductPaths","DependentProductPaths","TestHostPath","TestBundlePath","UITargetAppPath"]),tF=new Map,t$=new Set;function tU(e){return e?.trim()??""}function tG(e=process.env){return tU(e.AGENT_DEVICE_IOS_BUNDLE_ID)||tU(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function tV(e=process.env){let t=tU(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${tG(e)}.uitests`}let tB=function(e=process.env){let t=tG(e),n=tV(e);return Array.from(new Set([tU(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${n}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);function tj(e=r.homedir()){return s.join(e,"Library","Developer","XCTestDevices")}async function tq(e,t={}){if("ios"!==e.platform||"simulator"!==e.kind)return null;let a=L(e.simulatorSetPath);if(!a)return null;let i=s.resolve(a),o=s.resolve(t.xctestDeviceSetPath??tj()),l=s.resolve(t.backupPath??function(e=tj()){return`${e}${tL}`}(o)),d=s.resolve(t.lockDirPath??function(e=r.homedir()){return s.join(e,".agent-device","xctest-device-set.lock")}()),u=t.ownerStartTime??B(process.pid),c=await tK({lockDirPath:d,owner:{pid:t.ownerPid??process.pid,startTime:u,acquiredAtMs:t.nowMs??Date.now()}});try{if(tW({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,`${tT}.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)&&tH(r),e}}({requestedSetPath:i,xctestDeviceSetPath:o})}catch(e){throw tW({xctestDeviceSetPath:o,backupPath:l}),await c(),new m("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{tW({xctestDeviceSetPath:o,backupPath:l})}finally{await c()}}}}}function tW(e){let{xctestDeviceSetPath:t,backupPath:a}=e,i=[a,...function(e){let t=s.dirname(e),a=s.basename(e).replace(tL,""),i=a===tT?tk:`${a}${tk}`;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&&tH(t),n.existsSync(t))if(!o)return void I({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&&(I({level:"warn",phase:"ios_runner_xctest_device_set_orphaned_symlink",data:{xctestDeviceSetPath:t}}),tH(t))}function tH(e){!n.existsSync(e)||n.lstatSync(e).isSymbolicLink()&&n.unlinkSync(e)}async function tK(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)&&V(r.pid)&&(!r.startTime||B(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 new Promise(e=>setTimeout(e,100))}throw new m("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(tR,"derived","macos"):"simulator"===a.kind?s.join(tR,"derived"):s.join(tR,"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 tN(tF,r,async()=>{eH(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)&&(t8("clean","forced_clean",{derived:r}),t5(r),tJ(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=>tY(t,e),xctestrunReferencesProjectRoot:tQ,resolveExistingXctestrunProductPaths:t6});if("reuse_ready"!==a.reason&&t8("rebuild",a.reason,{derived:r,xctestrunPath:a.xctestrunPath}),"reuse_ready"===a.reason)try{return await tE(e,a.productPaths,a.xctestrunPath),t8("reuse","reuse_ready",{derived:r,xctestrunPath:a.xctestrunPath}),a.xctestrunPath}catch(e){if(!function(e){if(!(e instanceof m))return!1;let t=e.details&&"object"==typeof e.details?e.details.reason:void 0;return"string"==typeof t&&tx.has(t)}(e))throw e;t8("rebuild","repair_failed",{derived:r,xctestrunPath:a.xctestrunPath})}a.xctestrunPath&&(t5(r),tJ(r));let i=s.join(o,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!n.existsSync(i))throw new m("COMMAND_FAILED","iOS runner project not found",{projectPath:i});await t1(e,i,r,t);let l=tY(r,e);if(!l)throw new m("COMMAND_FAILED","Failed to locate .xctestrun after build");let d=t6(l);if(!d)throw new m("COMMAND_FAILED","Runner build is missing expected products",{xctestrunPath:l});return await tE(e,d,l),t8("build","built_new",{derived:r,xctestrunPath:l}),l})}function tJ(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,tX.has(t)&&n.rmSync(s.join(e,a.name),{recursive:!0,force:!0})}}catch{}}let tX=new Set(["Build","BuildCache.noindex","Index.noindex","Logs","ModuleCache.noindex","SDKStatCaches.noindex","SourcePackages","TextBasedInstallAPI","info.plist"]);function tY(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=tZ(n.path,t)-tZ(e.path,t);if(0!==a)return a}return n.mtimeMs-e.mtimeMs||e.path.localeCompare(n.path)}),a[0]?.path??null)}function tZ(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 tQ(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 t0(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 S("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==u.exitCode||!u.stdout.trim())throw new m("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:u.stderr});try{i=JSON.parse(u.stdout)}catch(t){throw new m("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&&t.TestBundlePath&&(c(t),i[e]=t);n.writeFileSync(l,JSON.stringify(i,null,2));let f=await S("plutil",["-convert","xml1","-o",d,l],{allowFailure:!0});if(0!==f.exitCode)throw new m("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:d,stderr:f.stderr});return{xctestrunPath:d,jsonPath:l}}async function t1(e,t,n,a){let i=function(e=process.env){let t=tG(e),n=tV(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 tq(e);try{var l;let s;await A("xcodebuild",["build-for-testing","-project",t,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",t4(e),"1","-destination",(l=e,s=t2(l),"macOS"===s?`platform=macOS,arch=${t3()}`:"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=>{t$.add(e),e.on("close",()=>{t$.delete(e)})},onStdoutChunk:e=>{tb(e,a.logPath,a.traceLogPath,a.verbose)},onStderrChunk:e=>{tb(e,a.logPath,a.traceLogPath,a.verbose)}})}catch(r){let e,t,n=r instanceof m?r:new m("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 m("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:n.message,details:n.details,logPath:a.logPath,hint:i})}finally{await s?.release()}}function t2(e){var t;if("ios"!==e.platform&&"macos"!==e.platform)throw new m("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 t3(){return"arm64"===process.arch?"arm64":"x86_64"}function t4(e){return"macos"===e.platform||"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}function t5(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return eH(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new m("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 t8(e,t,n){I({level:"rebuild"===e?"warn":"info",phase:"runner_xctestrun_cache",data:{action:e,reason:t,...n}})}function t6(e){let t=function(e){let t=function(e){try{let t=_("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=tM(a),t=new Set,tC(i,(e,n)=>{if(tP.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 t9=new Map,t7=new Map;async function ne(e,t){return await tN(t7,e.id,async()=>{var n;let a,i,r=t9.get(e.id);if(r){if(function(e){return!!e&&V(e)}(r.child.pid))return r;await ni(e.id,r)}await ("simulator"!==(n=e).kind?Promise.resolve():nd(n)),await nt(e);let o=await tz(e,t),s=await tv(),{xctestrunPath:l,jsonPath:d}=await t0(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),u=await tq(e);try{let t;({child:a,wait:i}=b("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",t4(e),"1","-destination-timeout",String(th),"-xctestrun",l,"-destination",(t=t2(e),"macOS"===t?`platform=macOS,arch=${t3()}`:"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=>{tb(e,t.logPath,t.traceLogPath,t.verbose)}),a.stderr?.on("data",e=>{tb(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 t9.set(e.id,c),c})}async function nt(e){if("simulator"===e.kind)for(let t of tB){let n=await S("xcrun",G(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 nn(e){let t=t9.get(e);return t?{sessionId:t.sessionId,alive:function(e){return!!e&&V(e)}(t.child.pid)}:null}async function na(e){await tN(t7,e.deviceId,async()=>{await ni(e.deviceId,e)})}async function ni(e,t){let n=t??t9.get(e);if(n){try{await tw(n.device,n.port,{command:"shutdown"},void 0,15e3)}catch{await nl(n.child.pid,"SIGTERM")}try{await Promise.race([n.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await nl(n.child.pid,"SIGKILL"),t_(n.xctestrunPath),t_(n.jsonPath),await n.simulatorSetRedirect?.release(),t9.get(e)===n&&t9.delete(e)}}async function nr(e){await tN(t7,e,async()=>{await ni(e)})}async function no(){let e=Array.from(t9.values()),t=Array.from(t$);await Promise.allSettled(e.map(async e=>{await nl(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await nl(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await nl(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await nl(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await nl(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await nl(e.pid,"SIGKILL"),t$.delete(e)})),await Promise.allSettled(e.map(async e=>{await e.simulatorSetRedirect?.release()}))}async function ns(){await no();let e=Array.from(t9.keys());await Promise.allSettled(e.map(async e=>{await nr(e)}));let t=Array.from(t$);await Promise.allSettled(t.map(async e=>{try{await nl(e.pid,"SIGTERM"),await nl(e.pid,"SIGKILL")}finally{t$.delete(e)}}))}async function nl(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 S("pkill",[`-${n}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function nd(e){await S("xcrun",G(e,["bootstatus",e.id,"-b"]),{timeoutMs:tl})}async function nu(e,t,n,a,i,r){let o=await tw(e,t.port,n,a,i,t,r);return await nc(o,t,a)}async function nc(e,t,n){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new m("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new m("string"==typeof i.error?.code&&i.error.code.trim().length>0?i.error.code:"COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:n});return t.ready=!0,i.data??{}}async function np(e,t,n={}){var a;if("ios"!==e.platform&&"macos"!==e.platform)throw new m("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new m("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(ts(n.requestId),"interactionFrame"===(a=t.command)||"snapshot"===a||"screenshot"===a||"findText"===a||"readText"===a||"alert"===a||"uptime"===a)?eZ(()=>(ts(n.requestId),nf(e,t,n)),{shouldRetry:e=>{ts(n.requestId);if(!(e instanceof m)||"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"))}}):nf(e,t,n)}async function nf(e,t,n={}){let a;ts(n.requestId);let i=e7(n.requestId);try{let r=(a=await ne(e,n)).ready?td:tl;return await nu(e,a,t,n.logPath,r,i)}catch(o){let r=o instanceof m?o:new m("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===r.code&&"string"==typeof r.message&&r.message.includes("Runner did not accept connection")&&ti(r)&&a?.ready){ts(n.requestId),a?await na(a):await nr(e.id),a=await ne(e,n);let r=await tw(a.device,a.port,t,n.logPath,tl,void 0,i);return await nc(r,a,n.logPath)}throw o}}function nm(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 nh(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 nw=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function ny(e){return`${e.stdout}
8
+ ${e.stderr}`}function ng(e,t){return["-s",e,...t]}function nI(e){return e.startsWith("emulator-")}function nA(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function nv(e,t=eJ){return S("adb",ng(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function nb(e,t){let n=t.replace(/_/g," ").trim();if(!nI(e))return n||e;let a=await nS(e);return a?a.replace(/_/g," "):n||e}async function n_(e,t,n){try{return await n("adb",ng(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 nS(e,t=S){for(let n of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let a=await n_(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 n_(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 nN(e,t){let n=ny(await S("adb",ng(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:eJ})).toLowerCase();return!!n.includes("true")||!n.includes("false")&&null}async function nx(e){return(await Promise.all(nw.map(async t=>await nN(e,t)))).some(e=>!0===e)}async function nE(e){var t;let n;return"tv"===((n=ny(await S("adb",ng(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:eJ})).toLowerCase()).includes("tv")||n.includes("leanback")?"tv":null)||await nx(e)?"tv":(t=ny(await S("adb",ng(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:eJ})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function nD(e={}){if(await j(),!await x("adb"))throw new m("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??$(void 0),n=(await nM()).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([nb(e,t),nL(e),nE(e)]);return{platform:"android",id:e,name:n,kind:nI(e)?"emulator":"device",target:i,booted:a}}))}async function nM(){return(await S("adb",["devices","-l"],{timeoutMs:eJ})).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 nC(){let e=await S("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:eJ});if(0!==e.exitCode)throw new m("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 nO(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await nT(e.avdName,e.serial);if(t)return{platform:"android",id:t,name:e.avdName,kind:"emulator",target:"mobile",booted:!1}}catch{}await new Promise(e=>setTimeout(e,1e3))}throw new m("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 nT(e,t){let n=nA(e);for(let e of(await nM()).filter(e=>(!t||e.serial===t)&&nI(e.serial)))if(nA(e.rawModel)===n||nA(await nb(e.serial,e.rawModel))===n)return e.serial}async function nL(e){try{let t=await nv(e);return"1"===t.stdout.trim()}catch{return!1}}async function nk(e){var t,n;let a;await j();let i=e.avdName.trim();if(!i)throw new m("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let r=e.timeoutMs??12e4;if(!await x("adb"))throw new m("TOOL_MISSING","adb not found in PATH");if(!await x("emulator"))throw new m("TOOL_MISSING","emulator not found in PATH");let o=await nC(),s=function(e,t){let n=e.find(e=>e===t);if(n)return n;let a=nA(t);return e.find(e=>nA(e)===a)}(o,i);if(!s)throw new m("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 nD(),n=e.serial,a=nA(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!n||e.id===n)&&nA(e.name)===a));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),v("emulator",t)}let u=d??await nO({avdName:s,serial:e.serial,timeoutMs:r}),c=Math.max(1e3,r-(Date.now()-l));await nR(u.id,c);let p=(await nD()).find(e=>e.id===u.id);return p?{...p,name:s,booted:!0}:{...u,name:s,booted:!0}}async function nR(e,t=6e4){let n,a=eX.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),r=!1;try{await eY(async({deadline:i})=>{if(i?.isExpired())throw r=!0,new m("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 nv(e,Math.min(o,eJ));if(n=s,"1"!==s.stdout.trim())throw new m("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=tn({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=>tn({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=tn({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:ta(d),stdout:o,stderr:s,exitCode:l};if(r||"ANDROID_BOOT_TIMEOUT"===d)throw new m("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new m("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new m("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new m(i.code,i.message,{...u,...i.details??{}},i.cause)}}async function nP(e,t){let n="url"===e.kind&&M(e.url),a=await C({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 nF(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:i.packageName,cleanup:a.cleanup}}async function nF(e){let t=s.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await q(e)}}let n$={settings:{type:"intent",value:"android.settings.SETTINGS"}},nU="android.intent.category.LAUNCHER",nG="android.intent.category.LEANBACK_LAUNCHER",nV="android.intent.category.DEFAULT",nB="Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.";async function nj(e,t){let n=t.trim();if("package"===R(n))return{type:"package",value:n};let a=n$[n.toLowerCase()];if(a)return a;let i=(await S("adb",P(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 m("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 m("APP_NOT_INSTALLED",`No package found matching "${t}"`,{hint:nB})}async function nq(e,t="all"){let n=await nW(e);return("user-installed"===t?(await nK(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:nz(e)}))}async function nW(e){let t=new Set;for(let n of nH(e,{includeFallbackWhenUnknown:!0})){let a=await S("adb",P(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 nH(e,t={}){return"tv"===e.target?[nG]:"mobile"===e.target?[nU]:t.includeFallbackWhenUnknown?[nU,nG]:[nU]}async function nK(e){return K((await S("adb",P(e,["shell","pm","list","packages","-3"]))).stdout)}function nz(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 nJ(e){let t=await nX(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let n=await nX(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return n||{}}async function nX(e,t){for(let n of t){let t=W((await S("adb",P(e,n),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function nY(e,t,n){var a,i;let r;e.booted||await nR(e.id);let o=t.trim();if(nm(o)){if(n)throw new m("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await S("adb",P(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",o]));return}let s=await nj(e,t),l=nH(e)[0]??nU;if("intent"===s.type){if(n)throw new m("INVALID_ARGS","Activity override requires a package name, not an intent");await S("adb",P(e,["shell","am","start","-W","-a",s.value]));return}if(n){let t=n.includes("/")?n:`${s.value}/${n.startsWith(".")?n:`.${n}`}`;try{await S("adb",P(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nV,"-c",l,"-n",t]))}catch(t){throw await n0(e,s.value,t),t}return}let d=await S("adb",P(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nV,"-c",l,"-p",s.value]),{allowFailure:!0});if(0===d.exitCode&&(a=d.stdout,i=d.stderr,r=`${a}
9
+ ${i}`,!/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)))return;let u=await n2(e,s.value);if(!u){if(!await nQ(e,s.value))throw nZ(s.value);throw new m("COMMAND_FAILED",`Failed to launch ${s.value}`,{stdout:d.stdout,stderr:d.stderr})}await S("adb",P(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",nV,"-c",l,"-n",u]))}function nZ(e){return new m("APP_NOT_INSTALLED",`No package found matching "${e}"`,{package:e,hint:nB})}async function nQ(e,t){let n=await S("adb",P(e,["shell","pm","path",t]),{allowFailure:!0}),a=`${n.stdout}
10
+ ${n.stderr}`;return!!(0===n.exitCode&&/\bpackage:/i.test(a))||(n1(a),!1)}async function n0(e,t,n){if(n1(n instanceof m?`${String(n.details?.stdout??"")}
11
+ ${String(n.details?.stderr??"")}`:"")||!await nQ(e,t))throw nZ(t)}function n1(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 n2(e,t){for(let n of Array.from(new Set(nH(e,{includeFallbackWhenUnknown:!0})))){let a=await S("adb",P(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 n3(e){e.booted||await nR(e.id)}async function n4(e,t){if("settings"===t.trim().toLowerCase())return void await S("adb",P(e,["shell","am","force-stop","com.android.settings"]));let n=await nj(e,t);if("intent"===n.type)throw new m("INVALID_ARGS","Close requires a package name, not an intent");await S("adb",P(e,["shell","am","force-stop",n.value]))}async function n5(e,t){let n=await nj(e,t);if("intent"===n.type)throw new m("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await S("adb",P(e,["uninstall",n.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
12
+ ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new m("COMMAND_FAILED",`adb uninstall failed for ${n.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:n.value}}let n8=null;async function n6(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(n8?.key===e)return n8.invocation;if(await x("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return n8={key:e,invocation:t},t}let t=await N(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,"AGENT_DEVICE_BUNDLETOOL_JAR");if(!t)throw new m("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 n8={key:e,invocation:n},n}async function n9(e){let t=await n6();await S(t.cmd,[...t.prefixArgs,...e])}async function n7(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 n9(["build-apks","--bundle",t,"--output",o,"--mode",l]),await n9(["install-apks","--apks",o,"--device-id",e.id])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function ae(e,t){".aab"===s.extname(t).toLowerCase()?await n7(e,t):await S("adb",P(e,["install","-r",t]))}async function at(e){return new Set((await S("adb",P(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function an(e,t){let n=Array.from(await at(e)).filter(e=>!t.has(e));if(1===n.length)return n[0]}async function aa(e,t){e.booted||await nR(e.id),await ae(e,t)}async function ai(e,t,n){let a=n?void 0:await at(e);return await aa(e,t),n??(a?await an(e,a):void 0)}async function ar(e,t){e.booted||await nR(e.id);let n=await nP({kind:"path",path:t});try{let t=await ai(e,n.installablePath,n.packageName),a=t?nz(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await n.cleanup()}}async function ao(e,t,n){e.booted||await nR(e.id);let{package:a}=await n5(e,t),i=await nP({kind:"path",path:n},{resolveIdentity:!1});try{return await aa(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function as(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 m("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 m("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)=>{if(i.length>=t){o=!0;return}if(a>s)return;let f=!!n.raw||function(e,t,n,a,i){var r;let o,s=af(e.type),l=!!(e.label&&e.label.trim().length>0),d=!!(e.identifier&&e.identifier.trim().length>0),u=l&&!am(e.label??""),c=d&&!am(e.identifier??""),p=(o=(r=s).split(".").pop()??r).includes("layout")||"viewgroup"===o||"view"===o,f="imageview"===s||"imagebutton"===s;if(t.interactiveOnly)return!!(e.hittable||ee(s)&&a)||!!(u||c)&&!f&&(!p||!!i)&&(n||a||i);return t.compact?u||c||!!e.hittable:!p&&!f||!!e.hittable||!!u||!!c&&!!a||a}(e,n,d,c(e),u),m=l;f&&(m=i.length,r.push(e),i.push({index:m,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 h=d||!!e.hittable,w=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,m,h,w),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 ad(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=au(t,e);if(null!==n)return"true"===n};return{text:au(t,"text"),desc:au(t,"content-desc"),resourceId:au(t,"resource-id"),className:au(t,"class"),bounds:au(t,"bounds"),clickable:n("clickable"),enabled:n("enabled"),focusable:n("focusable"),focused:n("focused")}}function au(e,t){return e.get(t)??null}function ac(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=ad(t),o=ac(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 am(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}function ah(e){if(0===e.length)return null;let t=[...e].sort((e,t)=>e-t);return t[Math.floor(t.length/2)]??null}function aw(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 ay(e,t){return{start:e.y-t.y,size:e.height,crossSize:e.width}}async function ag(e,t={}){let n=await aA(e);if(!t.interactiveOnly){let a=function(e,t){let{sourceNodes:n,...a}=al(ap(e),800,t);return a}(n,t);return await aI(e,a.nodes),a}let a=ap(n),i=al(a,800,{...t,interactiveOnly:!1});await aI(e,i.nodes),function(e){if(0===e.length||e.some(e=>e.hiddenContentAbove||e.hiddenContentBelow))return;let t=new Map(z(ei(e)).nodes.filter(e=>e.hiddenContentAbove||e.hiddenContentBelow).map(e=>[e.index,e]));for(let n of e){let e=t.get(n.index);e&&(e.hiddenContentAbove&&(n.hiddenContentAbove=!0),e.hiddenContentBelow&&(n.hiddenContentBelow=!0))}}(i.nodes),function(e){for(let[t,n]of e.sourceNodes.entries()){let a=e.nodes[t];a&&(a.hiddenContentAbove&&(n.hiddenContentAbove=!0),a.hiddenContentBelow&&(n.hiddenContentBelow=!0))}}(i);let{sourceNodes:r,...o}=al(a,800,t);return o}async function aI(e,t){if(!t.some(e=>ee(e.type)))return;let n=await aS(e);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;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=>ay(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)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 i=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=>ay(e,t.rect))}(e,t),r=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=ah(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(!aw(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(!aw(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?ah(o):r.length>0?ah(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:i,nativeScrollView:n});r&&(r.above&&(t.hiddenContentAbove=!0),r.below&&(t.hiddenContentBelow=!0))}}(t,n)}async function aA(e){return eZ(()=>av(e),{shouldRetry:a_})}async function av(e){var t,n,a;let i,r,o=await S("adb",P(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0}),s=ab(o.stdout,o.stderr);if(s)return s;let l="/sdcard/window_dump.xml",d=await S("adb",P(e,["shell","uiautomator","dump",l]),{allowFailure:!0}),u=(t=l,n=d.stdout,a=d.stderr,i=`${n}
13
+ ${a}`,r=/dumped to:\s*(\S+)/i.exec(i),r?.[1]??t),c=await S("adb",P(e,["shell","cat",u])),p=ab(c.stdout,c.stderr);if(!p)throw new m("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:c.stdout,stderr:c.stderr});return p}function ab(e,t){let n=`${e}
14
+ ${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 a_(e){if(!(e instanceof m)||"COMMAND_FAILED"!==e.code)return!1;let t=`${e.details?.stderr??""}`.toLowerCase();return!!(t.includes("device offline")||t.includes("device not found")||t.includes("transport error")||t.includes("connection reset")||t.includes("broken pipe")||t.includes("timed out")||t.includes("no such file or directory"))}async function aS(e){try{let t=await S("adb",P(e,["shell","dumpsys","activity","top"]),{allowFailure:!0,timeoutMs:8e3}),n=`${t.stdout}
15
+ ${t.stderr}`.trim();return n.length>0?n:null}catch{return null}}async function aN(e,t,n){await S("adb",P(e,["shell","input","tap",String(t),String(n)]))}async function ax(e,t,n,a,i,r=250){await S("adb",P(e,["shell","input","swipe",String(t),String(n),String(a),String(i),String(r)]))}async function aE(e){await S("adb",P(e,["shell","input","keyevent","4"]))}async function aD(e){await S("adb",P(e,["shell","input","keyevent","3"]))}async function aM(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 m("INVALID_ARGS",`Unsupported Android rotation: ${e}`)}}(t);await S("adb",P(e,["shell","settings","put","system","accelerometer_rotation","0"])),await S("adb",P(e,["shell","settings","put","system","user_rotation",n]))}async function aC(e){await S("adb",P(e,["shell","input","keyevent","187"]))}async function aO(e,t,n,a=800){await S("adb",P(e,["shell","input","swipe",String(t),String(n),String(t),String(n),String(a)]))}async function aT(e,t,n=0){n>0&&Array.from(t).length>1?await aG(e,t,1,n):await aL(e,t)}async function aL(e,t){let n=aV(t);if(!n||"ok"!==await aB(e,t))try{let n=t.replace(/ /g,"%s");await S("adb",P(e,["shell","input","text",n]))}catch(e){if(n&&function(e){if(!(e instanceof m)||"COMMAND_FAILED"!==e.code)return!1;let t=String(e.details?.stderr??"").toLowerCase();return!!(t.includes("exception occurred while executing 'text'")||t.includes("nullpointerexception")&&t.includes("inputshellcommand.sendtext"))}(e))throw new m("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 ak(e,t,n){await aN(e,t,n)}async function aR(e,t,n,a,i=0){let r=Array.from(a).length,o=aV(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 ak(e,t,n);let s=(d=r+o.clearPadding,u=o.minClear,Math.max(u,Math.min(o.maxClear,d)));if(await aj(e,s),"input_text"===o.strategy)await aT(e,a,i);else if("clipboard_paste"===o.strategy){if("ok"!==await aB(e,a))continue}else await aG(e,a,1,i>0?i:15);let c=await aP(e,t,n,a);if(l=c.actual,c.ok)return}throw new m("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:l??null})}async function aP(e,t,n,a){let i=null;for(let r of[0,150,350])if(r>0&&await T(r),function(e,t){if(e===t)return!0;let n=aF(e),a=aF(t);return!!n&&!!a&&(!!(n===a||n.includes(a))||a.includes(n)&&n.length>=Math.max(4,Math.floor(.8*a.length)))}(i=await aq(e,t,n),a))return{ok:!0,actual:i};return{ok:!1,actual:i}}function aF(e){return(e??"").replace(/\s+/g," ").trim()}async function a$(e,t,n){let a=await aU(e),i=as({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:a.width,referenceHeight:a.height});return await S("adb",P(e,["shell","input","swipe",String(i.x1),String(i.y1),String(i.x2),String(i.y2),"300"])),i}async function aU(e){let t=(await S("adb",P(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new m("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function aG(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 aL(e,n),a>0&&t+i<r.length&&await T(a)}}function aV(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 aB(e,t){let n=await S("adb",P(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==n.exitCode?"failed":U(n.stdout,n.stderr)?"unsupported":0===(await S("adb",P(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await S("adb",P(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function aj(e,t){let n=Math.max(0,t);await S("adb",P(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 S("adb",P(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function aq(e,t,n){let a,i=await aA(e),r=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=r.exec(i));){let e=ad(a[0]),i=ac(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&&aW(r)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&aW(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 aW(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function aH(e){let t=await S("adb",P(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new m("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 aK(e){let t=await aH(e),n=t,a=0;for(;n.visible&&a<2;)await S("adb",P(e,["shell","input","keyevent","111"])),a+=1,await T(120),n=await aH(e);if(t.visible&&n.visible)throw new m("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 az(e){let t,n;return(n=(t=(await aX(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 aJ(e,t){await aX(e,["shell","cmd","clipboard","set","text",t],"write")}async function aX(e,t,n){let a=await S("adb",P(e,t),{allowFailure:!0});if(U(a.stdout,a.stderr))throw new m("UNSUPPORTED_OPERATION",`Android shell clipboard ${n} is not supported on this device.`);if(0!==a.exitCode)throw new m("COMMAND_FAILED",`Failed to ${n} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let aY=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function aZ(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new m("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function aQ(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 m("INVALID_ARGS",`permission setting requires a target: ${aY.join("|")}`)}function a0(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new m("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function a1(e,t,n,a,i){switch(t.toLowerCase()){case"wifi":{let t=a3(n);await S("adb",P(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=a3(n);await S("adb",P(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await S("adb",P(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=a3(n);await S("adb",P(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await a4(e,n);await S("adb",P(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 m("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(n);await a2(e,t);return}case"permission":{if(!a)throw new m("INVALID_ARGS","permission setting requires an active app in session");let t=aZ(n),r=function(e,t){let n=aQ(e);if(t?.trim())throw new m("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 m("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 a8(e,a,t,r);let o="grant"===t?"grant":"revoke";if("photos"===r.type)return void await a5(e,a,o);await S("adb",P(e,["shell","pm",o,a,r.value]));return}default:throw new m("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function a2(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 S("adb",P(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}
16
+ ${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 m("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 m("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function a3(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 m("INVALID_ARGS",`Invalid setting state: ${e}`)}async function a4(e,t){let n=a0(t);if("toggle"!==n)return n;let a=await S("adb",P(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new m("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}
17
+ ${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 m("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 a5(e,t,n){let a=await a6(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 S("adb",P(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 m("COMMAND_FAILED",`Failed to ${n} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function a8(e,t,n,a){"grant"===n?await S("adb",P(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await S("adb",P(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===n&&(await S("adb",P(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await S("adb",P(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await S("adb",P(e,["shell","appops","set",t,a.appOps,"grant"===n?"allow":"deny"===n?"deny":"default"]))}async function a6(e){let t=await S("adb",P(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 a9(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 m("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 m("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await S("adb",P(e,i)),{action:a,extrasCount:s}}let a7=Buffer.from([137,80,78,71,13,10,26,10]);async function ie(e,t){await it(e);try{await T(1e3),await ii(e,t)}finally{await ia(e).catch(()=>{})}}async function it(e){let t=t=>S("adb",P(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 ia(e){await S("adb",P(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function ii(e,t){let n=await S("adb",P(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!n.stdoutBuffer)throw new m("COMMAND_FAILED","Failed to capture screenshot");let a=n.stdoutBuffer.indexOf(a7);if(a<0)throw new m("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let r=function(e,t){let n=t+a7.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 m("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await i.writeFile(t,n.stdoutBuffer.subarray(a,r))}let ir=D(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,ez,5e3),io=D(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,eK,1e3),is=D(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),il=D(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),id=D(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),iu=D(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),ic=D(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3),ip=eH(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_RUNNER_FALLBACK);async function im(e,t){let n=["devicectl",...e],a=await S("xcrun",n,{allowFailure:!0,timeoutMs:il});if(0===a.exitCode)return;let i=String(a.stdout??""),r=String(a.stderr??"");throw new m("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:t.deviceId,hint:ig(i,r)??iy})}async function ih(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 S("xcrun",a,{allowFailure:!0,timeoutMs:il});try{var l,d;if(0!==o.exitCode){let t=String(o.stdout??""),n=String(o.stderr??"");throw new m("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:o.exitCode,stdout:t,stderr:n,deviceId:e.id,hint:ig(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 m)throw t;throw new m("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await i.unlink(n).catch(()=>{})}}async function iw(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 S("xcrun",n,{allowFailure:!0,timeoutMs:il});try{if(0!==a.exitCode){let t=String(a.stdout??""),i=String(a.stderr??"");throw new m("COMMAND_FAILED","Failed to list iOS processes",{cmd:"xcrun",args:n,exitCode:a.exitCode,stdout:t,stderr:i,deviceId:e.id,hint:ig(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 m)throw t;throw new m("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 ig(e,t){let n=`${e}
18
+ ${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 iI(e){if(!(e instanceof m)||"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 iA(e,t){let n=await S("xcrun",G(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 S("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 S("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 iv(e,t){if("simulator"!==e.kind)throw new m("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function ib(){await S("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:id})}async function i_(e){let t,n;if("simulator"!==e.kind||"Booted"===await iN(e))return;let a=eX.fromTimeoutMs(ir);try{await eY(async({deadline:a})=>{if(a?.isExpired())throw new m("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:ir});let i=Math.max(1e3,a?.remainingMs()??ir),r=await S("xcrun",G(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(r.stdout??""),stderr:String(r.stderr??""),exitCode:r.exitCode};let o=`${t.stdout}
19
+ ${t.stderr}`.toLowerCase(),s=o.includes("already booted")||o.includes("current state: booted");if(0!==t.exitCode&&!s)throw new m("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await S("xcrun",G(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 m("COMMAND_FAILED","simctl bootstatus failed",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode});let d=await iN(e);if("Booted"!==d)throw new m("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=tn({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=>tn({error:e,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(r){let i=tn({error:r,stdout:n?.stdout??t?.stdout,stderr:n?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new m("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:ir,elapsedMs:a.elapsedMs(),reason:i,hint:ta(i),boot:t,bootstatus:n})}await ib()}async function iS(e){let t=G(e,["shutdown",e.id]),n=await S("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===n.exitCode,exitCode:n.exitCode,stdout:String(n.stdout??""),stderr:String(n.stderr??"")}}async function iN(e){let t="string"==typeof e?e:e.id,n="string"==typeof e?k(["list","devices","-j"]):G(e,["list","devices","-j"]),a=await S("xcrun",n,{allowFailure:!0,timeoutMs:io});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 ix(e,t){try{let n=await S("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,tC(tM(n),(e,t)=>{void 0===r&&e===a&&"string"===t.name&&(r=t.text??void 0)}),r}catch{return}}async function iE(e,t){if("url"===e.kind&&!M(e.url))throw new m("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 C({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||M(e.url),signal:t?.signal}),a=await iM(n.installablePath,t),i=await iD(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 iD(e){let t=s.join(e,"Info.plist"),[n,a,i]=await Promise.all([ix(t,"CFBundleIdentifier"),ix(t,"CFBundleDisplayName"),ix(t,"CFBundleName")]);return{bundleId:n,appName:a??i}}async function iM(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 S("unzip",["-q",e,"-d",n]);let r=s.join(n,"Payload"),o=(await i.readdir(r,{withFileTypes:!0}).catch(()=>{throw new m("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 m("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await iC(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 m("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 m("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload and none matched "${l}". Available bundles: ${o.map(iO).join(", ")}`)}throw new m("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${o.map(iO).join(", ")}`)}catch(e){throw await a(),e}}async function iC(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await iD(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function iO(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function iT(e,t){return"user-installed"===t?e.filter(e=>!e.bundleId.startsWith("com.apple.")):e}let iL="agent-device-macos-helper",ik="AGENT_DEVICE_MACOS_HELPER_BIN",iR=s.join(r.homedir(),".agent-device","macos-helper","current"),iP=s.join(iR,"manifest.json"),iF=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)+$/;function i$(e){let t=e.trim();if(!iF.test(t))throw new m("INVALID_ARGS","macOS bundle id must use reverse-DNS form like com.example.App",{bundleId:e});return t}function iU(){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 m("COMMAND_FAILED","Unable to locate macOS helper package root",{modulePath:e})}(u(import.meta.url))}async function iG(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 iG(n):t.isFile()&&(t.name.endsWith(".swift")||"Package.swift"===t.name)?[n]:[]}))).flat().sort()}async function iV(e){let t=await iG(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 S("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 iB(){try{let e=JSON.parse(await i.readFile(iP,"utf8"));return"string"==typeof e.fingerprint?e.fingerprint:null}catch{return null}}async function ij(){let e=await E(process.env[ik],ik);if(e)return e;let t=iU(),n=await iV(t),a=s.join(iR,iL);try{if(await iB()===n)return await i.access(a),a}catch{}let r=s.join(iU(),".build","release",iL);process.stderr.write("agent-device: building macOS helper (first run or helper update)\n"),await S("swift",["build","-c","release","--package-path",t],{cwd:t,timeoutMs:12e4}),await i.mkdir(iR,{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(iP,`${JSON.stringify({fingerprint:n},null,2)}
20
+ `,"utf8"),a}async function iq(e){let t=process.env[ik]?.trim();if("darwin"!==process.platform&&!t)throw new m("UNSUPPORTED_PLATFORM","macOS helper is only available on macOS");let n=await ij(),a=await S(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 m("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 iW(){return await iq(["app","frontmost"])}async function iH(e){return await iq(["app","quit","--bundle-id",i$(e)])}async function iK(e,t){return await iq(["permission",e,t])}async function iz(e,t={}){let n=["alert",e];return t.bundleId&&n.push("--bundle-id",i$(t.bundleId)),t.surface&&n.push("--surface",t.surface),await iq(n)}async function iJ(e,t={}){let n=["snapshot","--surface",e];return t.bundleId&&n.push("--bundle-id",i$(t.bundleId)),await iq(n)}async function iX(e,t,n={}){let a=["read","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",i$(n.bundleId)),n.surface&&a.push("--surface",n.surface),await iq(a)}async function iY(e,t,n={}){let a=["press","--x",String(e),"--y",String(t)];return n.bundleId&&a.push("--bundle-id",i$(n.bundleId)),n.surface&&a.push("--surface",n.surface),await iq(a)}async function iZ(e,t={}){let n=["screenshot","--out",e];return t.surface&&n.push("--surface",t.surface),t.fullscreen&&n.push("--fullscreen"),await iq(n)}let iQ={settings:"com.apple.systempreferences"},i0=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;function i1(e,t){let n=["-b",e];return t&&n.push(t),n}async function i2(e){for(let t of[s.join(e,"Contents","Info.plist"),s.join(e,"Info.plist")]){let[e,n,a]=await Promise.all([ix(t,"CFBundleIdentifier"),ix(t,"CFBundleDisplayName"),ix(t,"CFBundleName")]);if(e||n||a)return{bundleId:e,appName:n??a}}return{}}async function i3(e){let t=e.trim(),n=iQ[t.toLowerCase()];if(n)return n;if(i0.test(t))return t;let a=(await re("all")).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new m("INVALID_ARGS",`Multiple apps matched "${e}"`,{matches:a});throw new m("APP_NOT_INSTALLED",`No app found matching "${e}"`)}async function i4(e,t,n){let a=n?.url?.trim();if(a){if(!nm(a))throw new m("INVALID_ARGS","open <app> <url> requires a valid URL target");let e=n?.appBundleId??await i3(t);await S("open",i1(e,a));return}let i=t.trim();if(nm(i))return void await S("open",[i]);let r=n?.appBundleId??await i3(i);await S("open",i1(r))}async function i5(e,t){let n=await i3(t),a=await iH(n);if(a.running&&!a.terminated&&!a.forceTerminated)throw new m("COMMAND_FAILED",`Failed to close macOS app ${t}`,{bundleId:n,running:a.running,terminated:a.terminated,forceTerminated:a.forceTerminated})}async function i8(){let e=await S("pbpaste",[],{allowFailure:!0});if(0!==e.exitCode)throw new m("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 i6(e){let t=await S("pbcopy",[],{allowFailure:!0,stdin:e});if(0!==t.exitCode)throw new m("COMMAND_FAILED","Failed to write macOS clipboard",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode})}async function i9(){let e=await S("osascript",["-e",'tell application "System Events" to tell appearance preferences to get dark mode'],{allowFailure:!0});if(0!==e.exitCode)throw new m("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 m("COMMAND_FAILED",`Unable to determine current macOS appearance from osascript output: ${e.stdout.trim()}`)}async function i7(e){let t=a0(e),n="toggle"===t?!await i9():"dark"===t,a=`tell application "System Events" to tell appearance preferences to set dark mode to ${n?"true":"false"}`,i=await S("osascript",["-e",a],{allowFailure:!0});if(0!==i.exitCode)throw new m("COMMAND_FAILED","Failed to set macOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}async function re(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 S("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 iT((await Promise.all(Array.from(n).map(async e=>{let t=await i2(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 rt=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],rn={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"},ra={1:"searching",2:"failed",3:"active"},ri={0:"notSupported",1:"searching",2:"failed",3:"active"};function rr(e,t,n){return S("xcrun",G(e,t),n)}async function ro(e,t){var n,a;let i;await rl(e),t&&await rd(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 rs(e){let t=await rr(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new m("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=rn[n];if(!a)throw new m("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=ra[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=ri[e];if(!n)throw new m("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 rl(e){await rr(e,["status_bar",e.id,"clear"])}async function rd(e,t){0!==t.length&&await rr(e,["status_bar",e.id,"override",...t])}function ru(e,t,n){I({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof m))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 rc(e,t,n){return S("xcrun",G(e,t),n)}let rp={ensureBooted:i_,prepareStatusBarForScreenshot:async function e(e){let t=null,n=!1;try{t=await rs(e),n=!0}catch(t){ru(e,"snapshot_failed",t)}try{await rl(e),await rd(e,rt)}catch(t){ru(e,"prepare_failed",t)}return async()=>{await ro(e,n?t:null)}},captureWithRetry:rh,runnerFallbackEnabled:ip,captureWithRunner:rw,shouldFallbackToRunner:r_};async function rf(e,t,n,a){if("macos"===e.platform)return void await rw(e,t,n,a);if("simulator"===e.kind)return void await rm(e,t,n,a);try{await im(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof m)||"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
+ ${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;rA(e,"devicectl_screenshot",t)}await rw(e,t,n,a)}async function rm(e,t,n,a,i=rp){if("simulator"!==e.kind)throw new m("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){rv(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=rb(l),I({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 m?d:new m("COMMAND_FAILED","Failed to capture iOS screenshot: simulator screenshot retries exhausted",void 0,d),new m(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)}rA(e,"simctl_screenshot",t)}await r.captureWithRunner(e,t,n,"boolean"==typeof a?a:void 0)}finally{await o().catch(t=>rv(e,"restore_failed",t))}}async function rh(e,t){let n=eX.fromTimeoutMs(iu);await eY(async({deadline:n})=>{await rc(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,n?.remainingMs()??iu)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>r_(e)},{deadline:n,phase:"ios_simulator_screenshot"})}async function rw(e,t,n,a){let r=(await np(e,{command:"screenshot",appBundleId:n,fullscreen:a})).message;if(!r)throw new m("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"macos"===e.platform?await i.copyFile(r,t):"simulator"===e.kind?await rg(e,r,t):await ry(e,r,t)}async function ry(e,t,n){let a=eX.fromTimeoutMs(ic),i={exitCode:1,stdout:"",stderr:""};for(let r of tB)if(0===(i=await S("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",n,"--domain-type","appDataContainer","--domain-identifier",r],{allowFailure:!0,timeoutMs:rI(a,ic,"runner screenshot copy")})).exitCode)return;let r=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new m("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}async function rg(e,t,n){let a=eX.fromTimeoutMs(ic),r="Unable to locate runner container for simulator screenshot";for(let o of tB){let l=await rc(e,["get_app_container",e.id,o,"data"],{allowFailure:!0,timeoutMs:rI(a,ic,"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 m("COMMAND_FAILED",`Failed to capture iOS screenshot: ${r}`)}function rI(e,t,n){let a=e.remainingMs();if(a>0)return a;throw new m("COMMAND_FAILED",`iOS ${n} timed out after ${t}ms`,{timeoutMs:t,step:n})}function rA(e,t,n){let a=rb(n);I({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function rv(e,t,n){I({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...rb(n)}})}function rb(e){if(!(e instanceof m))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 r_(e){if(!(e instanceof m)||"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
+ ${n}
24
+ ${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 rS={settings:"com.apple.Preferences"},rN=null;function rx(e,t,n){return S("xcrun",G(e,t),n)}function rE(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function rD(e,t){if("macos"===e.platform)return await i3(t);let n=t.trim();if(n.includes("."))return n;let a=rS[n.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await rV(e):await ih(e,"all")).filter(e=>e.name.toLowerCase()===n.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new m("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new m("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function rM(e,t,n){if("macos"===e.platform)return void await i4(e,t,n);let a=n?.url?.trim();if(a){if(!nm(a))throw new m("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await i_(e),await rx(e,["openurl",e.id,a]);return}let i=nh(n?.appBundleId??await rD(e,t),a);if(!i)throw new m("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await rX(e,i,{payloadUrl:a});return}let i=t.trim();if(nm(i)){if("simulator"===e.kind){await i_(e),await rx(e,["openurl",e.id,i]);return}let t=nh(n?.appBundleId,i);if(!t)throw new m("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await rX(e,t,{payloadUrl:i});return}let r=n?.appBundleId??await rD(e,t);"simulator"===e.kind?await rJ(e,r):await rX(e,r)}async function rC(e){"macos"===e.platform||"simulator"!==e.kind||"Booted"!==await iN(e)&&await i_(e)}async function rO(e,t){if("macos"===e.platform)return void await i5(e,t);let n=await rD(e,t);if("simulator"===e.kind){await i_(e);let t=G(e,["terminate",e.id,n]),a=await S("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new m("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await im(["device","process","terminate","--device",e.id,n],{action:"terminate iOS app",deviceId:e.id})}async function rT(e,t){let n=await rD(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,n],a=await S("xcrun",t,{allowFailure:!0,timeoutMs:il});if(0!==a.exitCode){let i=String(a.stdout??""),r=String(a.stderr??"");if(!rE(`${i}
26
+ ${r}`.toLowerCase()))throw new m("COMMAND_FAILED",`Failed to uninstall iOS app ${n}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:r,deviceId:e.id,hint:ig(i,r)??iy})}return{bundleId:n}}await i_(e);let a=await rx(e,["uninstall",e.id,n],{allowFailure:!0});if(0!==a.exitCode&&!rE(`${a.stdout}
27
+ ${a.stderr}`.toLowerCase()))throw new m("COMMAND_FAILED",`simctl uninstall failed for ${n}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:n}}async function rL(e,t,n){let a=await iE({kind:"path",path:t},n);try{return await rR(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 rT(e,t);return await rL(e,n,{appIdentifierHint:t}),{bundleId:a}}async function rR(e,t){"simulator"!==e.kind?await im(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await i_(e),await rx(e,["install",e.id,t]))}async function rP(e){if("macos"===e.platform)return await i8();iv(e,"clipboard"),await i_(e);let t=await rx(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new m("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 rF(e,t){if("macos"===e.platform)return void await i6(t);iv(e,"clipboard"),await i_(e);let n=await rx(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==n.exitCode)throw new m("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}async function r$(e,t,n){iv(e,"push"),await i_(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 rx(e,["push",e.id,t,o])}finally{await i.rm(a,{recursive:!0,force:!0})}}async function rU(e,t,n,a,i){if("macos"===e.platform){let e=t.toLowerCase();if("appearance"===e)return void await i7(n);if("permission"===e){let e=aZ(n);if("deny"===e)throw new m("INVALID_ARGS",eN("permission"));let t=function(e){let t=e?.trim().toLowerCase();if("accessibility"===t||"screen-recording"===t||"input-monitoring"===t)return t;throw new m("INVALID_ARGS","Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.")}(i?.permissionTarget);return await iK(e,t)}throw new m("INVALID_ARGS",eN(t))}iv(e,"settings"),await i_(e);let r=t.toLowerCase();switch(r){case"wifi":{let t=rB(n);await rx(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(rB(n)?await rx(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await rx(e,["status_bar",e.id,"clear"]));case"location":{let t=rB(n);if(!a)throw new m("INVALID_ARGS","location setting requires an active app in session");await rx(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=rq[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 m("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(n,r);await rz(e,a,{settingName:r,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await rj(e,n);await rx(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new m("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=aZ(n))?"revoke":o,r=function(e,t){let n=aQ(e);if("photos"!==n&&t?.trim())throw new m("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 m("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new m("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 rW(e,t,r,a);return}default:throw new m("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function rG(e,t="all"){return"macos"===e.platform?await re(t):"simulator"===e.kind?iT(await rV(e),t):await ih(e,t)}async function rV(e){let t=(await rx(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 S("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 rB(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 m("INVALID_ARGS",`Invalid setting state: ${e}`)}async function rj(e,t){let n=a0(t);if("toggle"!==n)return n;let a=await rx(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new m("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 m("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let rq={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function rW(e,t,n,a){let i=await rK(e);if(!i.has(n))throw new m("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 rx(e,r);return}catch(t){if(!(o&&rH(t)))throw t;throw new m("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 rx(e,r);return}catch(e){if(!rH(e))throw e}try{await rx(e,["privacy",e.id,"reset","all",a])}catch(t){throw new m("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 rH(e){if(!(e instanceof m)||"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 rK(t){let n=L(t.simulatorSetPath),a=`${process.env.PATH??""}::${n??""}`;if(rN&&e===a)return rN;let i=await rx(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 m("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 rN=r,e=a,r}async function rz(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=G(e,t),a=await S("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 m("UNSUPPORTED_OPERATION",`${n.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r});throw new m("COMMAND_FAILED",`Failed to simulate ${n.settingName}.`,{deviceId:e.id,action:t,setting:n.settingName,attempts:r})}async function rJ(e,t){await i_(e);let n=0,a=eX.fromTimeoutMs(is);try{await eY(async({deadline:n})=>{var a;if(n?.isExpired())throw new m("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:is});let i=(a=["launch",e.id,t],G(e,a)),r=await S("xcrun",i,{allowFailure:!0});if(0!==r.exitCode)throw new m("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=>!!iI(e)&&(n+=1)<3},{deadline:a})}catch(n){if(iI(n)){var i;let a=(i=await iA(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 rX(e,t,n){let a=["device","process","launch","--device",e.id,t];n?.payloadUrl&&a.push("--payload-url",n.payloadUrl),await im(a,{action:"launch iOS app",deviceId:e.id})}async function rY(e,t,n,a,i,r,o){if("tv"===t.target)return r0(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 rZ(e,t,n,a),l=as({direction:i,amount:r?.amount,pixels:r?.pixels,referenceWidth:s.referenceWidth,referenceHeight:s.referenceHeight});return r0(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 rZ(e,t,n,a){let i=await e(t,{command:"interactionFrame",appBundleId:n.appBundleId},a),r=rQ(i.x),o=rQ(i.y),s=rQ(i.referenceWidth),l=rQ(i.referenceHeight);if(void 0===r||void 0===o||void 0===s||void 0===l)throw new m("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:r,originY:o,referenceWidth:s,referenceHeight:l}}function rQ(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function r0(e,t){var n;let{x1:a,y1:i,x2:r,y2:o}={x1:rQ((n=e).x),y1:rQ(n.y),x2:rQ(n.x2),y2:rQ(n.y2)},s=rQ(e.referenceWidth),l=rQ(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 r1(){return process.env.WAYLAND_DISPLAY||"wayland"===process.env.XDG_SESSION_TYPE?"wayland":"x11"}let r2=null;async function r3(){if(r2)return r2;let e=r1();if("wayland"===e){if(await x("ydotool"))return r2={tool:"ydotool",display:e};throw new m("TOOL_MISSING","ydotool is required for input synthesis on Wayland (xdotool does not work on Wayland). Install it via your package manager.")}if(await x("xdotool"))return r2={tool:"xdotool",display:e};throw new m("TOOL_MISSING","xdotool is required for input synthesis on X11. Install it via your package manager.")}async function r4(...e){await S("xdotool",e,{allowFailure:!1,timeoutMs:1e4})}async function r5(...e){await S("ydotool",e,{allowFailure:!1,timeoutMs:1e4})}async function r8(e,t){let{tool:n}=await r3();"xdotool"===n?await r4("mousemove","--sync",String(e),String(t)):await r5("mousemove","--absolute","-x",String(e),"-y",String(t))}async function r6(e,t){let{tool:n}=await r3();"xdotool"===n?await r4("key","--clearmodifiers",e):await r5("key",...t)}async function r9(e,t,n,a){await r8(e,t);let{tool:i}=await r3();"xdotool"===i?await r4("click",n):await r5("click",a)}async function r7(e,t){await r9(e,t,"1","0xC0")}async function oe(e,t){await r9(e,t,"3","0xC1")}async function ot(e,t){await r9(e,t,"2","0xC2")}async function on(e,t){let{tool:n}=await r3();await r8(e,t),"xdotool"===n?await r4("click","--repeat","2","1"):(await r5("click","0xC0"),await r5("click","0xC0"))}async function oa(e,t,n=800){let{tool:a}=await r3();await r8(e,t),"xdotool"===a?(await r4("mousedown","1"),await od(n),await r4("mouseup","1")):(await r5("click","--down","0xC0"),await od(n),await r5("click","--up","0xC0"))}async function oi(e,t){await r7(e,t)}async function or(e,t,n,a,i=300){let{tool:r}=await r3();await r8(e,t),"xdotool"===r?(await r4("mousedown","1"),await r4("mousemove","--sync",String(n),String(a)),await od(i),await r4("mouseup","1")):(await r5("click","--down","0xC0"),await r5("mousemove","--absolute","-x",String(n),"-y",String(a)),await od(i),await r5("click","--up","0xC0"))}async function oo(e,t){let{tool:n}=await r3(),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 r4("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 r5("mousemove","--wheel","-y",t)}else{let t="left"===e?String(-a):String(a);await r5("mousemove","--wheel","-x",t)}}async function os(e,t=0){let{tool:n}=await r3();if("xdotool"===n){let n=["type"];t>0&&n.push("--delay",String(t)),n.push("--clearmodifiers","--",e),await r4(...n)}else await r5("type","--",e)}async function ol(e,t,n,a=0){await r7(e,t),await od(100),await r6("ctrl+a",["29:1","30:1","30:0","29:0"]),await od(50),await os(n,a)}function od(e){return new Promise(t=>setTimeout(t,e))}function ou(e){let t=null;return{resolve:async function(){if(t)return t;let n="wayland"===r1()?"wayland":"x11";for(let a of"wayland"===n?e.wayland:e.x11)if(await x(a.command))return t={tool:a.tool,display:n};throw new m("TOOL_MISSING","wayland"===n?e.waylandError:e.x11Error)},resetCache:()=>{t=null}}}let oc=ou({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 op(e){let{tool:t}=await oc.resolve();switch(t){case"grim":await S("grim",[e]);break;case"scrot":await S("scrot",[e]);break;case"import":await S("import",["-window","root",e]);break;case"gnome-screenshot":await S("gnome-screenshot",["-f",e])}}async function of(e){if(e.includes("://")||e.startsWith("/"))return void await S("xdg-open",[e]);if(await x(e)){S(e,[],{allowFailure:!0}).catch(t=>{I({level:"warn",phase:"linux_app_launch",data:{app:e,error:String(t)}})}),await new Promise(e=>setTimeout(e,500));return}await S("xdg-open",[e],{allowFailure:!0})}async function om(e){await x("wmctrl")?await S("wmctrl",["-c",e],{allowFailure:!0}):await S("pkill",["-x",e],{allowFailure:!0})}async function oh(){await r6("alt+Left",["56:1","105:1","105:0","56:0"])}async function ow(){await r6("super+d",["125:1","32:1","32:0","125:0"])}let oy=ou({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 og(){let{tool:e}=await oy.resolve();switch(e){case"wl-clipboard":return(await S("wl-paste",["--no-newline"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xclip":return(await S("xclip",["-selection","clipboard","-o"],{allowFailure:!0,timeoutMs:5e3})).stdout;case"xsel":return(await S("xsel",["--clipboard","--output"],{allowFailure:!0,timeoutMs:5e3})).stdout}}async function oI(e){let{tool:t}=await oy.resolve();switch(t){case"wl-clipboard":await S("wl-copy",["--",e],{allowFailure:!1,timeoutMs:5e3});break;case"xclip":await S("xclip",["-selection","clipboard"],{allowFailure:!1,timeoutMs:5e3,stdin:e});break;case"xsel":await S("xsel",["--clipboard","--input"],{allowFailure:!1,timeoutMs:5e3,stdin:e})}}async function oA(){return"linux"!==process.platform?[]:[{platform:"linux",id:"local",name:o(),kind:"device",target:"desktop",booted:!0}]}oy.resetCache;let ov={"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"},ob="atspi-dump.py",o_=null;async function oS(e,t={}){let a;if("linux"!==process.platform)throw new m("UNSUPPORTED_PLATFORM","AT-SPI2 bridge is only available on Linux");if(!await x("python3"))throw new m("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(o_)return o_;let e=s.dirname(u(import.meta.url));for(let t=0;t<5;t++){let a=s.join(e,"src","platforms","linux",ob);if(n.existsSync(a))return o_=a,a;if(0===t){let t=s.join(e,ob);if(n.existsSync(t))return o_=t,t}e=s.dirname(e)}throw new m("TOOL_MISSING",`Cannot find ${ob}. Ensure the agent-device package is installed correctly.`)}(),"--surface",e,"--max-nodes",String(i),"--max-depth",String(r),"--max-apps",String(o)],d=await S("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 m("TOOL_MISSING","AT-SPI2 Python bindings not found. Install python3-gi and gir1.2-atspi-2.0.",{cause:e});throw new m("COMMAND_FAILED",`AT-SPI2 snapshot failed (exit ${d.exitCode}): ${e||d.stdout}`)}try{a=JSON.parse(d.stdout)}catch{throw new m("COMMAND_FAILED",`AT-SPI2 snapshot returned invalid JSON: ${d.stdout.slice(0,200)}`)}if(a.error)throw new m("COMMAND_FAILED",`AT-SPI2: ${a.error}`);return{nodes:(a.nodes??[]).map(e=>{let t,n;return{index:e.index,type:(n=ov[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 oN(e){let t="desktop"===e?"desktop":"frontmost-app"===e||"app"===e?"frontmost-app":("menubar"===e&&I({level:"warn",phase:"linux_snapshot",data:{message:"menubar surface is not supported on Linux, falling back to desktop"}}),"desktop"),n=await oS(t);return{nodes:n.nodes,truncated:n.truncated}}function ox(e){return e?.clickButton??"primary"}function oE(e){return"primary"===e.button?null:"click"!==e.commandLabel?new m("INVALID_ARGS","--button is supported only for click"):"macos"!==e.platform&&"linux"!==e.platform?new m("UNSUPPORTED_OPERATION",`click --button ${e.button} is supported only on macOS and Linux`):"macos"===e.platform&&"middle"===e.button?new m("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 m("INVALID_ARGS",`click --button ${e.button} does not support repeat or gesture modifier flags`):null}function oD(e){return"primary"===e?{}:{button:e}}let oM=/^[A-Za-z0-9_.:-]{1,64}$/,oC=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];async function oO(e,t,n){for(let a=0;a<e;a+=1)await n(a),a<e-1&&t>0&&await oT(t)}async function oT(e){await new Promise(t=>setTimeout(t,e))}function oL(e,t){let a,i=t?.subject??"Payload",r=e.trim();if(!r)throw new m("INVALID_ARGS",`${i} cannot be empty`);let o=t?.expandPath?t.expandPath(r,t.cwd):r;try{if(!n.statSync(o).isFile())throw new m("INVALID_ARGS",`${i} path is not a file: ${o}`);return{kind:"file",path:o}}catch(t){if(t instanceof m)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new m("INVALID_ARGS",`${i} file is not readable: ${o}`);if(e&&"ENOENT"!==e)throw new m("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 m("INVALID_ARGS",`${i} file not found: ${o}`)}async function ok(e){let t=oL(e,{subject:"Push payload"}),n="inline"===t.kind?t.text:await oR(t.path);try{let e=JSON.parse(n);if(!e||"object"!=typeof e||Array.isArray(e))throw new m("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof m)throw t;throw new m("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function oR(e){try{return await i.readFile(e,"utf8")}catch(n){let t=n.code;if("ENOENT"===t)throw new m("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new m("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new m("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new m("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(n)})}}function oP(e){if(void 0===e)throw new m("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 m("INVALID_ARGS",`Invalid rotation: ${e}. Use portrait|portrait-upside-down|landscape-left|landscape-right.`)}}let oF=D(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),o$=/^(iphone|ipad|ipod|appletv)/i,oU=/\b(iphone|ipad|ipod)\b/i,oG=/^appletv/i,oV=["apple tv","appletv","tvos"],oB=/^==\s*(.+?)\s*==$/,oj=/^(?<name>.+?)\s+\[(?<id>[^[\]]+)\]\s*$/;function oq(e){return(e??"").trim().toLowerCase()}function oW(e){return oq(e.hardwareProperties?.platform)}function oH(e){return e.includes("tvos")}function oK(e){let t=oq(e);return oV.some(e=>t.includes(e))}function oz(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function oJ(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function oX(e={}){let t,n,a=L(e.simulatorSetPath),i=e.target;try{t=await S("xcrun",k(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{n=JSON.parse(t.stdout)}catch{return null}let r=oY(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 oY(e,t){let n=[];for(let[a,i]of Object.entries(e.devices))if(function(e){let t=oq(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:oH(oq(a))?"tv":"mobile",booted:"Booted"===e.state,...t?{simulatorSetPath:t}:{}});return n}function oZ(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 oQ(){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 S("xcrun",["devicectl","list","devices","--json-output",e],{allowFailure:!0,timeoutMs:oF});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=oW(e);return!!(n.includes("ios")||n.includes("tvos"))||(t=oJ(e),!!o$.test(t.trim())||oz(e).some(oK))}(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 oH(oW(e))?"tv":(t=oJ(e),oG.test(t.trim())||oz(e).some(oK))?"tv":"mobile"}(n),booted:!0})}return t}(JSON.parse(n))}catch{return[]}finally{e&&await i.rm(e,{force:!0}).catch(()=>{})}}async function o0(){try{let e=await S("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=oB.exec(e);if(i){n=i[1]?.trim()??null;continue}if("Devices"!==n)continue;let r=oj.exec(e),o=r?.groups?.id?.trim()??"",s=r?.groups?.name?.trim()??"";if(!o||!s)continue;let l=function(e){return oK(e)?"tv":oU.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 o1(e={}){if("darwin"!==process.platform)throw new m("UNSUPPORTED_PLATFORM","Apple tools are only available on macOS");if(!await x("xcrun"))throw new m("TOOL_MISSING","xcrun not found in PATH");let t=L(e.simulatorSetPath),n=await S("xcrun",k(["list","devices","-j"],{simulatorSetPath:t})),a=[];try{let e=JSON.parse(n.stdout);a=oY(e,t)}catch(e){throw new m("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([oQ(),o0()]);return a=oZ(a,i),oZ(a,o)}async function o2(e,t,n){let a,i=!!(t.udid||t.serial||t.deviceName);try{a=await e$(e,t,n)}catch(e){if(i||!(e instanceof m)||"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 oX({simulatorSetPath:n.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new m("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function o3(e){let t=ek(e.platform),n=eF({simulatorSetPath:L(e.iosSimulatorDeviceSet),platform:t,target:e.target}),a=$(e.androidDeviceAllowlist);return await g("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 m("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 oA();return await e$(e,i)}if("android"===i.platform){await F();let e=await nD({serialAllowlist:a});return await e$(e,i)}if(i.platform){let e=await o1({simulatorSetPath:n});return await o2(e,i,{simulatorSetPath:n})}let r=[];try{r.push(...await nD({serialAllowlist:a}))}catch{}try{r.push(...await o1({simulatorSetPath:n}))}catch{}try{r.push(...await oA())}catch{}return await e$(r,i,{simulatorSetPath:n})},{platform:t,target:e.target})}async function o4(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)=>nY(e,t,n?.activity),openDevice:()=>n3(e),close:t=>n4(e,t),tap:(t,n)=>aN(e,t,n),doubleTap:async(t,n)=>{await aN(e,t,n),await aN(e,t,n)},swipe:(t,n,a,i,r)=>ax(e,t,n,a,i,r),longPress:(t,n,a)=>aO(e,t,n,a),focus:(t,n)=>ak(e,t,n),type:(t,n)=>aT(e,t,n),fill:(t,n,a,i)=>aR(e,t,n,a,i),scroll:(t,n)=>a$(e,t,n),screenshot:t=>ie(e,t),back:t=>aE(e),home:()=>aD(e),rotate:t=>aM(e,t),appSwitcher:()=>aC(e),readClipboard:()=>az(e),writeClipboard:t=>aJ(e,t),setSetting:(t,n,a,i)=>a1(e,t,n,a,i)};case"linux":return{open:e=>of(e),openDevice:()=>Promise.resolve(),close:e=>om(e),tap:(e,t)=>r7(e,t),doubleTap:(e,t)=>on(e,t),swipe:(e,t,n,a,i)=>or(e,t,n,a,i),longPress:(e,t,n)=>oa(e,t,n),focus:(e,t)=>oi(e,t),type:(e,t)=>os(e,t),fill:(e,t,n,a)=>ol(e,t,n,a),scroll:(e,t)=>oo(e,t),screenshot:e=>op(e),back:()=>oh(),home:()=>ow(),rotate:()=>{throw new m("UNSUPPORTED_OPERATION","rotate not supported on Linux")},appSwitcher:()=>{throw new m("UNSUPPORTED_OPERATION","appSwitcher not yet supported on Linux")},readClipboard:()=>og(),writeClipboard:e=>oI(e),setSetting:()=>{throw new m("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 np(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),doubleTap:async(a,i)=>await np(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 np(e,{command:"drag",x:a,y:i,x2:r,y2:o,durationMs:s,appBundleId:t.appBundleId},n),longPress:async(a,i,r)=>await np(e,{command:"longPress",x:a,y:i,durationMs:r,appBundleId:t.appBundleId},n),focus:async(a,i)=>await np(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n),type:async(a,i)=>{await np(e,{command:"type",text:a,delayMs:i,appBundleId:t.appBundleId},n)},fill:async(a,i,r,o)=>{let s=await np(e,{command:"tap",x:a,y:i,appBundleId:t.appBundleId},n);return await np(e,{command:"type",text:r,clearFirst:!0,delayMs:o,appBundleId:t.appBundleId},n),s},scroll:async(a,i)=>await rY(np,e,t,n,a,i)}};return{open:(t,n)=>rM(e,t,{appBundleId:n?.appBundleId,url:n?.url}),openDevice:()=>rC(e),close:t=>rO(e,t),screenshot:async(t,n)=>{"macos"===e.platform&&n?.surface&&"app"!==n.surface?await iZ(t,{surface:n.surface,fullscreen:n.fullscreen}):await rf(e,t,n?.appBundleId,n?.fullscreen)},back:async n=>{await np(e,{command:"system"===n?"backSystem":"backInApp",appBundleId:t.appBundleId},i)},home:async()=>{await np(e,{command:"home",appBundleId:t.appBundleId},i)},rotate:async n=>{await np(e,{command:"rotate",orientation:n,appBundleId:t.appBundleId},i)},appSwitcher:async()=>{await np(e,{command:"appSwitcher",appBundleId:t.appBundleId},i)},readClipboard:()=>rP(e),writeClipboard:t=>rF(e,t),setSetting:(t,n,a,i)=>rU(e,t,n,a,i),...a}}default:throw new m("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,o);return I({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await g("platform_command",async()=>{switch(t){case"open":return o5(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 o8(e,l,n,r,o);case"swipe":return o6(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 m("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 m("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 m("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 m("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(sl("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 m("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(sl("Filled",a))}}case"scroll":return o9(l,n,r);case"pinch":return o7(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 m("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!oM.test(t))throw new m("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 m("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 m("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 m("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return n}catch(t){if(t instanceof m)throw t;throw new m("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 m("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 m("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=oP(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 se(l,n);case"keyboard":return st(e,l,n,r,o);case"settings":return sn(e,l,n,r);case"push":return sa(e,n,r);case"snapshot":return si(e,n,r,o);case"read":return sr(e,n,r,o);default:throw new m("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}async function o5(e,t,n,a){let i=n[0],r=n[1];if(n.length>2)throw new m("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 m("INVALID_ARGS","open <app> <url> is supported only on Apple platforms");if(nm(i))throw new m("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!nm(r))throw new m("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 o8(e,t,n,a,i){let r,[o,s]=n.map(Number);if(Number.isNaN(o)||Number.isNaN(s))throw new m("INVALID_ARGS","press requires x y");if("macos"===e.platform&&a?.surface&&"app"!==a.surface){let e=ox(a);if("primary"!==e)throw new m("UNSUPPORTED_OPERATION",`${e} click is not supported on macOS ${a.surface} sessions.`);return await iY(o,s,{bundleId:a.appBundleId,surface:a.surface}),{x:o,y:s,...Y(so({x:o,y:s}))}}let l=ox(a);if("primary"!==l){let t=oE({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 oe(o,s):await ot(o,s):await np(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(so({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 m("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(f&&p>0)throw new m("INVALID_ARGS","double-tap cannot be combined with jitter-px");if(("ios"===e.platform||"macos"===e.platform)&&d>1&&0===c&&0===p){let t=await np(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(so({x:o,y:s}))}}return await oO(d,u,async e=>{let[n,a]=function(e,t){if(t<=0)return[0,0];let[n,a]=oC[e%oC.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},so({x:o,y:s}))}async function o6(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 m("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 m("INVALID_ARGS",`Invalid pattern: ${f}`);if(("ios"===e.platform||"macos"===e.platform)&&c>1){let t=await np(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(ss(c,f))}}return await oO(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},ss(c,f))}async function o9(e,t,n){let a=t[0],i=t[1]?Number(t[1]):void 0,r=n?.pixels;if(!a)throw new m("INVALID_ARGS","scroll requires direction");if(void 0!==i&&!Number.isFinite(i))throw new m("INVALID_ARGS","scroll amount must be a number");if(void 0!==i&&void 0!==r)throw new m("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 m("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 o7(e,t,n,a){if("android"===e.platform)throw new m("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 m("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 m("INVALID_ARGS","pinch requires scale > 0");return await np(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 se(e,t){let n=(t[0]??"").toLowerCase();if("read"!==n&&"write"!==n)throw new m("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===n){if(1!==t.length)throw new m("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:n,text:await e.readClipboard()}}if(t.length<2)throw new m("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 st(e,t,n,a,i){let r=(n[0]??"status").toLowerCase();if("status"!==r&&"get"!==r&&"dismiss"!==r)throw new m("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(n.length>1)throw new m("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("android"===e.platform){if("dismiss"===r){let t=await aK(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 aH(e);return{platform:"android",action:"status",visible:t.visible,inputType:t.inputType,type:t.type}}if("ios"===e.platform){if("dismiss"!==r)throw new m("UNSUPPORTED_OPERATION","keyboard status/get is currently supported only on Android; use keyboard dismiss on iOS");let t=await np(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 m("UNSUPPORTED_OPERATION","keyboard is supported only on Android and iOS")}async function sn(e,t,n,a){var i;let[r,o,s,l,d]=n,u="permission"===r?{permissionTarget:s,permissionMode:l}:void 0;I({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 sa(e,t,n){let a=t[0]?.trim(),i=t[1]?.trim();if(!a||!i)throw new m("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let r=await ok(i);if("ios"===e.platform)return await r$(e,a,r),{platform:"ios",bundleId:a,...Y(`Pushed notification to ${a}`)};let o=await a9(e,a,r);return{platform:"android",package:a,action:o.action,extrasCount:o.extrasCount,...Y(`Pushed notification to ${a}`)}}async function si(e,t,n,a){if("linux"===e.platform){let e=await g("snapshot_capture",async()=>await oN(n?.surface),{backend:"linux-atspi"});return{nodes:e.nodes??[],truncated:e.truncated??!1,backend:"linux-atspi"}}if("android"!==e.platform){let t=await g("snapshot_capture",async()=>await np(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 m("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:a,truncated:t.truncated??!1,backend:"xctest"}}let i=await g("snapshot_capture",async()=>await ag(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 sr(e,t,n,a){let[i,r]=t.map(Number);if(Number.isNaN(i)||Number.isNaN(r))throw new m("INVALID_ARGS","read requires x y");if("android"===e.platform)return{action:"read",text:await aq(e,i,r)??""};if("macos"===e.platform&&n?.surface&&"app"!==n.surface)return{action:"read",text:(await iX(i,r,{bundleId:n.appBundleId,surface:n.surface})).text};let o=await np(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 so(e){return e.button&&"primary"!==e.button?`Clicked ${e.button} (${e.x}, ${e.y})`:`Tapped (${e.x}, ${e.y})`}function ss(e,t){return e<=1?"Swiped":"ping-pong"===t?`Swiped ${e} times (ping-pong)`:`Swiped ${e} times`}function sl(e,t){return`${e} ${Array.from(t).length} chars`}let sd=[250,400];function su(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?sm(n?.nodes??[]):void 0,routeComparable:a}}function sc(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 sp(e){e&&"android"===e.device.platform&&delete e.androidSnapshotFreshness}function sf(e){return"press"===e||"click"===e||"back"===e||"open"===e}function sm(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("|"))}function sh(e,t,n,a,i){return{requestId:i??w().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,count:t?.count,intervalMs:t?.intervalMs,delayMs:t?.delayMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,pixels:t?.pixels,doubleTap:t?.doubleTap,clickButton:ox(t),backMode:t?.backMode,pauseMs:t?.pauseMs,pattern:t?.pattern}}async function sw(e){let t=sc(e.session);if(t&&"android"===e.device.platform)return await sg(e,t);let n=await sy(e);return sp(e.session),{snapshot:sv(n,e.flags),analysis:n.analysis}}async function sy(e){let{device:t,session:n,flags:a,outPath:i,logPath:r,snapshotScope:o}=e;if("linux"===t.platform){let e=await oN(n?.surface);return sb({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?sb(await iJ(n.surface,{bundleId:"menubar"===n.surface?n.appBundleId:void 0}),{snapshotDepth:a?.snapshotDepth,snapshotInteractiveOnly:a?.snapshotInteractiveOnly,snapshotScope:o}):await o4(t,"snapshot",[],i,{...sh(r,{...a,snapshotScope:o},n?.appBundleId,n?.trace?.outPath)})}async function sg(e,t){let n=await sI(e),a=sA(n,t,e.flags),i=0;for(let r of sd){if(!a)break;await new Promise(e=>setTimeout(e,r)),n=await sI(e),i+=1,a=sA(n,t,e.flags)}return a||sp(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 sI(e){let t=await sy(e);return{data:t,snapshot:sv(t,e.flags)}}function sA(e,t,n){var a,i;let r=n?.snapshotInteractiveOnly===!0,o=e.data.analysis;if(r&&0===e.snapshot.nodes.length&&o&&o.rawNodeCount>=12)return"empty-interactive";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&&sf(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=sm(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 sv(e,t){let n=e?.nodes??[],a=J(t?.snapshotRaw?n:ed(n));return{nodes:ei(t?.snapshotScope&&e?.backend!=="macos-helper"?s_(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 sb(e,t){var n,a;let i=e.nodes??[];return t.snapshotScope&&(i=s_(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:sS(e.filter(e=>n.has(e.index)))}(i)),"number"==typeof t.snapshotDepth&&(n=i,a=t.snapshotDepth,i=sS(n.filter(e=>(e.depth??0)<=a))),{...e,nodes:i}}function s_(e,t){let n=eu(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 sS(r,i)}function sS(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 sN(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return eL("INVALID_ARGS","Ref scope requires an existing snapshot in session.");let n=ea(e.trim());if(!n)return eL("INVALID_ARGS",`Invalid ref scope: ${e}`);let a=et(t.snapshot.nodes,n),i=a?ec(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:eL("COMMAND_FAILED",`Ref ${e} not found or has no label`)}let sx=D(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function sE(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve(em);await t(e);return}if("device"===e.kind)return void await sD(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve(ef);await t(e.id)}}async function sD(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(sx/1e3));try{let a=await S("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(n)],{allowFailure:!0,timeoutMs:sx+3e3}),i=String(a.stdout??""),r=String(a.stderr??""),o=await sM(t);if(0===a.exitCode){if(!o.parsed)throw new m("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 m("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 m("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:sC(i,r)})}catch(t){if(t instanceof m&&"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??sx),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 m("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:r,stdout:a,stderr:i,hint:a||i?sC(a,i):o},t)}throw new m("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 sM(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 sC(e,t){let n=ig(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.":iy)}async function sO(e,t,n){let a=e.get(t),i=a?.device??await o3(n??{});return a||await sE(i),{session:a,device:i}}async function sT(e,t,n){let a=!e&&"ios"===t.platform;try{return await n()}finally{a&&await nr(t.id)}}function sL(e,t,n,a){t&&e.recordAction(t,{command:n.command,positionals:n.positionals??[],flags:n.flags??{},result:a})}function sk(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function sR(e){if(0===e.length)return null;let t=sk(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=sk(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=sk(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let n=sk(e[e.length-1]),a=er(null!==n?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=eo(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}}async function sP(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(!eq("alert",r))return eL("UNSUPPORTED_OPERATION","alert is not supported on this device");if("macos"===r.platform){let e=async()=>await iz("wait"===o?"get":o,s);if("wait"===o){let n=sk(t.positionals?.[1])??1e4,r=Date.now();for(;Date.now()-r<n;){try{let n=await e();return sL(a,i,t,n),{ok:!0,data:n}}catch{}await new Promise(e=>setTimeout(e,300))}return eL("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 iz(n,s);return sL(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 new Promise(e=>setTimeout(e,300))}throw sF(e)}let r=await iz("get",s);return sL(a,i,t,r),{ok:!0,data:r}}if("wait"===o){let e=sk(t.positionals?.[1])??1e4,o=Date.now();for(;Date.now()-o<e;){try{let e=await np(r,{command:"alert",action:"get",appBundleId:i?.appBundleId},{verbose:t.flags?.verbose,logPath:n,traceLogPath:i?.trace?.outPath,requestId:t.meta?.requestId});return sL(a,i,t,e),{ok:!0,data:e}}catch{}await new Promise(e=>setTimeout(e,300))}return eL("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 np(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sL(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 new Promise(e=>setTimeout(e,300))}throw sF(e)}let u=await np(r,{command:"alert",action:l,appBundleId:i?.appBundleId},d);return sL(a,i,t,u),{ok:!0,data:u}}function sF(e){if(!(e instanceof m))return e;let t=String(e.message??"").toLowerCase();return t.includes("alert not found")||t.includes("no alert")?new m(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}async function s$(e){let t,{req:n,logPath:a,sessionStore:i,session:r,device:o,parsed:s}=e,{setting:l,state:d,permissionTarget:u}=s;if(!eq("settings",o))return eL("UNSUPPORTED_OPERATION","settings is not supported on this device");if("macos"===o.platform&&"appearance"!==(t=l.trim().toLowerCase())&&"permission"!==t)return eL("INVALID_ARGS",eN(l));let c=r?.appBundleId,p="permission"===l?[l,d,u??"",n.positionals?.[3]??"",c??""]:[l,d,c??""],f=await o4(o,"settings",p,n.flags?.out,{...sh(a,n.flags,c,r?.trace?.outPath)});return sL(i,r,n,f??{setting:l,state:d}),{ok:!0,data:f??{setting:l,state:d}}}function sU(e,t={}){let n=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new m("UNSUPPORTED_OPERATION",`${e} ${n} not resolve input artifacts`)},reserveOutput:async()=>{throw new m("UNSUPPORTED_OPERATION",`${e} ${n} not reserve output artifacts`)},createTempFile:async()=>{throw new m("UNSUPPORTED_OPERATION",`${e} ${n} not create temporary files`)}}}async function sG(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sO(i,n,t.flags);if(!eq("snapshot",o))return eL("UNSUPPORTED_OPERATION","snapshot is not supported on this device");let s=sN(t.flags?.snapshotScope,r);return s.ok?await sT(r,o,async()=>{let e=sB({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 sj({req:t,sessionName:n,sessionStore:i,result:{nodes:l.nodes.length,truncated:l.truncated}}),{ok:!0,data:l}}):s}async function sV(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,{session:r,device:o}=await sO(i,n,t.flags);if(!eq("diff",o))return eL("UNSUPPORTED_OPERATION","diff is not supported on this device");let s=sN(t.flags?.snapshotScope,r);return s.ok?await sT(r,o,async()=>{let e=sB({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 sj({req:t,sessionName:n,sessionStore:i,result:{mode:"snapshot",baselineInitialized:l.baselineInitialized,summary:l.summary}}),{ok:!0,data:l}}):s}function sB(e){let{req:t,sessionName:n,logPath:a,sessionStore:i,session:r,device:o,snapshotScope:s}=e;return h({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 sw({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:sU("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 m("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:y()})}function sj(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 sq(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 sW(e){let{device:t,node:n,flags:a,appBundleId:i,traceOutPath:r,surface:o,contextFromFlags:s}=e,l=es(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 o4(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 I({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:n.ref,surface:o,platform:t.platform}}),l}catch(e){return I({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 sH=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function sK(e,t){let n=function(e){if(!e)return[];let t=[];for(let[n,a]of sH)void 0!==e[n]&&t.push(a);return t}(t);return 0===n.length?null:eL("INVALID_ARGS",`${e} @ref does not support ${n.join(", ")}.`)}async function sz(e,t){let n=await sJ(e);if(n)throw new m("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${n.foregroundPackage}. The tap likely escaped the app.`,n)}async function sJ(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let n=await nJ(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 sX(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function sY(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 sZ(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 sQ(e){return e.startsWith("@")?e.slice(1):e}async function s0(e){var t;let{req:n}=e;if("find"!==n.command)return null;let a=n.positionals??[];if(0===a.length)return eL("INVALID_ARGS","find requires a locator or text");let i=ep(a);if(!i.query)return eL("INVALID_ARGS","find requires a value");if(n.flags?.findFirst&&n.flags?.findLast)return eL("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 s5(e,{requireSession:!1,capability:"find"});return o.ok?await s9(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 sY(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 s1(e){let{req:t}=e;if("get"!==t.command)return null;let n=t.positionals?.[0];if("text"!==n&&"attrs"!==n)return eL("INVALID_ARGS","get only supports text or attrs");let a=await s5(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:eL("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!i.ok)return i.response;if("ref"===i.target.kind){let e=sK("get",t.flags);if(e)return e}return await s9(async()=>{let r,o=await a.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:n,target:i.target});return sY(e.sessionStore,e.sessionName,t,function(e,t){let n=Array.isArray(e.selectorChain)?e.selectorChain:void 0,a=sZ(e),i=a?.kind==="ref"?sQ(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=sZ(o),{...r?.kind==="ref"?{ref:sQ(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 s2(e){let{req:t}=e;if("is"!==t.command)return null;let n=(t.positionals?.[0]??"").toLowerCase();if(!Z(n))return eL("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:a}=el(t.positionals??[]);if(!a)return eL("INVALID_ARGS","is requires a selector expression");let i=a.rest.join(" ").trim();if("text"===n&&!i)return eL("INVALID_ARGS","is text requires expected text value");if("text"!==n&&a.rest.length>0)return eL("INVALID_ARGS",`is ${n} does not accept trailing values`);let r=await s5(e,{requireSession:!0,capability:"is"});if(!r.ok)return r.response;let o=await s9(async()=>{let o=await r.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:n,selector:a.selectorExpression,expectedText:i});return sY(e.sessionStore,e.sessionName,t,o),function(e){let{selectorChain:t,...n}=e;return n}(o)});return await s7(e,o,`is ${n}`)}async function s3(e){let{req:t,sessionName:n,sessionStore:a}=e,i=sR(t.positionals??[]);if(!i)return eL("INVALID_ARGS","wait requires a duration or text");let{session:r,device:o}=await sO(a,n,t.flags);if("sleep"!==i.kind&&!eq("wait",o))return eL("UNSUPPORTED_OPERATION","wait is not supported on this device");let s=async()=>{let s=s4({...e,session:r,device:o}),l=await s9(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 m("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new m("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(i,r)});return sY(a,n,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}});return await s7(e,l,"wait")};return"sleep"===i.kind?await s():await sT(r,o,s)}function s4(e){return h({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&&!sc(a))return t;let h=await sw({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 sW({device:i,node:o,flags:n.flags,appBundleId:a?.appBundleId,traceOutPath:a?.trace?.outPath,surface:a?.surface,contextFromFlags:e.contextFromFlags??((e,t,n)=>sh(r??"",e,t,n))})}),findText:async(t,n)=>({found:await s8(e,n)})}}(e),artifacts:sU("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:y()})}async function s5(e,t){let n=e.sessionStore.get(e.sessionName);if(!n&&t.requireSession)return{ok:!1,response:eL("SESSION_NOT_FOUND","No active session. Run open first.")};let a=n?.device??await o3(e.req.flags??{});return(n||await sE(a),eq(t.capability,a))?{ok:!0,runtime:s4({...e,session:n,device:a})}:{ok:!1,response:eL("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function s8(e,t){let{device:n,session:a,req:i,logPath:r}=e;if("macos"===n.platform&&a?.surface&&"app"!==a.surface)return!!eu((await s6(e)).nodes,t);if(eR(n.platform)){let e=await np(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!!eu((await s6(e)).nodes,t)}async function s6(e){let t=await sw({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 s9(e){try{return{ok:!0,data:await e()}}catch(t){let e=f(t);return eL(e.code,e.message,e.details)}}async function s7(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 sJ(r)}catch{return t}return i?eL(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 le=new Set(["snapshot","diff","wait","alert","settings"]);async function lt(e){let{req:t,sessionName:n,logPath:a,sessionStore:i}=e,r=t.command;if(!le.has(r))return null;if("snapshot"===r)return await sG({req:t,sessionName:n,logPath:a,sessionStore:i});if("diff"===r)return t.positionals?.[0]!=="snapshot"?eL("INVALID_ARGS","diff currently supports only: diff snapshot"):await sV({req:t,sessionName:n,logPath:a,sessionStore:i});if("wait"===r)return await s3({req:t,sessionName:n,logPath:a,sessionStore:i});if("alert"===r){let{session:e,device:r}=await sO(i,n,t.flags);return await sT(e,r,async()=>await sP({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}}:eL("INVALID_ARGS",eS));if(!s.ok)return s;let{session:l,device:d}=await sO(i,n,t.flags);return await sT(l,d,async()=>await s$({req:t,logPath:a,sessionStore:i,session:l,device:d,parsed:s.parsed}))}return null}export{ensureAdb}from"./9323.js";export{eD as DEFAULT_BATCH_MAX_STEPS,iy as IOS_DEVICECTL_DEFAULT_HINT,tB as IOS_RUNNER_CONTAINER_BUNDLE_IDS,io as IOS_SIMCTL_LIST_TIMEOUT_MS,ex as SESSION_SURFACES,e_ as SETTINGS_USAGE_OVERRIDE,no as abortAllIosRunnerSessions,aC as appSwitcherAndroid,sz as assertAndroidPressStayedInApp,aE as backAndroid,as as buildScrollGesturePlan,sv as buildSnapshotState,oD as buttonTag,eq as capabilities_isCommandSupportedOnDevice,sy as captureSnapshotData,e6 as clearRequestCanceled,n4 as closeAndroidApp,rO as closeIosApp,sh as context_contextFromFlags,te as createRequestCanceledError,sU as createUnsupportedArtifactAdapter,eR as device_isApplePlatform,nR as waitForAndroidBoot,aK as dismissAndroidKeyboard,o4 as dispatchCommand,s0 as dispatchFindReadOnlyViaRuntime,s1 as dispatchGetViaRuntime,s2 as dispatchIsViaRuntime,nk as ensureAndroidEmulatorBooted,sE as ensureDeviceReady,aR as fillAndroid,oX as findBootableIosSimulator,ak as focusAndroid,sc as getActiveAndroidSnapshotFreshness,nJ as getAndroidAppState,aH as getAndroidKeyboardState,aU as getAndroidScreenSize,oE as getClickButtonValidationError,e7 as getRequestSignal,nn as getRunnerSessionSnapshot,lt as handleSnapshotCommands,aD as homeAndroid,nz as inferAndroidAppName,ar as installAndroidApp,ai as installAndroidInstallablePathAndResolvePackageName,rL as installIosApp,rR as installIosInstallablePath,sX as isAndroidEscapeError,nm as isDeepLinkTarget,eH as isEnvTruthy,sf as isNavigationSensitiveAction,e9 as isRequestCanceled,nq as listAndroidApps,nD as listAndroidDevices,o1 as listAppleDevices,rG as listIosApps,ih as listIosDeviceApps,iw as listIosDeviceProcesses,aO as longPressAndroid,su as markAndroidSnapshotFreshness,e8 as markRequestCanceled,eP as matchesPlatformSelector,ek as normalizePlatformSelector,nY as openAndroidApp,n3 as openAndroidDevice,rM as openIosApp,rC as openIosDevice,eO as parseBatchStepsJson,sq as parseCoordinateTarget,oP as parseDeviceRotation,eE as parseSessionSurface,sR as parseWaitArgs,tM as parseXmlDocumentSync,nP as prepareAndroidInstallArtifact,iE as prepareIosInstallArtifact,aN as pressAndroid,a9 as pushAndroidNotification,r$ as pushIosNotification,az as readAndroidClipboardText,aq as readAndroidTextAtPoint,ix as readInfoPlistString,rP as readIosClipboardText,sW as readTextForNode,sK as refSnapshotFlagGuardResponse,e5 as registerRequestAbort,ao as reinstallAndroidApp,rk as reinstallIosApp,nj as resolveAndroidApp,eF as resolveAppleSimulatorSetPathForSelector,ox as resolveClickButton,iW as resolveFrontmostMacOsApp,rD as resolveIosApp,nh as resolveIosDeviceDeepLinkBundleId,ig as resolveIosDevicectlHint,oL as resolvePayloadInput,e4 as resolveRequestTrackingId,o3 as resolveTargetDevice,eL as response_errorResponse,aM as rotateAndroid,iz as runMacOsAlertAction,np as runner_client_runIosRunnerCommand,ie as screenshotAndroid,rf as screenshotIos,a$ as scrollAndroid,a1 as setAndroidSetting,rU as setIosSetting,iS as shutdownSimulator,i_ as ensureBootedSimulator,ag as snapshotAndroid,sw as snapshot_capture_captureSnapshot,ns as stopAllIosRunnerSessions,nr as stopIosRunnerSession,ax as swipeAndroid,aT as typeAndroid,eT as validateAndNormalizeBatchSteps,tN as withKeyedLock,aJ as writeAndroidClipboardText,rF as writeIosClipboardText};
@@ -0,0 +1 @@
1
+ function t(t){return t.map((t,n)=>({...t,ref:`e${n+1}`}))}function n(t){let n=t.trim();return n.startsWith("@")?n.slice(1)||null:n.startsWith("e")?n:null}function e(t,n){return t.find(t=>t.ref===n)??null}function r(t){return{x:Math.round(t.x+t.width/2),y:Math.round(t.y+t.height/2)}}export{t as attachRefs,r as centerOfRect,e as findNodeByRef,n as normalizeRef};
@@ -0,0 +1 @@
1
+ import{AppError as e}from"./9152.js";function t(e,l,o,u={}){let c=i(o);if(!c)return{matches:[],score:0};let a=0,s=[];for(let t of e){if(u.requireRect&&!t.rect)continue;let e=function(e,t,i){switch(t){case"role":return function(e,t){let r=n(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,i);case"label":return r(e.label,i);case"value":return r(e.value,i);case"id":return r(e.identifier,i);default:return Math.max(r(e.label,i),r(e.value,i),r(e.identifier,i))}}(t,l,c);if(!(e<=0)){if(e>a){a=e,s.length=0,s.push(t);continue}e===a&&s.push(t)}}return{matches:s,score:a}}function r(e,t){let r=i(e??"");return r?r===t?2:+!!r.includes(t):0}function i(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function n(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}function l(t){let r="any",i=0;["text","label","value","role","id"].includes(t[0])&&(r=t[0],i=1);let n=t[i]??"",l=t.slice(i+1);if(0===l.length)return{locator:r,query:n,action:"click"};let o=l[0].toLowerCase();if("get"===o){let t=l[1]?.toLowerCase();if("text"===t)return{locator:r,query:n,action:"get_text"};if("attrs"===t)return{locator:r,query:n,action:"get_attrs"};throw new e("INVALID_ARGS","find get only supports text or attrs")}if("wait"===o)return{locator:r,query:n,action:"wait",timeoutMs:function(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}(l[1])??void 0};if("exists"===o)return{locator:r,query:n,action:"exists"};if("click"===o)return{locator:r,query:n,action:"click"};if("focus"===o)return{locator:r,query:n,action:"focus"};if("fill"===o)return{locator:r,query:n,action:"fill",value:l.slice(1).join(" ")};if("type"===o)return{locator:r,query:n,action:"type",value:l.slice(1).join(" ")};throw new e("INVALID_ARGS",`Unsupported find action: ${l[0]}`)}export{t as findBestMatchesByLocator,n as normalizeRole,i as normalizeText,l as parseFindArgs};
@@ -0,0 +1 @@
1
+ let t;import e from"node:fs/promises";import r from"node:path";import{TextDecoder as n}from"node:util";import{isExecutablePath as a,runCmd as i}from"./9818.js";import{resolveAndroidSdkRoots as f}from"./8164.js";let o=new n("utf-16le");async function u(t){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var e;let n=await l(t,r);if(!n)continue;let a=(e=n).subarray(0,Math.min(e.length,128)).toString("utf8").trimStart().startsWith("<")?function(t){let e=t.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return e?.[1]}(e.toString("utf8")):function(t){let e;if(!(t.length<8)&&3===t.readUInt16LE(0))for(let r=t.readUInt16LE(2);r+8<=t.length;){let n=t.readUInt16LE(r),a=t.readUInt16LE(r+2),i=t.readUInt32LE(r+4);if(i<=0||r+i>t.length)break;if(1===n)e=function(t){if(t.length<28)return[];let e=t.readUInt32LE(8),r=t.readUInt32LE(16),n=t.readUInt32LE(20),a=(256&r)!=0,i=[];for(let r=0;r<e;r+=1){let e=28+4*r;if(e+4>t.length)break;let f=n+t.readUInt32LE(e);i.push(a?function(t,e){let[,r]=d(t,e),[n,a]=d(t,e+r),i=e+r+a;return t.subarray(i,i+n).toString("utf8")}(t,f):function(t,e){let[r,n]=function(t,e){let r=t.readUInt16LE(e);return(32768&r)==0?[r,2]:[(32767&r)<<16|t.readUInt16LE(e+2),4]}(t,e),a=e+n;return o.decode(t.subarray(a,a+2*r))}(t,f))}return i}(t.subarray(r,r+i));else if(258===n&&e){let n=function(t,e,r,n){if(r<36||e+r>t.length||"manifest"!==n[t.readUInt32LE(e+20)])return;let a=t.readUInt16LE(e+24),i=t.readUInt16LE(e+26),f=t.readUInt16LE(e+28),o=e+a;for(let e=0;e<f;e+=1){let r=o+e*i;if(r+20>t.length)break;if("package"!==n[t.readUInt32LE(r+4)])continue;let a=t.readUInt32LE(r+8);if(0xffffffff!==a)return n[a];let f=t.readUInt8(r+15),u=t.readUInt32LE(r+16);if(3===f)return n[u];break}}(t,r,a,e);if(n)return n}r+=i}}(e);if(a)return a}return await c(t)}async function l(t,e){try{let r=await i("unzip",["-p",t,e],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function d(t,e){let r=t.readUInt8(e);return(128&r)==0?[r,1]:[(127&r)<<8|t.readUInt8(e+1),2]}async function c(t){let e=await s();if(!e)return;let r=await i(e,["dump","badging",t],{allowFailure:!0});if(0!==r.exitCode)return;let n=r.stdout.match(/package:\s+name='([^']+)'/);return n?.[1]}async function s(){if(void 0!==t)return t??void 0;try{for(let n of f()){let i=r.join(n,"build-tools");try{for(let n of(await e.readdir(i)).sort((t,e)=>e.localeCompare(t,void 0,{numeric:!0}))){let e=r.join(i,n,"aapt");if(r.isAbsolute(e)&&await a(e))return t=e,e}}catch{}}}catch{}t=null}export{u as resolveAndroidArchivePackageName};