agent-device 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/src/224.js +2 -2
  2. package/dist/src/331.js +1 -1
  3. package/dist/src/bin.js +61 -60
  4. package/dist/src/client-shared.d.ts +20 -0
  5. package/dist/src/core/dispatch-resolve.d.ts +2 -2
  6. package/dist/src/daemon/handlers/session-batch.d.ts +2 -0
  7. package/dist/src/daemon/handlers/session-close.d.ts +31 -0
  8. package/dist/src/daemon/handlers/session-deploy.d.ts +37 -0
  9. package/dist/src/daemon/handlers/session-device-utils.d.ts +25 -0
  10. package/dist/src/daemon/handlers/session-open-target.d.ts +3 -0
  11. package/dist/src/daemon/handlers/session-open.d.ts +22 -0
  12. package/dist/src/daemon/handlers/session-perf.d.ts +2 -0
  13. package/dist/src/daemon/handlers/session-runtime-command.d.ts +9 -0
  14. package/dist/src/daemon/handlers/session-runtime.d.ts +41 -0
  15. package/dist/src/daemon/handlers/session-startup-metrics.d.ts +11 -0
  16. package/dist/src/daemon/handlers/session.d.ts +4 -29
  17. package/dist/src/daemon/selectors-build.d.ts +4 -0
  18. package/dist/src/daemon/selectors-match.d.ts +5 -0
  19. package/dist/src/daemon/selectors-parse.d.ts +29 -0
  20. package/dist/src/daemon/selectors-resolve.d.ts +32 -0
  21. package/dist/src/daemon/selectors.d.ts +5 -65
  22. package/dist/src/daemon.js +36 -36
  23. package/dist/src/platforms/android/index.d.ts +2 -1
  24. package/dist/src/platforms/android/screenshot.d.ts +16 -0
  25. package/dist/src/platforms/android/snapshot.d.ts +0 -1
  26. package/dist/src/platforms/ios/config.d.ts +1 -0
  27. package/dist/src/platforms/ios/index.d.ts +1 -1
  28. package/dist/src/platforms/ios/screenshot-status-bar.d.ts +2 -0
  29. package/dist/src/platforms/ios/screenshot.d.ts +2 -1
  30. package/dist/src/utils/command-schema.d.ts +2 -0
  31. package/dist/src/utils/device.d.ts +1 -1
  32. package/dist/src/utils/interactors.d.ts +7 -0
  33. package/dist/src/utils/output.d.ts +3 -1
  34. package/dist/src/utils/path-resolution.d.ts +8 -0
  35. package/dist/src/utils/screenshot-diff.d.ts +23 -0
  36. package/package.json +5 -5
  37. package/skills/agent-device/SKILL.md +4 -0
  38. package/skills/agent-device/references/snapshot-refs.md +1 -0
  39. package/skills/dogfood/SKILL.md +12 -12
  40. package/skills/dogfood/references/issue-taxonomy.md +5 -5
  41. package/skills/dogfood/templates/dogfood-report-template.md +19 -19
  42. package/dist/src/utils/interactive.d.ts +0 -1
@@ -1,41 +1,41 @@
1
- let e,t;import{isCancel as r,select as i}from"@clack/prompts";import a from"node:dns/promises";import n from"node:fs/promises";import{node_path as o,readProcessCommand as s,normalizeTenantId as l,isAgentDeviceDaemonProcess as d,runCmdDetached as u,runCmdBackground as c,node_crypto as p,runCmd as f,spawn as m,asAppError as h,pathToFileURL as w,AppError as g,external_node_url_URL as I,whichCmd as A,fileURLToPath as v,runCmdStreaming as y,normalizeError as b,resolveSessionIsolationMode as N,readVersion as S,findProjectRoot as _,getDiagnosticsMeta as D,withDiagnosticTimer as E,emitDiagnostic as k,promises as L,isProcessAlive as O,readProcessStartTime as M,withDiagnosticsScope as x,node_fs as C,flushDiagnosticsToSessionFile as R,node_os as P,node_net as T,resolveDaemonServerMode as $,resolveDaemonPaths as U,node_http as F}from"./331.js";import{buildSnapshotDisplayLines as V,DEFAULT_BATCH_MAX_STEPS as G,formatRole as j,validateAndNormalizeBatchSteps as B,SETTINGS_INVALID_ARGS_MESSAGE as q,displayLabel as H,TextDecoder as W,formatSnapshotLine as z}from"./274.js";let J=K(process.env.AGENT_DEVICE_RETRY_LOGS);function K(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let X=2e4,Z=12e4,Y=1e4;class Q{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new Q(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 ee(e,t={},r={}){let i,a={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=a.maxAttempts;t+=1){if(r.signal?.aborted)throw new g("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let i=await e({attempt:t,maxAttempts:a.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:a.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),er({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:a.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),i}catch(d){i=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:a.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),er(n),t>=a.maxAttempts||a.shouldRetry&&!a.shouldRetry(d,t))break;let o=function(e,t,r,i){let a=Math.min(t,e*2**(i-1));return Math.max(0,a+a*r*(2*Math.random()-1))}(a.baseDelayMs,a.maxDelayMs,a.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:a.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),er(l),await function(e,t){return new Promise(r=>{let i;if(t?.aborted)return void r();let a=!1,n=()=>{a||(a=!0,t&&i&&t.removeEventListener("abort",i),r())},o=setTimeout(n,e);i=()=>{clearTimeout(o),n()},t&&t.addEventListener("abort",i,{once:!0})})}(s,r.signal)}}let n={phase:r.phase,event:"exhausted",attempt:a.maxAttempts,maxAttempts:a.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(i)};if(r.onEvent?.(n),er(n),i)throw i;throw new g("COMMAND_FAILED","retry failed")}async function et(e,t={}){return ee(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function er(e){k({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),J&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
- `)}let ei=new Set,ea=new Map,en="request_canceled",eo="request canceled";function es(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",i=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${i}`}function el(e){if(!e)return;let t=new AbortController;ea.set(e,t),ei.has(e)&&t.abort()}function ed(e){e&&(ei.add(e),ea.get(e)?.abort())}function eu(e){e&&(ei.delete(e),ea.delete(e))}function ec(e){return!!e&&ei.has(e)}function ep(e){if(e)return ea.get(e)?.signal}function ef(){return new g("COMMAND_FAILED",eo,{reason:en})}function em(e){return e instanceof g&&"COMMAND_FAILED"===e.code&&(e.details?.reason===en||e.message===eo)}function eh(e){let t=e.error?h(e.error):null,r=e.context?.platform,i=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let a=t?.details??{},n="string"==typeof a.message?a.message:void 0,o="string"==typeof a.stdout?a.stdout:void 0,s="string"==typeof a.stderr?a.stderr:void 0,l=a.boot&&"object"==typeof a.boot?a.boot:null,d=a.bootstatus&&"object"==typeof a.bootstatus?a.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,n,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===i&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===i&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===i&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function ew(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 eg(e){return!(e instanceof g)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eI(e){let{port:t,endpoints:r,logPath:i,lastError:a}=e,n="Runner did not accept connection";return new g("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:i,lastError:a?String(a):void 0,reason:eh({error:a,message:n,context:{platform:"ios",phase:"connect"}}),hint:ew("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eA(e){var t,r;let i,{session:a,port:n,logPath:o}=e,s=await a.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=eh({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new g("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(i=`${l}
1
+ let e,t;import r from"node:dns/promises";import a from"node:fs/promises";import{node_path as i,readProcessCommand as n,normalizeTenantId as o,isAgentDeviceDaemonProcess as s,runCmdDetached as l,runCmdBackground as d,node_crypto as u,runCmd as c,spawn as p,asAppError as f,expandUserHomePath as m,pathToFileURL as h,AppError as w,external_node_url_URL as g,whichCmd as I,fileURLToPath as A,runCmdStreaming as v,normalizeError as y,resolveSessionIsolationMode as b,resolveUserPath as N,readVersion as _,getDiagnosticsMeta as S,findProjectRoot as D,withDiagnosticTimer as E,emitDiagnostic as k,promises as L,isProcessAlive as O,readProcessStartTime as M,withDiagnosticsScope as x,node_fs as C,flushDiagnosticsToSessionFile as R,node_os as T,node_net as P,resolveDaemonServerMode as $,resolveDaemonPaths as U,node_http as F}from"./331.js";import{buildSnapshotDisplayLines as V,DEFAULT_BATCH_MAX_STEPS as G,formatRole as B,validateAndNormalizeBatchSteps as j,SETTINGS_INVALID_ARGS_MESSAGE as q,displayLabel as H,TextDecoder as W,formatSnapshotLine as z}from"./274.js";let J=K(process.env.AGENT_DEVICE_RETRY_LOGS);function K(e){return["1","true","yes","on"].includes((e??"").toLowerCase())}let X=2e4,Z=12e4,Y=1e4;class Q{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(e,t=Date.now()){return new Q(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 ee(e,t={},r={}){let a,i={maxAttempts:t.maxAttempts??3,baseDelayMs:t.baseDelayMs??200,maxDelayMs:t.maxDelayMs??2e3,jitter:t.jitter??.2,shouldRetry:t.shouldRetry};for(let t=1;t<=i.maxAttempts;t+=1){if(r.signal?.aborted)throw new w("COMMAND_FAILED","request canceled",{reason:"request_canceled"});if(r.deadline?.isExpired()&&t>1)break;try{let a=await e({attempt:t,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),er({phase:r.phase,event:"succeeded",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),a}catch(d){a=d;let e=r.classifyReason?.(d),n={phase:r.phase,event:"attempt_failed",attempt:t,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};if(r.onEvent?.(n),er(n),t>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(d,t))break;let o=function(e,t,r,a){let i=Math.min(t,e*2**(a-1));return Math.max(0,i+i*r*(2*Math.random()-1))}(i.baseDelayMs,i.maxDelayMs,i.jitter,t),s=r.deadline?Math.min(o,r.deadline.remainingMs()):o;if(s<=0)break;let l={phase:r.phase,event:"retry_scheduled",attempt:t,maxAttempts:i.maxAttempts,delayMs:s,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:e};r.onEvent?.(l),er(l),await function(e,t){return new Promise(r=>{let a;if(t?.aborted)return void r();let i=!1,n=()=>{i||(i=!0,t&&a&&t.removeEventListener("abort",a),r())},o=setTimeout(n,e);a=()=>{clearTimeout(o),n()},t&&t.addEventListener("abort",a,{once:!0})})}(s,r.signal)}}let n={phase:r.phase,event:"exhausted",attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};if(r.onEvent?.(n),er(n),a)throw a;throw new w("COMMAND_FAILED","retry failed")}async function et(e,t={}){return ee(()=>e(),{maxAttempts:t.attempts,baseDelayMs:t.baseDelayMs,maxDelayMs:t.maxDelayMs,jitter:t.jitter,shouldRetry:t.shouldRetry})}function er(e){k({level:"attempt_failed"===e.event||"exhausted"===e.event?"warn":"debug",phase:"retry",data:{...e}}),J&&process.stderr.write(`[agent-device][retry] ${JSON.stringify(e)}
2
+ `)}let ea=new Set,ei=new Map,en="request_canceled",eo="request canceled";function es(e,t){if("string"==typeof e&&e.length>0)return e;let r=("string"==typeof t?t:"number"==typeof t&&Number.isFinite(t)?String(t):"generated").trim().replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,32)||"generated",a=Math.random().toString(36).slice(2,10);return`req:${r}:${process.pid}:${Date.now()}:${a}`}function el(e){if(!e)return;let t=new AbortController;ei.set(e,t),ea.has(e)&&t.abort()}function ed(e){e&&(ea.add(e),ei.get(e)?.abort())}function eu(e){e&&(ea.delete(e),ei.delete(e))}function ec(e){return!!e&&ea.has(e)}function ep(e){if(e)return ei.get(e)?.signal}function ef(){return new w("COMMAND_FAILED",eo,{reason:en})}function em(e){return e instanceof w&&"COMMAND_FAILED"===e.code&&(e.details?.reason===en||e.message===eo)}function eh(e){let t=e.error?f(e.error):null,r=e.context?.platform,a=e.context?.phase;if(t?.code==="TOOL_MISSING")return"android"===r?"ADB_TRANSPORT_UNAVAILABLE":"IOS_TOOL_MISSING";let i=t?.details??{},n="string"==typeof i.message?i.message:void 0,o="string"==typeof i.stdout?i.stdout:void 0,s="string"==typeof i.stderr?i.stderr:void 0,l=i.boot&&"object"==typeof i.boot?i.boot:null,d=i.bootstatus&&"object"==typeof i.bootstatus?i.bootstatus:null,u=[e.message,t?.message,e.stdout,e.stderr,n,o,s,"string"==typeof l?.stdout?l.stdout:void 0,"string"==typeof l?.stderr?l.stderr:void 0,"string"==typeof d?.stdout?d.stdout:void 0,"string"==typeof d?.stderr?d.stderr:void 0].filter(Boolean).join("\n").toLowerCase();return"ios"===r&&(u.includes("runner did not accept connection")||"connect"===a&&(u.includes("timed out")||u.includes("timeout")||u.includes("econnrefused")||u.includes("connection refused")||u.includes("fetch failed")||u.includes("socket hang up")))?"IOS_RUNNER_CONNECT_TIMEOUT":"ios"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"IOS_BOOT_TIMEOUT":"android"===r&&"boot"===a&&(u.includes("timed out")||u.includes("timeout"))?"ANDROID_BOOT_TIMEOUT":u.includes("resource temporarily unavailable")||u.includes("killed: 9")||u.includes("cannot allocate memory")||u.includes("system is low on memory")?"CI_RESOURCE_STARVATION_SUSPECTED":"android"===r&&(u.includes("device not found")||u.includes("no devices")||u.includes("device offline")||u.includes("offline")||u.includes("unauthorized")||u.includes("not authorized")||u.includes("unable to locate device")||u.includes("invalid device"))?"ADB_TRANSPORT_UNAVAILABLE":t?.code==="COMMAND_FAILED"||u.length>0?"BOOT_COMMAND_FAILED":"UNKNOWN"}function ew(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 eg(e){return!(e instanceof w)||"COMMAND_FAILED"!==e.code||!String(e.message??"").toLowerCase().includes("xcodebuild exited early")}function eI(e){let{port:t,endpoints:r,logPath:a,lastError:i}=e,n="Runner did not accept connection";return new w("COMMAND_FAILED",n,{port:t,endpoints:r,logPath:a,lastError:i?String(i):void 0,reason:eh({error:i,message:n,context:{platform:"ios",phase:"connect"}}),hint:ew("IOS_RUNNER_CONNECT_TIMEOUT")})}async function eA(e){var t,r;let a,{session:i,port:n,logPath:o}=e,s=await i.testPromise,l="Runner did not accept connection (xcodebuild exited early)",d=eh({message:l,stdout:s.stdout,stderr:s.stderr,context:{platform:"ios",phase:"connect"}});return new w("COMMAND_FAILED",l,{port:n,logPath:o,xcodebuild:{exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr},reason:d,hint:(t=s.stdout,r=s.stderr,(a=`${l}
3
3
  ${t}
4
- ${r}`.toLowerCase()).includes("device is busy")&&i.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":ew("IOS_RUNNER_CONNECT_TIMEOUT"))})}function ev(e){if(ec(e))throw ef()}function ey(e,t,r){if(!e)return t;let i=Number(e);return Number.isFinite(i)?Math.max(r,Math.floor(i)):t}let eb=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],eN=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function eS(e){return e?.trim()||void 0}function e_(e,t){for(let r of e){let e=eS(t[r]);if(e)return e}}function eD(e,t=process.env){return eS(e)??e_(eb,t)}function eE(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ek(e,t=process.env){let r=eS(e)??e_(eN,t);if(r)return eE(r)}function eL(e,t={}){let r=eD(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eO(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eL(t,{simulatorSetPath:e.simulatorSetPath})}let eM=ey(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),ex=ey(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),eC=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),eR=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),eP=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),eT=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),e$=ey(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),eU=ey(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function eF(e,t,r,i,a=eM,n,o){let s=Q.fromTimeoutMs(a),l=await eV(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(a/eC));try{return await ee(async({deadline:s})=>{if(s?.isExpired())throw new g("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:a});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eA({session:n,port:t,logPath:i});for(let i of("device"===e.kind&&(l=await eV(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??a;if(e<=0)throw new g("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:a});return await eG(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(eT,e),o)}catch(e){if(o?.aborted||em(e))throw ef();d=e}throw new g("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:eR,maxDelayMs:eP,jitter:.2,shouldRetry:eg},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||em(e))throw ef();d||(d=e)}if(o?.aborted)throw ef();if("simulator"===e.kind){let a=s.remainingMs();if(a<=0)throw eI({port:t,endpoints:l,logPath:i,lastError:d});let n=await eB(e,t,r,a);return new Response(n.body,{status:n.status})}throw eI({port:t,endpoints:l,logPath:i,lastError:d})}async function eV(e,t,r){let i=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return i;let a=await ej(e.id,r);return a&&i.unshift(`http://[${a}]:${t}/command`),i}async function eG(e,t,r,i){let a,n=new AbortController,o=setTimeout(()=>n.abort(),r);i&&(i.aborted?(clearTimeout(o),n.abort()):(a=()=>n.abort(),i.addEventListener("abort",a,{once:!0})));try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o),a&&i&&i.removeEventListener("abort",a)}}async function ej(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(e$,t)):e$,i=o.join(P.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),a=await f("xcrun",["devicectl","device","info","details","--device",e,"--json-output",i,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==a.exitCode||!C.existsSync(i))return null;let n=JSON.parse(C.readFileSync(i,"utf8"));if(n.info?.outcome&&"success"!==n.info.outcome)return null;let o=(n.result?.connectionProperties?.tunnelIPAddress??n.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{eW(i)}}async function eB(e,t,r,i){let a=JSON.stringify(r),n=eO(e,["spawn",e.id,"/usr/bin/curl","-s","-X","POST","-H","Content-Type: application/json","--data",a,`http://127.0.0.1:${t}/command`]),o=await f("xcrun",n,{allowFailure:!0,timeoutMs:i}),s=o.stdout;if(0!==o.exitCode){let e=eh({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new g("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:ew(e)})}return{status:200,body:s}}async function eq(){return await new Promise((e,t)=>{let r=T.createServer();r.listen(0,"127.0.0.1",()=>{let i=r.address();r.close(),"object"==typeof i&&i?.port?e(i.port):t(new g("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}function eH(e,t,r,i){t&&C.appendFileSync(t,e),r&&C.appendFileSync(r,e),i&&process.stderr.write(e)}function eW(e){try{C.existsSync(e)&&C.unlinkSync(e)}catch{}}async function ez(e,t,r){let i=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)})}function eJ(e){return"apple"===e?"ios":e}async function eK(e,t,a={}){let n=e,o=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(n=n.filter(e=>e.platform===t.platform)),t.target&&(n=n.filter(e=>(e.target??"mobile")===t.target)),t.udid){let e=n.find(e=>e.id===t.udid&&"ios"===e.platform);if(!e)throw new g("DEVICE_NOT_FOUND",`No iOS device with UDID ${t.udid}`);return e}if(t.serial){let e=n.find(e=>e.id===t.serial&&"android"===e.platform);if(!e)throw new g("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=o(t.deviceName),r=n.find(t=>o(t.name)===e);if(!r)throw new g("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===n.length)return n[0];if(0===n.length){let e=a.simulatorSetPath;if(e&&(!t.platform||"ios"===t.platform))throw new g("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
5
- xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new g("DEVICE_NOT_FOUND","No devices found",{selector:t})}let s=n.filter(e=>"device"!==e.kind);s.length>0&&(n=s);let l=n.filter(e=>e.booted);if(1===l.length)return l[0];if(!process.env.CI&&process.stdin.isTTY&&process.stdout.isTTY){let e=await i({message:"Multiple devices available. Choose a device to continue:",options:(l.length>0?l:n).map(e=>({label:`${e.name} (${e.platform}${e.kind?`, ${e.kind}`:""}${e.booted?", booted":""})`,value:e.id}))});if(r(e))throw new g("INVALID_ARGS","Device selection cancelled");if(e){let t=n.find(t=>t.id===e);if(t)return t}}return l[0]??n[0]}let eX=o.join(P.homedir(),".agent-device","ios-runner"),eZ=new Map,eY=new Set;function eQ(e){return e?.trim()??""}function e0(e=process.env){return eQ(e.AGENT_DEVICE_IOS_BUNDLE_ID)||eQ(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function e1(e=process.env){let t=eQ(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${e0(e)}.uitests`}let e2=function(e=process.env){let t=e0(e),r=e1(e);return Array.from(new Set([eQ(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function e3(e,t){var r;let i,a=(r=e.kind,(i=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?o.resolve(i):"simulator"===r?o.join(eX,"derived"):o.join(eX,"derived",r));return await ez(eZ,a,async()=>{if(K(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)){!function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return K(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new g("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."})}(a);try{C.rmSync(a,{recursive:!0,force:!0})}catch{}}let r=e4(a);if(r)return r;let i=function(){let e=o.dirname(v(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=o.join(t,"package.json");if(C.existsSync(e))return t;t=o.dirname(t)}return e}(),n=o.join(i,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!C.existsSync(n))throw new g("COMMAND_FAILED","iOS runner project not found",{projectPath:n});let s=function(e=process.env){let t=e0(e),r=e1(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),l=function(e=process.env,t=!1){if(!t)return[];let r=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",i=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",a=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",n=["CODE_SIGN_STYLE=Automatic"];return r&&n.push(`DEVELOPMENT_TEAM=${r}`),i&&n.push(`CODE_SIGN_IDENTITY=${i}`),a&&n.push(`PROVISIONING_PROFILE_SPECIFIER=${a}`),n}(process.env,"device"===e.kind),d="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var u;let r;await y("xcodebuild",["build-for-testing","-project",n,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",e5(e),"1","-destination",(u=e,r=e6(u),"simulator"===u.kind?`platform=${r} Simulator,id=${u.id}`:`generic/platform=${r}`),"-derivedDataPath",a,"COMPILER_INDEX_STORE_ENABLE=NO",...s,...d,...l],{detached:!0,onSpawn:e=>{eY.add(e),e.on("close",()=>{eY.delete(e)})},onStdoutChunk:e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)},onStderrChunk:e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)}})}catch(n){let e,r,i=n instanceof g?n:new g("COMMAND_FAILED",String(n)),a=(e=i.details?JSON.stringify(i.details):"",(r=`${i.message}
6
- ${e}`.toLowerCase()).includes("failed registering bundle identifier")||r.includes("app identifier")&&r.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":r.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":r.includes("no profiles for")||r.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":r.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 g("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:i.message,details:i.details,logPath:t.logPath,hint:a})}let c=e4(a);if(!c)throw new g("COMMAND_FAILED","Failed to locate .xctestrun after build");return c})}function e4(e){if(!C.existsSync(e))return null;let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let i of C.readdirSync(e,{withFileTypes:!0})){let a=o.join(e,i.name);if(i.isDirectory()){r.push(a);continue}if(i.isFile()&&i.name.endsWith(".xctestrun"))try{let e=C.statSync(a);t.push({path:a,mtimeMs:e.mtimeMs})}catch{}}}return 0===t.length?null:(t.sort((e,t)=>t.mtimeMs-e.mtimeMs),t[0]?.path??null)}async function e8(e,t,r){let i,a=o.dirname(e),n=r.replace(/[^a-zA-Z0-9._-]/g,"_"),s=o.join(a,`AgentDeviceRunner.env.${n}.json`),l=o.join(a,`AgentDeviceRunner.env.${n}.xctestrun`),d=await f("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new g("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{i=JSON.parse(d.stdout)}catch(t){throw new g("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},c=i.TestConfigurations;if(Array.isArray(c))for(let e of c){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(i))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),i[e]=t);C.writeFileSync(s,JSON.stringify(i,null,2));let p=await f("plutil",["-convert","xml1","-o",l,s],{allowFailure:!0});if(0!==p.exitCode)throw new g("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:p.stderr});return{xctestrunPath:l,jsonPath:s}}function e6(e){if("ios"!==e.platform)throw new g("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"tv"===e.target?"tvOS":"iOS"}function e5(e){return"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}let e9=new Map,e7=new Map;async function te(e,t){return await ez(e7,e.id,async()=>{var r,i;let a,n=e9.get(e.id);if(n){if((r=n.child.pid)&&O(r))return n;await tr(e.id,n)}await ("simulator"!==(i=e).kind?Promise.resolve():ts(i));let o=await e3(e,t),s=await eq(),{xctestrunPath:l,jsonPath:d}=await e8(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),{child:u,wait:p}=c("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",e5(e),"1","-destination-timeout",String(eU),"-xctestrun",l,"-destination",(a=e6(e),"simulator"===e.kind?`platform=${a} Simulator,id=${e.id}`:`platform=${a},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0});u.stdout?.on("data",e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)}),u.stderr?.on("data",e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)});let f={device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:d,testPromise:p,child:u,ready:!1};return e9.set(e.id,f),f})}async function tt(e){await ez(e7,e.deviceId,async()=>{await tr(e.deviceId,e)})}async function tr(e,t){let r=t??e9.get(e);if(r){try{await eF(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await to(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await to(r.child.pid,"SIGKILL"),eW(r.xctestrunPath),eW(r.jsonPath),e9.get(e)===r&&e9.delete(e)}}async function ti(e){await ez(e7,e,async()=>{await tr(e)})}async function ta(){let e=Array.from(e9.values()),t=Array.from(eY);await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGKILL"),eY.delete(e)}))}async function tn(){await ta();let e=Array.from(e9.keys());await Promise.allSettled(e.map(async e=>{await ti(e)}));let t=Array.from(eY);await Promise.allSettled(t.map(async e=>{try{await to(e.pid,"SIGTERM"),await to(e.pid,"SIGKILL")}finally{eY.delete(e)}}))}async function to(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await f("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function ts(e){await f("xcrun",eO(e,["bootstatus",e.id,"-b"]),{timeoutMs:eM})}async function tl(e,t,r,i,a,n){let o=await eF(e,t.port,r,i,a,t,n);return await td(o,t,i)}async function td(e,t,r){let i=await e.text(),a={};try{a=JSON.parse(i)}catch{throw new g("COMMAND_FAILED","Invalid runner response",{text:i})}if(!a.ok)throw new g("COMMAND_FAILED",a.error?.message??"Runner error",{runner:a,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,a.data??{}}async function tu(e,t,r={}){var i;if("ios"!==e.platform)throw new g("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new g("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(ev(r.requestId),"snapshot"===(i=t.command)||"screenshot"===i||"findText"===i||"alert"===i)?et(()=>(ev(r.requestId),tc(e,t,r)),{shouldRetry:e=>{ev(r.requestId);if(!(e instanceof g)||"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"))}}):tc(e,t,r)}async function tc(e,t,r={}){let i;ev(r.requestId);let a=ep(r.requestId);try{let n=(i=await te(e,r)).ready?ex:eM;return await tl(e,i,t,r.logPath,n,a)}catch(o){let n=o instanceof g?o:new g("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eg(n)&&i?.ready){ev(r.requestId),i?await tt(i):await ti(e.id),i=await te(e,r);let n=await eF(i.device,i.port,t,r.logPath,eM,void 0,a);return await td(n,i,r.logPath)}throw o}}function tp(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function tf(e){let t=new Set,r=[];for(let i of e)t.has(i)||(t.add(i),r.push(i));return r}let tm=/^-?\d+(\.\d+)?$/,th=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tw=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function tg(e){return"click"===e||"press"===e}function tI(e){let t=e.trim();return t.startsWith("@")||tm.test(t)?t:JSON.stringify(t)}function tA(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function tv(e,t){let r=t.flags??{};if(tg(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");return}"swipe"===t.command&&("number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern))}function ty(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",tA(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tA(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tA(t.launchUrl)))}function tb(e,t){let r=[],i={},a=tg(e)?th:"swipe"===e?tw:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tg(e)&&"--double-tap"===o){i.doubleTap=!0;continue}let s=a?.get(o);if(s&&n+1<t.length){let e=tN(t[n+1]);null!==e&&(i[s]=e),n+=1;continue}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(i.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:i}}function tN(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}class tS{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=tS.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:i,serial:a,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:I,count:A,intervalMs:v,holdMs:y,jitterPx:b,doubleTap:N,pauseMs:S,pattern:_}=e;return{platform:t,device:r,udid:i,serial:a,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:I,count:A,intervalMs:v,holdMs:y,jitterPx:b,doubleTap:N,pauseMs:S,pattern:_}}(t.flags),result:t.result}),k({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=o.dirname(t);C.existsSync(r)||C.mkdirSync(r,{recursive:!0});let i=function(e,t){let r=[],i=e.device.name.replace(/"/g,'\\"'),a=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${i}"${a} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(tg(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tI(r));let i=e.result?.refLabel;return"string"==typeof i&&i.trim().length>0&&t.push(tI(i)),tv(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tI(r)),tv(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tI(r));let i=e.result?.refLabel,a=e.positionals.slice(1).join(" ");return"string"==typeof i&&i.trim().length>0&&t.push(tI(i)),a&&t.push(tI(a)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],i=e.positionals?.[1];if(r&&i){if(t.push(tI(r)),t.push(tI(i)),i.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tI(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tI(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(tI(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tA(r)),ty(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tI(r));return tv(t,e),t.join(" ")}(n));return`${r.join("\n")}
7
- `}(e,this.buildOptimizedActions(e));C.writeFileSync(t,i)}catch{}}defaultTracePath(e){let t=tS.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return o.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return o.join(this.sessionsDir,tS.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return o.join(this.sessionsDir,tS.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return e.startsWith("~/")?o.join(P.homedir(),e.slice(2)):t&&!o.isAbsolute(e)?o.resolve(t,e):o.resolve(e)}resolveScriptPath(e){if(e.saveScriptPath)return tS.expandHome(e.saveScriptPath);C.existsSync(this.sessionsDir)||C.mkdirSync(this.sessionsDir,{recursive:!0});let t=tS.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return o.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let i=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(i.length>0&&(tg(r.command)||"fill"===r.command||"get"===r.command)){let e=i.join(" || ");if(tg(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let i=tp(r);if(i.length>0){t.push({...r,positionals:[e,i]});continue}}if("get"===r.command){let i=r.positionals?.[0];if("text"===i||"attrs"===i){t.push({...r,positionals:[i,e]});continue}}}if(tg(r.command)||"fill"===r.command||"get"===r.command){let i=r.result?.refLabel;"string"==typeof i&&i.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:i.trim()},result:{scope:i.trim()}})}t.push(r)}return t}}function t_(e,t){if(!e)return;let r=o.dirname(e);C.existsSync(r)||C.mkdirSync(r,{recursive:!0});let i={pid:t,startTime:M(t)??void 0,command:s(t)??void 0};C.writeFileSync(e,`${JSON.stringify(i)}
8
- `)}function tD(e){if(e&&C.existsSync(e))try{C.unlinkSync(e)}catch{}}async function tE(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tk(e){await new Promise(t=>setTimeout(t,e))}function tL(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],i="",a=i=>{(!(r.length>0)||r.some(e=>i.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(i,t.redactionPatterns))};return{onChunk:e=>{let t=`${i}${e}`.split("\n");for(let e of(i=t.pop()??"",t))a(`${e}
9
- `)},flush:()=>{i&&(a(i),i="")}}}function tO(e,t,r){let i=e.stdout,a=e.stderr;return i&&a?(i.setEncoding("utf8"),a.setEncoding("utf8"),i.on("data",r.writer.onChunk),a.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(i=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),i({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function tM(e,t){let r=(await f("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tx(e,t,r,i,a){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await tM(e,t);if(!d){await tk(1e3);continue}let u=m("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=tL(r,{redactionPatterns:i});o=tO(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&t_(a,u.pid);let p=await o;if(tD(a),n=void 0,o=void 0,l)break;0!==p.exitCode&&(s="failed"),await tk(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tD(a)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tE(o),n&&!n.killed&&n.kill("SIGKILL"),await tE(d),tD(a)}}}async function tC(e,t,r,i){let a="active",n=m("log",["stream","--style","compact","--predicate",`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`],{stdio:["ignore","pipe","pipe"]}),o=tL(t,{redactionPatterns:r});"number"==typeof n.pid&&t_(i,n.pid);let s=tO(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(a="failed"),tD(i),e));return{backend:"ios-simulator",getState:()=>a,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tE(s),n.killed||n.kill("SIGKILL"),await tE(s),tD(i)}}}async function tR(e,t,r,i){let a="active",n=m("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tL(t,{redactionPatterns:r});"number"==typeof n.pid&&t_(i,n.pid);let s=tO(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(a="failed"),tD(i),e));return{backend:"ios-device",getState:()=>a,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tE(s),n.killed||n.kill("SIGKILL"),await tE(s),tD(i)}}}function tP(e,t){let r=process.env[e];if(!r)return t;let i=Number.parseInt(r,10);return Number.isInteger(i)&&i>0?i:t}function tT(e){let t=o.dirname(e);C.existsSync(t)||C.mkdirSync(t,{recursive:!0}),function(e,t){if(C.existsSync(e)&&!(C.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,i=`${e}.${r}`;C.existsSync(t)&&(C.existsSync(i)&&C.unlinkSync(i),C.renameSync(t,i))}}(e,{maxBytes:tP("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:tP("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function t$(e,t,r,i){tT(r);let a=C.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await tR(e.id,a,n,i):await tC(t,a,n,i);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new g("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await tx(e.id,t,a,n,i)}throw a.end(),new g("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function tU(e){await e.stop(),await tE(e.wait)}async function tF(e,t){let r={},i=[];if(t||i.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await f("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await f("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await f("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await f("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}return{checks:r,notes:i}}function tV(e){let t=o.dirname(e),r=o.basename(e);C.existsSync(t)||C.mkdirSync(t,{recursive:!0}),C.existsSync(e)?C.truncateSync(e,0):C.writeFileSync(e,"","utf8");let i=0;for(let e of C.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let a=e.slice(r.length+1);if(/^\d+$/.test(a))try{C.unlinkSync(o.join(t,e)),i+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:i}}let tG=new Map;function tj(e){let t=tG.get(e);if(t&&(clearTimeout(t.timer),tG.delete(e),t.deleteAfterDownload))try{C.rmSync(t.artifactPath,{force:!0})}catch{}}let tB=new Map;function tq(e,t){let r=tB.get(e);if(!r)throw new g("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new g("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function tH(e){let t=tB.get(e);t&&(clearTimeout(t.timer),tB.delete(e),C.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function tW(e){let t=await tz(e);await f("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=o.join(e.tempDir,t);if(!C.existsSync(r))throw new g("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function tz(e){let t=await f("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new g("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new g("INVALID_ARGS","Uploaded app bundle archive is empty");let i=r.map(e=>(function(e){if(e.includes("\0"))throw new g("INVALID_ARGS",`Invalid archive entry: ${e}`);if(o.posix.isAbsolute(e))throw new g("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=o.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new g("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t})(e)),a=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let i=[...r];if("ios"===t){let e=i.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new g("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new g("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===i.length)return i[0];throw new g("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${i.join(", ")}`)}(i,e.platform);if(!i.some(e=>e===a||e.startsWith(`${a}/`)))throw new g("INVALID_ARGS",`Uploaded archive must contain a top-level "${a}" bundle`);for(let e of i){var n=e,s=a;if(n!==s&&!n.startsWith(`${s}/`))throw new g("INVALID_ARGS",`Archive entry must stay inside top-level "${s}" bundle: ${n}`)}for(let t of(await f("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean)){let e=t[0];if("l"===e||"h"===e)throw new g("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links")}return a}let tJ=ey(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function tK(e,t){return new Promise((r,i)=>{let a,n=C.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},s=!1,l=0,d=e=>{if(!s){if(s=!0,a&&clearTimeout(a),e){n.destroy(),C.rmSync(t,{force:!0}),i(e);return}r()}},u=()=>{a&&clearTimeout(a),a=setTimeout(()=>{let e=new g("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:tJ});o(e),n.destroy(e),d(e)},tJ)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((l+=t)>0x80000000){let e=new g("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new g("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",d),n.on("finish",()=>d()),u(),e.pipe(n)})}async function tX(e){let t,r=e.headers["x-artifact-type"],i=e.headers["x-artifact-filename"];if(!r||!i)throw new g("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new g("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new g("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let a=function(e){let t=e.trim(),r=o.basename(t);if(!r||"."===r||".."===r)throw new g("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(i),n=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),C.mkdtempSync(o.join(P.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=o.join(n,a);return await tK(e,t),{artifactPath:t,tempDir:n}}let t=o.join(n,"artifact.tar");await tK(e,t);let i=await tW({archivePath:t,tempDir:n,platform:"ios",expectedRootName:a});return C.rmSync(t,{force:!0}),{artifactPath:i,tempDir:n}}catch(e){throw C.rmSync(n,{recursive:!0,force:!0}),e}}let tZ=new Set(["agent_device.command","agent-device.command"]),tY=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),tQ=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),t0={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},t1=new Set([...tZ,...tY,...tQ,...Object.keys(t0)]);function t2(e,t,r,i){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:i}}}function t3(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function t4(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function t8(e,t){let r="string"==typeof t.authorization?t.authorization:"",i=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,a="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??a??i??""}function t6(e,t){let r=e[t];return"string"==typeof r?r:void 0}function t5(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function t9(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=b(new g("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:t2(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=b(new g(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:t2(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=l(r.tenantId);if(!e){let e=b(new g("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:t2(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function t7(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",i=o.isAbsolute(t)?t:o.resolve(t);try{e=await import(w(i).href)}catch(e){throw new g("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:i,error:e instanceof Error?e.message:String(e)})}let a=e[r];if("function"!=typeof a)throw new g("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:i,exportName:r});return a}async function re(e){let t=await t7(),{handleRequest:r,token:i}=e;return F.createServer((e,a)=>{if("GET"===e.method&&"/health"===e.url){a.statusCode=200,a.setHeader("content-type","application/json"),a.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rt(e,a,t,i);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rr(e,a,t,i);if("POST"!==e.method||"/rpc"!==e.url){a.statusCode=404,a.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{a.headersSent||t3(a,t2(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let i,o;try{i=JSON.parse(n)}catch{t3(a,t2(null,-32700,"Parse error"),400);return}if("2.0"!==i.jsonrpc||"string"!=typeof i.method)return void t3(a,t2(i.id??null,-32600,"Invalid Request"),400);if(!t1.has(i.method))return void t3(a,t2(i.id??null,-32601,`Method not found: ${i.method}`),404);if(!i.params||"object"!=typeof i.params)return void t3(a,t2(i.id??null,-32602,"Invalid params"),400);try{var s;let n=i.params,l=function(e,t,r){if(tZ.has(e))return{token:t8(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(tY.has(e)){let e,i=t6(t,"platform");if("ios"!==i&&"android"!==i)throw new g("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:t8(t,r),session:t6(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:i},meta:{requestId:t6(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new g("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new g("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,i={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new g("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new g("INVALID_ARGS","Invalid params: source.headers values must be strings");i[e]=t}}return Object.keys(i).length>0?{kind:"url",url:e,headers:i}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new g("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new g("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:t5(t,"retentionMs")}}}if(tQ.has(e)){let e=t6(t,"materializationId")?.trim();if(!e)throw new g("INVALID_ARGS","Invalid params: materializationId is required");return{token:t8(t,r),session:t6(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:t6(t,"requestId"),materializationId:e}}}let i=t0[e];if(i)return{token:t8(t,r),session:t6(t,"session")??"default",command:i,positionals:[],meta:{tenantId:t6(t,"tenantId")??t6(t,"tenant"),runId:t6(t,"runId"),leaseId:t6(t,"leaseId"),leaseTtlMs:t5(t,"ttlMs"),leaseBackend:t6(t,"backend")}};throw new g("INVALID_ARGS",`Method not found: ${e}`)}(i.method,n,e.headers);if(s=i.method,tZ.has(s)&&("string"!=typeof l.command||0===l.command.length))return void t3(a,t2(i.id??null,-32602,"Invalid params: command is required"),400);o=es(l.meta?.requestId,i.id),l.meta={...l.meta,requestId:o},el(o);let d=()=>{a.writableFinished||ed(o)};e.on("aborted",d),a.on("close",d);let u=await t9(t,{headers:e.headers,rpcRequest:i,daemonRequest:l});if(!u.ok)return void t3(a,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void t3(a,{jsonrpc:"2.0",id:i.id??null,result:c});t3(a,t2(i.id??null,-32e3,c.error.message,c.error),t4(c.error.code))}catch(t){let e=b(t);t3(a,t2(i.id??null,-32e3,e.message,e),t4(e.code))}finally{eu(o)}})})}async function rt(e,t,r,i){try{var a;let n,o,s=t8({},e.headers),l=ri(s,i);if(l){t.statusCode=t4(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await t9(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:s,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let u=await tX(e),c=(a={artifactPath:u.artifactPath,tempDir:u.tempDir,tenantId:d.tenantId},n=p.randomUUID(),o=setTimeout(()=>{tH(n)},3e5),tB.set(n,{artifactPath:a.artifactPath,tempDir:a.tempDir,tenantId:a.tenantId,timer:o}),n);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:c}))}catch(r){let e=b(r);t.statusCode=t4(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rr(e,t,r,i){let a=e.url?.slice("/upload/".length)??"";if(!a){t.statusCode=400,t.end("Missing artifact id");return}try{let n=t8({},e.headers),o=ri(n,i);if(o){t.statusCode=t4(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await t9(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[a]}});if(!s.ok){t.statusCode=s.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.response.error?.data?.message??s.response.error?.message??"Unauthorized"}));return}let l=function(e,t){let r=tG.get(e);if(!r)throw new g("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new g("UNAUTHORIZED","Artifact belongs to a different tenant");if(!C.existsSync(r.artifactPath))throw tj(e),new g("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(a,s.tenantId),d=C.createReadStream(l.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),l.fileName&&t.setHeader("content-disposition",`attachment; filename="${l.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=b(e);t.statusCode=t4(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&tj(a)}),d.pipe(t)}catch(r){let e=b(r);t.statusCode=t4(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function ri(e,t){return t&&e!==t?b(new g("UNAUTHORIZED","Invalid token")):null}function ra(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rn(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function ro(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new g("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rs{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=ro(e.backend),r=l(e.tenantId);if(!r)throw new g("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let i=ra(e.runId);if(!i)throw new g("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let a=this.resolveLeaseTtlMs(e.ttlMs),n=this.bindingKey(r,i,t),o=this.runBindings.get(n);if(o){let e=this.leases.get(o);if(e)return this.refreshLease(e,a);this.runBindings.delete(n)}this.enforceCapacity(t);let s=this.now(),d={leaseId:p.randomBytes(16).toString("hex"),tenantId:r,runId:i,backend:t,createdAt:s,heartbeatAt:s,expiresAt:s+a};return this.leases.set(d.leaseId,d),this.runBindings.set(n,d.leaseId),{...d}}heartbeatLease(e){let t=rn(e.leaseId);if(!t)throw new g("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new g("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let i=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,i)}releaseLease(e){let t=rn(e.leaseId);if(!t)throw new g("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=ro(e.backend),r=l(e.tenantId);if(!r)throw new g("INVALID_ARGS","tenant isolation requires tenant id.");let i=ra(e.runId);if(!i)throw new g("INVALID_ARGS","tenant isolation requires run id.");let a=rn(e.leaseId);if(!a)throw new g("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(a);if(!n)throw new g("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==i)throw new g("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new g("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new g("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),i={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(i.leaseId,i),this.runBindings.set(this.bindingKey(i.tenantId,i.runId,i.backend),i.leaseId),{...i}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let i=l(t),a=ra(r);if(t&&!i)throw new g("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!a)throw new g("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(i&&e.tenantId!==i||a&&e.runId!==a)throw new g("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}function rl(e,t){return["-s",e.id,...t]}async function rd(){if(!await A("adb"))throw new g("TOOL_MISSING","adb not found in PATH")}function ru(e,t){let r=`${e}
10
- ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function rc(e){await new Promise(t=>setTimeout(t,e))}function rp(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let i=r[1]?.toLowerCase(),a=r[2]??"";return"http"!==i&&"https"!==i&&"ws"!==i&&"wss"!==i&&"ftp"!==i&&"ftps"!==i||a.startsWith("//")}function rf(e,t){let r,i=e?.trim();return i?i:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let rm=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function rh(e){return`${e.stdout}
11
- ${e.stderr}`}function rw(e,t){return["-s",e,...t]}function rg(e){return e.startsWith("emulator-")}function rI(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function rA(e,t=Y){return f("adb",rw(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function rv(e,t){let r=t.replace(/_/g," ").trim();if(!rg(e))return r||e;let i=await ry(e);return i?i.replace(/_/g," "):r||e}async function ry(e){for(let t of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let r=await f("adb",rw(e,["shell","getprop",t]),{allowFailure:!0,timeoutMs:1e4}),i=r.stdout.trim();if(0===r.exitCode&&i.length>0)return i}let t=await f("adb",rw(e,["emu","avd","name"]),{allowFailure:!0,timeoutMs:1e4}),r=t.stdout.trim();if(0===t.exitCode&&r.length>0)return r}async function rb(e,t){let r=rh(await f("adb",rw(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:Y})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function rN(e){return(await Promise.all(rm.map(async t=>await rb(e,t)))).some(e=>!0===e)}async function rS(e){var t;let r;return"tv"===((r=rh(await f("adb",rw(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:Y})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await rN(e)?"tv":(t=rh(await f("adb",rw(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:Y})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function r_(e={}){if(!await A("adb"))throw new g("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ek(void 0),r=(await rD()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,i,a]=await Promise.all([rv(e,t),rO(e),rS(e)]);return{platform:"android",id:e,name:r,kind:rg(e)?"emulator":"device",target:a,booted:i}}))}async function rD(){return(await f("adb",["devices","-l"],{timeoutMs:Y})).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 rE(){let e=await f("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:Y});if(0!==e.exitCode)throw new g("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 rk(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await rL(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 g("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 rL(e,t){let r=rI(e);for(let e of(await rD()).filter(e=>(!t||e.serial===t)&&rg(e.serial)))if(rI(e.rawModel)===r||rI(await rv(e.serial,e.rawModel))===r)return e.serial}async function rO(e){try{let t=await rA(e);return"1"===t.stdout.trim()}catch{return!1}}async function rM(e){var t,r;let i,a=e.avdName.trim();if(!a)throw new g("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await A("adb"))throw new g("TOOL_MISSING","adb not found in PATH");if(!await A("emulator"))throw new g("TOOL_MISSING","emulator not found in PATH");let o=await rE(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let i=rI(t);return e.find(e=>rI(e)===i)}(o,a);if(!s)throw new g("DEVICE_NOT_FOUND",`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:a,availableAvds:o,hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=Date.now(),d=(t=await r_(),r=e.serial,i=rI(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&rI(e.name)===i));if(!d){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),u("emulator",t)}let c=d??await rk({avdName:s,serial:e.serial,timeoutMs:n}),p=Math.max(1e3,n-(Date.now()-l));await rx(c.id,p);let f=(await r_()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function rx(e,t=6e4){let r,i=Q.fromTimeoutMs(t),a=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await ee(async({deadline:a})=>{if(a?.isExpired())throw n=!0,new g("COMMAND_FAILED","Android boot deadline exceeded",{serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),message:"timeout"});let o=Math.max(1e3,a?.remainingMs()??t),s=await rA(e,Math.min(o,Y));if(r=s,"1"!==s.stdout.trim())throw new g("COMMAND_FAILED","Android device is still booting",{serial:e,stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode})},{maxAttempts:a,baseDelayMs:1e3,maxDelayMs:1e3,jitter:0,shouldRetry:e=>{let t=eh({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:i,phase:"boot",classifyReason:e=>eh({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let a=h(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eh({error:c,stdout:o,stderr:s,context:{platform:"android",phase:"boot"}});"BOOT_COMMAND_FAILED"===d&&"Android device is still booting"===a.message&&(d="ANDROID_BOOT_TIMEOUT");let u={serial:e,timeoutMs:t,elapsedMs:i.elapsedMs(),reason:d,hint:ew(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new g("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===a.code)throw new g("TOOL_MISSING",a.message,{...u,...a.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new g("COMMAND_FAILED",a.message,{...u,...a.details??{}});throw new g(a.code,a.message,{...u,...a.details??{}},a.cause)}}let rC=/\.(?:apk|aab)$/i,rR=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function rP(e){var t,r;let i=e.trim();return 0===i.length?"other":rC.test(i)?i.includes("/")||i.includes("\\")||i.startsWith(".")||i.startsWith("~")||(t=i,!rR.test(t))?"binary":"package":(r=i,rR.test(r))?"package":"other"}function rT(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let r$=[".zip",".tar",".tar.gz",".tgz"],rU=ey(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),rF=["1","true","yes","on"];async function rV(e){let t=[];try{let r=await rG(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let i=await rW(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:i.archivePath,installablePath:i.installablePath,cleanup:async()=>{await rX(t)}}}catch(e){throw await rX(t),e}}async function rG(e,t){if("path"===e.kind){var r;return{localPath:(r=e.path).startsWith("~")?"~"===r?P.homedir():r.startsWith("~/")?o.join(P.homedir(),r.slice(2)):r:r,cleanup:async()=>{}}}let i=await L.mkdtemp(o.join(P.tmpdir(),"agent-device-source-"));try{return{localPath:await rj(i,e.url,e.headers,t),cleanup:async()=>{await L.rm(i,{recursive:!0,force:!0})}}}catch(e){throw await L.rm(i,{recursive:!0,force:!0}),e}}async function rj(e,t,r,i){let a;try{a=new URL(t)}catch{throw new g("INVALID_ARGS",`Invalid source URL: ${t}`)}await rB(a);let n=i?.signal;if(n?.aborted)throw new g("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let s=new AbortController,l=()=>{s.abort(n?.reason)};n?.addEventListener("abort",l,{once:!0});let d=i?.downloadTimeoutMs??rU,u=setTimeout(()=>{s.abort(Error("download timeout"))},d);try{let t=await fetch(a,{headers:r,redirect:"follow",signal:s.signal});if(!t.ok)throw new g("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:a.toString()});let i=function(e,t){let r=e.headers.get("content-disposition"),i=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),a=i?.[1]?.trim();if(a)return o.basename(a);let n=o.basename(t.pathname);return n||"downloaded-artifact.bin"}(t,a),n=o.join(e,i),l=t.body;if(!l)throw new g("COMMAND_FAILED","Download response body was empty",{url:a.toString()});let d=await L.open(n,"w");try{for await(let e of l)await d.write(e)}finally{await d.close()}return n}catch(e){if(n?.aborted)throw new g("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(s.signal.aborted)throw new g("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:a.toString()},e);throw e}finally{n?.removeEventListener("abort",l),clearTimeout(u)}}async function rB(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new g("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!rF.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||rH(t))throw new g("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await a.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>rH(e.address)))throw new g("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function rq(e){var t,r,i,a;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(i=o,a=s,("expo.dev"===i||!!i.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(a))}function rH(e){let t,r=T.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,i]=t;return 10===r||127===r||169===r&&254===i||172===r&&!!(i>=16)&&!!(i<=31)||192===r&&168===i}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function rW(e,t){let r=await L.stat(e).catch(()=>null);if(!r)throw new g("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&rK(e)){if(!t.allowArchiveExtraction)throw new g("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await rJ(e);return t.registerCleanup(r.cleanup),await rW(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await rz(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new g("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let i=await rz(e,(e,t)=>t.isFile()&&rK(e));if(1===i.length){if(!t.allowArchiveExtraction)throw new g("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:i[0]});let e=await rJ(i[0]);return t.registerCleanup(e.cleanup),await rW(e.outputPath,{...t,archivePath:t.archivePath??i[0]})}if(i.length>1)throw new g("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:i})}throw new g("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function rz(e,t){let r=[],i=[{path:e,depth:0}];for(;i.length>0;){let e=i.shift();if(!e)continue;let a=await L.readdir(e.path,{withFileTypes:!0});for(let n of(a.sort((e,t)=>e.name.localeCompare(t.name)),a)){let a=o.join(e.path,n.name);if(t(a,n)){r.push(a);continue}n.isDirectory()&&e.depth<5&&i.push({path:a,depth:e.depth+1})}}return r}async function rJ(e){let t=await L.mkdtemp(o.join(P.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await f("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await f("tar",["-xzf",e,"-C",t]):await f("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await L.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await L.rm(t,{recursive:!0,force:!0}),e}}function rK(e){let t=e.toLowerCase();return r$.some(e=>t.endsWith(e))}async function rX(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let rZ=new W("utf-16le");async function rY(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let i=await rQ(e,r);if(!i)continue;let a=(t=i).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let i=e.readUInt16LE(r),a=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===i)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),i=e.readUInt32LE(20),a=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=i+e.readUInt32LE(t);n.push(a?function(e,t){let[,r]=r0(e,t),[i,a]=r0(e,t+r),n=t+r+a;return e.subarray(n,n+i).toString("utf8")}(e,o):function(e,t){let[r,i]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),a=t+i;return rZ.decode(e.subarray(a,a+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===i&&t){let i=function(e,t,r,i){if(r<36||t+r>e.length||"manifest"!==i[e.readUInt32LE(t+20)])return;let a=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+a;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==i[e.readUInt32LE(r+4)])continue;let a=e.readUInt32LE(r+8);if(0xffffffff!==a)return i[a];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return i[l];break}}(e,r,a,t);if(i)return i}r+=n}}(t);if(a)return a}return await r1(e)}async function rQ(e,t){try{let r=await f("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function r0(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function r1(e){let t=await r2();if(!t)return;let r=await f(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let i=r.stdout.match(/package:\s+name='([^']+)'/);return i?.[1]}async function r2(){if(void 0!==e)return e??void 0;let t=process.env.ANDROID_HOME?.trim();if(!t){e=null;return}try{let r=o.join(t,"build-tools");for(let t of(await n.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let i=o.join(r,t,"aapt");try{return await n.access(i),e=i,i}catch{}}}catch{}e=null}async function r3(e,t){let r="url"===e.kind&&rq(e.url),i=await rV({source:e,isInstallablePath:(e,t)=>{var r;let i;return t.isFile()&&(r=e,".apk"===(i=o.extname(r).toLowerCase())||".aab"===i)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),a=t?.resolveIdentity===!1?{}:await r4(i.installablePath);return{archivePath:i.archivePath,installablePath:i.installablePath,packageName:a.packageName,cleanup:i.cleanup}}async function r4(e){let t=o.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await rY(e)}}let r8={settings:{type:"intent",value:"android.settings.SETTINGS"}},r6="android.intent.category.LAUNCHER",r5="android.intent.category.LEANBACK_LAUNCHER",r9="android.intent.category.DEFAULT";async function r7(e,t){let r=t.trim();if("package"===rP(r))return{type:"package",value:r};let i=r8[r.toLowerCase()];if(i)return i;let a=(await f("adb",rl(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===a.length)return{type:"package",value:a[0]};if(a.length>1)throw new g("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:a});throw new g("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function ie(e,t="all"){let r=await it(e);return("user-installed"===t?(await ii(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:ia(e)}))}async function it(e){let t=new Set;for(let r of ir(e,{includeFallbackWhenUnknown:!0})){let i=await f("adb",rl(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===i.exitCode&&0!==i.stdout.trim().length)for(let e of i.stdout.split("\n")){let r=e.trim();if(!r)continue;let i=r.split(/\s+/)[0],a=i.includes("/")?i.split("/")[0]:i;a&&t.add(a)}}return t}function ir(e,t={}){return"tv"===e.target?[r5]:"mobile"===e.target?[r6]:t.includeFallbackWhenUnknown?[r6,r5]:[r6]}async function ii(e){return(await f("adb",rl(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function ia(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),i=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let a=r[e];if(!t.has(a)){i=a;break}}return i.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function io(e){let t=await is(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await is(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function is(e,t){for(let r of t){let t=function(e){for(let t of[/mCurrentFocus=Window\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mFocusedApp=AppWindowToken\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/,/ResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/]){let r=t.exec(e);if(r)return{package:r[1],activity:r[2]}}return null}((await f("adb",rl(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function il(e,t,r){e.booted||await rx(e.id);let i=t.trim();if(rp(i)){if(r)throw new g("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await f("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",i]));return}let a=await r7(e,t),n=ir(e)[0]??r6;if("intent"===a.type){if(r)throw new g("INVALID_ARGS","Activity override requires a package name, not an intent");await f("adb",rl(e,["shell","am","start","-W","-a",a.value]));return}if(r){let t=r.includes("/")?r:`${a.value}/${r.startsWith(".")?r:`.${r}`}`;await f("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-n",t]));return}let o=await f("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-p",a.value]),{allowFailure:!0});if(0===o.exitCode&&!iu(o.stdout,o.stderr))return;let s=await id(e,a.value);if(!s)throw new g("COMMAND_FAILED",`Failed to launch ${a.value}`,{stdout:o.stdout,stderr:o.stderr});await f("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-n",s]))}async function id(e,t){for(let r of Array.from(new Set(ir(e,{includeFallbackWhenUnknown:!0})))){let i=await f("adb",rl(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==i.exitCode)continue;let a=ic(i.stdout);if(a)return a}return null}function iu(e,t){let r=`${e}
12
- ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)}function ic(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}async function ip(e){e.booted||await rx(e.id)}async function im(e,t){if("settings"===t.trim().toLowerCase())return void await f("adb",rl(e,["shell","am","force-stop","com.android.settings"]));let r=await r7(e,t);if("intent"===r.type)throw new g("INVALID_ARGS","Close requires a package name, not an intent");await f("adb",rl(e,["shell","am","force-stop",r.value]))}async function ih(e,t){let r=await r7(e,t);if("intent"===r.type)throw new g("INVALID_ARGS","App uninstall requires a package name, not an intent");let i=await f("adb",rl(e,["uninstall",r.value]),{allowFailure:!0});if(0!==i.exitCode){let e=`${i.stdout}
13
- ${i.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new g("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return{package:r.value}}let iw=null;async function ig(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(iw?.key===e)return iw.invocation;if(await A("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return iw={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new g("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await L.access(t)}catch{throw new g("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return iw={key:e,invocation:r},r}async function iI(e){let t=await ig();await f(t.cmd,[...t.prefixArgs,...e])}async function iA(e,t){let r,i=await L.mkdtemp(o.join(P.tmpdir(),"agent-device-aab-")),a=o.join(i,"bundle.apks"),n=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await iI(["build-apks","--bundle",t,"--output",a,"--mode",n]),await iI(["install-apks","--apks",a,"--device-id",e.id])}finally{await L.rm(i,{recursive:!0,force:!0})}}async function iv(e,t){".aab"===o.extname(t).toLowerCase()?await iA(e,t):await f("adb",rl(e,["install","-r",t]))}async function iy(e){return new Set((await f("adb",rl(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function ib(e,t){let r=Array.from(await iy(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function iN(e,t){e.booted||await rx(e.id),await iv(e,t)}async function iS(e,t,r){let i=r?void 0:await iy(e);return await iN(e,t),r??(i?await ib(e,i):void 0)}async function i_(e,t){e.booted||await rx(e.id);let r=await r3({kind:"path",path:t});try{let t=await iS(e,r.installablePath,r.packageName),i=t?ia(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:i,launchTarget:t}}finally{await r.cleanup()}}async function iD(e,t,r){e.booted||await rx(e.id);let{package:i}=await ih(e,t),a=await r3({kind:"path",path:r},{resolveIdentity:!1});try{return await iN(e,a.installablePath),{package:i}}finally{await a.cleanup()}}function iE(e){let t=ik(e),r=e=>{let r=iL(t,e);if(null!==r)return"true"===r};return{text:iL(t,"text"),desc:iL(t,"content-desc"),resourceId:iL(t,"resource-id"),className:iL(t,"class"),bounds:iL(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function ik(e){let t=new Map,r=e.indexOf(" "),i=e.lastIndexOf(">");if(r<0||i<=r)return t;let a=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<i;){for(;n<i;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=i)break;let r=e[n];if("/"===r||">"===r)break;a.lastIndex=n;let o=a.exec(e);if(!o)break;t.set(o[1],o[3]),n=a.lastIndex}return t}function iL(e,t){return e.get(t)??null}function iO(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),i=Number(t[2]);return{x:r,y:i,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-i)}}function iM(e){return e?e.toLowerCase():""}function ix(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function iC(e,t={}){return function(e,t,r){let i=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],i=/<node\b[^>]*>|<\/node>/g,a=i.exec(e);for(;a;){let t=a[0];if(t.startsWith("</node")){r.length>1&&r.pop(),a=i.exec(e);continue}let n=iE(t),o=iO(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),a=i.exec(e)}return t}(e),a=[],n=!1,o=r.depth??1/0,s=r.scope?function(e,t){let r=t.toLowerCase(),i=[...e.children];for(;i.length>0;){let e=i.shift(),t=e.label?.toLowerCase()??"",a=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||a.includes(r)||n.includes(r))return e;i.push(...e.children)}return null}(i,r.scope):null,l=s?[s]:i.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,t,i,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,I,A,v,y,b,N,S;if(a.length>=800){n=!0;return}if(t>o)return;let _=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,I=iM(d.type),A=!!(d.label&&d.label.trim().length>0),v=!!(d.identifier&&d.identifier.trim().length>0),y=A&&!ix(d.label??""),b=v&&!ix(d.identifier??""),N=(g=(w=I).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,S="imageview"===I||"imagebutton"===I,p.interactiveOnly?!!d.hittable||!!(y||b)&&!S&&(!N||!!h)&&(f||m||h):p.compact?y||b||!!d.hittable:!N&&!S||!!d.hittable||!!y||!!b&&!!m||m),D=i;_&&(D=a.length,a.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:i}));let E=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=iM(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let r of e.children)if(c(r,t+1,D,E,k),n)return};for(let e of l)if(c(e,0,void 0,!1,!1),n)break;return n?{nodes:a,truncated:n}:{nodes:a}}(await iT(e),0,t)}let iR=Buffer.from([137,80,78,71,13,10,26,10]);async function iP(e,t){let r=await f("adb",rl(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new g("COMMAND_FAILED","Failed to capture screenshot");let i=r.stdoutBuffer.indexOf(iR);if(i<0)throw new g("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let a=function(e,t){let r=t+iR.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),i=r+4,a=e.toString("ascii",i,i+4),n=r+12+t;if(n>e.length)break;if("IEND"===a)return n;r=n}return null}(r.stdoutBuffer,i);if(!a)throw new g("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await L.writeFile(t,r.stdoutBuffer.subarray(i,a))}async function iT(e){return et(()=>i$(e),{shouldRetry:iF})}async function i$(e){var t,r,i;let a,n,o=await f("adb",rl(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=iU(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await f("adb",rl(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,i=l.stderr,a=`${r}
14
- ${i}`,n=/dumped to:\s*(\S+)/i.exec(a),n?.[1]??t),u=await f("adb",rl(e,["shell","cat",d])),c=iU(u.stdout,u.stderr);if(!c)throw new g("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return c}function iU(e,t){let r=`${e}
15
- ${t}`,i=r.indexOf("<?xml"),a=i>=0?i:r.indexOf("<hierarchy");if(a<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<a)return null;let o=r.slice(a,n+12).trim();return o.length>0?o:null}function iF(e){if(!(e instanceof g)||"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 iV(e,t,r){await f("adb",rl(e,["shell","input","tap",String(t),String(r)]))}async function iG(e,t,r,i,a,n=250){await f("adb",rl(e,["shell","input","swipe",String(t),String(r),String(i),String(a),String(n)]))}async function ij(e){await f("adb",rl(e,["shell","input","keyevent","4"]))}async function iB(e){await f("adb",rl(e,["shell","input","keyevent","3"]))}async function iq(e){await f("adb",rl(e,["shell","input","keyevent","187"]))}async function iH(e,t,r,i=800){await f("adb",rl(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(i)]))}async function iW(e,t){let r=iQ(t);if(!r||"ok"!==await i0(e,t))try{let r=t.replace(/ /g,"%s");await f("adb",rl(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof g)||"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 g("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 iz(e,t,r){await iV(e,t,r)}async function iJ(e,t,r,i){let a=Array.from(i).length,n=iQ(i),o=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];n||(o.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),o.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96}));let s=null;for(let n of o){var l,d;await iz(e,t,r);let o=(l=a+n.clearPadding,d=n.minClear,Math.max(d,Math.min(n.maxClear,l)));if(await i1(e,o),"input_text"===n.strategy)await iW(e,i);else if("clipboard_paste"===n.strategy){if("ok"!==await i0(e,i))continue}else await iY(e,i,1,15);if((s=await i2(e,t,r))===i)return}throw new g("COMMAND_FAILED","Android fill verification failed",{expected:i,actual:s??null})}async function iK(e,t,r=.6){let{width:i,height:a}=await iZ(e),n=Math.floor(i*r),o=Math.floor(a*r),s=Math.floor(i/2),l=Math.floor(a/2),d=s,u=l,c=s,p=l;switch(t){case"up":u=l-Math.floor(o/2),p=l+Math.floor(o/2);break;case"down":u=l+Math.floor(o/2),p=l-Math.floor(o/2);break;case"left":d=s-Math.floor(n/2),c=s+Math.floor(n/2);break;case"right":d=s+Math.floor(n/2),c=s-Math.floor(n/2);break;default:throw new g("INVALID_ARGS",`Unknown direction: ${t}`)}await f("adb",rl(e,["shell","input","swipe",String(d),String(u),String(c),String(p),"300"]))}async function iX(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await iT(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new g("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(function(e,t){let r=t.toLowerCase(),i=/<node[^>]+>/g,a=i.exec(e);for(;a;){let t=ik(a[0]),n=(iL(t,"text")??"").toLowerCase(),o=(iL(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=iO(iL(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}a=i.exec(e)}return null}(r,t))return;await iK(e,"down",.5)}throw new g("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function iZ(e){let t=(await f("adb",rl(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new g("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function iY(e,t,r,i){let a=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=a){let r=n.slice(t,t+a).join("");await iW(e,r),i>0&&t+a<n.length&&await rc(i)}}function iQ(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 i0(e,t){let r=await f("adb",rl(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":ru(r.stdout,r.stderr)?"unsupported":0===(await f("adb",rl(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await f("adb",rl(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function i1(e,t){let r=Math.max(0,t);await f("adb",rl(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let i=Math.min(24,r-t);await f("adb",rl(e,["shell","input","keyevent",...Array(i).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function i2(e,t,r){let i,a=await iT(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(i=n.exec(a));){let e=iE(i[0]),a=iO(e.bounds);if(!a)continue;let n=e.className??"",d=(e.text??"").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),u=e.focused??!1;if(!d)continue;let c=Math.max(1,a.width*a.height),p=t>=a.x&&t<=a.x+a.width&&r>=a.y&&r<=a.y+a.height;if(u&&i3(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&i3(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}p&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function i3(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function i4(e){let t=await f("adb",rl(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new g("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],i=r[2]?.toLowerCase();e&&("true"===i||"false"===i)&&t.set(e,"true"===i)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let i=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),a=i.length>0?i[i.length-1]?.[1]:void 0,n=a?`0x${a.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let i=4080&t;return 32===i||208===i?"email":128===i||224===i||144===i?"password":"text"}(n):void 0}}(t.stdout)}async function i8(e){let t=await i4(e),r=t,i=0;for(;r.visible&&i<2;)await ij(e),i+=1,await rc(120),r=await i4(e);return{attempts:i,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function i6(e){let t,r;return(r=(t=(await i9(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?r[1]??"":"null"===t.trim().toLowerCase()?"":t}async function i5(e,t){await i9(e,["shell","cmd","clipboard","set","text",t],"write")}async function i9(e,t,r){let i=await f("adb",rl(e,t),{allowFailure:!0});if(ru(i.stdout,i.stderr))throw new g("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==i.exitCode)throw new g("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return i.stdout}let i7=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function ae(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new g("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function at(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 g("INVALID_ARGS",`permission setting requires a target: ${i7.join("|")}`)}function ar(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new g("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function ai(e,t,r,i,a){switch(t.toLowerCase()){case"wifi":{let t=an(r);await f("adb",rl(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=an(r);await f("adb",rl(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await f("adb",rl(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=an(r);await f("adb",rl(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await ao(e,r);await f("adb",rl(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 g("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await aa(e,t);return}case"permission":{if(!i)throw new g("INVALID_ARGS","permission setting requires an active app in session");let t=ae(r),n=function(e,t){let r=at(e);if(t?.trim())throw new g("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new g("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(a?.permissionTarget,a?.permissionMode);if("notifications"===n.kind)return void await al(e,i,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await as(e,i,o);await f("adb",rl(e,["shell","pm",o,i,n.value]));return}default:throw new g("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function aa(e,t){var r;let i,a,n=(r=e,a=[["shell","cmd","fingerprint","touch",i="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",i]],"emulator"===r.kind&&a.push(["emu","finger","touch",i]),a),o=[];for(let t of n){let r=await f("adb",rl(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
16
- ${r}`.toLowerCase()).includes("unknown command")||i.includes("can't find service: fingerprint")||i.includes("service fingerprint was not found")||i.includes("fingerprint cmd unavailable")||i.includes("emu command is not supported")||i.includes("emulator console is not running")||i.includes("fingerprint")&&i.includes("not found")}))throw new g("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 g("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function an(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 g("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ao(e,t){let r=ar(t);if("toggle"!==r)return r;let i=await f("adb",rl(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==i.exitCode)throw new g("COMMAND_FAILED","Failed to read current Android appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let a=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
17
- ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"yes"===i?"dark":"no"===i?"light":"auto"===i?"auto":null}(i.stdout,i.stderr);if(!a)throw new g("COMMAND_FAILED","Unable to determine current Android appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"auto"===a?"dark":"dark"===a?"light":"dark"}async function as(e,t,r){let i=await ad(e),a=[];for(let n of null!==i&&i>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let i=await f("adb",rl(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===i.exitCode)return;a.push({permission:n,stderr:i.stderr,exitCode:i.exitCode})}throw new g("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:i,attempts:a})}async function al(e,t,r,i){"grant"===r?await f("adb",rl(e,["shell","pm","grant",t,i.permission]),{allowFailure:!0}):(await f("adb",rl(e,["shell","pm","revoke",t,i.permission]),{allowFailure:!0}),"reset"===r&&(await f("adb",rl(e,["shell","pm","clear-permission-flags",t,i.permission,"user-set"]),{allowFailure:!0}),await f("adb",rl(e,["shell","pm","clear-permission-flags",t,i.permission,"user-fixed"]),{allowFailure:!0}))),await f("adb",rl(e,["shell","appops","set",t,i.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function ad(e){let t=await f("adb",rl(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}async function au(e,t,r){let i="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,a=["shell","am","broadcast","-a",i,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&a.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new g("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,r){if("string"==typeof r)return e.push("--es",t,r);if("boolean"==typeof r)return e.push("--ez",t,r?"true":"false");if("number"==typeof r&&Number.isFinite(r))return Number.isInteger(r)?e.push("--ei",t,String(r)):e.push("--ef",t,String(r));throw new g("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(a,e,t),s+=1);return await f("adb",rl(e,a)),{action:i,extrasCount:s}}let ac=ey(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,Z,5e3),ap=ey(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,X,1e3),af=ey(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),am=ey(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),ah=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),aw=ey(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function ag(e,t){let r=["devicectl",...e],i=await f("xcrun",r,{allowFailure:!0,timeoutMs:am});if(0===i.exitCode)return;let a=String(i.stdout??""),n=String(i.stderr??"");throw new g("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:i.exitCode,stdout:a,stderr:n,deviceId:t.deviceId,hint:ay(a,n)??av})}async function aI(e,t){let r=o.join(P.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),i=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],a=await f("xcrun",i,{allowFailure:!0,timeoutMs:am});try{var n,s;if(0!==a.exitCode){let t=String(a.stdout??""),r=String(a.stderr??"");throw new g("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:i,exitCode:a.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:ay(t,r)??av})}let o=await L.readFile(r,"utf8");return n=aA(JSON.parse(o)),s=t,"user-installed"===s?n.filter(e=>!e.bundleId.startsWith("com.apple.")):n}catch(t){if(t instanceof g)throw t;throw new g("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await L.unlink(r).catch(()=>{})}}function aA(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let i="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:i})}return r}let av="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function ay(e,t){let r=`${e}
18
- ${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function ab(e){if(!(e instanceof g)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let r=String(t.stderr??"").toLowerCase();return r.includes("fbsopenapplicationserviceerrordomain")&&r.includes("the request to open")}async function aN(e,t){let r=await f("xcrun",eO(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let i=r.stdout.trim();if(!i)return{installed:!1};let a=await f("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${i}/Info.plist`],{allowFailure:!0});if(0!==a.exitCode||!a.stdout.trim())return{installed:!0};let n=a.stdout.trim(),o=`${i}/${n}`,s=await f("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 aS(e,t){if("simulator"!==e.kind)throw new g("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function a_(){await f("open",["-a","Simulator"],{allowFailure:!0})}async function aD(e){let t,r;if("simulator"!==e.kind||"Booted"===await ak(e))return;let i=Q.fromTimeoutMs(ac);try{await ee(async({deadline:i})=>{if(i?.isExpired())throw new g("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:ac});let a=Math.max(1e3,i?.remainingMs()??ac),n=await f("xcrun",eO(e,["boot",e.id]),{allowFailure:!0,timeoutMs:a});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.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 g("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await f("xcrun",eO(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:a});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new g("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await ak(e);if("Booted"!==d)throw new g("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let i=eh({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==i&&"CI_RESOURCE_STARVATION_SUSPECTED"!==i}},{deadline:i,phase:"boot",classifyReason:e=>eh({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let a=eh({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new g("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:ac,elapsedMs:i.elapsedMs(),reason:a,hint:ew(a),boot:t,bootstatus:r})}}async function aE(e){let t=eO(e,["shutdown",e.id]),r=await f("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function ak(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eL(["list","devices","-j"]):eO(e,["list","devices","-j"]),i=await f("xcrun",r,{allowFailure:!0,timeoutMs:ap});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function aL(e,t){try{let r=await f("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await L.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!i?.[1])return;let a=i[1].trim().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&amp;/g,"&");return a.length>0?a:void 0}(r,t)}catch{return}}async function aO(e,t){if("url"===e.kind&&!rq(e.url))throw new g("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let r=await rV({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||rq(e.url),signal:t?.signal}),i=await ax(r.installablePath,t),a=await aM(i.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:i.installPath,bundleId:a.bundleId,appName:a.appName,cleanup:async()=>{await i.cleanup(),await r.cleanup()}}}async function aM(e){let t=o.join(e,"Info.plist"),[r,i,a]=await Promise.all([aL(t,"CFBundleIdentifier"),aL(t,"CFBundleDisplayName"),aL(t,"CFBundleName")]);return{bundleId:r,appName:i??a}}async function ax(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await L.mkdtemp(o.join(P.tmpdir(),"agent-device-ios-ipa-")),i=async()=>{await L.rm(r,{recursive:!0,force:!0})};try{await f("ditto",["-x","-k",e,r]);let a=o.join(r,"Payload"),n=(await L.readdir(a,{withFileTypes:!0}).catch(()=>{throw new g("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:o.join(a,e.name),bundleName:e.name.replace(/\.app$/i,"")}));if(1===n.length)return{installPath:n[0].installPath,cleanup:i};if(0===n.length)throw new g("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await aC(n);let s=t?.appIdentifierHint?.trim();if(s){let e=function(e,t){let r=t.toLowerCase(),i=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===i.length)return i[0];if(i.length>1)throw new g("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(n,s);if(e)return{installPath:e.installPath,cleanup:i};throw new g("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload and none matched "${s}". Available bundles: ${n.map(aR).join(", ")}`)}throw new g("INVALID_ARGS",`Invalid IPA: found ${n.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${n.map(aR).join(", ")}`)}catch(e){throw await i(),e}}async function aC(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await aM(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function aR(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}function aP(e,t,r){return f("xcrun",eO(e,t),r)}let aT={ensureBooted:aD,captureWithRetry:aF,captureWithRunner:aV,shouldFallbackToRunner:aH};async function a$(e,t,r){if("simulator"===e.kind)return void await aU(e,t,r);try{await ag(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof g)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",i="string"==typeof t.stderr?t.stderr:"",a=`${e.message}
4
+ ${r}`.toLowerCase()).includes("device is busy")&&a.includes("connecting")?"Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.":ew("IOS_RUNNER_CONNECT_TIMEOUT"))})}function ev(e){if(ec(e))throw ef()}function ey(e,t,r){if(!e)return t;let a=Number(e);return Number.isFinite(a)?Math.max(r,Math.floor(a)):t}let eb=["AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET","IOS_SIMULATOR_DEVICE_SET"],eN=["AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST","ANDROID_DEVICE_ALLOWLIST"];function e_(e){return e?.trim()||void 0}function eS(e,t){for(let r of e){let e=e_(t[r]);if(e)return e}}function eD(e,t=process.env){return e_(e)??eS(eb,t)}function eE(e){return new Set(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean))}function ek(e,t=process.env){let r=e_(e)??eS(eN,t);if(r)return eE(r)}function eL(e,t={}){let r=eD(t.simulatorSetPath);return r?["simctl","--set",r,...e]:["simctl",...e]}function eO(e,t){return"ios"!==e.platform||"simulator"!==e.kind?["simctl",...t]:eL(t,{simulatorSetPath:e.simulatorSetPath})}let eM=ey(process.env.AGENT_DEVICE_RUNNER_STARTUP_TIMEOUT_MS,45e3,5e3),ex=ey(process.env.AGENT_DEVICE_RUNNER_COMMAND_TIMEOUT_MS,45e3,1e3),eC=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_ATTEMPT_INTERVAL_MS,250,50),eR=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_BASE_DELAY_MS,300,10),eT=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_RETRY_MAX_DELAY_MS,2e3,10),eP=ey(process.env.AGENT_DEVICE_RUNNER_CONNECT_REQUEST_TIMEOUT_MS,2e4,250),e$=ey(process.env.AGENT_DEVICE_IOS_DEVICE_INFO_TIMEOUT_MS,1e4,500),eU=ey(process.env.AGENT_DEVICE_RUNNER_DESTINATION_TIMEOUT_SECONDS,20,5);async function eF(e,t,r,a,i=eM,n,o){let s=Q.fromTimeoutMs(i),l=await eV(e,t,s.remainingMs()),d=null,u=Math.max(1,Math.ceil(i/eC));try{return await ee(async({deadline:s})=>{if(s?.isExpired())throw new w("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});if(n&&null!==n.child.exitCode&&void 0!==n.child.exitCode)throw await eA({session:n,port:t,logPath:a});for(let a of("device"===e.kind&&(l=await eV(e,t,s?.remainingMs())),l))try{let e=s?.remainingMs()??i;if(e<=0)throw new w("COMMAND_FAILED","Runner connection deadline exceeded",{port:t,timeoutMs:i});return await eG(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},Math.min(eP,e),o)}catch(e){if(o?.aborted||em(e))throw ef();d=e}throw new w("COMMAND_FAILED","Runner endpoint probe failed",{port:t,endpoints:l,lastError:d?String(d):void 0})},{maxAttempts:u,baseDelayMs:eR,maxDelayMs:eT,jitter:.2,shouldRetry:eg},{deadline:s,phase:"ios_runner_connect",signal:o})}catch(e){if(o?.aborted||em(e))throw ef();d||(d=e)}if(o?.aborted)throw ef();if("simulator"===e.kind){let i=s.remainingMs();if(i<=0)throw eI({port:t,endpoints:l,logPath:a,lastError:d});let n=await ej(e,t,r,i);return new Response(n.body,{status:n.status})}throw eI({port:t,endpoints:l,logPath:a,lastError:d})}async function eV(e,t,r){let a=[`http://127.0.0.1:${t}/command`];if("device"!==e.kind)return a;let i=await eB(e.id,r);return i&&a.unshift(`http://[${i}]:${t}/command`),a}async function eG(e,t,r,a){let i,n=new AbortController,o=setTimeout(()=>n.abort(),r);a&&(a.aborted?(clearTimeout(o),n.abort()):(i=()=>n.abort(),a.addEventListener("abort",i,{once:!0})));try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o),i&&a&&a.removeEventListener("abort",i)}}async function eB(e,t){if("number"==typeof t&&t<=0)return null;let r="number"==typeof t?Math.max(1,Math.min(e$,t)):e$,a=i.join(T.tmpdir(),`agent-device-devicectl-info-${process.pid}-${Date.now()}.json`);try{let t=Math.max(1,Math.ceil(r/1e3)),i=await c("xcrun",["devicectl","device","info","details","--device",e,"--json-output",a,"--timeout",String(t)],{allowFailure:!0,timeoutMs:r});if(0!==i.exitCode||!C.existsSync(a))return null;let n=JSON.parse(C.readFileSync(a,"utf8"));if(n.info?.outcome&&"success"!==n.info.outcome)return null;let o=(n.result?.connectionProperties?.tunnelIPAddress??n.result?.device?.connectionProperties?.tunnelIPAddress)?.trim();return o&&o.length>0?o:null}catch{return null}finally{eW(a)}}async function ej(e,t,r,a){let i=JSON.stringify(r),n=eO(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 c("xcrun",n,{allowFailure:!0,timeoutMs:a}),s=o.stdout;if(0!==o.exitCode){let e=eh({message:"Runner did not accept connection (simctl spawn)",stdout:o.stdout,stderr:o.stderr,context:{platform:"ios",phase:"connect"}});throw new w("COMMAND_FAILED","Runner did not accept connection (simctl spawn)",{port:t,stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode,reason:e,hint:ew(e)})}return{status:200,body:s}}async function eq(){return await new Promise((e,t)=>{let r=P.createServer();r.listen(0,"127.0.0.1",()=>{let a=r.address();r.close(),"object"==typeof a&&a?.port?e(a.port):t(new w("COMMAND_FAILED","Failed to allocate port"))}),r.on("error",t)})}function eH(e,t,r,a){t&&C.appendFileSync(t,e),r&&C.appendFileSync(r,e),a&&process.stderr.write(e)}function eW(e){try{C.existsSync(e)&&C.unlinkSync(e)}catch{}}async function ez(e,t,r){let a=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r);return e.set(t,a),a.finally(()=>{e.get(t)===a&&e.delete(t)})}function eJ(e){return"apple"===e?"ios":e}async function eK(e,t,r={}){let a=e,i=e=>e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim();if(t.platform&&(a=a.filter(e=>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&&"ios"===e.platform);if(!e)throw new w("DEVICE_NOT_FOUND",`No iOS 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 w("DEVICE_NOT_FOUND",`No Android device with serial ${t.serial}`);return e}if(t.deviceName){let e=i(t.deviceName),r=a.find(t=>i(t.name)===e);if(!r)throw new w("DEVICE_NOT_FOUND",`No device named ${t.deviceName}`);return r}if(1===a.length)return a[0];if(0===a.length){let e=r.simulatorSetPath;if(e&&(!t.platform||"ios"===t.platform))throw new w("DEVICE_NOT_FOUND","No devices found in the scoped simulator set",{simulatorSetPath:e,hint:`The simulator set at "${e}" appears to be empty. Create a simulator first:
5
+ xcrun simctl --set "${e}" create "iPhone 16" com.apple.CoreSimulator.SimDeviceType.iPhone-16 com.apple.CoreSimulator.SimRuntime.iOS-18-0`,selector:t});throw new w("DEVICE_NOT_FOUND","No devices found",{selector:t})}let n=a.filter(e=>"device"!==e.kind);n.length>0&&(a=n);let o=a.filter(e=>e.booted);return 1===o.length?o[0]:o[0]??a[0]}let eX=i.join(T.homedir(),".agent-device","ios-runner"),eZ=new Map,eY=new Set;function eQ(e){return e?.trim()??""}function e0(e=process.env){return eQ(e.AGENT_DEVICE_IOS_BUNDLE_ID)||eQ(e.AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)||"com.callstack.agentdevice.runner"}function e1(e=process.env){let t=eQ(e.AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID);return t||`${e0(e)}.uitests`}let e2=function(e=process.env){let t=e0(e),r=e1(e);return Array.from(new Set([eQ(e.AGENT_DEVICE_IOS_RUNNER_CONTAINER_BUNDLE_ID),`${r}.xctrunner`,t].filter(e=>e.length>0)))}(process.env);async function e3(e,t){var r;let a,n=(r=e.kind,(a=process.env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim())?i.resolve(a):"simulator"===r?i.join(eX,"derived"):i.join(eX,"derived",r));return await ez(eZ,n,async()=>{if(K(process.env.AGENT_DEVICE_IOS_CLEAN_DERIVED)){!function(e,t=process.env){if(t.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH?.trim()&&!function(e=process.env){return K(e.AGENT_DEVICE_IOS_ALLOW_OVERRIDE_DERIVED_CLEAN)}(t))throw new w("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."})}(n);try{C.rmSync(n,{recursive:!0,force:!0})}catch{}}let r=e4(n);if(r)return r;let a=function(){let e=i.dirname(A(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=i.join(t,"package.json");if(C.existsSync(e))return t;t=i.dirname(t)}return e}(),o=i.join(a,"ios-runner","AgentDeviceRunner","AgentDeviceRunner.xcodeproj");if(!C.existsSync(o))throw new w("COMMAND_FAILED","iOS runner project not found",{projectPath:o});let s=function(e=process.env){let t=e0(e),r=e1(e);return[`AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID=${t}`,`AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID=${r}`]}(process.env),l=function(e=process.env,t=!1){if(!t)return[];let r=e.AGENT_DEVICE_IOS_TEAM_ID?.trim()||"",a=e.AGENT_DEVICE_IOS_SIGNING_IDENTITY?.trim()||"",i=e.AGENT_DEVICE_IOS_PROVISIONING_PROFILE?.trim()||"",n=["CODE_SIGN_STYLE=Automatic"];return r&&n.push(`DEVELOPMENT_TEAM=${r}`),a&&n.push(`CODE_SIGN_IDENTITY=${a}`),i&&n.push(`PROVISIONING_PROFILE_SPECIFIER=${i}`),n}(process.env,"device"===e.kind),d="device"===e.kind?["-allowProvisioningUpdates"]:[];try{var u;let r;await v("xcodebuild",["build-for-testing","-project",o,"-scheme","AgentDeviceRunner","-parallel-testing-enabled","NO",e6(e),"1","-destination",(u=e,r=e5(u),"simulator"===u.kind?`platform=${r} Simulator,id=${u.id}`:`generic/platform=${r}`),"-derivedDataPath",n,"COMPILER_INDEX_STORE_ENABLE=NO",...s,...d,...l],{detached:!0,onSpawn:e=>{eY.add(e),e.on("close",()=>{eY.delete(e)})},onStdoutChunk:e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)},onStderrChunk:e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)}})}catch(n){let e,r,a=n instanceof w?n:new w("COMMAND_FAILED",String(n)),i=(e=a.details?JSON.stringify(a.details):"",(r=`${a.message}
6
+ ${e}`.toLowerCase()).includes("failed registering bundle identifier")||r.includes("app identifier")&&r.includes("not available")?"Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.":r.includes("requires a development team")?"Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.":r.includes("no profiles for")||r.includes("provisioning profile")?"Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.":r.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 w("COMMAND_FAILED","xcodebuild build-for-testing failed",{error:a.message,details:a.details,logPath:t.logPath,hint:i})}let c=e4(n);if(!c)throw new w("COMMAND_FAILED","Failed to locate .xctestrun after build");return c})}function e4(e){if(!C.existsSync(e))return null;let t=[],r=[e];for(;r.length>0;){let e=r.pop();for(let a of C.readdirSync(e,{withFileTypes:!0})){let n=i.join(e,a.name);if(a.isDirectory()){r.push(n);continue}if(a.isFile()&&a.name.endsWith(".xctestrun"))try{let e=C.statSync(n);t.push({path:n,mtimeMs:e.mtimeMs})}catch{}}}return 0===t.length?null:(t.sort((e,t)=>t.mtimeMs-e.mtimeMs),t[0]?.path??null)}async function e8(e,t,r){let a,n=i.dirname(e),o=r.replace(/[^a-zA-Z0-9._-]/g,"_"),s=i.join(n,`AgentDeviceRunner.env.${o}.json`),l=i.join(n,`AgentDeviceRunner.env.${o}.xctestrun`),d=await c("plutil",["-convert","json","-o","-",e],{allowFailure:!0});if(0!==d.exitCode||!d.stdout.trim())throw new w("COMMAND_FAILED","Failed to read xctestrun plist",{xctestrunPath:e,stderr:d.stderr});try{a=JSON.parse(d.stdout)}catch(t){throw new w("COMMAND_FAILED","Failed to parse xctestrun JSON",{xctestrunPath:e,error:String(t)})}let u=e=>{e.EnvironmentVariables={...e.EnvironmentVariables??{},...t},e.UITestEnvironmentVariables={...e.UITestEnvironmentVariables??{},...t},e.UITargetAppEnvironmentVariables={...e.UITargetAppEnvironmentVariables??{},...t},e.TestingEnvironmentVariables={...e.TestingEnvironmentVariables??{},...t}},p=a.TestConfigurations;if(Array.isArray(p))for(let e of p){if(!e||"object"!=typeof e)continue;let t=e.TestTargets;if(Array.isArray(t))for(let e of t)e&&"object"==typeof e&&u(e)}for(let[e,t]of Object.entries(a))t&&"object"==typeof t&&t.TestBundlePath&&(u(t),a[e]=t);C.writeFileSync(s,JSON.stringify(a,null,2));let f=await c("plutil",["-convert","xml1","-o",l,s],{allowFailure:!0});if(0!==f.exitCode)throw new w("COMMAND_FAILED","Failed to write xctestrun plist",{tmpXctestrunPath:l,stderr:f.stderr});return{xctestrunPath:l,jsonPath:s}}function e5(e){if("ios"!==e.platform)throw new w("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);return"tv"===e.target?"tvOS":"iOS"}function e6(e){return"device"===e.kind?"-maximum-concurrent-test-device-destinations":"-maximum-concurrent-test-simulator-destinations"}let e9=new Map,e7=new Map;async function te(e,t){return await ez(e7,e.id,async()=>{var r,a;let i,n=e9.get(e.id);if(n){if((r=n.child.pid)&&O(r))return n;await tr(e.id,n)}await ("simulator"!==(a=e).kind?Promise.resolve():ts(a));let o=await e3(e,t),s=await eq(),{xctestrunPath:l,jsonPath:u}=await e8(o,{AGENT_DEVICE_RUNNER_PORT:String(s)},`session-${e.id}-${s}`),{child:c,wait:p}=d("xcodebuild",["test-without-building","-only-testing","AgentDeviceRunnerUITests/RunnerTests/testCommand","-parallel-testing-enabled","NO","-test-timeouts-enabled","NO","-collect-test-diagnostics","never",e6(e),"1","-destination-timeout",String(eU),"-xctestrun",l,"-destination",(i=e5(e),"simulator"===e.kind?`platform=${i} Simulator,id=${e.id}`:`platform=${i},id=${e.id}`)],{allowFailure:!0,env:{...process.env,AGENT_DEVICE_RUNNER_PORT:String(s)},detached:!0});c.stdout?.on("data",e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)}),c.stderr?.on("data",e=>{eH(e,t.logPath,t.traceLogPath,t.verbose)});let f={device:e,deviceId:e.id,port:s,xctestrunPath:l,jsonPath:u,testPromise:p,child:c,ready:!1};return e9.set(e.id,f),f})}async function tt(e){await ez(e7,e.deviceId,async()=>{await tr(e.deviceId,e)})}async function tr(e,t){let r=t??e9.get(e);if(r){try{await eF(r.device,r.port,{command:"shutdown"},void 0,15e3)}catch{await to(r.child.pid,"SIGTERM")}try{await Promise.race([r.testPromise,new Promise(e=>setTimeout(e,1e4))])}catch{}await to(r.child.pid,"SIGKILL"),eW(r.xctestrunPath),eW(r.jsonPath),e9.get(e)===r&&e9.delete(e)}}async function ta(e){await ez(e7,e,async()=>{await tr(e)})}async function ti(){let e=Array.from(e9.values()),t=Array.from(eY);await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGINT")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGINT")})),await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGTERM")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGTERM")})),await Promise.allSettled(e.map(async e=>{await to(e.child.pid,"SIGKILL")})),await Promise.allSettled(t.map(async e=>{await to(e.pid,"SIGKILL"),eY.delete(e)}))}async function tn(){await ti();let e=Array.from(e9.keys());await Promise.allSettled(e.map(async e=>{await ta(e)}));let t=Array.from(eY);await Promise.allSettled(t.map(async e=>{try{await to(e.pid,"SIGTERM"),await to(e.pid,"SIGKILL")}finally{eY.delete(e)}}))}async function to(e,t){if(!e||e<=0)return;try{process.kill(-e,t)}catch{}try{process.kill(e,t)}catch{}let r="SIGINT"===t?"INT":"SIGTERM"===t?"TERM":"KILL";try{await c("pkill",[`-${r}`,"-P",String(e)],{allowFailure:!0})}catch{}}async function ts(e){await c("xcrun",eO(e,["bootstatus",e.id,"-b"]),{timeoutMs:eM})}async function tl(e,t,r,a,i,n){let o=await eF(e,t.port,r,a,i,t,n);return await td(o,t,a)}async function td(e,t,r){let a=await e.text(),i={};try{i=JSON.parse(a)}catch{throw new w("COMMAND_FAILED","Invalid runner response",{text:a})}if(!i.ok)throw new w("COMMAND_FAILED",i.error?.message??"Runner error",{runner:i,xcodebuild:{exitCode:1,stdout:"",stderr:""},logPath:r});return t.ready=!0,i.data??{}}async function tu(e,t,r={}){var a;if("ios"!==e.platform)throw new w("UNSUPPORTED_PLATFORM",`Unsupported platform for iOS runner: ${e.platform}`);if("simulator"!==e.kind&&"device"!==e.kind)throw new w("UNSUPPORTED_OPERATION",`Unsupported iOS device kind for runner: ${e.kind}`);return(ev(r.requestId),"snapshot"===(a=t.command)||"screenshot"===a||"findText"===a||"alert"===a)?et(()=>(ev(r.requestId),tc(e,t,r)),{shouldRetry:e=>{ev(r.requestId);if(!(e instanceof w)||"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"))}}):tc(e,t,r)}async function tc(e,t,r={}){let a;ev(r.requestId);let i=ep(r.requestId);try{let n=(a=await te(e,r)).ready?ex:eM;return await tl(e,a,t,r.logPath,n,i)}catch(o){let n=o instanceof w?o:new w("COMMAND_FAILED",String(o));if("COMMAND_FAILED"===n.code&&"string"==typeof n.message&&n.message.includes("Runner did not accept connection")&&eg(n)&&a?.ready){ev(r.requestId),a?await tt(a):await ta(e.id),a=await te(e,r);let n=await eF(a.device,a.port,t,r.logPath,eM,void 0,i);return await td(n,a,r.logPath)}throw o}}function tp(e){let t=e.result?.text;if("string"==typeof t&&t.trim().length>0)return t;let r=e.positionals??[];return 0===r.length?"":r[0].startsWith("@")?r.length>=3?r.slice(2).join(" ").trim():r.slice(1).join(" ").trim():!(r.length>=3)||Number.isNaN(Number(r[0]))||Number.isNaN(Number(r[1]))?r.slice(1).join(" ").trim():r.slice(2).join(" ").trim()}function tf(e){let t=new Set,r=[];for(let a of e)t.has(a)||(t.add(a),r.push(a));return r}let tm=/^-?\d+(\.\d+)?$/,th=new Map([["--count","count"],["--interval-ms","intervalMs"],["--hold-ms","holdMs"],["--jitter-px","jitterPx"]]),tw=new Map([["--count","count"],["--pause-ms","pauseMs"]]);function tg(e){return"click"===e||"press"===e}function tI(e){let t=e.trim();return t.startsWith("@")||tm.test(t)?t:JSON.stringify(t)}function tA(e){let t=e.trim();return/\s/.test(t)?JSON.stringify(t):t}function tv(e,t){let r=t.flags??{};if(tg(t.command)){"number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.intervalMs&&e.push("--interval-ms",String(r.intervalMs)),"number"==typeof r.holdMs&&e.push("--hold-ms",String(r.holdMs)),"number"==typeof r.jitterPx&&e.push("--jitter-px",String(r.jitterPx)),!0===r.doubleTap&&e.push("--double-tap");return}"swipe"===t.command&&("number"==typeof r.count&&e.push("--count",String(r.count)),"number"==typeof r.pauseMs&&e.push("--pause-ms",String(r.pauseMs)),("one-way"===r.pattern||"ping-pong"===r.pattern)&&e.push("--pattern",r.pattern))}function ty(e,t){t&&(("ios"===t.platform||"android"===t.platform)&&e.push("--platform",t.platform),"string"==typeof t.metroHost&&t.metroHost.length>0&&e.push("--metro-host",tA(t.metroHost)),"number"==typeof t.metroPort&&e.push("--metro-port",String(t.metroPort)),"string"==typeof t.bundleUrl&&t.bundleUrl.length>0&&e.push("--bundle-url",tA(t.bundleUrl)),"string"==typeof t.launchUrl&&t.launchUrl.length>0&&e.push("--launch-url",tA(t.launchUrl)))}function tb(e,t){let r=[],a={},i=tg(e)?th:"swipe"===e?tw:void 0;for(let n=0;n<t.length;n+=1){let o=t[n];if(tg(e)&&"--double-tap"===o){a.doubleTap=!0;continue}let s=i?.get(o);if(s&&n+1<t.length){let e=tN(t[n+1]);null!==e&&(a[s]=e),n+=1;continue}if("swipe"===e&&"--pattern"===o&&n+1<t.length){let e=t[n+1];("one-way"===e||"ping-pong"===e)&&(a.pattern=e),n+=1;continue}r.push(o)}return{positionals:r,flags:a}}function tN(e){if(!e)return null;let t=Number(e);return!Number.isFinite(t)||t<0?null:Math.floor(t)}class t_{sessions=new Map;runtimeHints=new Map;sessionsDir;constructor(e){this.sessionsDir=e}get(e){return this.sessions.get(e)}has(e){return this.sessions.has(e)}set(e,t){this.sessions.set(e,t)}delete(e){return this.runtimeHints.delete(e),this.sessions.delete(e)}values(){return this.sessions.values()}toArray(){return Array.from(this.sessions.values())}getRuntimeHints(e){return this.runtimeHints.get(e)}setRuntimeHints(e,t){this.runtimeHints.set(e,t)}clearRuntimeHints(e){return this.runtimeHints.delete(e)}recordAction(e,t){t.flags?.noRecord||(t.flags?.saveScript&&(e.recordSession=!0,"string"==typeof t.flags.saveScript&&(e.saveScriptPath=t_.expandHome(t.flags.saveScript))),e.actions.push({ts:Date.now(),command:t.command,positionals:t.positionals,flags:function(e){if(!e)return{};let{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:I,count:A,intervalMs:v,holdMs:y,jitterPx:b,doubleTap:N,pauseMs:_,pattern:S}=e;return{platform:t,device:r,udid:a,serial:i,out:n,verbose:o,metroHost:s,metroPort:l,bundleUrl:d,launchUrl:u,snapshotInteractiveOnly:c,snapshotCompact:p,snapshotDepth:f,snapshotScope:m,snapshotRaw:h,relaunch:w,saveScript:g,noRecord:I,count:A,intervalMs:v,holdMs:y,jitterPx:b,doubleTap:N,pauseMs:_,pattern:S}}(t.flags),result:t.result}),k({level:"debug",phase:"record_action",data:{command:t.command,session:e.name}}))}writeSessionLog(e){try{if(!e.recordSession)return;let t=this.resolveScriptPath(e),r=i.dirname(t);C.existsSync(r)||C.mkdirSync(r,{recursive:!0});let a=function(e,t){let r=[],a=e.device.name.replace(/"/g,'\\"'),i=e.device.kind?` kind=${e.device.kind}`:"";for(let n of(r.push(`context platform=${e.device.platform} device="${a}"${i} theme=unknown`),t))n.flags?.noRecord||r.push(function(e){let t=[e.command];if(tg(e.command)){let r=e.positionals?.[0];if(r){if(r.startsWith("@")){t.push(tI(r));let a=e.result?.refLabel;return"string"==typeof a&&a.trim().length>0&&t.push(tI(a)),tv(t,e),t.join(" ")}if(1===e.positionals.length)return t.push(tI(r)),tv(t,e),t.join(" ")}}if("fill"===e.command){let r=e.positionals?.[0];if(r&&r.startsWith("@")){t.push(tI(r));let a=e.result?.refLabel,i=e.positionals.slice(1).join(" ");return"string"==typeof a&&a.trim().length>0&&t.push(tI(a)),i&&t.push(tI(i)),t.join(" ")}}if("get"===e.command){let r=e.positionals?.[0],a=e.positionals?.[1];if(r&&a){if(t.push(tI(r)),t.push(tI(a)),a.startsWith("@")){let r=e.result?.refLabel;"string"==typeof r&&r.trim().length>0&&t.push(tI(r))}return t.join(" ")}}if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tI(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(tI(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}if("runtime"===e.command){let r=e.positionals?.[0];return r&&t.push(tA(r)),ty(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tI(r));return tv(t,e),t.join(" ")}(n));return`${r.join("\n")}
7
+ `}(e,this.buildOptimizedActions(e));C.writeFileSync(t,a)}catch{}}defaultTracePath(e){let t=t_.safeSessionName(e.name),r=new Date().toISOString().replace(/[:.]/g,"-");return i.join(this.sessionsDir,`${t}-${r}.trace.log`)}resolveAppLogPath(e){return i.join(this.sessionsDir,t_.safeSessionName(e),"app.log")}resolveAppLogPidPath(e){return i.join(this.sessionsDir,t_.safeSessionName(e),"app-log.pid")}static safeSessionName(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}static expandHome(e,t){return N(e,{cwd:t})}resolveScriptPath(e){if(e.saveScriptPath)return t_.expandHome(e.saveScriptPath);C.existsSync(this.sessionsDir)||C.mkdirSync(this.sessionsDir,{recursive:!0});let t=t_.safeSessionName(e.name),r=new Date(e.createdAt).toISOString().replace(/[:.]/g,"-");return i.join(this.sessionsDir,`${t}-${r}.ad`)}buildOptimizedActions(e){let t=[];for(let r of e.actions){if("snapshot"===r.command)continue;let a=Array.isArray(r.result?.selectorChain)&&r.result?.selectorChain.every(e=>"string"==typeof e)?r.result.selectorChain:[];if(a.length>0&&(tg(r.command)||"fill"===r.command||"get"===r.command)){let e=a.join(" || ");if(tg(r.command)){t.push({...r,positionals:[e]});continue}if("fill"===r.command){let a=tp(r);if(a.length>0){t.push({...r,positionals:[e,a]});continue}}if("get"===r.command){let a=r.positionals?.[0];if("text"===a||"attrs"===a){t.push({...r,positionals:[a,e]});continue}}}if(tg(r.command)||"fill"===r.command||"get"===r.command){let a=r.result?.refLabel;"string"==typeof a&&a.trim().length>0&&t.push({ts:r.ts,command:"snapshot",positionals:[],flags:{platform:e.device.platform,snapshotInteractiveOnly:!0,snapshotCompact:!0,snapshotScope:a.trim()},result:{scope:a.trim()}})}t.push(r)}return t}}function tS(e,t){if(!e)return;let r=i.dirname(e);C.existsSync(r)||C.mkdirSync(r,{recursive:!0});let a={pid:t,startTime:M(t)??void 0,command:n(t)??void 0};C.writeFileSync(e,`${JSON.stringify(a)}
8
+ `)}function tD(e){if(e&&C.existsSync(e))try{C.unlinkSync(e)}catch{}}async function tE(e,t=2e3){await Promise.race([e.then(()=>void 0).catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}async function tk(e){await new Promise(t=>setTimeout(t,e))}function tL(e,t){let r=t.includeTokens?.filter(e=>e.length>0)??[],a="",i=a=>{(!(r.length>0)||r.some(e=>a.includes(e)))&&e.write(function(e,t){if(0===t.length)return e;let r=e;for(let e of t)r=r.replace(e,"[REDACTED]");return r}(a,t.redactionPatterns))};return{onChunk:e=>{let t=`${a}${e}`.split("\n");for(let e of(a=t.pop()??"",t))i(`${e}
9
+ `)},flush:()=>{a&&(i(a),a="")}}}function tO(e,t,r){let a=e.stdout,i=e.stderr;return a&&i?(a.setEncoding("utf8"),i.setEncoding("utf8"),a.on("data",r.writer.onChunk),i.on("data",r.writer.onChunk),t.on("error",()=>{e.killed||e.kill("SIGKILL")}),e.on("error",()=>t.destroy()),new Promise(a=>{e.on("close",e=>{r.writer.flush(),r.endStreamOnClose&&t.end(),a({stdout:"",stderr:"",exitCode:e??1})})})):Promise.resolve({stdout:"",stderr:"missing stdio pipes",exitCode:1})}async function tM(e,t){let r=(await c("adb",["-s",e,"shell","pidof",t],{allowFailure:!0})).stdout.trim().split(/\s+/)[0];return r&&/^\d+$/.test(r)?r:null}async function tx(e,t,r,a,i){let n,o,s="active",l=!1,d=(async()=>{try{for(;!l;){let d=await tM(e,t);if(!d){await tk(1e3);continue}let u=p("adb",["-s",e,"logcat","-v","time","--pid",d],{stdio:["ignore","pipe","pipe"]});n=u;let c=tL(r,{redactionPatterns:a});o=tO(u,r,{endStreamOnClose:!1,writer:c}),"number"==typeof u.pid&&tS(i,u.pid);let f=await o;if(tD(i),n=void 0,o=void 0,l)break;0!==f.exitCode&&(s="failed"),await tk(500)}return{stdout:"",stderr:"",exitCode:0}}finally{r.end(),tD(i)}})();return{backend:"android",getState:()=>s,startedAt:Date.now(),wait:d,stop:async()=>{l=!0,n&&!n.killed&&n.kill("SIGINT"),o&&await tE(o),n&&!n.killed&&n.kill("SIGKILL"),await tE(d),tD(i)}}}async function tC(e,t,r,a){let i="active",n=p("log",["stream","--style","compact","--predicate",`subsystem == "${e}" OR processImagePath ENDSWITH[c] "/${e}" OR senderImagePath ENDSWITH[c] "/${e}" OR eventMessage CONTAINS[c] "${e}"`],{stdio:["ignore","pipe","pipe"]}),o=tL(t,{redactionPatterns:r});"number"==typeof n.pid&&tS(a,n.pid);let s=tO(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tD(a),e));return{backend:"ios-simulator",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tE(s),n.killed||n.kill("SIGKILL"),await tE(s),tD(a)}}}async function tR(e,t,r,a){let i="active",n=p("xcrun",["devicectl","device","log","stream","--device",e],{stdio:["ignore","pipe","pipe"]}),o=tL(t,{redactionPatterns:r});"number"==typeof n.pid&&tS(a,n.pid);let s=tO(n,t,{endStreamOnClose:!0,writer:o}).then(e=>(0!==e.exitCode&&(i="failed"),tD(a),e));return{backend:"ios-device",getState:()=>i,startedAt:Date.now(),wait:s,stop:async()=>{n.killed||n.kill("SIGINT"),await tE(s),n.killed||n.kill("SIGKILL"),await tE(s),tD(a)}}}function tT(e,t){let r=process.env[e];if(!r)return t;let a=Number.parseInt(r,10);return Number.isInteger(a)&&a>0?a:t}function tP(e){let t=i.dirname(e);C.existsSync(t)||C.mkdirSync(t,{recursive:!0}),function(e,t){if(C.existsSync(e)&&!(C.statSync(e).size<t.maxBytes))for(let r=t.maxRotatedFiles;r>=1;r-=1){let t=1===r?e:`${e}.${r-1}`,a=`${e}.${r}`;C.existsSync(t)&&(C.existsSync(a)&&C.unlinkSync(a),C.renameSync(t,a))}}(e,{maxBytes:tT("AGENT_DEVICE_APP_LOG_MAX_BYTES",5242880),maxRotatedFiles:tT("AGENT_DEVICE_APP_LOG_MAX_FILES",1)})}async function t$(e,t,r,a){tP(r);let i=C.createWriteStream(r,{flags:"a"}),n=function(){let e=process.env.AGENT_DEVICE_APP_LOG_REDACT_PATTERNS;if(!e)return[];let t=e.split(",").map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of t)try{r.push(RegExp(e,"gi"))}catch{}return r}();if("ios"===e.platform)return"device"===e.kind?await tR(e.id,i,n,a):await tC(t,i,n,a);if("android"===e.platform){if(!/^[a-zA-Z0-9._:-]+$/.test(t))throw new w("INVALID_ARGS",`Invalid Android package name for logs: ${t}`);return await tx(e.id,t,i,n,a)}throw i.end(),new w("UNSUPPORTED_PLATFORM",`unsupported platform: ${e.platform}`)}async function tU(e){await e.stop(),await tE(e.wait)}async function tF(e,t){let r={},a=[];if(t||a.push("No app bundle is tracked in this session. Run open <app> first for app-scoped logs."),"android"===e.platform){try{let e=await c("adb",["version"],{allowFailure:!0});r.adbAvailable=0===e.exitCode}catch{r.adbAvailable=!1}if(t)try{r.androidPidVisible=(await c("adb",["-s",e.id,"shell","pidof",t],{allowFailure:!0})).stdout.trim().length>0}catch{r.androidPidVisible=!1}}if("ios"===e.platform&&"simulator"===e.kind)try{let e=await c("xcrun",["simctl","help"],{allowFailure:!0});r.simctlAvailable=0===e.exitCode}catch{r.simctlAvailable=!1}if("ios"===e.platform&&"device"===e.kind)try{let e=await c("xcrun",["devicectl","--version"],{allowFailure:!0});r.devicectlAvailable=0===e.exitCode}catch{r.devicectlAvailable=!1}return{checks:r,notes:a}}function tV(e){let t=i.dirname(e),r=i.basename(e);C.existsSync(t)||C.mkdirSync(t,{recursive:!0}),C.existsSync(e)?C.truncateSync(e,0):C.writeFileSync(e,"","utf8");let a=0;for(let e of C.readdirSync(t)){if(!e.startsWith(`${r}.`))continue;let n=e.slice(r.length+1);if(/^\d+$/.test(n))try{C.unlinkSync(i.join(t,e)),a+=1}catch{}}return{path:e,cleared:!0,removedRotatedFiles:a}}let tG=new Map;function tB(e){let t=tG.get(e);if(t&&(clearTimeout(t.timer),tG.delete(e),t.deleteAfterDownload))try{C.rmSync(t.artifactPath,{force:!0})}catch{}}let tj=new Map;function tq(e,t){let r=tj.get(e);if(!r)throw new w("INVALID_ARGS",`Uploaded artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new w("UNAUTHORIZED","Uploaded artifact belongs to a different tenant");return clearTimeout(r.timer),r.artifactPath}function tH(e){let t=tj.get(e);t&&(clearTimeout(t.timer),tj.delete(e),C.rmSync(t.tempDir,{recursive:!0,force:!0}))}async function tW(e){let t=await tz(e);await c("tar",["xf",e.archivePath,"-C",e.tempDir]);let r=i.join(e.tempDir,t);if(!C.existsSync(r))throw new w("INVALID_ARGS",`Expected extracted bundle "${t}" not found in archive`);return r}async function tz(e){let t=await c("tar",["-tf",e.archivePath],{allowFailure:!0});if(0!==t.exitCode)throw new w("INVALID_ARGS","Artifact is not a valid tar archive",{archivePath:e.archivePath,stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let r=t.stdout.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);if(0===r.length)throw new w("INVALID_ARGS","Uploaded app bundle archive is empty");let a=r.map(e=>(function(e){if(e.includes("\0"))throw new w("INVALID_ARGS",`Invalid archive entry: ${e}`);if(i.posix.isAbsolute(e))throw new w("INVALID_ARGS",`Archive entry must be relative: ${e}`);let t=i.posix.normalize(e).replace(/^(\.\/)+/,"");if(!t||"."===t||t.startsWith("../"))throw new w("INVALID_ARGS",`Archive entry escapes bundle root: ${e}`);return t})(e)),n=e.expectedRootName??function(e,t){let r=new Set;for(let t of e){let[e]=t.split("/");e&&r.add(e)}let a=[...r];if("ios"===t){let e=a.filter(e=>e.toLowerCase().endsWith(".app"));if(1===e.length)return e[0];if(0===e.length)throw new w("INVALID_ARGS","iOS app bundle archives must contain a single top-level .app directory");throw new w("INVALID_ARGS",`iOS app bundle archives must contain exactly one top-level .app directory, found: ${e.join(", ")}`)}if(1===a.length)return a[0];throw new w("INVALID_ARGS",`Archive must contain a single top-level bundle, found: ${a.join(", ")}`)}(a,e.platform);if(!a.some(e=>e===n||e.startsWith(`${n}/`)))throw new w("INVALID_ARGS",`Uploaded archive must contain a top-level "${n}" bundle`);for(let e of a){var o=e,s=n;if(o!==s&&!o.startsWith(`${s}/`))throw new w("INVALID_ARGS",`Archive entry must stay inside top-level "${s}" bundle: ${o}`)}for(let t of(await c("tar",["-tvf",e.archivePath])).stdout.split(/\r?\n/).filter(Boolean)){let e=t[0];if("l"===e||"h"===e)throw new w("INVALID_ARGS","Uploaded app bundle archive cannot contain symlinks or hard links")}return n}let tJ=ey(process.env.AGENT_DEVICE_ARTIFACT_IDLE_TIMEOUT_MS,6e4,1e3);function tK(e,t){return new Promise((r,a)=>{let i,n=C.createWriteStream(t),o=t=>{"destroy"in e&&"function"==typeof e.destroy&&e.destroy(t)},s=!1,l=0,d=e=>{if(!s){if(s=!0,i&&clearTimeout(i),e){n.destroy(),C.rmSync(t,{force:!0}),a(e);return}r()}},u=()=>{i&&clearTimeout(i),i=setTimeout(()=>{let e=new w("COMMAND_FAILED","Artifact transfer timed out due to inactivity",{timeoutMs:tJ});o(e),n.destroy(e),d(e)},tJ)};e.on("data",e=>{u();let t=Buffer.isBuffer(e)?e.length:Buffer.byteLength(e);if((l+=t)>0x80000000){let e=new w("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes");o(e),n.destroy(e),d(e)}}),e.on("error",d),e.on("aborted",()=>{d(new w("COMMAND_FAILED","Artifact transfer was interrupted"))}),n.on("error",d),n.on("finish",()=>d()),u(),e.pipe(n)})}async function tX(e){let t,r=e.headers["x-artifact-type"],a=e.headers["x-artifact-filename"];if(!r||!a)throw new w("INVALID_ARGS","Missing required headers: x-artifact-type and x-artifact-filename");if("file"!==r&&"app-bundle"!==r)throw new w("INVALID_ARGS",`Invalid x-artifact-type: ${r}. Must be "file" or "app-bundle".`);!function(e){if(void 0===e)return;let t=Number(e);if(Number.isFinite(t)&&t>0x80000000)throw new w("INVALID_ARGS","Upload exceeds maximum size of 2147483648 bytes")}(e.headers["content-length"]);let n=function(e){let t=e.trim(),r=i.basename(t);if(!r||"."===r||".."===r)throw new w("INVALID_ARGS",`Invalid artifact filename: ${e}`);return r}(a),o=(t=function(e){let t=e?.trim();if(!t)return"request";let r=t.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0?r.slice(0,48):"request"}("upload"),C.mkdtempSync(i.join(T.tmpdir(),`agent-device-artifact-${t}-`)));try{if("file"===r){let t=i.join(o,n);return await tK(e,t),{artifactPath:t,tempDir:o}}let t=i.join(o,"artifact.tar");await tK(e,t);let a=await tW({archivePath:t,tempDir:o,platform:"ios",expectedRootName:n});return C.rmSync(t,{force:!0}),{artifactPath:a,tempDir:o}}catch(e){throw C.rmSync(o,{recursive:!0,force:!0}),e}}let tZ=new Set(["agent_device.command","agent-device.command"]),tY=new Set(["agent_device.install_from_source","agent-device.install_from_source"]),tQ=new Set(["agent_device.release_materialized_paths","agent-device.release_materialized_paths"]),t0={"agent_device.lease.allocate":"lease_allocate","agent-device.lease.allocate":"lease_allocate","agent_device.lease.heartbeat":"lease_heartbeat","agent-device.lease.heartbeat":"lease_heartbeat","agent_device.lease.release":"lease_release","agent-device.lease.release":"lease_release"},t1=new Set([...tZ,...tY,...tQ,...Object.keys(t0)]);function t2(e,t,r,a){return{jsonrpc:"2.0",id:e,error:{code:t,message:r,data:a}}}function t3(e,t,r=200){e.statusCode=r,e.setHeader("content-type","application/json"),e.end(JSON.stringify(t))}function t4(e){switch(e){case"INVALID_ARGS":return 400;case"UNAUTHORIZED":return 401;case"SESSION_NOT_FOUND":return 404;default:return 500}}function t8(e,t){let r="string"==typeof t.authorization?t.authorization:"",a=r.toLowerCase().startsWith("bearer ")?r.slice(7):void 0,i="string"==typeof t["x-agent-device-token"]?t["x-agent-device-token"]:void 0;return("string"==typeof e.token?e.token:void 0)??i??a??""}function t5(e,t){let r=e[t];return"string"==typeof r?r:void 0}function t6(e,t){let r=e[t];return Number.isInteger(r)?Number(r):void 0}async function t9(e,t){if(!e)return{ok:!0};let r=await e(t);if(void 0===r||!0===r)return{ok:!0};if(!1===r){let e=y(new w("UNAUTHORIZED","Request rejected by auth hook"));return{ok:!1,statusCode:401,response:t2(t.rpcRequest.id??null,-32001,e.message,e)}}if(!1===r.ok){let e=y(new w(r.code??"UNAUTHORIZED",r.message??"Request rejected by auth hook",r.details));return{ok:!1,statusCode:401,response:t2(t.rpcRequest.id??null,-32001,e.message,e)}}if("string"==typeof r.tenantId&&r.tenantId.length>0){let e=o(r.tenantId);if(!e){let e=y(new w("INVALID_ARGS","Auth hook returned invalid tenantId"));return{ok:!1,statusCode:500,response:t2(t.rpcRequest.id??null,-32e3,e.message,e)}}return{ok:!0,tenantId:e}}return{ok:!0}}async function t7(){let e,t=process.env.AGENT_DEVICE_HTTP_AUTH_HOOK;if(!t)return null;let r=process.env.AGENT_DEVICE_HTTP_AUTH_EXPORT||"default",a=i.isAbsolute(t)?t:i.resolve(t);try{e=await import(h(a).href)}catch(e){throw new w("COMMAND_FAILED","Failed to load AGENT_DEVICE_HTTP_AUTH_HOOK module",{hookPath:a,error:e instanceof Error?e.message:String(e)})}let n=e[r];if("function"!=typeof n)throw new w("INVALID_ARGS",`Auth hook export ${r} is not a function`,{hookPath:a,exportName:r});return n}async function re(e){let t=await t7(),{handleRequest:r,token:a}=e;return F.createServer((e,i)=>{if("GET"===e.method&&"/health"===e.url){i.statusCode=200,i.setHeader("content-type","application/json"),i.end(JSON.stringify({ok:!0}));return}if("POST"===e.method&&"/upload"===e.url)return void rt(e,i,t,a);if("GET"===e.method&&e.url?.startsWith("/upload/"))return void rr(e,i,t,a);if("POST"!==e.method||"/rpc"!==e.url){i.statusCode=404,i.end("Not found");return}let n="";e.setEncoding("utf8"),e.on("data",t=>{(n+=t).length>1048576&&e.destroy(Error("request too large"))}),e.on("error",()=>{i.headersSent||t3(i,t2(null,-32700,"Parse error"),400)}),e.on("end",async()=>{let a,o;try{a=JSON.parse(n)}catch{t3(i,t2(null,-32700,"Parse error"),400);return}if("2.0"!==a.jsonrpc||"string"!=typeof a.method)return void t3(i,t2(a.id??null,-32600,"Invalid Request"),400);if(!t1.has(a.method))return void t3(i,t2(a.id??null,-32601,`Method not found: ${a.method}`),404);if(!a.params||"object"!=typeof a.params)return void t3(i,t2(a.id??null,-32602,"Invalid params"),400);try{var s;let n=a.params,l=function(e,t,r){if(tZ.has(e))return{token:t8(t,r),session:t.session??"default",command:t.command??"",positionals:Array.isArray(t.positionals)?t.positionals:[],flags:t.flags,runtime:t.runtime,meta:t.meta};if(tY.has(e)){let e,a=t5(t,"platform");if("ios"!==a&&"android"!==a)throw new w("INVALID_ARGS",'Invalid params: platform must be "ios" or "android"');return{token:t8(t,r),session:t5(t,"session")??"default",command:"install_source",positionals:[],flags:{platform:a},meta:{requestId:t5(t,"requestId"),installSource:function(e){let t=e.source;if(!t||"object"!=typeof t)throw new w("INVALID_ARGS","Invalid params: source is required");if("url"===t.kind){let e="string"==typeof t.url?t.url.trim():"";if(!e)throw new w("INVALID_ARGS","Invalid params: source.url is required for url sources");let r=t.headers,a={};if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw new w("INVALID_ARGS","Invalid params: source.headers must be a string map");for(let[e,t]of Object.entries(r)){if("string"!=typeof t)throw new w("INVALID_ARGS","Invalid params: source.headers values must be strings");a[e]=t}}return Object.keys(a).length>0?{kind:"url",url:e,headers:a}:{kind:"url",url:e}}if("path"===t.kind){let e="string"==typeof t.path?t.path.trim():"";if(!e)throw new w("INVALID_ARGS","Invalid params: source.path is required for path sources");return{kind:"path",path:e}}throw new w("INVALID_ARGS",'Invalid params: source.kind must be "url" or "path"')}(t),retainMaterializedPaths:(e=t.retainPaths,"boolean"==typeof e?e:void 0),materializedPathRetentionMs:t6(t,"retentionMs")}}}if(tQ.has(e)){let e=t5(t,"materializationId")?.trim();if(!e)throw new w("INVALID_ARGS","Invalid params: materializationId is required");return{token:t8(t,r),session:t5(t,"session")??"default",command:"release_materialized_paths",positionals:[],meta:{requestId:t5(t,"requestId"),materializationId:e}}}let a=t0[e];if(a)return{token:t8(t,r),session:t5(t,"session")??"default",command:a,positionals:[],meta:{tenantId:t5(t,"tenantId")??t5(t,"tenant"),runId:t5(t,"runId"),leaseId:t5(t,"leaseId"),leaseTtlMs:t6(t,"ttlMs"),leaseBackend:t5(t,"backend")}};throw new w("INVALID_ARGS",`Method not found: ${e}`)}(a.method,n,e.headers);if(s=a.method,tZ.has(s)&&("string"!=typeof l.command||0===l.command.length))return void t3(i,t2(a.id??null,-32602,"Invalid params: command is required"),400);o=es(l.meta?.requestId,a.id),l.meta={...l.meta,requestId:o},el(o);let d=()=>{i.writableFinished||ed(o)};e.on("aborted",d),i.on("close",d);let u=await t9(t,{headers:e.headers,rpcRequest:a,daemonRequest:l});if(!u.ok)return void t3(i,u.response,u.statusCode);u.tenantId&&(l.meta={...l.meta,tenantId:u.tenantId,sessionIsolation:l.meta?.sessionIsolation??l.flags?.sessionIsolation??"tenant"});let c=await r(l);if(c.ok)return void t3(i,{jsonrpc:"2.0",id:a.id??null,result:c});t3(i,t2(a.id??null,-32e3,c.error.message,c.error),t4(c.error.code))}catch(t){let e=y(t);t3(i,t2(a.id??null,-32e3,e.message,e),t4(e.code))}finally{eu(o)}})})}async function rt(e,t,r,a){try{var i;let n,o,s=t8({},e.headers),l=ra(s,a);if(l){t.statusCode=t4(l.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:l.message,code:l.code}));return}let d=await t9(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:s,session:"default",command:"upload",positionals:[]}});if(!d.ok){t.statusCode=d.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:d.response.error?.data?.message??d.response.error?.message??"Unauthorized"}));return}let c=await tX(e),p=(i={artifactPath:c.artifactPath,tempDir:c.tempDir,tenantId:d.tenantId},n=u.randomUUID(),o=setTimeout(()=>{tH(n)},3e5),tj.set(n,{artifactPath:i.artifactPath,tempDir:i.tempDir,tenantId:i.tenantId,timer:o}),n);t.statusCode=200,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!0,uploadId:p}))}catch(r){let e=y(r);t.statusCode=t4(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}async function rr(e,t,r,a){let i=e.url?.slice("/upload/".length)??"";if(!i){t.statusCode=400,t.end("Missing artifact id");return}try{let n=t8({},e.headers),o=ra(n,a);if(o){t.statusCode=t4(o.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:o.message,code:o.code}));return}let s=await t9(r,{headers:e.headers,rpcRequest:{jsonrpc:"2.0",id:null,method:"agent_device.command"},daemonRequest:{token:n,session:"default",command:"download_artifact",positionals:[i]}});if(!s.ok){t.statusCode=s.statusCode,t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:s.response.error?.data?.message??s.response.error?.message??"Unauthorized"}));return}let l=function(e,t){let r=tG.get(e);if(!r)throw new w("INVALID_ARGS",`Artifact not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new w("UNAUTHORIZED","Artifact belongs to a different tenant");if(!C.existsSync(r.artifactPath))throw tB(e),new w("COMMAND_FAILED",`Artifact file is missing: ${r.artifactPath}`);return{artifactPath:r.artifactPath,fileName:r.fileName,deleteAfterDownload:r.deleteAfterDownload}}(i,s.tenantId),d=C.createReadStream(l.artifactPath);t.statusCode=200,t.setHeader("content-type","application/octet-stream"),l.fileName&&t.setHeader("content-disposition",`attachment; filename="${l.fileName.replace(/"/g,"")}"`),d.on("error",e=>{if(t.headersSent)t.destroy(e);else{let r=y(e);t.statusCode=t4(r.code),t.end(r.message)}}),t.on("close",()=>{t.writableFinished&&tB(i)}),d.pipe(t)}catch(r){let e=y(r);t.statusCode=t4(e.code),t.setHeader("content-type","application/json"),t.end(JSON.stringify({ok:!1,error:e.message,code:e.code}))}}function ra(e,t){return t&&e!==t?y(new w("UNAUTHORIZED","Invalid token")):null}function ri(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}function rn(e){if(!e)return;let t=e.trim();if(t&&/^[a-f0-9]{16,128}$/i.test(t))return t.toLowerCase()}function ro(e){let t=(e??"").trim().toLowerCase();if(!t||"ios-simulator"===t)return"ios-simulator";throw new w("INVALID_ARGS",`Unsupported lease backend: ${e??""}`)}class rs{leases=new Map;runBindings=new Map;maxActiveSimulatorLeases;defaultLeaseTtlMs;minLeaseTtlMs;maxLeaseTtlMs;now;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.defaultLeaseTtlMs=Number.isInteger(e.defaultLeaseTtlMs)?Math.max(1,Number(e.defaultLeaseTtlMs)):6e4,this.minLeaseTtlMs=Number.isInteger(e.minLeaseTtlMs)?Math.max(1,Number(e.minLeaseTtlMs)):5e3,this.maxLeaseTtlMs=Number.isInteger(e.maxLeaseTtlMs)?Math.max(this.minLeaseTtlMs,Number(e.maxLeaseTtlMs)):6e5,this.now=e.now??(()=>Date.now())}allocateLease(e){let t=ro(e.backend),r=o(e.tenantId);if(!r)throw new w("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");let a=ri(e.runId);if(!a)throw new w("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");this.cleanupExpiredLeases();let i=this.resolveLeaseTtlMs(e.ttlMs),n=this.bindingKey(r,a,t),s=this.runBindings.get(n);if(s){let e=this.leases.get(s);if(e)return this.refreshLease(e,i);this.runBindings.delete(n)}this.enforceCapacity(t);let l=this.now(),d={leaseId:u.randomBytes(16).toString("hex"),tenantId:r,runId:a,backend:t,createdAt:l,heartbeatAt:l,expiresAt:l+i};return this.leases.set(d.leaseId,d),this.runBindings.set(n,d.leaseId),{...d}}heartbeatLease(e){let t=rn(e.leaseId);if(!t)throw new w("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);if(!r)throw new w("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});this.assertOptionalScopeMatch(r,e.tenantId,e.runId);let a=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(r,a)}releaseLease(e){let t=rn(e.leaseId);if(!t)throw new w("INVALID_ARGS","Invalid lease id.");this.cleanupExpiredLeases();let r=this.leases.get(t);return r?(this.assertOptionalScopeMatch(r,e.tenantId,e.runId),this.leases.delete(t),this.runBindings.delete(this.bindingKey(r.tenantId,r.runId,r.backend)),{released:!0}):{released:!1}}assertLeaseAdmission(e){let t=ro(e.backend),r=o(e.tenantId);if(!r)throw new w("INVALID_ARGS","tenant isolation requires tenant id.");let a=ri(e.runId);if(!a)throw new w("INVALID_ARGS","tenant isolation requires run id.");let i=rn(e.leaseId);if(!i)throw new w("INVALID_ARGS","tenant isolation requires lease id.");this.cleanupExpiredLeases();let n=this.leases.get(i);if(!n)throw new w("UNAUTHORIZED","Lease is not active",{reason:"LEASE_NOT_FOUND"});if(n.backend!==t||n.tenantId!==r||n.runId!==a)throw new w("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}cleanupExpiredLeases(){let e=this.now();for(let t of this.leases.values())t.expiresAt>e||(this.leases.delete(t.leaseId),this.runBindings.delete(this.bindingKey(t.tenantId,t.runId,t.backend)))}enforceCapacity(e){if("ios-simulator"!==e||this.maxActiveSimulatorLeases<=0)return;let t=Array.from(this.leases.values()).filter(e=>"ios-simulator"===e.backend).length;if(!(t<this.maxActiveSimulatorLeases))throw new w("COMMAND_FAILED","No simulator lease capacity available",{reason:"LEASE_CAPACITY_EXCEEDED",activeLeases:t,maxActiveLeases:this.maxActiveSimulatorLeases,backend:e,hint:"Retry after releasing another simulator lease."})}resolveLeaseTtlMs(e){if(!Number.isInteger(e))return this.defaultLeaseTtlMs;let t=Number(e);if(t<this.minLeaseTtlMs||t>this.maxLeaseTtlMs)throw new w("INVALID_ARGS",`Lease ttlMs must be between ${this.minLeaseTtlMs} and ${this.maxLeaseTtlMs}.`);return t}refreshLease(e,t){let r=this.now(),a={...e,heartbeatAt:r,expiresAt:r+t};return this.leases.set(a.leaseId,a),this.runBindings.set(this.bindingKey(a.tenantId,a.runId,a.backend),a.leaseId),{...a}}bindingKey(e,t,r){return`${e}:${t}:${r}`}assertOptionalScopeMatch(e,t,r){let a=o(t),i=ri(r);if(t&&!a)throw new w("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(r&&!i)throw new w("INVALID_ARGS","Invalid run id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if(a&&e.tenantId!==a||i&&e.runId!==i)throw new w("UNAUTHORIZED","Lease does not match tenant/run scope",{reason:"LEASE_SCOPE_MISMATCH"})}}function rl(e,t){return["-s",e.id,...t]}async function rd(){if(!await I("adb"))throw new w("TOOL_MISSING","adb not found in PATH")}function ru(e,t){let r=`${e}
10
+ ${t}`.toLowerCase();return r.includes("no shell command implementation")||r.includes("unknown command")}async function rc(e){await new Promise(t=>setTimeout(t,e))}function rp(e){let t=e.trim();if(!t||/\s/.test(t))return!1;let r=/^([A-Za-z][A-Za-z0-9+.-]*):(.+)$/.exec(t);if(!r)return!1;let a=r[1]?.toLowerCase(),i=r[2]??"";return"http"!==a&&"https"!==a&&"ws"!==a&&"wss"!==a&&"ftp"!==a&&"ftps"!==a||i.startsWith("//")}function rf(e,t){let r,a=e?.trim();return a?a:"http"===(r=t.trim().split(":")[0]?.toLowerCase())||"https"===r?"com.apple.mobilesafari":void 0}let rm=["android.software.leanback","android.software.leanback_only","android.hardware.type.television"];function rh(e){return`${e.stdout}
11
+ ${e.stderr}`}function rw(e,t){return["-s",e,...t]}function rg(e){return e.startsWith("emulator-")}function rI(e){return e.toLowerCase().replace(/_/g," ").replace(/\s+/g," ").trim()}async function rA(e,t=Y){return c("adb",rw(e,["shell","getprop","sys.boot_completed"]),{allowFailure:!0,timeoutMs:t})}async function rv(e,t){let r=t.replace(/_/g," ").trim();if(!rg(e))return r||e;let a=await ry(e);return a?a.replace(/_/g," "):r||e}async function ry(e){for(let t of["ro.boot.qemu.avd_name","persist.sys.avd_name"]){let r=await c("adb",rw(e,["shell","getprop",t]),{allowFailure:!0,timeoutMs:1e4}),a=r.stdout.trim();if(0===r.exitCode&&a.length>0)return a}let t=await c("adb",rw(e,["emu","avd","name"]),{allowFailure:!0,timeoutMs:1e4}),r=t.stdout.trim();if(0===t.exitCode&&r.length>0)return r}async function rb(e,t){let r=rh(await c("adb",rw(e,["shell","cmd","package","has-feature",t]),{allowFailure:!0,timeoutMs:Y})).toLowerCase();return!!r.includes("true")||!r.includes("false")&&null}async function rN(e){return(await Promise.all(rm.map(async t=>await rb(e,t)))).some(e=>!0===e)}async function r_(e){var t;let r;return"tv"===((r=rh(await c("adb",rw(e,["shell","getprop","ro.build.characteristics"]),{allowFailure:!0,timeoutMs:Y})).toLowerCase()).includes("tv")||r.includes("leanback")?"tv":null)||await rN(e)?"tv":(t=rh(await c("adb",rw(e,["shell","pm","list","features"]),{allowFailure:!0,timeoutMs:Y})),/feature:android\.(software\.leanback(_only)?|hardware\.type\.television)\b/i.test(t))?"tv":"mobile"}async function rS(e={}){if(!await I("adb"))throw new w("TOOL_MISSING","adb not found in PATH");let t=e.serialAllowlist??ek(void 0),r=(await rD()).filter(e=>!t||t.has(e.serial));return await Promise.all(r.map(async({serial:e,rawModel:t})=>{let[r,a,i]=await Promise.all([rv(e,t),rO(e),r_(e)]);return{platform:"android",id:e,name:r,kind:rg(e)?"emulator":"device",target:i,booted:a}}))}async function rD(){return(await c("adb",["devices","-l"],{timeoutMs:Y})).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 rE(){let e=await c("emulator",["-list-avds"],{allowFailure:!0,timeoutMs:Y});if(0!==e.exitCode)throw new w("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 rk(e){let t=Date.now();for(;Date.now()-t<e.timeoutMs;){try{let t=await rL(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 w("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 rL(e,t){let r=rI(e);for(let e of(await rD()).filter(e=>(!t||e.serial===t)&&rg(e.serial)))if(rI(e.rawModel)===r||rI(await rv(e.serial,e.rawModel))===r)return e.serial}async function rO(e){try{let t=await rA(e);return"1"===t.stdout.trim()}catch{return!1}}async function rM(e){var t,r;let a,i=e.avdName.trim();if(!i)throw new w("INVALID_ARGS","Android emulator boot requires a non-empty AVD name.");let n=e.timeoutMs??12e4;if(!await I("adb"))throw new w("TOOL_MISSING","adb not found in PATH");if(!await I("emulator"))throw new w("TOOL_MISSING","emulator not found in PATH");let o=await rE(),s=function(e,t){let r=e.find(e=>e===t);if(r)return r;let a=rI(t);return e.find(e=>rI(e)===a)}(o,i);if(!s)throw new w("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 d=Date.now(),u=(t=await rS(),r=e.serial,a=rI(s),t.find(e=>"android"===e.platform&&"emulator"===e.kind&&(!r||e.id===r)&&rI(e.name)===a));if(!u){let t=["-avd",s];e.headless&&t.push("-no-window","-no-audio"),l("emulator",t)}let c=u??await rk({avdName:s,serial:e.serial,timeoutMs:n}),p=Math.max(1e3,n-(Date.now()-d));await rx(c.id,p);let f=(await rS()).find(e=>e.id===c.id);return f?{...f,name:s,booted:!0}:{...c,name:s,booted:!0}}async function rx(e,t=6e4){let r,a=Q.fromTimeoutMs(t),i=Math.max(1,Math.ceil(t/1e3)),n=!1;try{await ee(async({deadline:i})=>{if(i?.isExpired())throw n=!0,new w("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 rA(e,Math.min(o,Y));if(r=s,"1"!==s.stdout.trim())throw new w("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=eh({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}});return"ADB_TRANSPORT_UNAVAILABLE"!==t&&"ANDROID_BOOT_TIMEOUT"!==t}},{deadline:a,phase:"boot",classifyReason:e=>eh({error:e,stdout:r?.stdout,stderr:r?.stderr,context:{platform:"android",phase:"boot"}})})}catch(c){let i=f(c),o=r?.stdout,s=r?.stderr,l=r?.exitCode,d=eh({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:ew(d),stdout:o,stderr:s,exitCode:l};if(n||"ANDROID_BOOT_TIMEOUT"===d)throw new w("COMMAND_FAILED","Android device did not finish booting in time",u);if("TOOL_MISSING"===i.code)throw new w("TOOL_MISSING",i.message,{...u,...i.details??{}});if("ADB_TRANSPORT_UNAVAILABLE"===d)throw new w("COMMAND_FAILED",i.message,{...u,...i.details??{}});throw new w(i.code,i.message,{...u,...i.details??{}},i.cause)}}let rC=/\.(?:apk|aab)$/i,rR=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function rT(e){var t,r;let a=e.trim();return 0===a.length?"other":rC.test(a)?a.includes("/")||a.includes("\\")||a.startsWith(".")||a.startsWith("~")||(t=a,!rR.test(t))?"binary":"package":(r=a,rR.test(r))?"package":"other"}function rP(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}let r$=[".zip",".tar",".tar.gz",".tgz"],rU=ey(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS,12e4,1e3),rF=["1","true","yes","on"];async function rV(e){let t=[];try{let r=await rG(e.source,{signal:e.signal,downloadTimeoutMs:e.downloadTimeoutMs});t.push(r.cleanup);let a=await rW(r.localPath,{archivePath:void 0,isInstallablePath:e.isInstallablePath,installableLabel:e.installableLabel,allowArchiveExtraction:!1!==e.allowArchiveExtraction,registerCleanup:e=>{t.push(e)}});return{archivePath:a.archivePath,installablePath:a.installablePath,cleanup:async()=>{await rX(t)}}}catch(e){throw await rX(t),e}}async function rG(e,t){if("path"===e.kind)return{localPath:m(e.path),cleanup:async()=>{}};let r=await L.mkdtemp(i.join(T.tmpdir(),"agent-device-source-"));try{return{localPath:await rB(r,e.url,e.headers,t),cleanup:async()=>{await L.rm(r,{recursive:!0,force:!0})}}}catch(e){throw await L.rm(r,{recursive:!0,force:!0}),e}}async function rB(e,t,r,a){let n;try{n=new URL(t)}catch{throw new w("INVALID_ARGS",`Invalid source URL: ${t}`)}await rj(n);let o=a?.signal;if(o?.aborted)throw new w("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let s=new AbortController,l=()=>{s.abort(o?.reason)};o?.addEventListener("abort",l,{once:!0});let d=a?.downloadTimeoutMs??rU,u=setTimeout(()=>{s.abort(Error("download timeout"))},d);try{let t=await fetch(n,{headers:r,redirect:"follow",signal:s.signal});if(!t.ok)throw new w("COMMAND_FAILED",`Failed to download app source: ${t.status} ${t.statusText}`,{status:t.status,statusText:t.statusText,url:n.toString()});let a=function(e,t){let r=e.headers.get("content-disposition"),a=r?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),n=a?.[1]?.trim();if(n)return i.basename(n);let o=i.basename(t.pathname);return o||"downloaded-artifact.bin"}(t,n),o=i.join(e,a),l=t.body;if(!l)throw new w("COMMAND_FAILED","Download response body was empty",{url:n.toString()});let d=await L.open(o,"w");try{for await(let e of l)await d.write(e)}finally{await d.close()}return o}catch(e){if(o?.aborted)throw new w("COMMAND_FAILED","request canceled",{reason:"request_canceled"},e);if(s.signal.aborted)throw new w("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:n.toString()},e);throw e}finally{o?.removeEventListener("abort",l),clearTimeout(u)}}async function rj(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new w("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!rF.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){var t;if(!(t=e.hostname.toLowerCase())||"localhost"===t||t.endsWith(".localhost")||rH(t))throw new w("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await r.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(e=>rH(e.address)))throw new w("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function rq(e){var t,r,a,i;let n=e instanceof URL?e:new URL(e),o=n.hostname.toLowerCase();if(!o)return!1;let s=n.pathname;return t=o,r=s,("api.github.com"===t?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(r):"github.com"===t&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(r))||(a=o,i=s,("expo.dev"===a||!!a.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(i))}function rH(e){let t,r=P.isIP(e);return 4===r?function(e){let t=e.split(".").map(e=>Number.parseInt(e,10));if(4!==t.length||t.some(e=>Number.isNaN(e)||e<0||e>255))return!1;let[r,a]=t;return 10===r||127===r||169===r&&254===a||172===r&&!!(a>=16)&&!!(a<=31)||192===r&&168===a}(e):6===r&&!!("::1"===(t=e.toLowerCase())||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("fe80:"))}async function rW(e,t){let r=await L.stat(e).catch(()=>null);if(!r)throw new w("INVALID_ARGS",`App source not found: ${e}`);if(t.isInstallablePath(e,r))return{archivePath:t.archivePath,installablePath:e};if(r.isFile()&&rK(e)){if(!t.allowArchiveExtraction)throw new w("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; archive extraction is not allowed`,{path:e});let r=await rJ(e);return t.registerCleanup(r.cleanup),await rW(r.outputPath,{...t,archivePath:t.archivePath??e})}if(r.isDirectory()){let r=await rz(e,t.isInstallablePath);if(1===r.length)return{archivePath:t.archivePath,installablePath:r[0]};if(r.length>1)throw new w("INVALID_ARGS",`Found multiple ${t.installableLabel} candidates under ${e}`,{matches:r});let a=await rz(e,(e,t)=>t.isFile()&&rK(e));if(1===a.length){if(!t.allowArchiveExtraction)throw new w("INVALID_ARGS",`URL sources must point directly to a ${t.installableLabel}; nested archives are not allowed`,{path:a[0]});let e=await rJ(a[0]);return t.registerCleanup(e.cleanup),await rW(e.outputPath,{...t,archivePath:t.archivePath??a[0]})}if(a.length>1)throw new w("INVALID_ARGS",`Found multiple nested archives under ${e}; expected one ${t.installableLabel} source`,{matches:a})}throw new w("INVALID_ARGS",`Expected ${t.installableLabel} source, but got ${e}`)}async function rz(e,t){let r=[],a=[{path:e,depth:0}];for(;a.length>0;){let e=a.shift();if(!e)continue;let n=await L.readdir(e.path,{withFileTypes:!0});for(let o of(n.sort((e,t)=>e.name.localeCompare(t.name)),n)){let n=i.join(e.path,o.name);if(t(n,o)){r.push(n);continue}o.isDirectory()&&e.depth<5&&a.push({path:n,depth:e.depth+1})}}return r}async function rJ(e){let t=await L.mkdtemp(i.join(T.tmpdir(),"agent-device-archive-"));try{return e.toLowerCase().endsWith(".zip")?await c("ditto",["-x","-k",e,t]):e.toLowerCase().endsWith(".tar.gz")||e.toLowerCase().endsWith(".tgz")?await c("tar",["-xzf",e,"-C",t]):await c("tar",["-xf",e,"-C",t]),{outputPath:t,cleanup:async()=>{await L.rm(t,{recursive:!0,force:!0})}}}catch(e){throw await L.rm(t,{recursive:!0,force:!0}),e}}function rK(e){let t=e.toLowerCase();return r$.some(e=>t.endsWith(e))}async function rX(e){for(let t=e.length-1;t>=0;t-=1)await e[t]()}let rZ=new W("utf-16le");async function rY(e){for(let r of["AndroidManifest.xml","base/manifest/AndroidManifest.xml"]){var t;let a=await rQ(e,r);if(!a)continue;let i=(t=a).subarray(0,Math.min(t.length,128)).toString("utf8").trimStart().startsWith("<")?function(e){let t=e.match(/<manifest\b[^>]*\bpackage\s*=\s*["']([^"']+)["']/i);return t?.[1]}(t.toString("utf8")):function(e){let t;if(!(e.length<8)&&3===e.readUInt16LE(0))for(let r=e.readUInt16LE(2);r+8<=e.length;){let a=e.readUInt16LE(r),i=e.readUInt16LE(r+2),n=e.readUInt32LE(r+4);if(n<=0||r+n>e.length)break;if(1===a)t=function(e){if(e.length<28)return[];let t=e.readUInt32LE(8),r=e.readUInt32LE(16),a=e.readUInt32LE(20),i=(256&r)!=0,n=[];for(let r=0;r<t;r+=1){let t=28+4*r;if(t+4>e.length)break;let o=a+e.readUInt32LE(t);n.push(i?function(e,t){let[,r]=r0(e,t),[a,i]=r0(e,t+r),n=t+r+i;return e.subarray(n,n+a).toString("utf8")}(e,o):function(e,t){let[r,a]=function(e,t){let r=e.readUInt16LE(t);return(32768&r)==0?[r,2]:[(32767&r)<<16|e.readUInt16LE(t+2),4]}(e,t),i=t+a;return rZ.decode(e.subarray(i,i+2*r))}(e,o))}return n}(e.subarray(r,r+n));else if(258===a&&t){let a=function(e,t,r,a){if(r<36||t+r>e.length||"manifest"!==a[e.readUInt32LE(t+20)])return;let i=e.readUInt16LE(t+24),n=e.readUInt16LE(t+26),o=e.readUInt16LE(t+28),s=t+i;for(let t=0;t<o;t+=1){let r=s+t*n;if(r+20>e.length)break;if("package"!==a[e.readUInt32LE(r+4)])continue;let i=e.readUInt32LE(r+8);if(0xffffffff!==i)return a[i];let o=e.readUInt8(r+15),l=e.readUInt32LE(r+16);if(3===o)return a[l];break}}(e,r,i,t);if(a)return a}r+=n}}(t);if(i)return i}return await r1(e)}async function rQ(e,t){try{let r=await c("unzip",["-p",e,t],{allowFailure:!0,binaryStdout:!0});if(0!==r.exitCode||!r.stdoutBuffer||0===r.stdoutBuffer.length)return;return r.stdoutBuffer}catch{return}}function r0(e,t){let r=e.readUInt8(t);return(128&r)==0?[r,1]:[(127&r)<<8|e.readUInt8(t+1),2]}async function r1(e){let t=await r2();if(!t)return;let r=await c(t,["dump","badging",e],{allowFailure:!0});if(0!==r.exitCode)return;let a=r.stdout.match(/package:\s+name='([^']+)'/);return a?.[1]}async function r2(){if(void 0!==e)return e??void 0;let t=process.env.ANDROID_HOME?.trim();if(!t){e=null;return}try{let r=i.join(t,"build-tools");for(let t of(await a.readdir(r)).sort((e,t)=>t.localeCompare(e,void 0,{numeric:!0}))){let n=i.join(r,t,"aapt");try{return await a.access(n),e=n,n}catch{}}}catch{}e=null}async function r3(e,t){let r="url"===e.kind&&rq(e.url),a=await rV({source:e,isInstallablePath:(e,t)=>{var r;let a;return t.isFile()&&(r=e,".apk"===(a=i.extname(r).toLowerCase())||".aab"===a)},installableLabel:"Android installable (.apk or .aab)",allowArchiveExtraction:"url"!==e.kind||r,signal:t?.signal}),n=t?.resolveIdentity===!1?{}:await r4(a.installablePath);return{archivePath:a.archivePath,installablePath:a.installablePath,packageName:n.packageName,cleanup:a.cleanup}}async function r4(e){let t=i.extname(e).toLowerCase();return".apk"!==t&&".aab"!==t?{}:{packageName:await rY(e)}}let r8={settings:{type:"intent",value:"android.settings.SETTINGS"}},r5="android.intent.category.LAUNCHER",r6="android.intent.category.LEANBACK_LAUNCHER",r9="android.intent.category.DEFAULT";async function r7(e,t){let r=t.trim();if("package"===rT(r))return{type:"package",value:r};let a=r8[r.toLowerCase()];if(a)return a;let i=(await c("adb",rl(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase()));if(1===i.length)return{type:"package",value:i[0]};if(i.length>1)throw new w("INVALID_ARGS",`Multiple packages matched "${t}"`,{matches:i});throw new w("APP_NOT_INSTALLED",`No package found matching "${t}"`)}async function ae(e,t="all"){let r=await at(e);return("user-installed"===t?(await aa(e)).filter(e=>r.has(e)):Array.from(r)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:ai(e)}))}async function at(e){let t=new Set;for(let r of ar(e,{includeFallbackWhenUnknown:!0})){let a=await c("adb",rl(e,["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",r]),{allowFailure:!0});if(0===a.exitCode&&0!==a.stdout.trim().length)for(let e of a.stdout.split("\n")){let r=e.trim();if(!r)continue;let a=r.split(/\s+/)[0],i=a.includes("/")?a.split("/")[0]:a;i&&t.add(i)}}return t}function ar(e,t={}){return"tv"===e.target?[r6]:"mobile"===e.target?[r5]:t.includeFallbackWhenUnknown?[r5,r6]:[r5]}async function aa(e){return(await c("adb",rl(e,["shell","pm","list","packages","-3"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean)}function ai(e){let t=new Set(["com","android","google","app","apps","service","services","mobile","client"]),r=e.split(".").flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),a=r[r.length-1]??e;for(let e=r.length-1;e>=0;e-=1){let i=r[e];if(!t.has(i)){a=i;break}}return a.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function an(e){let t=await ao(e,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(t)return t;let r=await ao(e,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return r||{}}async function ao(e,t){for(let r of t){let t=function(e){for(let t of[/mCurrentFocus=Window\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mFocusedApp=AppWindowToken\{[^}]*\s([\w.]+)\/([\w.$]+)/,/mResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/,/ResumedActivity:.*?\s([\w.]+)\/([\w.$]+)/]){let r=t.exec(e);if(r)return{package:r[1],activity:r[2]}}return null}((await c("adb",rl(e,r),{allowFailure:!0})).stdout??"");if(t)return t}return null}async function as(e,t,r){e.booted||await rx(e.id);let a=t.trim();if(rp(a)){if(r)throw new w("INVALID_ARGS","Activity override is not supported when opening a deep link URL");await c("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.VIEW","-d",a]));return}let i=await r7(e,t),n=ar(e)[0]??r5;if("intent"===i.type){if(r)throw new w("INVALID_ARGS","Activity override requires a package name, not an intent");await c("adb",rl(e,["shell","am","start","-W","-a",i.value]));return}if(r){let t=r.includes("/")?r:`${i.value}/${r.startsWith(".")?r:`.${r}`}`;await c("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-n",t]));return}let o=await c("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-p",i.value]),{allowFailure:!0});if(0===o.exitCode&&!ad(o.stdout,o.stderr))return;let s=await al(e,i.value);if(!s)throw new w("COMMAND_FAILED",`Failed to launch ${i.value}`,{stdout:o.stdout,stderr:o.stderr});await c("adb",rl(e,["shell","am","start","-W","-a","android.intent.action.MAIN","-c",r9,"-c",n,"-n",s]))}async function al(e,t){for(let r of Array.from(new Set(ar(e,{includeFallbackWhenUnknown:!0})))){let a=await c("adb",rl(e,["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",r,t]),{allowFailure:!0});if(0!==a.exitCode)continue;let i=au(a.stdout);if(i)return i}return null}function ad(e,t){let r=`${e}
12
+ ${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(r)}function au(e){let t=e.split("\n").map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;e-=1){let r=t[e];if(r.includes("/"))return r.split(/\s+/)[0]}return null}async function ac(e){e.booted||await rx(e.id)}async function ap(e,t){if("settings"===t.trim().toLowerCase())return void await c("adb",rl(e,["shell","am","force-stop","com.android.settings"]));let r=await r7(e,t);if("intent"===r.type)throw new w("INVALID_ARGS","Close requires a package name, not an intent");await c("adb",rl(e,["shell","am","force-stop",r.value]))}async function af(e,t){let r=await r7(e,t);if("intent"===r.type)throw new w("INVALID_ARGS","App uninstall requires a package name, not an intent");let a=await c("adb",rl(e,["uninstall",r.value]),{allowFailure:!0});if(0!==a.exitCode){let e=`${a.stdout}
13
+ ${a.stderr}`.toLowerCase();if(!e.includes("unknown package")&&!e.includes("not installed"))throw new w("COMMAND_FAILED",`adb uninstall failed for ${r.value}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return{package:r.value}}let am=null;async function ah(){let e=`${process.env.PATH??""}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??""}`;if(am?.key===e)return am.invocation;if(await I("bundletool")){let t={cmd:"bundletool",prefixArgs:[]};return am={key:e,invocation:t},t}let t=process.env.AGENT_DEVICE_BUNDLETOOL_JAR?.trim();if(!t)throw new w("TOOL_MISSING","bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.");try{await L.access(t)}catch{throw new w("TOOL_MISSING",`AGENT_DEVICE_BUNDLETOOL_JAR points to a missing file: ${t}`)}let r={cmd:"java",prefixArgs:["-jar",t]};return am={key:e,invocation:r},r}async function aw(e){let t=await ah();await c(t.cmd,[...t.prefixArgs,...e])}async function ag(e,t){let r,a=await L.mkdtemp(i.join(T.tmpdir(),"agent-device-aab-")),n=i.join(a,"bundle.apks"),o=(r=process.env.AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE?.trim())&&r.length>0?r:"universal";try{await aw(["build-apks","--bundle",t,"--output",n,"--mode",o]),await aw(["install-apks","--apks",n,"--device-id",e.id])}finally{await L.rm(a,{recursive:!0,force:!0})}}async function aI(e,t){".aab"===i.extname(t).toLowerCase()?await ag(e,t):await c("adb",rl(e,["install","-r",t]))}async function aA(e){return new Set((await c("adb",rl(e,["shell","pm","list","packages"]))).stdout.split("\n").map(e=>e.replace("package:","").trim()).filter(Boolean))}async function av(e,t){let r=Array.from(await aA(e)).filter(e=>!t.has(e));if(1===r.length)return r[0]}async function ay(e,t){e.booted||await rx(e.id),await aI(e,t)}async function ab(e,t,r){let a=r?void 0:await aA(e);return await ay(e,t),r??(a?await av(e,a):void 0)}async function aN(e,t){e.booted||await rx(e.id);let r=await r3({kind:"path",path:t});try{let t=await ab(e,r.installablePath,r.packageName),a=t?ai(t):void 0;return{archivePath:r.archivePath,installablePath:r.installablePath,packageName:t,appName:a,launchTarget:t}}finally{await r.cleanup()}}async function a_(e,t,r){e.booted||await rx(e.id);let{package:a}=await af(e,t),i=await r3({kind:"path",path:r},{resolveIdentity:!1});try{return await ay(e,i.installablePath),{package:a}}finally{await i.cleanup()}}function aS(e){let t=aD(e),r=e=>{let r=aE(t,e);if(null!==r)return"true"===r};return{text:aE(t,"text"),desc:aE(t,"content-desc"),resourceId:aE(t,"resource-id"),className:aE(t,"class"),bounds:aE(t,"bounds"),clickable:r("clickable"),enabled:r("enabled"),focusable:r("focusable"),focused:r("focused")}}function aD(e){let t=new Map,r=e.indexOf(" "),a=e.lastIndexOf(">");if(r<0||a<=r)return t;let i=/([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/y,n=r;for(;n<a;){for(;n<a;){let t=e[n];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)break;n+=1}if(n>=a)break;let r=e[n];if("/"===r||">"===r)break;i.lastIndex=n;let o=i.exec(e);if(!o)break;t.set(o[1],o[3]),n=i.lastIndex}return t}function aE(e,t){return e.get(t)??null}function ak(e){if(!e)return;let t=/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/.exec(e);if(!t)return;let r=Number(t[1]),a=Number(t[2]);return{x:r,y:a,width:Math.max(0,Number(t[3])-r),height:Math.max(0,Number(t[4])-a)}}function aL(e){return e?e.toLowerCase():""}function aO(e){let t=e.trim();return!!t&&/^[\w.]+:id\/[\w.-]+$/i.test(t)}async function aM(e,t={}){return function(e,t,r){let a=function(e){let t={type:null,label:null,value:null,identifier:null,depth:-1,children:[]},r=[t],a=/<node\b[^>]*>|<\/node>/g,i=a.exec(e);for(;i;){let t=i[0];if(t.startsWith("</node")){r.length>1&&r.pop(),i=a.exec(e);continue}let n=aS(t),o=ak(n.bounds),s=r[r.length-1],l={type:n.className,label:n.text||n.desc,value:n.text,identifier:n.resourceId,rect:o,enabled:n.enabled,hittable:n.clickable??n.focusable,depth:s.depth+1,parentIndex:void 0,children:[]};s.children.push(l),t.endsWith("/>")||r.push(l),i=a.exec(e)}return t}(e),i=[],n=!1,o=r.depth??1/0,s=r.scope?function(e,t){let r=t.toLowerCase(),a=[...e.children];for(;a.length>0;){let e=a.shift(),t=e.label?.toLowerCase()??"",i=e.value?.toLowerCase()??"",n=e.identifier?.toLowerCase()??"";if(t.includes(r)||i.includes(r)||n.includes(r))return e;a.push(...e.children)}return null}(a,r.scope):null,l=s?[s]:a.children,d=new Map,u=e=>{let t=d.get(e);if(void 0!==t)return t;for(let t of e.children)if(t.hittable||u(t))return d.set(e,!0),!0;return d.set(e,!1),!1},c=(e,t,a,s=!1,l=!1)=>{var d,p,f,m,h,w;let g,I,A,v,y,b,N,_;if(i.length>=800){n=!0;return}if(t>o)return;let S=!!r.raw||(d=e,p=r,f=s,m=u(e),h=l,I=aL(d.type),A=!!(d.label&&d.label.trim().length>0),v=!!(d.identifier&&d.identifier.trim().length>0),y=A&&!aO(d.label??""),b=v&&!aO(d.identifier??""),N=(g=(w=I).split(".").pop()??w).includes("layout")||"viewgroup"===g||"view"===g,_="imageview"===I||"imagebutton"===I,p.interactiveOnly?!!d.hittable||!!(y||b)&&!_&&(!N||!!h)&&(f||m||h):p.compact?y||b||!!d.hittable:!N&&!_||!!d.hittable||!!y||!!b&&!!m||m),D=a;S&&(D=i.length,i.push({index:D,type:e.type??void 0,label:e.label??void 0,value:e.value??void 0,identifier:e.identifier??void 0,rect:e.rect,enabled:e.enabled,hittable:e.hittable,depth:t,parentIndex:a}));let E=s||!!e.hittable,k=l||function(e){if(!e)return!1;let t=aL(e);return t.includes("recyclerview")||t.includes("listview")||t.includes("gridview")}(e.type);for(let r of e.children)if(c(r,t+1,D,E,k),n)return};for(let e of l)if(c(e,0,void 0,!1,!1),n)break;return n?{nodes:i,truncated:n}:{nodes:i}}(await ax(e),0,t)}async function ax(e){return et(()=>aC(e),{shouldRetry:aT})}async function aC(e){var t,r,a;let i,n,o=await c("adb",rl(e,["exec-out","uiautomator","dump","/dev/tty"]),{allowFailure:!0});if(0===o.exitCode){let e=aR(o.stdout,o.stderr);if(e)return e}let s="/sdcard/window_dump.xml",l=await c("adb",rl(e,["shell","uiautomator","dump",s])),d=(t=s,r=l.stdout,a=l.stderr,i=`${r}
14
+ ${a}`,n=/dumped to:\s*(\S+)/i.exec(i),n?.[1]??t),u=await c("adb",rl(e,["shell","cat",d])),p=aR(u.stdout,u.stderr);if(!p)throw new w("COMMAND_FAILED","uiautomator dump did not return XML",{stdout:u.stdout,stderr:u.stderr});return p}function aR(e,t){let r=`${e}
15
+ ${t}`,a=r.indexOf("<?xml"),i=a>=0?a:r.indexOf("<hierarchy");if(i<0)return null;let n=r.lastIndexOf("</hierarchy>");if(n<0||n<i)return null;let o=r.slice(i,n+12).trim();return o.length>0?o:null}function aT(e){if(!(e instanceof w)||"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 aP(e,t,r){await c("adb",rl(e,["shell","input","tap",String(t),String(r)]))}async function a$(e,t,r,a,i,n=250){await c("adb",rl(e,["shell","input","swipe",String(t),String(r),String(a),String(i),String(n)]))}async function aU(e){await c("adb",rl(e,["shell","input","keyevent","4"]))}async function aF(e){await c("adb",rl(e,["shell","input","keyevent","3"]))}async function aV(e){await c("adb",rl(e,["shell","input","keyevent","187"]))}async function aG(e,t,r,a=800){await c("adb",rl(e,["shell","input","swipe",String(t),String(r),String(t),String(r),String(a)]))}async function aB(e,t){let r=aK(t);if(!r||"ok"!==await aX(e,t))try{let r=t.replace(/ /g,"%s");await c("adb",rl(e,["shell","input","text",r]))}catch(e){if(r&&function(e){if(!(e instanceof w)||"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 w("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 aj(e,t,r){await aP(e,t,r)}async function aq(e,t,r,a){let i=Array.from(a).length,n=aK(a),o=[{strategy:"input_text",clearPadding:12,minClear:8,maxClear:48}];n||(o.push({strategy:"clipboard_paste",clearPadding:12,minClear:8,maxClear:48}),o.push({strategy:"chunked_input",clearPadding:24,minClear:16,maxClear:96}));let s=null;for(let n of o){var l,d;await aj(e,t,r);let o=(l=i+n.clearPadding,d=n.minClear,Math.max(d,Math.min(n.maxClear,l)));if(await aZ(e,o),"input_text"===n.strategy)await aB(e,a);else if("clipboard_paste"===n.strategy){if("ok"!==await aX(e,a))continue}else await aJ(e,a,1,15);if((s=await aY(e,t,r))===a)return}throw new w("COMMAND_FAILED","Android fill verification failed",{expected:a,actual:s??null})}async function aH(e,t,r=.6){let{width:a,height:i}=await az(e),n=Math.floor(a*r),o=Math.floor(i*r),s=Math.floor(a/2),l=Math.floor(i/2),d=s,u=l,p=s,f=l;switch(t){case"up":u=l-Math.floor(o/2),f=l+Math.floor(o/2);break;case"down":u=l+Math.floor(o/2),f=l-Math.floor(o/2);break;case"left":d=s-Math.floor(n/2),p=s+Math.floor(n/2);break;case"right":d=s+Math.floor(n/2),p=s-Math.floor(n/2);break;default:throw new w("INVALID_ARGS",`Unknown direction: ${t}`)}await c("adb",rl(e,["shell","input","swipe",String(d),String(u),String(p),String(f),"300"]))}async function aW(e,t){for(let r=0;r<8;r+=1){let r="";try{r=await ax(e)}catch(t){let e=t instanceof Error?t.message:String(t);throw new w("UNSUPPORTED_OPERATION",`uiautomator dump failed: ${e}`)}if(function(e,t){let r=t.toLowerCase(),a=/<node[^>]+>/g,i=a.exec(e);for(;i;){let t=aD(i[0]),n=(aE(t,"text")??"").toLowerCase(),o=(aE(t,"content-desc")??"").toLowerCase();if(n.includes(r)||o.includes(r)){let e=ak(aE(t,"bounds"));if(e)return{x:Math.floor(e.x+e.width/2),y:Math.floor(e.y+e.height/2)};return{x:0,y:0}}i=a.exec(e)}return null}(r,t))return;await aH(e,"down",.5)}throw new w("COMMAND_FAILED",`Could not find element containing "${t}" after scrolling`)}async function az(e){let t=(await c("adb",rl(e,["shell","wm","size"]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!t)throw new w("COMMAND_FAILED","Unable to read screen size");return{width:Number(t[1]),height:Number(t[2])}}async function aJ(e,t,r,a){let i=Math.max(1,Math.floor(r)),n=Array.from(t);for(let t=0;t<n.length;t+=i){let r=n.slice(t,t+i).join("");await aB(e,r),a>0&&t+i<n.length&&await rc(a)}}function aK(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 aX(e,t){let r=await c("adb",rl(e,["shell","cmd","clipboard","set","text",t]),{allowFailure:!0});return 0!==r.exitCode?"failed":ru(r.stdout,r.stderr)?"unsupported":0===(await c("adb",rl(e,["shell","input","keyevent","KEYCODE_PASTE"]),{allowFailure:!0})).exitCode||0===(await c("adb",rl(e,["shell","input","keyevent","279"]),{allowFailure:!0})).exitCode?"ok":"failed"}async function aZ(e,t){let r=Math.max(0,t);await c("adb",rl(e,["shell","input","keyevent","KEYCODE_MOVE_END"]),{allowFailure:!0});for(let t=0;t<r;t+=24){let a=Math.min(24,r-t);await c("adb",rl(e,["shell","input","keyevent",...Array(a).fill("KEYCODE_DEL")]),{allowFailure:!0})}}async function aY(e,t,r){let a,i=await ax(e),n=/<node\b[^>]*>/g,o=null,s=null,l=null;for(;null!==(a=n.exec(i));){let e=aS(a[0]),i=ak(e.bounds);if(!i)continue;let n=e.className??"",d=(e.text??"").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),u=e.focused??!1;if(!d)continue;let c=Math.max(1,i.width*i.height),p=t>=i.x&&t<=i.x+i.width&&r>=i.y&&r<=i.y+i.height;if(u&&aQ(n)){(!o||c<=o.area)&&(o={text:d,area:c});continue}if(p&&aQ(n)){(!s||c<=s.area)&&(s={text:d,area:c});continue}p&&(!l||c<=l.area)&&(l={text:d,area:c})}return o?.text??s?.text??l?.text??null}function aQ(e){let t=e.toLowerCase();return t.includes("edittext")||t.includes("textfield")}async function a0(e){let t=await c("adb",rl(e,["shell","dumpsys","input_method"]),{allowFailure:!0});if(0!==t.exitCode)throw new w("COMMAND_FAILED","Failed to query Android keyboard state",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});return function(e){let t=function(e){let t=new Map;for(let r of e.matchAll(/\b(mInputShown|mIsInputViewShown|isInputViewShown)=([a-zA-Z]+)\b/g)){let e=r[1],a=r[2]?.toLowerCase();e&&("true"===a||"false"===a)&&t.set(e,"true"===a)}if(0===t.size)return null;for(let e of t.values())if(e)return!0;return!1}(e),r=t??!1;if(null===t){let t=e.match(/\bmImeWindowVis=0x([0-9a-fA-F]+)\b/);if(t?.[1]){let e=Number.parseInt(t[1],16);Number.isNaN(e)||(r=(1&e)!=0)}}let a=Array.from(e.matchAll(/\binputType=0x([0-9a-fA-F]+)\b/gi)),i=a.length>0?a[a.length-1]?.[1]:void 0,n=i?`0x${i.toLowerCase()}`:void 0;return{visible:r,inputType:n,type:n?function(e){let t=Number.parseInt(e.replace(/^0x/i,""),16);if(Number.isNaN(t))return"unknown";let r=15&t;if(2===r)return"number";if(3===r)return"phone";if(4===r)return"datetime";if(1!==r)return"unknown";let a=4080&t;return 32===a||208===a?"email":128===a||224===a||144===a?"password":"text"}(n):void 0}}(t.stdout)}async function a1(e){let t=await a0(e),r=t,a=0;for(;r.visible&&a<2;)await aU(e),a+=1,await rc(120),r=await a0(e);return{attempts:a,wasVisible:t.visible,dismissed:t.visible&&!r.visible,visible:r.visible,inputType:r.inputType,type:r.type}}async function a2(e){let t,r;return(r=(t=(await a4(e,["shell","cmd","clipboard","get","text"],"read")).replace(/\r\n/g,"\n").replace(/\n$/,"")).match(/^clipboard text:\s*(.*)$/i))?r[1]??"":"null"===t.trim().toLowerCase()?"":t}async function a3(e,t){await a4(e,["shell","cmd","clipboard","set","text",t],"write")}async function a4(e,t,r){let a=await c("adb",rl(e,t),{allowFailure:!0});if(ru(a.stdout,a.stderr))throw new w("UNSUPPORTED_OPERATION",`Android shell clipboard ${r} is not supported on this device.`);if(0!==a.exitCode)throw new w("COMMAND_FAILED",`Failed to ${r} Android clipboard text`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return a.stdout}let a8=["camera","microphone","photos","contacts","contacts-limited","notifications","calendar","location","location-always","media-library","motion","reminders","siri"];function a5(e){let t=e.trim().toLowerCase();if("grant"===t)return"grant";if("deny"===t)return"deny";if("reset"===t)return"reset";throw new w("INVALID_ARGS",`Invalid permission action: ${e}. Use grant|deny|reset.`)}function a6(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 w("INVALID_ARGS",`permission setting requires a target: ${a8.join("|")}`)}function a9(e){let t=e.trim().toLowerCase();if("light"===t)return"light";if("dark"===t)return"dark";if("toggle"===t)return"toggle";throw new w("INVALID_ARGS",`Invalid appearance state: ${e}. Use light|dark|toggle.`)}async function a7(e,t,r,a,i){switch(t.toLowerCase()){case"wifi":{let t=it(r);await c("adb",rl(e,["shell","svc","wifi",t?"enable":"disable"]));return}case"airplane":{let t=it(r);await c("adb",rl(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"])),await c("adb",rl(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]));return}case"location":{let t=it(r);await c("adb",rl(e,["shell","settings","put","secure","location_mode",t?"3":"0"]));return}case"appearance":{let t=await ir(e,r);await c("adb",rl(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 w("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await ie(e,t);return}case"permission":{if(!a)throw new w("INVALID_ARGS","permission setting requires an active app in session");let t=a5(r),n=function(e,t){let r=a6(e);if(t?.trim())throw new w("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new w("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(i?.permissionTarget,i?.permissionMode);if("notifications"===n.kind)return void await ii(e,a,t,n);let o="grant"===t?"grant":"revoke";if("photos"===n.type)return void await ia(e,a,o);await c("adb",rl(e,["shell","pm",o,a,n.value]));return}default:throw new w("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function ie(e,t){var r;let a,i,n=(r=e,i=[["shell","cmd","fingerprint","touch",a="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",a]],"emulator"===r.kind&&i.push(["emu","finger","touch",a]),i),o=[];for(let t of n){let r=await c("adb",rl(e,t),{allowFailure:!0});if(0===r.exitCode)return;o.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let s=o.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(o.length>0&&o.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
16
+ ${r}`.toLowerCase()).includes("unknown command")||a.includes("can't find service: fingerprint")||a.includes("service fingerprint was not found")||a.includes("fingerprint cmd unavailable")||a.includes("emu command is not supported")||a.includes("emulator console is not running")||a.includes("fingerprint")&&a.includes("not found")}))throw new w("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 w("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:s})}function it(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 w("INVALID_ARGS",`Invalid setting state: ${e}`)}async function ir(e,t){let r=a9(t);if("toggle"!==r)return r;let a=await c("adb",rl(e,["shell","cmd","uimode","night"]),{allowFailure:!0});if(0!==a.exitCode)throw new w("COMMAND_FAILED","Failed to read current Android appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
17
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"yes"===a?"dark":"no"===a?"light":"auto"===a?"auto":null}(a.stdout,a.stderr);if(!i)throw new w("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 ia(e,t,r){let a=await io(e),i=[];for(let n of null!==a&&a>=33?["android.permission.READ_MEDIA_IMAGES","android.permission.READ_EXTERNAL_STORAGE"]:["android.permission.READ_EXTERNAL_STORAGE","android.permission.READ_MEDIA_IMAGES"]){let a=await c("adb",rl(e,["shell","pm",r,t,n]),{allowFailure:!0});if(0===a.exitCode)return;i.push({permission:n,stderr:a.stderr,exitCode:a.exitCode})}throw new w("COMMAND_FAILED",`Failed to ${r} Android photos permission`,{appPackage:t,sdkInt:a,attempts:i})}async function ii(e,t,r,a){"grant"===r?await c("adb",rl(e,["shell","pm","grant",t,a.permission]),{allowFailure:!0}):(await c("adb",rl(e,["shell","pm","revoke",t,a.permission]),{allowFailure:!0}),"reset"===r&&(await c("adb",rl(e,["shell","pm","clear-permission-flags",t,a.permission,"user-set"]),{allowFailure:!0}),await c("adb",rl(e,["shell","pm","clear-permission-flags",t,a.permission,"user-fixed"]),{allowFailure:!0}))),await c("adb",rl(e,["shell","appops","set",t,a.appOps,"grant"===r?"allow":"deny"===r?"deny":"default"]))}async function io(e){let t=await c("adb",rl(e,["shell","getprop","ro.build.version.sdk"]),{allowFailure:!0});if(0!==t.exitCode)return null;let r=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(r)||r<=0?null:r}async function is(e,t,r){let a="string"==typeof r.action&&r.action.trim()?r.action.trim():`${t}.TEST_PUSH`,i=["shell","am","broadcast","-a",a,"-p",t],n="string"==typeof r.receiver?r.receiver.trim():"";n&&i.push("-n",n);let o=r.extras;if(void 0!==o&&("object"!=typeof o||null===o||Array.isArray(o)))throw new w("INVALID_ARGS","Android push payload extras must be an object");let s=0;for(let[e,t]of Object.entries(o??{}))e&&(function(e,t,r){if("string"==typeof r)return e.push("--es",t,r);if("boolean"==typeof r)return e.push("--ez",t,r?"true":"false");if("number"==typeof r&&Number.isFinite(r))return Number.isInteger(r)?e.push("--ei",t,String(r)):e.push("--ef",t,String(r));throw new w("INVALID_ARGS",`Unsupported Android broadcast extra type for "${t}". Use string, boolean, or number.`)}(i,e,t),s+=1);return await c("adb",rl(e,i)),{action:a,extrasCount:s}}let il=Buffer.from([137,80,78,71,13,10,26,10]),id={enableDemoMode:ic,settle:rc,capture:im,disableDemoMode:ip};async function iu(e,t,r=id){await r.enableDemoMode(e);try{await r.settle(1e3),await r.capture(e,t)}finally{await r.disableDemoMode(e).catch(()=>{})}}async function ic(e){let t=t=>c("adb",rl(e,["shell",t]),{allowFailure:!0});await t("settings put global sysui_demo_allowed 1");let r=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await r("clock -e hhmm 0941"),await r("notifications -e visible false")}async function ip(e){await c("adb",rl(e,["shell","am broadcast -a com.android.systemui.demo -e command exit"]),{allowFailure:!0})}async function im(e,t){let r=await c("adb",rl(e,["exec-out","screencap","-p"]),{binaryStdout:!0});if(!r.stdoutBuffer)throw new w("COMMAND_FAILED","Failed to capture screenshot");let a=r.stdoutBuffer.indexOf(il);if(a<0)throw new w("COMMAND_FAILED","Screenshot data does not contain a valid PNG header");let i=function(e,t){let r=t+il.length;for(;r+8<=e.length;){let t=e.readUInt32BE(r),a=r+4,i=e.toString("ascii",a,a+4),n=r+12+t;if(n>e.length)break;if("IEND"===i)return n;r=n}return null}(r.stdoutBuffer,a);if(!i)throw new w("COMMAND_FAILED","Screenshot data does not contain a complete PNG payload");await L.writeFile(t,r.stdoutBuffer.subarray(a,i))}let ih=ey(process.env.AGENT_DEVICE_IOS_BOOT_TIMEOUT_MS,Z,5e3),iw=ey(process.env.AGENT_DEVICE_IOS_SIMCTL_LIST_TIMEOUT_MS,X,1e3),ig=ey(process.env.AGENT_DEVICE_IOS_APP_LAUNCH_TIMEOUT_MS,3e4,5e3),iI=ey(process.env.AGENT_DEVICE_IOS_DEVICECTL_TIMEOUT_MS,2e4,1e3),iA=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_FOCUS_TIMEOUT_MS,1e4,1e3),iv=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_SCREENSHOT_TIMEOUT_MS,2e4,1e3),iy=ey(process.env.AGENT_DEVICE_IOS_RUNNER_SCREENSHOT_COPY_TIMEOUT_MS,2e4,1e3);async function ib(e,t){let r=["devicectl",...e],a=await c("xcrun",r,{allowFailure:!0,timeoutMs:iI});if(0===a.exitCode)return;let i=String(a.stdout??""),n=String(a.stderr??"");throw new w("COMMAND_FAILED",`Failed to ${t.action}`,{cmd:"xcrun",args:r,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:t.deviceId,hint:iD(i,n)??iS})}async function iN(e,t){let r=i.join(T.tmpdir(),`agent-device-ios-apps-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),a=["devicectl","device","info","apps","--device",e.id,"--include-all-apps","--json-output",r],n=await c("xcrun",a,{allowFailure:!0,timeoutMs:iI});try{var o,s;if(0!==n.exitCode){let t=String(n.stdout??""),r=String(n.stderr??"");throw new w("COMMAND_FAILED","Failed to list iOS apps",{cmd:"xcrun",args:a,exitCode:n.exitCode,stdout:t,stderr:r,deviceId:e.id,hint:iD(t,r)??iS})}let i=await L.readFile(r,"utf8");return o=i_(JSON.parse(i)),s=t,"user-installed"===s?o.filter(e=>!e.bundleId.startsWith("com.apple.")):o}catch(t){if(t instanceof w)throw t;throw new w("COMMAND_FAILED","Failed to parse iOS apps list",{deviceId:e.id,cause:String(t)})}finally{await L.unlink(r).catch(()=>{})}}function i_(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let r=[];for(let e of t){if(!e||"object"!=typeof e)continue;let t="string"==typeof e.bundleIdentifier?e.bundleIdentifier.trim():"";if(!t)continue;let a="string"==typeof e.name&&e.name.trim().length>0?e.name.trim():t;r.push({bundleId:t,name:a})}return r}let iS="Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.";function iD(e,t){let r=`${e}
18
+ ${t}`.toLowerCase();return r.includes("device is busy")&&r.includes("connecting")?"iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.":r.includes("coredeviceservice")&&r.includes("timed out")?"CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.":null}function iE(e){if(!(e instanceof w)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{};if(4!==t.exitCode)return!1;let r=String(t.stderr??"").toLowerCase();return r.includes("fbsopenapplicationserviceerrordomain")&&r.includes("the request to open")}async function ik(e,t){let r=await c("xcrun",eO(e,["get_app_container",e.id,t]),{allowFailure:!0});if(0!==r.exitCode)return{installed:!1};let a=r.stdout.trim();if(!a)return{installed:!1};let i=await c("plutil",["-extract","CFBundleExecutable","raw","-o","-",`${a}/Info.plist`],{allowFailure:!0});if(0!==i.exitCode||!i.stdout.trim())return{installed:!0};let n=i.stdout.trim(),o=`${a}/${n}`,s=await c("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 iL(e,t){if("simulator"!==e.kind)throw new w("UNSUPPORTED_OPERATION",`${t} is only supported on iOS simulators`)}async function iO(){await c("open",["-a","Simulator"],{allowFailure:!0,timeoutMs:iA})}async function iM(e){let t,r;if("simulator"!==e.kind||"Booted"===await iC(e))return;let a=Q.fromTimeoutMs(ih);try{await ee(async({deadline:a})=>{if(a?.isExpired())throw new w("COMMAND_FAILED","iOS simulator boot deadline exceeded",{timeoutMs:ih});let i=Math.max(1e3,a?.remainingMs()??ih),n=await c("xcrun",eO(e,["boot",e.id]),{allowFailure:!0,timeoutMs:i});t={stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.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 w("COMMAND_FAILED","simctl boot failed",{stdout:t.stdout,stderr:t.stderr,exitCode:t.exitCode});let l=await c("xcrun",eO(e,["bootstatus",e.id,"-b"]),{allowFailure:!0,timeoutMs:i});if(r={stdout:String(l.stdout??""),stderr:String(l.stderr??""),exitCode:l.exitCode},0!==r.exitCode)throw new w("COMMAND_FAILED","simctl bootstatus failed",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});let d=await iC(e);if("Booted"!==d)throw new w("COMMAND_FAILED","Simulator is still booting",{state:d})},{maxAttempts:3,baseDelayMs:500,maxDelayMs:2e3,jitter:.2,shouldRetry:e=>{let a=eh({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});return"IOS_BOOT_TIMEOUT"!==a&&"CI_RESOURCE_STARVATION_SUSPECTED"!==a}},{deadline:a,phase:"boot",classifyReason:e=>eh({error:e,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}})})}catch(n){let i=eh({error:n,stdout:r?.stdout??t?.stdout,stderr:r?.stderr??t?.stderr,context:{platform:"ios",phase:"boot"}});throw new w("COMMAND_FAILED","iOS simulator failed to boot",{platform:"ios",deviceId:e.id,timeoutMs:ih,elapsedMs:a.elapsedMs(),reason:i,hint:ew(i),boot:t,bootstatus:r})}}async function ix(e){let t=eO(e,["shutdown",e.id]),r=await c("xcrun",t,{allowFailure:!0,timeoutMs:15e3});return{success:0===r.exitCode,exitCode:r.exitCode,stdout:String(r.stdout??""),stderr:String(r.stderr??"")}}async function iC(e){let t="string"==typeof e?e:e.id,r="string"==typeof e?eL(["list","devices","-j"]):eO(e,["list","devices","-j"]),a=await c("xcrun",r,{allowFailure:!0,timeoutMs:iw});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let r of Object.values(e.devices??{})){let e=r.find(e=>e.udid===t);if(e)return e.state}return null}catch{return null}}async function iR(e,t){try{let r=await c("plutil",["-extract",t,"raw","-o","-",e],{allowFailure:!0});if(0===r.exitCode){let e=String(r.stdout??"").trim();if(e.length>0)return e}}catch{}try{let r=await L.readFile(e,"utf8");return function(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=e.match(RegExp(`<key>\\s*${r}\\s*<\\/key>\\s*<string>([\\s\\S]*?)<\\/string>`,"i"));if(!a?.[1])return;let i=a[1].trim().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&amp;/g,"&");return i.length>0?i:void 0}(r,t)}catch{return}}async function iT(e,t){if("url"===e.kind&&!rq(e.url))throw new w("INVALID_ARGS","iOS install_from_source URL sources are only supported for trusted artifact services such as GitHub Actions and EAS. Use a path source for other hosts.");let r=await rV({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||rq(e.url),signal:t?.signal}),a=await i$(r.installablePath,t),i=await iP(a.installPath);return{archivePath:r.archivePath??(r.installablePath.toLowerCase().endsWith(".ipa")?r.installablePath:void 0),installablePath:a.installPath,bundleId:i.bundleId,appName:i.appName,cleanup:async()=>{await a.cleanup(),await r.cleanup()}}}async function iP(e){let t=i.join(e,"Info.plist"),[r,a,n]=await Promise.all([iR(t,"CFBundleIdentifier"),iR(t,"CFBundleDisplayName"),iR(t,"CFBundleName")]);return{bundleId:r,appName:a??n}}async function i$(e,t){if(!e.toLowerCase().endsWith(".ipa"))return{installPath:e,cleanup:async()=>{}};let r=await L.mkdtemp(i.join(T.tmpdir(),"agent-device-ios-ipa-")),a=async()=>{await L.rm(r,{recursive:!0,force:!0})};try{await c("ditto",["-x","-k",e,r]);let n=i.join(r,"Payload"),o=(await L.readdir(n,{withFileTypes:!0}).catch(()=>{throw new w("INVALID_ARGS","Invalid IPA: missing Payload directory")})).filter(e=>e.isDirectory()&&e.name.toLowerCase().endsWith(".app")).map(e=>({installPath:i.join(n,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 w("INVALID_ARGS","Invalid IPA: expected at least one .app under Payload, found 0");await iU(o);let s=t?.appIdentifierHint?.trim();if(s){let e=function(e,t){let r=t.toLowerCase(),a=e.filter(e=>e.bundleName.toLowerCase()===r);if(1===a.length)return a[0];if(a.length>1)throw new w("INVALID_ARGS",`Invalid IPA: multiple app bundles matched "${t}" by name. Use a bundle id hint instead.`);if(t.includes(".")){let t=e.filter(e=>e.bundleId?.toLowerCase()===r);if(1===t.length)return t[0]}}(o,s);if(e)return{installPath:e.installPath,cleanup:a};throw new w("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload and none matched "${s}". Available bundles: ${o.map(iF).join(", ")}`)}throw new w("INVALID_ARGS",`Invalid IPA: found ${o.length} .app bundles under Payload. Pass an app identifier or bundle name matching one of: ${o.map(iF).join(", ")}`)}catch(e){throw await a(),e}}async function iU(e){await Promise.all(e.map(async e=>{if(e.bundleId&&e.appName)return;let t=await iP(e.installPath);e.bundleId=e.bundleId??t.bundleId,e.appName=e.appName??t.appName}))}function iF(e){let t=e.bundleId??e.appName;return t?`${e.bundleName}.app (${t})`:`${e.bundleName}.app`}let iV=["--time","9:41","--dataNetwork","wifi","--wifiMode","active","--wifiBars","3","--batteryState","charged","--batteryLevel","100"],iG={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"},iB={1:"searching",2:"failed",3:"active"},ij={0:"notSupported",1:"searching",2:"failed",3:"active"};function iq(e,t,r){return c("xcrun",eO(e,t),r)}async function iH(e,t){var r,a;let i;await iz(e),t&&await iJ(e,(i=[],(r=t).dataNetwork&&i.push("--dataNetwork",r.dataNetwork),r.wifiMode&&i.push("--wifiMode",r.wifiMode),void 0!==r.wifiBars&&("wifi"===r.dataNetwork||r.wifiMode)&&i.push("--wifiBars",r.wifiBars),r.cellularMode&&i.push("--cellularMode",r.cellularMode),void 0!==r.cellularBars&&(r.cellularMode||(a=r.dataNetwork)&&"hide"!==a&&"wifi"!==a||void 0!==r.operatorName)&&i.push("--cellularBars",r.cellularBars),void 0!==r.operatorName&&i.push("--operatorName",r.operatorName),i))}async function iW(e){let t=await iq(e,["status_bar",e.id,"list"],{allowFailure:!0});if(0!==t.exitCode)throw new w("COMMAND_FAILED","Failed to read simulator status bar overrides",{exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr});return function(e){let t={};for(let r of e.split("\n").map(e=>e.trim()).filter(e=>e.length>0&&"Current Status Bar Overrides:"!==e&&!/^=+$/.test(e))){let e=/^DataNetworkType:\s+(\d+)$/.exec(r);if(e){let r=Number(e[1]),a=iG[r];if(!a)throw new w("COMMAND_FAILED",`Unsupported simulator data network type: ${r}`);t.dataNetwork=a;continue}let a=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(r);if(a){let e=iB[Number(a[1])];e&&(t.wifiMode=e),t.wifiBars=a[2];continue}let i=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(r);if(i){let e=Number(i[1]),r=ij[e];if(!r)throw new w("COMMAND_FAILED",`Unsupported simulator cellular mode: ${e}`);t.cellularMode=r,t.cellularBars=i[2];continue}let n=/^Operator Name:\s*(.*)$/.exec(r);if(n){t.operatorName=n[1]??"";continue}}return 0===Object.keys(t).length?null:t}(t.stdout)}async function iz(e){await iq(e,["status_bar",e.id,"clear"])}async function iJ(e,t){0!==t.length&&await iq(e,["status_bar",e.id,"override",...t])}function iK(e,t,r){k({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...function(e){if(!(e instanceof w))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}(r)}})}function iX(e,t,r){return c("xcrun",eO(e,t),r)}let iZ={ensureBooted:iM,prepareStatusBarForScreenshot:async function e(e){let t=null,r=!1;try{t=await iW(e),r=!0}catch(t){iK(e,"snapshot_failed",t)}try{await iz(e),await iJ(e,iV)}catch(t){iK(e,"prepare_failed",t)}return async()=>{await iH(e,r?t:null)}},captureWithRetry:i0,captureWithRunner:i1,shouldFallbackToRunner:i9};async function iY(e,t,r){if("simulator"===e.kind)return void await iQ(e,t,r);try{await ib(["device","screenshot","--device",e.id,t],{action:"capture iOS screenshot",deviceId:e.id});return}catch(t){if(!function(e){if(!(e instanceof w)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=`${e.message}
20
20
  ${r}
21
- ${i}`.toLowerCase();return a.includes("unknown option '--device'")||a.includes("unknown subcommand")&&a.includes("screenshot")||a.includes("unrecognized subcommand")&&a.includes("screenshot")}(t))throw t;aq(e,"devicectl_screenshot",t)}await aV(e,t,r)}async function aU(e,t,r,i=aT){if("simulator"!==e.kind)throw new g("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");await i.ensureBooted(e);try{await i.captureWithRetry(e,t);return}catch(t){if(!i.shouldFallbackToRunner(t))throw t;aq(e,"simctl_screenshot",t)}await i.captureWithRunner(e,t,r)}async function aF(e,t){let r=Q.fromTimeoutMs(ah);await a_(),await ee(async({attempt:r,deadline:i})=>{r>1&&await a_(),await aP(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,i?.remainingMs()??ah)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>aH(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function aV(e,t,r){let i=(await tu(e,{command:"screenshot",appBundleId:r})).message;if(!i)throw new g("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"simulator"===e.kind?await aj(e,i,t):await aG(e,i,t)}async function aG(e,t,r){let i=Q.fromTimeoutMs(aw),a={exitCode:1,stdout:"",stderr:""};for(let n of e2)if(0===(a=await f("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:aB(i,aw,"runner screenshot copy")})).exitCode)return;let n=a.stderr.trim()||a.stdout.trim()||`devicectl exited with code ${a.exitCode}`;throw new g("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function aj(e,t,r){let i=Q.fromTimeoutMs(aw),a="Unable to locate runner container for simulator screenshot";for(let n of e2){let s=await aP(e,["get_app_container",e.id,n,"data"],{allowFailure:!0,timeoutMs:aB(i,aw,"runner screenshot container lookup")});if(0!==s.exitCode){let e=s.stderr.trim();e&&(a=e);continue}let l=s.stdout.trim();if(!l){a="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=o.resolve(e),i=t.trim();if(!i)return[];let a=[],n=new Set,s=e=>{let t=o.normalize(e);n.has(t)||(n.add(t),a.push(t))},l=i.replace(/^\/+/,""),d=l.replace(/\\/g,"/");if(l&&s(o.join(r,l)),o.isAbsolute(i)&&s(o.normalize(i)),d.startsWith("tmp/"))s(o.join(r,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);s(o.join(r,t))}}let u=o.basename(i);return u&&s(o.join(r,"tmp",u)),a}(l,t))try{await L.copyFile(e,r);return}catch(e){a=e instanceof Error?e.message:String(e)}}throw new g("COMMAND_FAILED",`Failed to capture iOS screenshot: ${a}`)}function aB(e,t,r){let i=e.remainingMs();if(i>0)return i;throw new g("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function aq(e,t,r){let i=function(e){if(!(e instanceof g))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}(r);k({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...i}})}function aH(e){if(!(e instanceof g)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",i="string"==typeof t.stderr?t.stderr:"",a=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",n=`${e.message}
21
+ ${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;i8(e,"devicectl_screenshot",t)}await i1(e,t,r)}async function iQ(e,t,r,a=iZ){if("simulator"!==e.kind)throw new w("UNSUPPORTED_OPERATION","Simulator screenshot fallback flow supports only iOS simulators");await a.ensureBooted(e);let i=async()=>{};try{i=await a.prepareStatusBarForScreenshot(e)}catch(t){i5(e,"prepare_failed",t)}try{try{await a.captureWithRetry(e,t);return}catch(t){if(!a.shouldFallbackToRunner(t))throw t;i8(e,"simctl_screenshot",t)}await a.captureWithRunner(e,t,r)}finally{await i().catch(t=>i5(e,"restore_failed",t))}}async function i0(e,t){let r=Q.fromTimeoutMs(iv);await iO(),await ee(async({attempt:r,deadline:a})=>{r>1&&await iO(),await iX(e,["io",e.id,"screenshot",t],{timeoutMs:Math.max(1e3,a?.remainingMs()??iv)})},{maxAttempts:5,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>i9(e)},{deadline:r,phase:"ios_simulator_screenshot"})}async function i1(e,t,r){let a=(await tu(e,{command:"screenshot",appBundleId:r})).message;if(!a)throw new w("COMMAND_FAILED","Failed to capture iOS screenshot: runner returned no file path");"simulator"===e.kind?await i3(e,a,t):await i2(e,a,t)}async function i2(e,t,r){let a=Q.fromTimeoutMs(iy),i={exitCode:1,stdout:"",stderr:""};for(let n of e2)if(0===(i=await c("xcrun",["devicectl","device","copy","from","--device",e.id,"--source",t,"--destination",r,"--domain-type","appDataContainer","--domain-identifier",n],{allowFailure:!0,timeoutMs:i4(a,iy,"runner screenshot copy")})).exitCode)return;let n=i.stderr.trim()||i.stdout.trim()||`devicectl exited with code ${i.exitCode}`;throw new w("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}async function i3(e,t,r){let a=Q.fromTimeoutMs(iy),n="Unable to locate runner container for simulator screenshot";for(let o of e2){let s=await iX(e,["get_app_container",e.id,o,"data"],{allowFailure:!0,timeoutMs:i4(a,iy,"runner screenshot container lookup")});if(0!==s.exitCode){let e=s.stderr.trim();e&&(n=e);continue}let l=s.stdout.trim();if(!l){n="simctl get_app_container returned empty output";continue}for(let e of function(e,t){let r=i.resolve(e),a=t.trim();if(!a)return[];let n=[],o=new Set,s=e=>{let t=i.normalize(e);o.has(t)||(o.add(t),n.push(t))},l=a.replace(/^\/+/,""),d=l.replace(/\\/g,"/");if(l&&s(i.join(r,l)),i.isAbsolute(a)&&s(i.normalize(a)),d.startsWith("tmp/"))s(i.join(r,d));else{let e=d.lastIndexOf("/tmp/");if(e>=0){let t=d.slice(e+1);s(i.join(r,t))}}let u=i.basename(a);return u&&s(i.join(r,"tmp",u)),n}(l,t))try{await L.copyFile(e,r);return}catch(e){n=e instanceof Error?e.message:String(e)}}throw new w("COMMAND_FAILED",`Failed to capture iOS screenshot: ${n}`)}function i4(e,t,r){let a=e.remainingMs();if(a>0)return a;throw new w("COMMAND_FAILED",`iOS ${r} timed out after ${t}ms`,{timeoutMs:t,step:r})}function i8(e,t,r){let a=i6(r);k({level:"warn",phase:"ios_screenshot_fallback",data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:"runner",...a}})}function i5(e,t,r){k({level:"warn",phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...i6(r)}})}function i6(e){if(!(e instanceof w))return{reason:e instanceof Error?e.message:String(e)};let t=e.details??{},r=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):void 0;return{errorCode:e.code,reason:e.message,timeoutMs:"number"==typeof t.timeoutMs?t.timeoutMs:void 0,exitCode:"number"==typeof t.exitCode?t.exitCode:void 0,stderr:"string"==typeof t.stderr&&t.stderr.trim()?t.stderr:void 0,stdout:"string"==typeof t.stdout&&t.stdout.trim()?t.stdout:void 0,commandArgs:r}}function i9(e){if(!(e instanceof w)||"COMMAND_FAILED"!==e.code)return!1;let t=e.details??{},r="string"==typeof t.stdout?t.stdout:"",a="string"==typeof t.stderr?t.stderr:"",i=Array.isArray(t.args)?t.args.filter(e=>"string"==typeof e).join(" "):"",n=`${e.message}
22
22
  ${r}
23
- ${i}
24
- ${a}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let aW={settings:"com.apple.Preferences"},az=null;function aJ(e,t,r){return f("xcrun",eO(e,t),r)}function aK(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function aX(e,t){let r=t.trim();if(r.includes("."))return r;let i=aW[r.toLowerCase()];if(i)return i;let a=("simulator"===e.kind?await a7(e):await aI(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===a.length)return a[0].bundleId;if(a.length>1)throw new g("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:a});throw new g("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function aZ(e,t,r){let i=r?.url?.trim();if(i){if(!rp(i))throw new g("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await aD(e),await a_(),await aJ(e,["openurl",e.id,i]);return}let a=rf(r?.appBundleId??await aX(e,t),i);if(!a)throw new g("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await nl(e,a,{payloadUrl:i});return}let a=t.trim();if(rp(a)){if("simulator"===e.kind){await aD(e),await a_(),await aJ(e,["openurl",e.id,a]);return}let t=rf(r?.appBundleId,a);if(!t)throw new g("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await nl(e,t,{payloadUrl:a});return}let n=r?.appBundleId??await aX(e,t);"simulator"===e.kind?await ns(e,n):await nl(e,n)}async function aY(e){"simulator"!==e.kind||"Booted"!==await ak(e)&&(await aD(e),await a_())}async function aQ(e,t){let r=await aX(e,t);if("simulator"===e.kind){await aD(e);let t=eO(e,["terminate",e.id,r]),i=await f("xcrun",t,{allowFailure:!0});if(0!==i.exitCode){if(i.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new g("COMMAND_FAILED",`xcrun exited with code ${i.exitCode}`,{cmd:"xcrun",args:t,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode})}return}await ag(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function a0(e,t){let r=await aX(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],i=await f("xcrun",t,{allowFailure:!0,timeoutMs:am});if(0!==i.exitCode){let a=String(i.stdout??""),n=String(i.stderr??"");if(!aK(`${a}
25
- ${n}`.toLowerCase()))throw new g("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:i.exitCode,stdout:a,stderr:n,deviceId:e.id,hint:ay(a,n)??av})}return{bundleId:r}}await aD(e);let i=await aJ(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==i.exitCode&&!aK(`${i.stdout}
26
- ${i.stderr}`.toLowerCase()))throw new g("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return{bundleId:r}}async function a1(e,t,r){let i=await aO({kind:"path",path:t},r);try{return await a3(e,i.installablePath),{archivePath:i.archivePath,installablePath:i.installablePath,bundleId:i.bundleId,appName:i.appName,launchTarget:i.bundleId}}finally{await i.cleanup()}}async function a2(e,t,r){let{bundleId:i}=await a0(e,t);return await a1(e,r,{appIdentifierHint:t}),{bundleId:i}}async function a3(e,t){"simulator"!==e.kind?await ag(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await aD(e),await aJ(e,["install",e.id,t]))}async function a4(e){aS(e,"clipboard"),await aD(e);let t=await aJ(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new g("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 a8(e,t){aS(e,"clipboard"),await aD(e);let r=await aJ(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new g("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function a6(e,t,r){aS(e,"push"),await aD(e);let i=await L.mkdtemp(o.join(P.tmpdir(),"agent-device-ios-push-")),a=o.join(i,"payload.apns");try{await L.writeFile(a,`${JSON.stringify(r)}
27
- `,"utf8"),await aJ(e,["push",e.id,t,a])}finally{await L.rm(i,{recursive:!0,force:!0})}}async function a5(e,t,r,i,a){aS(e,"settings"),await aD(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=ne(r);await aJ(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(ne(r)?await aJ(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await aJ(e,["status_bar",e.id,"clear"]));case"location":{let t=ne(r);if(!i)throw new g("INVALID_ARGS","location setting requires an active app in session");await aJ(e,["privacy",e.id,t?"grant":"revoke","location",i]);return}case"faceid":case"touchid":{let t=nr[n],i=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new g("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await no(e,i,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await nt(e,r);await aJ(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!i)throw new g("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=ae(r))?"revoke":o,n=function(e,t){let r=at(e);if("photos"!==r&&t?.trim())throw new g("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return"camera";if("microphone"===r)return"microphone";if("contacts"===r)return"contacts";if("contacts-limited"===r)return"contacts-limited";if("notifications"===r)return"notifications";if("calendar"===r)return"calendar";if("location"===r)return"location";if("location-always"===r)return"location-always";if("media-library"===r)return"media-library";if("motion"===r)return"motion";if("reminders"===r)return"reminders";if("siri"===r)return"siri";if("photos"===r){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new g("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new g("INVALID_ARGS",`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}(a?.permissionTarget,a?.permissionMode);await ni(e,t,n,i);return}default:throw new g("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function a9(e,t="all"){var r;return"simulator"===e.kind?(r=await a7(e),"user-installed"===t?r.filter(e=>!e.bundleId.startsWith("com.apple.")):r):await aI(e,t)}async function a7(e){let t=(await aJ(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await f("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function ne(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 g("INVALID_ARGS",`Invalid setting state: ${e}`)}async function nt(e,t){let r=ar(t);if("toggle"!==r)return r;let i=await aJ(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==i.exitCode)throw new g("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let a=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
28
- ${t}`);if(!r)return null;let i=r[1].toLowerCase();return"dark"===i?"dark":"light"===i?"light":null}(i.stdout,i.stderr);if(!a)throw new g("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:i.stdout,stderr:i.stderr});return"dark"===a?"light":"dark"}let nr={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function ni(e,t,r,i){let a=await nn(e);if(!a.has(r))throw new g("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(", ")}`});let n=["privacy",e.id,t,r,i],o="notifications"===r;if(!("reset"===t&&o))try{await aJ(e,n);return}catch(t){if(!(o&&na(t)))throw t;throw new g("UNSUPPORTED_OPERATION","iOS simulator does not support setting notifications permission via simctl privacy on this runtime.",{deviceId:e.id,appBundleId:i,hint:"Use reset notifications for reprompt behavior, or toggle notifications manually in Settings."})}try{await aJ(e,n);return}catch(e){if(!na(e))throw e}try{await aJ(e,["privacy",e.id,"reset","all",i])}catch(t){throw new g("COMMAND_FAILED","iOS simulator blocked direct notifications reset. Fallback reset-all also failed.",{deviceId:e.id,appBundleId:i,hint:"Use reinstall to force a fresh notifications prompt, or reset simulator content and settings."},t instanceof Error?t:void 0)}}function na(e){if(!(e instanceof g)||"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 nn(e){let r=eD(e.simulatorSetPath),i=`${process.env.PATH??""}::${r??""}`;if(az&&t===i)return az;let a=await aJ(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let i of e.split("\n")){let e=i.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let a=/^([a-z-]+)\s+-\s+/.exec(e);a&&t.add(a[1])}return t}(`${a.stdout}
29
- ${a.stderr}`);if(0===n.size)throw new g("COMMAND_FAILED","Unable to determine supported simctl privacy services",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return az=n,t=i,n}async function no(e,t,r){let i=function(e,t,r){let i=r.length>0?r:["face"];switch(t){case"match":return i.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return i.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),a=[];for(let t of i){let r=eO(e,t),i=await f("xcrun",r,{allowFailure:!0});if(0===i.exitCode)return;a.push({args:r,stderr:i.stderr,stdout:i.stdout,exitCode:i.exitCode})}let n=a.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(a.length>0&&a.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
30
- ${r}`.toLowerCase()).includes("unrecognized subcommand")||i.includes("unknown subcommand")||i.includes("not supported")||i.includes("unavailable")||i.includes("biometric")&&i.includes("invalid")}))throw new g("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new g("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function ns(e,t){await aD(e),await a_();let r=0,i=Q.fromTimeoutMs(af);try{await ee(async({deadline:r})=>{var i;if(r?.isExpired())throw new g("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:af});let a=(i=["launch",e.id,t],eO(e,i)),n=await f("xcrun",a,{allowFailure:!0});if(0!==n.exitCode)throw new g("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:a,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!ab(e)&&(r+=1)<3},{deadline:i})}catch(r){if(ab(r)){var a;let i=(a=await aN(e,t)).installed?!1===a.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(i)}}throw r}}async function nl(e,t,r){let i=["device","process","launch","--device",e.id,t];r?.payloadUrl&&i.push("--payload-url",r.payloadUrl),await ag(i,{action:"launch iOS app",deviceId:e.id})}let nd=/^[A-Za-z0-9_.:-]{1,64}$/,nu=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function nc(e,t,r,i){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>i)throw new g("INVALID_ARGS",`${t} must be an integer between ${r} and ${i}`);return e}async function np(e,t,r){for(let i=0;i<e;i+=1)await r(i),i<e-1&&t>0&&await nf(t)}async function nf(e){await new Promise(t=>setTimeout(t,e))}function nm(e,t){let r,i=t?.subject??"Payload",a=e.trim();if(!a)throw new g("INVALID_ARGS",`${i} cannot be empty`);let n=t?.expandPath?t.expandPath(a,t.cwd):a;try{if(!C.statSync(n).isFile())throw new g("INVALID_ARGS",`${i} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof g)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new g("INVALID_ARGS",`${i} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new g("COMMAND_FAILED",`Unable to read ${i} file: ${n}`,{cause:String(t)})}if((r=a.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:a};throw new g("INVALID_ARGS",`${i} file not found: ${n}`)}async function nh(e){let t=nm(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await nw(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new g("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof g)throw t;throw new g("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function nw(e){try{return await L.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new g("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new g("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new g("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new g("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let ng=ey(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),nI=/^(iphone|ipad|ipod|appletv)/i,nA=/^appletv/i,nv=["apple tv","appletv","tvos"];function ny(e){return(e??"").trim().toLowerCase()}function nb(e){return ny(e.hardwareProperties?.platform)}function nN(e){return e.includes("tvos")}function nS(e){return nN(ny(e))?"tv":"mobile"}function n_(e){let t=ny(e);return t.includes("ios")||t.includes("tvos")}function nD(e){let t=ny(e);return nv.some(e=>t.includes(e))}function nE(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function nk(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function nL(e={}){let t,r,i=eD(e.simulatorSetPath),a=e.target;try{t=await f("xcrun",eL(["list","devices","-j"],{simulatorSetPath:i}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!n_(e))continue;let r=nS(e);if(!a||r===a)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...i?{simulatorSetPath:i}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function nO(e={}){if("darwin"!==process.platform)throw new g("UNSUPPORTED_PLATFORM","iOS tools are only available on macOS");if(!await A("xcrun"))throw new g("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eD(e.simulatorSetPath),i=await f("xcrun",eL(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(i.stdout);for(let[i,a]of Object.entries(e.devices))if(n_(i))for(let e of a)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:nS(i),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new g("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(r)return t;let a=null;try{a=o.join(P.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await f("xcrun",["devicectl","list","devices","--json-output",a],{allowFailure:!0,timeoutMs:ng});if(0!==e.exitCode)return t;let r=await L.readFile(a,"utf8"),i=JSON.parse(r);for(let e of i.result?.devices??[])if(function(e){var t;let r=nb(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=nk(e),!!nI.test(t.trim())||nE(e).some(nD))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",i=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:i,kind:"device",target:function(e){var t;return nN(nb(e))?"tv":(t=nk(e),nA.test(t.trim())||nE(e).some(nD))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{a&&await L.rm(a,{force:!0}).catch(()=>{})}return t}async function nM(e,t,r,i){let a,n=!!(t.udid||t.serial||t.deviceName);try{a=await i.selectDevice(e,t,r)}catch(e){if(n||!(e instanceof g)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!a||"device"===a.kind)){let e=await i.findBootableSimulator({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(a)return a;throw new g("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function nx(e){let t=eJ(e.platform),r=eD(e.iosSimulatorDeviceSet),i=ek(e.androidDeviceAllowlist);return await E("resolve_target_device",async()=>{let a={platform:t,target:e.target,deviceName:e.device,udid:e.udid,serial:e.serial};if(a.target&&!a.platform)throw new g("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|android|apple with --target mobile|tv.");if("android"===a.platform){await rd();let e=await r_({serialAllowlist:i});return await eK(e,a)}if("ios"===a.platform){let e=await nO({simulatorSetPath:r});return await nM(e,a,{simulatorSetPath:r},{selectDevice:eK,findBootableSimulator:nL})}let n=[];try{n.push(...await r_({serialAllowlist:i}))}catch{}try{n.push(...await nO({simulatorSetPath:r}))}catch{}return await eK(n,a,{simulatorSetPath:r})},{platform:t,target:e.target})}async function nC(e,t,r,i,a){let n=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>il(e,t,r?.activity),openDevice:()=>ip(e),close:t=>im(e,t),tap:(t,r)=>iV(e,t,r),doubleTap:async(t,r)=>{await iV(e,t,r),await iV(e,t,r)},swipe:(t,r,i,a,n)=>iG(e,t,r,i,a,n),longPress:(t,r,i)=>iH(e,t,r,i),focus:(t,r)=>iz(e,t,r),type:t=>iW(e,t),fill:(t,r,i)=>iJ(e,t,r,i),scroll:(t,r)=>iK(e,t,r),scrollIntoView:t=>iX(e,t),screenshot:(t,r)=>iP(e,t)};case"ios":var r,i;let a,n;return{open:(t,r)=>aZ(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>aY(e),close:t=>aQ(e,t),screenshot:(t,r)=>a$(e,t,r),...(r=e,a={verbose:(i=t).verbose,logPath:i.logPath,traceLogPath:i.traceLogPath,requestId:i.requestId},n=()=>{if(ec(i.requestId))throw ef()},{tap:async(e,t)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},a)},doubleTap:async(e,t)=>{await tu(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:i.appBundleId},a)},swipe:async(e,t,n,o,s)=>{await tu(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:i.appBundleId},a)},longPress:async(e,t,n)=>{await tu(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:i.appBundleId},a)},focus:async(e,t)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},a)},type:async e=>{await tu(r,{command:"type",text:e,appBundleId:i.appBundleId},a)},fill:async(e,t,n)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:i.appBundleId},a),await tu(r,{command:"type",text:n,clearFirst:!0,appBundleId:i.appBundleId},a)},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new g("INVALID_ARGS",`Unknown direction: ${e}`);let n=function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left"}}(e);await tu(r,{command:"swipe",direction:n,appBundleId:i.appBundleId},a)},scrollIntoView:async e=>{let t=await tu(r,{command:"findText",text:e,appBundleId:i.appBundleId},a);if(t?.found)return{attempts:1};for(let t=0;t<12;t+=1){for(let e=0;e<4;e+=1)n(),await tu(r,{command:"swipe",direction:"up",appBundleId:i.appBundleId},a),await new Promise(e=>setTimeout(e,80));n();let o=await tu(r,{command:"findText",text:e,appBundleId:i.appBundleId},a);if(o?.found)return{attempts:t+2}}throw new g("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}})};default:throw new g("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:a?.requestId,appBundleId:a?.appBundleId,verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath});return k({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await E("platform_command",async()=>{switch(t){case"open":{let t=r[0],i=r[1];if(r.length>2)throw new g("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await n.openDevice(),{app:null};if(void 0!==i){if("ios"!==e.platform)throw new g("INVALID_ARGS","open <app> <url> is supported only on iOS");if(rp(t))throw new g("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rp(i))throw new g("INVALID_ARGS","open <app> <url> requires a valid URL target");return await n.open(t,{activity:a?.activity,appBundleId:a?.appBundleId,url:i}),{app:t,url:i}}return await n.open(t,{activity:a?.activity,appBundleId:a?.appBundleId}),{app:t}}case"close":{let e=r[0];if(!e)return{closed:"session"};return await n.close(e),{app:e}}case"press":{let[t,i]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(i))throw new g("INVALID_ARGS","press requires x y");let o=nc(a?.count??1,"count",1,200),s=nc(a?.intervalMs??0,"interval-ms",0,1e4),l=nc(a?.holdMs??0,"hold-ms",0,1e4),d=nc(a?.jitterPx??0,"jitter-px",0,100),u=a?.doubleTap===!0;if(u&&l>0)throw new g("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(u&&d>0)throw new g("INVALID_ARGS","double-tap cannot be combined with jitter-px");if("ios"===e.platform&&o>1&&0===l&&0===d)return await tu(e,{command:"tapSeries",x:t,y:i,count:o,intervalMs:s,doubleTap:u,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x:t,y:i,count:o,intervalMs:s,holdMs:l,jitterPx:d,doubleTap:u,timingMode:"runner-series"};return await np(o,s,async e=>{let[r,a]=function(e,t){if(t<=0)return[0,0];let[r,i]=nu[e%nu.length];return[r*t,i*t]}(e,d),o=t+r,s=i+a;u?await n.doubleTap(o,s):l>0?await n.longPress(o,s,l):await n.tap(o,s)}),{x:t,y:i,count:o,intervalMs:s,holdMs:l,jitterPx:d,doubleTap:u}}case"swipe":{let t=Number(r[0]),i=Number(r[1]),o=Number(r[2]),s=Number(r[3]);if([t,i,o,s].some(Number.isNaN))throw new g("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=nc(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=nc(a?.count??1,"count",1,200),c=nc(a?.pauseMs??0,"pause-ms",0,1e4),p=a?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new g("INVALID_ARGS",`Invalid pattern: ${p}`);if("ios"===e.platform&&u>1)return await tu(e,{command:"dragSeries",x:t,y:i,x2:o,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{x1:t,y1:i,x2:o,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p};return await np(u,c,async e=>{"ping-pong"===p&&e%2==1?await n.swipe(o,s,t,i,d):await n.swipe(t,i,o,s,d)}),{x1:t,y1:i,x2:o,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:p}}case"longpress":{let e=Number(r[0]),t=Number(r[1]),i=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new g("INVALID_ARGS","longpress requires x y [durationMs]");return await n.longPress(e,t,i),{x:e,y:t,durationMs:i}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new g("INVALID_ARGS","focus requires x y");return await n.focus(e,t),{x:e,y:t}}case"type":{let e=r.join(" ");if(!e)throw new g("INVALID_ARGS","type requires text");return await n.type(e),{text:e}}case"fill":{let e=Number(r[0]),t=Number(r[1]),i=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!i)throw new g("INVALID_ARGS","fill requires x y text");return await n.fill(e,t,i),{x:e,y:t,text:i}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0;if(!e)throw new g("INVALID_ARGS","scroll requires direction");return await n.scroll(e,t),{direction:e,amount:t}}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new g("INVALID_ARGS","scrollintoview requires text");let t=await n.scrollIntoView(e);if(t?.attempts)return{text:e,attempts:t.attempts};return{text:e}}case"pinch":{if("android"===e.platform)throw new g("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),i=r[1]?Number(r[1]):void 0,n=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new g("INVALID_ARGS","pinch requires scale > 0");return await tu(e,{command:"pinch",scale:t,x:i,y:n,appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{scale:t,x:i,y:n}}case"trigger-app-event":{let{eventName:t,payload:i}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new g("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!nd.test(t))throw new g("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 g("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let i=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new g("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let i=JSON.stringify(r);if(Buffer.byteLength(i,"utf8")>8192)throw new g("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof g)throw t;throw new g("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:i}}(r),o=function(e,t,r){let i,a=(i=("ios"===e?process.env.AGENT_DEVICE_IOS_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(!a)throw new g("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 n=r?JSON.stringify(r):"",o=a.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(n)).replaceAll("{platform}",encodeURIComponent(e));if(o.length>4096)throw new g("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:o.length,maxLength:4096});return o}(e.platform,t,i);return await n.open(o,{appBundleId:a?.appBundleId}),{event:t,eventUrl:o,transport:"deep-link"}}case"screenshot":{let e=r[0]??i??`./screenshot-${Date.now()}.png`;return await L.mkdir(o.dirname(e),{recursive:!0}),await n.screenshot(e,a?.appBundleId),{path:e}}case"back":if("ios"===e.platform)return await tu(e,{command:"back",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"back"};return await ij(e),{action:"back"};case"home":if("ios"===e.platform)return await tu(e,{command:"home",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"home"};return await iB(e),{action:"home"};case"app-switcher":if("ios"===e.platform)return await tu(e,{command:"appSwitcher",appBundleId:a?.appBundleId},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{action:"app-switcher"};return await iq(e),{action:"app-switcher"};case"clipboard":{let t=(r[0]??"").toLowerCase();if("read"!==t&&"write"!==t)throw new g("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===t){if(1!==r.length)throw new g("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:t,text:"ios"===e.platform?await a4(e):await i6(e)}}if(r.length<2)throw new g("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let i=r.slice(1).join(" ");return"ios"===e.platform?await a8(e,i):await i5(e,i),{action:t,textLength:Array.from(i).length}}case"keyboard":{if("android"!==e.platform)throw new g("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new g("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new g("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await i8(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 i=await i4(e);return{platform:"android",action:"status",visible:i.visible,inputType:i.inputType,type:i.type}}case"settings":{let[t,i,n,o,s]=r,l="permission"===t?{permissionTarget:n,permissionMode:o}:void 0;if(k({level:"debug",phase:"settings_apply",data:{setting:t,state:i,target:n,mode:o,platform:e.platform}}),"ios"===e.platform)return await a5(e,t,i,s??a?.appBundleId,l),{setting:t,state:i};return await ai(e,t,i,s??a?.appBundleId,l),{setting:t,state:i}}case"push":{let t=r[0]?.trim(),i=r[1]?.trim();if(!t||!i)throw new g("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let a=await nh(i);if("ios"===e.platform)return await a6(e,t,a),{platform:"ios",bundleId:t};let n=await au(e,t,a);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount}}case"snapshot":{if("ios"===e.platform){let t=await E("snapshot_capture",async()=>await tu(e,{command:"snapshot",appBundleId:a?.appBundleId,interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw},{verbose:a?.verbose,logPath:a?.logPath,traceLogPath:a?.traceLogPath,requestId:a?.requestId}),{backend:"xctest"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new g("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await E("snapshot_capture",async()=>await iC(e,{interactiveOnly:a?.snapshotInteractiveOnly,compact:a?.snapshotCompact,depth:a?.snapshotDepth,scope:a?.snapshotScope,raw:a?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}default:throw new g("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let nR={alert:{ios:{simulator:!0},android:{}},pinch:{ios:{simulator:!0},android:{}},"app-switcher":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},apps:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},click:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},keyboard:{ios:{},android:{emulator:!0,device:!0,unknown:!0}},close:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},logs:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},reinstall:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},press:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},record:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},snapshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function nP(e,t){let r=nR[e];if(!r)return!0;let i=r[t.platform];return!!i&&!0===i[t.kind??"unknown"]}function nT(e,t,r,i,a){return{requestId:a??D().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:i,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,doubleTap:t?.doubleTap,pauseMs:t?.pauseMs,pattern:t?.pattern}}let n$=ey(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function nU(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:aD}));await t(e);return}if("device"===e.kind)return void await nF(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:rx}));await t(e.id)}}async function nF(e){let t=o.join(P.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(n$/1e3));try{let i=await f("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:n$+3e3}),a=String(i.stdout??""),n=String(i.stderr??""),o=await nV(t);if(0===i.exitCode){if(!o.parsed)throw new g("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:a,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new g("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 g("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:a,stderr:n,exitCode:i.exitCode,tunnelState:o?.tunnelState,hint:nG(a,n)})}catch(t){if(t instanceof g&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},i=String(r.stdout??""),a=String(r.stderr??""),n=Number(r.timeoutMs??n$),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new g("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:i,stderr:a,hint:i||a?nG(i,a):o},t)}throw new g("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 L.rm(t,{force:!0}).catch(()=>{})}}async function nV(e){try{let t=await L.readFile(e,"utf8"),r=JSON.parse(t),i=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,i=t.device?.connectionProperties?.tunnelState,a="string"==typeof r?r:"string"==typeof i?i:void 0;return a?{tunnelState:a}:{}}(r);return{parsed:!0,tunnelState:i.tunnelState}}catch{return{parsed:!1}}}function nG(e,t){let r=ay(e,t);return r||(`${e}
31
- ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":av)}function nj(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function nB(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function nq(e,t){return e.find(e=>e.ref===t)??null}function nH(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function nW(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),i=(e.value??"").toLowerCase(),a=(e.identifier??"").toLowerCase();return t.includes(r)||i.includes(r)||a.includes(r)})??null}function nz(e,t){let r=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);return r&&nJ(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,i=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!nJ(t))continue;let a=Math.abs(e.rect.y+e.rect.height/2-r);(!i||a<i.distance)&&(i={label:t,distance:a})}return i?.label}(e,t)??(r&&nJ(r)?r:void 0)}function nJ(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function nK(e){let t=[],r=[];for(let i of e){let e=i.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let a=nX(i.type??""),n=[i.label,i.value,i.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&nJ(n);if(("group"===a||"ioscontentgroup"===a)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...i,depth:s})}return r}function nX(e){let t=e.trim().replace(/XCUIElementType/gi,"").toLowerCase(),r=Math.max(t.lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function nZ(e,t){let r=nX(e);return!r||("android"===t?r.includes("edittext")||r.includes("autocompletetextview"):r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("textview")||r.includes("textarea")||"search"===r)}function nY(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let nQ=new Set(["id","role","text","label","value"]),n0=new Set(["visible","hidden","editable","selected","enabled","hittable"]),n1=new Set([...nQ,...n0]);function n2(e){let t=e.trim();if(!t)throw new g("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",i=null;for(let a=0;a<e.length;a+=1){let n=e[a];if(('"'===n||"'"===n)&&!ou(e,a)){i?i===n&&(i=null):i=n,r+=n;continue}if(!i&&"|"===n&&"|"===e[a+1]){let i=r.trim();if(!i)throw new g("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(i),r="",a+=1;continue}r+=n}let a=r.trim();if(!a)throw new g("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(a),t}(t);if(0===r.length)throw new g("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new g("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",i=null;for(let a=0;a<e.length;a+=1){let n=e[a];if(('"'===n||"'"===n)&&!ou(e,a)){i?i===n&&(i=null):i=n,r+=n;continue}if(!i&&/\s/.test(n)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=n}if(i)throw new g("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new g("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(or)}})(e))}}function n3(e){try{return n2(e)}catch{return null}}function n4(e,t,r){let i=r.requireRect??!1,a=r.requireUnique??!0,n=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let i=0,a=null,n=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!oi(s,t,r.platform))continue;if(i+=1,a||(a=s),!n){n=s;continue}let e=function(e,t){let r=e.depth??0,i=t.depth??0;if(r!==i)return r>i?1:-1;let a=od(e),n=od(t);return a!==n?a<n?1:-1:0}(s,n);if(e>0){n=s,o=!1;continue}0===e&&(o=!0)}return{count:i,firstNode:a,disambiguated:o?null:n}}(e,l,{platform:r.platform,requireRect:i});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(a&&1!==d.count){if(!n)continue;let e=d.disambiguated;if(!e)continue;return{node:e,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}return{node:d.firstNode,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}}return null}function n8(e,t,r){let i=r.requireRect??!1,a=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r){let i=0;for(let a of e)(!r.requireRect||a.rect)&&oi(a,t,r.platform)&&(i+=1);return i}(e,o,{platform:r.platform,requireRect:i});if(a.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:a}}return null}function n6(e,t,r){let i=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let a=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return i?`Selector did not resolve uniquely (${a})`:`Selector did not match (${a})`}function n5(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,i=0,a=[];for(;i<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return n1.has(e)}return n1.has(t.toLowerCase())}(e[i]);){i+=1;let t=e.slice(0,i).join(" ").trim();t&&n3(t)&&a.push(i)}if(0===a.length)return null;let n=a[a.length-1];if(r){for(let t=a.length-1;t>=0;t-=1)if(a[t]<e.length){n=a[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function n9(e){let t=e[0]??"",r=n5(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function n7(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function oe(e,t){return nZ(e.type??"",t)&&!1!==e.enabled}function ot(e,t,r={}){let i=[],a=nX(e.type??""),n=ol(e.identifier),o=ol(e.label),s=ol(e.value),l=ol(nY(e)),d="fill"===r.action;n&&i.push(`id=${os(n)}`),a&&o&&i.push(d?`role=${os(a)} label=${os(o)} editable=true`:`role=${os(a)} label=${os(o)}`),o&&i.push(d?`label=${os(o)} editable=true`:`label=${os(o)}`),s&&i.push(d?`value=${os(s)} editable=true`:`value=${os(s)}`),l&&l!==o&&l!==s&&i.push(d?`text=${os(l)} editable=true`:`text=${os(l)}`),a&&d&&!i.some(e=>e.includes("editable=true"))&&i.push(`role=${os(a)} editable=true`);let u=tf(i);return 0===u.length&&a&&u.push(d?`role=${os(a)} editable=true`:`role=${os(a)}`),0===u.length&&n7(e)&&u.push("visible=true"),u}function or(e){let t=e.trim();if(!t)throw new g("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!n0.has(r))throw new g("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let i=t.slice(0,r).trim().toLowerCase(),a=t.slice(r+1).trim();if(!n1.has(i))throw new g("INVALID_ARGS",`Unknown selector key: ${i}`);if(!a)throw new g("INVALID_ARGS",`Missing selector value for key: ${i}`);if(n0.has(i)){let e,t="true"===(e=oa(a).toLowerCase())||"false"!==e&&null;if(null===t)throw new g("INVALID_ARGS",`Invalid boolean value for ${i}: ${a}`);return{key:i,value:t}}return{key:i,value:oa(a)}}function oi(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return on(e.identifier,String(t.value));case"role":var i,a;return i=e.type,a=String(t.value),function(e){return nX(e)}(i??"")===function(e){return nX(e)}(a);case"label":return on(e.label,String(t.value));case"value":return on(e.value,String(t.value));case"text":{let r=oo(String(t.value));return oo(nY(e))===r}case"visible":return n7(e)===!!t.value;case"hidden":return!n7(e)==!!t.value;case"editable":return oe(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function oa(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function on(e,t){return oo(e??"")===oo(t)}function oo(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function os(e){return JSON.stringify(e)}function ol(e){if(!e)return null;let t=e.trim();return t||null}function od(e){return e.rect?e.rect.width*e.rect.height:1/0}function ou(e,t){let r=0;for(let i=t-1;i>=0&&"\\"===e[i];i-=1)r+=1;return r%2==1}let oc=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),op=/https?:\/\/[^\s"'<>\])]+/i,of=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function om(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function oh(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return ow(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(i?.[1])return i[1].trim()}}function ow(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function og(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function oI(e,t,r,i){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(i,e)):t}let oA="shared_prefs/ReactNativeDevPrefs.xml",ov="debug_http_host",oy="dev_server_https",ob="RCT_jsLocation",oN="RCT_packager_scheme",oS="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",o_='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function oD(e){return void 0!==oE(e)}function oE(e){if(!e)return;let t=oF(e.metroHost),r=oG(e.metroPort),i="http",a=oF(e.bundleUrl);if(a){var n;let e;try{e=new I(a)}catch(e){throw new g("INVALID_ARGS",`Invalid runtime bundle URL: ${a}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=oF(e.hostname),r??=oG(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),i="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:i}}async function ok(e){let{device:t,appId:r,runtime:i}=e;if(!r)return;let a=oE(i);if(a){if("android"===t.platform)return void await oO(t,r,a);"ios"===t.platform&&"simulator"===t.kind&&await oR(t,r,a)}}async function oL(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await oM(t,r);"ios"===t.platform&&"simulator"===t.kind&&await oP(t,r)}}async function oO(e,t,r){var i,a,n,o,s,l;let d,u;oV(t);let c=(i=await ox(e,t),a=ov,n=`${r.host}:${r.port}`,d=` <string name="${oj(a)}">${oj(n)}</string>`,o$(oU(i,a),d));o=c,s=oy,l="https"===r.scheme,u=` <boolean name="${oj(s)}" value="${l?"true":"false"}" />`,c=o$(oU(o,s),u),await oC(e,t,c)}async function oM(e,t){oV(t);let r=await ox(e,t),i=oU(r,ov),a=oU(i,oy);a!==r&&await oC(e,t,a)}async function ox(e,t){let r=await f("adb",rl(e,["shell","run-as",t,"cat",oA]),{allowFailure:!0});return 0!==r.exitCode?o_:oT(r.stdout)}async function oC(e,t,r){let i=rl(e,["shell","run-as",t,"id"]),a=await f("adb",i,{allowFailure:!0});if(0!==a.exitCode){let e=oB(a.stdout,a.stderr);throw new g("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:i,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,hint:e?oS:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await f("adb",rl(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await f("adb",rl(e,["shell","run-as",t,"tee",oA]),{stdin:r.trimEnd()})}catch(i){let e=h(i);if("TOOL_MISSING"===e.code)throw e;let r=oB("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new g("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?oS:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function oR(e,t,r){await f("xcrun",eO(e,["spawn",e.id,"defaults","write",t,ob,"-string",`${r.host}:${r.port}`])),await f("xcrun",eO(e,["spawn",e.id,"defaults","write",t,oN,"-string",r.scheme]))}async function oP(e,t){await f("xcrun",eO(e,["spawn",e.id,"defaults","delete",t,ob]),{allowFailure:!0}),await f("xcrun",eO(e,["spawn",e.id,"defaults","delete",t,oN]),{allowFailure:!0})}function oT(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
32
- `:o_}function o$(e,t){return oT(e).replace("</map>",`${t}
33
- </map>`)}function oU(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return oT(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function oF(e){let t=e?.trim();return t&&t.length>0?t:void 0}function oV(e){if("binary"!==rP(e))return;let t=rT(e);throw new g("INVALID_ARGS",t,{package:e,hint:t})}function oG(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function oj(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function oB(e,t){let r=`${e}
34
- ${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}function oq(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),i=n5(r?e.slice(0,-1):e.slice());return!i||i.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:i.selectorExpression,selectorTimeout:r?t:null}}function oH(e){return!!e&&!Number.isNaN(Number(e))}let oW=ey(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),oz=new Map;async function oJ(e){let t=await n.mkdtemp(o.join(P.tmpdir(),"agent-device-materialized-"));try{let r=await oZ(e.installablePath,o.join(t,"installable")),i=e.archivePath?await oZ(e.archivePath,o.join(t,"archive")):void 0,a=p.randomUUID(),n=e.ttlMs??oW,s=Date.now()+n,l=setTimeout(()=>{oK(a)},n);return oz.set(a,{rootPath:t,installablePath:r,archivePath:i,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:a,installablePath:r,...i?{archivePath:i}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await n.rm(t,{recursive:!0,force:!0}),e}}async function oK(e,t){let r=oz.get(e);if(!r)throw new g("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new g("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),oz.delete(e),await n.rm(r.rootPath,{recursive:!0,force:!0})}async function oX(e){let t=Array.from(oz.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await oK(e)}))}async function oZ(e,t){let r=await n.stat(e);await n.mkdir(t,{recursive:!0});let i=o.join(t,o.basename(e));return r.isDirectory()?await n.cp(e,i,{recursive:!0}):await n.copyFile(e,i),i}async function oY(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new g("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await nU(e.session.device),e.session.device}if(!r)throw new g("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let i=await nx(e.flags??{});return await nU(i),i}async function oQ(e){let{req:t,sessionName:r,sessionStore:i,deps:a}=e,n=i.get(r);try{let e,o,s,l=(o=function(e){let t=e.meta?.installSource;if(!t)throw new g("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new g("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new g("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(s=t.meta?.uploadedArtifactId)&&"path"===o.kind?{source:{kind:"path",path:tq(s,t.meta?.tenantId)},cleanup:()=>{tH(s)}}:{source:o,cleanup:()=>{}}),d=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new g("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await (a?.resolveInstallDevice??oY)({session:n,flags:t.flags});if(!nP("install",u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let c=(a?.getRequestSignal??ep)(t.meta?.requestId);if("ios"===u.platform){let e,o=a?.installIosInstallablePath??(await Promise.resolve().then(()=>({closeIosApp:aQ,ensureBootedSimulator:aD,installIosApp:a1,installIosInstallablePath:a3,listIosApps:a9,listSimulatorApps:a7,openIosApp:aZ,openIosDevice:aY,parseIosDeviceAppsPayload:aA,pushIosNotification:a6,readIosClipboardText:a4,reinstallIosApp:a2,resolveIosApp:aX,screenshotIos:a$,setIosSetting:a5,uninstallIosApp:a0,writeIosClipboardText:a8}))).installIosInstallablePath,s=a?.prepareIosInstallArtifact??(await Promise.resolve().then(()=>({prepareIosInstallArtifact:aO,readIosBundleInfo:aM}))).prepareIosInstallArtifact,p=await s(l.source,{signal:c});try{if(d.enabled&&(e=await oJ({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs})),await o(u,p.installablePath),!p.bundleId)throw new g("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let a={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:p.bundleId,...p.appName?{appName:p.appName}:{},launchTarget:p.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&i.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:a}),{ok:!0,data:a}}catch(r){throw e&&await oK(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),l.cleanup()}}let p=a?.prepareAndroidInstallArtifact??(await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:r3}))).prepareAndroidInstallArtifact,f=a?.installAndroidInstallablePathAndResolvePackageName??(await Promise.resolve().then(()=>({appSwitcherAndroid:iq,backAndroid:ij,closeAndroidApp:im,dismissAndroidKeyboard:i8,ensureAdb:rd,fillAndroid:iJ,focusAndroid:iz,getAndroidAppState:io,getAndroidKeyboardState:i4,homeAndroid:iB,inferAndroidAppName:ia,installAndroidApp:i_,installAndroidInstallablePath:iN,installAndroidInstallablePathAndResolvePackageName:iS,isAmStartError:iu,listAndroidApps:ie,longPressAndroid:iH,openAndroidApp:il,openAndroidDevice:ip,parseAndroidLaunchComponent:ic,pressAndroid:iV,pushAndroidNotification:au,readAndroidClipboardText:i6,reinstallAndroidApp:iD,resolveAndroidApp:r7,screenshotAndroid:iP,scrollAndroid:iK,scrollIntoViewAndroid:iX,setAndroidSetting:ai,snapshotAndroid:iC,swipeAndroid:iG,typeAndroid:iW,writeAndroidClipboardText:i5}))).installAndroidInstallablePathAndResolvePackageName,m=await p(l.source,{signal:c});try{d.enabled&&(e=await oJ({archivePath:m.archivePath,installablePath:m.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs}));let o=await f(u,m.installablePath,m.packageName);if(!o)throw new g("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let s=(a?.inferAndroidAppName??(await Promise.resolve().then(()=>({appSwitcherAndroid:iq,backAndroid:ij,closeAndroidApp:im,dismissAndroidKeyboard:i8,ensureAdb:rd,fillAndroid:iJ,focusAndroid:iz,getAndroidAppState:io,getAndroidKeyboardState:i4,homeAndroid:iB,inferAndroidAppName:ia,installAndroidApp:i_,installAndroidInstallablePath:iN,installAndroidInstallablePathAndResolvePackageName:iS,isAmStartError:iu,listAndroidApps:ie,longPressAndroid:iH,openAndroidApp:il,openAndroidDevice:ip,parseAndroidLaunchComponent:ic,pressAndroid:iV,pushAndroidNotification:au,readAndroidClipboardText:i6,reinstallAndroidApp:iD,resolveAndroidApp:r7,screenshotAndroid:iP,scrollAndroid:iK,scrollIntoViewAndroid:iX,setAndroidSetting:ai,snapshotAndroid:iC,swipeAndroid:iG,typeAndroid:iW,writeAndroidClipboardText:i5}))).inferAndroidAppName)(o),l={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:o,...s?{appName:s}:{},launchTarget:o,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&i.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:l}),{ok:!0,data:l}}catch(r){throw e&&await oK(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await m.cleanup(),l.cleanup()}}catch(e){return{ok:!1,error:b(e)}}}async function o0(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new g("INVALID_ARGS","release_materialized_paths requires a materializationId");return await oK(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:b(e)}}}async function o1(e){let t,r,i,{deviceName:a,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new g("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await o2({deviceName:a,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,i=!1):(t=(await o3({deviceName:a,runtime:n,simctlOpts:u})).udid,r=await o4(t,u),i=!0)}else t=(await o3({deviceName:a,runtime:n,simctlOpts:u})).udid,r=await o4(t,u),i=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:a,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:a,runtime:r,created:i,booted:c}}async function o2(e){let{deviceName:t,runtime:r,simctlOpts:i}=e,a=await f("xcrun",eL(["list","devices","-j"],i),{allowFailure:!0,timeoutMs:ap});if(0!==a.exitCode)return null;try{let e=JSON.parse(String(a.stdout??""));for(let[i,a]of Object.entries(e.devices??{}))if(!r||o8(i).includes(o8(r))){for(let e of a)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:i}}return null}catch{return null}}async function o3(e){let{deviceName:t,runtime:r,simctlOpts:i}=e,a=r?["create",t,t,r]:["create",t,t],n=await f("xcrun",eL(a,i),{allowFailure:!0});if(0!==n.exitCode)throw new g("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new g("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function o4(e,t){let r=await f("xcrun",eL(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:ap});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,i]of Object.entries(t.devices??{}))if(i.some(t=>t.udid===e))return r;return""}catch{return""}}function o8(e){return e.toLowerCase().replace(/[._-]/g,"")}let o6='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',o5=["platform","target","device","udid","serial","verbose","out"],o9=["platform","target","device","udid","serial","verbose","out"],o7=["path","start","stop","doctor","mark","clear"],se=`logs requires ${o7.slice(0,-1).join(", ")}, or ${o7.at(-1)}`,st="Not implemented for this platform in this release.",sr="open-command-roundtrip",si=["platform","metroHost","metroPort","bundleUrl","launchUrl"],sa=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sn=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function so(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function ss(e){let t=e?.trim();return t&&t.length>0?t:void 0}function sl(e,t){if(void 0!==e){if("string"!=typeof e)throw new g("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return ss(e)}}function sd(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new g("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function su(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:i,device:a}=e,n=r.getRuntimeHints(i),o=function(e){let{runtime:t,sessionName:r,platform:i}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new g("INVALID_ARGS","open runtime must be an object.");let a=Object.keys(t).find(e=>!si.includes(e));if(a)throw new g("INVALID_ARGS",`Invalid open runtime field: ${a}. Supported fields are ${si.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new g("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new g("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,i),metroHost:sl(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new g("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return sd(e)}}(t.metroPort),bundleUrl:sl(t.bundleUrl,"bundleUrl"),launchUrl:sl(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:i,platform:a.platform});return void 0===t.runtime?{runtime:function(e,t,r){let i=e.getRuntimeHints(t);if(i){if(i.platform&&r&&i.platform!==r.platform)throw new g("INVALID_ARGS",`Session runtime hints target ${i.platform}, but session "${t}" is bound to ${r.platform}. Clear the runtime hints or use a different session.`);return r?.platform&&i.platform!==r.platform?{...i,platform:r.platform}:i}}(r,i,a),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&so(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=h(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}async function sc(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:i,session:a,clearRuntimeHints:n}=e;!t||!a?.appBundleId||!oD(r)||oD(i)||await n({device:a.device,appId:a.appBundleId})}async function sp(e){var t,r,i,a,n,o;let{req:s,sessionName:l,sessionStore:d,logPath:u,device:c,dispatch:p,applyRuntimeHints:f,stopIosRunner:m,settleSimulator:h,openTarget:w,openPositionals:g,appBundleId:I,runtime:A,existingSession:v}=e,y=s.flags?.relaunch===!0,b=v?.trace?.outPath;if(y&&w){let e=I??w;await sS({device:c,closeTarget:e,stopIosRunner:m,dispatch:p,outFlag:s.flags?.out,context:{...nT(u,s.flags,I??v?.appBundleId,b)},settleSimulator:h})}await f({device:c,appId:I,runtime:A});let N=Date.now();await p(c,"open",g,s.flags?.out,{...nT(u,s.flags,I)}),await sf({runtime:A,device:c,dispatch:p,req:s,logPath:u,appBundleId:I,traceLogPath:b,openPositionals:g});let S=w?(t=N,r=w,i=I,{durationMs:Math.max(0,Date.now()-t),measuredAt:new Date().toISOString(),method:sr,appTarget:r,appBundleId:i}):void 0;await h(c,sn);let _=function(e){let{existingSession:t,sessionName:r,device:i,appBundleId:a,openTarget:n,saveScript:o}=e;return t?{...t,appBundleId:a,appName:n,recordSession:t.recordSession||o,snapshot:void 0}:{name:r,device:i,createdAt:Date.now(),appBundleId:a,appName:n,recordSession:o,actions:[]}}({existingSession:v,sessionName:l,device:c,appBundleId:I,openTarget:w,saveScript:!!s.flags?.saveScript});void 0!==s.runtime&&(a=d,n=l,(o=A)&&(0===so(o)?a.clearRuntimeHints(n):a.setRuntimeHints(n,o)));let D=function(e){let{sessionName:t,appName:r,appBundleId:i,startup:a,device:n,runtime:o}=e,s={session:t};return r&&(s.appName=r),i&&(s.appBundleId=i),a&&(s.startup=a),o&&so(o)>0&&(s.runtime=o),n&&(s.platform=n.platform,s.target=n.target??"mobile",s.device=n.name,s.id=n.id,s.kind=n.kind,"android"===n.platform&&(s.serial=n.id)),n?.platform==="ios"&&(s.device_udid=n.id,s.ios_simulator_device_set=n.simulatorSetPath??null),s}({sessionName:l,appName:w,appBundleId:I,startup:S,device:c,runtime:A});return!function(e){let{req:t,sessionStore:r,session:i,sessionName:a,runtime:n}=e;if(void 0!==t.runtime){if(n)return r.recordAction(i,{command:"runtime",positionals:["set"],flags:{...t.flags??{},platform:i.device.platform,metroHost:n.metroHost,metroPort:n.metroPort,bundleUrl:n.bundleUrl,launchUrl:n.launchUrl},result:{session:a,configured:!0,runtime:n}});r.recordAction(i,{command:"runtime",positionals:["clear"],flags:t.flags??{},result:{session:a,cleared:!0}})}}({req:s,sessionStore:d,session:_,sessionName:l,runtime:A}),d.recordAction(_,{command:"open",positionals:g,flags:s.flags??{},result:D}),d.set(l,_),{ok:!0,data:D}}async function sf(e){let{runtime:t,device:r,dispatch:i,req:a,logPath:n,appBundleId:o,traceLogPath:s,openPositionals:l}=e,d=t?.launchUrl;if(!d||0===l.length||l.length>1)return;let u=l[0]?.trim();!u||rp(u)||await i(r,"open",[d],a.flags?.out,{...nT(n,a.flags,o,s)})}let sm=["dump","log"],sh=`network requires ${sm.join(" or ")}`,sw=["summary","headers","body","all"],sg=`network include mode must be one of: ${sw.join(", ")}`;function sI(e,t,r){return t||sA(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sA(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sv(e){return"ios"===e.platform&&"simulator"===e.kind}async function sy(e,t){sv(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sb(e){let t=await f("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function sN(e){let{device:t,shutdownRequested:r,shutdownSimulator:i,shutdownAndroidEmulator:a}=e;if(r&&(sv(t)||"android"===t.platform&&"emulator"===t.kind))try{return sv(t)?await i(t):await a(t)}catch(t){let e=b(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function sS(e){let{device:t,closeTarget:r,stopIosRunner:i,dispatch:a,outFlag:n,context:o,settleSimulator:s}=e;"ios"===t.platform&&await i(t.id),await a(t,"close",[r],n,o),await s(t,sa)}async function s_(e){let t=sA(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):e.session.device;return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}function sD(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let sE=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:i}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:rM}));return await i({avdName:e,serial:t,headless:r})};async function sk(e){let{req:t,sessionName:r,logPath:i,sessionStore:a,ensureReady:n,resolveDevice:o,dispatch:s,command:l,positionals:d,recordPositionals:u,deriveNextSession:c}=e,p=a.get(r),f=t.flags??{},m=sI(l,p,f);if(m)return m;let h=await s_({session:p,flags:f,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!nP(l,h))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${l} is not supported on this device`}};let w=await s(h,l,d,t.flags?.out,{...nT(i,t.flags,p?.appBundleId,p?.trace?.outPath)});if(p){let e=c?await c(p,w,h):p;a.recordAction(e,{command:l,positionals:u??d,flags:t.flags??{},result:w??{}}),e!==p&&a.set(r,e)}return{ok:!0,data:w??{}}}let sL={ios:async(e,t,r)=>{let{reinstallIosApp:i}=await Promise.resolve().then(()=>({reinstallIosApp:a2}));return await i(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:i}=await Promise.resolve().then(()=>({reinstallAndroidApp:iD}));return await i(e,t,r)}},sO={ios:async(e,t,r)=>{let{installIosApp:i}=await Promise.resolve().then(()=>({installIosApp:a1})),a=await i(e,r,{appIdentifierHint:t});return{bundleId:a.bundleId,appName:a.appName,launchTarget:a.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:i}=await Promise.resolve().then(()=>({installAndroidApp:i_})),a=await i(e,r);return{package:a.packageName,appName:a.appName,launchTarget:a.launchTarget}}};async function sM(e){let{req:t,command:r,sessionName:i,sessionStore:a,ensureReady:n,resolveDevice:o,deployOps:s}=e,l=a.get(i),d=t.flags??{},u=sI(r,l,d);if(u)return u;let c=t.positionals?.[0]?.trim(),p=t.positionals?.[1]?.trim();if(!c||!p)return{ok:!1,error:{code:"INVALID_ARGS",message:`${r} requires: ${r} <app> <path-to-app-binary>`}};let f=t.meta?.uploadedArtifactId;try{let e,i=f?tq(f,t.meta?.tenantId):tS.expandHome(p);if(!C.existsSync(i))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${i}`}};let u=await s_({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!1});if(!nP(r,u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}};if("ios"===u.platform){let t=await s.ios(u,c,i),r=t.bundleId;e=r?{app:c,appPath:i,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:i,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await s.android(u,c,i),r=t.package;e=r?{app:c,appPath:i,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:i,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}return l&&a.recordAction(l,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:e}),{ok:!0,data:e}}finally{f&&tH(f)}}async function sx(e,t,r){if("ios"===e.platform&&t)return rp(t)?"device"===e.kind?rf(r,t):void 0:await sC(e,t)}async function sC(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:aX}));return await r(e,t)}catch{return}}async function sR(e,t){if(!("android"!==e.platform||!t||rp(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:r7})),i=await r(e,t);return"package"===i.type?i.value:void 0}catch{return}}async function sP(e,t,r,i){return await sx(e,t,r)??await i(e,t)??("android"===e.platform&&t&&rp(t)?r:void 0)}async function sT(e){let{req:t,sessionName:r,sessionStore:i,ensureReady:a,resolveDevice:n}=e,o=i.get(r),s=t.flags??{},l=eJ(s.platform);if(!o&&"string"==typeof s?.session&&s.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===l?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`}};let d=sI("appstate",o,s);if(d)return d;let u=o?.device.platform==="ios"&&function(e,t){if(!t)return!1;if(!sA(e))return!0;let r=eJ(e?.platform);return!(r&&r!==t.device.platform||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:o6}};if(u){let e=o.appName??o.appBundleId;return o.appName||o.appBundleId?{ok:!0,data:{platform:"ios",appName:e??"unknown",appBundleId:o.appBundleId,source:"session",device_udid:o.device.id,ios_simulator_device_set:o.device.simulatorSetPath??null}}:{ok:!1,error:{code:"COMMAND_FAILED",message:"No foreground app is tracked for this iOS session. Open an app in the session, then retry appstate."}}}let c=await s_({session:o,flags:s,ensureReadyFn:a,resolveTargetDeviceFn:n,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:o6}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:io})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function s$(e){let{req:t,sessionName:r,logPath:i,sessionStore:a,ensureReady:n,resolveDevice:o,dispatch:s}=e,l=a.get(r),d=t.flags??{},u=sI("clipboard",l,d);if(u)return u;let c=(t.positionals?.[0]??"").toLowerCase();if("read"!==c&&"write"!==c)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let p=await s_({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!nP("clipboard",p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let f=await s(p,"clipboard",t.positionals??[],t.flags?.out,{...nT(i,t.flags,l?.appBundleId,l?.trace?.outPath)});return l&&a.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:f??{}}),{ok:!0,data:{platform:p.platform,...f??{}}}}async function sU(e){var t,r;let{req:i,sessionName:a,logPath:n,sessionStore:o,invoke:s,dispatch:l,ensureReady:d,resolveTargetDevice:u,installOps:c=sO,reinstallOps:p=sL,stopIosRunner:f,appLogOps:m={start:t$,stop:tU},ensureAndroidEmulatorBoot:w=sE,resolveAndroidPackageForOpen:I=sR,applyRuntimeHints:A=ok,clearRuntimeHints:v=oL,settleSimulator:y,shutdownSimulator:N,shutdownAndroidEmulator:S}=e,_=l??nC,D=d??nU,E=u??nx,k=f??ti,L=y??sy,O=i.command;if("session_list"===O)return{ok:!0,data:{sessions:o.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",device:e.device.name,id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("runtime"===O){let e=(i.positionals?.[0]??"show").toLowerCase(),n=o.get(a),s=o.getRuntimeHints(a);if(!["set","show","clear"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===e){oD(s)&&n?.appBundleId&&await v({device:n.device,appId:n.appBundleId});let e=o.clearRuntimeHints(a);return{ok:!0,data:{session:a,cleared:e}}}if("show"===e)return{ok:!0,data:{session:a,configured:!!s,runtime:s}};let l=eJ(i.flags?.platform)??s?.platform??n?.device.platform;if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires --platform when the session has not been opened yet."}};if(n&&n.device.platform!==l)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${l}, but session "${a}" is already bound to ${n.device.platform}.`}};let d={platform:(t=i.flags,r={platform:l,metroHost:ss(t?.metroHost),metroPort:sd(t?.metroPort),bundleUrl:ss(t?.bundleUrl),launchUrl:ss(t?.launchUrl)}).platform??s?.platform,metroHost:r.metroHost??s?.metroHost,metroPort:r.metroPort??s?.metroPort,bundleUrl:r.bundleUrl??s?.bundleUrl,launchUrl:r.launchUrl??s?.launchUrl};return 0===so(d)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(o.setRuntimeHints(a,d),{ok:!0,data:{session:a,configured:!0,runtime:d}})}if("ensure-simulator"===O)try{let e=i.flags??{},t=e.device,r=e.runtime,a=eD(e.iosSimulatorDeviceSet);if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=!0===e.boot,o=!1!==e.reuseExisting,s=await o1({deviceName:t,runtime:r,simulatorSetPath:a,reuseExisting:o,boot:n,ensureReady:D});return{ok:!0,data:{udid:s.udid,device:s.device,runtime:s.runtime,ios_simulator_device_set:a??null,created:s.created,booted:s.booted}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===O)try{let e=[],t=eD(i.flags?.iosSimulatorDeviceSet),r=ek(i.flags?.androidDeviceAllowlist),a=eJ(i.flags?.platform);if("android"===a){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:r_}));e.push(...await t({serialAllowlist:r}))}else if("ios"===a){let{listIosDevices:r}=await Promise.resolve().then(()=>({listIosDevices:nO}));e.push(...await r({simulatorSetPath:t}))}else{let{listAndroidDevices:i}=await Promise.resolve().then(()=>({listAndroidDevices:r_})),{listIosDevices:a}=await Promise.resolve().then(()=>({listIosDevices:nO}));try{e.push(...await i({serialAllowlist:r}))}catch{}try{e.push(...await a({simulatorSetPath:t}))}catch{}}let n=(i.flags?.target?e.filter(e=>(e.target??"mobile")===i.flags?.target):e).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:n}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===O){let e=o.get(a),t=i.flags??{},r=sI(O,e,t);if(r)return r;let n=await s_({session:e,flags:t,ensureReadyFn:D,resolveTargetDeviceFn:E,ensureReady:!0});if(!nP("apps",n))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=i.flags?.appsFilter??"all";if("ios"===n.platform){let{listIosApps:e}=await Promise.resolve().then(()=>({listIosApps:a9}));return{ok:!0,data:{apps:(await e(n,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve().then(()=>({listAndroidApps:ie}));return{ok:!0,data:{apps:(await l(n,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}if("boot"===O){let e,t=o.get(a),r=i.flags??{},n=sI(O,t,r);if(n)return n;let s="android"===(eJ(r.platform)??t?.device.platform),l=!0===r.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=sD({flags:r,sessionDevice:t?.device}),u=s&&!!d,c=!1;try{e=await s_({session:t,flags:r,ensureReadyFn:D,resolveTargetDeviceFn:E,ensureReady:!1})}catch(i){let t=h(i);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw i;e=await w({avdName:d,serial:r.serial,headless:l}),c=!0}if(r.target&&(e.target??"mobile")!==r.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${r.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let i=sD({flags:r,sessionDevice:t?.device,resolvedDevice:e});if(!i)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await w({avdName:i,serial:r.serial,headless:!0})}await D(e)}else("android"!==e.platform||!0!==e.booted)&&await D(e);return nP("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"boot is not supported on this device"}}}if("appstate"===O)return await sT({req:i,sessionName:a,sessionStore:o,ensureReady:D,resolveDevice:E});if("clipboard"===O)return await s$({req:i,sessionName:a,logPath:n,sessionStore:o,ensureReady:D,resolveDevice:E,dispatch:_});if("keyboard"===O)return await sk({req:i,sessionName:a,logPath:n,sessionStore:o,ensureReady:D,resolveDevice:E,dispatch:_,command:"keyboard",positionals:i.positionals??[]});if("perf"===O){let e,t,r,i=o.get(a);return i?{ok:!0,data:(r=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===sr&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:sr,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(i.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:sr,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:sr},{session:i.name,platform:i.device.platform,device:i.device.name,deviceId:i.device.id,metrics:{startup:r,fps:{available:!1,reason:st},memory:{available:!1,reason:st},cpu:{available:!1,reason:st}},sampling:{startup:{method:sr,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("install"===O||"reinstall"===O)return await sM({req:i,command:O,sessionName:a,sessionStore:o,ensureReady:D,resolveDevice:E,deployOps:"install"===O?c:p});if("install_source"===O)return await oQ({req:i,sessionName:a,sessionStore:o});if("release_materialized_paths"===O)return await o0({req:i});if("push"===O){let e,t=i.positionals?.[0]?.trim(),r=i.positionals?.[1]?.trim();if(!t||!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}};let s="file"===(e=nm(r,{subject:"Push payload",cwd:i.meta?.cwd,expandPath:(e,t)=>tS.expandHome(e,t)})).kind?e.path:e.text;return await sk({req:i,sessionName:a,logPath:n,sessionStore:o,ensureReady:D,resolveDevice:E,dispatch:_,command:"push",positionals:[t,s],recordPositionals:[t,r]})}if("trigger-app-event"===O)return await sk({req:i,sessionName:a,logPath:n,sessionStore:o,ensureReady:D,resolveDevice:E,dispatch:_,command:"trigger-app-event",positionals:i.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,i=r?await sP(e.device,r,e.appBundleId,I)??e.appBundleId:e.appBundleId;return{...e,appBundleId:i}}});if("open"===O){let e=i.flags?.relaunch===!0;if(o.has(a)){let t=o.get(a),r=i.positionals?.[0],s=r??(e?t?.appName:void 0);if(!t||!s)return e?{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app name or an active session app."}}:{ok:!1,error:{code:"INVALID_ARGS",message:"Session already active. Close it first or pass a new --session name."}};if(e&&rp(s))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};if(e&&"android"===t.device.platform&&"binary"===rP(s))return{ok:!1,error:{code:"INVALID_ARGS",message:rT(s)}};await D(t.device);let l=await sP(t.device,s,t.appBundleId,I),d=su({req:i,sessionStore:o,sessionName:a,device:t.device});if(!d.ok)return d.response;let{runtime:u,previousRuntime:c,replacedStoredRuntime:p}=d.data;await sc({replacedStoredRuntime:p,previousRuntime:c,runtime:u,session:t,clearRuntimeHints:v});let f=r?i.positionals??[]:[s];return await sp({req:i,sessionName:a,sessionStore:o,logPath:n,device:t.device,dispatch:_,applyRuntimeHints:A,stopIosRunner:k,settleSimulator:L,openTarget:s,openPositionals:f,appBundleId:l,runtime:u,existingSession:t})}let t=i.positionals?.[0];if(e&&!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app argument."}};if(e&&t&&rp(t))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};let r=await E(i.flags??{});if(e&&"android"===r.platform&&t&&"binary"===rP(t))return{ok:!1,error:{code:"INVALID_ARGS",message:rT(t)}};let s=o.toArray().find(e=>e.device.id===r.id);if(s)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${s.name}".`,details:{session:s.name,deviceId:r.id,deviceName:r.name}}};await D(r);let l=await sP(r,t,void 0,I),d=su({req:i,sessionStore:o,sessionName:a,device:r});if(!d.ok)return d.response;let{runtime:u}=d.data;return await sp({req:i,sessionName:a,sessionStore:o,logPath:n,device:r,dispatch:_,applyRuntimeHints:A,stopIosRunner:k,settleSimulator:L,openTarget:t,openPositionals:i.positionals??[],appBundleId:l,runtime:u})}if("replay"===O){let e=i.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let t=tS.expandHome(e,i.meta?.cwd),r=C.readFileSync(t,"utf8"),l=r.trimStart()[0];if("{"===l||"["===l)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let d=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let i=r+1,a=!1;for(;i<e.length;){let t=e[i];if('"'===t&&!a)break;a="\\"===t&&!a,"\\"!==t&&(a=!1),i+=1}if(i>=e.length)throw new g("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,i+1);t.push(JSON.parse(n)),r=i+1;continue}let i=r;for(;i<e.length&&!/\s/.test(e[i]);)i+=1;t.push(e.slice(r,i)),r=i}return t}(t);if(0===r.length)return null;let[i,...a]=r;if("context"===i)return null;let n={ts:Date.now(),command:i,positionals:[],flags:{}};if("snapshot"===i){n.positionals=[];for(let e=0;e<a.length;e+=1){let t=a[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<a.length){let t=Number(a[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<a.length){n.flags.snapshotScope=a[e+1],e+=1;continue}if("--backend"===t&&e+1<a.length){e+=1;continue}}return n}if("open"===i){n.positionals=[];for(let e=0;e<a.length;e+=1){let t=a[e];if("--relaunch"===t){n.flags.relaunch=!0;continue}n.positionals.push(t)}return n}if("runtime"===i){let e=function(e){let t=[],r={};for(let i=0;i<e.length;i+=1){let a=e[i];if("--platform"===a&&i+1<e.length){let t=e[i+1];("ios"===t||"android"===t)&&(r.platform=t),i+=1;continue}if("--metro-host"===a&&i+1<e.length){r.metroHost=e[i+1],i+=1;continue}if("--metro-port"===a&&i+1<e.length){let t=tN(e[i+1]);null!==t&&(r.metroPort=t),i+=1;continue}if("--bundle-url"===a&&i+1<e.length){r.bundleUrl=e[i+1],i+=1;continue}if("--launch-url"===a&&i+1<e.length){r.launchUrl=e[i+1],i+=1;continue}t.push(a)}return{positionals:t,flags:r}}(a);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tg(i)){let e=tb(i,a);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return oH(r)&&oH(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===i){if(a.length<2)return n.positionals=a,n;let e=a[0];return e.startsWith("@")?(a.length>=3?(n.positionals=[e,a.slice(2).join(" ")],n.result={refLabel:a[1]}):n.positionals=[e,a[1]],n):(n.positionals=[e,a.slice(1).join(" ")],n)}if("get"===i){if(a.length<2)return n.positionals=a,n;let e=a[0],t=a[1];return t.startsWith("@")?(n.positionals=[e,t],a[2]&&(n.result={refLabel:a[2]})):n.positionals=[e,a.slice(1).join(" ")],n}if("swipe"===i){let e=tb(i,a);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}return n.positionals=a,n}(r);e&&t.push(e)}return t}(r),u=i.flags?.replayUpdate===!0,c=0;for(let e=0;e<d.length;e+=1){let r=d[e];if(!r||"replay"===r.command)continue;let l=await s({token:i.token,session:a,command:r.command,positionals:r.positionals??[],flags:sj(i.flags,r.flags),meta:i.meta});if(l.ok)continue;if(!u)return sG(l,r,e,t);let p=await sB({action:r,sessionName:a,logPath:n,sessionStore:o,dispatch:_});if(!p)return sG(l,r,e,t);if(d[e]=p,!(l=await s({token:i.token,session:a,command:p.command,positionals:p.positionals??[],flags:sj(i.flags,p.flags),meta:i.meta})).ok)return sG(l,p,e,t);c+=1}if(u&&c>0){let e=o.get(a);!function(e,t,r){let i=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",a=r.device.target?` target=${r.device.target}`:"";i.push(`context platform=${r.device.platform}${a} device="${e}"${t} theme=unknown`)}for(let e of t)i.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tI(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(tI(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}if("runtime"===e.command){for(let r of e.positionals??[])t.push(tA(r));return ty(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tI(r));return tv(t,e),t.join(" ")}(e));let a=`${i.join("\n")}
35
- `,n=`${e}.tmp-${process.pid}-${Date.now()}`;C.writeFileSync(n,a),C.renameSync(n,e)}(t,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:a}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===O){let e=o.get(a);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};let t=(i.positionals?.[0]??"path").toLowerCase(),r=!!i.flags?.restart;if(!o7.includes(t))return{ok:!1,error:{code:"INVALID_ARGS",message:se}};if(r&&"clear"!==t)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===t){let t=o.resolveAppLogPath(a),r=function(e){if(!C.existsSync(e))return{exists:!1,sizeBytes:0};let t=C.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t),i=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android");return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:i,sizeBytes:r.sizeBytes,modifiedAt:r.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===t){let t=o.resolveAppLogPath(a),r=await tF(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:r.checks,notes:r.notes}}}if("mark"===t){let e,t=i.positionals?.slice(1).join(" ")??"",r=o.resolveAppLogPath(a);return tT(r),e=`[agent-device][mark][${new Date().toISOString()}] ${t.trim()||"marker"}
36
- `,C.appendFileSync(r,e,"utf8"),{ok:!0,data:{path:r,marked:!0}}}if("clear"===t){if(e.appLog&&!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(r){if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};if(!nP("logs",e.device))return{ok:!1,error:b(new g("UNSUPPORTED_OPERATION","logs is not supported on this device"))}}let t=o.resolveAppLogPath(a);if(r){e.appLog&&await m.stop(e.appLog);let r=tV(t),i=o.resolveAppLogPidPath(a);try{let n=await m.start(e.device,e.appBundleId,t,i),s={...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}};return o.set(a,s),{ok:!0,data:{...r,restarted:!0}}}catch(r){let t=b(r);return o.set(a,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:tV(t)}}if("start"===t){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};if(!nP("logs",e.device))return{ok:!1,error:b(new g("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let t=o.resolveAppLogPath(a),r=o.resolveAppLogPidPath(a);try{let i=await m.start(e.device,e.appBundleId,t,r),n={...e,appLog:{platform:e.device.platform,backend:i.backend,outPath:t,startedAt:i.startedAt,getState:i.getState,stop:i.stop,wait:i.wait}};return o.set(a,n),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:b(e)}}}if("stop"===t){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await m.stop(e.appLog),o.set(a,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===O){let e=o.get(a);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};let t=(i.positionals?.[0]??"dump").toLowerCase();if(!sm.includes(t))return{ok:!1,error:{code:"INVALID_ARGS",message:sh}};let r=i.positionals?.[1],n=r?Number.parseInt(r,10):25;if(!Number.isInteger(n)||n<1||n>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let s=(i.positionals?.[2]??"summary").toLowerCase();if(!sw.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:sg}};let l=function(e,t){let r=oI(t?.maxEntries,25,1,200),i=t?.include??"summary",a=oI(t?.maxPayloadChars,2048,64,16384),n=oI(t?.maxScanLines,4e3,100,2e4);if(!C.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:i,limits:{maxEntries:r,maxPayloadChars:a,maxScanLines:n}};let o=C.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-n),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,i){let a=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let i=e.slice(t,r+1);try{let e=JSON.parse(i);return e&&"object"==typeof e?e:null}catch{return null}}(e),n=om(a,["method","httpMethod"]),o=om(a,["url","requestUrl"]),s=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(a,["status","statusCode","responseCode"]),l=oc.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=op.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of of){let r=t.exec(e);if(!r)continue;let i=Number.parseInt(r[1]??"",10);if(Number.isInteger(i))return i}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:og(e,i),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return ow(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,a);t&&(f.headers=og(t,i))}if("body"===r||"all"===r){let t=oh(e,a,["requestBody","body","payload","request"]),r=oh(e,a,["responseBody","response"]);t&&(f.requestBody=og(t,i)),r&&(f.responseBody=og(r,i))}return f}(t,s+e+1,i,a);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:i,limits:{maxEntries:r,maxPayloadChars:a,maxScanLines:n}}}(o.resolveAppLogPath(a),{maxEntries:n,include:s,maxPayloadChars:2048,maxScanLines:4e3}),d=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"),u=[];return e.appLog||u.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&u.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:d,notes:u}}}if("batch"===O)return await sF(i,a,s);if("close"===O){let e=o.get(a);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};e.appLog&&await m.stop(e.appLog),i.positionals&&i.positionals.length>0&&("ios"===e.device.platform&&await k(e.device.id),await _(e.device,"close",i.positionals,i.flags?.out,{...nT(n,i.flags,e.appBundleId,e.trace?.outPath)}),await L(e.device,sa)),"ios"===e.device.platform&&await k(e.device.id),oD(o.getRuntimeHints(a))&&e.appBundleId&&await v({device:e.device,appId:e.appBundleId}).catch(()=>{}),o.recordAction(e,{command:O,positionals:i.positionals??[],flags:i.flags??{},result:{session:a}}),i.flags?.saveScript&&(e.recordSession=!0),o.writeSessionLog(e),await oX(a).catch(()=>{}),o.delete(a);let t=await sN({device:e.device,shutdownRequested:i.flags?.shutdown,shutdownSimulator:N??aE,shutdownAndroidEmulator:S??sb});return t?{ok:!0,data:{session:a,shutdown:t}}:{ok:!0,data:{session:a}}}return null}async function sF(e,t,r){let i=e.flags?.batchOnError??"stop";if("stop"!==i)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${i}.`}};let a=e.flags?.batchMaxSteps??G;if(!Number.isInteger(a)||a<1||a>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let i=B(e.flags?.batchSteps,a),n=Date.now(),o=[];for(let a=0;a<i.length;a+=1){let n=i[a],s=await sV(e,t,n,r,a+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:a,total:i.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:i.length,executed:i.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=h(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function sV(e,t,r,i,a){let n=Date.now(),o=await i({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:function(e,t){let r={...t??{}};delete r.batchSteps,delete r.batchOnError,delete r.batchMaxSteps;let i=e??{};for(let e of o5)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}(e.flags,r.flags),runtime:r.runtime,meta:e.meta}),s=Date.now()-n;return o.ok?{ok:!0,step:a,result:{step:a,command:r.command,ok:!0,data:o.data??{},durationMs:s}}:{ok:!1,step:a,error:o.error}}function sG(e,t,r,i){if(e.ok)return e;let a=r+1,n=function(e){let t;return t=(e.positionals??[]).map(e=>tI(e)),[e.command,...t].join(" ")}(t),o={...e.error.details??{},replayPath:i,step:a,action:t.command,positionals:t.positionals??[]};return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${a} (${n}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:o}}}function sj(e,t){let r={...t??{}},i=e??{};for(let e of o9)void 0===r[e]&&void 0!==i[e]&&(r[e]=i[e]);return r}async function sB(e){let{action:t,sessionName:r,logPath:i,sessionStore:a,dispatch:n}=e;if(!(tg(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=a.get(r);if(!o)return null;let s=tg(t.command)||"fill"===t.command,l=tg(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await sq(o,t,i,s,n,a);for(let e of function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),tg(e.command)){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&t.push(e.positionals.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=n9(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=oq(e.positionals??[]);r&&t.push(r)}let i="string"==typeof e.result?.refLabel?e.result.refLabel.trim():"";if(i.length>0){let r=JSON.stringify(i);"fill"===e.command?(t.push(`id=${r} editable=true`),t.push(`label=${r} editable=true`),t.push(`text=${r} editable=true`),t.push(`value=${r} editable=true`)):(t.push(`id=${r}`),t.push(`label=${r}`),t.push(`text=${r}`),t.push(`value=${r}`))}return tf(t).filter(e=>e.trim().length>0)}(t)){let r=n3(e);if(!r)continue;let i=n4(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!i)continue;let a=ot(i.node,o.device.platform,{action:tg(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tg(t.command))return{...t,positionals:[a]};if("fill"===t.command){let e=tp(t);if(!e)continue;return{...t,positionals:[a,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,a]}}if("is"===t.command){let{predicate:e,split:r}=n9(t.positionals);if(!e)continue;let i=r?.rest.join(" ").trim()??"",n=[e,a];return"text"===e&&i.length>0&&n.push(i),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=oq(t.positionals??[]),r=[a];return e&&r.push(e),{...t,positionals:r}}}let u=function(e,t,r){if("get"!==e.command||e.positionals?.[0]!=="text")return null;let i=e.positionals?.[1];if(!i)return null;let a=n3(i);if(!a)return null;let n=new Set,o=!1;for(let e of a.selectors)for(let t of e.terms)"role"===t.key&&"string"==typeof t.value&&n.add(nX(t.value)),("text"===t.key||"label"===t.key||"value"===t.key)&&"string"==typeof t.value&&/^\d+$/.test(t.value.trim())&&(o=!0);if(!o)return null;let s=t.nodes.filter(e=>{let t=nY(e).trim();return!!/^\d+$/.test(t)&&(0===n.size||n.has(nX(e.type??"")))});if(0===s.length||1!==tf(s.map(e=>nY(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=ot(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function sq(e,t,r,i,a,n){let o=await a(e.device,"snapshot",[],t.flags?.out,{...nT(r,{...t.flags??{},snapshotInteractiveOnly:i,snapshotCompact:i},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:nj(t.flags?.snapshotRaw?s:nK(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,n.set(e.name,e),l}function sH(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function sW(e,t){let r=j(e.type??"Element"),i=H(e,r),a=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,i,a,n,o].join("|")}function sz(e,t){return t.flatten?e.map(e=>({text:z(e,0,!1),comparable:sW(e,0)})):V(e).map(e=>({text:e.text,comparable:sW(e.node,e.depth)}))}function sJ(e,t){return e.get(t)??0}async function sK(e){let{req:t,sessionName:r,logPath:i,sessionStore:a}=e,n=e.dispatchSnapshotCommand??nC,o=e.runnerCommand??tu,s=t.command;if("snapshot"===s){let{session:e,device:o}=await sY(a,r,t.flags);if(!nP("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let s=sZ(t.flags?.snapshotScope,e);return s.ok?await sQ(e,o,async()=>{let l=e?.appBundleId,d=await sX({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope}),u=e?{...e,snapshot:d.snapshot}:{name:r,device:o,createdAt:Date.now(),appBundleId:l,snapshot:d.snapshot,actions:[]};return s0(a,u,t,{nodes:d.snapshot.nodes.length,truncated:d.snapshot.truncated??!1}),a.set(r,u),{ok:!0,data:{nodes:d.snapshot.nodes,truncated:d.snapshot.truncated??!1,appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):s.response}if("diff"===s){if(t.positionals?.[0]!=="snapshot")return{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}};let{session:e,device:o}=await sY(a,r,t.flags);if(!nP("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=sZ(t.flags?.snapshotScope,e);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await sQ(e,o,async()=>{let d=e?.appBundleId,u=(await sX({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:i,snapshotScope:s.scope})).snapshot;if(!e?.snapshot){let i=function(e,t={}){return sz(e,t).length}(u.nodes,{flatten:l}),n=e?{...e,snapshot:u}:{name:r,device:o,createdAt:Date.now(),appBundleId:d,snapshot:u,actions:[]};return s0(a,n,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i}}),a.set(r,n),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:i},lines:[]}}}let c=function(e,t,r={}){let i=function(e,t){let r=e.length,i=t.length,a=r+i,n=new Map,o=[];n.set(1,0);for(let s=0;s<=a;s+=1){o.push(new Map(n));for(let a=-s;a<=s;a+=2){let l=a===-s||a!==s&&sJ(n,a-1)<sJ(n,a+1)?sJ(n,a+1):sJ(n,a-1)+1,d=l-a;for(;l<r&&d<i&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(a,l),l>=r&&d>=i)return function(e,t,r,i,a){let n=[],o=i,s=a;for(let i=e.length-1;i>=0;i-=1){let a=e[i],l=o-s,d=l===-i||l!==i&&sJ(a,l-1)<sJ(a,l+1)?l+1:l-1,u=sJ(a,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===i)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,i)}}return[]}(sz(e,r),sz(t,r)),a={additions:0,removals:0,unchanged:0};for(let e of i)"added"===e.kind&&(a.additions+=1),"removed"===e.kind&&(a.removals+=1),"unchanged"===e.kind&&(a.unchanged+=1);return{summary:a,lines:i}}(e.snapshot.nodes,u.nodes,{flatten:l}),p={...e,snapshot:u};return s0(a,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),a.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines}}})}if("wait"===s){let{session:e,device:o}=await sY(a,r,t.flags),s=function(e){if(0===e.length)return null;let t=sH(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=sH(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=sH(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=sH(e[e.length-1]),i=n5(null!==r?e.slice(0,-1):e.slice());if(i&&0===i.rest.length){let e=n3(i.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:i.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);return s?"sleep"===s.kind?(await new Promise(e=>setTimeout(e,s.durationMs)),s0(a,e,t,{waitedMs:s.durationMs}),{ok:!0,data:{waitedMs:s.durationMs}}):nP("wait",o)?await sQ(e,o,async()=>{let l,d;if("selector"===s.kind){let l=s.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let l=await n(o,"snapshot",[],t.flags?.out,{...nT(i,{...t.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},e?.appBundleId,e?.trace?.outPath)}),u=l?.nodes??[],c=nj(t.flags?.snapshotRaw?u:nK(u));e&&(e.snapshot={nodes:c,truncated:l?.truncated,createdAt:Date.now(),backend:l?.backend},a.set(r,e));let p=n8(c,s.selector,{platform:o.platform});if(p)return s0(a,e,t,{selector:p.selector.raw,waitedMs:Date.now()-d}),{ok:!0,data:{selector:p.selector.raw,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${s.selectorExpression}`}}}if("ref"===s.kind){if(!e?.snapshot)return{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}};let t=nB(s.rawRef);if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${s.rawRef}`}};let r=nq(e.snapshot.nodes,t),i=r?nz(r,e.snapshot.nodes):void 0;if(!i)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s.rawRef} not found or has no label`}};l=i,d=s.timeoutMs}else l=s.text,d=s.timeoutMs;if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}};let u=d??1e4,c=Date.now();for(;Date.now()-c<u;){if("ios"===o.platform){let r=await tu(o,{command:"findText",text:l,appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});if(r?.found)return s0(a,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}}}else if("android"===o.platform&&nW(nj((await iC(o,{scope:l})).nodes??[]),l))return s0(a,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${l}`}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}}:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}}}if("alert"===s){let{session:e,device:n}=await sY(a,r,t.flags),s=(t.positionals?.[0]??"get").toLowerCase();return nP("alert",n)?await sQ(e,n,async()=>{if("wait"===s){let r=sH(t.positionals?.[1])??1e4,s=Date.now();for(;Date.now()-s<r;){try{let r=await o(n,{command:"alert",action:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return s0(a,e,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===s||"dismiss"===s?s:"get",l={verbose:t.flags?.verbose,logPath:i,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===r||"dismiss"===r){let i,s=Date.now();for(;Date.now()-s<2e3;){try{let i=await o(n,{command:"alert",action:r,appBundleId:e?.appBundleId},l);return s0(a,e,t,i),{ok:!0,data:i}}catch(t){i=t;let e=String(t?.message??"").toLowerCase();if(!e.includes("alert not found")&&!e.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw i}let d=await o(n,{command:"alert",action:r,appBundleId:e?.appBundleId},l);return s0(a,e,t,d),{ok:!0,data:d}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}}}if("settings"===s){let e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase();if(!e||!n||"permission"===e&&!o)return{ok:!1,error:{code:"INVALID_ARGS",message:q}};let{session:s,device:l}=await sY(a,r,t.flags);return nP("settings",l)?await sQ(s,l,async()=>{let r=s?.appBundleId,d="permission"===e?[e,n,o,t.positionals?.[3]??"",r??""]:[e,n,r??""],u=await nC(l,"settings",d,t.flags?.out,{...nT(i,t.flags,r,s?.trace?.outPath)});return s0(a,s,t,u??{setting:e,state:n}),{ok:!0,data:u??{setting:e,state:n}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}}}return null}async function sX(e){let{dispatchSnapshotCommand:t,device:r,session:i,req:a,logPath:n,snapshotScope:o}=e,s=await t(r,"snapshot",[],a.flags?.out,{...nT(n,{...a.flags,snapshotScope:o},i?.appBundleId,i?.trace?.outPath)}),l=s?.nodes??[];return{snapshot:{nodes:nj(a.flags?.snapshotRaw?l:nK(l)),truncated:s?.truncated,createdAt:Date.now(),backend:s?.backend}}}function sZ(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref scope requires an existing snapshot in session."}}};let r=nB(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let i=nq(t.snapshot.nodes,r),a=i?nz(i,t.snapshot.nodes):void 0;return a?{ok:!0,scope:a}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function sY(e,t,r){let i=e.get(t),a=i?.device??await nx(r??{});return i||await nU(a),{session:i,device:a}}async function sQ(e,t,r){let i=!e&&"ios"===t.platform;try{return await r()}finally{i&&await ti(t.id)}}function s0(e,t,r,i){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:i})}function s1(e,t,r,i={}){let a=s3(r);if(!a)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(i.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return s2(e.label,r);case"value":return s2(e.value,r);case"id":return s2(e.identifier,r);default:return Math.max(s2(e.label,r),s2(e.value,r),s2(e.identifier,r))}}(r,t,a);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function s2(e,t){let r=s3(e??"");return r?r===t?2:+!!r.includes(t):0}function s3(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function s4(e){let{req:t,sessionName:r,logPath:i,sessionStore:a,invoke:n}=e,o=e.dispatch??nC,s=t.command;if("find"!==s)return null;let l=t.positionals??[];if(0===l.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:d,query:u,action:c,value:p,timeoutMs:f}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let i=e[r]??"",a=e.slice(r+1);if(0===a.length)return{locator:t,query:i,action:"click"};let n=a[0].toLowerCase();if("get"===n){let e=a[1]?.toLowerCase();if("text"===e)return{locator:t,query:i,action:"get_text"};if("attrs"===e)return{locator:t,query:i,action:"get_attrs"};throw new g("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:i,action:"wait",timeoutMs:sH(a[1])??void 0};if("exists"===n)return{locator:t,query:i,action:"exists"};if("click"===n)return{locator:t,query:i,action:"click"};if("focus"===n)return{locator:t,query:i,action:"focus"};if("fill"===n)return{locator:t,query:i,action:"fill",value:a.slice(1).join(" ")};if("type"===n)return{locator:t,query:i,action:"type",value:a.slice(1).join(" ")};throw new g("INVALID_ARGS",`Unsupported find action: ${a[0]}`)}(l);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let m=a.get(r);if(!m&&"exists"!==c&&"wait"!==c&&"get_text"!==c&&"get_attrs"!==c)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let h=m?.device??await nx(t.flags??{});m||await nU(h);let w=m?.appBundleId,I="role"!==d?u:void 0,A="click"===c||"focus"===c||"fill"===c||"type"===c,v=0,y=null,b=async()=>{let e=Date.now();if(y&&e-v<750)return{nodes:y};let n=await o(h,"snapshot",[],t.flags?.out,{...nT(i,{...t.flags,snapshotScope:I,snapshotInteractiveOnly:A,snapshotCompact:A},w,m?.trace?.outPath)}),s=n?.nodes??[],l=nj(t.flags?.snapshotRaw?s:nK(s));return v=e,y=l,m&&(m.snapshot={nodes:l,truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend},a.set(r,m)),{nodes:l,truncated:n?.truncated,backend:n?.backend}};if("wait"===c){let e=f??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await b();if(s1(e,d,u,{requireRect:!1}).matches[0])return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:N}=await b(),S=s1(N,d,u,{requireRect:A});if(A&&S.matches.length>1){let e=S.matches.slice(0,8).map(e=>{let t=nY(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${S.matches.length} elements for ${d} "${u}". Use a more specific locator or selector.`,details:{locator:d,query:u,matches:S.matches.length,candidates:e}}}}let _=S.matches[0]??null;if(!_)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let D="click"===c||"focus"===c||"fill"===c||"type"===c?function(e,t){if(t.hittable)return t;let r=t,i=new Set;for(;void 0!==r.parentIndex&&!i.has(r.ref);){i.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}(N,_)??_:_,E=`@${D.ref}`,k={...t.flags??{},noRecord:!0};if("exists"===c)return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===c){let e=nY(_);return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"get text",text:e}}),{ok:!0,data:{ref:E,text:e,node:_}}}if("get_attrs"===c)return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"get attrs"}}),{ok:!0,data:{ref:E,node:_}};if("click"===c){let e=await n({token:t.token,session:r,command:"click",positionals:[E],flags:k});if(!e.ok)return e;let i=D.rect?nH(D.rect):null,o={ref:E,locator:d,query:u};return i&&(o.x=i.x,o.y=i.y),m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"click",locator:d,query:u}}),{ok:!0,data:o}}if("fill"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await n({token:t.token,session:r,command:"fill",positionals:[E,p],flags:k});return e.ok&&m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"fill"}}),e}if("focus"===c){let e=_.rect?nH(_.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...nT(i,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"focus"}}),{ok:!0,data:r??{ref:E}}}if("type"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=_.rect?nH(_.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...nT(i,t.flags,m?.appBundleId,m?.trace?.outPath)});let r=await o(h,"type",[p],t.flags?.out,{...nT(i,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&a.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"type"}}),{ok:!0,data:r??{ref:E}}}return null}function s8(e){return e instanceof Error?e.message:String(e)}function s6(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function s5(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function s9(e){let{req:t,sessionName:r,sessionStore:i,logPath:a}=e,n=e.deps??{runCmd:f,runCmdBackground:c,runIosRunnerCommand:tu},s=t.command;if("record"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};let u=i.get(r),c=u?.device??await nx(t.flags??{});u||await nU(c);let p=u??{name:r,device:c,createdAt:Date.now(),actions:[]};if("start"===e){if(p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let e=t.flags?.fps;if(void 0!==e&&(!Number.isInteger(e)||e<1||e>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};let u=t.positionals?.[1]??`./recording-${Date.now()}.mp4`;if(!nP("record",c))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let f="ios"===c.platform&&"device"===c.kind?s6(p):void 0;if("ios"===c.platform&&"device"===c.kind&&!f)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};let m=tS.expandHome(u,t.meta?.cwd),h=t.meta?.clientArtifactPaths?.outPath;C.mkdirSync(o.dirname(m),{recursive:!0});let w=s5(t,a,p);if("ios"===c.platform&&"device"===c.kind){let t=`agent-device-recording-${Date.now()}.mp4`,r=`tmp/${t}`,a=async()=>{await n.runIosRunnerCommand(c,{command:"recordStart",outPath:t,fps:e,appBundleId:f},w)};try{await a()}catch(e){if(!s8(e).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${s8(e)}`}};{var l,d;k({level:"warn",phase:"record_start_runner_desynced",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:s8(e)}});let t=(l=c.id,d=p.name,i.toArray().find(e=>e.name!==d&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===l&&e.recording?.platform==="ios-device-runner"));if(t)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${t.name}'`}};try{await n.runIosRunnerCommand(c,{command:"recordStop",appBundleId:f},w)}catch{}try{await a()}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${s8(e)}`}}}}}p.recording={platform:"ios-device-runner",outPath:m,clientOutPath:h,remotePath:r}}else if("ios"===c.platform){let{child:e,wait:t}=n.runCmdBackground("xcrun",eO(c,["io",c.id,"recordVideo",m]),{allowFailure:!0});p.recording={platform:"ios",outPath:m,clientOutPath:h,child:e,wait:t}}else{let e=`/sdcard/agent-device-recording-${Date.now()}.mp4`,{child:t,wait:r}=n.runCmdBackground("adb",["-s",c.id,"shell","screenrecord",e],{allowFailure:!0});p.recording={platform:"android",outPath:m,clientOutPath:h,remotePath:e,child:t,wait:r}}return i.set(r,p),i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start"}}),{ok:!0,data:{recording:"started",outPath:h??u}}}if(!p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let f=p.recording;if("ios-device-runner"===f.platform){let e=s6(p);try{await n.runIosRunnerCommand(c,{command:"recordStop",appBundleId:e},s5(t,a,p))}catch(e){k({level:"warn",phase:"record_stop_runner_failed",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:s8(e)}})}let r={stdout:"",stderr:"",exitCode:1};for(let e of e2)if(0===(r=await n.runCmd("xcrun",["devicectl","device","copy","from","--device",c.id,"--source",f.remotePath,"--destination",f.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(p.recording=void 0,0!==r.exitCode){let e=r.stderr.trim()||r.stdout.trim()||`devicectl exited with code ${r.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}}else{f.child.kill("SIGINT");try{await f.wait}catch{}if("android"===f.platform&&f.remotePath)try{await n.runCmd("adb",["-s",c.id,"pull",f.remotePath,f.outPath],{allowFailure:!0}),await n.runCmd("adb",["-s",c.id,"shell","rm","-f",f.remotePath],{allowFailure:!0})}catch{}p.recording=void 0}i.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:f.outPath}});let m=[{field:"outPath",path:f.outPath,localPath:f.clientOutPath,fileName:o.basename(f.clientOutPath??f.outPath)}];return{ok:!0,data:{recording:"stopped",outPath:f.outPath,artifacts:m}}}if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let a=i.get(r);if(!a)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??i.defaultTracePath(a),r=tS.expandHome(e);return C.mkdirSync(o.dirname(r),{recursive:!0}),C.appendFileSync(r,""),a.trace={outPath:r,startedAt:Date.now()},i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!a.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let n=a.trace.outPath;if(t.positionals?.[1]){let e=tS.expandHome(t.positionals[1]);C.mkdirSync(o.dirname(e),{recursive:!0}),C.existsSync(n)?C.renameSync(n,e):C.appendFileSync(e,""),n=e}return a.trace=void 0,i.recordAction(a,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:n}}),{ok:!0,data:{trace:"stopped",outPath:n}}}return null}function s7(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function le(e){let t=null,r=-1;for(let i of e){let e=i.width*i.height;e>r&&(t=i,r=e)}return t}function lt(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function lr(e){let{req:t,sessionName:r,sessionStore:i,contextFromFlags:a}=e,n=e.dispatch??nC,o=t.command;if("press"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nP("press",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let s=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(s){let r=await n(e.device,"press",[String(s.x),String(s.y)],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[String(s.x),String(s.y)],flags:t.flags??{},result:r??{x:s.x,y:s.y}}),{ok:!0,data:r??{x:s.x,y:s.y}}}let l="click",d=t.positionals?.[0]??"";if(d.startsWith("@")){let r=ln("press",t.flags);if(r)return r;let s=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",u=lo({session:e,refInput:d,fallbackLabel:s,requireRect:!0,invalidRefMessage:`${o} requires a ref like @e2`,notFoundMessage:`Ref ${d} not found or has no bounds`});if(!u.ok)return u.response;let{ref:c}=u.target,p=u.target.node,f=u.target.snapshotNodes,m=ls(p.rect);if(!m){let r=await li(e,t.flags,i,a,{interactiveOnly:!0},n),o=nq(r.nodes,c),l=s.length>0?nW(r.nodes,s):null,d=ls(l?.rect),u=ls(o?.rect)?o:d?l:o??l,h=ls(u?.rect);u&&h&&(p=u,f=r.nodes,m=h)}if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${d} not found or has invalid bounds`}};let h=nz(p,f),w=ot(p,e.device.platform,{action:l}),{x:g,y:I}=m,A=await n(e.device,"press",[String(g),String(I)],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath)});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:c,x:g,y:I,refLabel:h,selectorChain:w}}),{ok:!0,data:{...A??{},ref:c,x:g,y:I}}}let u=(t.positionals??[]).join(" ").trim();if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:`${o} requires @ref, selector expression, or x y coordinates`}};let c=n2(u),p=await li(e,t.flags,i,a,{interactiveOnly:!0},n),f=await E("selector_resolve",()=>n4(p.nodes,c,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!f||!f.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:n6(c,f?.diagnostics??[],{unique:!0})}};let m=ls(f.node.rect);if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${f.selector.raw} resolved to invalid bounds`}};let{x:h,y:w}=m,g=await n(e.device,"press",[String(h),String(w)],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath)}),I=ot(f.node,e.device.platform,{action:l}),A=nz(f.node,p.nodes);return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{x:h,y:w,selector:f.selector.raw,selectorChain:I,refLabel:A}}),{ok:!0,data:{...g??{},selector:f.selector.raw,x:h,y:w}}}if("fill"===o){let e=i.get(r);if(e&&!nP("fill",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let r=ln("fill",t.flags);if(r)return r;let s=t.positionals.length>=3?t.positionals[1]:"",l=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let d=lo({session:e,refInput:t.positionals[0],fallbackLabel:s,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let f=c.type??"",m=f&&!nZ(f,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${f}", attempting fill anyway.`:void 0,h=nz(c,p),w=ot(c,e.device.platform,{action:"fill"}),{x:g,y:I}=nH(c.rect),A={...await n(e.device,"fill",[String(g),String(I),l],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath)})??{ref:u,x:g,y:I}};return m&&(A.warning=m),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...A,refLabel:h,selectorChain:w}}),{ok:!0,data:A}}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let s=n5(t.positionals??[],{preferTrailingValue:!0});if(s){if(0===s.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=s.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let l=n2(s.selectorExpression),d=await li(e,t.flags,i,a,{interactiveOnly:!0},n),u=await E("selector_resolve",()=>n4(d.nodes,l,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!u||!u.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:n6(l,u?.diagnostics??[],{unique:!0})}};let c=u.node,p=c.type??"",f=p&&!nZ(p,e.device.platform)?`fill target ${u.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=nH(u.node.rect),w=await n(e.device,"fill",[String(m),String(h),r],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath)}),g=ot(c,e.device.platform,{action:"fill"}),I={...w??{x:m,y:h,text:r},selector:u.selector.raw,selectorChain:g,refLabel:nz(c,d.nodes)};return f&&(I.warning=f),i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:I}),{ok:!0,data:I}}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}if("get"===o){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nP("get",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let l=t.positionals?.[1]??"";if(l.startsWith("@")){let r=ln("get",t.flags);if(r)return r;let a=lo({session:s,refInput:l,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${l} not found`});if(!a.ok)return a.response;let{ref:n,node:d}=a.target,u=ot(d,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:n,selectorChain:u}}),{ok:!0,data:{ref:n,node:d}};let c=nY(d);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:n,text:c,refLabel:c||void 0,selectorChain:u}}),{ok:!0,data:{ref:n,text:c,node:d}}}let d=t.positionals.slice(1).join(" ").trim();if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let u=n2(d),c=await li(s,t.flags,i,a,{interactiveOnly:!1},n),p=await E("selector_resolve",()=>n4(c.nodes,u,{platform:s.device.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===e}),{command:o});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:n6(u,[],{unique:!0})}};let f=p.node,m=ot(f,s.device.platform,{action:"get"});if("attrs"===e)return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,node:f}};let h=nY(f);return i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{text:h,refLabel:h||void 0,selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,text:h,node:f}}}if("is"===o){let e=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let s=i.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nP("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=n9(t.positionals);if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let d=l.rest.join(" ").trim();if("text"===e&&!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==e&&l.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${e} does not accept trailing values`}};let u=n2(l.selectorExpression),c=await li(s,t.flags,i,a,{interactiveOnly:!1},n);if("exists"===e){let r=n8(c.nodes,u,{platform:s.device.platform});return r?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:r.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:r.matches}}),{ok:!0,data:{predicate:e,pass:!0,selector:r.selector.raw,matches:r.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:n6(u,[],{unique:!1})}}}let p=await E("selector_resolve",()=>n4(c.nodes,u,{platform:s.device.platform,requireUnique:!0}),{command:"is",predicate:e});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:n6(u,[],{unique:!0})}};let f=function(e){let{predicate:t,node:r,expectedText:i,platform:a}=e,n=nY(r),o=!1;switch(t){case"visible":o=n7(r);break;case"hidden":o=!n7(r);break;case"editable":o=oe(r,a);break;case"selected":o=!0===r.selected;break;case"text":o=n===(i??"")}let s="text"===t?`expected="${i??""}" actual="${n}"`:`actual=${JSON.stringify({visible:n7(r),editable:oe(r,a),selected:!0===r.selected})}`;return{pass:o,actualText:n,details:s}}({predicate:e,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(i.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===e?f.actualText:void 0}}),{ok:!0,data:{predicate:e,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${e} failed for selector ${p.selector.raw}: ${f.details}`}}}if("scrollintoview"===o){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nP("scrollintoview",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let s=t.positionals?.[0]??"";if(!s.startsWith("@"))return null;let l=ln("scrollintoview",t.flags);if(l)return l;let d=lo({session:e,refInput:s,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${s} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s} not found or has no bounds`}};let f=function(e,t){let r=nH(t),i=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),a=i.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=le(a.map(e=>e.rect).filter(e=>s7(e,r.x,r.y)));if(n)return n;let o=le(a.map(e=>e.rect));if(o)return o;let s=le(i.map(e=>e.rect).filter(e=>s7(e,r.x,r.y)));return s||null}(p,c.rect);if(!f)return{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${s}`}};let m=function(e,t){var r,i;let a=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+a,l=t.x,d=t.x+n,u=o+.25*a,c=s-.25*a,p=Math.max(8,.1*n),f=e.y+e.height/2,m=e.x+e.width/2;if(f>=u&&f<=c)return null;let h=Math.round((r=m,i=l+p,Math.min(d-p,Math.max(i,r)))),w=Math.round(o+.86*a),g=Math.round(o+.14*a),I=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:lt(Math.ceil((f-c)/I),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:lt(Math.ceil((u-f)/I),1,50),direction:"up"}}(c.rect,f),h=nz(c,p),w=ot(c,e.device.platform,{action:"get"});if(!m)return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,attempts:0,alreadyVisible:!0,refLabel:h,selectorChain:w}}),{ok:!0,data:{ref:u,attempts:0,alreadyVisible:!0}};let g=await n(e.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...a(t.flags,e.appBundleId,e.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return i.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...g??{},ref:u,attempts:m.count,direction:m.direction,refLabel:h,selectorChain:w}}),{ok:!0,data:{...g??{},ref:u,attempts:m.count,direction:m.direction}}}return null}async function li(e,t,r,i,a,n=nC){let o=await n(e.device,"snapshot",[],t?.out,{...i({...t??{},snapshotInteractiveOnly:a.interactiveOnly,snapshotCompact:a.interactiveOnly},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[];return e.snapshot={nodes:nj(t?.snapshotRaw?s:nK(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}let la=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function ln(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,i]of la)void 0!==e[r]&&t.push(i);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}function lo(e){let{session:t,refInput:r,fallbackLabel:i,requireRect:a,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=nB(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=nq(t.snapshot.nodes,s);return((!l||a&&!l.rect)&&i.length>0&&(l=nW(t.snapshot.nodes,i)),l&&(!a||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function ls(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),i=Number(e.width),a=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(i)&&Number.isFinite(a)&&!(i<0)&&!(a<0)?{x:t,y:r,width:i,height:a}:null}(e);if(!t)return null;let r=nH(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function ll(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function ld(e){let{req:t,leaseRegistry:r}=e,i=ll(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:i.tenantId??"",runId:i.runId??"",backend:i.leaseBackend,ttlMs:i.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId,ttlMs:i.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:i.leaseId??"",tenantId:i.tenantId,runId:i.runId})};default:return null}}function lu(e,t){if(!t)return[];let r=[],i=e.device,a=eJ(t.platform);if(a&&a!==i.platform&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(i.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==i.platform||t.udid!==i.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==i.platform||t.serial!==i.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==i.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),a=i.simulatorSetPath?.trim();("ios"!==i.platform||"simulator"!==i.kind||e!==a)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eE(t.androidDeviceAllowlist);"android"===i.platform&&e.has(i.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function lc(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let lp=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],lf=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),lm=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function lh(e,t,r,i){let a=D().requestId;return{...nT(e,t,r,i,a),requestId:a}}function lw(e){C.existsSync(e)&&C.unlinkSync(e)}function lg(e){if(!C.existsSync(e))return null;try{let t=JSON.parse(C.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function lI(e){let t=lg(e);if(!t||t.pid===process.pid)try{C.existsSync(e)&&C.unlinkSync(e)}catch{}}function lA(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:lv,infoPath:ly,lockPath:lb,logPath:lN,sessionsDir:lS}=U(process.env.AGENT_DEVICE_STATE_DIR),l_=$(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var lD=lS;if(C.existsSync(lD))for(let e of C.readdirSync(lD,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=o.join(lD,e.name,"app-log.pid");if(C.existsSync(t))try{let e=function(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}(C.readFileSync(t,"utf8"));if(e&&function(e){let t,r=M(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let i=s(e.pid);return!!i&&!!((t=i.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||i===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{tD(t)}}let lE=new tS(lS),lk=new rs({maxActiveSimulatorLeases:lA(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:lA(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:lA(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:lA(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),lL=S(),lO=p.randomBytes(24).toString("hex"),lM=M(process.pid)??void 0,lx=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=C.statSync(e),r=_(),i=o.relative(r,e)||e;return`${i}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),lC=function(e){let{logPath:t,token:r,sessionStore:i,leaseRegistry:a,trackDownloadableArtifact:n}=e,s=e.dispatchCommand??nC;async function d(e){let u="click"===e.command?{...e,command:"press"}:e,c=!!(u.meta?.debug||u.flags?.verbose);return await x({session:u.session,requestId:u.meta?.requestId,command:u.command,debug:c,logPath:t},async()=>{if(u.token!==r)return{ok:!1,error:b(new g("UNAUTHORIZED","Invalid token"))};try{let e=function(e){let t=N(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,i=l(r);if(r&&!i)throw new g("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!i)throw new g("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");return{...e,session:`${i}:${e.session||"default"}`,meta:{...e.meta,tenantId:i,sessionIsolation:t}}}(u);k({level:"info",phase:"request_start",data:{session:e.session,command:e.command,tenant:e.meta?.tenantId,isolation:e.meta?.sessionIsolation}});let r=e.command,c=ll(e);lm.has(r)||e.meta?.sessionIsolation!=="tenant"||a.assertLeaseAdmission({tenantId:c.tenantId,runId:c.runId,leaseId:c.leaseId,backend:c.leaseBackend});let p=function(e,t){var r;let i,a=e.session||"default";if(r=e,i=r.flags?.session,"string"==typeof i&&i.trim().length>0||"default"!==a||t.has(a))return a;let n=t.toArray();return 1===n.length?n[0].name:a}(e,i),f=i.get(p),m=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let i={...e.flags??{}},a=t?lu(t,i):function(e,t){let r=[],i=eJ(t);for(let t of(void 0!==e.platform&&i&&eJ(e.platform)!==i&&r.push({key:"platform",value:e.platform}),lp)){let i=e[t];"string"==typeof i&&i.trim().length>0&&r.push({key:t,value:i})}return r}(i,e.meta?.lockPlatform);if(0===a.length)return!t&&e.meta?.lockPlatform&&void 0===i.platform&&(i.platform=e.meta.lockPlatform),{...e,flags:i};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(i,a),i.platform=t.device.platform):function(e,t){for(let t of lp)delete e[t];t&&(e.platform=t)}(i,e.meta?.lockPlatform),{...e,flags:i};throw new g("INVALID_ARGS",`${e.command} cannot override session lock policy with ${a.map(lc).join(", ")}. Unset those selectors or remove the request lock policy.`)}(e,f),h=e=>(function(e,t,r){let i=D();if(!t.ok){k({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=R({force:!0})??void 0;return{ok:!1,error:b(new g(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:i.diagnosticId,logPath:e})}}return k({level:"info",phase:"request_success"}),R(),{ok:!0,data:function(e,t,r){var i,a;let n;if(!t)return t;let s=(i=e,a=t,n=Array.isArray(a.artifacts)?[...a.artifacts]:[],"screenshot"!==i.command||n.some(e=>e?.field==="path")||"string"!=typeof a.path||n.push({field:"path",path:a.path,localPath:i.meta?.clientArtifactPaths?.path,fileName:o.basename(i.meta?.clientArtifactPaths?.path??a.path)}),n.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===s.length?t:{...t,artifacts:s.map(t=>{let i=t.path;return{field:t.field,artifactId:r({artifactPath:i,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(m,e,n);!f||m.meta?.lockPolicy||lf.has(r)||function(e,t){let r=lu(e,t);if(0!==r.length){var i;let t,a,n;throw new g("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(i=e).device.platform,a=i.device.name.trim(),n=i.device.id,`${t} device "${a}" (${n})`)} and cannot be used with ${r.map(lc).join(", ")}. Use a different --session name or close this session first.`)}}(f,m.flags);let w=await ld({req:m,leaseRegistry:a});if(w)return h(w);let I=await sU({req:m,sessionName:p,logPath:t,sessionStore:i,invoke:d});if(I)return h(I);let A=await sK({req:m,sessionName:p,logPath:t,sessionStore:i});if(A)return h(A);let v=await s9({req:m,sessionName:p,sessionStore:i,logPath:t});if(v)return h(v);let y=await s4({req:m,sessionName:p,logPath:t,sessionStore:i,invoke:d});if(y)return h(y);let S=await lr({req:m,sessionName:p,sessionStore:i,contextFromFlags:(e,r,i)=>lh(t,e,r,i)});if(S)return h(S);let _=i.get(p);if(!_)return h({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!nP(r,_.device))return h({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}});let E=m.positionals??[],L=m.flags?.out,O="screenshot"===r&&E[0]?[tS.expandHome(E[0],m.meta?.cwd),...E.slice(1)]:E,M="screenshot"===r&&L?tS.expandHome(L,m.meta?.cwd):L,x="screenshot"===r?O:E,C="screenshot"===r&&M?{...m.flags??{},out:M}:m.flags??{},P=await s(_.device,r,O,M,{...lh(t,m.flags,_.appBundleId,_.trace?.outPath)});return i.recordAction(_,{command:r,positionals:x,flags:C,result:P??{}}),h({ok:!0,data:P??{}})}catch(r){k({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=D(),t=R({force:!0})??void 0;return{ok:!1,error:b(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return d}({logPath:lN,token:lO,sessionStore:lE,leaseRegistry:lk,trackDownloadableArtifact:function(e){let t=p.randomUUID(),r=setTimeout(()=>{tj(t)},9e5);return r.unref(),tG.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){C.existsSync(e)||C.mkdirSync(e,{recursive:!0});let i=JSON.stringify(r,null,2),a=()=>{try{return C.writeFileSync(t,i,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(a())return!0;let n=lg(t);if(n?.pid&&n.pid!==process.pid&&d(n.pid,n.processStartTime))return!1;try{C.unlinkSync(t)}catch{}return a()}(lv,lb,{pid:process.pid,version:lL,startedAt:Date.now(),processStartTime:lM})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var i;let a;if("socket"===l_||"dual"===l_){let t=T.createServer(e=>{let t="",r=0,i=new Set,a=!1,n=()=>{if(!a&&0!==r){for(let e of(a=!0,i))ed(e);k({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await ta(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async a=>{let n=(t+=a).indexOf("\n");for(;-1!==n;){let a,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=es(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},i.add(o),el(o),ec(o))throw ef();a=await lC(e)}catch(e){a={ok:!1,error:b(e)}}finally{r-=1,o&&(i.delete(o),eu(o))}e.destroyed||e.write(`${JSON.stringify(a)}
37
- `),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let i=t.address();"object"==typeof i&&i?.port?e(i.port):r(new g("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===l_||"dual"===l_){let e=await re({handleRequest:lC,token:lO});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let i=e.address();"object"==typeof i&&i?.port?t(i.port):r(new g("COMMAND_FAILED","Failed to bind HTTP server"))})})}i={socketPort:e,httpPort:t,token:lO,version:lL,codeSignature:lx,processStartTime:lM},C.existsSync(lv)||C.mkdirSync(lv,{recursive:!0}),C.writeFileSync(lN,""),a=i.socketPort&&i.httpPort?"dual":i.httpPort?"http":"socket",C.writeFileSync(ly,JSON.stringify({port:i.socketPort,httpPort:i.httpPort,transport:a,token:i.token,pid:process.pid,version:i.version,codeSignature:i.codeSignature,processStartTime:i.processStartTime,stateDir:lv},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
23
+ ${a}
24
+ ${i}`.toLowerCase();return n.includes("timeout waiting for screen surfaces")||n.includes("nsposixerrordomain")&&n.includes("code=60")&&n.includes("screenshot")||n.includes("timed out")&&n.includes("screenshot")}let i7={settings:"com.apple.Preferences"},ne=null;function nt(e,t,r){return c("xcrun",eO(e,t),r)}function nr(e){return e.includes("not installed")||e.includes("not found")||e.includes("no such file")}async function na(e,t){let r=t.trim();if(r.includes("."))return r;let a=i7[r.toLowerCase()];if(a)return a;let i=("simulator"===e.kind?await nw(e):await iN(e,"all")).filter(e=>e.name.toLowerCase()===r.toLowerCase());if(1===i.length)return i[0].bundleId;if(i.length>1)throw new w("INVALID_ARGS",`Multiple apps matched "${t}"`,{matches:i});throw new w("APP_NOT_INSTALLED",`No app found matching "${t}"`)}async function ni(e,t,r){let a=r?.url?.trim();if(a){if(!rp(a))throw new w("INVALID_ARGS","open <app> <url> requires a valid URL target");if("simulator"===e.kind){await iM(e),await iO(),await nt(e,["openurl",e.id,a]);return}let i=rf(r?.appBundleId??await na(e,t),a);if(!i)throw new w("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await nS(e,i,{payloadUrl:a});return}let i=t.trim();if(rp(i)){if("simulator"===e.kind){await iM(e),await iO(),await nt(e,["openurl",e.id,i]);return}let t=rf(r?.appBundleId,i);if(!t)throw new w("INVALID_ARGS","Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.");await nS(e,t,{payloadUrl:i});return}let n=r?.appBundleId??await na(e,t);"simulator"===e.kind?await n_(e,n):await nS(e,n)}async function nn(e){"simulator"!==e.kind||"Booted"!==await iC(e)&&(await iM(e),await iO())}async function no(e,t){let r=await na(e,t);if("simulator"===e.kind){await iM(e);let t=eO(e,["terminate",e.id,r]),a=await c("xcrun",t,{allowFailure:!0});if(0!==a.exitCode){if(a.stderr.toLowerCase().includes("found nothing to terminate"))return;throw new w("COMMAND_FAILED",`xcrun exited with code ${a.exitCode}`,{cmd:"xcrun",args:t,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode})}return}await ib(["device","process","terminate","--device",e.id,r],{action:"terminate iOS app",deviceId:e.id})}async function ns(e,t){let r=await na(e,t);if("simulator"!==e.kind){let t=["devicectl","device","uninstall","app","--device",e.id,r],a=await c("xcrun",t,{allowFailure:!0,timeoutMs:iI});if(0!==a.exitCode){let i=String(a.stdout??""),n=String(a.stderr??"");if(!nr(`${i}
25
+ ${n}`.toLowerCase()))throw new w("COMMAND_FAILED",`Failed to uninstall iOS app ${r}`,{cmd:"xcrun",args:t,exitCode:a.exitCode,stdout:i,stderr:n,deviceId:e.id,hint:iD(i,n)??iS})}return{bundleId:r}}await iM(e);let a=await nt(e,["uninstall",e.id,r],{allowFailure:!0});if(0!==a.exitCode&&!nr(`${a.stdout}
26
+ ${a.stderr}`.toLowerCase()))throw new w("COMMAND_FAILED",`simctl uninstall failed for ${r}`,{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{bundleId:r}}async function nl(e,t,r){let a=await iT({kind:"path",path:t},r);try{return await nu(e,a.installablePath),{archivePath:a.archivePath,installablePath:a.installablePath,bundleId:a.bundleId,appName:a.appName,launchTarget:a.bundleId}}finally{await a.cleanup()}}async function nd(e,t,r){let{bundleId:a}=await ns(e,t);return await nl(e,r,{appIdentifierHint:t}),{bundleId:a}}async function nu(e,t){"simulator"!==e.kind?await ib(["device","install","app","--device",e.id,t],{action:"install iOS app",deviceId:e.id}):(await iM(e),await nt(e,["install",e.id,t]))}async function nc(e){iL(e,"clipboard"),await iM(e);let t=await nt(e,["pbpaste",e.id],{allowFailure:!0});if(0!==t.exitCode)throw new w("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 np(e,t){iL(e,"clipboard"),await iM(e);let r=await nt(e,["pbcopy",e.id],{allowFailure:!0,stdin:t});if(0!==r.exitCode)throw new w("COMMAND_FAILED","Failed to write iOS simulator clipboard",{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}async function nf(e,t,r){iL(e,"push"),await iM(e);let a=await L.mkdtemp(i.join(T.tmpdir(),"agent-device-ios-push-")),n=i.join(a,"payload.apns");try{await L.writeFile(n,`${JSON.stringify(r)}
27
+ `,"utf8"),await nt(e,["push",e.id,t,n])}finally{await L.rm(a,{recursive:!0,force:!0})}}async function nm(e,t,r,a,i){iL(e,"settings"),await iM(e);let n=t.toLowerCase();switch(n){case"wifi":{let t=ng(r);await nt(e,["status_bar",e.id,"override","--wifiMode",t?"active":"failed"]);return}case"airplane":return void(ng(r)?await nt(e,["status_bar",e.id,"override","--dataNetwork","hide","--wifiMode","failed","--wifiBars","0","--cellularMode","failed","--cellularBars","0","--operatorName",""]):await nt(e,["status_bar",e.id,"clear"]));case"location":{let t=ng(r);if(!a)throw new w("INVALID_ARGS","location setting requires an active app in session");await nt(e,["privacy",e.id,t?"grant":"revoke","location",a]);return}case"faceid":case"touchid":{let t=nA[n],a=function(e,t){let r=e.trim().toLowerCase();if("match"===r)return"match";if("nonmatch"===r)return"nonmatch";if("enroll"===r)return"enroll";if("unenroll"===r)return"unenroll";throw new w("INVALID_ARGS",`Invalid ${t} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}(r,n);await nN(e,a,{settingName:n,label:t.label,modalityAliases:t.modalityAliases});return}case"appearance":{let t=await nI(e,r);await nt(e,["ui",e.id,"appearance",t]);return}case"permission":{var o;if(!a)throw new w("INVALID_ARGS","permission setting requires an active app in session");let t="deny"===(o=a5(r))?"revoke":o,n=function(e,t){let r=a6(e);if("photos"!==r&&t?.trim())throw new w("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return"camera";if("microphone"===r)return"microphone";if("contacts"===r)return"contacts";if("contacts-limited"===r)return"contacts-limited";if("notifications"===r)return"notifications";if("calendar"===r)return"calendar";if("location"===r)return"location";if("location-always"===r)return"location-always";if("media-library"===r)return"media-library";if("motion"===r)return"motion";if("reminders"===r)return"reminders";if("siri"===r)return"siri";if("photos"===r){let e=t?.trim().toLowerCase();if(!e||"full"===e)return"photos";if("limited"===e)return"photos-add";throw new w("INVALID_ARGS",`Invalid photos mode: ${t}. Use full|limited.`)}throw new w("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 nv(e,t,n,a);return}default:throw new w("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function nh(e,t="all"){var r;return"simulator"===e.kind?(r=await nw(e),"user-installed"===t?r.filter(e=>!e.bundleId.startsWith("com.apple.")):r):await iN(e,t)}async function nw(e){let t=(await nt(e,["listapps",e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let r=null;if(t.startsWith("{"))try{r=JSON.parse(t)}catch{r=null}if(!r&&t.startsWith("{"))try{let e=await c("plutil",["-convert","json","-o","-","-"],{allowFailure:!0,stdin:t});0===e.exitCode&&e.stdout.trim().startsWith("{")&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>({bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e})):[]}function ng(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 w("INVALID_ARGS",`Invalid setting state: ${e}`)}async function nI(e,t){let r=a9(t);if("toggle"!==r)return r;let a=await nt(e,["ui",e.id,"appearance"],{allowFailure:!0});if(0!==a.exitCode)throw new w("COMMAND_FAILED","Failed to read current iOS appearance",{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});let i=function(e,t){let r=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}
28
+ ${t}`);if(!r)return null;let a=r[1].toLowerCase();return"dark"===a?"dark":"light"===a?"light":null}(a.stdout,a.stderr);if(!i)throw new w("COMMAND_FAILED","Unable to determine current iOS appearance for toggle",{stdout:a.stdout,stderr:a.stderr});return"dark"===i?"light":"dark"}let nA={faceid:{label:"Face ID",modalityAliases:["face"]},touchid:{label:"Touch ID",modalityAliases:["finger","touch"]}};async function nv(e,t,r,a){let i=await nb(e);if(!i.has(r))throw new w("UNSUPPORTED_OPERATION",`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:a,hint:`Supported services: ${Array.from(i).sort().join(", ")}`});let n=["privacy",e.id,t,r,a],o="notifications"===r;if(!("reset"===t&&o))try{await nt(e,n);return}catch(t){if(!(o&&ny(t)))throw t;throw new w("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 nt(e,n);return}catch(e){if(!ny(e))throw e}try{await nt(e,["privacy",e.id,"reset","all",a])}catch(t){throw new w("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 ny(e){if(!(e instanceof w)||"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 nb(e){let r=eD(e.simulatorSetPath),a=`${process.env.PATH??""}::${r??""}`;if(ne&&t===a)return ne;let i=await nt(e,["privacy","help"],{allowFailure:!0}),n=function(e){let t=new Set,r=!1;for(let a of e.split("\n")){let e=a.trim();if(!e)continue;if("service"===e){r=!0;continue}if(!r)continue;if(e.startsWith("bundle identifier"))break;let i=/^([a-z-]+)\s+-\s+/.exec(e);i&&t.add(i[1])}return t}(`${i.stdout}
29
+ ${i.stderr}`);if(0===n.size)throw new w("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 ne=n,t=a,n}async function nN(e,t,r){let a=function(e,t,r){let a=r.length>0?r:["face"];switch(t){case"match":return a.flatMap(t=>[["biometric",e,"match",t],["biometric","match",e,t]]);case"nonmatch":return a.flatMap(t=>[["biometric",e,"nonmatch",t],["biometric",e,"nomatch",t],["biometric","nonmatch",e,t],["biometric","nomatch",e,t]]);case"enroll":return[["biometric",e,"enroll","yes"],["biometric",e,"enroll","1"],["biometric","enroll",e,"yes"],["biometric","enroll",e,"1"]];case"unenroll":return[["biometric",e,"enroll","no"],["biometric",e,"enroll","0"],["biometric","enroll",e,"no"],["biometric","enroll",e,"0"]]}}(e.id,t,r.modalityAliases),i=[];for(let t of a){let r=eO(e,t),a=await c("xcrun",r,{allowFailure:!0});if(0===a.exitCode)return;i.push({args:r,stderr:a.stderr,stdout:a.stdout,exitCode:a.exitCode})}let n=i.map(e=>({args:e.args.join(" "),exitCode:e.exitCode,stderr:e.stderr.slice(0,400)}));if(i.length>0&&i.every(e=>{var t,r;let a;return t=e.stdout,r=e.stderr,(a=`${t}
30
+ ${r}`.toLowerCase()).includes("unrecognized subcommand")||a.includes("unknown subcommand")||a.includes("not supported")||a.includes("unavailable")||a.includes("biometric")&&a.includes("invalid")}))throw new w("UNSUPPORTED_OPERATION",`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n});throw new w("COMMAND_FAILED",`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:t,setting:r.settingName,attempts:n})}async function n_(e,t){await iM(e),await iO();let r=0,a=Q.fromTimeoutMs(ig);try{await ee(async({deadline:r})=>{var a;if(r?.isExpired())throw new w("COMMAND_FAILED","App launch deadline exceeded",{timeoutMs:ig});let i=(a=["launch",e.id,t],eO(e,a)),n=await c("xcrun",i,{allowFailure:!0});if(0!==n.exitCode)throw new w("COMMAND_FAILED",`xcrun exited with code ${n.exitCode}`,{cmd:"xcrun",args:i,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry:e=>!!iE(e)&&(r+=1)<3},{deadline:a})}catch(r){if(iE(r)){var i;let a=(i=await ik(e,t)).installed?!1===i.simulatorCompatible?"ARCH_MISMATCH":"PERSISTENT_LAUNCH_FAIL":"APP_NOT_INSTALLED";r.details={...r.details,hint:function(e){switch(e){case"ARCH_MISMATCH":return"The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.";case"APP_NOT_INSTALLED":return"The app bundle is not installed on this simulator. Run install before open.";case"PERSISTENT_LAUNCH_FAIL":return"The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.";default:return"The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details."}}(a)}}throw r}}async function nS(e,t,r){let a=["device","process","launch","--device",e.id,t];r?.payloadUrl&&a.push("--payload-url",r.payloadUrl),await ib(a,{action:"launch iOS app",deviceId:e.id})}let nD=/^[A-Za-z0-9_.:-]{1,64}$/,nE=[[0,0],[1,0],[0,1],[-1,0],[0,-1],[1,1],[-1,1],[1,-1],[-1,-1]];function nk(e,t,r,a){if(!Number.isFinite(e)||!Number.isInteger(e)||e<r||e>a)throw new w("INVALID_ARGS",`${t} must be an integer between ${r} and ${a}`);return e}async function nL(e,t,r){for(let a=0;a<e;a+=1)await r(a),a<e-1&&t>0&&await nO(t)}async function nO(e){await new Promise(t=>setTimeout(t,e))}function nM(e,t){let r,a=t?.subject??"Payload",i=e.trim();if(!i)throw new w("INVALID_ARGS",`${a} cannot be empty`);let n=t?.expandPath?t.expandPath(i,t.cwd):i;try{if(!C.statSync(n).isFile())throw new w("INVALID_ARGS",`${a} path is not a file: ${n}`);return{kind:"file",path:n}}catch(t){if(t instanceof w)throw t;let e=t.code;if("EACCES"===e||"EPERM"===e)throw new w("INVALID_ARGS",`${a} file is not readable: ${n}`);if(e&&"ENOENT"!==e)throw new w("COMMAND_FAILED",`Unable to read ${a} file: ${n}`,{cause:String(t)})}if((r=i.trim()).startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))return{kind:"inline",text:i};throw new w("INVALID_ARGS",`${a} file not found: ${n}`)}async function nx(e){let t=nM(e,{subject:"Push payload"}),r="inline"===t.kind?t.text:await nC(t.path);try{let e=JSON.parse(r);if(!e||"object"!=typeof e||Array.isArray(e))throw new w("INVALID_ARGS","push payload must be a JSON object");return e}catch(t){if(t instanceof w)throw t;throw new w("INVALID_ARGS",`Invalid push payload JSON: ${e}`)}}async function nC(e){try{return await L.readFile(e,"utf8")}catch(r){let t=r.code;if("ENOENT"===t)throw new w("INVALID_ARGS",`Push payload file not found: ${e}`);if("EISDIR"===t)throw new w("INVALID_ARGS",`Push payload path is not a file: ${e}`);if("EACCES"===t||"EPERM"===t)throw new w("INVALID_ARGS",`Push payload file is not readable: ${e}`);throw new w("COMMAND_FAILED",`Unable to read push payload file: ${e}`,{cause:String(r)})}}let nR=ey(process.env.AGENT_DEVICE_IOS_DEVICECTL_LIST_TIMEOUT_MS,8e3,500),nT=/^(iphone|ipad|ipod|appletv)/i,nP=/^appletv/i,n$=["apple tv","appletv","tvos"];function nU(e){return(e??"").trim().toLowerCase()}function nF(e){return nU(e.hardwareProperties?.platform)}function nV(e){return e.includes("tvos")}function nG(e){return nV(nU(e))?"tv":"mobile"}function nB(e){let t=nU(e);return t.includes("ios")||t.includes("tvos")}function nj(e){let t=nU(e);return n$.some(e=>t.includes(e))}function nq(e){return[e.name??"",e.deviceProperties?.name??"",e.deviceProperties?.deviceType??""]}function nH(e){return e.hardwareProperties?.productType??e.deviceProperties?.productType??""}async function nW(e={}){let t,r,a=eD(e.simulatorSetPath),i=e.target;try{t=await c("xcrun",eL(["list","devices","-j"],{simulatorSetPath:a}))}catch{return null}try{r=JSON.parse(t.stdout)}catch{return null}let n=null,o=null,s=null;for(let[e,t]of Object.entries(r.devices)){if(!nB(e))continue;let r=nG(e);if(!i||r===i)for(let e of t){if(!e.isAvailable)continue;let t={platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:r,booted:"Booted"===e.state,...a?{simulatorSetPath:a}:{}};t.booted&&(n=n??t),"mobile"===r&&(o=o??t),s=s??t}}return n??o??s}async function nz(e={}){if("darwin"!==process.platform)throw new w("UNSUPPORTED_PLATFORM","iOS tools are only available on macOS");if(!await I("xcrun"))throw new w("TOOL_MISSING","xcrun not found in PATH");let t=[],r=eD(e.simulatorSetPath),a=await c("xcrun",eL(["list","devices","-j"],{simulatorSetPath:r}));try{let e=JSON.parse(a.stdout);for(let[a,i]of Object.entries(e.devices))if(nB(a))for(let e of i)e.isAvailable&&t.push({platform:"ios",id:e.udid,name:e.name,kind:"simulator",target:nG(a),booted:"Booted"===e.state,...r?{simulatorSetPath:r}:{}})}catch(e){throw new w("COMMAND_FAILED","Failed to parse simctl devices JSON",void 0,e)}if(r)return t;let n=null;try{n=i.join(T.tmpdir(),`agent-device-devicectl-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);let e=await c("xcrun",["devicectl","list","devices","--json-output",n],{allowFailure:!0,timeoutMs:nR});if(0!==e.exitCode)return t;let r=await L.readFile(n,"utf8"),a=JSON.parse(r);for(let e of a.result?.devices??[])if(function(e){var t;let r=nF(e);return!!(r.includes("ios")||r.includes("tvos"))||(t=nH(e),!!nT.test(t.trim())||nq(e).some(nj))}(e)){let r=e.hardwareProperties?.udid??e.identifier??"",a=e.name??e.deviceProperties?.name??r;if(!r)continue;t.push({platform:"ios",id:r,name:a,kind:"device",target:function(e){var t;return nV(nF(e))?"tv":(t=nH(e),nP.test(t.trim())||nq(e).some(nj))?"tv":"mobile"}(e),booted:!0})}}catch{}finally{n&&await L.rm(n,{force:!0}).catch(()=>{})}return t}async function nJ(e,t,r,a){let i,n=!!(t.udid||t.serial||t.deviceName);try{i=await a.resolveDevice(e,t,r)}catch(e){if(n||!(e instanceof w)||"DEVICE_NOT_FOUND"!==e.code)throw e}if(!n&&(!i||"device"===i.kind)){let e=await a.findBootableSimulator({simulatorSetPath:r.simulatorSetPath,target:t.target});if(e)return e}if(i)return i;throw new w("DEVICE_NOT_FOUND","No devices found",{selector:t})}async function nK(e){let t=eJ(e.platform),r=eD(e.iosSimulatorDeviceSet),a=ek(e.androidDeviceAllowlist);return await E("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 w("INVALID_ARGS","Device target selector requires --platform. Use --platform ios|android|apple with --target mobile|tv.");if("android"===i.platform){await rd();let e=await rS({serialAllowlist:a});return await eK(e,i)}if("ios"===i.platform){let e=await nz({simulatorSetPath:r});return await nJ(e,i,{simulatorSetPath:r},{resolveDevice:eK,findBootableSimulator:nW})}let n=[];try{n.push(...await rS({serialAllowlist:a}))}catch{}try{n.push(...await nz({simulatorSetPath:r}))}catch{}return await eK(n,i,{simulatorSetPath:r})},{platform:t,target:e.target})}async function nX(e,t,r,a,n){let o=function(e,t){switch(e.platform){case"android":return{open:(t,r)=>as(e,t,r?.activity),openDevice:()=>ac(e),close:t=>ap(e,t),tap:(t,r)=>aP(e,t,r),doubleTap:async(t,r)=>{await aP(e,t,r),await aP(e,t,r)},swipe:(t,r,a,i,n)=>a$(e,t,r,a,i,n),longPress:(t,r,a)=>aG(e,t,r,a),focus:(t,r)=>aj(e,t,r),type:t=>aB(e,t),fill:(t,r,a)=>aq(e,t,r,a),scroll:(t,r)=>aH(e,t,r),scrollIntoView:t=>aW(e,t),screenshot:(t,r)=>iu(e,t),back:()=>aU(e),home:()=>aF(e),appSwitcher:()=>aV(e),readClipboard:()=>a2(e),writeClipboard:t=>a3(e,t),setSetting:(t,r,a,i)=>a7(e,t,r,a,i)};case"ios":{var r,a;let i,n,{overrides:o,runnerOpts:s}=(r=e,i={verbose:(a=t).verbose,logPath:a.logPath,traceLogPath:a.traceLogPath,requestId:a.requestId},n=()=>{if(ec(a.requestId))throw ef()},{runnerOpts:i,overrides:{tap:async(e,t)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i)},doubleTap:async(e,t)=>{await tu(r,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:a.appBundleId},i)},swipe:async(e,t,n,o,s)=>{await tu(r,{command:"drag",x:e,y:t,x2:n,y2:o,durationMs:s,appBundleId:a.appBundleId},i)},longPress:async(e,t,n)=>{await tu(r,{command:"longPress",x:e,y:t,durationMs:n,appBundleId:a.appBundleId},i)},focus:async(e,t)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i)},type:async e=>{await tu(r,{command:"type",text:e,appBundleId:a.appBundleId},i)},fill:async(e,t,n)=>{await tu(r,{command:"tap",x:e,y:t,appBundleId:a.appBundleId},i),await tu(r,{command:"type",text:n,clearFirst:!0,appBundleId:a.appBundleId},i)},scroll:async(e,t)=>{if(!["up","down","left","right"].includes(e))throw new w("INVALID_ARGS",`Unknown direction: ${e}`);let n=function(e){switch(e){case"up":return"down";case"down":return"up";case"left":return"right";case"right":return"left"}}(e);await tu(r,{command:"swipe",direction:n,appBundleId:a.appBundleId},i)},scrollIntoView:async e=>{let t=await tu(r,{command:"findText",text:e,appBundleId:a.appBundleId},i);if(t?.found)return{attempts:1};for(let t=0;t<12;t+=1){for(let e=0;e<4;e+=1)n(),await tu(r,{command:"swipe",direction:"up",appBundleId:a.appBundleId},i),await new Promise(e=>setTimeout(e,80));n();let o=await tu(r,{command:"findText",text:e,appBundleId:a.appBundleId},i);if(o?.found)return{attempts:t+2}}throw new w("COMMAND_FAILED",`scrollintoview could not find text: ${e}`)}}});return{open:(t,r)=>ni(e,t,{appBundleId:r?.appBundleId,url:r?.url}),openDevice:()=>nn(e),close:t=>no(e,t),screenshot:(t,r)=>iY(e,t,r),back:async()=>{await tu(e,{command:"back",appBundleId:t.appBundleId},s)},home:async()=>{await tu(e,{command:"home",appBundleId:t.appBundleId},s)},appSwitcher:async()=>{await tu(e,{command:"appSwitcher",appBundleId:t.appBundleId},s)},readClipboard:()=>nc(e),writeClipboard:t=>np(e,t),setSetting:(t,r,a,i)=>nm(e,t,r,a,i),...o}}default:throw new w("UNSUPPORTED_PLATFORM",`Unsupported platform: ${e.platform}`)}}(e,{requestId:n?.requestId,appBundleId:n?.appBundleId,verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath});return k({level:"debug",phase:"platform_command_prepare",data:{command:t,platform:e.platform,kind:e.kind}}),await E("platform_command",async()=>{switch(t){case"open":{let t=r[0],a=r[1];if(r.length>2)throw new w("INVALID_ARGS","open accepts at most two arguments: <app|url> [url]");if(!t)return await o.openDevice(),{app:null};if(void 0!==a){if("ios"!==e.platform)throw new w("INVALID_ARGS","open <app> <url> is supported only on iOS");if(rp(t))throw new w("INVALID_ARGS","open <app> <url> requires an app target as the first argument");if(!rp(a))throw new w("INVALID_ARGS","open <app> <url> requires a valid URL target");return await o.open(t,{activity:n?.activity,appBundleId:n?.appBundleId,url:a}),{app:t,url:a}}return await o.open(t,{activity:n?.activity,appBundleId:n?.appBundleId}),{app:t}}case"close":{let e=r[0];if(!e)return{closed:"session"};return await o.close(e),{app:e}}case"press":{let[t,a]=r.map(Number);if(Number.isNaN(t)||Number.isNaN(a))throw new w("INVALID_ARGS","press requires x y");let i=nk(n?.count??1,"count",1,200),s=nk(n?.intervalMs??0,"interval-ms",0,1e4),l=nk(n?.holdMs??0,"hold-ms",0,1e4),d=nk(n?.jitterPx??0,"jitter-px",0,100),u=n?.doubleTap===!0;if(u&&l>0)throw new w("INVALID_ARGS","double-tap cannot be combined with hold-ms");if(u&&d>0)throw new w("INVALID_ARGS","double-tap cannot be combined with jitter-px");if("ios"===e.platform&&i>1&&0===l&&0===d)return await tu(e,{command:"tapSeries",x:t,y:a,count:i,intervalMs:s,doubleTap:u,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{x:t,y:a,count:i,intervalMs:s,holdMs:l,jitterPx:d,doubleTap:u,timingMode:"runner-series"};return await nL(i,s,async e=>{let[r,i]=function(e,t){if(t<=0)return[0,0];let[r,a]=nE[e%nE.length];return[r*t,a*t]}(e,d),n=t+r,s=a+i;u?await o.doubleTap(n,s):l>0?await o.longPress(n,s,l):await o.tap(n,s)}),{x:t,y:a,count:i,intervalMs:s,holdMs:l,jitterPx:d,doubleTap:u}}case"swipe":{let t=Number(r[0]),a=Number(r[1]),i=Number(r[2]),s=Number(r[3]);if([t,a,i,s].some(Number.isNaN))throw new w("INVALID_ARGS","swipe requires x1 y1 x2 y2 [durationMs]");let l=nk(r[4]?Number(r[4]):250,"durationMs",16,1e4),d="ios"===e.platform?Math.min(60,Math.max(16,Math.round(l))):l,u=nk(n?.count??1,"count",1,200),c=nk(n?.pauseMs??0,"pause-ms",0,1e4),p=n?.pattern??"one-way";if("one-way"!==p&&"ping-pong"!==p)throw new w("INVALID_ARGS",`Invalid pattern: ${p}`);if("ios"===e.platform&&u>1)return await tu(e,{command:"dragSeries",x:t,y:a,x2:i,y2:s,durationMs:d,count:u,pauseMs:c,pattern:p,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{x1:t,y1:a,x2:i,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"runner-series",count:u,pauseMs:c,pattern:p};return await nL(u,c,async e=>{"ping-pong"===p&&e%2==1?await o.swipe(i,s,t,a,d):await o.swipe(t,a,i,s,d)}),{x1:t,y1:a,x2:i,y2:s,durationMs:l,effectiveDurationMs:d,timingMode:"ios"===e.platform?"safe-normalized":"direct",count:u,pauseMs:c,pattern:p}}case"longpress":{let e=Number(r[0]),t=Number(r[1]),a=r[2]?Number(r[2]):void 0;if(Number.isNaN(e)||Number.isNaN(t))throw new w("INVALID_ARGS","longpress requires x y [durationMs]");return await o.longPress(e,t,a),{x:e,y:t,durationMs:a}}case"focus":{let[e,t]=r.map(Number);if(Number.isNaN(e)||Number.isNaN(t))throw new w("INVALID_ARGS","focus requires x y");return await o.focus(e,t),{x:e,y:t}}case"type":{let e=r.join(" ");if(!e)throw new w("INVALID_ARGS","type requires text");return await o.type(e),{text:e}}case"fill":{let e=Number(r[0]),t=Number(r[1]),a=r.slice(2).join(" ");if(Number.isNaN(e)||Number.isNaN(t)||!a)throw new w("INVALID_ARGS","fill requires x y text");return await o.fill(e,t,a),{x:e,y:t,text:a}}case"scroll":{let e=r[0],t=r[1]?Number(r[1]):void 0;if(!e)throw new w("INVALID_ARGS","scroll requires direction");return await o.scroll(e,t),{direction:e,amount:t}}case"scrollintoview":{let e=r.join(" ").trim();if(!e)throw new w("INVALID_ARGS","scrollintoview requires text");let t=await o.scrollIntoView(e);if(t?.attempts)return{text:e,attempts:t.attempts};return{text:e}}case"pinch":{if("android"===e.platform)throw new w("UNSUPPORTED_OPERATION","Android pinch is not supported in current adb backend; requires instrumentation-based backend.");let t=Number(r[0]),a=r[1]?Number(r[1]):void 0,i=r[2]?Number(r[2]):void 0;if(Number.isNaN(t)||t<=0)throw new w("INVALID_ARGS","pinch requires scale > 0");return await tu(e,{command:"pinch",scale:t,x:a,y:i,appBundleId:n?.appBundleId},{verbose:n?.verbose,logPath:n?.logPath,traceLogPath:n?.traceLogPath,requestId:n?.requestId}),{scale:t,x:a,y:i}}case"trigger-app-event":{let{eventName:t,payload:a}=function(e){let t=e[0]?.trim(),r=e[1]?.trim();if(!t)throw new w("INVALID_ARGS","trigger-app-event requires <event> [payloadJson]");if(!nD.test(t))throw new w("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 w("INVALID_ARGS","trigger-app-event accepts at most two arguments: <event> [payloadJson]");let a=function(e,t){if(e)try{let r=JSON.parse(e);if(!r||"object"!=typeof r||Array.isArray(r))throw new w("INVALID_ARGS",`trigger-app-event payload for "${t}" must be a JSON object`);let a=JSON.stringify(r);if(Buffer.byteLength(a,"utf8")>8192)throw new w("INVALID_ARGS",`trigger-app-event payload for "${t}" exceeds 8192 bytes`);return r}catch(t){if(t instanceof w)throw t;throw new w("INVALID_ARGS",`Invalid trigger-app-event payload JSON: ${e}`)}}(r,t);return{eventName:t,payload:a}}(r),i=function(e,t,r){let a,i=(a=("ios"===e?process.env.AGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATE:process.env.AGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE)??process.env.AGENT_DEVICE_APP_EVENT_URL_TEMPLATE,a?.trim()||void 0);if(!i)throw new w("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 n=r?JSON.stringify(r):"",o=i.replaceAll("{event}",encodeURIComponent(t)).replaceAll("{payload}",encodeURIComponent(n)).replaceAll("{platform}",encodeURIComponent(e));if(o.length>4096)throw new w("INVALID_ARGS","trigger-app-event URL exceeds maximum supported length",{hint:"Reduce payload size or shorten AGENT_DEVICE_*_APP_EVENT_URL_TEMPLATE.",length:o.length,maxLength:4096});return o}(e.platform,t,a);return await o.open(i,{appBundleId:n?.appBundleId}),{event:t,eventUrl:i,transport:"deep-link"}}case"screenshot":{let e=r[0]??a??`./screenshot-${Date.now()}.png`;return await L.mkdir(i.dirname(e),{recursive:!0}),await o.screenshot(e,n?.appBundleId),{path:e}}case"back":return await o.back(),{action:"back"};case"home":return await o.home(),{action:"home"};case"app-switcher":return await o.appSwitcher(),{action:"app-switcher"};case"clipboard":{let e=(r[0]??"").toLowerCase();if("read"!==e&&"write"!==e)throw new w("INVALID_ARGS","clipboard requires a subcommand: read or write");if("read"===e){if(1!==r.length)throw new w("INVALID_ARGS","clipboard read does not accept additional arguments");return{action:e,text:await o.readClipboard()}}if(r.length<2)throw new w("INVALID_ARGS",'clipboard write requires text (use "" to clear clipboard)');let t=r.slice(1).join(" ");return await o.writeClipboard(t),{action:e,textLength:Array.from(t).length}}case"keyboard":{if("android"!==e.platform)throw new w("UNSUPPORTED_OPERATION","keyboard is currently supported only on Android");let t=(r[0]??"status").toLowerCase();if("status"!==t&&"get"!==t&&"dismiss"!==t)throw new w("INVALID_ARGS","keyboard requires a subcommand: status, get, or dismiss");if(r.length>1)throw new w("INVALID_ARGS","keyboard accepts at most one subcommand argument");if("dismiss"===t){let t=await a1(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 a=await a0(e);return{platform:"android",action:"status",visible:a.visible,inputType:a.inputType,type:a.type}}case"settings":{let[t,a,i,s,l]=r,d="permission"===t?{permissionTarget:i,permissionMode:s}:void 0;return k({level:"debug",phase:"settings_apply",data:{setting:t,state:a,target:i,mode:s,platform:e.platform}}),await o.setSetting(t,a,l??n?.appBundleId,d),{setting:t,state:a}}case"push":{let t=r[0]?.trim(),a=r[1]?.trim();if(!t||!a)throw new w("INVALID_ARGS","push requires <bundle|package> <payload.json|inline-json>");let i=await nx(a);if("ios"===e.platform)return await nf(e,t,i),{platform:"ios",bundleId:t};let n=await is(e,t,i);return{platform:"android",package:t,action:n.action,extrasCount:n.extrasCount}}case"snapshot":{if("ios"===e.platform){let t=await E("snapshot_capture",async()=>await tu(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"}),r=t.nodes??[];if(0===r.length&&"simulator"===e.kind)throw new w("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:t.truncated??!1,backend:"xctest"}}let t=await E("snapshot_capture",async()=>await aM(e,{interactiveOnly:n?.snapshotInteractiveOnly,compact:n?.snapshotCompact,depth:n?.snapshotDepth,scope:n?.snapshotScope,raw:n?.snapshotRaw}),{backend:"android"});return{nodes:t.nodes??[],truncated:t.truncated??!1,backend:"android"}}default:throw new w("INVALID_ARGS",`Unknown command: ${t}`)}},{command:t,platform:e.platform})}let nZ={alert:{ios:{simulator:!0},android:{}},pinch:{ios:{simulator:!0},android:{}},"app-switcher":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},apps:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},back:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},boot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},click:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},clipboard:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},keyboard:{ios:{},android:{emulator:!0,device:!0,unknown:!0}},close:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},fill:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},diff:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},find:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},focus:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},get:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},is:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},home:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},logs:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},network:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},longpress:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},open:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},perf:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},install:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},reinstall:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},press:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},push:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},record:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},screenshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scroll:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},scrollintoview:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},swipe:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},settings:{ios:{simulator:!0},android:{emulator:!0,device:!0,unknown:!0}},snapshot:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},"trigger-app-event":{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},type:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}},wait:{ios:{simulator:!0,device:!0},android:{emulator:!0,device:!0,unknown:!0}}};function nY(e,t){let r=nZ[e];if(!r)return!0;let a=r[t.platform];return!!a&&!0===a[t.kind??"unknown"]}function nQ(e,t,r,a,i){return{requestId:i??S().requestId,appBundleId:r,activity:t?.activity,verbose:t?.verbose,logPath:e,traceLogPath:a,snapshotInteractiveOnly:t?.snapshotInteractiveOnly,snapshotCompact:t?.snapshotCompact,snapshotDepth:t?.snapshotDepth,snapshotScope:t?.snapshotScope,snapshotRaw:t?.snapshotRaw,count:t?.count,intervalMs:t?.intervalMs,holdMs:t?.holdMs,jitterPx:t?.jitterPx,doubleTap:t?.doubleTap,pauseMs:t?.pauseMs,pattern:t?.pattern}}let n0=ey(process.env.AGENT_DEVICE_IOS_DEVICE_READY_TIMEOUT_MS,15e3,1e3);async function n1(e){if("ios"===e.platform){if("simulator"===e.kind){let{ensureBootedSimulator:t}=await Promise.resolve().then(()=>({ensureBootedSimulator:iM}));await t(e);return}if("device"===e.kind)return void await n2(e.id)}if("android"===e.platform){let{waitForAndroidBoot:t}=await Promise.resolve().then(()=>({waitForAndroidBoot:rx}));await t(e.id)}}async function n2(e){let t=i.join(T.tmpdir(),`agent-device-ready-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),r=Math.max(1,Math.ceil(n0/1e3));try{let a=await c("xcrun",["devicectl","device","info","details","--device",e,"--json-output",t,"--timeout",String(r)],{allowFailure:!0,timeoutMs:n0+3e3}),i=String(a.stdout??""),n=String(a.stderr??""),o=await n3(t);if(0===a.exitCode){if(!o.parsed)throw new w("COMMAND_FAILED","iOS device readiness probe failed",{kind:"probe_inconclusive",deviceId:e,stdout:i,stderr:n,hint:"CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device."});let t=o?.tunnelState?.toLowerCase();if("connecting"===t)throw new w("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 w("COMMAND_FAILED","iOS device is not ready for automation",{kind:"not_ready",deviceId:e,stdout:i,stderr:n,exitCode:a.exitCode,tunnelState:o?.tunnelState,hint:n4(i,n)})}catch(t){if(t instanceof w&&"COMMAND_FAILED"===t.code){if("not_ready"===("string"==typeof t.details?.kind?t.details.kind:""))throw t;let r=t.details??{},a=String(r.stdout??""),i=String(r.stderr??""),n=Number(r.timeoutMs??n0),o=`CoreDevice did not respond within ${n}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;throw new w("COMMAND_FAILED","iOS device readiness probe failed",{deviceId:e,cause:t.message,timeoutMs:n,stdout:a,stderr:i,hint:a||i?n4(a,i):o},t)}throw new w("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 L.rm(t,{force:!0}).catch(()=>{})}}async function n3(e){try{let t=await L.readFile(e,"utf8"),r=JSON.parse(t),a=function(e){let t=e?.result;if(!t||"object"!=typeof t)return{};let r=t.connectionProperties?.tunnelState,a=t.device?.connectionProperties?.tunnelState,i="string"==typeof r?r:"string"==typeof a?a:void 0;return i?{tunnelState:i}:{}}(r);return{parsed:!0,tunnelState:a.tunnelState}}catch{return{parsed:!1}}}function n4(e,t){let r=iD(e,t);return r||(`${e}
31
+ ${t}`.toLowerCase().includes("timed out waiting for all destinations")?"Xcode destination did not become available in time. Keep device unlocked and retry.":iS)}function n8(e){return e.map((e,t)=>({...e,ref:`e${t+1}`}))}function n5(e){let t=e.trim();return t.startsWith("@")?t.slice(1)||null:t.startsWith("e")?t:null}function n6(e,t){return e.find(e=>e.ref===t)??null}function n9(e){return{x:Math.round(e.x+e.width/2),y:Math.round(e.y+e.height/2)}}function n7(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),a=(e.value??"").toLowerCase(),i=(e.identifier??"").toLowerCase();return t.includes(r)||a.includes(r)||i.includes(r)})??null}function oe(e,t){let r=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);return r&&ot(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,a=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!ot(t))continue;let i=Math.abs(e.rect.y+e.rect.height/2-r);(!a||i<a.distance)&&(a={label:t,distance:i})}return a?.label}(e,t)??(r&&ot(r)?r:void 0)}function ot(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function or(e){let t=[],r=[];for(let a of e){let e=a.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let i=oa(a.type??""),n=[a.label,a.value,a.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),o=!!n&&ot(n);if(("group"===i||"ioscontentgroup"===i)&&!o){t.push(e);continue}let s=Math.max(0,e-t.length);r.push({...a,depth:s})}return r}function oa(e){let t=e.trim().replace(/XCUIElementType/gi,"").toLowerCase(),r=Math.max(t.lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function oi(e,t){let r=oa(e);return!r||("android"===t?r.includes("edittext")||r.includes("autocompletetextview"):r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("textview")||r.includes("textarea")||"search"===r)}function on(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}let oo=new Set(["id","role","text","label","value"]),os=new Set(["visible","hidden","editable","selected","enabled","hittable"]),ol=new Set([...oo,...os]);function od(e){let t=e.trim();if(!t)throw new w("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!oh(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&"|"===n&&"|"===e[i+1]){let a=r.trim();if(!a)throw new w("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",i+=1;continue}r+=n}let i=r.trim();if(!i)throw new w("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(i),t}(t);if(0===r.length)throw new w("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new w("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let i=0;i<e.length;i+=1){let n=e[i];if(('"'===n||"'"===n)&&!oh(e,i)){a?a===n&&(a=null):a=n,r+=n;continue}if(!a&&/\s/.test(n)){r.trim().length>0&&t.push(r.trim()),r="";continue}r+=n}if(a)throw new w("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim().length>0&&t.push(r.trim()),t}(t);if(0===r.length)throw new w("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(of)}})(e))}}function ou(e){try{return od(e)}catch{return null}}function oc(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,a=0,i=[];for(;a<e.length&&function(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return ol.has(e)}return ol.has(t.toLowerCase())}(e[a]);){a+=1;let t=e.slice(0,a).join(" ").trim();t&&ou(t)&&i.push(a)}if(0===i.length)return null;let n=i[i.length-1];if(r){for(let t=i.length-1;t>=0;t-=1)if(i[t]<e.length){n=i[t];break}}let o=e.slice(0,n).join(" ").trim();return o?{selectorExpression:o,rest:e.slice(n)}:null}function op(e){let t=e[0]??"",r=oc(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function of(e){let t=e.trim();if(!t)throw new w("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!os.has(r))throw new w("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),i=t.slice(r+1).trim();if(!ol.has(a))throw new w("INVALID_ARGS",`Unknown selector key: ${a}`);if(!i)throw new w("INVALID_ARGS",`Missing selector value for key: ${a}`);if(os.has(a)){let e,t="true"===(e=om(i).toLowerCase())||"false"!==e&&null;if(null===t)throw new w("INVALID_ARGS",`Invalid boolean value for ${a}: ${i}`);return{key:a,value:t}}return{key:a,value:om(i)}}function om(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function oh(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}function ow(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return oA(e.identifier,String(t.value));case"role":var a,i;return a=e.type,i=String(t.value),function(e){return oa(e)}(a??"")===function(e){return oa(e)}(i);case"label":return oA(e.label,String(t.value));case"value":return oA(e.value,String(t.value));case"text":{let r=ov(String(t.value));return ov(on(e))===r}case"visible":return og(e)===!!t.value;case"hidden":return!og(e)==!!t.value;case"editable":return oI(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function og(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function oI(e,t){return oi(e.type??"",t)&&!1!==e.enabled}function oA(e,t){return ov(e??"")===ov(t)}function ov(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function oy(e,t,r){let a=r.requireRect??!1,i=r.requireUnique??!0,n=r.disambiguateAmbiguous??!1,o=[];for(let s=0;s<t.selectors.length;s+=1){let l=t.selectors[s],d=function(e,t,r){let a=0,i=null,n=null,o=!1;for(let s of e){if(r.requireRect&&!s.rect||!ow(s,t,r.platform))continue;if(a+=1,i||(i=s),!n){n=s;continue}let e=function(e,t){let r=e.depth??0,a=t.depth??0;if(r!==a)return r>a?1:-1;let i=o_(e),n=o_(t);return i!==n?i<n?1:-1:0}(s,n);if(e>0){n=s,o=!1;continue}0===e&&(o=!0)}return{count:a,firstNode:i,disambiguated:o?null:n}}(e,l,{platform:r.platform,requireRect:a});if(o.push({selector:l.raw,matches:d.count}),0!==d.count&&d.firstNode){if(i&&1!==d.count){if(!n)continue;let e=d.disambiguated;if(!e)continue;return{node:e,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}return{node:d.firstNode,selector:l,selectorIndex:s,matches:d.count,diagnostics:o}}}return null}function ob(e,t,r){let a=r.requireRect??!1,i=[];for(let n=0;n<t.selectors.length;n+=1){let o=t.selectors[n],s=function(e,t,r){let a=0;for(let i of e)(!r.requireRect||i.rect)&&ow(i,t,r.platform)&&(a+=1);return a}(e,o,{platform:r.platform,requireRect:a});if(i.push({selector:o.raw,matches:s}),s>0)return{selectorIndex:n,selector:o,matches:s,diagnostics:i}}return null}function oN(e,t,r){let a=r.unique??!0;if(0===t.length)return`Selector did not match: ${e.raw}`;let i=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return a?`Selector did not resolve uniquely (${i})`:`Selector did not match (${i})`}function o_(e){return e.rect?e.rect.width*e.rect.height:1/0}function oS(e,t,r={}){let a=[],i=oa(e.type??""),n=oE(e.identifier),o=oE(e.label),s=oE(e.value),l=oE(on(e)),d="fill"===r.action;n&&a.push(`id=${oD(n)}`),i&&o&&a.push(d?`role=${oD(i)} label=${oD(o)} editable=true`:`role=${oD(i)} label=${oD(o)}`),o&&a.push(d?`label=${oD(o)} editable=true`:`label=${oD(o)}`),s&&a.push(d?`value=${oD(s)} editable=true`:`value=${oD(s)}`),l&&l!==o&&l!==s&&a.push(d?`text=${oD(l)} editable=true`:`text=${oD(l)}`),i&&d&&!a.some(e=>e.includes("editable=true"))&&a.push(`role=${oD(i)} editable=true`);let u=tf(a);return 0===u.length&&i&&u.push(d?`role=${oD(i)} editable=true`:`role=${oD(i)}`),0===u.length&&og(e)&&u.push("visible=true"),u}function oD(e){return JSON.stringify(e)}function oE(e){if(!e)return null;let t=e.trim();return t||null}let ok=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b","i"),oL=/https?:\/\/[^\s"'<>\])]+/i,oO=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i];function oM(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function ox(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return oC(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(a?.[1])return a[1].trim()}}function oC(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function oR(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function oT(e,t,r,a){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(a,e)):t}let oP="shared_prefs/ReactNativeDevPrefs.xml",o$="debug_http_host",oU="dev_server_https",oF="RCT_jsLocation",oV="RCT_packager_scheme",oG="React Native runtime hints require adb run-as access to the app sandbox. Verify the app is debuggable and the selected package/device are correct.",oB='<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\n<map>\n</map>\n';function oj(e){return void 0!==oq(e)}function oq(e){if(!e)return;let t=o2(e.metroHost),r=o4(e.metroPort),a="http",i=o2(e.bundleUrl);if(i){var n;let e;try{e=new g(i)}catch(e){throw new w("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},e)}("http:"===e.protocol||"https:"===e.protocol)&&(t??=o2(e.hostname),r??=o4(e.port.length>0?Number(e.port):"https:"===(n=e.protocol)?443:"http:"===n?80:void 0),a="https:"===e.protocol?"https":"http")}if(t&&r)return{host:t,port:r,scheme:a}}async function oH(e){let{device:t,appId:r,runtime:a}=e;if(!r)return;let i=oq(a);if(i){if("android"===t.platform)return void await oz(t,r,i);"ios"===t.platform&&"simulator"===t.kind&&await oZ(t,r,i)}}async function oW(e){let{device:t,appId:r}=e;if(r){if("android"===t.platform)return void await oJ(t,r);"ios"===t.platform&&"simulator"===t.kind&&await oY(t,r)}}async function oz(e,t,r){var a,i,n,o,s,l;let d,u;o3(t);let c=(a=await oK(e,t),i=o$,n=`${r.host}:${r.port}`,d=` <string name="${o8(i)}">${o8(n)}</string>`,o0(o1(a,i),d));o=c,s=oU,l="https"===r.scheme,u=` <boolean name="${o8(s)}" value="${l?"true":"false"}" />`,c=o0(o1(o,s),u),await oX(e,t,c)}async function oJ(e,t){o3(t);let r=await oK(e,t),a=o1(r,o$),i=o1(a,oU);i!==r&&await oX(e,t,i)}async function oK(e,t){let r=await c("adb",rl(e,["shell","run-as",t,"cat",oP]),{allowFailure:!0});return 0!==r.exitCode?oB:oQ(r.stdout)}async function oX(e,t,r){let a=rl(e,["shell","run-as",t,"id"]),i=await c("adb",a,{allowFailure:!0});if(0!==i.exitCode){let e=o5(i.stdout,i.stderr);throw new w("COMMAND_FAILED",e?`Failed to access Android app sandbox for ${t}`:`Failed to probe Android app sandbox for ${t}`,{package:t,cmd:"adb",args:a,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:e?oG:"adb shell run-as probe failed. Check adb connectivity and that the device is reachable. Inspect stderr/details for more information."})}try{await c("adb",rl(e,["shell","run-as",t,"mkdir","-p","shared_prefs"])),await c("adb",rl(e,["shell","run-as",t,"tee",oP]),{stdin:r.trimEnd()})}catch(a){let e=f(a);if("TOOL_MISSING"===e.code)throw e;let r=o5("string"==typeof e.details?.stdout?e.details.stdout:"","string"==typeof e.details?.stderr?e.details.stderr:"");throw new w("COMMAND_FAILED",r?`Failed to access Android app sandbox for ${t}`:`Failed to write Android runtime hints for ${t}`,{...e.details??{},package:t,cmd:"adb",phase:"write-runtime-hints",hint:r?oG:"adb run-as succeeded, but writing ReactNativeDevPrefs.xml failed. Inspect stderr/details for the failing shell command."},e)}}async function oZ(e,t,r){await c("xcrun",eO(e,["spawn",e.id,"defaults","write",t,oF,"-string",`${r.host}:${r.port}`])),await c("xcrun",eO(e,["spawn",e.id,"defaults","write",t,oV,"-string",r.scheme]))}async function oY(e,t){await c("xcrun",eO(e,["spawn",e.id,"defaults","delete",t,oF]),{allowFailure:!0}),await c("xcrun",eO(e,["spawn",e.id,"defaults","delete",t,oV]),{allowFailure:!0})}function oQ(e){let t=e.trim();return t.includes("<map")&&t.includes("</map>")?`${t}
32
+ `:oB}function o0(e,t){return oQ(e).replace("</map>",`${t}
33
+ </map>`)}function o1(e,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return oQ(e).replace(RegExp(`^\\s*<string name="${r}">[\\s\\S]*?<\\/string>\\n?`,"m"),"").replace(RegExp(`^\\s*<boolean name="${r}" value="(?:true|false)"\\s*\\/?>\\n?`,"m"),"")}function o2(e){let t=e?.trim();return t&&t.length>0?t:void 0}function o3(e){if("binary"!==rT(e))return;let t=rP(e);throw new w("INVALID_ARGS",t,{package:e,hint:t})}function o4(e){if(Number.isInteger(e)&&!(e<=0)&&!(e>65535))return e}function o8(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function o5(e,t){let r=`${e}
34
+ ${t}`.toLowerCase();return["run-as: package not debuggable","run-as: permission denied","run-as: package is unknown","run-as: unknown package","is unknown","is not an application","could not set capabilities"].some(e=>r.includes(e))}function o6(e){if(0===e.length)return{selectorExpression:null,selectorTimeout:null};let t=e[e.length-1],r=/^\d+$/.test(t??""),a=oc(r?e.slice(0,-1):e.slice());return!a||a.rest.length>0?{selectorExpression:null,selectorTimeout:null}:{selectorExpression:a.selectorExpression,selectorTimeout:r?t:null}}function o9(e){return!!e&&!Number.isNaN(Number(e))}let o7=ey(process.env.AGENT_DEVICE_INSTALL_SOURCE_RETAIN_TTL_MS,9e5,5e3),se=new Map;async function st(e){let t=await a.mkdtemp(i.join(T.tmpdir(),"agent-device-materialized-"));try{let r=await si(e.installablePath,i.join(t,"installable")),a=e.archivePath?await si(e.archivePath,i.join(t,"archive")):void 0,n=u.randomUUID(),o=e.ttlMs??o7,s=Date.now()+o,l=setTimeout(()=>{sr(n)},o);return se.set(n,{rootPath:t,installablePath:r,archivePath:a,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:s,timer:l}),{materializationId:n,installablePath:r,...a?{archivePath:a}:{},expiresAt:new Date(s).toISOString()}}catch(e){throw await a.rm(t,{recursive:!0,force:!0}),e}}async function sr(e,t){let r=se.get(e);if(!r)throw new w("INVALID_ARGS",`Materialized paths not found: ${e}`);if(r.tenantId&&r.tenantId!==t)throw new w("UNAUTHORIZED","Materialized paths belong to a different tenant");clearTimeout(r.timer),se.delete(e),await a.rm(r.rootPath,{recursive:!0,force:!0})}async function sa(e){let t=Array.from(se.entries()).filter(([,t])=>t.sessionName===e).map(([e])=>e);await Promise.all(t.map(async e=>{await sr(e)}))}async function si(e,t){let r=await a.stat(e);await a.mkdir(t,{recursive:!0});let n=i.join(t,i.basename(e));return r.isDirectory()?await a.cp(e,n,{recursive:!0}):await a.copyFile(e,n),n}async function sn(e){var t;let r="ios"===(t=e.flags?.platform)||"android"===t?t:void 0;if(e.session){if(r&&e.session.device.platform!==r)throw new w("INVALID_ARGS",`install_from_source requested platform ${r}, but session is bound to ${e.session.device.platform}`);return await n1(e.session.device),e.session.device}if(!r)throw new w("INVALID_ARGS",'install_from_source requires platform "ios" or "android" when no session is provided');let a=await nK(e.flags??{});return await n1(a),a}async function so(e){let{req:t,sessionName:r,sessionStore:a,deps:i}=e,n=a.get(r);try{let e,o,s,l=(o=function(e){let t=e.meta?.installSource;if(!t)throw new w("INVALID_ARGS","install_from_source requires a source payload");if("url"===t.kind){if(!t.url||0===t.url.trim().length)throw new w("INVALID_ARGS","install_from_source url source requires a non-empty url");return t}if(!t.path||0===t.path.trim().length)throw new w("INVALID_ARGS","install_from_source path source requires a non-empty path");return t}(t),(s=t.meta?.uploadedArtifactId)&&"path"===o.kind?{source:{kind:"path",path:tq(s,t.meta?.tenantId)},cleanup:()=>{tH(s)}}:{source:o,cleanup:()=>{}}),d=function(e){let t=e.meta?.retainMaterializedPaths===!0,r=e.meta?.materializedPathRetentionMs;if(!t)return{enabled:!1};if(void 0!==r&&r<=0)throw new w("INVALID_ARGS","install_from_source retentionMs must be a positive integer");return{enabled:!0,ttlMs:r}}(t),u=await (i?.resolveInstallDevice??sn)({session:n,flags:t.flags});if(!nY("install",u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"install_from_source is not supported on this device"}};let c=(i?.getRequestSignal??ep)(t.meta?.requestId);if("ios"===u.platform){let e,o=i?.installIosInstallablePath??(await Promise.resolve().then(()=>({closeIosApp:no,ensureBootedSimulator:iM,installIosApp:nl,installIosInstallablePath:nu,listIosApps:nh,listSimulatorApps:nw,openIosApp:ni,openIosDevice:nn,parseIosDeviceAppsPayload:i_,pushIosNotification:nf,readIosClipboardText:nc,reinstallIosApp:nd,resolveIosApp:na,screenshotIos:iY,setIosSetting:nm,uninstallIosApp:ns,writeIosClipboardText:np}))).installIosInstallablePath,s=i?.prepareIosInstallArtifact??(await Promise.resolve().then(()=>({prepareIosInstallArtifact:iT,readIosBundleInfo:iP}))).prepareIosInstallArtifact,p=await s(l.source,{signal:c});try{if(d.enabled&&(e=await st({archivePath:p.archivePath,installablePath:p.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs})),await o(u,p.installablePath),!p.bundleId)throw new w("COMMAND_FAILED","Installed iOS app identity could not be resolved from the artifact");let i={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},bundleId:p.bundleId,...p.appName?{appName:p.appName}:{},launchTarget:p.bundleId,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:i}),{ok:!0,data:i}}catch(r){throw e&&await sr(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await p.cleanup(),l.cleanup()}}let p=i?.prepareAndroidInstallArtifact??(await Promise.resolve().then(()=>({prepareAndroidInstallArtifact:r3}))).prepareAndroidInstallArtifact,f=i?.installAndroidInstallablePathAndResolvePackageName??(await Promise.resolve().then(()=>({appSwitcherAndroid:aV,backAndroid:aU,closeAndroidApp:ap,dismissAndroidKeyboard:a1,ensureAdb:rd,fillAndroid:aq,focusAndroid:aj,getAndroidAppState:an,getAndroidKeyboardState:a0,homeAndroid:aF,inferAndroidAppName:ai,installAndroidApp:aN,installAndroidInstallablePath:ay,installAndroidInstallablePathAndResolvePackageName:ab,isAmStartError:ad,listAndroidApps:ae,longPressAndroid:aG,openAndroidApp:as,openAndroidDevice:ac,parseAndroidLaunchComponent:au,pressAndroid:aP,pushAndroidNotification:is,readAndroidClipboardText:a2,reinstallAndroidApp:a_,resolveAndroidApp:r7,screenshotAndroid:iu,scrollAndroid:aH,scrollIntoViewAndroid:aW,setAndroidSetting:a7,snapshotAndroid:aM,swipeAndroid:a$,typeAndroid:aB,writeAndroidClipboardText:a3}))).installAndroidInstallablePathAndResolvePackageName,m=await p(l.source,{signal:c});try{d.enabled&&(e=await st({archivePath:m.archivePath,installablePath:m.installablePath,tenantId:t.meta?.tenantId,sessionName:n?r:void 0,ttlMs:d.ttlMs}));let o=await f(u,m.installablePath,m.packageName);if(!o)throw new w("COMMAND_FAILED","Installed Android app identity could not be resolved from the artifact or device state");let s=(i?.inferAndroidAppName??(await Promise.resolve().then(()=>({appSwitcherAndroid:aV,backAndroid:aU,closeAndroidApp:ap,dismissAndroidKeyboard:a1,ensureAdb:rd,fillAndroid:aq,focusAndroid:aj,getAndroidAppState:an,getAndroidKeyboardState:a0,homeAndroid:aF,inferAndroidAppName:ai,installAndroidApp:aN,installAndroidInstallablePath:ay,installAndroidInstallablePathAndResolvePackageName:ab,isAmStartError:ad,listAndroidApps:ae,longPressAndroid:aG,openAndroidApp:as,openAndroidDevice:ac,parseAndroidLaunchComponent:au,pressAndroid:aP,pushAndroidNotification:is,readAndroidClipboardText:a2,reinstallAndroidApp:a_,resolveAndroidApp:r7,screenshotAndroid:iu,scrollAndroid:aH,scrollIntoViewAndroid:aW,setAndroidSetting:a7,snapshotAndroid:aM,swipeAndroid:a$,typeAndroid:aB,writeAndroidClipboardText:a3}))).inferAndroidAppName)(o),l={...e?.archivePath?{archivePath:e.archivePath}:{},...e?{installablePath:e.installablePath}:{},packageName:o,...s?{appName:s}:{},launchTarget:o,...e?{materializationId:e.materializationId,materializationExpiresAt:e.expiresAt}:{}};return n&&a.recordAction(n,{command:"install_source",positionals:[],flags:t.flags??{},result:l}),{ok:!0,data:l}}catch(r){throw e&&await sr(e.materializationId,t.meta?.tenantId).catch(()=>{}),r}finally{await m.cleanup(),l.cleanup()}}catch(e){return{ok:!1,error:y(e)}}}async function ss(e){let{req:t}=e;try{let e=t.meta?.materializationId?.trim();if(!e)throw new w("INVALID_ARGS","release_materialized_paths requires a materializationId");return await sr(e,t.meta?.tenantId),{ok:!0,data:{released:!0,materializationId:e}}}catch(e){return{ok:!1,error:y(e)}}}async function sl(e){let t,r,a,{deviceName:i,runtime:n,simulatorSetPath:o,reuseExisting:s,boot:l,ensureReady:d}=e;if("darwin"!==process.platform)throw new w("UNSUPPORTED_PLATFORM","ensure-simulator is only available on macOS");let u={simulatorSetPath:o??void 0};if(s){let e=await sd({deviceName:i,runtime:n,simctlOpts:u});e?(t=e.udid,r=e.runtime,a=!1):(t=(await su({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await sc(t,u),a=!0)}else t=(await su({deviceName:i,runtime:n,simctlOpts:u})).udid,r=await sc(t,u),a=!0;let c=!1;if(l){let e={platform:"ios",id:t,name:i,kind:"simulator",target:"mobile",...o?{simulatorSetPath:o}:{}};await d(e),c=!0}return{udid:t,device:i,runtime:r,created:a,booted:c}}async function sd(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=await c("xcrun",eL(["list","devices","-j"],a),{allowFailure:!0,timeoutMs:iw});if(0!==i.exitCode)return null;try{let e=JSON.parse(String(i.stdout??""));for(let[a,i]of Object.entries(e.devices??{}))if(!r||sp(a).includes(sp(r))){for(let e of i)if(e.isAvailable&&e.name.toLowerCase()===t.toLowerCase())return{udid:e.udid,runtime:a}}return null}catch{return null}}async function su(e){let{deviceName:t,runtime:r,simctlOpts:a}=e,i=r?["create",t,t,r]:["create",t,t],n=await c("xcrun",eL(i,a),{allowFailure:!0});if(0!==n.exitCode)throw new w("COMMAND_FAILED","Failed to create iOS simulator",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??""),exitCode:n.exitCode,hint:"Ensure the device type and runtime identifiers are valid. Run `xcrun simctl list devicetypes` and `xcrun simctl list runtimes` to see available options."});let o=String(n.stdout??"").trim();if(!o)throw new w("COMMAND_FAILED","simctl create returned no UDID",{deviceName:t,runtime:r,stdout:String(n.stdout??""),stderr:String(n.stderr??"")});return{udid:o}}async function sc(e,t){let r=await c("xcrun",eL(["list","devices","-j"],t),{allowFailure:!0,timeoutMs:iw});if(0!==r.exitCode)return"";try{let t=JSON.parse(String(r.stdout??""));for(let[r,a]of Object.entries(t.devices??{}))if(a.some(t=>t.udid===e))return r;return""}catch{return""}}function sp(e){return e.toLowerCase().replace(/[._-]/g,"")}let sf=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_CLOSE_SETTLE_MS,300,0),sm=ey(process.env.AGENT_DEVICE_IOS_SIMULATOR_POST_OPEN_SETTLE_MS,300,0);function sh(e,t,r){return t||sw(r)?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} requires an active session or an explicit device selector (e.g. --platform ios).`}}}function sw(e){return!!(e?.platform||e?.target||e?.device||e?.udid||e?.serial)}function sg(e){return"ios"===e.platform&&"simulator"===e.kind}async function sI(e,t){sg(e)&&!(t<=0)&&await new Promise(e=>setTimeout(e,t))}async function sA(e){let t=sw(e.flags)||!e.session?await e.resolveTargetDeviceFn(e.flags??{}):e.session.device;return!1!==e.ensureReady&&await e.ensureReadyFn(t),t}function sv(e){let t=e.flags?.device?.trim();return t||(e.resolvedDevice?.platform==="android"&&"emulator"===e.resolvedDevice.kind?e.resolvedDevice.name:e.sessionDevice?.platform==="android"&&"emulator"===e.sessionDevice.kind?e.sessionDevice.name:void 0)}let sy=["platform","metroHost","metroPort","bundleUrl","launchUrl"];function sb(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>void 0!==e&&""!==e).length:0}function sN(e){let t=e?.trim();return t&&t.length>0?t:void 0}function s_(e,t){if(void 0!==e){if("string"!=typeof e)throw new w("INVALID_ARGS",`Invalid open runtime ${t}: expected string.`);return sN(e)}}function sS(e){if(void 0!==e){if(!Number.isInteger(e)||e<1||e>65535)throw new w("INVALID_ARGS",`Invalid runtime metroPort: ${String(e)}. Use an integer between 1 and 65535.`);return e}}function sD(e){try{return{ok:!0,data:function(e){let{req:t,sessionStore:r,sessionName:a,device:i}=e,n=r.getRuntimeHints(a),o=function(e){let{runtime:t,sessionName:r,platform:a}=e;if(void 0===t)return;if(!t||"object"!=typeof t||Array.isArray(t))throw new w("INVALID_ARGS","open runtime must be an object.");let i=Object.keys(t).find(e=>!sy.includes(e));if(i)throw new w("INVALID_ARGS",`Invalid open runtime field: ${i}. Supported fields are ${sy.join(", ")}.`);return{platform:function(e,t,r){if(void 0===e)return r;if("ios"!==e&&"android"!==e)throw new w("INVALID_ARGS",`Invalid open runtime platform: ${String(e)}. Use "ios" or "android".`);if(r&&e!==r)throw new w("INVALID_ARGS",`open runtime targets ${e}, but session "${t}" is bound to ${r}.`);return e}(t.platform,r,a),metroHost:s_(t.metroHost,"metroHost"),metroPort:function(e){if(void 0!==e){if("number"!=typeof e)throw new w("INVALID_ARGS","Invalid open runtime metroPort: expected integer.");return sS(e)}}(t.metroPort),bundleUrl:s_(t.bundleUrl,"bundleUrl"),launchUrl:s_(t.launchUrl,"launchUrl")}}({runtime:t.runtime,sessionName:a,platform:i.platform});return void 0===t.runtime?{runtime:function(e,t,r){let a=e.getRuntimeHints(t);if(a){if(a.platform&&r&&a.platform!==r.platform)throw new w("INVALID_ARGS",`Session runtime hints target ${a.platform}, but session "${t}" is bound to ${r.platform}. Clear the runtime hints or use a different session.`);return r?.platform&&a.platform!==r.platform?{...a,platform:r.platform}:a}}(r,a,i),previousRuntime:n,replacedStoredRuntime:!1}:{runtime:o&&sb(o)>0?o:void 0,previousRuntime:n,replacedStoredRuntime:!0}}(e)}}catch(t){let e=f(t);return{ok:!1,response:{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}}async function sE(e){let{replacedStoredRuntime:t,previousRuntime:r,runtime:a,session:i,clearRuntimeHints:n}=e;!t||!i?.appBundleId||!oj(r)||oj(a)||await n({device:i.device,appId:i.appBundleId})}async function sk(e){var t,r;let{req:a,sessionName:i,sessionStore:n,clearRuntimeHints:o=oW}=e,s=(a.positionals?.[0]??"show").toLowerCase(),l=n.get(i),d=n.getRuntimeHints(i);if(!["set","show","clear"].includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime requires set, show, or clear"}};if("clear"===s){oj(d)&&l?.appBundleId&&await o({device:l.device,appId:l.appBundleId});let e=n.clearRuntimeHints(i);return{ok:!0,data:{session:i,cleared:e}}}if("show"===s)return{ok:!0,data:{session:i,configured:!!d,runtime:d}};let u=eJ(a.flags?.platform)??d?.platform??l?.device.platform;if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires --platform when the session has not been opened yet."}};if(l&&l.device.platform!==u)return{ok:!1,error:{code:"INVALID_ARGS",message:`runtime set targets ${u}, but session "${i}" is already bound to ${l.device.platform}.`}};let c={platform:(t=a.flags,r={platform:u,metroHost:sN(t?.metroHost),metroPort:sS(t?.metroPort),bundleUrl:sN(t?.bundleUrl),launchUrl:sN(t?.launchUrl)}).platform??d?.platform,metroHost:r.metroHost??d?.metroHost,metroPort:r.metroPort??d?.metroPort,bundleUrl:r.bundleUrl??d?.bundleUrl,launchUrl:r.launchUrl??d?.launchUrl};return 0===sb(c)?{ok:!1,error:{code:"INVALID_ARGS",message:"runtime set requires at least one hint such as --metro-host, --metro-port, --bundle-url, or --launch-url."}}:(n.setRuntimeHints(i,c),{ok:!0,data:{session:i,configured:!0,runtime:c}})}async function sL(e,t,r){if("ios"===e.platform&&t)return rp(t)?"device"===e.kind?rf(r,t):void 0:await sO(e,t)}async function sO(e,t){try{let{resolveIosApp:r}=await Promise.resolve().then(()=>({resolveIosApp:na}));return await r(e,t)}catch{return}}async function sM(e,t){if(!("android"!==e.platform||!t||rp(t)))try{let{resolveAndroidApp:r}=await Promise.resolve().then(()=>({resolveAndroidApp:r7})),a=await r(e,t);return"package"===a.type?a.value:void 0}catch{return}}async function sx(e,t,r,a){return await sL(e,t,r)??await a(e,t)??("android"===e.platform&&t&&rp(t)?r:void 0)}let sC="open-command-roundtrip",sR="Not implemented for this platform in this release.";async function sT(e){let{device:t,closeTarget:r,stopIosRunner:a,dispatch:i,outFlag:n,context:o,settleSimulator:s}=e;"ios"===t.platform&&await a(t.id),await i(t,"close",[r],n,o),await s(t,sf)}async function sP(e){let{runtime:t,device:r,dispatch:a,req:i,logPath:n,appBundleId:o,traceLogPath:s,openPositionals:l}=e,d=t?.launchUrl;if(!d||0===l.length||l.length>1)return;let u=l[0]?.trim();!u||rp(u)||await a(r,"open",[d],i.flags?.out,{...nQ(n,i.flags,o,s)})}async function s$(e){var t,r,a;let{req:i,sessionName:n,sessionStore:o,logPath:s,device:l,dispatch:d,applyRuntimeHints:u,stopIosRunner:c,settleSimulator:p,openTarget:f,openPositionals:m,appBundleId:h,runtime:w,existingSession:g}=e,I=i.flags?.relaunch===!0,A=g?.trace?.outPath;if(I&&f){let e=h??f;await sT({device:l,closeTarget:e,stopIosRunner:c,dispatch:d,outFlag:i.flags?.out,context:{...nQ(s,i.flags,h??g?.appBundleId,A)},settleSimulator:p})}await u({device:l,appId:h,runtime:w});let v=Date.now();await d(l,"open",m,i.flags?.out,{...nQ(s,i.flags,h)}),await sP({runtime:w,device:l,dispatch:d,req:i,logPath:s,appBundleId:h,traceLogPath:A,openPositionals:m});let y=f?{durationMs:Math.max(0,Date.now()-v),measuredAt:new Date().toISOString(),method:sC,appTarget:f,appBundleId:h}:void 0;await p(l,sm);let b=function(e){let{existingSession:t,sessionName:r,device:a,appBundleId:i,openTarget:n,saveScript:o}=e;return t?{...t,appBundleId:i,appName:n,recordSession:t.recordSession||o,snapshot:void 0}:{name:r,device:a,createdAt:Date.now(),appBundleId:i,appName:n,recordSession:o,actions:[]}}({existingSession:g,sessionName:n,device:l,appBundleId:h,openTarget:f,saveScript:!!i.flags?.saveScript});void 0!==i.runtime&&(t=o,r=n,(a=w)&&(0===sb(a)?t.clearRuntimeHints(r):t.setRuntimeHints(r,a)));let N=function(e){let{sessionName:t,appName:r,appBundleId:a,startup:i,device:n,runtime:o}=e,s={session:t};return r&&(s.appName=r),a&&(s.appBundleId=a),i&&(s.startup=i),o&&sb(o)>0&&(s.runtime=o),n&&(s.platform=n.platform,s.target=n.target??"mobile",s.device=n.name,s.id=n.id,s.kind=n.kind,"android"===n.platform&&(s.serial=n.id)),n?.platform==="ios"&&(s.device_udid=n.id,s.ios_simulator_device_set=n.simulatorSetPath??null),s}({sessionName:n,appName:f,appBundleId:h,startup:y,device:l,runtime:w});return!function(e){let{req:t,sessionStore:r,session:a,sessionName:i,runtime:n}=e;if(void 0!==t.runtime){if(n)return r.recordAction(a,{command:"runtime",positionals:["set"],flags:{...t.flags??{},platform:a.device.platform,metroHost:n.metroHost,metroPort:n.metroPort,bundleUrl:n.bundleUrl,launchUrl:n.launchUrl},result:{session:i,configured:!0,runtime:n}});r.recordAction(a,{command:"runtime",positionals:["clear"],flags:t.flags??{},result:{session:i,cleared:!0}})}}({req:i,sessionStore:o,session:b,sessionName:n,runtime:w}),o.recordAction(b,{command:"open",positionals:m,flags:i.flags??{},result:N}),o.set(n,b),{ok:!0,data:N}}async function sU(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,ensureReady:o,resolveDevice:s,applyRuntimeHints:l=oH,clearRuntimeHints:d=oW,stopIosRunner:u=ta,settleSimulator:c=sI,resolveAndroidPackageForOpen:p=sM}=e,f=t.flags?.relaunch===!0;if(i.has(r)){let e=i.get(r),s=t.positionals?.[0],m=s??(f?e?.appName:void 0);if(!e||!m)return f?{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app name or an active session app."}}:{ok:!1,error:{code:"INVALID_ARGS",message:"Session already active. Close it first or pass a new --session name."}};if(f&&rp(m))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};if(f&&"android"===e.device.platform&&"binary"===rT(m))return{ok:!1,error:{code:"INVALID_ARGS",message:rP(m)}};await o(e.device);let h=await sx(e.device,m,e.appBundleId,p),w=sD({req:t,sessionStore:i,sessionName:r,device:e.device});if(!w.ok)return w.response;let{runtime:g,previousRuntime:I,replacedStoredRuntime:A}=w.data;await sE({replacedStoredRuntime:A,previousRuntime:I,runtime:g,session:e,clearRuntimeHints:d});let v=s?t.positionals??[]:[m];return await s$({req:t,sessionName:r,sessionStore:i,logPath:a,device:e.device,dispatch:n,applyRuntimeHints:l,stopIosRunner:u,settleSimulator:c,openTarget:m,openPositionals:v,appBundleId:h,runtime:g,existingSession:e})}let m=t.positionals?.[0];if(f&&!m)return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch requires an app argument."}};if(f&&m&&rp(m))return{ok:!1,error:{code:"INVALID_ARGS",message:"open --relaunch does not support URL targets."}};let h=await s(t.flags??{});if(f&&"android"===h.platform&&m&&"binary"===rT(m))return{ok:!1,error:{code:"INVALID_ARGS",message:rP(m)}};let w=i.toArray().find(e=>e.device.id===h.id);if(w)return{ok:!1,error:{code:"DEVICE_IN_USE",message:`Device is already in use by session "${w.name}".`,details:{session:w.name,deviceId:h.id,deviceName:h.name}}};await o(h);let g=await sx(h,m,void 0,p),I=sD({req:t,sessionStore:i,sessionName:r,device:h});if(!I.ok)return I.response;let{runtime:A}=I.data;return await s$({req:t,sessionName:r,sessionStore:i,logPath:a,device:h,dispatch:n,applyRuntimeHints:l,stopIosRunner:u,settleSimulator:c,openTarget:m,openPositionals:t.positionals??[],appBundleId:g,runtime:A})}async function sF(e){let t=await c("adb",["-s",e.id,"emu","kill"],{allowFailure:!0,timeoutMs:15e3});return{success:0===t.exitCode,exitCode:t.exitCode,stdout:String(t.stdout??""),stderr:String(t.stderr??"")}}async function sV(e){let{device:t,shutdownRequested:r,shutdownSimulator:a,shutdownAndroidEmulator:i}=e;if(r&&(sg(t)||"android"===t.platform&&"emulator"===t.kind))try{return sg(t)?await a(t):await i(t)}catch(t){let e=y(t);return{success:!1,exitCode:-1,stdout:"",stderr:e.message,error:e}}}async function sG(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n,stopIosRunner:o=ta,clearRuntimeHints:s=oW,settleSimulator:l=sI,shutdownSimulator:d=ix,shutdownAndroidEmulator:u=sF,appLogOps:c}=e,p=i.get(r);if(!p)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};p.appLog&&await c.stop(p.appLog),t.positionals&&t.positionals.length>0&&("ios"===p.device.platform&&await o(p.device.id),await n(p.device,"close",t.positionals,t.flags?.out,{...nQ(a,t.flags,p.appBundleId,p.trace?.outPath)}),await l(p.device,sf)),"ios"===p.device.platform&&await o(p.device.id),oj(i.getRuntimeHints(r))&&p.appBundleId&&await s({device:p.device,appId:p.appBundleId}).catch(()=>{}),i.recordAction(p,{command:"close",positionals:t.positionals??[],flags:t.flags??{},result:{session:r}}),t.flags?.saveScript&&(p.recordSession=!0),i.writeSessionLog(p),await sa(r).catch(()=>{}),i.delete(r);let f=await sV({device:p.device,shutdownRequested:t.flags?.shutdown,shutdownSimulator:d,shutdownAndroidEmulator:u});return f?{ok:!0,data:{session:r,shutdown:f}}:{ok:!0,data:{session:r}}}let sB={ios:async(e,t,r)=>{let{reinstallIosApp:a}=await Promise.resolve().then(()=>({reinstallIosApp:nd}));return await a(e,t,r)},android:async(e,t,r)=>{let{reinstallAndroidApp:a}=await Promise.resolve().then(()=>({reinstallAndroidApp:a_}));return await a(e,t,r)}},sj={ios:async(e,t,r)=>{let{installIosApp:a}=await Promise.resolve().then(()=>({installIosApp:nl})),i=await a(e,r,{appIdentifierHint:t});return{bundleId:i.bundleId,appName:i.appName,launchTarget:i.launchTarget}},android:async(e,t,r)=>{let{installAndroidApp:a}=await Promise.resolve().then(()=>({installAndroidApp:aN})),i=await a(e,r);return{package:i.packageName,appName:i.appName,launchTarget:i.launchTarget}}};async function sq(e){let{req:t,command:r,sessionName:a,sessionStore:i,ensureReady:n,resolveDevice:o,deployOps:s}=e,l=i.get(a),d=t.flags??{},u=sh(r,l,d);if(u)return u;let c=t.positionals?.[0]?.trim(),p=t.positionals?.[1]?.trim();if(!c||!p)return{ok:!1,error:{code:"INVALID_ARGS",message:`${r} requires: ${r} <app> <path-to-app-binary>`}};let f=t.meta?.uploadedArtifactId;try{let e,a=f?tq(f,t.meta?.tenantId):t_.expandHome(p);if(!C.existsSync(a))return{ok:!1,error:{code:"INVALID_ARGS",message:`App binary not found: ${a}`}};let u=await sA({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!1});if(!nY(r,u))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}};if("ios"===u.platform){let t=await s.ios(u,c,a),r=t.bundleId;e=r?{app:c,appPath:a,platform:"ios",appId:r,bundleId:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"ios",appName:t.appName,launchTarget:t.launchTarget}}else{let t=await s.android(u,c,a),r=t.package;e=r?{app:c,appPath:a,platform:"android",appId:r,package:r,packageName:r,appName:t.appName,launchTarget:t.launchTarget}:{app:c,appPath:a,platform:"android",appName:t.appName,launchTarget:t.launchTarget}}return l&&i.recordAction(l,{command:r,positionals:t.positionals??[],flags:t.flags??{},result:e}),{ok:!0,data:e}}finally{f&&tH(f)}}let sH=["platform","target","device","udid","serial","verbose","out"];async function sW(e,t,r){let a=e.flags?.batchOnError??"stop";if("stop"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:`Unsupported batch on-error mode: ${a}.`}};let i=e.flags?.batchMaxSteps??G;if(!Number.isInteger(i)||i<1||i>1e3)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid batch max-steps: ${String(e.flags?.batchMaxSteps)}`}};try{let a=j(e.flags?.batchSteps,i),n=Date.now(),o=[];for(let i=0;i<a.length;i+=1){let n=a[i],s=await sz(e,t,n,r,i+1);if(!s.ok)return{ok:!1,error:{code:s.error.code,message:`Batch failed at step ${s.step} (${n.command}): ${s.error.message}`,hint:s.error.hint,diagnosticId:s.error.diagnosticId,logPath:s.error.logPath,details:{...s.error.details??{},step:s.step,command:n.command,positionals:n.positionals,executed:i,total:a.length,partialResults:o}}};o.push(s.result)}return{ok:!0,data:{total:a.length,executed:a.length,totalDurationMs:Date.now()-n,results:o}}}catch(t){let e=f(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}}async function sz(e,t,r,a,i){let n=Date.now(),o=await a({token:e.token,session:t,command:r.command,positionals:r.positionals,flags:function(e,t){let{batchSteps:r,batchOnError:a,batchMaxSteps:i,...n}=t??{},o=e??{};for(let e of sH)void 0===n[e]&&void 0!==o[e]&&(n[e]=o[e]);return n}(e.flags,r.flags),runtime:r.runtime,meta:e.meta}),s=Date.now()-n;return o.ok?{ok:!0,step:i,result:{step:i,command:r.command,ok:!0,data:o.data??{},durationMs:s}}:{ok:!1,step:i,error:o.error}}let sJ='iOS appstate requires an active session on the target device. Run open first (for example: open --session sim --platform ios --device "<name>" <app>).',sK=["platform","target","device","udid","serial","verbose","out"],sX=["path","start","stop","doctor","mark","clear"],sZ=`logs requires ${sX.slice(0,-1).join(", ")}, or ${sX.at(-1)}`,sY=["dump","log"],sQ=`network requires ${sY.join(" or ")}`,s0=["summary","headers","body","all"],s1=`network include mode must be one of: ${s0.join(", ")}`,s2=async({avdName:e,serial:t,headless:r})=>{let{ensureAndroidEmulatorBooted:a}=await Promise.resolve().then(()=>({ensureAndroidEmulatorBooted:rM}));return await a({avdName:e,serial:t,headless:r})};async function s3(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:n,resolveDevice:o,dispatch:s,command:l,positionals:d,recordPositionals:u,deriveNextSession:c}=e,p=i.get(r),f=t.flags??{},m=sh(l,p,f);if(m)return m;let h=await sA({session:p,flags:f,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!nY(l,h))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${l} is not supported on this device`}};let w=await s(h,l,d,t.flags?.out,{...nQ(a,t.flags,p?.appBundleId,p?.trace?.outPath)});if(p){let e=c?await c(p,w,h):p;i.recordAction(e,{command:l,positionals:u??d,flags:t.flags??{},result:w??{}}),e!==p&&i.set(r,e)}return{ok:!0,data:w??{}}}async function s4(e){let{req:t,sessionName:r,sessionStore:a,ensureReady:i,resolveDevice:n}=e,o=a.get(r),s=t.flags??{},l=eJ(s.platform);if(!o&&"string"==typeof s?.session&&s.session.trim().length>0)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"ios"===l?`No active session "${r}". Run open with --session ${r} first.`:`No active session "${r}". Run open with --session ${r} first, or omit --session to query by device selector.`}};let d=sh("appstate",o,s);if(d)return d;let u=o?.device.platform==="ios"&&function(e,t){if(!t)return!1;if(!sw(e))return!0;let r=eJ(e?.platform);return!(r&&r!==t.device.platform||e?.target&&e.target!==(t.device.target??"mobile")||e?.udid&&e.udid!==t.device.id||e?.serial&&e.serial!==t.device.id)&&(!e?.device||e.device.trim().toLowerCase()===t.device.name.trim().toLowerCase())}(s,o);if("ios"===l&&!u)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:sJ}};if(u){let e=o.appName??o.appBundleId;return o.appName||o.appBundleId?{ok:!0,data:{platform:"ios",appName:e??"unknown",appBundleId:o.appBundleId,source:"session",device_udid:o.device.id,ios_simulator_device_set:o.device.simulatorSetPath??null}}:{ok:!1,error:{code:"COMMAND_FAILED",message:"No foreground app is tracked for this iOS session. Open an app in the session, then retry appstate."}}}let c=await sA({session:o,flags:s,ensureReadyFn:i,resolveTargetDeviceFn:n,ensureReady:!0});if("ios"===c.platform)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:sJ}};let{getAndroidAppState:p}=await Promise.resolve().then(()=>({getAndroidAppState:an})),f=await p(c);return{ok:!0,data:{platform:"android",package:f.package,activity:f.activity}}}async function s8(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:n,resolveDevice:o,dispatch:s}=e,l=i.get(r),d=t.flags??{},u=sh("clipboard",l,d);if(u)return u;let c=(t.positionals?.[0]??"").toLowerCase();if("read"!==c&&"write"!==c)return{ok:!1,error:{code:"INVALID_ARGS",message:"clipboard requires a subcommand: read or write"}};let p=await sA({session:l,flags:d,ensureReadyFn:n,resolveTargetDeviceFn:o,ensureReady:!0});if(!nY("clipboard",p))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"clipboard is not supported on this device"}};let f=await s(p,"clipboard",t.positionals??[],t.flags?.out,{...nQ(a,t.flags,l?.appBundleId,l?.trace?.outPath)});return l&&i.recordAction(l,{command:t.command,positionals:t.positionals??[],flags:t.flags??{},result:f??{}}),{ok:!0,data:{platform:p.platform,...f??{}}}}async function s5(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n,dispatch:o,ensureReady:s,resolveTargetDevice:l,installOps:d=sj,reinstallOps:u=sB,stopIosRunner:c,appLogOps:p={start:t$,stop:tU},ensureAndroidEmulatorBoot:m=s2,resolveAndroidPackageForOpen:h=sM,applyRuntimeHints:g=oH,clearRuntimeHints:I=oW,settleSimulator:A,shutdownSimulator:v,shutdownAndroidEmulator:b}=e,N=o??nX,_=s??n1,S=l??nK,D=c??ta,E=A??sI,k=t.command;if("session_list"===k)return{ok:!0,data:{sessions:i.toArray().map(e=>({name:e.name,platform:e.device.platform,target:e.device.target??"mobile",device:e.device.name,id:e.device.id,createdAt:e.createdAt,..."ios"===e.device.platform&&{device_udid:e.device.id,ios_simulator_device_set:e.device.simulatorSetPath??null}}))}};if("runtime"===k)return await sk({req:t,sessionName:r,sessionStore:i,clearRuntimeHints:I});if("ensure-simulator"===k)try{let e=t.flags??{},r=e.device,a=e.runtime,i=eD(e.iosSimulatorDeviceSet);if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"ensure-simulator requires --device <name>"}};let n=!0===e.boot,o=!1!==e.reuseExisting,s=await sl({deviceName:r,runtime:a,simulatorSetPath:i,reuseExisting:o,boot:n,ensureReady:_});return{ok:!0,data:{udid:s.udid,device:s.device,runtime:s.runtime,ios_simulator_device_set:i??null,created:s.created,booted:s.booted}}}catch(t){let e=f(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("devices"===k)try{let e=[],r=eD(t.flags?.iosSimulatorDeviceSet),a=ek(t.flags?.androidDeviceAllowlist),i=eJ(t.flags?.platform);if("android"===i){let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:rS}));e.push(...await t({serialAllowlist:a}))}else if("ios"===i){let{listIosDevices:t}=await Promise.resolve().then(()=>({listIosDevices:nz}));e.push(...await t({simulatorSetPath:r}))}else{let{listAndroidDevices:t}=await Promise.resolve().then(()=>({listAndroidDevices:rS})),{listIosDevices:i}=await Promise.resolve().then(()=>({listIosDevices:nz}));try{e.push(...await t({serialAllowlist:a}))}catch{}try{e.push(...await i({simulatorSetPath:r}))}catch{}}let n=(t.flags?.target?e.filter(e=>(e.target??"mobile")===t.flags?.target):e).map(({simulatorSetPath:e,...t})=>t);return{ok:!0,data:{devices:n}}}catch(t){let e=f(t);return{ok:!1,error:{code:e.code,message:e.message,details:e.details}}}if("apps"===k){let e=i.get(r),a=t.flags??{},n=sh(k,e,a);if(n)return n;let o=await sA({session:e,flags:a,ensureReadyFn:_,resolveTargetDeviceFn:S,ensureReady:!0});if(!nY("apps",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"apps is not supported on this device"}};let s=t.flags?.appsFilter??"all";if("ios"===o.platform){let{listIosApps:e}=await Promise.resolve().then(()=>({listIosApps:nh}));return{ok:!0,data:{apps:(await e(o,s)).map(e=>e.name&&e.name!==e.bundleId?`${e.name} (${e.bundleId})`:e.bundleId)}}}let{listAndroidApps:l}=await Promise.resolve().then(()=>({listAndroidApps:ae}));return{ok:!0,data:{apps:(await l(o,s)).map(e=>e.name&&e.name!==e.package?`${e.name} (${e.package})`:e.package)}}}if("boot"===k){let e,a=i.get(r),n=t.flags??{},o=sh(k,a,n);if(o)return o;let s="android"===(eJ(n.platform)??a?.device.platform),l=!0===n.headless;if(l&&!s)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};let d=sv({flags:n,sessionDevice:a?.device}),u=s&&!!d,c=!1;try{e=await sA({session:a,flags:n,ensureReadyFn:_,resolveTargetDeviceFn:S,ensureReady:!1})}catch(r){let t=f(r);if(s&&l&&!d&&"DEVICE_NOT_FOUND"===t.code)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};if(!u||"DEVICE_NOT_FOUND"!==t.code||!d)throw r;e=await m({avdName:d,serial:n.serial,headless:l}),c=!0}if(n.target&&(e.target??"mobile")!==n.target)return{ok:!1,error:{code:"DEVICE_NOT_FOUND",message:`No ${e.platform} device found matching --target ${n.target}.`}};if(s&&l){if("android"!==e.platform||"emulator"!==e.kind)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless is supported only for Android emulators."}};if(!c){let t=sv({flags:n,sessionDevice:a?.device,resolvedDevice:e});if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:"boot --headless requires --device <avd-name> (or an Android emulator session target)."}};e=await m({avdName:t,serial:n.serial,headless:!0})}await _(e)}else("android"!==e.platform||!0!==e.booted)&&await _(e);return nY("boot",e)?{ok:!0,data:{platform:e.platform,target:e.target??"mobile",device:e.name,id:e.id,kind:e.kind,booted:!0}}:{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"boot is not supported on this device"}}}if("appstate"===k)return await s4({req:t,sessionName:r,sessionStore:i,ensureReady:_,resolveDevice:S});if("clipboard"===k)return await s8({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:_,resolveDevice:S,dispatch:N});if("keyboard"===k)return await s3({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:_,resolveDevice:S,dispatch:N,command:"keyboard",positionals:t.positionals??[]});if("perf"===k){let e,t,a,n=i.get(r);return n?{ok:!0,data:(a=(t=(e=function(e){let t=[];for(let r of e){if("open"!==r.command)continue;let e=r.result?.startup;e&&"object"==typeof e&&"number"==typeof e.durationMs&&Number.isFinite(e.durationMs)&&"string"==typeof e.measuredAt&&0!==e.measuredAt.trim().length&&e.method===sC&&t.push({durationMs:Math.max(0,Math.round(e.durationMs)),measuredAt:e.measuredAt,method:sC,appTarget:"string"==typeof e.appTarget&&e.appTarget.length>0?e.appTarget:void 0,appBundleId:"string"==typeof e.appBundleId&&e.appBundleId.length>0?e.appBundleId:void 0})}return t.slice(-20)}(n.actions)).at(-1))?{available:!0,lastDurationMs:t.durationMs,lastMeasuredAt:t.measuredAt,method:sC,sampleCount:e.length,samples:e}:{available:!1,reason:"No startup sample captured yet. Run open <app|url> in this session first.",method:sC},{session:n.name,platform:n.device.platform,device:n.device.name,deviceId:n.device.id,metrics:{startup:a,fps:{available:!1,reason:sR},memory:{available:!1,reason:sR},cpu:{available:!1,reason:sR}},sampling:{startup:{method:sC,description:"Elapsed wall-clock time around dispatching the open command for the active session app target.",unit:"ms"}}})}:{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"perf requires an active session. Run open first."}}}if("install"===k||"reinstall"===k)return await sq({req:t,command:k,sessionName:r,sessionStore:i,ensureReady:_,resolveDevice:S,deployOps:"install"===k?d:u});if("install_source"===k)return await so({req:t,sessionName:r,sessionStore:i});if("release_materialized_paths"===k)return await ss({req:t});if("push"===k){let e,n=t.positionals?.[0]?.trim(),o=t.positionals?.[1]?.trim();if(!n||!o)return{ok:!1,error:{code:"INVALID_ARGS",message:"push requires <bundle|package> <payload.json|inline-json>"}};let s="file"===(e=nM(o,{subject:"Push payload",cwd:t.meta?.cwd,expandPath:(e,t)=>t_.expandHome(e,t)})).kind?e.path:e.text;return await s3({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:_,resolveDevice:S,dispatch:N,command:"push",positionals:[n,s],recordPositionals:[n,o]})}if("trigger-app-event"===k)return await s3({req:t,sessionName:r,logPath:a,sessionStore:i,ensureReady:_,resolveDevice:S,dispatch:N,command:"trigger-app-event",positionals:t.positionals??[],deriveNextSession:async(e,t)=>{let r="string"==typeof t?.eventUrl?t.eventUrl:void 0,a=r?await sx(e.device,r,e.appBundleId,h)??e.appBundleId:e.appBundleId;return{...e,appBundleId:a}}});if("open"===k)return await sU({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:N,ensureReady:_,resolveDevice:S,applyRuntimeHints:g,clearRuntimeHints:I,stopIosRunner:D,settleSimulator:E,resolveAndroidPackageForOpen:h});if("replay"===k){let e=t.positionals?.[0];if(!e)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay requires a path"}};try{let o=t_.expandHome(e,t.meta?.cwd),s=C.readFileSync(o,"utf8"),l=s.trimStart()[0];if("{"===l||"["===l)return{ok:!1,error:{code:"INVALID_ARGS",message:"replay accepts .ad script files. JSON replay payloads are no longer supported."}};let d=function(e){let t=[];for(let r of e.split(/\r?\n/)){let e=function(e){let t=e.trim();if(0===t.length||t.startsWith("#"))return null;let r=function(e){let t=[],r=0;for(;r<e.length;){for(;r<e.length&&/\s/.test(e[r]);)r+=1;if(r>=e.length)break;if('"'===e[r]){let a=r+1,i=!1;for(;a<e.length;){let t=e[a];if('"'===t&&!i)break;i="\\"===t&&!i,"\\"!==t&&(i=!1),a+=1}if(a>=e.length)throw new w("INVALID_ARGS",`Invalid replay script line: ${e}`);let n=e.slice(r,a+1);t.push(JSON.parse(n)),r=a+1;continue}let a=r;for(;a<e.length&&!/\s/.test(e[a]);)a+=1;t.push(e.slice(r,a)),r=a}return t}(t);if(0===r.length)return null;let[a,...i]=r;if("context"===a)return null;let n={ts:Date.now(),command:a,positionals:[],flags:{}};if("snapshot"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("-i"===t){n.flags.snapshotInteractiveOnly=!0;continue}if("-c"===t){n.flags.snapshotCompact=!0;continue}if("--raw"===t){n.flags.snapshotRaw=!0;continue}if(("-d"===t||"--depth"===t)&&e+1<i.length){let t=Number(i[e+1]);Number.isFinite(t)&&t>=0&&(n.flags.snapshotDepth=Math.floor(t)),e+=1;continue}if(("-s"===t||"--scope"===t)&&e+1<i.length){n.flags.snapshotScope=i[e+1],e+=1;continue}if("--backend"===t&&e+1<i.length){e+=1;continue}}return n}if("open"===a){n.positionals=[];for(let e=0;e<i.length;e+=1){let t=i[e];if("--relaunch"===t){n.flags.relaunch=!0;continue}n.positionals.push(t)}return n}if("runtime"===a){let e=function(e){let t=[],r={};for(let a=0;a<e.length;a+=1){let i=e[a];if("--platform"===i&&a+1<e.length){let t=e[a+1];("ios"===t||"android"===t)&&(r.platform=t),a+=1;continue}if("--metro-host"===i&&a+1<e.length){r.metroHost=e[a+1],a+=1;continue}if("--metro-port"===i&&a+1<e.length){let t=tN(e[a+1]);null!==t&&(r.metroPort=t),a+=1;continue}if("--bundle-url"===i&&a+1<e.length){r.bundleUrl=e[a+1],a+=1;continue}if("--launch-url"===i&&a+1<e.length){r.launchUrl=e[a+1],a+=1;continue}t.push(i)}return{positionals:t,flags:r}}(i);return n.positionals=e.positionals,Object.assign(n.flags,e.flags),n}if(tg(a)){let e=tb(a,i);if(Object.assign(n.flags,e.flags),0===e.positionals.length)return n;let t=e.positionals[0];if(t.startsWith("@"))return n.positionals=[t],e.positionals[1]&&(n.result={refLabel:e.positionals[1]}),n;let r=e.positionals[0],o=e.positionals[1];return o9(r)&&o9(o)&&e.positionals.length>=2?n.positionals=[r,o]:n.positionals=[e.positionals.join(" ")],n}if("fill"===a){if(i.length<2)return n.positionals=i,n;let e=i[0];return e.startsWith("@")?(i.length>=3?(n.positionals=[e,i.slice(2).join(" ")],n.result={refLabel:i[1]}):n.positionals=[e,i[1]],n):(n.positionals=[e,i.slice(1).join(" ")],n)}if("get"===a){if(i.length<2)return n.positionals=i,n;let e=i[0],t=i[1];return t.startsWith("@")?(n.positionals=[e,t],i[2]&&(n.result={refLabel:i[2]})):n.positionals=[e,i.slice(1).join(" ")],n}if("swipe"===a){let e=tb(a,i);return Object.assign(n.flags,e.flags),n.positionals=e.positionals,n}return n.positionals=i,n}(r);e&&t.push(e)}return t}(s),u=t.flags?.replayUpdate===!0,c=0;for(let e=0;e<d.length;e+=1){let s=d[e];if(!s||"replay"===s.command)continue;let l=await n({token:t.token,session:r,command:s.command,positionals:s.positionals??[],flags:s9(t.flags,s.flags),meta:t.meta});if(l.ok)continue;if(!u)return s6(l,s,e,o);let p=await s7({action:s,sessionName:r,logPath:a,sessionStore:i,dispatch:N});if(!p)return s6(l,s,e,o);if(d[e]=p,!(l=await n({token:t.token,session:r,command:p.command,positionals:p.positionals??[],flags:s9(t.flags,p.flags),meta:t.meta})).ok)return s6(l,p,e,o);c+=1}if(u&&c>0){let e=i.get(r);!function(e,t,r){let a=[];if(r){let e=r.device.name.replace(/"/g,'\\"'),t=r.device.kind?` kind=${r.device.kind}`:"",i=r.device.target?` target=${r.device.target}`:"";a.push(`context platform=${r.device.platform}${i} device="${e}"${t} theme=unknown`)}for(let e of t)a.push(function(e){let t=[e.command];if("snapshot"===e.command)return e.flags?.snapshotInteractiveOnly&&t.push("-i"),e.flags?.snapshotCompact&&t.push("-c"),"number"==typeof e.flags?.snapshotDepth&&t.push("-d",String(e.flags.snapshotDepth)),e.flags?.snapshotScope&&t.push("-s",tI(e.flags.snapshotScope)),e.flags?.snapshotRaw&&t.push("--raw"),t.join(" ");if("open"===e.command){for(let r of e.positionals??[])t.push(tI(r));return e.flags?.relaunch&&t.push("--relaunch"),t.join(" ")}if("runtime"===e.command){for(let r of e.positionals??[])t.push(tA(r));return ty(t,e.flags),t.join(" ")}for(let r of e.positionals??[])t.push(tI(r));return tv(t,e),t.join(" ")}(e));let i=`${a.join("\n")}
35
+ `,n=`${e}.tmp-${process.pid}-${Date.now()}`;C.writeFileSync(n,i),C.renameSync(n,e)}(o,d,e)}return{ok:!0,data:{replayed:d.length,healed:c,session:r}}}catch(t){let e=f(t);return{ok:!1,error:{code:e.code,message:e.message}}}}if("logs"===k){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"logs requires an active session"}};let a=(t.positionals?.[0]??"path").toLowerCase(),n=!!t.flags?.restart;if(!sX.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:sZ}};if(n&&"clear"!==a)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs --restart is only supported with logs clear"}};if("path"===a){let t=i.resolveAppLogPath(r),a=function(e){if(!C.existsSync(e))return{exists:!1,sizeBytes:0};let t=C.statSync(e);return{exists:!0,sizeBytes:t.size,modifiedAt:t.mtime.toISOString()}}(t),n=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android");return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:n,sizeBytes:a.sizeBytes,modifiedAt:a.modifiedAt,startedAt:e.appLog?.startedAt?new Date(e.appLog.startedAt).toISOString():void 0,hint:'Grep the file for token-efficient debugging, e.g. grep -n "Error\\|Exception" <path>'}}}if("doctor"===a){let t=i.resolveAppLogPath(r),a=await tF(e.device,e.appBundleId);return{ok:!0,data:{path:t,active:!!e.appLog,state:e.appLog?.getState()??"inactive",checks:a.checks,notes:a.notes}}}if("mark"===a){let e,a=t.positionals?.slice(1).join(" ")??"",n=i.resolveAppLogPath(r);return tP(n),e=`[agent-device][mark][${new Date().toISOString()}] ${a.trim()||"marker"}
36
+ `,C.appendFileSync(n,e,"utf8"),{ok:!0,data:{path:n,marked:!0}}}if("clear"===a){if(e.appLog&&!n)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear requires logs to be stopped first; run logs stop"}};if(n){if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs clear --restart requires an app session; run open <app> first"}};if(!nY("logs",e.device))return{ok:!1,error:y(new w("UNSUPPORTED_OPERATION","logs is not supported on this device"))}}let t=i.resolveAppLogPath(r);if(n){e.appLog&&await p.stop(e.appLog);let a=tV(t),n=i.resolveAppLogPidPath(r);try{let o=await p.start(e.device,e.appBundleId,t,n),s={...e,appLog:{platform:e.device.platform,backend:o.backend,outPath:t,startedAt:o.startedAt,getState:o.getState,stop:o.stop,wait:o.wait}};return i.set(r,s),{ok:!0,data:{...a,restarted:!0}}}catch(a){let t=y(a);return i.set(r,{...e,appLog:void 0}),{ok:!1,error:t}}}return{ok:!0,data:tV(t)}}if("start"===a){if(e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"app log already streaming; run logs stop first"}};if(!e.appBundleId)return{ok:!1,error:{code:"INVALID_ARGS",message:"logs start requires an app session; run open <app> first"}};if(!nY("logs",e.device))return{ok:!1,error:y(new w("UNSUPPORTED_OPERATION","logs is not supported on this device"))};let t=i.resolveAppLogPath(r),a=i.resolveAppLogPidPath(r);try{let n=await p.start(e.device,e.appBundleId,t,a),o={...e,appLog:{platform:e.device.platform,backend:n.backend,outPath:t,startedAt:n.startedAt,getState:n.getState,stop:n.stop,wait:n.wait}};return i.set(r,o),{ok:!0,data:{path:t,started:!0}}}catch(e){return{ok:!1,error:y(e)}}}if("stop"===a){if(!e.appLog)return{ok:!1,error:{code:"INVALID_ARGS",message:"no app log stream active"}};let t=e.appLog.outPath;return await p.stop(e.appLog),i.set(r,{...e,appLog:void 0}),{ok:!0,data:{path:t,stopped:!0}}}}if("network"===k){let e=i.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"network requires an active session"}};let a=(t.positionals?.[0]??"dump").toLowerCase();if(!sY.includes(a))return{ok:!1,error:{code:"INVALID_ARGS",message:sQ}};let n=t.positionals?.[1],o=n?Number.parseInt(n,10):25;if(!Number.isInteger(o)||o<1||o>200)return{ok:!1,error:{code:"INVALID_ARGS",message:"network dump limit must be an integer in range 1..200"}};let s=(t.positionals?.[2]??"summary").toLowerCase();if(!s0.includes(s))return{ok:!1,error:{code:"INVALID_ARGS",message:s1}};let l=function(e,t){let r=oT(t?.maxEntries,25,1,200),a=t?.include??"summary",i=oT(t?.maxPayloadChars,2048,64,16384),n=oT(t?.maxScanLines,4e3,100,2e4);if(!C.existsSync(e))return{path:e,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}};let o=C.readFileSync(e,"utf8").split("\n"),s=Math.max(0,o.length-n),l=o.slice(s),d=[];for(let e=l.length-1;e>=0&&d.length<r;e-=1){let t=l[e]?.trim();if(!t)continue;let r=function(e,t,r,a){let i=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let a=e.slice(t,r+1);try{let e=JSON.parse(a);return e&&"object"==typeof e?e:null}catch{return null}}(e),n=oM(i,["method","httpMethod"]),o=oM(i,["url","requestUrl"]),s=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(i,["status","statusCode","responseCode"]),l=ok.exec(e),d=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(e),u=(n??d?.[1]??l?.[1])?.toUpperCase(),c=oL.exec(e),p=o??c?.[0];if(!p)return null;let f={method:u,url:p,status:s??function(e){for(let t of oO){let r=t.exec(e);if(!r)continue;let a=Number.parseInt(r[1]??"",10);if(Number.isInteger(a))return a}return null}(e)??void 0,timestamp:function(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);return t?.[0]}(e),raw:oR(e,a),line:t};if("headers"===r||"all"===r){let t=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return oC(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(e,i);t&&(f.headers=oR(t,a))}if("body"===r||"all"===r){let t=ox(e,i,["requestBody","body","payload","request"]),r=ox(e,i,["responseBody","response"]);t&&(f.requestBody=oR(t,a)),r&&(f.responseBody=oR(r,a))}return f}(t,s+e+1,a,i);r&&d.push(r)}return{path:e,exists:!0,scannedLines:l.length,matchedLines:d.length,entries:d,include:a,limits:{maxEntries:r,maxPayloadChars:i,maxScanLines:n}}}(i.resolveAppLogPath(r),{maxEntries:o,include:s,maxPayloadChars:2048,maxScanLines:4e3}),d=e.appLog?.backend??("ios"===e.device.platform?"device"===e.device.kind?"ios-device":"ios-simulator":"android"),u=[];return e.appLog||u.push("Capture uses the session app log file. For fresh traffic, run logs clear --restart before reproducing requests."),0===l.entries.length&&u.push("No HTTP(s) entries were found in recent session app logs."),{ok:!0,data:{...l,active:!!e.appLog,state:e.appLog?.getState()??"inactive",backend:d,notes:u}}}return"batch"===k?await sW(t,r,n):"close"===k?await sG({req:t,sessionName:r,logPath:a,sessionStore:i,dispatch:N,stopIosRunner:D,clearRuntimeHints:I,settleSimulator:E,shutdownSimulator:v??ix,shutdownAndroidEmulator:b,appLogOps:{stop:p.stop}}):null}function s6(e,t,r,a){if(e.ok)return e;let i=r+1,n=function(e){let t;return t=(e.positionals??[]).map(e=>tI(e)),[e.command,...t].join(" ")}(t),o={...e.error.details??{},replayPath:a,step:i,action:t.command,positionals:t.positionals??[]};return{ok:!1,error:{code:e.error.code,message:`Replay failed at step ${i} (${n}): ${e.error.message}`,hint:e.error.hint,diagnosticId:e.error.diagnosticId,logPath:e.error.logPath,details:o}}}function s9(e,t){let r={...t??{}},a=e??{};for(let e of sK)void 0===r[e]&&void 0!==a[e]&&(r[e]=a[e]);return r}async function s7(e){let{action:t,sessionName:r,logPath:a,sessionStore:i,dispatch:n}=e;if(!(tg(t.command)||["fill","get","is","wait"].includes(t.command)))return null;let o=i.get(r);if(!o)return null;let s=tg(t.command)||"fill"===t.command,l=tg(t.command)||"fill"===t.command||"get"===t.command&&t.positionals?.[0]==="text",d=await le(o,t,a,s,n,i);for(let e of function(e){let t=[],r=Array.isArray(e.result?.selectorChain)&&e.result?.selectorChain.every(e=>"string"==typeof e)?e.result.selectorChain:[];if(t.push(...r),tg(e.command)){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&t.push(e.positionals.join(" "))}if("fill"===e.command){let r=e.positionals?.[0]??"";r&&!r.startsWith("@")&&Number.isNaN(Number(r))&&t.push(r)}if("get"===e.command){let r=e.positionals?.[1]??"";r&&!r.startsWith("@")&&t.push(e.positionals.slice(1).join(" "))}if("is"===e.command){let{split:r}=op(e.positionals);r&&t.push(r.selectorExpression)}if("wait"===e.command){let{selectorExpression:r}=o6(e.positionals??[]);r&&t.push(r)}let a="string"==typeof e.result?.refLabel?e.result.refLabel.trim():"";if(a.length>0){let r=JSON.stringify(a);"fill"===e.command?(t.push(`id=${r} editable=true`),t.push(`label=${r} editable=true`),t.push(`text=${r} editable=true`),t.push(`value=${r} editable=true`)):(t.push(`id=${r}`),t.push(`label=${r}`),t.push(`text=${r}`),t.push(`value=${r}`))}return tf(t).filter(e=>e.trim().length>0)}(t)){let r=ou(e);if(!r)continue;let a=oy(d.nodes,r,{platform:o.device.platform,requireRect:s,requireUnique:!0,disambiguateAmbiguous:l});if(!a)continue;let i=oS(a.node,o.device.platform,{action:tg(t.command)?"click":"fill"===t.command?"fill":"get"}).join(" || ");if(tg(t.command))return{...t,positionals:[i]};if("fill"===t.command){let e=tp(t);if(!e)continue;return{...t,positionals:[i,e]}}if("get"===t.command){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)continue;return{...t,positionals:[e,i]}}if("is"===t.command){let{predicate:e,split:r}=op(t.positionals);if(!e)continue;let a=r?.rest.join(" ").trim()??"",n=[e,i];return"text"===e&&a.length>0&&n.push(a),{...t,positionals:n}}if("wait"===t.command){let{selectorTimeout:e}=o6(t.positionals??[]),r=[i];return e&&r.push(e),{...t,positionals:r}}}let u=function(e,t,r){if("get"!==e.command||e.positionals?.[0]!=="text")return null;let a=e.positionals?.[1];if(!a)return null;let i=ou(a);if(!i)return null;let n=new Set,o=!1;for(let e of i.selectors)for(let t of e.terms)"role"===t.key&&"string"==typeof t.value&&n.add(oa(t.value)),("text"===t.key||"label"===t.key||"value"===t.key)&&"string"==typeof t.value&&/^\d+$/.test(t.value.trim())&&(o=!0);if(!o)return null;let s=t.nodes.filter(e=>{let t=on(e).trim();return!!/^\d+$/.test(t)&&(0===n.size||n.has(oa(e.type??"")))});if(0===s.length||1!==tf(s.map(e=>on(e).trim())).length)return null;let l=s[0];if(!l)return null;let d=oS(l,r.device.platform,{action:"get"});return 0===d.length?null:{...e,positionals:["text",d.join(" || ")]}}(t,d,o);return u||null}async function le(e,t,r,a,i,n){let o=await i(e.device,"snapshot",[],t.flags?.out,{...nQ(r,{...t.flags??{},snapshotInteractiveOnly:a,snapshotCompact:a},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[],l={nodes:n8(t.flags?.snapshotRaw?s:or(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend};return e.snapshot=l,n.set(e.name,e),l}function lt(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}function lr(e,t){let r=B(e.type??"Element"),a=H(e,r),i=!1===e.enabled?"disabled":"enabled",n=!0===e.selected?"selected":"unselected",o=!0===e.hittable?"hittable":"not-hittable";return[String(t??e.depth??0),r,a,i,n,o].join("|")}function la(e,t){return t.flatten?e.map(e=>({text:z(e,0,!1),comparable:lr(e,0)})):V(e).map(e=>({text:e.text,comparable:lr(e.node,e.depth)}))}function li(e,t){return e.get(t)??0}async function ln(e){let{req:t,sessionName:r,logPath:a,sessionStore:i}=e,n=e.dispatchSnapshotCommand??nX,o=e.runnerCommand??tu,s=t.command;if("snapshot"===s){let{session:e,device:o}=await ll(i,r,t.flags);if(!nY("snapshot",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"snapshot is not supported on this device"}};let s=ls(t.flags?.snapshotScope,e);return s.ok?await ld(e,o,async()=>{let l=e?.appBundleId,d=await lo({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:s.scope}),u=e?{...e,snapshot:d.snapshot}:{name:r,device:o,createdAt:Date.now(),appBundleId:l,snapshot:d.snapshot,actions:[]};return lu(i,u,t,{nodes:d.snapshot.nodes.length,truncated:d.snapshot.truncated??!1}),i.set(r,u),{ok:!0,data:{nodes:d.snapshot.nodes,truncated:d.snapshot.truncated??!1,appName:u.appBundleId?u.appName??u.appBundleId:void 0,appBundleId:u.appBundleId}}}):s.response}if("diff"===s){if(t.positionals?.[0]!=="snapshot")return{ok:!1,error:{code:"INVALID_ARGS",message:"diff currently supports only: diff snapshot"}};let{session:e,device:o}=await ll(i,r,t.flags);if(!nY("diff",o))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"diff is not supported on this device"}};let s=ls(t.flags?.snapshotScope,e);if(!s.ok)return s.response;let l=t.flags?.snapshotInteractiveOnly===!0;return await ld(e,o,async()=>{let d=e?.appBundleId,u=(await lo({dispatchSnapshotCommand:n,device:o,session:e,req:t,logPath:a,snapshotScope:s.scope})).snapshot;if(!e?.snapshot){let a=function(e,t={}){return la(e,t).length}(u.nodes,{flatten:l}),n=e?{...e,snapshot:u}:{name:r,device:o,createdAt:Date.now(),appBundleId:d,snapshot:u,actions:[]};return lu(i,n,t,{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a}}),i.set(r,n),{ok:!0,data:{mode:"snapshot",baselineInitialized:!0,summary:{additions:0,removals:0,unchanged:a},lines:[]}}}let c=function(e,t,r={}){let a=function(e,t){let r=e.length,a=t.length,i=r+a,n=new Map,o=[];n.set(1,0);for(let s=0;s<=i;s+=1){o.push(new Map(n));for(let i=-s;i<=s;i+=2){let l=i===-s||i!==s&&li(n,i-1)<li(n,i+1)?li(n,i+1):li(n,i-1)+1,d=l-i;for(;l<r&&d<a&&e[l].comparable===t[d].comparable;)l+=1,d+=1;if(n.set(i,l),l>=r&&d>=a)return function(e,t,r,a,i){let n=[],o=a,s=i;for(let a=e.length-1;a>=0;a-=1){let i=e[a],l=o-s,d=l===-a||l!==a&&li(i,l-1)<li(i,l+1)?l+1:l-1,u=li(i,d),c=u-d;for(;o>u&&s>c;)n.push({kind:"unchanged",text:r[s-1].text}),o-=1,s-=1;if(0===a)break;o===u?(n.push({kind:"added",text:r[c].text}),s=c):(n.push({kind:"removed",text:t[u].text}),o=u)}return n.reverse(),n}(o,e,t,r,a)}}return[]}(la(e,r),la(t,r)),i={additions:0,removals:0,unchanged:0};for(let e of a)"added"===e.kind&&(i.additions+=1),"removed"===e.kind&&(i.removals+=1),"unchanged"===e.kind&&(i.unchanged+=1);return{summary:i,lines:a}}(e.snapshot.nodes,u.nodes,{flatten:l}),p={...e,snapshot:u};return lu(i,p,t,{mode:"snapshot",baselineInitialized:!1,summary:c.summary}),i.set(r,p),{ok:!0,data:{mode:"snapshot",baselineInitialized:!1,summary:c.summary,lines:c.lines}}})}if("wait"===s){let{session:e,device:o}=await ll(i,r,t.flags),s=function(e){if(0===e.length)return null;let t=lt(e[0]);if(null!==t)return{kind:"sleep",durationMs:t};if("text"===e[0]){let t=lt(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=lt(e[e.length-1]);return{kind:"ref",rawRef:e[0],timeoutMs:t}}let r=lt(e[e.length-1]),a=oc(null!==r?e.slice(0,-1):e.slice());if(a&&0===a.rest.length){let e=ou(a.selectorExpression);if(e)return{kind:"selector",selector:e,selectorExpression:a.selectorExpression,timeoutMs:r}}return{kind:"text",text:(null!==r?e.slice(0,-1).join(" "):e.join(" ")).trim(),timeoutMs:r}}(t.positionals??[]);return s?"sleep"===s.kind?(await new Promise(e=>setTimeout(e,s.durationMs)),lu(i,e,t,{waitedMs:s.durationMs}),{ok:!0,data:{waitedMs:s.durationMs}}):nY("wait",o)?await ld(e,o,async()=>{let l,d;if("selector"===s.kind){let l=s.timeoutMs??1e4,d=Date.now();for(;Date.now()-d<l;){let l=await n(o,"snapshot",[],t.flags?.out,{...nQ(a,{...t.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},e?.appBundleId,e?.trace?.outPath)}),u=l?.nodes??[],c=n8(t.flags?.snapshotRaw?u:or(u));e&&(e.snapshot={nodes:c,truncated:l?.truncated,createdAt:Date.now(),backend:l?.backend},i.set(r,e));let p=ob(c,s.selector,{platform:o.platform});if(p)return lu(i,e,t,{selector:p.selector.raw,waitedMs:Date.now()-d}),{ok:!0,data:{selector:p.selector.raw,waitedMs:Date.now()-d}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for selector: ${s.selectorExpression}`}}}if("ref"===s.kind){if(!e?.snapshot)return{ok:!1,error:{code:"INVALID_ARGS",message:"Ref wait requires an existing snapshot in session."}};let t=n5(s.rawRef);if(!t)return{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref: ${s.rawRef}`}};let r=n6(e.snapshot.nodes,t),a=r?oe(r,e.snapshot.nodes):void 0;if(!a)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s.rawRef} not found or has no label`}};l=a,d=s.timeoutMs}else l=s.text,d=s.timeoutMs;if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires text"}};let u=d??1e4,c=Date.now();for(;Date.now()-c<u;){if("ios"===o.platform){let r=await tu(o,{command:"findText",text:l,appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:a,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});if(r?.found)return lu(i,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}}}else if("android"===o.platform&&n7(n8((await aM(o,{scope:l})).nodes??[]),l))return lu(i,e,t,{text:l,waitedMs:Date.now()-c}),{ok:!0,data:{text:l,waitedMs:Date.now()-c}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:`wait timed out for text: ${l}`}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"wait is not supported on this device"}}:{ok:!1,error:{code:"INVALID_ARGS",message:"wait requires a duration or text"}}}if("alert"===s){let{session:e,device:n}=await ll(i,r,t.flags),s=(t.positionals?.[0]??"get").toLowerCase();return nY("alert",n)?await ld(e,n,async()=>{if("wait"===s){let r=lt(t.positionals?.[1])??1e4,s=Date.now();for(;Date.now()-s<r;){try{let r=await o(n,{command:"alert",action:"get",appBundleId:e?.appBundleId},{verbose:t.flags?.verbose,logPath:a,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId});return lu(i,e,t,r),{ok:!0,data:r}}catch{}await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"alert wait timed out"}}}let r="accept"===s||"dismiss"===s?s:"get",l={verbose:t.flags?.verbose,logPath:a,traceLogPath:e?.trace?.outPath,requestId:t.meta?.requestId};if("accept"===r||"dismiss"===r){let a,s=Date.now();for(;Date.now()-s<2e3;){try{let a=await o(n,{command:"alert",action:r,appBundleId:e?.appBundleId},l);return lu(i,e,t,a),{ok:!0,data:a}}catch(t){a=t;let e=String(t?.message??"").toLowerCase();if(!e.includes("alert not found")&&!e.includes("no alert"))break}await new Promise(e=>setTimeout(e,300))}throw a}let d=await o(n,{command:"alert",action:r,appBundleId:e?.appBundleId},l);return lu(i,e,t,d),{ok:!0,data:d}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"alert is only supported on iOS simulators"}}}if("settings"===s){let e=t.positionals?.[0]?.toLowerCase(),n=t.positionals?.[1]?.toLowerCase(),o=t.positionals?.[2]?.toLowerCase();if(!e||!n||"permission"===e&&!o)return{ok:!1,error:{code:"INVALID_ARGS",message:q}};let{session:s,device:l}=await ll(i,r,t.flags);return nY("settings",l)?await ld(s,l,async()=>{let r=s?.appBundleId,d="permission"===e?[e,n,o,t.positionals?.[3]??"",r??""]:[e,n,r??""],u=await nX(l,"settings",d,t.flags?.out,{...nQ(a,t.flags,r,s?.trace?.outPath)});return lu(i,s,t,u??{setting:e,state:n}),{ok:!0,data:u??{setting:e,state:n}}}):{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"settings is not supported on this device"}}}return null}async function lo(e){let{dispatchSnapshotCommand:t,device:r,session:a,req:i,logPath:n,snapshotScope:o}=e,s=await t(r,"snapshot",[],i.flags?.out,{...nQ(n,{...i.flags,snapshotScope:o},a?.appBundleId,a?.trace?.outPath)}),l=s?.nodes??[];return{snapshot:{nodes:n8(i.flags?.snapshotRaw?l:or(l)),truncated:s?.truncated,createdAt:Date.now(),backend:s?.backend}}}function ls(e,t){if(!e||!e.trim().startsWith("@"))return{ok:!0,scope:e};if(!t?.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"Ref scope requires an existing snapshot in session."}}};let r=n5(e.trim());if(!r)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:`Invalid ref scope: ${e}`}}};let a=n6(t.snapshot.nodes,r),i=a?oe(a,t.snapshot.nodes):void 0;return i?{ok:!0,scope:i}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${e} not found or has no label`}}}}async function ll(e,t,r){let a=e.get(t),i=a?.device??await nK(r??{});return a||await n1(i),{session:a,device:i}}async function ld(e,t,r){let a=!e&&"ios"===t.platform;try{return await r()}finally{a&&await ta(t.id)}}function lu(e,t,r,a){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:a})}function lc(e,t,r,a={}){let i=lf(r);if(!i)return{matches:[],score:0};let n=0,o=[];for(let r of e){if(a.requireRect&&!r.rect)continue;let e=function(e,t,r){switch(t){case"role":return function(e,t){let r=function(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,r);case"label":return lp(e.label,r);case"value":return lp(e.value,r);case"id":return lp(e.identifier,r);default:return Math.max(lp(e.label,r),lp(e.value,r),lp(e.identifier,r))}}(r,t,i);if(!(e<=0)){if(e>n){n=e,o.length=0,o.push(r);continue}e===n&&o.push(r)}}return{matches:o,score:n}}function lp(e,t){let r=lf(e??"");return r?r===t?2:+!!r.includes(t):0}function lf(e){return e.trim().toLowerCase().replace(/\s+/g," ")}async function lm(e){let{req:t,sessionName:r,logPath:a,sessionStore:i,invoke:n}=e,o=e.dispatch??nX,s=t.command;if("find"!==s)return null;let l=t.positionals??[];if(0===l.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a locator or text"}};let{locator:d,query:u,action:c,value:p,timeoutMs:f}=function(e){let t="any",r=0;["text","label","value","role","id"].includes(e[0])&&(t=e[0],r=1);let a=e[r]??"",i=e.slice(r+1);if(0===i.length)return{locator:t,query:a,action:"click"};let n=i[0].toLowerCase();if("get"===n){let e=i[1]?.toLowerCase();if("text"===e)return{locator:t,query:a,action:"get_text"};if("attrs"===e)return{locator:t,query:a,action:"get_attrs"};throw new w("INVALID_ARGS","find get only supports text or attrs")}if("wait"===n)return{locator:t,query:a,action:"wait",timeoutMs:lt(i[1])??void 0};if("exists"===n)return{locator:t,query:a,action:"exists"};if("click"===n)return{locator:t,query:a,action:"click"};if("focus"===n)return{locator:t,query:a,action:"focus"};if("fill"===n)return{locator:t,query:a,action:"fill",value:i.slice(1).join(" ")};if("type"===n)return{locator:t,query:a,action:"type",value:i.slice(1).join(" ")};throw new w("INVALID_ARGS",`Unsupported find action: ${i[0]}`)}(l);if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:"find requires a value"}};let m=i.get(r);if(!m&&"exists"!==c&&"wait"!==c&&"get_text"!==c&&"get_attrs"!==c)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let h=m?.device??await nK(t.flags??{});m||await n1(h);let g=m?.appBundleId,I="role"!==d?u:void 0,A="click"===c||"focus"===c||"fill"===c||"type"===c,v=0,y=null,b=async()=>{let e=Date.now();if(y&&e-v<750)return{nodes:y};let n=await o(h,"snapshot",[],t.flags?.out,{...nQ(a,{...t.flags,snapshotScope:I,snapshotInteractiveOnly:A,snapshotCompact:A},g,m?.trace?.outPath)}),s=n?.nodes??[],l=n8(t.flags?.snapshotRaw?s:or(s));return v=e,y=l,m&&(m.snapshot={nodes:l,truncated:n?.truncated,createdAt:Date.now(),backend:n?.backend},i.set(r,m)),{nodes:l,truncated:n?.truncated,backend:n?.backend}};if("wait"===c){let e=f??1e4,r=Date.now();for(;Date.now()-r<e;){let{nodes:e}=await b();if(lc(e,d,u,{requireRect:!1}).matches[0])return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0,waitedMs:Date.now()-r}}),{ok:!0,data:{found:!0,waitedMs:Date.now()-r}};await new Promise(e=>setTimeout(e,300))}return{ok:!1,error:{code:"COMMAND_FAILED",message:"find wait timed out"}}}let{nodes:N}=await b(),_=lc(N,d,u,{requireRect:A});if(A&&_.matches.length>1){let e=_.matches.slice(0,8).map(e=>{let t=on(e)||e.label||e.identifier||e.type||"";return`@${e.ref}${t?`(${t})`:""}`});return{ok:!1,error:{code:"AMBIGUOUS_MATCH",message:`find matched ${_.matches.length} elements for ${d} "${u}". Use a more specific locator or selector.`,details:{locator:d,query:u,matches:_.matches.length,candidates:e}}}}let S=_.matches[0]??null;if(!S)return{ok:!1,error:{code:"COMMAND_FAILED",message:"find did not match any element"}};let D="click"===c||"focus"===c||"fill"===c||"type"===c?function(e,t){if(t.hittable)return t;let r=t,a=new Set;for(;void 0!==r.parentIndex&&!a.has(r.ref);){a.add(r.ref);let t=e[r.parentIndex];if(!t)break;if(t.hittable)return t;r=t}return null}(N,S)??S:S,E=`@${D.ref}`,k={...t.flags??{},noRecord:!0};if("exists"===c)return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{found:!0}}),{ok:!0,data:{found:!0}};if("get_text"===c){let e=on(S);return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"get text",text:e}}),{ok:!0,data:{ref:E,text:e,node:S}}}if("get_attrs"===c)return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"get attrs"}}),{ok:!0,data:{ref:E,node:S}};if("click"===c){let e=await n({token:t.token,session:r,command:"click",positionals:[E],flags:k});if(!e.ok)return e;let a=D.rect?n9(D.rect):null,o={ref:E,locator:d,query:u};return a&&(o.x=a.x,o.y=a.y),m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"click",locator:d,query:u}}),{ok:!0,data:o}}if("fill"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find fill requires text"}};let e=await n({token:t.token,session:r,command:"fill",positionals:[E,p],flags:k});return e.ok&&m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"fill"}}),e}if("focus"===c){let e=S.rect?n9(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};let r=await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...nQ(a,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"focus"}}),{ok:!0,data:r??{ref:E}}}if("type"===c){if(!p)return{ok:!1,error:{code:"INVALID_ARGS",message:"find type requires text"}};let e=S.rect?n9(S.rect):null;if(!e)return{ok:!1,error:{code:"COMMAND_FAILED",message:"matched element has no bounds"}};await o(h,"focus",[String(e.x),String(e.y)],t.flags?.out,{...nQ(a,t.flags,m?.appBundleId,m?.trace?.outPath)});let r=await o(h,"type",[p],t.flags?.out,{...nQ(a,t.flags,m?.appBundleId,m?.trace?.outPath)});return m&&i.recordAction(m,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{ref:E,action:"type"}}),{ok:!0,data:r??{ref:E}}}return null}function lh(e){return e instanceof Error?e.message:String(e)}function lw(e){let t=e.appBundleId?.trim();return t&&t.length>0?t:void 0}function lg(e,t,r){return{verbose:e.flags?.verbose,logPath:t,traceLogPath:r.trace?.outPath}}async function lI(e){let{req:t,sessionName:r,sessionStore:a,logPath:n}=e,o=e.deps??{runCmd:c,runCmdBackground:d,runIosRunnerCommand:tu},s=t.command;if("record"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"record requires start|stop"}};let d=a.get(r),c=d?.device??await nK(t.flags??{});d||await n1(c);let p=d??{name:r,device:c,createdAt:Date.now(),actions:[]};if("start"===e){if(p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"recording already in progress"}};let e=t.flags?.fps;if(void 0!==e&&(!Number.isInteger(e)||e<1||e>120))return{ok:!1,error:{code:"INVALID_ARGS",message:"fps must be an integer between 1 and 120"}};let d=t.positionals?.[1]??`./recording-${Date.now()}.mp4`;if(!nY("record",c))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"record is not supported on this device"}};let f="ios"===c.platform&&"device"===c.kind?lw(p):void 0;if("ios"===c.platform&&"device"===c.kind&&!f)return{ok:!1,error:{code:"INVALID_ARGS",message:"record on physical iOS devices requires an active app session; run open <app> first"}};let m=t_.expandHome(d,t.meta?.cwd),h=t.meta?.clientArtifactPaths?.outPath;C.mkdirSync(i.dirname(m),{recursive:!0});let w=lg(t,n,p);if("ios"===c.platform&&"device"===c.kind){let t=`agent-device-recording-${Date.now()}.mp4`,r=`tmp/${t}`,i=async()=>{await o.runIosRunnerCommand(c,{command:"recordStart",outPath:t,fps:e,appBundleId:f},w)};try{await i()}catch(e){if(!lh(e).toLowerCase().includes("recording already in progress"))return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${lh(e)}`}};{var l,u;k({level:"warn",phase:"record_start_runner_desynced",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:lh(e)}});let t=(l=c.id,u=p.name,a.toArray().find(e=>e.name!==u&&"ios"===e.device.platform&&"device"===e.device.kind&&e.device.id===l&&e.recording?.platform==="ios-device-runner"));if(t)return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: recording already in progress in session '${t.name}'`}};try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:f},w)}catch{}try{await i()}catch(e){return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to start recording: ${lh(e)}`}}}}}p.recording={platform:"ios-device-runner",outPath:m,clientOutPath:h,remotePath:r}}else if("ios"===c.platform){let{child:e,wait:t}=o.runCmdBackground("xcrun",eO(c,["io",c.id,"recordVideo",m]),{allowFailure:!0});p.recording={platform:"ios",outPath:m,clientOutPath:h,child:e,wait:t}}else{let e=`/sdcard/agent-device-recording-${Date.now()}.mp4`,{child:t,wait:r}=o.runCmdBackground("adb",["-s",c.id,"shell","screenrecord",e],{allowFailure:!0});p.recording={platform:"android",outPath:m,clientOutPath:h,remotePath:e,child:t,wait:r}}return a.set(r,p),a.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start"}}),{ok:!0,data:{recording:"started",outPath:h??d}}}if(!p.recording)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active recording"}};let f=p.recording;if("ios-device-runner"===f.platform){let e=lw(p);try{await o.runIosRunnerCommand(c,{command:"recordStop",appBundleId:e},lg(t,n,p))}catch(e){k({level:"warn",phase:"record_stop_runner_failed",data:{platform:c.platform,kind:c.kind,deviceId:c.id,session:p.name,error:lh(e)}})}let r={stdout:"",stderr:"",exitCode:1};for(let e of e2)if(0===(r=await o.runCmd("xcrun",["devicectl","device","copy","from","--device",c.id,"--source",f.remotePath,"--destination",f.outPath,"--domain-type","appDataContainer","--domain-identifier",e],{allowFailure:!0})).exitCode)break;if(p.recording=void 0,0!==r.exitCode){let e=r.stderr.trim()||r.stdout.trim()||`devicectl exited with code ${r.exitCode}`;return{ok:!1,error:{code:"COMMAND_FAILED",message:`failed to copy recording from device: ${e}`}}}}else{f.child.kill("SIGINT");try{await f.wait}catch{}if("android"===f.platform&&f.remotePath)try{await o.runCmd("adb",["-s",c.id,"pull",f.remotePath,f.outPath],{allowFailure:!0}),await o.runCmd("adb",["-s",c.id,"shell","rm","-f",f.remotePath],{allowFailure:!0})}catch{}p.recording=void 0}a.recordAction(p,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:f.outPath}});let m=[{field:"outPath",path:f.outPath,localPath:f.clientOutPath,fileName:i.basename(f.clientOutPath??f.outPath)}];return{ok:!0,data:{recording:"stopped",outPath:f.outPath,artifacts:m}}}if("trace"===s){let e=(t.positionals?.[0]??"").toLowerCase();if(!["start","stop"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"trace requires start|stop"}};let n=a.get(r);if(!n)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session"}};if("start"===e){if(n.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"trace already in progress"}};let e=t.positionals?.[1]??a.defaultTracePath(n),r=t_.expandHome(e);return C.mkdirSync(i.dirname(r),{recursive:!0}),C.appendFileSync(r,""),n.trace={outPath:r,startedAt:Date.now()},a.recordAction(n,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"start",outPath:r}}),{ok:!0,data:{trace:"started",outPath:r}}}if(!n.trace)return{ok:!1,error:{code:"INVALID_ARGS",message:"no active trace"}};let o=n.trace.outPath;if(t.positionals?.[1]){let e=t_.expandHome(t.positionals[1]);C.mkdirSync(i.dirname(e),{recursive:!0}),C.existsSync(o)?C.renameSync(o,e):C.appendFileSync(e,""),o=e}return n.trace=void 0,a.recordAction(n,{command:s,positionals:t.positionals??[],flags:t.flags??{},result:{action:"stop",outPath:o}}),{ok:!0,data:{trace:"stopped",outPath:o}}}return null}function lA(e,t,r){return t>=e.x&&t<=e.x+e.width&&r>=e.y&&r<=e.y+e.height}function lv(e){let t=null,r=-1;for(let a of e){let e=a.width*a.height;e>r&&(t=a,r=e)}return t}function ly(e,t,r){return Math.min(r,Math.max(t,Math.round(e)))}async function lb(e){let{req:t,sessionName:r,sessionStore:a,contextFromFlags:i}=e,n=e.dispatch??nX,o=t.command;if("press"===o){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nY("press",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"press is not supported on this device"}};let s=function(e){if(e.length<2)return null;let t=Number(e[0]),r=Number(e[1]);return Number.isFinite(t)&&Number.isFinite(r)?{x:t,y:r}:null}(t.positionals??[]);if(s){let r=await n(e.device,"press",[String(s.x),String(s.y)],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath)});return a.recordAction(e,{command:o,positionals:t.positionals??[String(s.x),String(s.y)],flags:t.flags??{},result:r??{x:s.x,y:s.y}}),{ok:!0,data:r??{x:s.x,y:s.y}}}let l="click",d=t.positionals?.[0]??"";if(d.startsWith("@")){let r=lS("press",t.flags);if(r)return r;let s=t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",u=lD({session:e,refInput:d,fallbackLabel:s,requireRect:!0,invalidRefMessage:`${o} requires a ref like @e2`,notFoundMessage:`Ref ${d} not found or has no bounds`});if(!u.ok)return u.response;let{ref:c}=u.target,p=u.target.node,f=u.target.snapshotNodes,m=lE(p.rect);if(!m){let r=await lN(e,t.flags,a,i,{interactiveOnly:!0},n),o=n6(r.nodes,c),l=s.length>0?n7(r.nodes,s):null,d=lE(l?.rect),u=lE(o?.rect)?o:d?l:o??l,h=lE(u?.rect);u&&h&&(p=u,f=r.nodes,m=h)}if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${d} not found or has invalid bounds`}};let h=oe(p,f),w=oS(p,e.device.platform,{action:l}),{x:g,y:I}=m,A=await n(e.device,"press",[String(g),String(I)],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath)});return a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:c,x:g,y:I,refLabel:h,selectorChain:w}}),{ok:!0,data:{...A??{},ref:c,x:g,y:I}}}let u=(t.positionals??[]).join(" ").trim();if(!u)return{ok:!1,error:{code:"INVALID_ARGS",message:`${o} requires @ref, selector expression, or x y coordinates`}};let c=od(u),p=await lN(e,t.flags,a,i,{interactiveOnly:!0},n),f=await E("selector_resolve",()=>oy(p.nodes,c,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!f||!f.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:oN(c,f?.diagnostics??[],{unique:!0})}};let m=lE(f.node.rect);if(!m)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Selector ${f.selector.raw} resolved to invalid bounds`}};let{x:h,y:w}=m,g=await n(e.device,"press",[String(h),String(w)],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath)}),I=oS(f.node,e.device.platform,{action:l}),A=oe(f.node,p.nodes);return a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{x:h,y:w,selector:f.selector.raw,selectorChain:I,refLabel:A}}),{ok:!0,data:{...g??{},selector:f.selector.raw,x:h,y:w}}}if("fill"===o){let e=a.get(r);if(e&&!nY("fill",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"fill is not supported on this device"}};if(t.positionals?.[0]?.startsWith("@")){if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let r=lS("fill",t.flags);if(r)return r;let s=t.positionals.length>=3?t.positionals[1]:"",l=t.positionals.length>=3?t.positionals.slice(2).join(" "):t.positionals.slice(1).join(" ");if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after ref"}};let d=lD({session:e,refInput:t.positionals[0],fallbackLabel:s,requireRect:!0,invalidRefMessage:"fill requires a ref like @e2",notFoundMessage:`Ref ${t.positionals[0]} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${t.positionals[0]} not found or has no bounds`}};let f=c.type??"",m=f&&!oi(f,e.device.platform)?`fill target ${t.positionals[0]} resolved to "${f}", attempting fill anyway.`:void 0,h=oe(c,p),w=oS(c,e.device.platform,{action:"fill"}),{x:g,y:I}=n9(c.rect),A={...await n(e.device,"fill",[String(g),String(I),l],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath)})??{ref:u,x:g,y:I}};return m&&(A.warning=m),a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...A,refLabel:h,selectorChain:w}}),{ok:!0,data:A}}if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};let s=oc(t.positionals??[],{preferTrailingValue:!0});if(s){if(0===s.rest.length)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let r=s.rest.join(" ").trim();if(!r)return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires text after selector"}};let l=od(s.selectorExpression),d=await lN(e,t.flags,a,i,{interactiveOnly:!0},n),u=await E("selector_resolve",()=>oy(d.nodes,l,{platform:e.device.platform,requireRect:!0,requireUnique:!0,disambiguateAmbiguous:!0}),{command:o});if(!u||!u.node.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:oN(l,u?.diagnostics??[],{unique:!0})}};let c=u.node,p=c.type??"",f=p&&!oi(p,e.device.platform)?`fill target ${u.selector.raw} resolved to "${p}", attempting fill anyway.`:void 0,{x:m,y:h}=n9(u.node.rect),w=await n(e.device,"fill",[String(m),String(h),r],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath)}),g=oS(c,e.device.platform,{action:"fill"}),I={...w??{x:m,y:h,text:r},selector:u.selector.raw,selectorChain:g,refLabel:oe(c,d.nodes)};return f&&(I.warning=f),a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:I}),{ok:!0,data:I}}return{ok:!1,error:{code:"INVALID_ARGS",message:"fill requires x y text, @ref text, or selector text"}}}if("get"===o){let e=t.positionals?.[0];if("text"!==e&&"attrs"!==e)return{ok:!1,error:{code:"INVALID_ARGS",message:"get only supports text or attrs"}};let s=a.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nY("get",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"get is not supported on this device"}};let l=t.positionals?.[1]??"";if(l.startsWith("@")){let r=lS("get",t.flags);if(r)return r;let i=lD({session:s,refInput:l,fallbackLabel:t.positionals.length>2?t.positionals.slice(2).join(" ").trim():"",requireRect:!1,invalidRefMessage:"get text requires a ref like @e2",notFoundMessage:`Ref ${l} not found`});if(!i.ok)return i.response;let{ref:n,node:d}=i.target,u=oS(d,s.device.platform,{action:"get"});if("attrs"===e)return a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:n,selectorChain:u}}),{ok:!0,data:{ref:n,node:d}};let c=on(d);return a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:n,text:c,refLabel:c||void 0,selectorChain:u}}),{ok:!0,data:{ref:n,text:c,node:d}}}let d=t.positionals.slice(1).join(" ").trim();if(!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"get requires @ref or selector expression"}};let u=od(d),c=await lN(s,t.flags,a,i,{interactiveOnly:!1},n),p=await E("selector_resolve",()=>oy(c.nodes,u,{platform:s.device.platform,requireRect:!1,requireUnique:!0,disambiguateAmbiguous:"text"===e}),{command:o});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:oN(u,[],{unique:!0})}};let f=p.node,m=oS(f,s.device.platform,{action:"get"});if("attrs"===e)return a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,node:f}};let h=on(f);return a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{text:h,refLabel:h||void 0,selector:p.selector.raw,selectorChain:m}}),{ok:!0,data:{selector:p.selector.raw,text:h,node:f}}}if("is"===o){let e=(t.positionals?.[0]??"").toLowerCase();if(!["visible","hidden","exists","editable","selected","text"].includes(e))return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires predicate: visible|hidden|exists|editable|selected|text"}};let s=a.get(r);if(!s)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nY("is",s.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"is is not supported on this device"}};let{split:l}=op(t.positionals);if(!l)return{ok:!1,error:{code:"INVALID_ARGS",message:"is requires a selector expression"}};let d=l.rest.join(" ").trim();if("text"===e&&!d)return{ok:!1,error:{code:"INVALID_ARGS",message:"is text requires expected text value"}};if("text"!==e&&l.rest.length>0)return{ok:!1,error:{code:"INVALID_ARGS",message:`is ${e} does not accept trailing values`}};let u=od(l.selectorExpression),c=await lN(s,t.flags,a,i,{interactiveOnly:!1},n);if("exists"===e){let r=ob(c.nodes,u,{platform:s.device.platform});return r?(a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:r.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,matches:r.matches}}),{ok:!0,data:{predicate:e,pass:!0,selector:r.selector.raw,matches:r.matches}}):{ok:!1,error:{code:"COMMAND_FAILED",message:oN(u,[],{unique:!1})}}}let p=await E("selector_resolve",()=>oy(c.nodes,u,{platform:s.device.platform,requireUnique:!0}),{command:"is",predicate:e});if(!p)return{ok:!1,error:{code:"COMMAND_FAILED",message:oN(u,[],{unique:!0})}};let f=function(e){let{predicate:t,node:r,expectedText:a,platform:i}=e,n=on(r),o=!1;switch(t){case"visible":o=og(r);break;case"hidden":o=!og(r);break;case"editable":o=oI(r,i);break;case"selected":o=!0===r.selected;break;case"text":o=n===(a??"")}let s="text"===t?`expected="${a??""}" actual="${n}"`:`actual=${JSON.stringify({visible:og(r),editable:oI(r,i),selected:!0===r.selected})}`;return{pass:o,actualText:n,details:s}}({predicate:e,node:p.node,expectedText:d,platform:s.device.platform});return f.pass?(a.recordAction(s,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{predicate:e,selector:p.selector.raw,selectorChain:u.selectors.map(e=>e.raw),pass:!0,text:"text"===e?f.actualText:void 0}}),{ok:!0,data:{predicate:e,pass:!0,selector:p.selector.raw}}):{ok:!1,error:{code:"COMMAND_FAILED",message:`is ${e} failed for selector ${p.selector.raw}: ${f.details}`}}}if("scrollintoview"===o){let e=a.get(r);if(!e)return{ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}};if(!nY("scrollintoview",e.device))return{ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:"scrollintoview is not supported on this device"}};let s=t.positionals?.[0]??"";if(!s.startsWith("@"))return null;let l=lS("scrollintoview",t.flags);if(l)return l;let d=lD({session:e,refInput:s,fallbackLabel:t.positionals&&t.positionals.length>1?t.positionals.slice(1).join(" ").trim():"",requireRect:!0,invalidRefMessage:"scrollintoview requires a ref like @e2",notFoundMessage:`Ref ${s} not found or has no bounds`});if(!d.ok)return d.response;let{ref:u,node:c,snapshotNodes:p}=d.target;if(!c.rect)return{ok:!1,error:{code:"COMMAND_FAILED",message:`Ref ${s} not found or has no bounds`}};let f=function(e,t){let r=n9(t),a=e.filter(e=>{var t;return!!(t=e.rect)&&Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height)}),i=a.filter(e=>{let t=(e.type??"").toLowerCase();return t.includes("application")||t.includes("window")}),n=lv(i.map(e=>e.rect).filter(e=>lA(e,r.x,r.y)));if(n)return n;let o=lv(i.map(e=>e.rect));if(o)return o;let s=lv(a.map(e=>e.rect).filter(e=>lA(e,r.x,r.y)));return s||null}(p,c.rect);if(!f)return{ok:!1,error:{code:"COMMAND_FAILED",message:`scrollintoview could not infer viewport for ${s}`}};let m=function(e,t){var r,a;let i=Math.max(1,t.height),n=Math.max(1,t.width),o=t.y,s=t.y+i,l=t.x,d=t.x+n,u=o+.25*i,c=s-.25*i,p=Math.max(8,.1*n),f=e.y+e.height/2,m=e.x+e.width/2;if(f>=u&&f<=c)return null;let h=Math.round((r=m,a=l+p,Math.min(d-p,Math.max(a,r)))),w=Math.round(o+.86*i),g=Math.round(o+.14*i),I=Math.max(1,Math.abs(w-g));return f>c?{x:h,startY:w,endY:g,count:ly(Math.ceil((f-c)/I),1,50),direction:"down"}:{x:h,startY:g,endY:w,count:ly(Math.ceil((u-f)/I),1,50),direction:"up"}}(c.rect,f),h=oe(c,p),w=oS(c,e.device.platform,{action:"get"});if(!m)return a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{ref:u,attempts:0,alreadyVisible:!0,refLabel:h,selectorChain:w}}),{ok:!0,data:{ref:u,attempts:0,alreadyVisible:!0}};let g=await n(e.device,"swipe",[String(m.x),String(m.startY),String(m.x),String(m.endY),"16"],t.flags?.out,{...i(t.flags,e.appBundleId,e.trace?.outPath),count:m.count,pauseMs:0,pattern:"one-way"});return a.recordAction(e,{command:o,positionals:t.positionals??[],flags:t.flags??{},result:{...g??{},ref:u,attempts:m.count,direction:m.direction,refLabel:h,selectorChain:w}}),{ok:!0,data:{...g??{},ref:u,attempts:m.count,direction:m.direction}}}return null}async function lN(e,t,r,a,i,n=nX){let o=await n(e.device,"snapshot",[],t?.out,{...a({...t??{},snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.interactiveOnly},e.appBundleId,e.trace?.outPath)}),s=o?.nodes??[];return e.snapshot={nodes:n8(t?.snapshotRaw?s:or(s)),truncated:o?.truncated,createdAt:Date.now(),backend:o?.backend},r.set(e.name,e),e.snapshot}let l_=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function lS(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,a]of l_)void 0!==e[r]&&t.push(a);return t}(t);return 0===r.length?null:{ok:!1,error:{code:"INVALID_ARGS",message:`${e} @ref does not support ${r.join(", ")}.`}}}function lD(e){let{session:t,refInput:r,fallbackLabel:a,requireRect:i,invalidRefMessage:n,notFoundMessage:o}=e;if(!t.snapshot)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:"No snapshot in session. Run snapshot first."}}};let s=n5(r);if(!s)return{ok:!1,response:{ok:!1,error:{code:"INVALID_ARGS",message:n}}};let l=n6(t.snapshot.nodes,s);return((!l||i&&!l.rect)&&a.length>0&&(l=n7(t.snapshot.nodes,a)),l&&(!i||l.rect))?{ok:!0,target:{ref:s,node:l,snapshotNodes:t.snapshot.nodes}}:{ok:!1,response:{ok:!1,error:{code:"COMMAND_FAILED",message:o}}}}function lE(e){let t=function(e){if(!e)return null;let t=Number(e.x),r=Number(e.y),a=Number(e.width),i=Number(e.height);return Number.isFinite(t)&&Number.isFinite(r)&&Number.isFinite(a)&&Number.isFinite(i)&&!(a<0)&&!(i<0)?{x:t,y:r,width:a,height:i}:null}(e);if(!t)return null;let r=n9(t);return Number.isFinite(r.x)&&Number.isFinite(r.y)?r:null}function lk(e){return{tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,leaseTtlMs:e.meta?.leaseTtlMs,leaseBackend:e.meta?.leaseBackend}}async function lL(e){let{req:t,leaseRegistry:r}=e,a=lk(t);switch(t.command){case"lease_allocate":return{ok:!0,data:{lease:r.allocateLease({tenantId:a.tenantId??"",runId:a.runId??"",backend:a.leaseBackend,ttlMs:a.leaseTtlMs})}};case"lease_heartbeat":return{ok:!0,data:{lease:r.heartbeatLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId,ttlMs:a.leaseTtlMs})}};case"lease_release":return{ok:!0,data:r.releaseLease({leaseId:a.leaseId??"",tenantId:a.tenantId,runId:a.runId})};default:return null}}function lO(e,t){if(!t)return[];let r=[],a=e.device,i=eJ(t.platform);if(i&&i!==a.platform&&r.push({key:"platform",value:t.platform}),t.target&&t.target!==(a.target??"mobile")&&r.push({key:"target",value:t.target}),t.udid&&("ios"!==a.platform||t.udid!==a.id)&&r.push({key:"udid",value:t.udid}),t.serial&&("android"!==a.platform||t.serial!==a.id)&&r.push({key:"serial",value:t.serial}),t.device&&t.device.trim().toLowerCase()!==a.name.trim().toLowerCase()&&r.push({key:"device",value:t.device}),t.iosSimulatorDeviceSet){let e=t.iosSimulatorDeviceSet.trim(),i=a.simulatorSetPath?.trim();("ios"!==a.platform||"simulator"!==a.kind||e!==i)&&r.push({key:"iosSimulatorDeviceSet",value:t.iosSimulatorDeviceSet})}if(t.androidDeviceAllowlist){let e=eE(t.androidDeviceAllowlist);"android"===a.platform&&e.has(a.id)||r.push({key:"androidDeviceAllowlist",value:t.androidDeviceAllowlist})}return r}function lM(e){return`${function(e){switch(e){case"iosSimulatorDeviceSet":return"--ios-simulator-device-set";case"androidDeviceAllowlist":return"--android-device-allowlist";default:return`--${e}`}}(e.key)}=${e.value}`}let lx=["target","device","udid","serial","iosSimulatorDeviceSet","androidDeviceAllowlist"],lC=new Set(["session_list","devices","ensure-simulator","release_materialized_paths"]),lR=new Set(["session_list","devices","ensure-simulator","release_materialized_paths","lease_allocate","lease_heartbeat","lease_release"]);function lT(e,t,r,a){let i=S().requestId;return{...nQ(e,t,r,a,i),requestId:i}}function lP(e){C.existsSync(e)&&C.unlinkSync(e)}function l$(e){if(!C.existsSync(e))return null;try{let t=JSON.parse(C.readFileSync(e,"utf8"));if(!Number.isInteger(t.pid)||t.pid<=0)return null;return t}catch{return null}}function lU(e){let t=l$(e);if(!t||t.pid===process.pid)try{C.existsSync(e)&&C.unlinkSync(e)}catch{}}function lF(e){if(void 0===e)return;let t=Number(e);if(Number.isInteger(t))return t}let{baseDir:lV,infoPath:lG,lockPath:lB,logPath:lj,sessionsDir:lq}=U(process.env.AGENT_DEVICE_STATE_DIR),lH=$(process.env.AGENT_DEVICE_DAEMON_SERVER_MODE);var lW=lq;if(C.existsSync(lW))for(let e of C.readdirSync(lW,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=i.join(lW,e.name,"app-log.pid");if(C.existsSync(t))try{let e=function(e){let t=e.trim();if(!t)return null;if(/^\d+$/.test(t))return{pid:Number.parseInt(t,10)};try{let e=JSON.parse(t);if(!Number.isInteger(e.pid)||e.pid<=0)return null;return e}catch{return null}}(C.readFileSync(t,"utf8"));if(e&&function(e){let t,r=M(e.pid);if(!r||e.startTime&&r!==e.startTime)return!1;let a=n(e.pid);return!!a&&!!((t=a.toLowerCase().replaceAll("\\","/")).includes("log stream")||t.includes("logcat")||t.includes("devicectl device log stream"))&&(!e.command||a===e.command)}(e))try{process.kill(e.pid,"SIGTERM")}catch{}}catch{}finally{tD(t)}}let lz=new t_(lq),lJ=new rs({maxActiveSimulatorLeases:lF(process.env.AGENT_DEVICE_MAX_SIMULATOR_LEASES),defaultLeaseTtlMs:lF(process.env.AGENT_DEVICE_LEASE_TTL_MS),minLeaseTtlMs:lF(process.env.AGENT_DEVICE_LEASE_MIN_TTL_MS),maxLeaseTtlMs:lF(process.env.AGENT_DEVICE_LEASE_MAX_TTL_MS)}),lK=_(),lX=u.randomBytes(24).toString("hex"),lZ=M(process.pid)??void 0,lY=function(){let e=process.argv[1];if(!e)return"unknown";try{let t=C.statSync(e),r=D(),a=i.relative(r,e)||e;return`${a}:${t.size}:${Math.trunc(t.mtimeMs)}`}catch{return"unknown"}}(),lQ=function(e){let{logPath:t,token:r,sessionStore:a,leaseRegistry:n,trackDownloadableArtifact:s}=e,l=e.dispatchCommand??nX;async function d(e){let u="click"===e.command?{...e,command:"press"}:e,c=!!(u.meta?.debug||u.flags?.verbose);return await x({session:u.session,requestId:u.meta?.requestId,command:u.command,debug:c,logPath:t},async()=>{if(u.token!==r)return{ok:!1,error:y(new w("UNAUTHORIZED","Invalid token"))};try{let e=function(e){let t=b(e.meta?.sessionIsolation??e.flags?.sessionIsolation),r=e.meta?.tenantId??e.flags?.tenant,a=o(r);if(r&&!a)throw new w("INVALID_ARGS","Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.");if("tenant"!==t)return e;if(!a)throw new w("INVALID_ARGS","session isolation mode tenant requires --tenant (or meta.tenantId).");return{...e,session:`${a}:${e.session||"default"}`,meta:{...e.meta,tenantId:a,sessionIsolation:t}}}(u);k({level:"info",phase:"request_start",data:{session:e.session,command:e.command,tenant:e.meta?.tenantId,isolation:e.meta?.sessionIsolation}});let r=e.command,c=lk(e);lR.has(r)||e.meta?.sessionIsolation!=="tenant"||n.assertLeaseAdmission({tenantId:c.tenantId,runId:c.runId,leaseId:c.leaseId,backend:c.leaseBackend});let p=function(e,t){var r;let a,i=e.session||"default";if(r=e,a=r.flags?.session,"string"==typeof a&&a.trim().length>0||"default"!==i||t.has(i))return i;let n=t.toArray();return 1===n.length?n[0].name:i}(e,a),f=a.get(p),m=function(e,t){let r=e.meta?.lockPolicy;if(!r)return e;let a={...e.flags??{}},i=t?lO(t,a):function(e,t){let r=[],a=eJ(t);for(let t of(void 0!==e.platform&&a&&eJ(e.platform)!==a&&r.push({key:"platform",value:e.platform}),lx)){let a=e[t];"string"==typeof a&&a.trim().length>0&&r.push({key:t,value:a})}return r}(a,e.meta?.lockPlatform);if(0===i.length)return!t&&e.meta?.lockPlatform&&void 0===a.platform&&(a.platform=e.meta.lockPlatform),{...e,flags:a};if("strip"===r)return t?(function(e,t){for(let r of t)delete e[r.key]}(a,i),a.platform=t.device.platform):function(e,t){for(let t of lx)delete e[t];t&&(e.platform=t)}(a,e.meta?.lockPlatform),{...e,flags:a};throw new w("INVALID_ARGS",`${e.command} cannot override session lock policy with ${i.map(lM).join(", ")}. Unset those selectors or remove the request lock policy.`)}(e,f),h=e=>(function(e,t,r){let a=S();if(!t.ok){k({level:"error",phase:"request_failed",data:{code:t.error.code,message:t.error.message}});let e=R({force:!0})??void 0;return{ok:!1,error:y(new w(t.error.code,t.error.message,{...t.error.details??{},hint:t.error.hint,diagnosticId:t.error.diagnosticId,logPath:t.error.logPath}),{diagnosticId:a.diagnosticId,logPath:e})}}return k({level:"info",phase:"request_success"}),R(),{ok:!0,data:function(e,t,r){var a,n;let o;if(!t)return t;let s=(a=e,n=t,o=Array.isArray(n.artifacts)?[...n.artifacts]:[],"screenshot"!==a.command||o.some(e=>e?.field==="path")||"string"!=typeof n.path||o.push({field:"path",path:n.path,localPath:a.meta?.clientArtifactPaths?.path,fileName:i.basename(a.meta?.clientArtifactPaths?.path??n.path)}),o.filter(e=>!!(e&&"string"==typeof e.field&&"string"==typeof e.path&&"string"==typeof e.localPath&&e.localPath.length>0)));return 0===s.length?t:{...t,artifacts:s.map(t=>{let a=t.path;return{field:t.field,artifactId:r({artifactPath:a,tenantId:e.meta?.tenantId,fileName:t.fileName}),fileName:t.fileName,localPath:t.localPath}})}}(e,t.data,r)}})(m,e,s);!f||m.meta?.lockPolicy||lC.has(r)||function(e,t){let r=lO(e,t);if(0!==r.length){var a;let t,i,n;throw new w("INVALID_ARGS",`Session "${e.name}" is bound to ${(t=(a=e).device.platform,i=a.device.name.trim(),n=a.device.id,`${t} device "${i}" (${n})`)} and cannot be used with ${r.map(lM).join(", ")}. Use a different --session name or close this session first.`)}}(f,m.flags);let g=await lL({req:m,leaseRegistry:n});if(g)return h(g);let I=await s5({req:m,sessionName:p,logPath:t,sessionStore:a,invoke:d});if(I)return h(I);let A=await ln({req:m,sessionName:p,logPath:t,sessionStore:a});if(A)return h(A);let v=await lI({req:m,sessionName:p,sessionStore:a,logPath:t});if(v)return h(v);let N=await lm({req:m,sessionName:p,logPath:t,sessionStore:a,invoke:d});if(N)return h(N);let _=await lb({req:m,sessionName:p,sessionStore:a,contextFromFlags:(e,r,a)=>lT(t,e,r,a)});if(_)return h(_);let D=a.get(p);if(!D)return h({ok:!1,error:{code:"SESSION_NOT_FOUND",message:"No active session. Run open first."}});if(!nY(r,D.device))return h({ok:!1,error:{code:"UNSUPPORTED_OPERATION",message:`${r} is not supported on this device`}});let E=m.positionals??[],L=m.flags?.out,O="screenshot"===r&&E[0]?[t_.expandHome(E[0],m.meta?.cwd),...E.slice(1)]:E,M="screenshot"===r&&L?t_.expandHome(L,m.meta?.cwd):L,x="screenshot"===r?O:E,C="screenshot"===r&&M?{...m.flags??{},out:M}:m.flags??{},T=await l(D.device,r,O,M,{...lT(t,m.flags,D.appBundleId,D.trace?.outPath)});return a.recordAction(D,{command:r,positionals:x,flags:C,result:T??{}}),h({ok:!0,data:T??{}})}catch(r){k({level:"error",phase:"request_failed",data:{error:r instanceof Error?r.message:String(r)}});let e=S(),t=R({force:!0})??void 0;return{ok:!1,error:y(r,{diagnosticId:e.diagnosticId,logPath:t})}}})}return d}({logPath:lj,token:lX,sessionStore:lz,leaseRegistry:lJ,trackDownloadableArtifact:function(e){let t=u.randomUUID(),r=setTimeout(()=>{tB(t)},9e5);return r.unref(),tG.set(t,{artifactPath:e.artifactPath,tenantId:e.tenantId,fileName:e.fileName,deleteAfterDownload:!1!==e.deleteAfterDownload,timer:r}),t}});!async function(){let e,t;if(!function(e,t,r){C.existsSync(e)||C.mkdirSync(e,{recursive:!0});let a=JSON.stringify(r,null,2),i=()=>{try{return C.writeFileSync(t,a,{flag:"wx",mode:384}),!0}catch(e){if("EEXIST"===e.code)return!1;throw e}};if(i())return!0;let n=l$(t);if(n?.pid&&n.pid!==process.pid&&s(n.pid,n.processStartTime))return!1;try{C.unlinkSync(t)}catch{}return i()}(lV,lB,{pid:process.pid,version:lK,startedAt:Date.now(),processStartTime:lZ})){process.stderr.write("Daemon lock is held by another process; exiting.\n"),process.exit(0);return}let r=[];try{var a;let i;if("socket"===lH||"dual"===lH){let t=P.createServer(e=>{let t="",r=0,a=new Set,i=!1,n=()=>{if(!i&&0!==r){for(let e of(i=!0,a))ed(e);k({level:"warn",phase:"request_client_disconnected",data:{inFlightRequests:r}}),(async()=>{let e=Date.now()+15e3;for(;r>0&&Date.now()<e&&(await ti(),!(r<=0));)await new Promise(e=>setTimeout(e,200))})()}};e.setEncoding("utf8"),e.on("close",n),e.on("error",n),e.on("data",async i=>{let n=(t+=i).indexOf("\n");for(;-1!==n;){let i,o,s=t.slice(0,n).trim();if(t=t.slice(n+1),0===s.length){n=t.indexOf("\n");continue}r+=1;try{let e=JSON.parse(s);if(o=es(e.meta?.requestId,"socket"),e.meta={...e.meta,requestId:o},a.add(o),el(o),ec(o))throw ef();i=await lQ(e)}catch(e){i={ok:!1,error:y(e)}}finally{r-=1,o&&(a.delete(o),eu(o))}e.destroyed||e.write(`${JSON.stringify(i)}
37
+ `),n=t.indexOf("\n")}})});r.push(t),e=await new Promise((e,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r);let a=t.address();"object"==typeof a&&a?.port?e(a.port):r(new w("COMMAND_FAILED","Failed to bind socket server"))})})}if("http"===lH||"dual"===lH){let e=await re({handleRequest:lQ,token:lX});r.push(e),t=await new Promise((t,r)=>{e.once("error",r),e.listen(0,"127.0.0.1",()=>{e.off("error",r);let a=e.address();"object"==typeof a&&a?.port?t(a.port):r(new w("COMMAND_FAILED","Failed to bind HTTP server"))})})}a={socketPort:e,httpPort:t,token:lX,version:lK,codeSignature:lY,processStartTime:lZ},C.existsSync(lV)||C.mkdirSync(lV,{recursive:!0}),C.writeFileSync(lj,""),i=a.socketPort&&a.httpPort?"dual":a.httpPort?"http":"socket",C.writeFileSync(lG,JSON.stringify({port:a.socketPort,httpPort:a.httpPort,transport:i,token:a.token,pid:process.pid,version:a.version,codeSignature:a.codeSignature,processStartTime:a.processStartTime,stateDir:lV},null,2),{mode:384}),e&&process.stdout.write(`AGENT_DEVICE_DAEMON_PORT=${e}
38
38
  `),t&&process.stdout.write(`AGENT_DEVICE_DAEMON_HTTP_PORT=${t}
39
- `)}catch(t){let e=h(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
40
- `),r))try{t.close(()=>{})}catch{}lw(ly),lI(lb),process.exit(1);return}let a=!1,n=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!a){for(let e of(a=!0,await n(),lE.toArray()))lE.writeSessionLog(e);await tn(),lw(ly),lI(lb),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof g?e:h(e);process.stderr.write(`Daemon error: ${t.message}
39
+ `)}catch(t){let e=f(t);for(let t of(process.stderr.write(`Daemon error: ${e.message}
40
+ `),r))try{t.close(()=>{})}catch{}lP(lG),lU(lB),process.exit(1);return}let i=!1,n=async()=>{await Promise.all(r.map(async e=>{await new Promise(t=>{try{e.close(()=>t())}catch{t()}})}))},o=async()=>{if(!i){for(let e of(i=!0,await n(),lz.toArray()))lz.writeSessionLog(e);await tn(),lP(lG),lU(lB),process.exit(0)}};process.on("SIGINT",()=>{o()}),process.on("SIGTERM",()=>{o()}),process.on("SIGHUP",()=>{o()}),process.on("uncaughtException",e=>{let t=e instanceof w?e:f(e);process.stderr.write(`Daemon error: ${t.message}
41
41
  `),o()})}();